summaryrefslogtreecommitdiff
path: root/vp8
diff options
context:
space:
mode:
authorYaowu Xu <yaowu@google.com>2012-03-09 17:32:50 -0800
committerYaowu Xu <yaowu@google.com>2012-03-15 07:36:47 -0700
commit6035da5448392244936f1e1a9079e7f6cd857ffe (patch)
treedb96cbb161633c0db567204bcd730d56da1ec7ad /vp8
parent2b1c2990a98f090d91ab3ca5c6c1e1ce7ee1a701 (diff)
downloadlibvpx-6035da5448392244936f1e1a9079e7f6cd857ffe.tar
libvpx-6035da5448392244936f1e1a9079e7f6cd857ffe.tar.gz
libvpx-6035da5448392244936f1e1a9079e7f6cd857ffe.tar.bz2
libvpx-6035da5448392244936f1e1a9079e7f6cd857ffe.zip
WebM Experimental Codec Branch Snapshot
This is a code snapshot of experimental work currently ongoing for a next-generation codec. The codebase has been cut down considerably from the libvpx baseline. For example, we are currently only supporting VBR 2-pass rate control and have removed most of the code relating to coding speed, threading, error resilience, partitions and various other features. This is in part to make the codebase easier to work on and experiment with, but also because we want to have an open discussion about how the bitstream will be structured and partitioned and not have that conversation constrained by past work. Our basic working pattern has been to initially encapsulate experiments using configure options linked to #IF CONFIG_XXX statements in the code. Once experiments have matured and we are reasonably happy that they give benefit and can be merged without breaking other experiments, we remove the conditional compile statements and merge them in. Current changes include: * Temporal coding experiment for segments (though still only 4 max, it will likely be increased). * Segment feature experiment - to allow various bits of information to be coded at the segment level. Features tested so far include mode and reference frame information, limiting end of block offset and transform size, alongside Q and loop filter parameters, but this set is very fluid. * Support for 8x8 transform - 8x8 dct with 2nd order 2x2 haar is used in MBs using 16x16 prediction modes within inter frames. * Compound prediction (combination of signals from existing predictors to create a new predictor). * 8 tap interpolation filters and 1/8th pel motion vectors. * Loop filter modifications. * Various entropy modifications and changes to how entropy contexts and updates are handled. * Extended quantizer range matched to transform precision improvements. There are also ongoing further experiments that we hope to merge in the near future: For example, coding of motion and other aspects of the prediction signal to better support larger image formats, use of larger block sizes (e.g. 32x32 and up) and lossless non-transform based coding options (especially for key frames). It is our hope that we will be able to make regular updates and we will warmly welcome community contributions. Please be warned that, at this stage, the codebase is currently slower than VP8 stable branch as most new code has not been optimized, and even the 'C' has been deliberately written to be simple and obvious, not fast. The following graphs have the initial test results, numbers in the tables measure the compression improvement in terms of percentage. The build has the following optional experiments configured: --enable-experimental --enable-enhanced_interp --enable-uvintra --enable-high_precision_mv --enable-sixteenth_subpel_uv CIF Size clips: http://getwebm.org/tmp/cif/ HD size clips: http://getwebm.org/tmp/hd/ (stable_20120309 represents encoding results of WebM master branch build as of commit#7a15907) They were encoded using the following encode parameters: --good --cpu-used=0 -t 0 --lag-in-frames=25 --min-q=0 --max-q=63 --end-usage=0 --auto-alt-ref=1 -p 2 --pass=2 --kf-max-dist=9999 --kf-min-dist=0 --drop-frame=0 --static-thresh=0 --bias-pct=50 --minsection-pct=0 --maxsection-pct=800 --sharpness=0 --arnr-maxframes=7 --arnr-strength=3(for HD,6 for CIF) --arnr-type=3 Change-Id: I5c62ed09cfff5815a2bb34e7820d6a810c23183c
Diffstat (limited to 'vp8')
-rw-r--r--vp8/common/alloccommon.c73
-rw-r--r--vp8/common/arm/arm_systemdependent.c2
-rw-r--r--vp8/common/arm/filter_arm.c2
-rw-r--r--vp8/common/arm/neon/recon_neon.c2
-rw-r--r--vp8/common/arm/reconintra_arm.c2
-rw-r--r--vp8/common/blockd.c11
-rw-r--r--vp8/common/blockd.h114
-rw-r--r--vp8/common/coefupdateprobs.h175
-rw-r--r--vp8/common/common.h3
-rw-r--r--vp8/common/debugmodes.c7
-rw-r--r--vp8/common/defaultcoefcounts.h187
-rw-r--r--vp8/common/entropy.c50
-rw-r--r--vp8/common/entropy.h11
-rw-r--r--vp8/common/entropymode.c265
-rw-r--r--vp8/common/entropymode.h13
-rw-r--r--vp8/common/entropymv.c39
-rw-r--r--vp8/common/entropymv.h38
-rw-r--r--vp8/common/filter.c533
-rw-r--r--vp8/common/filter.h14
-rw-r--r--vp8/common/findnearmv.c72
-rw-r--r--vp8/common/findnearmv.h22
-rw-r--r--vp8/common/generic/systemdependent.c105
-rw-r--r--vp8/common/idct.h34
-rw-r--r--vp8/common/idctllm.c244
-rw-r--r--vp8/common/implicit_segmentation.c277
-rw-r--r--vp8/common/invtrans.c91
-rw-r--r--vp8/common/invtrans.h7
-rw-r--r--vp8/common/loopfilter.c243
-rw-r--r--vp8/common/loopfilter.h3
-rw-r--r--vp8/common/loopfilter_filters.c182
-rw-r--r--vp8/common/maskingmv.c855
-rw-r--r--vp8/common/modecont.c54
-rw-r--r--vp8/common/modecont.h4
-rw-r--r--vp8/common/onyx.h22
-rw-r--r--vp8/common/onyxc_int.h85
-rw-r--r--vp8/common/onyxd.h1
-rw-r--r--vp8/common/postproc.c8
-rw-r--r--vp8/common/pred_common.c339
-rw-r--r--vp8/common/pred_common.h51
-rw-r--r--vp8/common/predict_rotated.c85
-rw-r--r--vp8/common/quant_common.c116
-rw-r--r--vp8/common/quant_common.h1
-rw-r--r--vp8/common/recon.c32
-rw-r--r--vp8/common/recon.h107
-rw-r--r--vp8/common/reconinter.c209
-rw-r--r--vp8/common/reconinter.h6
-rw-r--r--vp8/common/reconintra.c509
-rw-r--r--vp8/common/reconintra4x4.c24
-rw-r--r--vp8/common/rotate.h2827
-rw-r--r--vp8/common/rotate2.h2827
-rw-r--r--vp8/common/seg_common.c167
-rw-r--r--vp8/common/seg_common.h85
-rw-r--r--vp8/common/subpixel.h23
-rw-r--r--vp8/common/systemdependent.h2
-rw-r--r--vp8/common/tapify.py106
-rw-r--r--vp8/common/threading.h94
-rw-r--r--vp8/common/x86/mask_sse3.asm484
-rw-r--r--vp8/common/x86/recon_wrapper_sse2.c2
-rw-r--r--vp8/common/x86/subpixel_ssse3.asm20
-rw-r--r--vp8/common/x86/vp8_asm_stubs.c43
-rw-r--r--vp8/common/x86/x86_systemdependent.c8
-rw-r--r--vp8/decoder/arm/arm_dsystemdependent.c2
-rw-r--r--vp8/decoder/arm/armv6/idct_blk_v6.c2
-rw-r--r--vp8/decoder/arm/dequantize_arm.c2
-rw-r--r--vp8/decoder/arm/neon/idct_blk_neon.c2
-rw-r--r--vp8/decoder/dboolhuff.h2
-rw-r--r--vp8/decoder/decodemv.c766
-rw-r--r--vp8/decoder/decoderthreading.h26
-rw-r--r--vp8/decoder/decodframe.c827
-rw-r--r--vp8/decoder/dequantize.c218
-rw-r--r--vp8/decoder/dequantize.h60
-rw-r--r--vp8/decoder/detokenize.c433
-rw-r--r--vp8/decoder/detokenize.h1
-rw-r--r--vp8/decoder/error_concealment.c629
-rw-r--r--vp8/decoder/error_concealment.h41
-rw-r--r--vp8/decoder/generic/dsystemdependent.c10
-rw-r--r--vp8/decoder/idct_blk.c44
-rw-r--r--vp8/decoder/onyxd_if.c316
-rw-r--r--vp8/decoder/onyxd_int.h57
-rw-r--r--vp8/decoder/reconintra_mt.c2
-rw-r--r--vp8/decoder/reconintra_mt.h11
-rw-r--r--vp8/decoder/threading.c1003
-rw-r--r--vp8/decoder/x86/idct_blk_mmx.c2
-rw-r--r--vp8/decoder/x86/idct_blk_sse2.c2
-rw-r--r--vp8/decoder/x86/x86_dsystemdependent.c2
-rw-r--r--vp8/encoder/arm/arm_csystemdependent.c6
-rw-r--r--vp8/encoder/arm/variance_arm.c18
-rw-r--r--vp8/encoder/arm/variance_arm.h3
-rw-r--r--vp8/encoder/bitstream.c1768
-rw-r--r--vp8/encoder/bitstream.h14
-rw-r--r--vp8/encoder/block.h24
-rw-r--r--vp8/encoder/dct.c144
-rw-r--r--vp8/encoder/dct.h15
-rw-r--r--vp8/encoder/defaultcoefcounts.h223
-rw-r--r--vp8/encoder/encodeframe.c644
-rw-r--r--vp8/encoder/encodeintra.c262
-rw-r--r--vp8/encoder/encodeintra.h7
-rw-r--r--vp8/encoder/encodemb.c660
-rw-r--r--vp8/encoder/encodemb.h13
-rw-r--r--vp8/encoder/encodemv.c385
-rw-r--r--vp8/encoder/encodemv.h5
-rw-r--r--vp8/encoder/ethreading.c566
-rw-r--r--vp8/encoder/find_rotation.c58
-rw-r--r--vp8/encoder/firstpass.c1008
-rw-r--r--vp8/encoder/generic/csystemdependent.c16
-rw-r--r--vp8/encoder/lookahead.c2
-rw-r--r--vp8/encoder/mbgraph.c564
-rw-r--r--vp8/encoder/mbgraph.h (renamed from vp8/encoder/pickinter.h)11
-rw-r--r--vp8/encoder/mcomp.c631
-rw-r--r--vp8/encoder/mcomp.h5
-rw-r--r--vp8/encoder/modecosts.c27
-rw-r--r--vp8/encoder/onyx_if.c2790
-rw-r--r--vp8/encoder/onyx_int.h164
-rw-r--r--vp8/encoder/pickinter.c937
-rw-r--r--vp8/encoder/picklpf.c252
-rw-r--r--vp8/encoder/ppc/csystemdependent.c4
-rw-r--r--vp8/encoder/quantize.c730
-rw-r--r--vp8/encoder/quantize.h29
-rw-r--r--vp8/encoder/ratectrl.c1276
-rw-r--r--vp8/encoder/ratectrl.h6
-rw-r--r--vp8/encoder/rdopt.c1566
-rw-r--r--vp8/encoder/rdopt.h9
-rw-r--r--vp8/encoder/sad_c.c2
-rw-r--r--vp8/encoder/satd_c.c53
-rw-r--r--vp8/encoder/segmentation.c265
-rw-r--r--vp8/encoder/segmentation.h27
-rw-r--r--vp8/encoder/temporal_filter.c64
-rw-r--r--vp8/encoder/tokenize.c498
-rw-r--r--vp8/encoder/tokenize.h9
-rw-r--r--vp8/encoder/treewriter.c6
-rw-r--r--vp8/encoder/variance.h13
-rw-r--r--vp8/encoder/variance_c.c15
-rw-r--r--vp8/encoder/x86/variance_impl_sse2.asm20
-rw-r--r--vp8/encoder/x86/variance_impl_ssse3.asm20
-rw-r--r--vp8/encoder/x86/variance_mmx.c39
-rw-r--r--vp8/encoder/x86/variance_sse2.c34
-rw-r--r--vp8/encoder/x86/variance_ssse3.c18
-rw-r--r--vp8/encoder/x86/variance_x86.h4
-rw-r--r--vp8/encoder/x86/x86_csystemdependent.c12
-rw-r--r--vp8/vp8_common.mk16
-rw-r--r--vp8/vp8_cx_iface.c104
-rw-r--r--vp8/vp8_dx_iface.c12
-rw-r--r--vp8/vp8cx.mk16
-rw-r--r--vp8/vp8dx.mk7
144 files changed, 22105 insertions, 10468 deletions
diff --git a/vp8/common/alloccommon.c b/vp8/common/alloccommon.c
index ee6e1cafe..5a7c79c8f 100644
--- a/vp8/common/alloccommon.c
+++ b/vp8/common/alloccommon.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "blockd.h"
#include "vpx_mem/vpx_mem.h"
#include "onyxc_int.h"
@@ -20,17 +20,37 @@
extern void vp8_init_scan_order_mask();
-static void update_mode_info_border(MODE_INFO *mi, int rows, int cols)
+static void update_mode_info_border( VP8_COMMON *cpi, MODE_INFO *mi_base )
{
+ int stride = cpi->mode_info_stride;
int i;
- vpx_memset(mi - cols - 2, 0, sizeof(MODE_INFO) * (cols + 1));
- for (i = 0; i < rows; i++)
+ // Clear down top border row
+ vpx_memset(mi_base, 0, sizeof(MODE_INFO) * cpi->mode_info_stride);
+
+ // Clear left border column
+ for (i = 1; i < cpi->mb_rows+1; i++)
{
- /* TODO(holmer): Bug? This updates the last element of each row
- * rather than the border element!
- */
- vpx_memset(&mi[i*cols-1], 0, sizeof(MODE_INFO));
+ vpx_memset(&mi_base[i*stride], 0, sizeof(MODE_INFO));
+ }
+}
+static void update_mode_info_in_image( VP8_COMMON *cpi, MODE_INFO *mi )
+{
+ int stride = cpi->mode_info_stride;
+ int rows = cpi->mb_rows;
+ int cols = cpi->mb_cols;
+ int i, j;
+
+ // For each in image mode_info element set the in image flag to 1
+ for (i = 0; i < cpi->mb_rows; i++)
+ {
+ for (j = 0; j < cpi->mb_cols; j++)
+ {
+ mi->mbmi.mb_in_image = 1;
+ mi++; // Next element in the row
+ }
+
+ mi++; // Step over border element at start of next row
}
}
@@ -116,7 +136,7 @@ int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height)
oci->mi = oci->mip + oci->mode_info_stride + 1;
/* allocate memory for last frame MODE_INFO array */
-#if CONFIG_ERROR_CONCEALMENT
+
oci->prev_mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
if (!oci->prev_mip)
@@ -126,10 +146,6 @@ int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height)
}
oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
-#else
- oci->prev_mip = NULL;
- oci->prev_mi = NULL;
-#endif
oci->above_context = vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * oci->mb_cols, 1);
@@ -139,10 +155,8 @@ int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height)
return 1;
}
- update_mode_info_border(oci->mi, oci->mb_rows, oci->mb_cols);
-#if CONFIG_ERROR_CONCEALMENT
- update_mode_info_border(oci->prev_mi, oci->mb_rows, oci->mb_cols);
-#endif
+ update_mode_info_border(oci, oci->mip);
+ update_mode_info_in_image(oci, oci->mi);
return 0;
}
@@ -153,10 +167,10 @@ void vp8_setup_version(VP8_COMMON *cm)
if (!CONFIG_EXPERIMENTAL)
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Bitstream was created by an experimental "
- "encoder");
+ "encoder");
cm->experimental = 1;
}
-
+
switch (cm->version & 0x3)
{
case 0:
@@ -172,17 +186,19 @@ void vp8_setup_version(VP8_COMMON *cm)
cm->full_pixel = 0;
break;
case 2:
+ case 3:
cm->no_lpf = 1;
cm->filter_type = NORMAL_LOOPFILTER;
cm->use_bilinear_mc_filter = 1;
cm->full_pixel = 0;
break;
- case 3:
- cm->no_lpf = 1;
- cm->filter_type = SIMPLE_LOOPFILTER;
- cm->use_bilinear_mc_filter = 1;
- cm->full_pixel = 1;
- break;
+ // Full pel only code deprecated in experimental code base
+ //case 3:
+ // cm->no_lpf = 1;
+ // cm->filter_type = SIMPLE_LOOPFILTER;
+ // cm->use_bilinear_mc_filter = 1;
+ // cm->full_pixel = 1;
+ // break;
}
}
void vp8_create_common(VP8_COMMON *oci)
@@ -190,14 +206,16 @@ void vp8_create_common(VP8_COMMON *oci)
vp8_machine_specific_config(oci);
vp8_init_mbmode_probs(oci);
+
vp8_default_bmode_probs(oci->fc.bmode_prob);
+ oci->txfm_mode = ONLY_4X4;
oci->mb_no_coeff_skip = 1;
+ oci->comp_pred_mode = HYBRID_PREDICTION;
oci->no_lpf = 0;
oci->filter_type = NORMAL_LOOPFILTER;
oci->use_bilinear_mc_filter = 0;
oci->full_pixel = 0;
- oci->multi_token_partition = ONE_PARTITION;
oci->clr_type = REG_YUV;
oci->clamp_type = RECON_CLAMP_REQUIRED;
@@ -207,6 +225,9 @@ void vp8_create_common(VP8_COMMON *oci)
/* Default disable buffer to buffer copying */
oci->copy_buffer_to_gf = 0;
oci->copy_buffer_to_arf = 0;
+#if CONFIG_QIMODE
+ oci->kf_ymode_probs_update = 0;
+#endif
}
void vp8_remove_common(VP8_COMMON *oci)
diff --git a/vp8/common/arm/arm_systemdependent.c b/vp8/common/arm/arm_systemdependent.c
index 2b45afe4b..c0467cd84 100644
--- a/vp8/common/arm/arm_systemdependent.c
+++ b/vp8/common/arm/arm_systemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/arm.h"
#include "vp8/common/g_common.h"
#include "vp8/common/pragmas.h"
diff --git a/vp8/common/arm/filter_arm.c b/vp8/common/arm/filter_arm.c
index 6d95eb8e3..6582fb29a 100644
--- a/vp8/common/arm/filter_arm.c
+++ b/vp8/common/arm/filter_arm.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include <math.h>
#include "vp8/common/filter.h"
#include "vp8/common/subpixel.h"
diff --git a/vp8/common/arm/neon/recon_neon.c b/vp8/common/arm/neon/recon_neon.c
index d2aafd51f..09fd2a56f 100644
--- a/vp8/common/arm/neon/recon_neon.c
+++ b/vp8/common/arm/neon/recon_neon.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/recon.h"
#include "vp8/common/blockd.h"
diff --git a/vp8/common/arm/reconintra_arm.c b/vp8/common/arm/reconintra_arm.c
index cd82baf7c..f8f4dca3e 100644
--- a/vp8/common/arm/reconintra_arm.c
+++ b/vp8/common/arm/reconintra_arm.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/blockd.h"
#include "vp8/common/reconintra.h"
#include "vpx_mem/vpx_mem.h"
diff --git a/vp8/common/blockd.c b/vp8/common/blockd.c
index 1fc3cd0ca..60ef31217 100644
--- a/vp8/common/blockd.c
+++ b/vp8/common/blockd.c
@@ -12,6 +12,7 @@
#include "blockd.h"
#include "vpx_mem/vpx_mem.h"
+
const unsigned char vp8_block2left[25] =
{
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
@@ -20,3 +21,13 @@ const unsigned char vp8_block2above[25] =
{
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8
};
+
+const unsigned char vp8_block2left_8x8[25] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 8
+};
+const unsigned char vp8_block2above_8x8[25] =
+{
+ 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 8
+};
+
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
index 6cb3fe1bb..89fe03516 100644
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -14,21 +14,26 @@
void vpx_log(const char *format, ...);
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_scale/yv12config.h"
#include "mv.h"
#include "treecoder.h"
#include "subpixel.h"
#include "vpx_ports/mem.h"
+#include "common.h"
#define TRUE 1
#define FALSE 0
+//#define MODE_STATS
+
/*#define DCPRED 1*/
#define DCPREDSIMTHRESH 0
#define DCPREDCNTTHRESH 3
#define MB_FEATURE_TREE_PROBS 3
+#define PREDICTION_PROBS 3
+
#define MAX_MB_SEGMENTS 4
#define MAX_REF_LF_DELTAS 4
@@ -60,11 +65,13 @@ typedef struct
extern const unsigned char vp8_block2left[25];
extern const unsigned char vp8_block2above[25];
+extern const unsigned char vp8_block2left_8x8[25];
+extern const unsigned char vp8_block2above_8x8[25];
+
#define VP8_COMBINEENTROPYCONTEXTS( Dest, A, B) \
Dest = ((A)!=0) + ((B)!=0);
-
typedef enum
{
KEY_FRAME = 0,
@@ -77,6 +84,7 @@ typedef enum
V_PRED, /* vertical prediction */
H_PRED, /* horizontal prediction */
TM_PRED, /* Truemotion prediction */
+ I8X8_PRED, /* 8x8 based prediction, each 8x8 has its own prediction mode */
B_PRED, /* block based prediction, each block has its own prediction mode */
NEARESTMV,
@@ -88,21 +96,32 @@ typedef enum
MB_MODE_COUNT
} MB_PREDICTION_MODE;
-/* Macroblock level features */
+// Segment level features.
typedef enum
{
- MB_LVL_ALT_Q = 0, /* Use alternate Quantizer .... */
- MB_LVL_ALT_LF = 1, /* Use alternate loop filter value... */
- MB_LVL_MAX = 2 /* Number of MB level features supported */
+ 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_MODE = 3, // Optional Segment mode
+ SEG_LVL_EOB = 4, // EOB end stop marker.
+ SEG_LVL_TRANSFORM = 5, // Block transform size.
+ SEG_LVL_MAX = 6 // Number of MB level features supported
-} MB_LVL_FEATURES;
+} SEG_LVL_FEATURES;
-/* Segment Feature Masks */
-#define SEGMENT_ALTQ 0x01
-#define SEGMENT_ALT_LF 0x02
+// Segment level features.
+typedef enum
+{
+ TX_4X4 = 0, // 4x4 dct transform
+ TX_8X8 = 1, // 8x8 dct transform
+
+ TX_SIZE_MAX = 2 // Number of differnt transforms avaialble
+
+} TX_SIZE;
#define VP8_YMODES (B_PRED + 1)
#define VP8_UV_MODES (TM_PRED + 1)
+#define VP8_I8X8_MODES (TM_PRED + 1)
#define VP8_MVREFS (1 + SPLITMV - NEARESTMV)
@@ -139,7 +158,12 @@ typedef enum
union b_mode_info
{
- B_PREDICTION_MODE as_mode;
+ struct {
+ B_PREDICTION_MODE first;
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE second;
+#endif
+ } as_mode;
int_mv mv;
};
@@ -155,13 +179,26 @@ typedef enum
typedef struct
{
MB_PREDICTION_MODE mode, uv_mode;
- MV_REFERENCE_FRAME ref_frame;
- int_mv mv;
-
+#if CONFIG_COMP_INTRA_PRED
+ MB_PREDICTION_MODE second_mode, second_uv_mode;
+#endif
+ MV_REFERENCE_FRAME ref_frame, second_ref_frame;
+ TX_SIZE txfm_size;
+ int_mv mv, second_mv;
unsigned char partitioning;
unsigned char mb_skip_coeff; /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */
unsigned char need_to_clamp_mvs;
unsigned char segment_id; /* Which set of segmentation parameters should be used for this MB */
+
+ // Flags used for prediction status of various bistream signals
+ unsigned char seg_id_predicted;
+ unsigned char ref_predicted;
+
+ // Indicates if the mb is part of the image (1) vs border (0)
+ // This can be useful in determining whether the MB provides
+ // a valid predictor
+ unsigned char mb_in_image;
+
} MB_MODE_INFO;
typedef struct
@@ -205,8 +242,12 @@ typedef struct MacroBlockD
int fullpixel_mask;
YV12_BUFFER_CONFIG pre; /* Filtered copy of previous frame reconstruction */
+ struct {
+ uint8_t *y_buffer, *u_buffer, *v_buffer;
+ } second_pre;
YV12_BUFFER_CONFIG dst;
+ MODE_INFO *prev_mode_info_context;
MODE_INFO *mode_info_context;
int mode_info_stride;
@@ -229,13 +270,24 @@ typedef struct MacroBlockD
unsigned char update_mb_segmentation_data;
/* 0 (do not update) 1 (update) the macroblock segmentation feature data. */
- unsigned char mb_segement_abs_delta;
+ unsigned char mb_segment_abs_delta;
/* Per frame flags that define which MB level features (such as quantizer or loop filter level) */
/* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */
- vp8_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS]; /* Probability Tree used to code Segment number */
- signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS]; /* Segment parameters */
+ // Probability Tree used to code Segment number
+ vp8_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS];
+
+
+ // Segment features
+ signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];
+ unsigned int segment_feature_mask[MAX_MB_SEGMENTS];
+
+#if CONFIG_FEATUREUPDATES
+ // keep around the last set so we can figure out what updates...
+ unsigned int old_segment_feature_mask[MAX_MB_SEGMENTS];
+ signed char old_segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];
+#endif
/* mode_based Loop filter adjustment */
unsigned char mode_ref_lf_delta_enabled;
@@ -244,8 +296,8 @@ typedef struct MacroBlockD
/* Delta values have the range +/- MAX_LOOP_FILTER */
signed char last_ref_lf_deltas[MAX_REF_LF_DELTAS]; /* 0 = Intra, Last, GF, ARF */
signed char ref_lf_deltas[MAX_REF_LF_DELTAS]; /* 0 = Intra, Last, GF, ARF */
- signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS]; /* 0 = BPRED, ZERO_MV, MV, SPLIT */
- signed char mode_lf_deltas[MAX_MODE_LF_DELTAS]; /* 0 = BPRED, ZERO_MV, MV, SPLIT */
+ signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS]; /* 0 = BPRED, ZERO_MV, MV, SPLIT */
+ signed char mode_lf_deltas[MAX_MODE_LF_DELTAS]; /* 0 = BPRED, ZERO_MV, MV, SPLIT */
/* Distance of MB away from frame edges */
int mb_to_left_edge;
@@ -253,15 +305,17 @@ typedef struct MacroBlockD
int mb_to_top_edge;
int mb_to_bottom_edge;
- int ref_frame_cost[MAX_REF_FRAMES];
-
-
unsigned int frames_since_golden;
unsigned int frames_till_alt_ref_frame;
vp8_subpix_fn_t subpixel_predict;
vp8_subpix_fn_t subpixel_predict8x4;
vp8_subpix_fn_t subpixel_predict8x8;
vp8_subpix_fn_t subpixel_predict16x16;
+ vp8_subpix_fn_t subpixel_predict_avg8x8;
+ vp8_subpix_fn_t subpixel_predict_avg16x16;
+#if CONFIG_HIGH_PRECISION_MV
+ int allow_high_precision_mv;
+#endif /* CONFIG_HIGH_PRECISION_MV */
void *current_bc;
@@ -284,4 +338,20 @@ typedef struct MacroBlockD
extern void vp8_build_block_doffsets(MACROBLOCKD *x);
extern void vp8_setup_block_dptrs(MACROBLOCKD *x);
+static void update_blockd_bmi(MACROBLOCKD *xd)
+{
+ int i;
+ int is_4x4;
+ is_4x4 = (xd->mode_info_context->mbmi.mode == SPLITMV) ||
+ (xd->mode_info_context->mbmi.mode == I8X8_PRED) ||
+ (xd->mode_info_context->mbmi.mode == B_PRED);
+
+ if (is_4x4)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ xd->block[i].bmi = xd->mode_info_context->bmi[i];
+ }
+ }
+}
#endif /* __INC_BLOCKD_H */
diff --git a/vp8/common/coefupdateprobs.h b/vp8/common/coefupdateprobs.h
index 9e194dc9a..05e456393 100644
--- a/vp8/common/coefupdateprobs.h
+++ b/vp8/common/coefupdateprobs.h
@@ -183,3 +183,178 @@ const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTE
},
},
};
+const vp8_prob vp8_coef_update_probs_8x8 [BLOCK_TYPES]
+ [COEF_BANDS]
+ [PREV_COEF_CONTEXTS]
+ [ENTROPY_NODES] =
+{
+ {
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 229, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {219, 234, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {239, 204, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 209, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {239, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 204, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {229, 209, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 193, 209, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {229, 198, 239, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 204, 204, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {219, 198, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 198, 204, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {209, 193, 234, 249, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 214, 214, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {173, 193, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ },
+ {
+ {
+ {255, 255, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {224, 224, 219, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {229, 239, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 234, 224, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {224, 234, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 255, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {229, 255, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 255, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {224, 255, 239, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ },
+ {
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {224, 219, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {234, 183, 214, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 193, 229, 255, 249, 255, 255, 255, 255, 255, 255, },
+ {229, 214, 234, 249, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 249, 255, 255, 249, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 198, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {229, 219, 249, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 193, 224, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {229, 204, 234, 249, 249, 255, 255, 255, 255, 255, 255, },
+ {255, 249, 249, 255, 244, 249, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 178, 224, 255, 249, 255, 255, 255, 255, 255, 255, },
+ {234, 224, 234, 249, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 183, 229, 255, 249, 255, 255, 255, 255, 255, 255, },
+ {234, 219, 234, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 249, 249, 255, 249, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 193, 224, 249, 255, 244, 255, 255, 255, 255, 255, },
+ {219, 224, 229, 255, 255, 249, 255, 255, 255, 255, 255, },
+ {255, 255, 255, 249, 249, 255, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 193, 229, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {224, 224, 239, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {249, 244, 249, 255, 255, 255, 255, 255, 255, 255, 255, },
+ },
+ },
+ {
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+ {255, 239, 234, 244, 239, 244, 249, 255, 255, 255, 255, },
+ },
+ {
+ {255, 249, 239, 239, 244, 255, 255, 255, 255, 255, 255, },
+ {255, 249, 244, 255, 249, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 239, 255, 255, 249, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 244, 239, 239, 244, 255, 255, 255, 255, 255, 255, },
+ {255, 234, 239, 234, 249, 255, 255, 255, 255, 255, 255, },
+ {255, 255, 229, 239, 234, 249, 244, 255, 255, 255, 255, },
+ },
+ {
+ {255, 239, 229, 239, 234, 234, 255, 255, 255, 255, 255, },
+ {255, 239, 234, 229, 244, 239, 255, 234, 255, 255, 255, },
+ {255, 229, 209, 229, 239, 234, 244, 229, 255, 249, 255, },
+ },
+ {
+ {255, 239, 234, 229, 244, 249, 255, 249, 255, 255, 255, },
+ {255, 234, 229, 244, 234, 249, 255, 249, 255, 255, 255, },
+ {255, 229, 239, 229, 249, 255, 255, 244, 255, 255, 255, },
+ },
+ {
+ {255, 239, 234, 239, 234, 239, 255, 249, 255, 255, 255, },
+ {255, 229, 234, 239, 239, 239, 255, 244, 255, 255, 255, },
+ {255, 229, 234, 239, 239, 244, 255, 255, 255, 255, 255, },
+ },
+ {
+ {255, 219, 224, 229, 229, 234, 239, 224, 255, 255, 255, },
+ {255, 229, 229, 224, 234, 229, 239, 239, 255, 255, 255, },
+ {255, 229, 224, 239, 234, 239, 224, 224, 255, 249, 255, },
+ },
+ {
+ {255, 234, 229, 244, 229, 229, 255, 214, 255, 255, 255, },
+ {255, 239, 234, 239, 214, 239, 255, 209, 255, 255, 255, },
+ {249, 239, 219, 209, 219, 224, 239, 204, 255, 255, 255, },
+ },
+ },
+
+};
diff --git a/vp8/common/common.h b/vp8/common/common.h
index 9a93da991..999f79f2f 100644
--- a/vp8/common/common.h
+++ b/vp8/common/common.h
@@ -13,7 +13,7 @@
#define common_h 1
#include <assert.h>
-
+#include "vpx_config.h"
/* Interface header for common constant data structures and lookup tables */
#include "vpx_mem/vpx_mem.h"
@@ -38,5 +38,4 @@
#define vp8_zero_array( Dest, N) vpx_memset( Dest, 0, N * sizeof( *Dest));
-
#endif /* common_h */
diff --git a/vp8/common/debugmodes.c b/vp8/common/debugmodes.c
index 46064e61d..6d306578b 100644
--- a/vp8/common/debugmodes.c
+++ b/vp8/common/debugmodes.c
@@ -97,7 +97,12 @@ void vp8_print_modes_and_motion_vectors(MODE_INFO *mi, int rows, int cols, int f
bindex = (b_row & 3) * 4 + (b_col & 3);
if (mi[mb_index].mbmi.mode == B_PRED)
- fprintf(mvs, "%2d ", mi[mb_index].bmi[bindex].as_mode);
+ {
+ fprintf(mvs, "%2d ", mi[mb_index].bmi[bindex].as_mode.first);
+#if CONFIG_COMP_INTRA_PRED
+ fprintf(mvs, "%2d ", mi[mb_index].bmi[bindex].as_mode.second);
+#endif
+ }
else
fprintf(mvs, "xx ");
diff --git a/vp8/common/defaultcoefcounts.h b/vp8/common/defaultcoefcounts.h
new file mode 100644
index 000000000..d84361bf9
--- /dev/null
+++ b/vp8/common/defaultcoefcounts.h
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+/* Generated file, included by entropy.c */
+
+static const unsigned int vp8_default_coef_counts_8x8[BLOCK_TYPES]
+ [COEF_BANDS]
+ [PREV_COEF_CONTEXTS]
+ [MAX_ENTROPY_TOKENS] =
+{
+
+ { /* block Type 0 */
+ { /* Coeff Band 0 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 1 */
+ { 21041, 13314, 3420, 592, 117, 0, 0, 0, 0, 0, 0, 11783},
+ { 48236, 6918, 586, 153, 0, 0, 0, 0, 0, 0, 0, 23137},
+ { 676112, 106685, 24701, 6003, 1426, 429, 165, 0, 0, 0, 0, 28910}
+ },
+ { /* Coeff Band 2 */
+ { 660107, 75227, 8451, 1345, 259, 0, 0, 0, 0, 0, 0, 0},
+ { 79164, 36835, 6865, 1185, 246, 47, 0, 0, 0, 0, 0, 2575},
+ { 19469, 14330, 3070, 579, 94, 6, 0, 0, 0, 0, 0, 44}
+ },
+ { /* Coeff Band 3 */
+ { 1978004, 235343, 28485, 3242, 271, 0, 0, 0, 0, 0, 0, 0},
+ { 228684, 106736, 21431, 2842, 272, 46, 0, 0, 0, 0, 0, 9266},
+ { 32470, 27496, 6852, 1386, 45, 93, 0, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 4 */
+ { 1911212, 224613, 49653, 13748, 2541, 568, 48, 0, 0, 0, 0, 0},
+ { 196670, 103472, 44473, 11490, 2432, 977, 72, 0, 0, 0, 0, 9447},
+ { 37876, 40417, 19142, 6069, 1799, 727, 51, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 5 */
+ { 3813399, 437714, 64387, 11312, 695, 219, 0, 0, 0, 0, 0, 0},
+ { 438288, 215917, 61905, 10194, 674, 107, 0, 0, 0, 0, 0, 17808},
+ { 99139, 93643, 30054, 5758, 802, 171, 0, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 6 */
+ { 12259383, 1625505, 234927, 46306, 8417, 1456, 151, 0, 0, 0, 0, 0},
+ { 1518161, 734287, 204240, 44228, 9462, 2240, 65, 0, 0, 0, 0, 107630},
+ { 292470, 258894, 94925, 25864, 6662, 2055, 170, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 7 */
+ { 9791308, 2118949, 169439, 16735, 1122, 0, 0, 0, 0, 0, 0, 0},
+ { 1500281, 752410, 123259, 13065, 1168, 47, 0, 0, 0, 0, 0, 707182},
+ { 193067, 142638, 31018, 4719, 516, 138, 0, 0, 0, 0, 0, 12439}
+ }
+ },
+ { /* block Type 1 */
+ { /* Coeff Band 0 */
+ { 16925, 10553, 852, 16, 63, 87, 47, 0, 0, 0, 0, 31232},
+ { 39777, 26839, 6822, 1908, 678, 456, 227, 168, 35, 0, 0, 46825},
+ { 17300, 16666, 4168, 1209, 492, 154, 118, 207, 0, 0, 0, 19608}
+ },
+ { /* Coeff Band 1 */
+ { 35882, 31722, 4625, 1270, 266, 237, 0, 0, 0, 0, 0, 0},
+ { 15426, 13894, 4482, 1305, 281, 43, 0, 0, 0, 0, 0, 18627},
+ { 3900, 6552, 3472, 1723, 746, 366, 115, 35, 0, 0, 0, 798}
+ },
+ { /* Coeff Band 2 */
+ { 21998, 29132, 3353, 679, 46, 0, 0, 0, 0, 0, 0, 0},
+ { 9098, 15767, 3794, 792, 268, 47, 0, 0, 0, 0, 0, 22402},
+ { 4007, 8472, 2844, 687, 217, 0, 0, 0, 0, 0, 0, 2739}
+ },
+ { /* Coeff Band 3 */
+ { 0, 31414, 2911, 682, 96, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 16515, 4425, 938, 124, 0, 0, 0, 0, 0, 0, 31369},
+ { 0, 4833, 2787, 1213, 150, 0, 0, 0, 0, 0, 0, 3744}
+ },
+ { /* Coeff Band 4 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 5 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 6 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52762},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13326}
+ },
+ { /* Coeff Band 7 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ }
+ },
+ { /* block Type 2 */
+ { /* Coeff Band 0 */
+ { 4444, 1614, 120, 48, 0, 48, 0, 0, 0, 0, 0, 278},
+ { 192436, 103730, 24494, 9845, 4122, 1193, 102, 0, 0, 0, 0, 2577},
+ { 3473446, 2308716, 815510, 370374, 167797, 92152, 12073, 86, 0, 0, 0, 6801}
+ },
+ { /* Coeff Band 1 */
+ { 2150616, 1136388, 250011, 86888, 31434, 13746, 1243, 0, 0, 0, 0, 0},
+ { 1179945, 799802, 266012, 106787, 40809, 16486, 1546, 0, 0, 0, 0, 2673},
+ { 465128, 504130, 286989, 146259, 62380, 30192, 2866, 20, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 2 */
+ { 2157762, 1177519, 282665, 108499, 43389, 23224, 2597, 34, 0, 0, 0, 0},
+ { 1135685, 813705, 278079, 123255, 53935, 29492, 3152, 39, 0, 0, 0, 2978},
+ { 391894, 428037, 264216, 144306, 69326, 40281, 5541, 29, 0, 0, 0, 38}
+ },
+ { /* Coeff Band 3 */
+ { 6669109, 3468471, 782161, 288484, 115500, 51083, 4943, 41, 0, 0, 0, 0},
+ { 3454493, 2361636, 809524, 337663, 141343, 65036, 6361, 0, 0, 0, 0, 8730},
+ { 1231825, 1359522, 824686, 420784, 185517, 98731, 10973, 72, 0, 0, 0, 20}
+ },
+ { /* Coeff Band 4 */
+ { 7606203, 3452846, 659856, 191703, 49335, 14336, 450, 0, 0, 0, 0, 0},
+ { 3806506, 2379332, 691697, 224938, 61966, 18324, 766, 0, 0, 0, 0, 8193},
+ { 1270110, 1283728, 628775, 243378, 72617, 24897, 1087, 0, 0, 0, 0, 0}
+ },
+ { /* Coeff Band 5 */
+ { 15314169, 7436809, 1579928, 515790, 167453, 58305, 3502, 19, 0, 0, 0, 0},
+ { 7021286, 4667922, 1545706, 574463, 191793, 68748, 4048, 1, 0, 0, 0, 17222},
+ { 2011989, 2145878, 1185336, 534879, 195719, 79103, 5343, 4, 0, 0, 0, 37}
+ },
+ { /* Coeff Band 6 */
+ { 63458382, 25384462, 4208045, 1091050, 299011, 95242, 5238, 33, 0, 0, 0, 0},
+ { 25638401, 14694085, 3945978, 1195420, 344813, 117355, 6703, 0, 0, 0, 0, 216811},
+ { 5988177, 5824044, 2754413, 1077350, 370739, 139710, 9693, 38, 0, 0, 0, 1835}
+ },
+ { /* Coeff Band 7 */
+ { 74998348, 29342158, 2955001, 452912, 69631, 9516, 37, 0, 0, 0, 0, 0},
+ { 24762356, 13281085, 2409883, 436787, 68948, 10658, 36, 0, 0, 0, 0, 6614989},
+ { 3882867, 3224489, 1052289, 252890, 46967, 8548, 154, 0, 0, 0, 0, 194354}
+ }
+ },
+ { /* block Type 3 */
+ { /* Coeff Band 0 */
+ { 10583, 12059, 3155, 1041, 248, 175, 24, 2, 0, 0, 0, 5717},
+ { 42461, 41782, 13553, 4966, 1352, 855, 89, 0, 0, 0, 0, 15000},
+ { 4691125, 5045589, 2673566, 1089317, 378161, 160268, 18252, 813, 69, 13, 0, 49}
+ },
+ { /* Coeff Band 1 */
+ { 1535203, 1685686, 924565, 390329, 141709, 60523, 5983, 171, 0, 0, 0, 0},
+ { 1594021, 1793276, 1016078, 441332, 164159, 70843, 8098, 311, 0, 0, 0, 11312},
+ { 1225223, 1430184, 888492, 460713, 203286, 115149, 22061, 804, 7, 0, 0, 0}
+ },
+ { /* Coeff Band 2 */
+ { 1522386, 1590366, 799910, 303691, 96625, 37608, 3637, 180, 33, 11, 0, 0},
+ { 1682184, 1793869, 913649, 353520, 113674, 46309, 4736, 221, 18, 3, 0, 963},
+ { 1574580, 1740474, 954392, 417994, 151400, 67091, 8000, 536, 73, 10, 0, 63}
+ },
+ { /* Coeff Band 3 */
+ { 4963672, 5197790, 2585383, 982161, 313333, 118498, 16014, 536, 62, 0, 0, 0},
+ { 5223913, 5569803, 2845858, 1107384, 364949, 147841, 18296, 658, 11, 11, 0, 1866},
+ { 4042207, 4548894, 2608767, 1154993, 446290, 221295, 41054, 2438, 124, 20, 0, 0}
+ },
+ { /* Coeff Band 4 */
+ { 3857216, 4431325, 2670447, 1330169, 553301, 286825, 46763, 1917, 0, 0, 0, 0},
+ { 4226215, 4963701, 3046198, 1523923, 644670, 355519, 58792, 2525, 0, 0, 0, 1298},
+ { 3831873, 4580350, 3018580, 1660048, 797298, 502983, 123906, 7172, 16, 0, 0, 0}
+ },
+ { /* Coeff Band 5 */
+ { 8524543, 9285149, 4979435, 2039330, 683458, 266032, 22628, 270, 0, 0, 0, 0},
+ { 9432163, 10428088, 5715661, 2385738, 838389, 326264, 29981, 361, 0, 0, 0, 884},
+ { 9039066, 10368964, 6136765, 2862030, 1098269, 511668, 63105, 945, 14, 0, 0, 0}
+ },
+ { /* Coeff Band 6 */
+ { 33222872, 34748297, 17701695, 7214933, 2602336, 1191859, 187873, 12667, 390, 3, 0, 0},
+ { 34765051, 37140719, 19525578, 8268934, 3085012, 1473864, 246743, 15258, 736, 3, 0, 8403},
+ { 28591289, 32252393, 19037068, 9213729, 4020653, 2372354, 586420, 67428, 3920, 92, 7, 3}
+ },
+ { /* Coeff Band 7 */
+ { 68604786, 60777665, 19712887, 5656955, 1520443, 507166, 51829, 2466, 10, 0, 0, 0},
+ { 55447403, 51682540, 19008774, 5928582, 1706884, 595531, 65998, 3661, 101, 0, 0, 8468343},
+ { 28321970, 29149398, 13565882, 5258675, 1868588, 898041, 192023, 21497, 672, 17, 0, 1884921}
+ }
+ }
+ };
diff --git a/vp8/common/entropy.c b/vp8/common/entropy.c
index 652450c78..2c1667225 100644
--- a/vp8/common/entropy.c
+++ b/vp8/common/entropy.c
@@ -60,6 +60,22 @@ DECLARE_ALIGNED(16, const int, vp8_default_zig_zag1d[16]) =
9, 12, 13, 10,
7, 11, 14, 15,
};
+DECLARE_ALIGNED(64, cuchar, vp8_coef_bands_8x8[64]) = { 0, 1, 2, 3, 5, 4, 4, 5,
+ 5, 3, 6, 3, 5, 4, 6, 6,
+ 6, 5, 5, 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
+};
+DECLARE_ALIGNED(64, const int, vp8_default_zig_zag1d_8x8[64]) =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
+};
DECLARE_ALIGNED(16, const short, vp8_default_inv_zig_zag[16]) =
{
@@ -70,8 +86,7 @@ DECLARE_ALIGNED(16, const short, vp8_default_inv_zig_zag[16]) =
};
DECLARE_ALIGNED(16, short, vp8_default_zig_zag_mask[16]);
-
-const int vp8_mb_feature_data_bits[MB_LVL_MAX] = {7, 6};
+DECLARE_ALIGNED(64, short, vp8_default_zig_zag_mask_8x8[64]);//int64_t
/* Array indices are identical to previously-existing CONTEXT_NODE indices */
@@ -113,7 +128,10 @@ void vp8_init_scan_order_mask()
{
vp8_default_zig_zag_mask[vp8_default_zig_zag1d[i]] = 1 << i;
}
-
+ for (i = 0; i < 64; i++)
+ {
+ vp8_default_zig_zag_mask_8x8[vp8_default_zig_zag1d_8x8[i]] = 1 << i;
+ }
}
static void init_bit_tree(vp8_tree_index *p, int n)
@@ -156,11 +174,37 @@ vp8_extra_bit_struct vp8_extra_bits[12] =
};
#include "default_coef_probs.h"
+#include "defaultcoefcounts.h"
void vp8_default_coef_probs(VP8_COMMON *pc)
{
+ int h;
vpx_memcpy(pc->fc.coef_probs, default_coef_probs,
sizeof(default_coef_probs));
+ h = 0;
+ do
+ {
+ int i = 0;
+
+ do
+ {
+ int k = 0;
+
+ do
+ {
+ unsigned int branch_ct [ENTROPY_NODES] [2];
+ vp8_tree_probs_from_distribution(
+ MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ pc->fc.coef_probs_8x8 [h][i][k], branch_ct, vp8_default_coef_counts_8x8 [h][i][k],
+ 256, 1);
+
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++i < COEF_BANDS);
+ }
+ while (++h < BLOCK_TYPES);
+
}
void vp8_coef_tree_initialize()
diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h
index 3c25453a7..c7a41f58b 100644
--- a/vp8/common/entropy.h
+++ b/vp8/common/entropy.h
@@ -14,7 +14,7 @@
#include "treecoder.h"
#include "blockd.h"
-
+#include "common.h"
/* Coefficient token alphabet */
#define ZERO_TOKEN 0 /* 0 Extra Bits 0+0 */
@@ -52,7 +52,6 @@ extern vp8_extra_bit_struct vp8_extra_bits[12]; /* indexed by token value */
#define MAX_PROB 255
#define DCT_MAX_VALUE 8192
-
/* Coefficients are predicted via a 3-dimensional probability table. */
/* Outside dimension. 0 = Y no DC, 1 = Y2, 2 = UV, 3 = Y with DC */
@@ -64,6 +63,7 @@ extern vp8_extra_bit_struct vp8_extra_bits[12]; /* indexed by token value */
#define COEF_BANDS 8
extern DECLARE_ALIGNED(16, const unsigned char, vp8_coef_bands[16]);
+extern DECLARE_ALIGNED(64, const unsigned char, vp8_coef_bands_8x8[64]);
/* Inside dimension is 3-valued measure of nearby complexity, that is,
the extent to which nearby coefficients are nonzero. For the first
@@ -87,15 +87,14 @@ extern DECLARE_ALIGNED(16, const unsigned char, vp8_coef_bands[16]);
extern DECLARE_ALIGNED(16, const unsigned char, vp8_prev_token_class[MAX_ENTROPY_TOKENS]);
extern const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
-
+extern const vp8_prob vp8_coef_update_probs_8x8 [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
struct VP8Common;
void vp8_default_coef_probs(struct VP8Common *);
-
extern DECLARE_ALIGNED(16, const int, vp8_default_zig_zag1d[16]);
extern DECLARE_ALIGNED(16, const short, vp8_default_inv_zig_zag[16]);
extern short vp8_default_zig_zag_mask[16];
-extern const int vp8_mb_feature_data_bits[MB_LVL_MAX];
-
+extern DECLARE_ALIGNED(64, const int, vp8_default_zig_zag1d_8x8[64]);
+extern short vp8_default_zig_zag_mask_8x8[64];//int64_t
void vp8_coef_tree_initialize(void);
#endif
diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c
index 930e896ce..f220a6ba0 100644
--- a/vp8/common/entropymode.c
+++ b/vp8/common/entropymode.c
@@ -9,15 +9,59 @@
*/
+#include "modecont.h"
#include "entropymode.h"
#include "entropy.h"
#include "vpx_mem/vpx_mem.h"
-static const unsigned int kf_y_mode_cts[VP8_YMODES] = { 1607, 915, 812, 811, 5455};
-static const unsigned int y_mode_cts [VP8_YMODES] = { 8080, 1908, 1582, 1007, 5874};
+#if CONFIG_QIMODE
+const unsigned int kf_y_mode_cts[8][VP8_YMODES] =
+{
+ {17, 6, 5, 2, 22, 203},
+ {27, 13, 13, 6, 27, 170},
+ {35, 17, 18, 9, 26, 152},
+ {45, 22, 24, 12, 27, 126},
+ {58, 26, 29, 13, 26, 104},
+ {73, 33, 36, 17, 20, 78},
+ {88, 38, 39, 19, 16, 57},
+ {99, 42, 43, 21, 12, 39},
+};
+#else
+static const unsigned int kf_y_mode_cts[VP8_YMODES] = {
+ 49, 22, 23, 11, 23, 128};
+#endif
+
+static const unsigned int y_mode_cts [VP8_YMODES] = {
+ 106, 25, 21, 13, 16, 74};
+
+#if CONFIG_UVINTRA
+static const unsigned int uv_mode_cts [VP8_YMODES] [VP8_UV_MODES] ={
+ { 210, 20, 20, 6},
+ { 180, 60, 10, 6},
+ { 150, 20, 80, 6},
+ { 170, 35, 35, 16},
+ { 142, 51, 45, 18}, /* never used */
+ { 160, 40, 46, 10},
+};
+#else
static const unsigned int uv_mode_cts [VP8_UV_MODES] = { 59483, 13605, 16492, 4230};
+#endif
+
+static const unsigned int i8x8_mode_cts [VP8_UV_MODES] = {93, 69, 81, 13};
+
+#if CONFIG_UVINTRA
+static const unsigned int kf_uv_mode_cts [VP8_YMODES] [VP8_UV_MODES] ={
+ { 180, 34, 34, 8},
+ { 132, 74, 40, 10},
+ { 132, 40, 74, 10},
+ { 152, 46, 40, 18},
+ { 142, 51, 45, 18}, /* never used */
+ { 142, 51, 45, 18},
+};
+#else
static const unsigned int kf_uv_mode_cts[VP8_UV_MODES] = { 5319, 1904, 1703, 674};
+#endif
static const unsigned int bmode_cts[VP8_BINTRAMODES] =
{
@@ -117,23 +161,30 @@ const vp8_tree_index vp8_bmode_tree[18] = /* INTRAMODECONTEXTNODE value */
/* Again, these trees use the same probability indices as their
explicitly-programmed predecessors. */
-
-const vp8_tree_index vp8_ymode_tree[8] =
+const vp8_tree_index vp8_ymode_tree[10] =
{
-DC_PRED, 2,
4, 6,
-V_PRED, -H_PRED,
- -TM_PRED, -B_PRED
+ -TM_PRED, 8,
+ -B_PRED, -I8X8_PRED
};
-const vp8_tree_index vp8_kf_ymode_tree[8] =
+const vp8_tree_index vp8_kf_ymode_tree[10] =
{
-B_PRED, 2,
4, 6,
-DC_PRED, -V_PRED,
- -H_PRED, -TM_PRED
+ -H_PRED, 8,
+ -TM_PRED, -I8X8_PRED
};
+const vp8_tree_index vp8_i8x8_mode_tree[6] =
+{
+ -DC_PRED, 2,
+ -V_PRED, 4,
+ -H_PRED, -TM_PRED
+};
const vp8_tree_index vp8_uv_mode_tree[6] =
{
-DC_PRED, 2,
@@ -168,11 +219,33 @@ struct vp8_token_struct vp8_bmode_encodings [VP8_BINTRAMODES];
struct vp8_token_struct vp8_ymode_encodings [VP8_YMODES];
struct vp8_token_struct vp8_kf_ymode_encodings [VP8_YMODES];
struct vp8_token_struct vp8_uv_mode_encodings [VP8_UV_MODES];
+struct vp8_token_struct vp8_i8x8_mode_encodings [VP8_UV_MODES];
struct vp8_token_struct vp8_mbsplit_encodings [VP8_NUMMBSPLITS];
struct vp8_token_struct vp8_mv_ref_encoding_array [VP8_MVREFS];
struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS];
+#if CONFIG_HIGH_PRECISION_MV
+const vp8_tree_index vp8_small_mvtree_hp [30] =
+{
+ 2, 16,
+ 4, 10,
+ 6, 8,
+ -0, -1,
+ -2, -3,
+ 12, 14,
+ -4, -5,
+ -6, -7,
+ 18, 24,
+ 20, 22,
+ -8, -9,
+ -10, -11,
+ 26, 28,
+ -12, -13,
+ -14, -15
+};
+struct vp8_token_struct vp8_small_mvencodings_hp [16];
+#endif /* CONFIG_HIGH_PRECISION_MV */
const vp8_tree_index vp8_small_mvtree [14] =
{
@@ -184,9 +257,10 @@ const vp8_tree_index vp8_small_mvtree [14] =
-4, -5,
-6, -7
};
-
struct vp8_token_struct vp8_small_mvencodings [8];
+
+
void vp8_init_mbmode_probs(VP8_COMMON *x)
{
unsigned int bct [VP8_YMODES] [2]; /* num Ymodes > num UV modes */
@@ -196,22 +270,56 @@ void vp8_init_mbmode_probs(VP8_COMMON *x)
x->fc.ymode_prob, bct, y_mode_cts,
256, 1
);
+#if CONFIG_QIMODE
+ {
+ int i;
+ for (i=0;i<8;i++)
+ vp8_tree_probs_from_distribution(
+ VP8_YMODES, vp8_kf_ymode_encodings, vp8_kf_ymode_tree,
+ x->kf_ymode_prob[i], bct, kf_y_mode_cts[i],
+ 256, 1
+ );
+ }
+#else
vp8_tree_probs_from_distribution(
VP8_YMODES, vp8_kf_ymode_encodings, vp8_kf_ymode_tree,
x->kf_ymode_prob, bct, kf_y_mode_cts,
256, 1
);
+#endif
+#if CONFIG_UVINTRA
+ {
+ int i;
+ for (i=0;i<VP8_YMODES;i++)
+ {
+ vp8_tree_probs_from_distribution(
+ VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
+ x->kf_uv_mode_prob[i], bct, kf_uv_mode_cts[i],
+ 256, 1);
+ vp8_tree_probs_from_distribution(
+ VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
+ x->fc.uv_mode_prob[i], bct, uv_mode_cts[i],
+ 256, 1);
+ }
+ }
+#else
vp8_tree_probs_from_distribution(
VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
x->fc.uv_mode_prob, bct, uv_mode_cts,
- 256, 1
- );
+ 256, 1);
+
vp8_tree_probs_from_distribution(
VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
x->kf_uv_mode_prob, bct, kf_uv_mode_cts,
+ 256, 1);
+#endif
+ vp8_tree_probs_from_distribution(
+ VP8_UV_MODES, vp8_i8x8_mode_encodings, vp8_i8x8_mode_tree,
+ x->i8x8_mode_prob, bct, i8x8_mode_cts,
256, 1
- );
+ );
vpx_memcpy(x->fc.sub_mv_ref_prob, sub_mv_ref_prob, sizeof(sub_mv_ref_prob));
+
}
@@ -262,6 +370,7 @@ void vp8_entropy_mode_init()
vp8_tokens_from_tree(vp8_ymode_encodings, vp8_ymode_tree);
vp8_tokens_from_tree(vp8_kf_ymode_encodings, vp8_kf_ymode_tree);
vp8_tokens_from_tree(vp8_uv_mode_encodings, vp8_uv_mode_tree);
+ vp8_tokens_from_tree(vp8_i8x8_mode_encodings, vp8_i8x8_mode_tree);
vp8_tokens_from_tree(vp8_mbsplit_encodings, vp8_mbsplit_tree);
vp8_tokens_from_tree_offset(vp8_mv_ref_encoding_array,
@@ -270,4 +379,138 @@ void vp8_entropy_mode_init()
vp8_sub_mv_ref_tree, LEFT4X4);
vp8_tokens_from_tree(vp8_small_mvencodings, vp8_small_mvtree);
+#if CONFIG_HIGH_PRECISION_MV
+ vp8_tokens_from_tree(vp8_small_mvencodings_hp, vp8_small_mvtree_hp);
+#endif
+}
+
+void vp8_init_mode_contexts(VP8_COMMON *pc)
+{
+ vpx_memset(pc->mv_ref_ct, 0, sizeof(pc->mv_ref_ct));
+ vpx_memset(pc->mv_ref_ct_a, 0, sizeof(pc->mv_ref_ct_a));
+
+ vpx_memcpy( pc->mode_context,
+ default_vp8_mode_contexts,
+ sizeof (pc->mode_context));
+ vpx_memcpy( pc->mode_context_a,
+ default_vp8_mode_contexts,
+ sizeof (pc->mode_context_a));
+
+}
+
+void vp8_accum_mv_refs(VP8_COMMON *pc,
+ MB_PREDICTION_MODE m,
+ const int ct[4])
+{
+ int (*mv_ref_ct)[4][2];
+
+ if(pc->refresh_alt_ref_frame)
+ mv_ref_ct = pc->mv_ref_ct_a;
+ else
+ mv_ref_ct = pc->mv_ref_ct;
+
+ if (m == ZEROMV)
+ {
+ ++mv_ref_ct [ct[0]] [0] [0];
+ }
+ else
+ {
+ ++mv_ref_ct [ct[0]] [0] [1];
+ if (m == NEARESTMV)
+ {
+ ++mv_ref_ct [ct[1]] [1] [0];
+ }
+ else
+ {
+ ++mv_ref_ct [ct[1]] [1] [1];
+ if (m == NEARMV)
+ {
+ ++mv_ref_ct [ct[2]] [2] [0];
+ }
+ else
+ {
+ ++mv_ref_ct [ct[2]] [2] [1];
+ if (m == NEWMV)
+ {
+ ++mv_ref_ct [ct[3]] [3] [0];
+ }
+ else
+ {
+ ++mv_ref_ct [ct[3]] [3] [1];
+ }
+ }
+ }
+ }
+}
+
+void vp8_update_mode_context(VP8_COMMON *pc)
+{
+ int i, j;
+ int (*mv_ref_ct)[4][2];
+ int (*mode_context)[4];
+
+ if(pc->refresh_alt_ref_frame)
+ {
+ mv_ref_ct = pc->mv_ref_ct_a;
+ mode_context = pc->mode_context_a;
+ }
+ else
+ {
+ mv_ref_ct = pc->mv_ref_ct;
+ mode_context = pc->mode_context;
+ }
+
+ for (j = 0; j < 6; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ int this_prob;
+ int count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
+ /* preventing rare occurances from skewing the probs */
+ if (count>=4)
+ {
+ this_prob = 256 * mv_ref_ct[j][i][0] / count;
+ this_prob = this_prob? (this_prob<255?this_prob:255):1;
+ mode_context[j][i] = this_prob;
+ }
+ }
+ }
+}
+#include "vp8/common/modecont.h"
+void print_mode_contexts(VP8_COMMON *pc)
+{
+ int j, i;
+ printf("====================\n");
+ for(j=0; j<6; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ printf( "%4d ", pc->mode_context[j][i]);
+ }
+ printf("\n");
+ }
+ printf("====================\n");
+ for(j=0; j<6; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ printf( "%4d ", pc->mode_context_a[j][i]);
+ }
+ printf("\n");
+ }
+
+}
+void print_mv_ref_cts(VP8_COMMON *pc)
+{
+ int j, i;
+ for(j=0; j<6; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ printf("(%4d:%4d) ",
+ pc->mv_ref_ct[j][i][0],
+ pc->mv_ref_ct[j][i][1]);
+ }
+ printf("\n");
+ }
}
diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h
index fdb170df3..09d5c7704 100644
--- a/vp8/common/entropymode.h
+++ b/vp8/common/entropymode.h
@@ -38,7 +38,7 @@ extern const vp8_tree_index vp8_bmode_tree[];
extern const vp8_tree_index vp8_ymode_tree[];
extern const vp8_tree_index vp8_kf_ymode_tree[];
extern const vp8_tree_index vp8_uv_mode_tree[];
-
+extern const vp8_tree_index vp8_i8x8_mode_tree[];
extern const vp8_tree_index vp8_mbsplit_tree[];
extern const vp8_tree_index vp8_mv_ref_tree[];
extern const vp8_tree_index vp8_sub_mv_ref_tree[];
@@ -46,6 +46,7 @@ extern const vp8_tree_index vp8_sub_mv_ref_tree[];
extern struct vp8_token_struct vp8_bmode_encodings [VP8_BINTRAMODES];
extern struct vp8_token_struct vp8_ymode_encodings [VP8_YMODES];
extern struct vp8_token_struct vp8_kf_ymode_encodings [VP8_YMODES];
+extern struct vp8_token_struct vp8_i8x8_mode_encodings [VP8_UV_MODES];
extern struct vp8_token_struct vp8_uv_mode_encodings [VP8_UV_MODES];
extern struct vp8_token_struct vp8_mbsplit_encodings [VP8_NUMMBSPLITS];
@@ -55,12 +56,20 @@ extern struct vp8_token_struct vp8_mv_ref_encoding_array [VP8_MVREFS];
extern struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS];
extern const vp8_tree_index vp8_small_mvtree[];
-
extern struct vp8_token_struct vp8_small_mvencodings [8];
+#if CONFIG_HIGH_PRECISION_MV
+extern const vp8_tree_index vp8_small_mvtree_hp[];
+extern struct vp8_token_struct vp8_small_mvencodings_hp [16];
+#endif
void vp8_entropy_mode_init(void);
void vp8_init_mbmode_probs(VP8_COMMON *x);
+extern void vp8_init_mode_contexts(VP8_COMMON *pc);
+extern void vp8_update_mode_context(VP8_COMMON *pc);;
+extern void vp8_accum_mv_refs(VP8_COMMON *pc,
+ MB_PREDICTION_MODE m,
+ const int ct[4]);
void vp8_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES-1]);
void vp8_kf_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1]);
diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c
index e5df1f095..90195f7bc 100644
--- a/vp8/common/entropymv.c
+++ b/vp8/common/entropymv.c
@@ -11,6 +11,41 @@
#include "entropymv.h"
+#if CONFIG_HIGH_PRECISION_MV
+const MV_CONTEXT_HP vp8_mv_update_probs_hp[2] =
+{
+ {{
+ 237,
+ 246,
+ 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 250, 250, 252, 254, 254, 254
+ }},
+ {{
+ 231,
+ 243,
+ 245, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 251, 251, 254, 254, 254, 254
+ }}
+};
+const MV_CONTEXT_HP vp8_default_mv_context_hp[2] =
+{
+ {{
+ /* row */
+ 162, /* is short */
+ 128, /* sign */
+ 220, 204, 180, 192, 192, 119, 192, 192, 180, 140, 192, 192, 224, 224, 224, /* short tree */
+ 128, 129, 132, 75, 145, 178, 206, 239, 254, 254, 254 /* long bits */
+ }},
+ {{
+ /* same for column */
+ 164, /* is short */
+ 128,
+ 220, 204, 180, 192, 192, 119, 192, 192, 180, 140, 192, 192, 224, 224, 224, /* short tree */
+ 128, 130, 130, 74, 148, 180, 203, 236, 254, 254, 254 /* long bits */
+ }}
+};
+#endif /* CONFIG_HIGH_PRECISION_MV */
+
const MV_CONTEXT vp8_mv_update_probs[2] =
{
{{
@@ -35,15 +70,11 @@ const MV_CONTEXT vp8_default_mv_context[2] =
225, 146, 172, 147, 214, 39, 156, /* short tree */
128, 129, 132, 75, 145, 178, 206, 239, 254, 254 /* long bits */
}},
-
-
-
{{
/* same for column */
164, /* is short */
128,
204, 170, 119, 235, 140, 230, 228,
128, 130, 130, 74, 148, 180, 203, 236, 254, 254 /* long bits */
-
}}
};
diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h
index 2db1e385b..d97c12eab 100644
--- a/vp8/common/entropymv.h
+++ b/vp8/common/entropymv.h
@@ -13,16 +13,18 @@
#define __INC_ENTROPYMV_H
#include "treecoder.h"
+#include "vpx_config.h"
enum
{
mv_max = 1023, /* max absolute value of a MV component */
MVvals = (2 * mv_max) + 1, /* # possible values "" */
- mvfp_max = 255, /* max absolute value of a full pixel MV component */
- MVfpvals = (2 * mvfp_max) +1, /* # possible full pixel MV values */
-
mvlong_width = 10, /* Large MVs have 9 bit magnitudes */
mvnum_short = 8, /* magnitudes 0 through 7 */
+ mvnum_short_bits = 3, /* number of bits for short mvs */
+
+ mvfp_max = 255, /* max absolute value of a full pixel MV component */
+ MVfpvals = (2 * mvfp_max) + 1, /* # possible full pixel MV values */
/* probability offsets for coding each MV component */
@@ -41,4 +43,34 @@ typedef struct mv_context
extern const MV_CONTEXT vp8_mv_update_probs[2], vp8_default_mv_context[2];
+#if CONFIG_HIGH_PRECISION_MV
+enum
+{
+ mv_max_hp = 2047, /* max absolute value of a MV component */
+ MVvals_hp = (2 * mv_max_hp) + 1, /* # possible values "" */
+ mvlong_width_hp = 11, /* Large MVs have 9 bit magnitudes */
+ mvnum_short_hp = 16, /* magnitudes 0 through 15 */
+ mvnum_short_bits_hp = 4, /* number of bits for short mvs */
+
+ mvfp_max_hp = 255, /* max absolute value of a full pixel MV component */
+ MVfpvals_hp = (2 * mvfp_max_hp) + 1, /* # possible full pixel MV values */
+
+ /* probability offsets for coding each MV component */
+
+ mvpis_short_hp = 0, /* short (<= 7) vs long (>= 8) */
+ MVPsign_hp, /* sign for non-zero */
+ MVPshort_hp, /* 8 short values = 7-position tree */
+
+ MVPbits_hp = MVPshort_hp + mvnum_short_hp - 1, /* mvlong_width long value bits */
+ MVPcount_hp = MVPbits_hp + mvlong_width_hp /* (with independent probabilities) */
+};
+
+typedef struct mv_context_hp
+{
+ vp8_prob prob[MVPcount_hp]; /* often come in row, col pairs */
+} MV_CONTEXT_HP;
+
+extern const MV_CONTEXT_HP vp8_mv_update_probs_hp[2], vp8_default_mv_context_hp[2];
+#endif /* CONFIG_HIGH_PRECISION_MV */
+
#endif
diff --git a/vp8/common/filter.c b/vp8/common/filter.c
index ae5952952..d1ef79666 100644
--- a/vp8/common/filter.c
+++ b/vp8/common/filter.c
@@ -13,8 +13,26 @@
#include "filter.h"
#include "vpx_ports/mem.h"
-DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[8][2]) =
+DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[SUBPEL_SHIFTS][2]) =
{
+#if SUBPEL_SHIFTS==16
+ { 128, 0 },
+ { 120, 8 },
+ { 112, 16 },
+ { 104, 24 },
+ { 96, 32 },
+ { 88, 40 },
+ { 80, 48 },
+ { 72, 56 },
+ { 64, 64 },
+ { 56, 72 },
+ { 48, 80 },
+ { 40, 88 },
+ { 32, 96 },
+ { 24, 104 },
+ { 16, 112 },
+ { 8, 120 }
+#else
{ 128, 0 },
{ 112, 16 },
{ 96, 32 },
@@ -23,8 +41,197 @@ DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[8][2]) =
{ 48, 80 },
{ 32, 96 },
{ 16, 112 }
+#endif /* SUBPEL_SHIFTS==16 */
+};
+
+#if CONFIG_ENHANCED_INTERP
+#define FILTER_ALPHA 60
+DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXTEND]) =
+{
+ /* Generated using MATLAB:
+ * alpha = 0.6;
+ * b=intfilt(8,4,alpha);
+ * bi=round(128*b);
+ * ba=flipud(reshape([bi 0], 8, 8));
+ * disp(num2str(ba, '%d,'))
+ */
+#if SUBPEL_SHIFTS==16
+#if FILTER_ALPHA == 70
+ /* alpha = 0.70 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 2, -6, 126, 8, -3, 1, 0},
+ {-1, 4, -11, 123, 18, -7, 3, -1},
+ {-1, 5, -15, 119, 27, -10, 4, -1},
+ {-2, 6, -18, 113, 38, -13, 5, -1},
+ {-2, 7, -20, 106, 49, -16, 6, -2},
+ {-2, 8, -22, 98, 59, -18, 7, -2},
+ {-2, 8, -22, 89, 69, -20, 8, -2},
+ {-2, 8, -21, 79, 79, -21, 8, -2},
+ {-2, 8, -20, 69, 89, -22, 8, -2},
+ {-2, 7, -18, 59, 98, -22, 8, -2},
+ {-2, 6, -16, 49, 106, -20, 7, -2},
+ {-1, 5, -13, 38, 113, -18, 6, -2},
+ {-1, 4, -10, 27, 119, -15, 5, -1},
+ {-1, 3, -7, 18, 123, -11, 4, -1},
+ { 0, 1, -3, 8, 126, -6, 2, 0}
+#elif FILTER_ALPHA == 65
+ /* alpha = 0.65 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 2, -6, 126, 8, -3, 1, 0},
+ {-1, 3, -10, 123, 18, -6, 2, -1},
+ {-1, 5, -14, 118, 27, -10, 4, -1},
+ {-1, 5, -17, 112, 38, -13, 5, -1},
+ {-2, 6, -19, 106, 48, -15, 5, -1},
+ {-2, 7, -21, 98, 59, -17, 6, -2},
+ {-2, 7, -21, 89, 69, -19, 7, -2},
+ {-2, 7, -20, 79, 79, -20, 7, -2},
+ {-2, 7, -19, 69, 89, -21, 7, -2},
+ {-2, 6, -17, 59, 98, -21, 7, -2},
+ {-1, 5, -15, 48, 106, -19, 6, -2},
+ {-1, 5, -13, 38, 112, -17, 5, -1},
+ {-1, 4, -10, 27, 118, -14, 5, -1},
+ {-1, 2, -6, 18, 123, -10, 3, -1},
+ { 0, 1, -3, 8, 126, -6, 2, 0}
+#elif FILTER_ALPHA == 60
+ /* alpha = 0.60 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 2, -6, 126, 8, -3, 1, 0},
+ {-1, 3, -10, 123, 18, -6, 2, -1},
+ {-1, 4, -14, 118, 28, -9, 3, -1},
+ {-1, 5, -17, 112, 38, -12, 4, -1},
+ {-1, 6, -19, 105, 48, -15, 5, -1},
+ {-1, 6, -20, 97, 58, -17, 6, -1},
+ {-1, 6, -20, 88, 69, -19, 6, -1},
+ {-1, 6, -20, 79, 79, -20, 6, -1},
+ {-1, 6, -19, 69, 88, -20, 6, -1},
+ {-1, 6, -17, 58, 97, -20, 6, -1},
+ {-1, 5, -15, 48, 105, -19, 6, -1},
+ {-1, 4, -12, 38, 112, -17, 5, -1},
+ {-1, 3, -9, 28, 118, -14, 4, -1},
+ {-1, 2, -6, 18, 123, -10, 3, -1},
+ { 0, 1, -3, 8, 126, -6, 2, 0}
+#elif FILTER_ALPHA == 55
+ /* alpha = 0.55 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 1, -5, 126, 8, -3, 1, 0},
+ {-1, 2, -10, 123, 18, -6, 2, 0},
+ {-1, 4, -13, 118, 27, -9, 3, -1},
+ {-1, 5, -16, 112, 37, -12, 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, -12, 37, 112, -16, 5, -1},
+ {-1, 3, -9, 27, 118, -13, 4, -1},
+ { 0, 2, -6, 18, 123, -10, 2, -1},
+ { 0, 1, -3, 8, 126, -5, 1, 0}
+#elif FILTER_ALPHA == 50
+ /* alpha = 0.50 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 1, -5, 126, 8, -3, 1, 0},
+ { 0, 2, -10, 122, 18, -6, 2, 0},
+ {-1, 3, -13, 118, 27, -9, 3, 0},
+ {-1, 4, -16, 112, 37, -11, 3, 0},
+ {-1, 5, -17, 104, 48, -14, 4, -1},
+ {-1, 5, -18, 96, 58, -16, 5, -1},
+ {-1, 5, -19, 88, 68, -17, 5, -1},
+ {-1, 5, -18, 78, 78, -18, 5, -1},
+ {-1, 5, -17, 68, 88, -19, 5, -1},
+ {-1, 5, -16, 58, 96, -18, 5, -1},
+ {-1, 4, -14, 48, 104, -17, 5, -1},
+ { 0, 3, -11, 37, 112, -16, 4, -1},
+ { 0, 3, -9, 27, 118, -13, 3, -1},
+ { 0, 2, -6, 18, 122, -10, 2, 0},
+ { 0, 1, -3, 8, 126, -5, 1, 0}
+#elif FILTER_ALPHA == 0
+ /* Lagrangian interpolation filter */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 1, -5, 126, 8, -3, 1, 0},
+ {-1, 3, -10, 122, 18, -6, 2, 0},
+ {-1, 4, -13, 118, 27, -9, 3, -1},
+ {-1, 4, -16, 112, 37, -11, 4, -1},
+ {-1, 5, -18, 105, 48, -14, 4, -1},
+ {-1, 5, -19, 97, 58, -16, 5, -1},
+ {-1, 6, -19, 88, 68, -18, 5, -1},
+ {-1, 6, -19, 78, 78, -19, 6, -1},
+ {-1, 5, -18, 68, 88, -19, 6, -1},
+ {-1, 5, -16, 58, 97, -19, 5, -1},
+ {-1, 4, -14, 48, 105, -18, 5, -1},
+ {-1, 4, -11, 37, 112, -16, 4, -1},
+ {-1, 3, -9, 27, 118, -13, 4, -1},
+ { 0, 2, -6, 18, 122, -10, 3, -1},
+ { 0, 1, -3, 8, 126, -5, 1, 0}
+#endif /* FILTER_ALPHA */
+#else /* SUBPEL_SHIFTS==16 */
+#if FILTER_ALPHA == 70
+ /* alpha = 0.70 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ {-1, 4, -11, 123, 18, -7, 3, -1},
+ {-2, 6, -18, 113, 38, -13, 5, -1},
+ {-2, 8, -22, 98, 59, -18, 7, -2},
+ {-2, 8, -21, 79, 79, -21, 8, -2},
+ {-2, 7, -18, 59, 98, -22, 8, -2},
+ {-1, 5, -13, 38, 113, -18, 6, -2},
+ {-1, 3, -7, 18, 123, -11, 4, -1}
+#elif FILTER_ALPHA == 65
+ /* alpha = 0.65 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ {-1, 3, -10, 123, 18, -6, 2, -1},
+ {-1, 5, -17, 112, 38, -13, 5, -1},
+ {-2, 7, -21, 98, 59, -17, 6, -2},
+ {-2, 7, -20, 79, 79, -20, 7, -2},
+ {-2, 6, -17, 59, 98, -21, 7, -2},
+ {-1, 5, -13, 38, 112, -17, 5, -1},
+ {-1, 2, -6, 18, 123, -10, 3, -1}
+#elif FILTER_ALPHA == 60
+ /* alpha = 0.60 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ {-1, 3, -10, 123, 18, -6, 2, -1},
+ {-1, 5, -17, 112, 38, -12, 4, -1},
+ {-1, 6, -20, 97, 58, -17, 6, -1},
+ {-1, 6, -20, 79, 79, -20, 6, -1},
+ {-1, 6, -17, 58, 97, -20, 6, -1},
+ {-1, 4, -12, 38, 112, -17, 5, -1},
+ {-1, 2, -6, 18, 123, -10, 3, -1}
+#elif FILTER_ALPHA == 55
+ /* alpha = 0.55 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ {-1, 2, -10, 123, 18, -6, 2, 0},
+ {-1, 5, -16, 112, 37, -12, 4, -1},
+ {-1, 5, -19, 97, 58, -16, 5, -1},
+ {-1, 6, -19, 78, 78, -19, 6, -1},
+ {-1, 5, -16, 58, 97, -19, 5, -1},
+ {-1, 4, -12, 37, 112, -16, 5, -1},
+ { 0, 2, -6, 18, 123, -10, 2, -1}
+#elif FILTER_ALPHA == 50
+ /* alpha = 0.50 */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 2, -10, 122, 18, -6, 2, 0},
+ {-1, 4, -16, 112, 37, -11, 3, 0},
+ {-1, 5, -18, 96, 58, -16, 5, -1},
+ {-1, 5, -18, 78, 78, -18, 5, -1},
+ {-1, 5, -16, 58, 96, -18, 5, -1},
+ { 0, 3, -11, 37, 112, -16, 4, -1},
+ { 0, 2, -6, 18, 122, -10, 2, 0}
+#elif FILTER_ALPHA == 0
+ /* Lagrangian interpolation filter */
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ {-1, 3, -10, 122, 18, -6, 2, 0},
+ {-1, 4, -16, 112, 37, -11, 4, -1},
+ {-1, 5, -19, 97, 58, -16, 5, -1},
+ {-1, 6, -19, 78, 78, -19, 6, -1},
+ {-1, 5, -16, 58, 97, -19, 5, -1},
+ {-1, 4, -11, 37, 112, -16, 4, -1},
+ { 0, 2, -6, 18, 122, -10, 3, -1},
+#endif /* FILTER_ALPHA */
+#endif /* SUBPEL_SHIFTS==16 */
};
+#else // CONFIG_ENHANCED_INTERP
+
DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]) =
{
@@ -38,6 +245,8 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]) =
{ 0, -1, 12, 123, -6, 0 },
};
+#endif // CONFIG_ENHANCED_INTERP
+
static void filter_block2d_first_pass
(
unsigned char *src_ptr,
@@ -56,13 +265,37 @@ static void filter_block2d_first_pass
{
for (j = 0; j < output_width; j++)
{
+#if INTERP_EXTEND == 3
Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
- ((int)src_ptr[0] * vp8_filter[2]) +
- ((int)src_ptr[pixel_step] * vp8_filter[3]) +
- ((int)src_ptr[2*pixel_step] * vp8_filter[4]) +
- ((int)src_ptr[3*pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[0] * vp8_filter[2]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[3]) +
+ ((int)src_ptr[2*pixel_step] * vp8_filter[4]) +
+ ((int)src_ptr[3*pixel_step] * vp8_filter[5]) +
(VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#elif INTERP_EXTEND == 4
+ Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
+ ((int)src_ptr[0] * vp8_filter[3]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[4]) +
+ ((int)src_ptr[2 * pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[3 * pixel_step] * vp8_filter[6]) +
+ ((int)src_ptr[4 * pixel_step] * vp8_filter[7]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#elif INTERP_EXTEND == 5
+ Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
+ ((int)src_ptr[0] * vp8_filter[4]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[2 * pixel_step] * vp8_filter[6]) +
+ ((int)src_ptr[3 * pixel_step] * vp8_filter[7]) +
+ ((int)src_ptr[4 * pixel_step] * vp8_filter[8]) +
+ ((int)src_ptr[5 * pixel_step] * vp8_filter[9]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#endif
/* Normalize back to 0-255 */
Temp = Temp >> VP8_FILTER_SHIFT;
@@ -102,13 +335,37 @@ static void filter_block2d_second_pass
for (j = 0; j < output_width; j++)
{
/* Apply filter */
+#if INTERP_EXTEND == 3
Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
- ((int)src_ptr[0] * vp8_filter[2]) +
- ((int)src_ptr[pixel_step] * vp8_filter[3]) +
- ((int)src_ptr[2*pixel_step] * vp8_filter[4]) +
- ((int)src_ptr[3*pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[0] * vp8_filter[2]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[3]) +
+ ((int)src_ptr[2*pixel_step] * vp8_filter[4]) +
+ ((int)src_ptr[3*pixel_step] * vp8_filter[5]) +
(VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#elif INTERP_EXTEND == 4
+ Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
+ ((int)src_ptr[0] * vp8_filter[3]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[4]) +
+ ((int)src_ptr[2 * pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[3 * pixel_step] * vp8_filter[6]) +
+ ((int)src_ptr[4 * pixel_step] * vp8_filter[7]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#elif INTERP_EXTEND == 5
+ Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
+ ((int)src_ptr[0] * vp8_filter[4]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[2 * pixel_step] * vp8_filter[6]) +
+ ((int)src_ptr[3 * pixel_step] * vp8_filter[7]) +
+ ((int)src_ptr[4 * pixel_step] * vp8_filter[8]) +
+ ((int)src_ptr[5 * pixel_step] * vp8_filter[9]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#endif
/* Normalize back to 0-255 */
Temp = Temp >> VP8_FILTER_SHIFT;
@@ -128,6 +385,83 @@ static void filter_block2d_second_pass
}
}
+/*
+ * The only functional difference between filter_block2d_second_pass()
+ * and this function is that filter_block2d_second_pass() does a sixtap
+ * filter on the input and stores it in the output. This function
+ * (filter_block2d_second_pass_avg()) does a sixtap filter on the input,
+ * and then averages that with the content already present in the output
+ * ((filter_result + dest + 1) >> 1) and stores that in the output.
+ */
+static void filter_block2d_second_pass_avg
+(
+ int *src_ptr,
+ unsigned char *output_ptr,
+ int output_pitch,
+ unsigned int src_pixels_per_line,
+ unsigned int pixel_step,
+ unsigned int output_height,
+ unsigned int output_width,
+ const short *vp8_filter
+)
+{
+ unsigned int i, j;
+ int Temp;
+
+ for (i = 0; i < output_height; i++)
+ {
+ for (j = 0; j < output_width; j++)
+ {
+ /* Apply filter */
+#if INTERP_EXTEND == 3
+ Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[0] * vp8_filter[2]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[3]) +
+ ((int)src_ptr[2*pixel_step] * vp8_filter[4]) +
+ ((int)src_ptr[3*pixel_step] * vp8_filter[5]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#elif INTERP_EXTEND == 4
+ Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
+ ((int)src_ptr[0] * vp8_filter[3]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[4]) +
+ ((int)src_ptr[2 * pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[3 * pixel_step] * vp8_filter[6]) +
+ ((int)src_ptr[4 * pixel_step] * vp8_filter[7]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#elif INTERP_EXTEND == 5
+ Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
+ ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
+ ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
+ ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
+ ((int)src_ptr[0] * vp8_filter[4]) +
+ ((int)src_ptr[pixel_step] * vp8_filter[5]) +
+ ((int)src_ptr[2 * pixel_step] * vp8_filter[6]) +
+ ((int)src_ptr[3 * pixel_step] * vp8_filter[7]) +
+ ((int)src_ptr[4 * pixel_step] * vp8_filter[8]) +
+ ((int)src_ptr[5 * pixel_step] * vp8_filter[9]) +
+ (VP8_FILTER_WEIGHT >> 1); /* Rounding */
+#endif
+
+ /* Normalize back to 0-255 */
+ Temp = Temp >> VP8_FILTER_SHIFT;
+
+ if (Temp < 0)
+ Temp = 0;
+ else if (Temp > 255)
+ Temp = 255;
+
+ output_ptr[j] = (unsigned char) ((output_ptr[j] + Temp + 1) >> 1);
+ src_ptr++;
+ }
+
+ /* Start next row */
+ src_ptr += src_pixels_per_line - output_width;
+ output_ptr += output_pitch;
+ }
+}
static void filter_block2d
(
@@ -139,13 +473,14 @@ static void filter_block2d
const short *VFilter
)
{
- int FData[9*4]; /* Temp data buffer used in filtering */
+ int FData[(3+INTERP_EXTEND*2)*4]; /* Temp data buffer used in filtering */
/* First filter 1-D horizontally... */
- filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 4, HFilter);
+ filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+ 3+INTERP_EXTEND*2, 4, HFilter);
/* then filter verticaly... */
- filter_block2d_second_pass(FData + 8, output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
+ filter_block2d_second_pass(FData + 4*(INTERP_EXTEND-1), output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
}
@@ -179,20 +514,48 @@ void vp8_sixtap_predict8x8_c
{
const short *HFilter;
const short *VFilter;
- int FData[13*16]; /* Temp data buffer used in filtering */
+ // int FData[(7+INTERP_EXTEND*2)*16]; /* Temp data buffer used in filtering */
+ int FData[(7+INTERP_EXTEND*2)*8]; /* Temp data buffer used in filtering */
HFilter = vp8_sub_pel_filters[xoffset]; /* 6 tap */
VFilter = vp8_sub_pel_filters[yoffset]; /* 6 tap */
/* First filter 1-D horizontally... */
- filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 13, 8, HFilter);
+ filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+ 7+INTERP_EXTEND*2, 8, HFilter);
/* then filter verticaly... */
- filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+ filter_block2d_second_pass(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
}
+void vp8_sixtap_predict_avg8x8_c
+(
+ unsigned char *src_ptr,
+ int src_pixels_per_line,
+ int xoffset,
+ int yoffset,
+ unsigned char *dst_ptr,
+ int dst_pitch
+)
+{
+ const short *HFilter;
+ const short *VFilter;
+ // int FData[(7+INTERP_EXTEND*2)*16]; /* Temp data buffer used in filtering */
+ int FData[(7+INTERP_EXTEND*2)*8]; /* Temp data buffer used in filtering */
+
+ HFilter = vp8_sub_pel_filters[xoffset]; /* 6 tap */
+ VFilter = vp8_sub_pel_filters[yoffset]; /* 6 tap */
+
+ /* First filter 1-D horizontally... */
+ filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+ 7+INTERP_EXTEND*2, 8, HFilter);
+
+ /* then filter verticaly... */
+ filter_block2d_second_pass_avg(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+}
+
void vp8_sixtap_predict8x4_c
(
unsigned char *src_ptr,
@@ -205,17 +568,19 @@ void vp8_sixtap_predict8x4_c
{
const short *HFilter;
const short *VFilter;
- int FData[13*16]; /* Temp data buffer used in filtering */
+ // int FData[(7+INTERP_EXTEND*2)*16]; /* Temp data buffer used in filtering */
+ int FData[(3+INTERP_EXTEND*2)*8]; /* Temp data buffer used in filtering */
HFilter = vp8_sub_pel_filters[xoffset]; /* 6 tap */
VFilter = vp8_sub_pel_filters[yoffset]; /* 6 tap */
/* First filter 1-D horizontally... */
- filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 8, HFilter);
+ filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+ 3+INTERP_EXTEND*2, 8, HFilter);
/* then filter verticaly... */
- filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
+ filter_block2d_second_pass(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
}
@@ -231,20 +596,48 @@ void vp8_sixtap_predict16x16_c
{
const short *HFilter;
const short *VFilter;
- int FData[21*24]; /* Temp data buffer used in filtering */
+ // int FData[(15+INTERP_EXTEND*2)*24]; /* Temp data buffer used in filtering */
+ int FData[(15+INTERP_EXTEND*2)*16]; /* Temp data buffer used in filtering */
HFilter = vp8_sub_pel_filters[xoffset]; /* 6 tap */
VFilter = vp8_sub_pel_filters[yoffset]; /* 6 tap */
/* First filter 1-D horizontally... */
- filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 21, 16, HFilter);
+ filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+ 15+INTERP_EXTEND*2, 16, HFilter);
/* then filter verticaly... */
- filter_block2d_second_pass(FData + 32, dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
+ filter_block2d_second_pass(FData + 16*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
}
+void vp8_sixtap_predict_avg16x16_c
+(
+ unsigned char *src_ptr,
+ int src_pixels_per_line,
+ int xoffset,
+ int yoffset,
+ unsigned char *dst_ptr,
+ int dst_pitch
+)
+{
+ const short *HFilter;
+ const short *VFilter;
+ // int FData[(15+INTERP_EXTEND*2)*24]; /* Temp data buffer used in filtering */
+ int FData[(15+INTERP_EXTEND*2)*16]; /* Temp data buffer used in filtering */
+
+ HFilter = vp8_sub_pel_filters[xoffset]; /* 6 tap */
+ VFilter = vp8_sub_pel_filters[yoffset]; /* 6 tap */
+
+ /* First filter 1-D horizontally... */
+ filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData,
+ src_pixels_per_line, 1, 15+INTERP_EXTEND*2, 16, HFilter);
+
+ /* then filter verticaly... */
+ filter_block2d_second_pass_avg(FData + 16*(INTERP_EXTEND-1), dst_ptr, dst_pitch,
+ 16, 16, 16, 16, VFilter);
+}
/****************************************************************************
*
@@ -349,6 +742,44 @@ static void filter_block2d_bil_second_pass
}
}
+/*
+ * As before for filter_block2d_second_pass_avg(), the functional difference
+ * between filter_block2d_bil_second_pass() and filter_block2d_bil_second_pass_avg()
+ * is that filter_block2d_bil_second_pass() does a bilinear filter on input
+ * and stores the result in output; filter_block2d_bil_second_pass_avg(),
+ * instead, does a bilinear filter on input, averages the resulting value
+ * with the values already present in the output and stores the result of
+ * that back into the output ((filter_result + dest + 1) >> 1).
+ */
+static void filter_block2d_bil_second_pass_avg
+(
+ unsigned short *src_ptr,
+ unsigned char *dst_ptr,
+ int dst_pitch,
+ unsigned int height,
+ unsigned int width,
+ const short *vp8_filter
+)
+{
+ unsigned int i, j;
+ int Temp;
+
+ for (i = 0; i < height; i++)
+ {
+ for (j = 0; j < width; j++)
+ {
+ /* Apply filter */
+ Temp = ((int)src_ptr[0] * vp8_filter[0]) +
+ ((int)src_ptr[width] * vp8_filter[1]) +
+ (VP8_FILTER_WEIGHT / 2);
+ dst_ptr[j] = (unsigned int)(((Temp >> VP8_FILTER_SHIFT) + dst_ptr[j] + 1) >> 1);
+ src_ptr++;
+ }
+
+ /* Next row... */
+ dst_ptr += dst_pitch;
+ }
+}
/****************************************************************************
*
@@ -395,6 +826,26 @@ static void filter_block2d_bil
filter_block2d_bil_second_pass(FData, dst_ptr, dst_pitch, Height, Width, VFilter);
}
+static void filter_block2d_bil_avg
+(
+ unsigned char *src_ptr,
+ unsigned char *dst_ptr,
+ unsigned int src_pitch,
+ unsigned int dst_pitch,
+ const short *HFilter,
+ const short *VFilter,
+ int Width,
+ int Height
+)
+{
+ unsigned short FData[17*16]; /* Temp data buffer used in filtering */
+
+ /* First filter 1-D horizontally... */
+ filter_block2d_bil_first_pass(src_ptr, FData, src_pitch, Height + 1, Width, HFilter);
+
+ /* then 1-D vertically... */
+ filter_block2d_bil_second_pass_avg(FData, dst_ptr, dst_pitch, Height, Width, VFilter);
+}
void vp8_bilinear_predict4x4_c
(
@@ -454,6 +905,26 @@ void vp8_bilinear_predict8x8_c
}
+void vp8_bilinear_predict_avg8x8_c
+(
+ unsigned char *src_ptr,
+ int src_pixels_per_line,
+ int xoffset,
+ int yoffset,
+ unsigned char *dst_ptr,
+ int dst_pitch
+)
+{
+ const short *HFilter;
+ const short *VFilter;
+
+ HFilter = vp8_bilinear_filters[xoffset];
+ VFilter = vp8_bilinear_filters[yoffset];
+
+ filter_block2d_bil_avg(src_ptr, dst_ptr, src_pixels_per_line,
+ dst_pitch, HFilter, VFilter, 8, 8);
+}
+
void vp8_bilinear_predict8x4_c
(
unsigned char *src_ptr,
@@ -492,3 +963,23 @@ void vp8_bilinear_predict16x16_c
filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
}
+
+void vp8_bilinear_predict_avg16x16_c
+(
+ unsigned char *src_ptr,
+ int src_pixels_per_line,
+ int xoffset,
+ int yoffset,
+ unsigned char *dst_ptr,
+ int dst_pitch
+)
+{
+ const short *HFilter;
+ const short *VFilter;
+
+ HFilter = vp8_bilinear_filters[xoffset];
+ VFilter = vp8_bilinear_filters[yoffset];
+
+ filter_block2d_bil_avg(src_ptr, dst_ptr, src_pixels_per_line,
+ dst_pitch, HFilter, VFilter, 16, 16);
+}
diff --git a/vp8/common/filter.h b/vp8/common/filter.h
index 0f225c25a..d502216d2 100644
--- a/vp8/common/filter.h
+++ b/vp8/common/filter.h
@@ -8,15 +8,23 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-
#ifndef FILTER_H
#define FILTER_H
+#include "vpx_config.h"
+#include "vpx_scale/yv12config.h"
+
#define BLOCK_HEIGHT_WIDTH 4
#define VP8_FILTER_WEIGHT 128
#define VP8_FILTER_SHIFT 7
-extern const short vp8_bilinear_filters[8][2];
-extern const short vp8_sub_pel_filters[8][6];
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define SUBPEL_SHIFTS 16
+#else
+#define SUBPEL_SHIFTS 8
+#endif
+
+extern const short vp8_bilinear_filters[SUBPEL_SHIFTS][2];
+extern const short vp8_sub_pel_filters[SUBPEL_SHIFTS][INTERP_EXTEND*2];
#endif //FILTER_H
diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c
index c1022363e..a74147106 100644
--- a/vp8/common/findnearmv.c
+++ b/vp8/common/findnearmv.c
@@ -21,10 +21,12 @@ const unsigned char vp8_mbsplit_offset[4][16] = {
/* Predict motion vectors using those from already-decoded nearby blocks.
Note that we only consider one 4x4 subblock from each candidate 16x16
macroblock. */
+
void vp8_find_near_mvs
(
MACROBLOCKD *xd,
const MODE_INFO *here,
+ const MODE_INFO *lf_here,
int_mv *nearest,
int_mv *nearby,
int_mv *best_mv,
@@ -36,6 +38,7 @@ void vp8_find_near_mvs
const MODE_INFO *above = here - xd->mode_info_stride;
const MODE_INFO *left = here - 1;
const MODE_INFO *aboveleft = above - 1;
+ const MODE_INFO *third = NULL;
int_mv near_mvs[4];
int_mv *mv = near_mvs;
int *cntx = cnt;
@@ -51,10 +54,10 @@ void vp8_find_near_mvs
if (above->mbmi.mv.as_int)
{
(++mv)->as_int = above->mbmi.mv.as_int;
- mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame], refframe, mv, ref_frame_sign_bias);
+ mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
+ refframe, mv, ref_frame_sign_bias);
++cntx;
}
-
*cntx += 2;
}
@@ -64,38 +67,44 @@ void vp8_find_near_mvs
if (left->mbmi.mv.as_int)
{
int_mv this_mv;
-
this_mv.as_int = left->mbmi.mv.as_int;
- mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame], refframe, &this_mv, ref_frame_sign_bias);
+ mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
+ refframe, &this_mv, ref_frame_sign_bias);
if (this_mv.as_int != mv->as_int)
{
(++mv)->as_int = this_mv.as_int;
++cntx;
}
-
*cntx += 2;
}
else
cnt[CNT_INTRA] += 2;
}
-
- /* Process above left */
- if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
+ /* Process above left or the one frome last frame */
+ if ( aboveleft->mbmi.ref_frame != INTRA_FRAME||
+ (lf_here->mbmi.ref_frame==LAST_FRAME && refframe == LAST_FRAME))
{
if (aboveleft->mbmi.mv.as_int)
{
+ third = aboveleft;
+ }
+ else if(lf_here->mbmi.mv.as_int)
+ {
+ third = lf_here;
+ }
+ if(third)
+ {
int_mv this_mv;
-
- this_mv.as_int = aboveleft->mbmi.mv.as_int;
- mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame], refframe, &this_mv, ref_frame_sign_bias);
+ this_mv.as_int = third->mbmi.mv.as_int;
+ mv_bias(ref_frame_sign_bias[third->mbmi.ref_frame],
+ refframe, &this_mv, ref_frame_sign_bias);
if (this_mv.as_int != mv->as_int)
{
(++mv)->as_int = this_mv.as_int;
++cntx;
}
-
*cntx += 1;
}
else
@@ -105,14 +114,16 @@ void vp8_find_near_mvs
/* If we have three distinct MV's ... */
if (cnt[CNT_SPLITMV])
{
- /* See if above-left MV can be merged with NEAREST */
+ /* See if the third MV can be merged with NEAREST */
if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
cnt[CNT_NEAREST] += 1;
}
cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
+ (left->mbmi.mode == SPLITMV)) * 2
- + (aboveleft->mbmi.mode == SPLITMV);
+ + (
+ lf_here->mbmi.mode == SPLITMV ||
+ aboveleft->mbmi.mode == SPLITMV);
/* Swap near and nearest if necessary */
if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
@@ -135,21 +146,40 @@ void vp8_find_near_mvs
nearest->as_int = near_mvs[CNT_NEAREST].as_int;
nearby->as_int = near_mvs[CNT_NEAR].as_int;
+ /* Make sure that the 1/8th bits of the Mvs are zero if high_precision
+ * is not being used, by truncating the last bit towards 0
+ */
+#if CONFIG_HIGH_PRECISION_MV
+ if (!xd->allow_high_precision_mv)
+ {
+ if (best_mv->as_mv.row & 1)
+ best_mv->as_mv.row += (best_mv->as_mv.row > 0 ? -1 : 1);
+ if (best_mv->as_mv.col & 1)
+ best_mv->as_mv.col += (best_mv->as_mv.col > 0 ? -1 : 1);
+ if (nearest->as_mv.row & 1)
+ nearest->as_mv.row += (nearest->as_mv.row > 0 ? -1 : 1);
+ if (nearest->as_mv.col & 1)
+ nearest->as_mv.col += (nearest->as_mv.col > 0 ? -1 : 1);
+ if (nearby->as_mv.row & 1)
+ nearby->as_mv.row += (nearby->as_mv.row > 0 ? -1 : 1);
+ if (nearby->as_mv.col & 1)
+ nearby->as_mv.col += (nearby->as_mv.col > 0 ? -1 : 1);
+ }
+#endif
+
//TODO: move clamp outside findnearmv
vp8_clamp_mv2(nearest, xd);
vp8_clamp_mv2(nearby, xd);
vp8_clamp_mv2(best_mv, xd);
}
-vp8_prob *vp8_mv_ref_probs(
+vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc,
vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
)
{
- p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0];
- p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1];
- p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2];
- p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3];
- /*p[3] = vp8_mode_contexts [near_mv_ref_ct[1] + near_mv_ref_ct[2] + near_mv_ref_ct[3]] [3];*/
+ p[0] = pc->vp8_mode_contexts [near_mv_ref_ct[0]] [0];
+ p[1] = pc->vp8_mode_contexts [near_mv_ref_ct[1]] [1];
+ p[2] = pc->vp8_mode_contexts [near_mv_ref_ct[2]] [2];
+ p[3] = pc->vp8_mode_contexts [near_mv_ref_ct[3]] [3];
return p;
}
-
diff --git a/vp8/common/findnearmv.h b/vp8/common/findnearmv.h
index c142a0415..523000b55 100644
--- a/vp8/common/findnearmv.h
+++ b/vp8/common/findnearmv.h
@@ -16,6 +16,7 @@
#include "blockd.h"
#include "modecont.h"
#include "treecoder.h"
+#include "onyxc_int.h"
static void mv_bias(int refmb_ref_frame_sign_bias, int refframe, int_mv *mvp, const int *ref_frame_sign_bias)
@@ -75,13 +76,14 @@ void vp8_find_near_mvs
(
MACROBLOCKD *xd,
const MODE_INFO *here,
+ const MODE_INFO *lfhere,
int_mv *nearest, int_mv *nearby, int_mv *best,
int near_mv_ref_cts[4],
int refframe,
int *ref_frame_sign_bias
);
-vp8_prob *vp8_mv_ref_probs(
+vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc,
vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
);
@@ -125,8 +127,6 @@ static B_PREDICTION_MODE left_block_mode(const MODE_INFO *cur_mb, int b)
--cur_mb;
switch (cur_mb->mbmi.mode)
{
- case B_PRED:
- return (cur_mb->bmi + b + 3)->as_mode;
case DC_PRED:
return B_DC_PRED;
case V_PRED:
@@ -135,15 +135,18 @@ static B_PREDICTION_MODE left_block_mode(const MODE_INFO *cur_mb, int b)
return B_HE_PRED;
case TM_PRED:
return B_TM_PRED;
+ case I8X8_PRED:
+ case B_PRED:
+ return (cur_mb->bmi + b + 3)->as_mode.first;
default:
return B_DC_PRED;
}
}
-
- return (cur_mb->bmi + b - 1)->as_mode;
+ return (cur_mb->bmi + b - 1)->as_mode.first;
}
-static B_PREDICTION_MODE above_block_mode(const MODE_INFO *cur_mb, int b, int mi_stride)
+static B_PREDICTION_MODE above_block_mode(const MODE_INFO
+ *cur_mb, int b, int mi_stride)
{
if (!(b >> 2))
{
@@ -152,8 +155,6 @@ static B_PREDICTION_MODE above_block_mode(const MODE_INFO *cur_mb, int b, int mi
switch (cur_mb->mbmi.mode)
{
- case B_PRED:
- return (cur_mb->bmi + b + 12)->as_mode;
case DC_PRED:
return B_DC_PRED;
case V_PRED:
@@ -162,12 +163,15 @@ static B_PREDICTION_MODE above_block_mode(const MODE_INFO *cur_mb, int b, int mi
return B_HE_PRED;
case TM_PRED:
return B_TM_PRED;
+ case I8X8_PRED:
+ case B_PRED:
+ return (cur_mb->bmi + b + 12)->as_mode.first;
default:
return B_DC_PRED;
}
}
- return (cur_mb->bmi + b - 4)->as_mode;
+ return (cur_mb->bmi + b - 4)->as_mode.first;
}
#endif
diff --git a/vp8/common/generic/systemdependent.c b/vp8/common/generic/systemdependent.c
index 75b0984bb..6168dc5ef 100644
--- a/vp8/common/generic/systemdependent.c
+++ b/vp8/common/generic/systemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/g_common.h"
#include "vp8/common/subpixel.h"
#include "vp8/common/loopfilter.h"
@@ -17,54 +17,9 @@
#include "vp8/common/idct.h"
#include "vp8/common/onyxc_int.h"
-#if CONFIG_MULTITHREAD
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#elif defined(_WIN32)
-#include <windows.h>
-typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
-#endif
-#endif
-
extern void vp8_arch_x86_common_init(VP8_COMMON *ctx);
extern void vp8_arch_arm_common_init(VP8_COMMON *ctx);
-#if CONFIG_MULTITHREAD
-static int get_cpu_count()
-{
- int core_count = 16;
-
-#if HAVE_UNISTD_H
-#if defined(_SC_NPROCESSORS_ONLN)
- core_count = sysconf(_SC_NPROCESSORS_ONLN);
-#elif defined(_SC_NPROC_ONLN)
- core_count = sysconf(_SC_NPROC_ONLN);
-#endif
-#elif defined(_WIN32)
- {
- PGNSI pGNSI;
- SYSTEM_INFO sysinfo;
-
- /* Call GetNativeSystemInfo if supported or
- * GetSystemInfo otherwise. */
-
- pGNSI = (PGNSI) GetProcAddress(
- GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
- if (pGNSI != NULL)
- pGNSI(&sysinfo);
- else
- GetSystemInfo(&sysinfo);
-
- core_count = sysinfo.dwNumberOfProcessors;
- }
-#else
- /* other platforms */
-#endif
-
- return core_count > 0 ? core_count : 1;
-}
-#endif
-
void vp8_machine_specific_config(VP8_COMMON *ctx)
{
#if CONFIG_RUNTIME_CPU_DETECT
@@ -75,34 +30,67 @@ void vp8_machine_specific_config(VP8_COMMON *ctx)
rtcd->idct.idct1_scalar_add = vp8_dc_only_idct_add_c;
rtcd->idct.iwalsh1 = vp8_short_inv_walsh4x4_1_c;
rtcd->idct.iwalsh16 = vp8_short_inv_walsh4x4_c;
-
+ rtcd->idct.idct8 = vp8_short_idct8x8_c;
+ rtcd->idct.idct1_scalar_add_8x8 = vp8_dc_only_idct_add_8x8_c;
+ rtcd->idct.ihaar2 = vp8_short_ihaar2x2_c;
rtcd->recon.copy16x16 = vp8_copy_mem16x16_c;
rtcd->recon.copy8x8 = vp8_copy_mem8x8_c;
+ rtcd->recon.avg16x16 = vp8_avg_mem16x16_c;
+ rtcd->recon.avg8x8 = vp8_avg_mem8x8_c;
rtcd->recon.copy8x4 = vp8_copy_mem8x4_c;
rtcd->recon.recon = vp8_recon_b_c;
+ rtcd->recon.recon_uv = vp8_recon_uv_b_c;
rtcd->recon.recon2 = vp8_recon2b_c;
rtcd->recon.recon4 = vp8_recon4b_c;
rtcd->recon.recon_mb = vp8_recon_mb_c;
rtcd->recon.recon_mby = vp8_recon_mby_c;
rtcd->recon.build_intra_predictors_mby =
vp8_build_intra_predictors_mby;
+#if CONFIG_COMP_INTRA_PRED
+ rtcd->recon.build_comp_intra_predictors_mby =
+ vp8_build_comp_intra_predictors_mby;
+#endif
rtcd->recon.build_intra_predictors_mby_s =
vp8_build_intra_predictors_mby_s;
rtcd->recon.build_intra_predictors_mbuv =
vp8_build_intra_predictors_mbuv;
rtcd->recon.build_intra_predictors_mbuv_s =
vp8_build_intra_predictors_mbuv_s;
+#if CONFIG_COMP_INTRA_PRED
+ rtcd->recon.build_comp_intra_predictors_mbuv =
+ vp8_build_comp_intra_predictors_mbuv;
+#endif
rtcd->recon.intra4x4_predict =
vp8_intra4x4_predict;
+#if CONFIG_COMP_INTRA_PRED
+ rtcd->recon.comp_intra4x4_predict =
+ vp8_comp_intra4x4_predict;
+#endif
+ rtcd->recon.intra8x8_predict =
+ vp8_intra8x8_predict;
+#if CONFIG_COMP_INTRA_PRED
+ rtcd->recon.comp_intra8x8_predict =
+ vp8_comp_intra8x8_predict;
+#endif
+ rtcd->recon.intra_uv4x4_predict =
+ vp8_intra_uv4x4_predict;
+#if CONFIG_COMP_INTRA_PRED
+ rtcd->recon.comp_intra_uv4x4_predict =
+ vp8_comp_intra_uv4x4_predict;
+#endif
- rtcd->subpix.sixtap16x16 = vp8_sixtap_predict16x16_c;
- rtcd->subpix.sixtap8x8 = vp8_sixtap_predict8x8_c;
- rtcd->subpix.sixtap8x4 = vp8_sixtap_predict8x4_c;
- rtcd->subpix.sixtap4x4 = vp8_sixtap_predict_c;
- rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_c;
- rtcd->subpix.bilinear8x8 = vp8_bilinear_predict8x8_c;
- rtcd->subpix.bilinear8x4 = vp8_bilinear_predict8x4_c;
- rtcd->subpix.bilinear4x4 = vp8_bilinear_predict4x4_c;
+ rtcd->subpix.sixtap16x16 = vp8_sixtap_predict16x16_c;
+ rtcd->subpix.sixtap8x8 = vp8_sixtap_predict8x8_c;
+ rtcd->subpix.sixtap_avg16x16 = vp8_sixtap_predict_avg16x16_c;
+ rtcd->subpix.sixtap_avg8x8 = vp8_sixtap_predict_avg8x8_c;
+ rtcd->subpix.sixtap8x4 = vp8_sixtap_predict8x4_c;
+ rtcd->subpix.sixtap4x4 = vp8_sixtap_predict_c;
+ rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_c;
+ rtcd->subpix.bilinear8x8 = vp8_bilinear_predict8x8_c;
+ rtcd->subpix.bilinear_avg16x16 = vp8_bilinear_predict_avg16x16_c;
+ rtcd->subpix.bilinear_avg8x8 = vp8_bilinear_predict_avg8x8_c;
+ rtcd->subpix.bilinear8x4 = vp8_bilinear_predict8x4_c;
+ rtcd->subpix.bilinear4x4 = vp8_bilinear_predict4x4_c;
rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_c;
rtcd->loopfilter.normal_b_v = vp8_loop_filter_bv_c;
@@ -133,17 +121,10 @@ void vp8_machine_specific_config(VP8_COMMON *ctx)
#if ARCH_ARM
vp8_arch_arm_common_init(ctx);
#endif
-#if CONFIG_EXTEND_QRANGE
rtcd->idct.idct1 = vp8_short_idct4x4llm_1_c;
rtcd->idct.idct16 = vp8_short_idct4x4llm_c;
rtcd->idct.idct1_scalar_add = vp8_dc_only_idct_add_c;
rtcd->idct.iwalsh1 = vp8_short_inv_walsh4x4_1_c;
rtcd->idct.iwalsh16 = vp8_short_inv_walsh4x4_c;
-#endif
-
-
-#if CONFIG_MULTITHREAD
- ctx->processor_core_count = get_cpu_count();
-#endif /* CONFIG_MULTITHREAD */
}
diff --git a/vp8/common/idct.h b/vp8/common/idct.h
index f5fd94dfd..e8ca23d66 100644
--- a/vp8/common/idct.h
+++ b/vp8/common/idct.h
@@ -31,6 +31,34 @@
#include "arm/idct_arm.h"
#endif
+
+#ifndef vp8_idct_idct8
+#define vp8_idct_idct8 vp8_short_idct8x8_c
+#endif
+extern prototype_idct(vp8_idct_idct8);
+
+#ifndef vp8_idct_idct8_1
+#define vp8_idct_idct8_1 vp8_short_idct8x8_1_c
+#endif
+extern prototype_idct(vp8_idct_idct8_1);
+
+#ifndef vp8_idct_ihaar2
+#define vp8_idct_ihaar2 vp8_short_ihaar2x2_c
+#endif
+extern prototype_idct(vp8_idct_ihaar2);
+
+#ifndef vp8_idct_ihaar2_1
+#define vp8_idct_ihaar2_1 vp8_short_ihaar2x2_1_c
+#endif
+extern prototype_idct(vp8_idct_ihaar2_1);
+
+#ifndef vp8_idct_idct1_scalar_add_8x8
+#define vp8_idct_idct1_scalar_add_8x8 vp8_dc_only_idct_add_8x8_c
+#endif
+extern prototype_idct_scalar_add(vp8_idct_idct1_scalar_add_8x8);
+
+
+
#ifndef vp8_idct_idct1
#define vp8_idct_idct1 vp8_short_idct4x4llm_1_c
#endif
@@ -69,6 +97,12 @@ typedef struct
vp8_second_order_fn_t iwalsh1;
vp8_second_order_fn_t iwalsh16;
+
+ vp8_idct_fn_t idct8;
+ vp8_idct_fn_t idct8_1;
+ vp8_idct_scalar_add_fn_t idct1_scalar_add_8x8;
+ vp8_idct_fn_t ihaar2;
+ vp8_idct_fn_t ihaar2_1;
} vp8_idct_rtcd_vtable_t;
#if CONFIG_RUNTIME_CPU_DETECT
diff --git a/vp8/common/idctllm.c b/vp8/common/idctllm.c
index a71e4be9c..f0536d5e4 100644
--- a/vp8/common/idctllm.c
+++ b/vp8/common/idctllm.c
@@ -22,11 +22,15 @@
* so
* x * sqrt(2) * cos (pi/8) = x + x * (sqrt(2) *cos(pi/8)-1).
**************************************************************************/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
+
+
+#include <math.h>
static const int cospi8sqrt2minus1 = 20091;
static const int sinpi8sqrt2 = 35468;
static const int rounding = 0;
+
void vp8_short_idct4x4llm_c(short *input, short *output, int pitch)
{
int i;
@@ -76,20 +80,11 @@ void vp8_short_idct4x4llm_c(short *input, short *output, int pitch)
temp2 = (ip[3] * sinpi8sqrt2 + rounding) >> 16;
d1 = temp1 + temp2;
-
-#if !CONFIG_EXTEND_QRANGE
- op[0] = (a1 + d1 + 4) >> 3;
- op[3] = (a1 - d1 + 4) >> 3;
-
- op[1] = (b1 + c1 + 4) >> 3;
- op[2] = (b1 - c1 + 4) >> 3;
-#else
op[0] = (a1 + d1 + 16) >> 5;
op[3] = (a1 - d1 + 16) >> 5;
op[1] = (b1 + c1 + 16) >> 5;
op[2] = (b1 - c1 + 16) >> 5;
-#endif
ip += shortpitch;
op += shortpitch;
@@ -102,11 +97,7 @@ void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch)
int a1;
short *op = output;
int shortpitch = pitch >> 1;
-#if !CONFIG_EXTEND_QRANGE
- a1 = ((input[0] + 4) >> 3);
-#else
a1 = ((input[0] + 16) >> 5);
-#endif
for (i = 0; i < 4; i++)
{
op[0] = a1;
@@ -119,11 +110,7 @@ void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch)
void vp8_dc_only_idct_add_c(short input_dc, unsigned char *pred_ptr, unsigned char *dst_ptr, int pitch, int stride)
{
-#if !CONFIG_EXTEND_QRANGE
- int a1 = ((input_dc + 4) >> 3);
-#else
int a1 = ((input_dc + 16) >> 5);
-#endif
int r, c;
for (r = 0; r < 4; r++)
@@ -185,17 +172,11 @@ void vp8_short_inv_walsh4x4_c(short *input, short *output)
c2 = a1 - b1;
d2 = d1 - c1;
-#if !CONFIG_EXTEND_QRANGE
- op[0] = (a2 + 3) >> 3;
- op[1] = (b2 + 3) >> 3;
- op[2] = (c2 + 3) >> 3;
- op[3] = (d2 + 3) >> 3;
-#else
op[0] = (a2 + 1) >> 2;
op[1] = (b2 + 1) >> 2;
op[2] = (c2 + 1) >> 2;
op[3] = (d2 + 1) >> 2;
-#endif
+
ip += 4;
op += 4;
}
@@ -207,11 +188,7 @@ void vp8_short_inv_walsh4x4_1_c(short *input, short *output)
int a1;
short *op = output;
-#if !CONFIG_EXTEND_QRANGE
- a1 = (input[0] + 3 )>> 3;
-#else
a1 = (input[0] + 1 )>> 2;
-#endif
for (i = 0; i < 4; i++)
{
@@ -222,3 +199,212 @@ void vp8_short_inv_walsh4x4_1_c(short *input, short *output)
op += 4;
}
}
+
+
+void vp8_dc_only_idct_add_8x8_c(short input_dc,
+ unsigned char *pred_ptr,
+ unsigned char *dst_ptr,
+ int pitch, int stride)
+{
+ int a1 = ((input_dc + 16) >> 5);
+ int r, c, b;
+ unsigned char *orig_pred = pred_ptr;
+ unsigned char *orig_dst = dst_ptr;
+ for (b = 0; b < 4; b++)
+ {
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ int a = a1 + pred_ptr[c] ;
+
+ if (a < 0)
+ a = 0;
+
+ if (a > 255)
+ a = 255;
+
+ dst_ptr[c] = (unsigned char) a ;
+ }
+
+ dst_ptr += stride;
+ pred_ptr += pitch;
+ }
+ dst_ptr = orig_dst + (b+1)%2*4 + (b+1)/2*4*stride;
+ pred_ptr = orig_pred + (b+1)%2*4 + (b+1)/2*4*pitch;
+ }
+}
+
+#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
+#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
+#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
+#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
+#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
+#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */
+
+/* row (horizontal) IDCT
+ *
+ * 7 pi 1 dst[k] = sum c[l] * src[l] * cos( -- *
+ * ( k + - ) * l ) l=0 8 2
+ *
+ * where: c[0] = 128 c[1..7] = 128*sqrt(2) */
+
+static void idctrow (int *blk)
+{
+ int x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ /* shortcut */
+ if (!((x1 = blk[4] << 11) | (x2 = blk[6]) | (x3 = blk[2]) |
+ (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3])))
+ {
+ blk[0] = blk[1] = blk[2] = blk[3] = blk[4]
+ = blk[5] = blk[6] = blk[7] = blk[0] << 3;
+ return;
+ }
+
+ x0 = (blk[0] << 11) + 128; /* for proper rounding in the fourth stage */
+ /* first stage */
+ x8 = W7 * (x4 + x5);
+ x4 = x8 + (W1 - W7) * x4;
+ x5 = x8 - (W1 + W7) * x5;
+ x8 = W3 * (x6 + x7);
+ x6 = x8 - (W3 - W5) * x6;
+ x7 = x8 - (W3 + W5) * x7;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6 * (x3 + x2);
+ x2 = x1 - (W2 + W6) * x2;
+ x3 = x1 + (W2 - W6) * x3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x4 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ blk[0] = (x7 + x1) >> 8;
+ blk[1] = (x3 + x2) >> 8;
+ blk[2] = (x0 + x4) >> 8;
+ blk[3] = (x8 + x6) >> 8;
+ blk[4] = (x8 - x6) >> 8;
+ blk[5] = (x0 - x4) >> 8;
+ blk[6] = (x3 - x2) >> 8;
+ blk[7] = (x7 - x1) >> 8;
+}
+
+/* column (vertical) IDCT
+ *
+ * 7 pi 1 dst[8*k] = sum c[l] * src[8*l] *
+ * cos( -- * ( k + - ) * l ) l=0 8 2
+ *
+ * where: c[0] = 1/1024 c[1..7] = (1/1024)*sqrt(2) */
+static void idctcol (int *blk)
+{
+ int x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+ /* shortcut */
+ if (!((x1 = (blk[8 * 4] << 8)) | (x2 = blk[8 * 6]) | (x3 = blk[8 * 2]) |
+ (x4 = blk[8 * 1]) | (x5 = blk[8 * 7]) | (x6 = blk[8 * 5]) |
+ (x7 = blk[8 * 3])))
+ {
+ blk[8 * 0] = blk[8 * 1] = blk[8 * 2] = blk[8 * 3]
+ = blk[8 * 4] = blk[8 * 5] = blk[8 * 6]
+ = blk[8 * 7] = ((blk[8 * 0] + 32) >>6);
+ return;
+ }
+
+ x0 = (blk[8 * 0] << 8) + 16384;
+
+ /* first stage */
+ x8 = W7 * (x4 + x5) + 4;
+ x4 = (x8 + (W1 - W7) * x4) >> 3;
+ x5 = (x8 - (W1 + W7) * x5) >> 3;
+ x8 = W3 * (x6 + x7) + 4;
+ x6 = (x8 - (W3 - W5) * x6) >> 3;
+ x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6 * (x3 + x2) + 4;
+ x2 = (x1 - (W2 + W6) * x2) >> 3;
+ x3 = (x1 + (W2 - W6) * x3) >> 3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x4 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ blk[8 * 0] = (x7 + x1 ) >> 14;
+ blk[8 * 1] = (x3 + x2 ) >> 14;
+ blk[8 * 2] = (x0 + x4 ) >> 14;
+ blk[8 * 3] = (x8 + x6 ) >> 14;
+ blk[8 * 4] = (x8 - x6 ) >> 14;
+ blk[8 * 5] = (x0 - x4 ) >> 14;
+ blk[8 * 6] = (x3 - x2 ) >> 14;
+ blk[8 * 7] = (x7 - x1 ) >> 14;
+}
+
+#define TX_DIM 8
+void vp8_short_idct8x8_c(short *coefs, short *block, int pitch)
+{
+ int X[TX_DIM*TX_DIM];
+ int i,j;
+ int shortpitch = pitch >> 1;
+
+ for (i = 0; i < TX_DIM; i++)
+ {
+ for (j = 0; j < TX_DIM; j++)
+ {
+ X[i * TX_DIM + j] = (int)(coefs[i * TX_DIM + j]+1
+ + (coefs[i * TX_DIM + j]<0))>>2;
+ }
+ }
+ for (i = 0; i < 8; i++)
+ idctrow (X + 8 * i);
+
+ for (i = 0; i < 8; i++)
+ idctcol (X + i);
+
+ for (i = 0; i < TX_DIM; i++)
+ {
+ for (j = 0; j < TX_DIM; j++)
+ {
+ block[i*shortpitch+j] = X[i * TX_DIM + j]>>1;
+ }
+ }
+}
+
+
+void vp8_short_ihaar2x2_c(short *input, short *output, int pitch)
+{
+ int i, x;
+ short *ip = input; //0,1, 4, 8
+ short *op = output;
+ for (i = 0; i < 16; i++)
+ {
+ op[i] = 0;
+ }
+
+ op[0] = (ip[0] + ip[1] + ip[4] + ip[8] + 1)>>1;
+ op[1] = (ip[0] - ip[1] + ip[4] - ip[8])>>1;
+ op[4] = (ip[0] + ip[1] - ip[4] - ip[8])>>1;
+ op[8] = (ip[0] - ip[1] - ip[4] + ip[8])>>1;
+}
+
diff --git a/vp8/common/implicit_segmentation.c b/vp8/common/implicit_segmentation.c
new file mode 100644
index 000000000..3f72f8455
--- /dev/null
+++ b/vp8/common/implicit_segmentation.c
@@ -0,0 +1,277 @@
+/*
+ * 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 "vp8/common/onyxc_int.h"
+
+#define MAX_REGIONS 24000
+#define NULL 0
+
+#define min_mbs_in_region 3
+
+// this linked list structure holds equivalences for connected
+// component labeling
+struct list_el {
+ int label;
+ int seg_value;
+ int count;
+ struct list_el * next;
+};
+typedef struct list_el item;
+
+// connected colorsegments
+typedef struct
+{
+ int min_x;
+ int min_y;
+ int max_x;
+ int max_y;
+ long long sum_x;
+ long long sum_y;
+ int pixels;
+ int seg_value;
+ int label;
+} segment_info;
+
+
+typedef enum
+{
+ SEGMENT_MODE,
+ SEGMENT_MV,
+ SEGMENT_REFFRAME,
+ SEGMENT_SKIPPED
+} SEGMENT_TYPE;
+
+
+// this merges the two equivalence lists and
+// then makes sure that every label points to the same
+// equivalence list
+void merge ( item *labels, int u, int v )
+{
+ item *a = labels[u].next;
+ item *b = labels[v].next;
+ item c;
+ item *it = &c;
+ int count;
+
+ // check if they are already merged
+ if(u==v || a==b)
+ return;
+
+ count = a->count + b->count;
+
+ // merge 2 sorted linked lists.
+ while ( a != NULL && b != NULL )
+ {
+ if ( a->label < b->label)
+ {
+ it->next = a;
+ a = a->next;
+ }
+ else
+ {
+ it->next = b;
+ b = b->next;
+ }
+
+ it = it->next;
+ }
+
+ if ( a == NULL )
+ it->next = b;
+ else
+ it->next = a;
+
+ it = c.next;
+
+ // make sure every equivalence in the linked list points to this new ll
+ while( it != NULL)
+ {
+ labels[it->label].next = c.next;
+ it=it->next;
+ }
+ c.next->count = count;
+
+}
+
+void segment_via_mode_info( VP8_COMMON *oci, int how)
+{
+ MODE_INFO *mi = oci->mi;
+ int i,j;
+ int mb_index = 0;
+
+ int label=1;
+ int pitch = oci->mb_cols;
+
+ // holds linked list equivalences
+ // the max should probably be allocated at a higher level in oci
+ item equivalences[MAX_REGIONS];
+ int eq_ptr = 0;
+ item labels[MAX_REGIONS];
+ segment_info segments[MAX_REGIONS];
+ int label_count = 1;
+ int labeling[400*300];
+ int *lp = labeling;
+
+ label_count = 1;
+ memset(labels,0,sizeof(labels));
+ memset(segments,0,sizeof(segments));
+
+ /* Go through each macroblock first pass labelling */
+ for (i = 0; i < oci->mb_rows; i++,lp+=pitch)
+ {
+ for (j = 0; j < oci->mb_cols; j++)
+ {
+ // int above seg_value, left seg_value, this seg_value...
+ int a=-1,l=-1,n=-1;
+
+ // above label, left label
+ int al=-1,ll=-1;
+ if(i)
+ {
+ al=lp[j-pitch];
+ a = labels[al].next->seg_value;
+ }
+ if(j)
+ {
+ ll=lp[j-1];
+ l = labels[ll].next->seg_value;
+ }
+
+ // what setting are we going to do the implicit segmentation on
+ switch (how)
+ {
+ case SEGMENT_MODE:
+ n= mi[mb_index].mbmi.mode;
+ break;
+ case SEGMENT_MV:
+ n = mi[mb_index].mbmi.mv.as_int;
+ if(mi[mb_index].mbmi.ref_frame == INTRA_FRAME)
+ n=-9999999;
+ break;
+ case SEGMENT_REFFRAME:
+ n = mi[mb_index].mbmi.ref_frame;
+ break;
+ case SEGMENT_SKIPPED:
+ n = mi[mb_index].mbmi.mb_skip_coeff;
+ break;
+ }
+
+ // above and left both have the same seg_value
+ if(n==a&&n==l)
+ {
+ // pick the lowest label
+ lp[j] = (al<ll?al:ll);
+ labels[lp[j]].next->count++;
+
+ // merge the above and left equivalencies
+ merge( labels, al, ll );
+ }
+ // this matches above seg_value
+ else if(n==a)
+ {
+ // give it the same label as above
+ lp[j]=al;
+ labels[al].next->count++;
+ }
+ // this matches left seg_value
+ else if(n==l)
+ {
+ // give it the same label as above
+ lp[j]=ll;
+ labels[ll].next->count++;
+ }
+ else
+ {
+ // new label doesn't match either
+ item *e = &labels[label];
+ item *nl = &equivalences[eq_ptr++];
+ lp[j]=label;
+ nl->label = label;
+ nl->next = 0;
+ nl->seg_value = n;
+ nl->count = 1;
+ e->next = nl;
+ label++;
+ }
+ mb_index++;
+ }
+ mb_index++;
+ }
+ lp = labeling;
+
+ // give new labels to regions
+ for(i=1;i<label;i++)
+ if(labels[i].next->count >min_mbs_in_region && labels[labels[i].next->label].label == 0 )
+ {
+ segment_info *cs= &segments[label_count];
+ cs->label = label_count;
+ labels[labels[i].next->label].label = label_count++;
+ labels[labels[i].next->label].seg_value = labels[i].next->seg_value;
+ cs->seg_value = labels[labels[i].next->label].seg_value;
+ cs->min_x = oci->mb_cols;
+ cs->min_y = oci->mb_rows;
+ cs->max_x = 0;
+ cs->max_y = 0;
+ cs->sum_x = 0;
+ cs->sum_y = 0;
+ cs->pixels= 0;
+
+ }
+ lp = labeling;
+
+ // this is just to gather stats...
+ for(i=0;i<oci->mb_rows;i++,lp+=pitch)
+ {
+ for(j=0;j<oci->mb_cols;j++)
+ {
+ segment_info *cs;
+ int oldlab = labels[lp[j]].next->label;
+ int lab = labels[oldlab].label;
+ lp[j] = lab;
+
+ cs= &segments[lab];
+
+ cs->min_x = (j<cs->min_x?j:cs->min_x);
+ cs->max_x = (j>cs->max_x?j:cs->max_x);
+ cs->min_y = (i<cs->min_y?i:cs->min_y);
+ cs->max_y = (i>cs->max_y?i:cs->max_y);
+ cs->sum_x += j;
+ cs->sum_y += i;
+ cs->pixels ++;
+
+ lp[j] = lab;
+ mb_index++;
+ }
+ mb_index++;
+ }
+
+ {
+ lp = labeling;
+ printf("labelling \n");
+ mb_index = 0;
+ for(i=0;i<oci->mb_rows;i++,lp+=pitch)
+ {
+ for(j=0;j<oci->mb_cols;j++)
+ {
+ printf("%4d",lp[j]);
+ }
+ printf(" ");
+ for(j=0;j<oci->mb_cols;j++,mb_index++)
+ {
+ //printf("%3d",mi[mb_index].mbmi.mode );
+ printf("%4d:%4d",mi[mb_index].mbmi.mv.as_mv.row,mi[mb_index].mbmi.mv.as_mv.col );
+ }
+ printf("\n");
+ ++mb_index;
+ }
+ printf("\n");
+ }
+}
+
diff --git a/vp8/common/invtrans.c b/vp8/common/invtrans.c
index 81a3f2d89..eed8363a3 100644
--- a/vp8/common/invtrans.c
+++ b/vp8/common/invtrans.c
@@ -24,13 +24,23 @@ static void recon_dcblock(MACROBLOCKD *x)
}
}
+static void recon_dcblock_8x8(MACROBLOCKD *x)
+{
+ BLOCKD *b = &x->block[24]; //for coeff 0, 2, 8, 10
+ x->block[0].dqcoeff[0] = b->diff[0];
+ x->block[4].dqcoeff[0] = b->diff[1];
+ x->block[8].dqcoeff[0] = b->diff[4];
+ x->block[12].dqcoeff[0] = b->diff[8];
+
+}
+
void vp8_inverse_transform_b(const vp8_idct_rtcd_vtable_t *rtcd, BLOCKD *b, int pitch)
{
- if (b->eob > 1)
- IDCT_INVOKE(rtcd, idct16)(b->dqcoeff, b->diff, pitch);
- else
+ if (b->eob <= 1)
IDCT_INVOKE(rtcd, idct1)(b->dqcoeff, b->diff, pitch);
+ else
+ IDCT_INVOKE(rtcd, idct16)(b->dqcoeff, b->diff, pitch);
}
@@ -66,6 +76,7 @@ void vp8_inverse_transform_mb(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x
int i;
if (x->mode_info_context->mbmi.mode != B_PRED &&
+ x->mode_info_context->mbmi.mode != I8X8_PRED &&
x->mode_info_context->mbmi.mode != SPLITMV)
{
/* do 2nd order transform on the dc block */
@@ -86,3 +97,77 @@ void vp8_inverse_transform_mb(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x
}
}
+
+
+void vp8_inverse_transform_b_8x8(const vp8_idct_rtcd_vtable_t *rtcd, short *input_dqcoeff, short *output_coeff, int pitch)//pay attention to use when 8x8
+{
+ // int b,i;
+ //if (b->eob > 1)
+ IDCT_INVOKE(rtcd, idct8)(input_dqcoeff, output_coeff, pitch);
+ //else
+ //IDCT_INVOKE(rtcd, idct8_1)(b->dqcoeff, b->diff, pitch);//pitch
+
+}
+
+
+void vp8_inverse_transform_mby_8x8(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+ int i;
+
+ // do 2nd order transform on the dc block
+ IDCT_INVOKE(rtcd, ihaar2)(x->block[24].dqcoeff, x->block[24].diff, 8);
+
+ recon_dcblock_8x8(x); //need to change for 8x8
+ for (i = 0; i < 9; i += 8)
+ {
+ vp8_inverse_transform_b_8x8(rtcd, &x->block[i].dqcoeff[0], &x->block[i].diff[0], 32);
+ }
+ for (i = 2; i < 11; i += 8)
+ {
+ vp8_inverse_transform_b_8x8(rtcd, &x->block[i+2].dqcoeff[0], &x->block[i].diff[0], 32);
+ }
+
+}
+void vp8_inverse_transform_mbuv_8x8(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+ int i;
+
+ for (i = 16; i < 24; i += 4)
+ {
+ vp8_inverse_transform_b_8x8(rtcd, &x->block[i].dqcoeff[0], &x->block[i].diff[0], 16);
+ }
+
+}
+
+
+void vp8_inverse_transform_mb_8x8(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+ int i;
+
+ if (x->mode_info_context->mbmi.mode != B_PRED &&
+ x->mode_info_context->mbmi.mode != SPLITMV)
+ {
+ // do 2nd order transform on the dc block
+
+ IDCT_INVOKE(rtcd, ihaar2)(&x->block[24].dqcoeff[0], x->block[24].diff, 8);//dqcoeff[0]
+ recon_dcblock_8x8(x); //need to change for 8x8
+
+ }
+
+ for (i = 0; i < 9; i += 8)
+ {
+ vp8_inverse_transform_b_8x8(rtcd, &x->block[i].dqcoeff[0], &x->block[i].diff[0], 32);
+ }
+ for (i = 2; i < 11; i += 8)
+ {
+ vp8_inverse_transform_b_8x8(rtcd, &x->block[i+2].dqcoeff[0], &x->block[i].diff[0], 32);
+ }
+
+
+ for (i = 16; i < 24; i += 4)
+ {
+ vp8_inverse_transform_b_8x8(rtcd, &x->block[i].dqcoeff[0], &x->block[i].diff[0], 16);
+ }
+
+}
+
diff --git a/vp8/common/invtrans.h b/vp8/common/invtrans.h
index d14573b91..4c4f0d3d2 100644
--- a/vp8/common/invtrans.h
+++ b/vp8/common/invtrans.h
@@ -12,7 +12,7 @@
#ifndef __INC_INVTRANS_H
#define __INC_INVTRANS_H
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "idct.h"
#include "blockd.h"
extern void vp8_inverse_transform_b(const vp8_idct_rtcd_vtable_t *rtcd, BLOCKD *b, int pitch);
@@ -20,4 +20,9 @@ extern void vp8_inverse_transform_mb(const vp8_idct_rtcd_vtable_t *rtcd, MACROBL
extern void vp8_inverse_transform_mby(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
extern void vp8_inverse_transform_mbuv(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+extern void vp8_inverse_transform_b_8x8(const vp8_idct_rtcd_vtable_t *rtcd, short *input_dqcoeff, short *output_coeff, int pitch);
+extern void vp8_inverse_transform_mb_8x8(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+extern void vp8_inverse_transform_mby_8x8(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+extern void vp8_inverse_transform_mbuv_8x8(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+
#endif
diff --git a/vp8/common/loopfilter.c b/vp8/common/loopfilter.c
index fe0644bdd..1cac063e0 100644
--- a/vp8/common/loopfilter.c
+++ b/vp8/common/loopfilter.c
@@ -14,10 +14,14 @@
#include "onyxc_int.h"
#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/seg_common.h"
+
typedef unsigned char uc;
prototype_loopfilter(vp8_loop_filter_horizontal_edge_c);
prototype_loopfilter(vp8_loop_filter_vertical_edge_c);
+
+
prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_c);
prototype_loopfilter(vp8_mbloop_filter_vertical_edge_c);
@@ -68,6 +72,14 @@ void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr,
vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
}
+void vp8_loop_filter_bh8x8_c(unsigned char *y_ptr, unsigned char *u_ptr,
+ unsigned char *v_ptr, int y_stride, int uv_stride,
+ loop_filter_info *lfi)
+{
+ vp8_mbloop_filter_horizontal_edge_c(
+ y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+}
+
void vp8_loop_filter_bhs_c(unsigned char *y_ptr, int y_stride,
const unsigned char *blimit)
{
@@ -92,6 +104,14 @@ void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr,
vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
}
+void vp8_loop_filter_bv8x8_c(unsigned char *y_ptr, unsigned char *u_ptr,
+ unsigned char *v_ptr, int y_stride, int uv_stride,
+ loop_filter_info *lfi)
+{
+ vp8_mbloop_filter_vertical_edge_c(
+ y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+}
+
void vp8_loop_filter_bvs_c(unsigned char *y_ptr, int y_stride,
const unsigned char *blimit)
{
@@ -133,7 +153,7 @@ static void lf_init_lut(loop_filter_info_n *lfi)
lfi->mode_lf_lut[H_PRED] = 1;
lfi->mode_lf_lut[TM_PRED] = 1;
lfi->mode_lf_lut[B_PRED] = 0;
-
+ lfi->mode_lf_lut[I8X8_PRED]=0;
lfi->mode_lf_lut[ZEROMV] = 1;
lfi->mode_lf_lut[NEARESTMV] = 2;
lfi->mode_lf_lut[NEARMV] = 2;
@@ -194,7 +214,7 @@ void vp8_loop_filter_init(VP8_COMMON *cm)
}
void vp8_loop_filter_frame_init(VP8_COMMON *cm,
- MACROBLOCKD *mbd,
+ MACROBLOCKD *xd,
int default_filt_lvl)
{
int seg, /* segment number */
@@ -215,22 +235,23 @@ void vp8_loop_filter_frame_init(VP8_COMMON *cm,
int lvl_seg = default_filt_lvl;
int lvl_ref, lvl_mode;
- /* Note the baseline filter values for each segment */
- if (mbd->segmentation_enabled)
+
+ // Set the baseline filter values for each segment
+ if ( segfeature_active( xd, seg, SEG_LVL_ALT_LF ) )
{
/* Abs value */
- if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+ if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA)
{
- lvl_seg = mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
+ lvl_seg = get_segdata( xd, seg, SEG_LVL_ALT_LF );
}
else /* Delta Value */
{
- lvl_seg += mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
+ lvl_seg += get_segdata( xd, seg, SEG_LVL_ALT_LF );;
lvl_seg = (lvl_seg > 0) ? ((lvl_seg > 63) ? 63: lvl_seg) : 0;
}
}
- if (!mbd->mode_ref_lf_delta_enabled)
+ if (!xd->mode_ref_lf_delta_enabled)
{
/* we could get rid of this if we assume that deltas are set to
* zero when not in use; encoder always uses deltas
@@ -245,12 +266,12 @@ void vp8_loop_filter_frame_init(VP8_COMMON *cm,
ref = INTRA_FRAME;
/* Apply delta for reference frame */
- lvl_ref += mbd->ref_lf_deltas[ref];
+ lvl_ref += xd->ref_lf_deltas[ref];
/* Apply delta for Intra modes */
mode = 0; /* B_PRED */
/* Only the split mode BPRED has a further special case */
- lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
+ lvl_mode = lvl_ref + xd->mode_lf_deltas[mode];
lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; /* clamp */
lfi->lvl[seg][ref][mode] = lvl_mode;
@@ -265,12 +286,12 @@ void vp8_loop_filter_frame_init(VP8_COMMON *cm,
int lvl_ref = lvl_seg;
/* Apply delta for reference frame */
- lvl_ref += mbd->ref_lf_deltas[ref];
+ lvl_ref += xd->ref_lf_deltas[ref];
/* Apply delta for Inter modes */
for (mode = 1; mode < 4; mode++)
{
- lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
+ lvl_mode = lvl_ref + xd->mode_lf_deltas[mode];
lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; /* clamp */
lfi->lvl[seg][ref][mode] = lvl_mode;
@@ -282,7 +303,7 @@ void vp8_loop_filter_frame_init(VP8_COMMON *cm,
void vp8_loop_filter_frame
(
VP8_COMMON *cm,
- MACROBLOCKD *mbd
+ MACROBLOCKD *xd
)
{
YV12_BUFFER_CONFIG *post = cm->frame_to_show;
@@ -302,7 +323,7 @@ void vp8_loop_filter_frame
const MODE_INFO *mode_info_context = cm->mi;
/* Initialize the loop filter for this frame. */
- vp8_loop_filter_frame_init(cm, mbd, cm->filter_level);
+ vp8_loop_filter_frame_init(cm, xd, cm->filter_level);
/* Set up the buffer pointers */
y_ptr = post->y_buffer;
@@ -315,13 +336,14 @@ void vp8_loop_filter_frame
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
{
int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+ mode_info_context->mbmi.mode != I8X8_PRED &&
mode_info_context->mbmi.mode != SPLITMV &&
mode_info_context->mbmi.mb_skip_coeff);
const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
const int seg = mode_info_context->mbmi.segment_id;
const int ref_frame = mode_info_context->mbmi.ref_frame;
-
+ int tx_type = mode_info_context->mbmi.txfm_size;
filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
if (filter_level)
@@ -335,21 +357,34 @@ void vp8_loop_filter_frame
lfi.hev_thr = lfi_n->hev_thr[hev_index];
if (mb_col > 0)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_v)
+ vp8_loop_filter_mbv_c
(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
if (!skip_lf)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v)
- (y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
+ {
+ if(tx_type == TX_8X8)
+ vp8_loop_filter_bv8x8_c
+ (y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
+ else
+ LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v)
+ (y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
+
+ }
/* don't apply across umv border */
if (mb_row > 0)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_h)
+ vp8_loop_filter_mbh_c
(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
if (!skip_lf)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h)
- (y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
+ {
+ if(tx_type == TX_8X8)
+ vp8_loop_filter_bh8x8_c
+ (y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
+ else
+ LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h)
+ (y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi);
+ }
}
else
{
@@ -390,7 +425,7 @@ void vp8_loop_filter_frame
void vp8_loop_filter_frame_yonly
(
VP8_COMMON *cm,
- MACROBLOCKD *mbd,
+ MACROBLOCKD *xd,
int default_filt_lvl
)
{
@@ -415,7 +450,7 @@ void vp8_loop_filter_frame_yonly
#endif
/* Initialize the loop filter for this frame. */
- vp8_loop_filter_frame_init( cm, mbd, default_filt_lvl);
+ vp8_loop_filter_frame_init( cm, xd, default_filt_lvl);
/* Set up the buffer pointers */
y_ptr = post->y_buffer;
@@ -426,12 +461,14 @@ void vp8_loop_filter_frame_yonly
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
{
int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+ mode_info_context->mbmi.mode != I8X8_PRED &&
mode_info_context->mbmi.mode != SPLITMV &&
mode_info_context->mbmi.mb_skip_coeff);
const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
const int seg = mode_info_context->mbmi.segment_id;
const int ref_frame = mode_info_context->mbmi.ref_frame;
+ int tx_type = mode_info_context->mbmi.txfm_size;
filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
@@ -446,21 +483,33 @@ void vp8_loop_filter_frame_yonly
lfi.hev_thr = lfi_n->hev_thr[hev_index];
if (mb_col > 0)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_v)
+ vp8_loop_filter_mbv_c
(y_ptr, 0, 0, post->y_stride, 0, &lfi);
if (!skip_lf)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v)
- (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ {
+ if(tx_type == TX_8X8)
+ vp8_loop_filter_bv8x8_c
+ (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ else
+ LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v)
+ (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ }
/* don't apply across umv border */
if (mb_row > 0)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_h)
+ vp8_loop_filter_mbh_c
(y_ptr, 0, 0, post->y_stride, 0, &lfi);
if (!skip_lf)
- LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h)
- (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ {
+ if(tx_type == TX_8X8)
+ vp8_loop_filter_bh8x8_c
+ (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ else
+ LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h)
+ (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ }
}
else
{
@@ -493,11 +542,134 @@ void vp8_loop_filter_frame_yonly
}
}
+#if CONFIG_FEATUREUPDATES
+// TODO: Multiple copies of loop filtering code should be pruned and
+// cut down. This just adds yet another so that I can do an if
+// on segment.
+void vp8_loop_filter_frame_segment(VP8_COMMON *cm, MACROBLOCKD *xd,
+ int default_filt_lvl, int segment)
+{
+ YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+
+ unsigned char *y_ptr;
+ int mb_row;
+ int mb_col;
+
+ loop_filter_info_n *lfi_n = &cm->lf_info;
+ loop_filter_info lfi;
+
+ int filter_level;
+ FRAME_TYPE frame_type = cm->frame_type;
+
+ /* Point at base of Mb MODE_INFO list */
+ const MODE_INFO *mode_info_context = cm->mi;
+
+#if 0
+ if(default_filt_lvl == 0) /* no filter applied */
+ return;
+#endif
+
+ /* Initialize the loop filter for this frame. */
+ vp8_loop_filter_frame_init(cm, xd, default_filt_lvl);
+
+ /* Set up the buffer pointers */
+ y_ptr = post->y_buffer;
+
+ /* vp8_filter each macro block */
+ for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+ {
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+ {
+ int skip_lf = (mode_info_context->mbmi.mode != B_PRED
+ && mode_info_context->mbmi.mode != I8X8_PRED
+ && mode_info_context->mbmi.mode != SPLITMV
+ && mode_info_context->mbmi.mb_skip_coeff);
+
+ const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi
+ .mode];
+ const int seg = mode_info_context->mbmi.segment_id;
+ const int ref_frame = mode_info_context->mbmi.ref_frame;
+
+ filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
+
+ // check if this mb has filtering applied
+ // and then whether it is the right segment or
+ // if not whether the passed in segment is 0 and this
+ // segment has no alt lf
+
+ // TODO: Make this work for when segment 0 has the alt lv enabled
+ if (filter_level
+ && (seg == segment
+ || (!segfeature_active(xd, seg, SEG_LVL_ALT_LF)
+ && segment == 0)))
+ {
+ if (cm->filter_type == NORMAL_LOOPFILTER)
+ {
+ const int hev_index =
+ lfi_n->hev_thr_lut[frame_type][filter_level];
+ lfi.mblim = lfi_n->mblim[filter_level];
+ lfi.blim = lfi_n->blim[filter_level];
+ lfi.lim = lfi_n->lim[filter_level];
+ lfi.hev_thr = lfi_n->hev_thr[hev_index];
+
+ if (mb_col > 0)
+ vp8_loop_filter_mbv_c(y_ptr, 0, 0, post->y_stride, 0,
+ &lfi);
+
+ if (!skip_lf)
+ LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v)(
+ y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+ /* don't apply across umv border */
+ if (mb_row > 0)
+ vp8_loop_filter_mbh_c(y_ptr, 0, 0, post->y_stride, 0,
+ &lfi);
+
+ if (!skip_lf)
+ LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h)(
+ y_ptr, 0, 0, post->y_stride, 0, &lfi);
+ }
+ else
+ {
+ if (mb_col > 0)
+ LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_v)(
+ y_ptr, post->y_stride,
+ lfi_n->mblim[filter_level]);
+
+ if (!skip_lf)
+ LF_INVOKE(&cm->rtcd.loopfilter, simple_b_v)(
+ y_ptr, post->y_stride,
+ lfi_n->blim[filter_level]);
+
+ /* don't apply across umv border */
+ if (mb_row > 0)
+ LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_h)(
+ y_ptr, post->y_stride,
+ lfi_n->mblim[filter_level]);
+
+ if (!skip_lf)
+ LF_INVOKE(&cm->rtcd.loopfilter, simple_b_h)(
+ y_ptr, post->y_stride,
+ lfi_n->blim[filter_level]);
+ }
+ }
+
+ y_ptr += 16;
+ mode_info_context++; /* step to next MB */
+
+ }
+
+ y_ptr += post->y_stride * 16 - post->y_width;
+ mode_info_context++; /* Skip border mb */
+ }
+
+}
+#endif
void vp8_loop_filter_partial_frame
(
VP8_COMMON *cm,
- MACROBLOCKD *mbd,
+ MACROBLOCKD *xd,
int default_filt_lvl
)
{
@@ -514,7 +686,7 @@ void vp8_loop_filter_partial_frame
loop_filter_info lfi;
int filter_level;
- int alt_flt_enabled = mbd->segmentation_enabled;
+ int alt_flt_enabled = xd->segmentation_enabled;
FRAME_TYPE frame_type = cm->frame_type;
const MODE_INFO *mode_info_context;
@@ -539,15 +711,15 @@ void vp8_loop_filter_partial_frame
{
for (i = 0; i < MAX_MB_SEGMENTS; i++)
{ /* Abs value */
- if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+ if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA)
{
- lvl_seg[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+ lvl_seg[i] = get_segdata( xd, i, SEG_LVL_ALT_LF );
}
/* Delta Value */
else
{
- lvl_seg[i] = default_filt_lvl
- + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+ lvl_seg[i] = default_filt_lvl +
+ get_segdata( xd, i, SEG_LVL_ALT_LF );
lvl_seg[i] = (lvl_seg[i] > 0) ?
((lvl_seg[i] > 63) ? 63: lvl_seg[i]) : 0;
}
@@ -563,6 +735,7 @@ void vp8_loop_filter_partial_frame
for (mb_col = 0; mb_col < mb_cols; mb_col++)
{
int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+ mode_info_context->mbmi.mode != I8X8_PRED &&
mode_info_context->mbmi.mode != SPLITMV &&
mode_info_context->mbmi.mb_skip_coeff);
diff --git a/vp8/common/loopfilter.h b/vp8/common/loopfilter.h
index 9887cf55b..0ae2b9a1b 100644
--- a/vp8/common/loopfilter.h
+++ b/vp8/common/loopfilter.h
@@ -14,6 +14,7 @@
#include "vpx_ports/mem.h"
#include "vpx_config.h"
+#include "blockd.h"
#define MAX_LOOP_FILTER 63
@@ -40,7 +41,7 @@ typedef struct
DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, hev_thr[4][SIMD_WIDTH]);
unsigned char lvl[4][4][4];
unsigned char hev_thr_lut[2][MAX_LOOP_FILTER + 1];
- unsigned char mode_lf_lut[10];
+ unsigned char mode_lf_lut[MB_MODE_COUNT];
} loop_filter_info_n;
typedef struct
diff --git a/vp8/common/loopfilter_filters.c b/vp8/common/loopfilter_filters.c
index 10228ae09..dbfd3c96f 100644
--- a/vp8/common/loopfilter_filters.c
+++ b/vp8/common/loopfilter_filters.c
@@ -10,6 +10,7 @@
#include <stdlib.h>
+#include "vpx_config.h"
#include "loopfilter.h"
#include "onyxc_int.h"
@@ -148,7 +149,8 @@ void vp8_loop_filter_vertical_edge_c
do
{
mask = vp8_filter_mask(limit[0], blimit[0],
- s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
+ s[-4], s[-3], s[-2], s[-1],
+ s[0], s[1], s[2], s[3]);
hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
@@ -158,62 +160,95 @@ void vp8_loop_filter_vertical_edge_c
}
while (++i < count * 8);
}
-
-static __inline void vp8_mbfilter(signed char mask, uc hev,
- uc *op2, uc *op1, uc *op0, uc *oq0, uc *oq1, uc *oq2)
+static __inline signed char vp8_flatmask(uc thresh,
+ uc p4, uc p3, uc p2, uc p1, uc p0,
+ uc q0, uc q1, uc q2, uc q3, uc q4)
{
- signed char s, u;
- signed char vp8_filter, Filter1, Filter2;
- signed char ps2 = (signed char) * op2 ^ 0x80;
- signed char ps1 = (signed char) * op1 ^ 0x80;
- signed char ps0 = (signed char) * op0 ^ 0x80;
- signed char qs0 = (signed char) * oq0 ^ 0x80;
- signed char qs1 = (signed char) * oq1 ^ 0x80;
- signed char qs2 = (signed char) * oq2 ^ 0x80;
-
- /* add outer taps if we have high edge variance */
- vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
- vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
- vp8_filter &= mask;
-
- Filter2 = vp8_filter;
- Filter2 &= hev;
-
- /* save bottom 3 bits so that we round one side +4 and the other +3 */
- Filter1 = vp8_signed_char_clamp(Filter2 + 4);
- Filter2 = vp8_signed_char_clamp(Filter2 + 3);
- Filter1 >>= 3;
- Filter2 >>= 3;
- qs0 = vp8_signed_char_clamp(qs0 - Filter1);
- ps0 = vp8_signed_char_clamp(ps0 + Filter2);
-
-
- /* only apply wider filter if not high edge variance */
- vp8_filter &= ~hev;
- Filter2 = vp8_filter;
-
- /* roughly 3/7th difference across boundary */
- u = vp8_signed_char_clamp((63 + Filter2 * 27) >> 7);
- s = vp8_signed_char_clamp(qs0 - u);
- *oq0 = s ^ 0x80;
- s = vp8_signed_char_clamp(ps0 + u);
- *op0 = s ^ 0x80;
-
- /* roughly 2/7th difference across boundary */
- u = vp8_signed_char_clamp((63 + Filter2 * 18) >> 7);
- s = vp8_signed_char_clamp(qs1 - u);
- *oq1 = s ^ 0x80;
- s = vp8_signed_char_clamp(ps1 + u);
- *op1 = s ^ 0x80;
-
- /* roughly 1/7th difference across boundary */
- u = vp8_signed_char_clamp((63 + Filter2 * 9) >> 7);
- s = vp8_signed_char_clamp(qs2 - u);
- *oq2 = s ^ 0x80;
- s = vp8_signed_char_clamp(ps2 + u);
- *op2 = s ^ 0x80;
+ signed char flat = 0;
+ flat |= (abs(p1 - p0) > 1) * -1;
+ flat |= (abs(q1 - q0) > 1) * -1;
+ flat |= (abs(p0 - p2) > 1) * -1;
+ flat |= (abs(q0 - q2) > 1) * -1;
+ flat |= (abs(p3 - p0) > 1) * -1;
+ flat |= (abs(q3 - q0) > 1) * -1;
+ flat |= (abs(p4 - p0) > 1) * -1;
+ flat |= (abs(q4 - q0) > 1) * -1;
+ flat = ~flat;
+ return flat;
}
+static __inline void vp8_mbfilter(signed char mask, uc hev, uc flat,
+ uc *op4, uc *op3, uc *op2, uc *op1, uc *op0,
+ uc *oq0, uc *oq1, uc *oq2, uc *oq3, uc *oq4)
+{
+ /* use a 7 tap filter [1, 1, 1, 2, 1, 1, 1] for flat line */
+ if(flat && mask)
+ {
+ unsigned char p0, q0;
+ unsigned char p1, q1;
+ unsigned char p2, q2;
+ unsigned char p3, q3;
+ unsigned char p4, q4;
+
+ p4 = *op4;
+ p3 = *op3;
+ p2 = *op2;
+ p1 = *op1;
+ p0 = *op0;
+ q0 = *oq0;
+ q1 = *oq1;
+ q2 = *oq2;
+ q3 = *oq3;
+ q4 = *oq4;
+
+ *op2 = ( p4 + p4 + p3 + p2 + p2 + p1 + p0 + q0 + 4)>>3;
+ *op1 = ( p4 + p3 + p2 + p1 + p1 + p0 + q0 + q1 + 4)>>3;
+ *op0 = ( p3 + p2 + p1 + p0 + p0 + q0 + q1 + q2 + 4)>>3;
+ *oq0 = ( p2 + p1 + p0 + q0 + q0 + q1 + q2 + q3 + 4)>>3;
+ *oq1 = ( p1 + p0 + q0 + q1 + q1 + q2 + q3 + q4 + 4)>>3;
+ *oq2 = ( p0 + q0 + q1 + q2 + q2 + q3 + q4 + q4 + 4)>>3;
+ }
+ else
+ {
+ signed char ps0, qs0;
+ signed char ps1, qs1;
+ signed char vp8_filter, Filter1, Filter2;
+ signed char u;
+
+ ps1 = (signed char) * op1 ^ 0x80;
+ ps0 = (signed char) * op0 ^ 0x80;
+ qs0 = (signed char) * oq0 ^ 0x80;
+ qs1 = (signed char) * oq1 ^ 0x80;
+
+ /* add outer taps if we have high edge variance */
+ vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
+ vp8_filter &= hev;
+
+ /* inner taps */
+ vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
+ vp8_filter &= mask;
+
+ Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
+ Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
+ Filter1 >>= 3;
+ Filter2 >>= 3;
+ u = vp8_signed_char_clamp(qs0 - Filter1);
+ *oq0 = u ^ 0x80;
+ u = vp8_signed_char_clamp(ps0 + Filter2);
+ *op0 = u ^ 0x80;
+ vp8_filter = Filter1;
+
+ /* outer tap adjustments */
+ vp8_filter += 1;
+ vp8_filter >>= 1;
+ vp8_filter &= ~hev;
+
+ u = vp8_signed_char_clamp(qs1 - vp8_filter);
+ *oq1 = u ^ 0x80;
+ u = vp8_signed_char_clamp(ps1 + vp8_filter);
+ *op1 = u ^ 0x80;
+ }
+}
void vp8_mbloop_filter_horizontal_edge_c
(
unsigned char *s,
@@ -226,6 +261,7 @@ void vp8_mbloop_filter_horizontal_edge_c
{
signed char hev = 0; /* high edge variance */
signed char mask = 0;
+ signed char flat = 0;
int i = 0;
/* loop filter designed to work using chars so that we can make maximum use
@@ -236,11 +272,16 @@ void vp8_mbloop_filter_horizontal_edge_c
mask = vp8_filter_mask(limit[0], blimit[0],
s[-4*p], s[-3*p], s[-2*p], s[-1*p],
- s[0*p], s[1*p], s[2*p], s[3*p]);
+ s[ 0*p], s[ 1*p], s[ 2*p], s[ 3*p]);
hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
- vp8_mbfilter(mask, hev, s - 3 * p, s - 2 * p, s - 1 * p, s, s + 1 * p, s + 2 * p);
+ flat = vp8_flatmask(thresh[0],
+ s[-5*p], s[-4*p], s[-3*p], s[-2*p], s[-1*p],
+ s[ 0*p], s[ 1*p], s[ 2*p], s[ 3*p], s[ 4*p]);
+ vp8_mbfilter(mask, hev, flat,
+ s - 5*p, s - 4*p, s- 3*p, s - 2*p, s - 1*p,
+ s, s + 1*p, s+ 2*p, s + 3*p, s + 4*p );
++s;
}
@@ -261,18 +302,23 @@ void vp8_mbloop_filter_vertical_edge_c
{
signed char hev = 0; /* high edge variance */
signed char mask = 0;
+ signed char flat = 0;
int i = 0;
do
{
mask = vp8_filter_mask(limit[0], blimit[0],
- s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
+ s[-4], s[-3], s[-2], s[-1],
+ s[0], s[1], s[2], s[3]);
hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
-
- vp8_mbfilter(mask, hev, s - 3, s - 2, s - 1, s, s + 1, s + 2);
-
+ flat = vp8_flatmask(thresh[0],
+ s[-5],s[-4],s[-3],s[-2],s[-1],
+ s[ 0],s[ 1],s[ 2],s[ 3],s[ 4]);
+ vp8_mbfilter(mask, hev, flat,
+ s - 5, s - 4, s - 3, s - 2, s - 1,
+ s, s + 1, s + 2, s + 3, s + 4);
s += p;
}
while (++i < count * 8);
@@ -280,7 +326,9 @@ void vp8_mbloop_filter_vertical_edge_c
}
/* should we apply any filter at all ( 11111111 yes, 00000000 no) */
-static __inline signed char vp8_simple_filter_mask(uc blimit, uc p1, uc p0, uc q0, uc q1)
+static __inline signed char vp8_simple_filter_mask(uc blimit,
+ uc p1, uc p0,
+ uc q0, uc q1)
{
/* Why does this cause problems for win32?
* error C2143: syntax error : missing ';' before 'type'
@@ -290,7 +338,9 @@ static __inline signed char vp8_simple_filter_mask(uc blimit, uc p1, uc p0, uc q
return mask;
}
-static __inline void vp8_simple_filter(signed char mask, uc *op1, uc *op0, uc *oq0, uc *oq1)
+static __inline void vp8_simple_filter(signed char mask,
+ uc *op1, uc *op0,
+ uc *oq0, uc *oq1)
{
signed char vp8_filter, Filter1, Filter2;
signed char p1 = (signed char) * op1 ^ 0x80;
@@ -327,8 +377,12 @@ void vp8_loop_filter_simple_horizontal_edge_c
do
{
- mask = vp8_simple_filter_mask(blimit[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
- vp8_simple_filter(mask, s - 2 * p, s - 1 * p, s, s + 1 * p);
+ mask = vp8_simple_filter_mask(blimit[0],
+ s[-2*p], s[-1*p],
+ s[0*p], s[1*p]);
+ vp8_simple_filter(mask,
+ s - 2 * p, s - 1 * p,
+ s, s + 1 * p);
++s;
}
while (++i < 16);
diff --git a/vp8/common/maskingmv.c b/vp8/common/maskingmv.c
new file mode 100644
index 000000000..d01a18fc8
--- /dev/null
+++ b/vp8/common/maskingmv.c
@@ -0,0 +1,855 @@
+/*
+ ============================================================================
+ Name : maskingmv.c
+ Author : jimbankoski
+ Version :
+ Copyright : Your copyright notice
+ Description : Hello World in C, Ansi-style
+ ============================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+extern unsigned int vp8_sad16x16_sse3(
+ unsigned char *src_ptr,
+ int src_stride,
+ unsigned char *ref_ptr,
+ int ref_stride,
+ int max_err);
+
+extern void vp8_sad16x16x3_sse3(
+ unsigned char *src_ptr,
+ int src_stride,
+ unsigned char *ref_ptr,
+ int ref_stride,
+ int *results);
+
+extern int vp8_growmaskmb_sse3(
+ unsigned char *om,
+ unsigned char *nm);
+
+extern void vp8_makemask_sse3(
+ unsigned char *y,
+ unsigned char *u,
+ unsigned char *v,
+ unsigned char *ym,
+ int yp,
+ int uvp,
+ int ys,
+ int us,
+ int vs,
+ int yt,
+ int ut,
+ int vt);
+
+unsigned int vp8_sad16x16_unmasked_wmt(
+ unsigned char *src_ptr,
+ int src_stride,
+ unsigned char *ref_ptr,
+ int ref_stride,
+ unsigned char *mask);
+
+unsigned int vp8_sad16x16_masked_wmt(
+ unsigned char *src_ptr,
+ int src_stride,
+ unsigned char *ref_ptr,
+ int ref_stride,
+ unsigned char *mask);
+
+unsigned int vp8_masked_predictor_wmt(
+ unsigned char *masked,
+ unsigned char *unmasked,
+ int src_stride,
+ unsigned char *dst_ptr,
+ int dst_stride,
+ unsigned char *mask);
+unsigned int vp8_masked_predictor_uv_wmt(
+ unsigned char *masked,
+ unsigned char *unmasked,
+ int src_stride,
+ unsigned char *dst_ptr,
+ int dst_stride,
+ unsigned char *mask);
+unsigned int vp8_uv_from_y_mask(
+ unsigned char *ymask,
+ unsigned char *uvmask);
+int yp=16;
+unsigned char sxy[]=
+{
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,80,120,120,90,90,90,90,90,80,120,120,90,90,90,90,90
+};
+
+unsigned char sts[]=
+{
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+};
+unsigned char str[]=
+{
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+unsigned char y[]=
+{
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,
+40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,
+60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,40,
+60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,40,
+60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,40,
+40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,
+40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,40,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,
+40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,40,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40,
+40,40,40,60,60,60,60,40,40,40,40,60,60,60,60,40
+};
+int uvp=8;
+unsigned char u[]=
+{
+90,80,70,70,90,90,90,17,
+90,80,70,70,90,90,90,17,
+84,70,70,90,90,90,17,17,
+84,70,70,90,90,90,17,17,
+80,70,70,90,90,90,17,17,
+90,80,70,70,90,90,90,17,
+90,80,70,70,90,90,90,17,
+90,80,70,70,90,90,90,17
+};
+
+unsigned char v[]=
+{
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80,
+80,80,80,80,80,80,80,80
+};
+
+unsigned char ym[256];
+unsigned char uvm[64];
+typedef struct
+{
+ unsigned char y;
+ unsigned char yt;
+ unsigned char u;
+ unsigned char ut;
+ unsigned char v;
+ unsigned char vt;
+ unsigned char use;
+} COLOR_SEG_ELEMENT;
+
+/*
+COLOR_SEG_ELEMENT segmentation[]=
+{
+ { 60,4,80,17,80,10, 1},
+ { 40,4,15,10,80,10, 1},
+};
+*/
+
+COLOR_SEG_ELEMENT segmentation[]=
+{
+ { 79,44,92,44, 237,60, 1},
+};
+
+unsigned char pixel_mask(unsigned char y,unsigned char u,unsigned char v,
+ COLOR_SEG_ELEMENT sgm[],
+ int c)
+{
+ COLOR_SEG_ELEMENT *s=sgm;
+ unsigned char m =0;
+ int i;
+ for(i=0;i<c;i++,s++)
+ m |= ( abs(y-s->y)< s->yt &&
+ abs(u-s->u)< s->ut &&
+ abs(v-s->v)< s->vt ? 255 : 0 );
+
+ return m;
+}
+int neighbors[256][8];
+int makeneighbors(void)
+{
+ int i,j;
+ for(i=0;i<256;i++)
+ {
+ int r=(i>>4),c=(i&15);
+ int ni=0;
+ for(j=0;j<8;j++)
+ neighbors[i][j]=i;
+ for(j=0;j<256;j++)
+ {
+ int nr=(j>>4),nc=(j&15);
+ if(abs(nr-r)<2&&abs(nc-c)<2)
+ neighbors[i][ni++]=j;
+ }
+ }
+ return 0;
+}
+void grow_ymask(unsigned char *ym)
+{
+ unsigned char nym[256];
+ int i,j;
+
+ for(i=0;i<256;i++)
+ {
+ nym[i]=ym[i];
+ for(j=0;j<8;j++)
+ {
+ nym[i]|=ym[neighbors[i][j]];
+ }
+ }
+ for(i=0;i<256;i++)
+ ym[i]=nym[i];
+}
+void make_mb_mask(unsigned char *y, unsigned char *u, unsigned char *v,
+ unsigned char *ym, unsigned char *uvm,
+ int yp, int uvp,
+ COLOR_SEG_ELEMENT sgm[],
+ int count)
+{
+ int r,c;
+ unsigned char *oym = ym;
+
+ memset(ym,20,256);
+ for(r=0;r<8;r++,uvm+=8,u+=uvp,v+=uvp,y+=(yp+yp),ym+=32)
+ for(c=0;c<8;c++)
+ {
+ int y1=y[c<<1];
+ int u1=u[c];
+ int v1=v[c];
+ int m = pixel_mask(y1,u1,v1,sgm,count);
+ uvm[c] = m;
+ ym[c<<1] = uvm[c];// = pixel_mask(y[c<<1],u[c],v[c],sgm,count);
+ ym[(c<<1)+1] = pixel_mask(y[1+(c<<1)],u[c],v[c],sgm,count);
+ ym[(c<<1)+16] = pixel_mask(y[yp+(c<<1)],u[c],v[c],sgm,count);
+ ym[(c<<1)+17] = pixel_mask(y[1+yp+(c<<1)],u[c],v[c],sgm,count);
+ }
+ grow_ymask(oym);
+}
+
+int masked_sad(unsigned char *src, int p, unsigned char *dst, int dp,
+ unsigned char *ym )
+{
+ int i,j;
+ unsigned sad = 0;
+ for(i=0;i<16;i++,src+=p,dst+=dp,ym+=16)
+ for(j=0;j<16;j++)
+ if(ym[j])
+ sad+= abs(src[j]-dst[j]);
+
+ return sad;
+}
+
+int compare_masks(unsigned char *sym, unsigned char *ym)
+{
+ int i,j;
+ unsigned sad = 0;
+ for(i=0;i<16;i++,sym += 16,ym+=16)
+ for(j=0;j<16;j++)
+ sad+= (sym[j]!=ym[j]?1:0);
+
+ return sad;
+}
+int unmasked_sad(unsigned char *src, int p, unsigned char *dst, int dp,
+ unsigned char *ym)
+{
+ int i,j;
+ unsigned sad = 0;
+ for(i=0;i<16;i++,src+=p,dst+=dp,ym+=16)
+ for(j=0;j<16;j++)
+ if(!ym[j])
+ sad+= abs(src[j]-dst[j]);
+
+ return sad;
+}
+int masked_motion_search( unsigned char *y, unsigned char *u, unsigned char *v,
+ int yp, int uvp,
+ unsigned char *dy, unsigned char *du, unsigned char *dv,
+ int dyp, int duvp,
+ COLOR_SEG_ELEMENT sgm[],
+ int count,
+ int *mi,
+ int *mj,
+ int *ui,
+ int *uj,
+ int *wm)
+{
+ int i,j;
+
+ unsigned char ym[256];
+ unsigned char uvm[64];
+ unsigned char dym[256];
+ unsigned char duvm[64];
+ unsigned int e = 0 ;
+ int beste=256;
+ int bmi=-32,bmj=-32;
+ int bui=-32,buj=-32;
+ int beste1=256;
+ int bmi1=-32,bmj1=-32;
+ int bui1=-32,buj1=-32;
+ int obeste;
+
+ // first try finding best mask and then unmasked
+ beste = 0xffffffff;
+
+ // find best unmasked mv
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ unsigned char *duz = i/2*duvp + du;
+ unsigned char *dvz = i/2*duvp + dv;
+ for(j=-32;j<32;j++)
+ {
+ // 0,0 masked destination
+ make_mb_mask(dyz+j,duz+j/2, dvz+j/2, dym, duvm, dyp, duvp,sgm,count);
+
+ e = unmasked_sad(y, yp, dyz+j, dyp, dym );
+
+ if(e<beste)
+ {
+ bui=i;
+ buj=j;
+ beste=e;
+ }
+ }
+ }
+ //bui=0;buj=0;
+ // best mv masked destination
+ make_mb_mask(dy+bui*dyp+buj,du+bui/2*duvp+buj/2, dv+bui/2*duvp+buj/2,
+ dym, duvm, dyp, duvp,sgm,count);
+
+ obeste = beste;
+ beste = 0xffffffff;
+
+ // find best masked
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ for(j=-32;j<32;j++)
+ {
+ e = masked_sad(y, yp, dyz+j, dyp, dym );
+
+ if(e<beste)
+ {
+ bmi=i;
+ bmj=j;
+ beste=e;
+ }
+ }
+ }
+ beste1=beste+obeste;
+ bmi1=bmi;bmj1=bmj;
+ bui1=bui;buj1=buj;
+
+ beste = 0xffffffff;
+ // source mask
+ make_mb_mask(y,u, v, ym, uvm, yp, uvp,sgm,count);
+
+ // find best mask
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ unsigned char *duz = i/2*duvp + du;
+ unsigned char *dvz = i/2*duvp + dv;
+ for(j=-32;j<32;j++)
+ {
+ // 0,0 masked destination
+ make_mb_mask(dyz+j,duz+j/2, dvz+j/2, dym, duvm, dyp, duvp,sgm,count);
+
+ e = compare_masks(ym, dym);
+
+ if(e<beste)
+ {
+ bmi=i;
+ bmj=j;
+ beste=e;
+ }
+ }
+ }
+
+
+ // best mv masked destination
+ make_mb_mask(dy+bmi*dyp+bmj,du+bmi/2*duvp+bmj/2, dv+bmi/2*duvp+bmj/2,
+ dym, duvm, dyp, duvp,sgm,count);
+
+ obeste = masked_sad(y, yp, dy+bmi*dyp+bmj, dyp, dym );
+
+ beste = 0xffffffff;
+
+ // find best unmasked mv
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ for(j=-32;j<32;j++)
+ {
+ e = unmasked_sad(y, yp, dyz+j, dyp, dym );
+
+ if(e<beste)
+ {
+ bui=i;
+ buj=j;
+ beste=e;
+ }
+ }
+ }
+ beste += obeste;
+
+
+ if(beste<beste1)
+ {
+ *mi = bmi;
+ *mj = bmj;
+ *ui = bui;
+ *uj = buj;
+ *wm = 1;
+ }
+ else
+ {
+ *mi = bmi1;
+ *mj = bmj1;
+ *ui = bui1;
+ *uj = buj1;
+ *wm = 0;
+
+ }
+ return 0;
+}
+
+int predict(unsigned char *src, int p, unsigned char *dst, int dp,
+ unsigned char *ym, unsigned char *prd )
+{
+ int i,j;
+ for(i=0;i<16;i++,src+=p,dst+=dp,ym+=16, prd+=16)
+ for(j=0;j<16;j++)
+ prd[j]=(ym[j] ? src[j]:dst[j]);
+ return 0;
+}
+
+int fast_masked_motion_search( unsigned char *y, unsigned char *u, unsigned char *v,
+ int yp, int uvp,
+ unsigned char *dy, unsigned char *du, unsigned char *dv,
+ int dyp, int duvp,
+ COLOR_SEG_ELEMENT sgm[],
+ int count,
+ int *mi,
+ int *mj,
+ int *ui,
+ int *uj,
+ int *wm)
+{
+ int i,j;
+
+ unsigned char ym[256];
+ unsigned char ym2[256];
+ unsigned char uvm[64];
+ unsigned char dym2[256];
+ unsigned char dym[256];
+ unsigned char duvm[64];
+ unsigned int e = 0 ;
+ int beste=256;
+ int bmi=-32,bmj=-32;
+ int bui=-32,buj=-32;
+ int beste1=256;
+ int bmi1=-32,bmj1=-32;
+ int bui1=-32,buj1=-32;
+ int obeste;
+
+ // first try finding best mask and then unmasked
+ beste = 0xffffffff;
+
+#if 0
+ for(i=0;i<16;i++)
+ {
+ unsigned char *dy = i*yp + y;
+ for(j=0;j<16;j++)
+ printf("%2x",dy[j]);
+ printf("\n");
+ }
+ printf("\n");
+
+ for(i=-32;i<48;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ for(j=-32;j<48;j++)
+ printf("%2x",dyz[j]);
+ printf("\n");
+ }
+#endif
+
+ // find best unmasked mv
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ unsigned char *duz = i/2*duvp + du;
+ unsigned char *dvz = i/2*duvp + dv;
+ for(j=-32;j<32;j++)
+ {
+ // 0,0 masked destination
+ vp8_makemask_sse3(dyz+j,duz+j/2, dvz+j/2, dym, dyp, duvp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+
+ vp8_growmaskmb_sse3(dym,dym2);
+
+ e = vp8_sad16x16_unmasked_wmt(y, yp, dyz+j, dyp, dym2 );
+
+ if(e<beste)
+ {
+ bui=i;
+ buj=j;
+ beste=e;
+ }
+ }
+ }
+ //bui=0;buj=0;
+ // best mv masked destination
+
+ vp8_makemask_sse3(dy+bui*dyp+buj,du+bui/2*duvp+buj/2, dv+bui/2*duvp+buj/2,
+ dym, dyp, duvp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+
+ vp8_growmaskmb_sse3(dym,dym2);
+
+ obeste = beste;
+ beste = 0xffffffff;
+
+ // find best masked
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ for(j=-32;j<32;j++)
+ {
+ e = vp8_sad16x16_masked_wmt(y, yp, dyz+j, dyp, dym2 );
+ if(e<beste)
+ {
+ bmi=i;
+ bmj=j;
+ beste=e;
+ }
+ }
+ }
+ beste1=beste+obeste;
+ bmi1=bmi;bmj1=bmj;
+ bui1=bui;buj1=buj;
+
+ // source mask
+ vp8_makemask_sse3(y,u, v,
+ ym, yp, uvp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+
+ vp8_growmaskmb_sse3(ym,ym2);
+
+ // find best mask
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ unsigned char *duz = i/2*duvp + du;
+ unsigned char *dvz = i/2*duvp + dv;
+ for(j=-32;j<32;j++)
+ {
+ // 0,0 masked destination
+ vp8_makemask_sse3(dyz+j,duz+j/2, dvz+j/2, dym, dyp, duvp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+
+ vp8_growmaskmb_sse3(dym,dym2);
+
+ e = compare_masks(ym2, dym2);
+
+ if(e<beste)
+ {
+ bmi=i;
+ bmj=j;
+ beste=e;
+ }
+ }
+ }
+
+ vp8_makemask_sse3(dy+bmi*dyp+bmj,du+bmi/2*duvp+bmj/2, dv+bmi/2*duvp+bmj/2,
+ dym, dyp, duvp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+
+ vp8_growmaskmb_sse3(dym,dym2);
+
+ obeste = vp8_sad16x16_masked_wmt(y, yp, dy+bmi*dyp+bmj, dyp, dym2 );
+
+ beste = 0xffffffff;
+
+ // find best unmasked mv
+ for(i=-32;i<32;i++)
+ {
+ unsigned char *dyz = i*dyp + dy;
+ for(j=-32;j<32;j++)
+ {
+ e = vp8_sad16x16_unmasked_wmt(y, yp, dyz+j, dyp, dym2 );
+
+ if(e<beste)
+ {
+ bui=i;
+ buj=j;
+ beste=e;
+ }
+ }
+ }
+ beste += obeste;
+
+ if(beste<beste1)
+ {
+ *mi = bmi;
+ *mj = bmj;
+ *ui = bui;
+ *uj = buj;
+ *wm = 1;
+ }
+ else
+ {
+ *mi = bmi1;
+ *mj = bmj1;
+ *ui = bui1;
+ *uj = buj1;
+ *wm = 0;
+ beste=beste1;
+
+ }
+ return beste;
+}
+
+int predict_all(unsigned char *ym, unsigned char *um, unsigned char *vm,
+ int ymp, int uvmp,
+ unsigned char *yp, unsigned char *up, unsigned char *vp,
+ int ypp, int uvpp,
+ COLOR_SEG_ELEMENT sgm[],
+ int count,
+ int mi,
+ int mj,
+ int ui,
+ int uj,
+ int wm)
+{
+ int i,j;
+ unsigned char dym[256];
+ unsigned char dym2[256];
+ unsigned char duvm[64];
+ unsigned char *yu=ym,*uu=um, *vu=vm;
+
+ unsigned char *dym3=dym2;
+
+ ym+=mi*ymp+mj;
+ um+=mi/2*uvmp+mj/2;
+ vm+=mi/2*uvmp+mj/2;
+
+ yu+=ui*ymp+uj;
+ uu+=ui/2*uvmp+uj/2;
+ vu+=ui/2*uvmp+uj/2;
+
+ // best mv masked destination
+ if(wm)
+ vp8_makemask_sse3(ym,um, vm, dym, ymp, uvmp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+ else
+ vp8_makemask_sse3(yu,uu, vu, dym, ymp, uvmp,
+ sgm[0].y,sgm[0].u,sgm[0].v,
+ sgm[0].yt,sgm[0].ut,sgm[0].vt);
+
+ vp8_growmaskmb_sse3(dym,dym2);
+ vp8_masked_predictor_wmt(ym,yu,ymp,yp,ypp,dym3);
+ vp8_uv_from_y_mask(dym3,duvm);
+ vp8_masked_predictor_uv_wmt(um,uu,uvmp,up,uvpp,duvm);
+ vp8_masked_predictor_uv_wmt(vm,vu,uvmp,vp,uvpp,duvm);
+
+ return 0;
+}
+
+unsigned char f0p[1280*720*3/2];
+unsigned char f1p[1280*720*3/2];
+unsigned char prd[1280*720*3/2];
+unsigned char msk[1280*720*3/2];
+
+
+int mainz(int argc, char *argv[]) {
+
+ FILE *f=fopen(argv[1],"rb");
+ FILE *g=fopen(argv[2],"wb");
+ int w=atoi(argv[3]),h=atoi(argv[4]);
+ int y_stride=w,uv_stride=w/2;
+ int r,c;
+ unsigned char *f0=f0p,*f1=f1p,*t;
+ unsigned char ym[256],uvm[64];
+ unsigned char ym2[256],uvm2[64];
+ unsigned char ym3[256],uvm3[64];
+ int a,b;
+
+ COLOR_SEG_ELEMENT last={ 20,20,20,20, 230,20, 1},best;
+#if 0
+ makeneighbors();
+ COLOR_SEG_ELEMENT segmentation[]=
+ {
+ { 60,4,80,17,80,10, 1},
+ { 40,4,15,10,80,10, 1},
+ };
+ make_mb_mask(y, u, v,ym2,uvm2,16,8,segmentation,1);
+
+ vp8_makemask_sse3(y,u,v,ym, (int) 16,(int) 8,
+ (int) segmentation[0].y,(int) segmentation[0].u,(int) segmentation[0].v,
+ segmentation[0].yt,segmentation[0].ut,segmentation[0].vt);
+
+ vp8_growmaskmb_sse3(ym,ym3);
+
+ a = vp8_sad16x16_masked_wmt(str,16,sts,16,ym3);
+ b = vp8_sad16x16_unmasked_wmt(str,16,sts,16,ym3);
+
+ vp8_masked_predictor_wmt(str,sts,16,ym,16,ym3);
+
+ vp8_uv_from_y_mask(ym3,uvm3);
+
+ return 4;
+#endif
+ makeneighbors();
+
+
+ memset(prd,128,w*h*3/2);
+
+ fread(f0,w*h*3/2,1,f);
+
+ while(!feof(f))
+ {
+ unsigned char *ys=f1,*yd=f0,*yp=prd;
+ unsigned char *us=f1+w*h,*ud=f0+w*h,*up=prd+w*h;
+ unsigned char *vs=f1+w*h*5/4,*vd=f0+w*h*5/4,*vp=prd+w*h*5/4;
+ fread(f1,w*h*3/2,1,f);
+
+ ys+=32*y_stride;yd+=32*y_stride;yp+=32*y_stride;
+ us+=16*uv_stride;ud+=16*uv_stride;up+=16*uv_stride;
+ vs+=16*uv_stride;vd+=16*uv_stride;vp+=16*uv_stride;
+ for(r=32;r<h-32;r+=16,
+ ys+=16*w,yd+=16*w,yp+=16*w,
+ us+=8*uv_stride,ud+=8*uv_stride,up+=8*uv_stride,
+ vs+=8*uv_stride,vd+=8*uv_stride,vp+=8*uv_stride)
+ {
+ for(c=32;c<w-32;c+=16)
+ {
+ int mi,mj,ui,uj,wm;
+ int bmi,bmj,bui,buj,bwm;
+ unsigned char ym[256];
+
+ if(vp8_sad16x16_sse3( ys+c,y_stride, yd+c,y_stride,0xffff) == 0)
+ bmi=bmj=bui=buj=bwm=0;
+ else
+ {
+ COLOR_SEG_ELEMENT cs[5];
+ int j;
+ unsigned int beste=0xfffffff;
+ unsigned int bestj=0;
+
+ // try color from last mb segmentation
+ cs[0] = last;
+
+ // try color segs from 4 pixels in mb recon as segmentation
+ cs[1].y = yd[c + y_stride + 1];cs[1].u = ud[c/2 + uv_stride];
+ cs[1].v = vd[c/2 + uv_stride];
+ cs[1].yt = cs[1].ut = cs[1].vt = 20;
+ cs[2].y = yd[c + w + 14];
+ cs[2].u = ud[c/2 + uv_stride+7];
+ cs[2].v = vd[c/2 + uv_stride+7];
+ cs[2].yt = cs[2].ut = cs[2].vt = 20;
+ cs[3].y = yd[c + w*14 + 1];
+ cs[3].u = ud[c/2 + uv_stride*7];
+ cs[3].v = vd[c/2 + uv_stride*7];
+ cs[3].yt = cs[3].ut = cs[3].vt = 20;
+ cs[4].y = yd[c + w*14 + 14];
+ cs[4].u = ud[c/2 + uv_stride*7+7];
+ cs[4].v = vd[c/2 + uv_stride*7+7];
+ cs[4].yt = cs[4].ut = cs[4].vt = 20;
+
+ for(j=0;j<5;j++)
+ {
+ int e;
+
+ e = fast_masked_motion_search(
+ ys+c, us+c/2, vs+c/2, y_stride, uv_stride,
+ yd+c, ud+c/2, vd+c/2, y_stride, uv_stride,
+ &cs[j], 1, &mi,&mj,&ui,&uj,&wm);
+
+ if(e<beste)
+ {
+ bmi=mi;bmj=mj;bui=ui;buj=uj,bwm=wm;
+ bestj=j;
+ beste=e;
+ }
+ }
+ best = cs[bestj];
+ //best = segmentation[0];
+ last = best;
+ }
+ predict_all(yd+c, ud+c/2, vd+c/2, w, uv_stride,
+ yp+c, up+c/2, vp+c/2, w, uv_stride,
+ &best, 1, bmi,bmj,bui,buj,bwm);
+
+ }
+ }
+ fwrite(prd,w*h*3/2,1,g);
+ t=f0;
+ f0=f1;
+ f1=t;
+
+ }
+ fclose(f);
+ fclose(g);
+ return;
+}
diff --git a/vp8/common/modecont.c b/vp8/common/modecont.c
index 86a74bc0f..d80e16ee5 100644
--- a/vp8/common/modecont.c
+++ b/vp8/common/modecont.c
@@ -10,31 +10,33 @@
#include "entropy.h"
-
-const int vp8_mode_contexts[6][4] =
+const int default_vp8_mode_contexts[6][4] =
+{
+ { /* 0 */
+ 7, 1, 1, 183},
+ { /* 1 */
+ 14, 18, 14, 147},
+ {/* 2 */
+ 135, 64, 57, 68},
+ { /* 3 */
+ 60, 56, 128, 65},
+ {/* 4 */
+ 159, 134, 128, 34},
+ { /* 5 */
+ 234, 188, 128, 28},
+};
+const int default_vp8_mode_contexts_a[6][4] =
{
- {
- /* 0 */
- 7, 1, 1, 143,
- },
- {
- /* 1 */
- 14, 18, 14, 107,
- },
- {
- /* 2 */
- 135, 64, 57, 68,
- },
- {
- /* 3 */
- 60, 56, 128, 65,
- },
- {
- /* 4 */
- 159, 134, 128, 34,
- },
- {
- /* 5 */
- 234, 188, 128, 28,
- },
+ { /* 0 */
+ 4, 1, 1, 143},
+ { /* 1 */
+ 7, 9, 7, 107},
+ {/* 2 */
+ 95, 34, 57, 68},
+ { /* 3 */
+ 95, 56, 128, 65},
+ {/* 4 */
+ 159, 67, 128, 34},
+ { /* 5 */
+ 234, 94, 128, 28},
};
diff --git a/vp8/common/modecont.h b/vp8/common/modecont.h
index 24db88295..f219d7594 100644
--- a/vp8/common/modecont.h
+++ b/vp8/common/modecont.h
@@ -12,6 +12,6 @@
#ifndef __INC_MODECONT_H
#define __INC_MODECONT_H
-extern const int vp8_mode_contexts[6][4];
-
+extern const int default_vp8_mode_contexts[6][4];
+extern const int default_vp8_mode_contexts_a[6][4];
#endif
diff --git a/vp8/common/onyx.h b/vp8/common/onyx.h
index 015b4c4d4..574c8bfb5 100644
--- a/vp8/common/onyx.h
+++ b/vp8/common/onyx.h
@@ -53,7 +53,6 @@ extern "C"
typedef enum
{
- MODE_REALTIME = 0x0,
MODE_GOODQUALITY = 0x1,
MODE_BESTQUALITY = 0x2,
MODE_FIRSTPASS = 0x3,
@@ -155,15 +154,6 @@ extern "C"
int best_allowed_q;
int cq_level;
- // allow internal resizing ( currently disabled in the build !!!!!)
- int allow_spatial_resampling;
- int resample_down_water_mark;
- int resample_up_water_mark;
-
- // allow internal frame rate alterations
- int allow_df;
- int drop_frames_water_mark;
-
// two pass datarate control
int two_pass_vbrbias; // two pass datarate control tweaks
int two_pass_vbrmin_section;
@@ -175,21 +165,9 @@ extern "C"
// these parameters aren't to be used in final build don't use!!!
int play_alternate;
int alt_freq;
- int alt_q;
- int key_q;
- int gold_q;
-
- int multi_threaded; // how many threads to run the encoder on
- int token_partitions; // how many token partitions to create for multi core decoding
int encode_breakout; // early breakout encode threshold : for video conf recommend 800
- unsigned int error_resilient_mode; // Bitfield defining the error
- // resiliency features to enable. Can provide
- // decodable frames after losses in previous
- // frames and decodable partitions after
- // losses in the same frame.
-
int arnr_max_frames;
int arnr_strength ;
int arnr_type ;
diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
index 11a830ff6..535eabb42 100644
--- a/vp8/common/onyxc_int.h
+++ b/vp8/common/onyxc_int.h
@@ -32,34 +32,38 @@
void vp8_initialize_common(void);
#define MINQ 0
-#define MAXQ 127
+
+#define MAXQ 255
+#define QINDEX_BITS 8
+
#define QINDEX_RANGE (MAXQ + 1)
#define NUM_YV12_BUFFERS 4
-#define MAX_PARTITIONS 9
+#define COMP_PRED_CONTEXTS 2
typedef struct frame_contexts
{
vp8_prob bmode_prob [VP8_BINTRAMODES-1];
vp8_prob ymode_prob [VP8_YMODES-1]; /* interframe intra mode probs */
+#if CONFIG_UVINTRA
+ vp8_prob uv_mode_prob [VP8_YMODES][VP8_UV_MODES-1];
+#else
vp8_prob uv_mode_prob [VP8_UV_MODES-1];
+#endif
vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1];
vp8_prob coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+ vp8_prob coef_probs_8x8 [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
MV_CONTEXT mvc[2];
MV_CONTEXT pre_mvc[2]; /* not to caculate the mvcost for the frame if mvc doesn't change. */
+#if CONFIG_HIGH_PRECISION_MV
+ MV_CONTEXT_HP mvc_hp[2];
+ MV_CONTEXT_HP pre_mvc_hp[2]; /* not to caculate the mvcost for the frame if mvc doesn't change. */
+#endif
} FRAME_CONTEXT;
typedef enum
{
- ONE_PARTITION = 0,
- TWO_PARTITION = 1,
- FOUR_PARTITION = 2,
- EIGHT_PARTITION = 3
-} TOKEN_PARTITION;
-
-typedef enum
-{
RECON_CLAMP_REQUIRED = 0,
RECON_CLAMP_NOTREQUIRED = 1
} CLAMP_TYPE;
@@ -70,6 +74,21 @@ typedef enum
BILINEAR = 1
} INTERPOLATIONFILTERTYPE;
+typedef enum
+{
+ SINGLE_PREDICTION_ONLY = 0,
+ COMP_PREDICTION_ONLY = 1,
+ HYBRID_PREDICTION = 2,
+ NB_PREDICTION_TYPES = 3,
+} COMPPREDMODE_TYPE;
+
+/* TODO: allows larger transform */
+typedef enum
+{
+ ONLY_4X4 = 0,
+ ALLOW_8X8 = 1
+} TXFM_MODE;
+
typedef struct VP8_COMMON_RTCD
{
#if CONFIG_RUNTIME_CPU_DETECT
@@ -127,6 +146,8 @@ typedef struct VP8Common
/* profile settings */
int experimental;
int mb_no_coeff_skip;
+ TXFM_MODE txfm_mode;
+ COMPPREDMODE_TYPE comp_pred_mode;
int no_lpf;
int use_bilinear_mc_filter;
int full_pixel;
@@ -152,6 +173,9 @@ typedef struct VP8Common
MODE_INFO *prev_mi; /* 'mi' from last frame (points into prev_mip) */
+ // Persistent mb segment id map used in prediction.
+ unsigned char * last_frame_seg_map;
+
INTERPOLATIONFILTERTYPE mcomp_filter_type;
LOOPFILTERTYPE filter_type;
@@ -176,24 +200,53 @@ typedef struct VP8Common
ENTROPY_CONTEXT_PLANES *above_context; /* row of context for each plane */
ENTROPY_CONTEXT_PLANES left_context; /* (up to) 4 contexts "" */
-
/* keyframe block modes are predicted by their above, left neighbors */
vp8_prob kf_bmode_prob [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1];
+#if CONFIG_QIMODE
+ vp8_prob kf_ymode_prob[8][VP8_YMODES-1]; /* keyframe "" */
+ int kf_ymode_probs_index;
+ int kf_ymode_probs_update;
+#else
vp8_prob kf_ymode_prob [VP8_YMODES-1]; /* keyframe "" */
+#endif
+#if CONFIG_UVINTRA
+ vp8_prob kf_uv_mode_prob[VP8_YMODES] [VP8_UV_MODES-1];
+#else
vp8_prob kf_uv_mode_prob [VP8_UV_MODES-1];
+#endif
+
+ vp8_prob i8x8_mode_prob [VP8_UV_MODES-1];
+
+ vp8_prob prob_intra_coded;
+ vp8_prob prob_last_coded;
+ vp8_prob prob_gf_coded;
+ // Context probabilities when using predictive coding of segment id
+ vp8_prob segment_pred_probs[PREDICTION_PROBS];
+ unsigned char temporal_update;
+ // Context probabilities for reference frame prediction
+ unsigned char ref_scores[MAX_REF_FRAMES];
+ vp8_prob ref_pred_probs[PREDICTION_PROBS];
+ vp8_prob mod_refprobs[MAX_REF_FRAMES][PREDICTION_PROBS];
+
+ vp8_prob prob_comppred[COMP_PRED_CONTEXTS];
+
+ FRAME_CONTEXT lfc_a; /* last alt ref entropy */
FRAME_CONTEXT lfc; /* last frame entropy */
FRAME_CONTEXT fc; /* this frame entropy */
- unsigned int current_video_frame;
+ int mv_ref_ct[6][4][2];
+ int mode_context[6][4];
+ int mv_ref_ct_a[6][4][2];
+ int mode_context_a[6][4];
+ int vp8_mode_contexts[6][4];
+ unsigned int current_video_frame;
int near_boffset[3];
int version;
- TOKEN_PARTITION multi_token_partition;
-
#ifdef PACKET_TESTING
VP8_HEADER oh;
#endif
@@ -203,9 +256,7 @@ typedef struct VP8Common
#if CONFIG_RUNTIME_CPU_DETECT
VP8_COMMON_RTCD rtcd;
#endif
-#if CONFIG_MULTITHREAD
- int processor_core_count;
-#endif
+
#if CONFIG_POSTPROC
struct postproc_state postproc_state;
#endif
diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h
index 08f1cca80..d3b2c18d1 100644
--- a/vp8/common/onyxd.h
+++ b/vp8/common/onyxd.h
@@ -32,7 +32,6 @@ extern "C"
int Version;
int postprocess;
int max_threads;
- int error_concealment;
int input_partition;
} VP8D_CONFIG;
typedef enum
diff --git a/vp8/common/postproc.c b/vp8/common/postproc.c
index ace4c113c..d88b419bc 100644
--- a/vp8/common/postproc.c
+++ b/vp8/common/postproc.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_scale/yv12config.h"
#include "postproc.h"
#include "vpx_scale/yv12extend.h"
@@ -1024,9 +1024,9 @@ int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t
if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
|| (ppflags->display_mb_modes_flag & B_PRED))
{
- Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
- U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
- V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
+ Y = B_PREDICTION_MODE_colors[bmi->as_mode.first][0];
+ U = B_PREDICTION_MODE_colors[bmi->as_mode.first][1];
+ V = B_PREDICTION_MODE_colors[bmi->as_mode.first][2];
POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
(yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c
new file mode 100644
index 000000000..6bbb619e5
--- /dev/null
+++ b/vp8/common/pred_common.c
@@ -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 "vp8/common/pred_common.h"
+
+// TBD prediction functions for various bitstream signals
+
+// Returns a context number for the given MB prediction signal
+unsigned char get_pred_context( VP8_COMMON *const cm,
+ MACROBLOCKD *const xd,
+ PRED_ID pred_id )
+{
+ int pred_context;
+ MODE_INFO *m = xd->mode_info_context;
+
+ // 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.
+ switch (pred_id)
+ {
+ case PRED_SEG_ID:
+ pred_context = (m - 1)->mbmi.seg_id_predicted +
+ (m - cm->mode_info_stride)->mbmi.seg_id_predicted;
+ break;
+
+
+ case PRED_REF:
+ pred_context = (m - 1)->mbmi.ref_predicted +
+ (m - cm->mode_info_stride)->mbmi.ref_predicted;
+ break;
+
+ case PRED_COMP:
+ // Context based on use of comp pred flag by neighbours
+ //pred_context =
+ // ((m - 1)->mbmi.second_ref_frame != INTRA_FRAME) +
+ // ((m - cm->mode_info_stride)->mbmi.second_ref_frame != INTRA_FRAME);
+
+ // Context based on mode and reference frame
+ //if ( m->mbmi.ref_frame == LAST_FRAME )
+ // pred_context = 0 + (m->mbmi.mode != ZEROMV);
+ //else if ( m->mbmi.ref_frame == GOLDEN_FRAME )
+ // pred_context = 2 + (m->mbmi.mode != ZEROMV);
+ //else
+ // pred_context = 4 + (m->mbmi.mode != ZEROMV);
+
+ if ( m->mbmi.ref_frame == LAST_FRAME )
+ pred_context = 0;
+ else
+ pred_context = 1;
+
+ break;
+
+ default:
+ // TODO *** add error trap code.
+ pred_context = 0;
+ break;
+ }
+
+ return pred_context;
+}
+
+// This function returns a context probability for coding a given
+// prediction signal
+vp8_prob get_pred_prob( VP8_COMMON *const cm,
+ MACROBLOCKD *const xd,
+ PRED_ID pred_id )
+{
+ vp8_prob pred_probability;
+ int pred_context;
+
+ // Get the appropriate prediction context
+ pred_context = get_pred_context( cm, xd, pred_id );
+
+ switch (pred_id)
+ {
+ case PRED_SEG_ID:
+ pred_probability = cm->segment_pred_probs[pred_context];
+ break;
+
+ case PRED_REF:
+ pred_probability = cm->ref_pred_probs[pred_context];
+ break;
+
+ case PRED_COMP:
+ // In keeping with convention elsewhre the probability returned is
+ // the probability of a "0" outcome which in this case means the
+ // probability of comp pred off.
+ pred_probability = cm->prob_comppred[pred_context];
+ break;
+
+ default:
+ // TODO *** add error trap code.
+ pred_probability = 128;
+ break;
+ }
+
+ return pred_probability;
+}
+
+// This function returns the status of the given prediction signal.
+// I.e. is the predicted value for the given signal correct.
+unsigned char get_pred_flag( MACROBLOCKD *const xd,
+ PRED_ID pred_id )
+{
+ unsigned char pred_flag = 0;
+
+ switch (pred_id)
+ {
+ case PRED_SEG_ID:
+ pred_flag = xd->mode_info_context->mbmi.seg_id_predicted;
+ break;
+
+ case PRED_REF:
+ pred_flag = xd->mode_info_context->mbmi.ref_predicted;
+ break;
+
+ default:
+ // TODO *** add error trap code.
+ pred_flag = 0;
+ break;
+}
+
+ return pred_flag;
+}
+
+// This function sets the status of the given prediction signal.
+// I.e. is the predicted value for the given signal correct.
+void set_pred_flag( MACROBLOCKD *const xd,
+ PRED_ID pred_id,
+ unsigned char pred_flag)
+{
+ switch (pred_id)
+ {
+ case PRED_SEG_ID:
+ xd->mode_info_context->mbmi.seg_id_predicted = pred_flag;
+ break;
+
+ case PRED_REF:
+ xd->mode_info_context->mbmi.ref_predicted = pred_flag;
+ break;
+
+ default:
+ // TODO *** add error trap code.
+ break;
+ }
+}
+
+
+// The following contain the guts of the prediction code used to
+// peredict various bitstream signals.
+
+// Macroblock segment id prediction function
+unsigned char get_pred_mb_segid( VP8_COMMON *const cm, int MbIndex )
+{
+ // Currently the prediction for the macroblock segment ID is
+ // the value stored for this macroblock in the previous frame.
+ return cm->last_frame_seg_map[MbIndex];
+}
+
+MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
+ MACROBLOCKD *const xd )
+{
+ MODE_INFO *m = xd->mode_info_context;
+
+ MV_REFERENCE_FRAME left;
+ MV_REFERENCE_FRAME above;
+ MV_REFERENCE_FRAME above_left;
+ MV_REFERENCE_FRAME pred_ref = LAST_FRAME;
+
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
+ int seg_ref_active;
+ int i;
+
+ unsigned char frame_allowed[MAX_REF_FRAMES] = {1,1,1,1};
+ unsigned char ref_score[MAX_REF_FRAMES];
+ unsigned char best_score = 0;
+ unsigned char left_in_image;
+ unsigned char above_in_image;
+ unsigned char above_left_in_image;
+
+ // Is segment coding ennabled
+ seg_ref_active = segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME );
+
+ // Special case treatment if segment coding is enabled.
+ // Dont allow prediction of a reference frame that the segment
+ // does not allow
+ if ( seg_ref_active )
+ {
+ for ( i = 0; i < MAX_REF_FRAMES; i++ )
+ {
+ frame_allowed[i] =
+ check_segref( xd, segment_id, i );
+
+ // Score set to 0 if ref frame not allowed
+ ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
+ }
+ }
+ else
+ vpx_memcpy( ref_score, cm->ref_scores, sizeof(ref_score) );
+
+ // Reference frames used by neighbours
+ left = (m - 1)->mbmi.ref_frame;
+ above = (m - cm->mode_info_stride)->mbmi.ref_frame;
+ above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame;
+
+ // Are neighbours in image
+ left_in_image = (m - 1)->mbmi.mb_in_image;
+ above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
+ above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image;
+
+ // Adjust scores for candidate reference frames based on neigbours
+ if ( frame_allowed[left] && left_in_image )
+ {
+ ref_score[left] += 16;
+ if ( above_left_in_image && (left == above_left) )
+ ref_score[left] += 4;
+ }
+ if ( frame_allowed[above] && above_in_image )
+ {
+ ref_score[above] += 16;
+ if ( above_left_in_image && (above == above_left) )
+ ref_score[above] += 4;
+ }
+
+ // Now choose the candidate with the highest score
+ for ( i = 0; i < MAX_REF_FRAMES; i++ )
+ {
+ if ( ref_score[i] > best_score )
+ {
+ pred_ref = i;
+ best_score = ref_score[i];
+ }
+ }
+
+ return pred_ref;
+}
+
+// Functions to computes a set of modified reference frame probabilities
+// to use when the prediction of the reference frame value fails
+void calc_ref_probs( int * count, vp8_prob * probs )
+{
+ int tot_count;
+
+ tot_count = count[0] + count[1] + count[2] + count[3];
+ if ( tot_count )
+ {
+ probs[0] = (vp8_prob)((count[0] * 255) / tot_count);
+ probs[0] += !probs[0];
+ }
+ else
+ probs[0] = 128;
+
+ tot_count -= count[0];
+ if ( tot_count )
+ {
+ probs[1] = (vp8_prob)((count[1] * 255) / tot_count);
+ probs[1] += !probs[1];
+ }
+ else
+ probs[1] = 128;
+
+ tot_count -= count[1];
+ if ( tot_count )
+ {
+ probs[2] = (vp8_prob)((count[2] * 255) / tot_count);
+ probs[2] += !probs[2];
+ }
+ else
+ probs[2] = 128;
+
+}
+
+// Computes a set of modified conditional probabilities for the reference frame
+// Values willbe set to 0 for reference frame options that are not possible
+// because wither they were predicted and prediction has failed or because
+// they are not allowed for a given segment.
+void compute_mod_refprobs( VP8_COMMON *const cm )
+{
+ int norm_cnt[MAX_REF_FRAMES];
+ int intra_count;
+ int inter_count;
+ int last_count;
+ int gfarf_count;
+ int gf_count;
+ int arf_count;
+
+ intra_count = cm->prob_intra_coded;
+ inter_count = (255 - intra_count);
+ last_count = (inter_count * cm->prob_last_coded)/255;
+ gfarf_count = inter_count - last_count;
+ gf_count = (gfarf_count * cm->prob_gf_coded)/255;
+ arf_count = gfarf_count - gf_count;
+
+ // Work out modified reference frame probabilities to use where prediction
+ // of the reference frame fails
+ norm_cnt[0] = 0;
+ norm_cnt[1] = last_count;
+ norm_cnt[2] = gf_count;
+ norm_cnt[3] = arf_count;
+ calc_ref_probs( norm_cnt, cm->mod_refprobs[INTRA_FRAME] );
+ cm->mod_refprobs[INTRA_FRAME][0] = 0; // This branch implicit
+
+ norm_cnt[0] = intra_count;
+ norm_cnt[1] = 0;
+ norm_cnt[2] = gf_count;
+ norm_cnt[3] = arf_count;
+ calc_ref_probs( norm_cnt, cm->mod_refprobs[LAST_FRAME]);
+ cm->mod_refprobs[LAST_FRAME][1] = 0; // This branch implicit
+
+ norm_cnt[0] = intra_count;
+ norm_cnt[1] = last_count;
+ norm_cnt[2] = 0;
+ norm_cnt[3] = arf_count;
+ calc_ref_probs( norm_cnt, cm->mod_refprobs[GOLDEN_FRAME] );
+ cm->mod_refprobs[GOLDEN_FRAME][2] = 0; // This branch implicit
+
+ norm_cnt[0] = intra_count;
+ norm_cnt[1] = last_count;
+ norm_cnt[2] = gf_count;
+ norm_cnt[3] = 0;
+ calc_ref_probs( norm_cnt, cm->mod_refprobs[ALTREF_FRAME] );
+ cm->mod_refprobs[ALTREF_FRAME][2] = 0; // This branch implicit
+
+ // Score the reference frames based on overal frequency.
+ // These scores contribute to the prediction choices.
+ // Max score 17 min 1
+ cm->ref_scores[INTRA_FRAME] = 1 + (intra_count * 16 / 255);
+ cm->ref_scores[LAST_FRAME] = 1 + (last_count * 16 / 255);
+ cm->ref_scores[GOLDEN_FRAME] = 1 + (gf_count * 16 / 255);
+ cm->ref_scores[ALTREF_FRAME] = 1 + (arf_count * 16 / 255);
+}
diff --git a/vp8/common/pred_common.h b/vp8/common/pred_common.h
new file mode 100644
index 000000000..cd68035b8
--- /dev/null
+++ b/vp8/common/pred_common.h
@@ -0,0 +1,51 @@
+/*
+ * 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 "type_aliases.h"
+#include "onyxc_int.h"
+#include "vp8/common/blockd.h"
+
+#ifndef __INC_PRED_COMMON_H__
+#define __INC_PRED_COMMON_H__ 1
+
+
+// Predicted items
+typedef enum
+{
+ PRED_SEG_ID = 0, // Segment identifier
+ PRED_REF = 1,
+ PRED_COMP = 2
+
+} PRED_ID;
+
+
+extern unsigned char get_pred_context( VP8_COMMON *const cm,
+ MACROBLOCKD *const xd,
+ PRED_ID pred_id );
+
+extern vp8_prob get_pred_prob( VP8_COMMON *const cm,
+ MACROBLOCKD *const xd,
+ PRED_ID pred_id );
+
+extern unsigned char get_pred_flag( MACROBLOCKD *const xd,
+ PRED_ID pred_id );
+
+extern void set_pred_flag( MACROBLOCKD *const xd,
+ PRED_ID pred_id,
+ unsigned char pred_flag);
+
+
+extern unsigned char get_pred_mb_segid( VP8_COMMON *const cm, int MbIndex );
+
+extern MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
+ MACROBLOCKD *const xd );
+extern void compute_mod_refprobs( VP8_COMMON *const cm );
+
+#endif /* __INC_PRED_COMMON_H__ */
diff --git a/vp8/common/predict_rotated.c b/vp8/common/predict_rotated.c
new file mode 100644
index 000000000..0880bfb4c
--- /dev/null
+++ b/vp8/common/predict_rotated.c
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#if CONFIG_ROTATION
+typedef struct
+{
+ int y;
+ int x;
+ unsigned long t;
+} tap;
+
+typedef struct
+{
+ tap pt[4];
+} point_taps;
+
+typedef struct
+{
+ point_taps pt[256];
+} mb_taps;
+
+mb_taps mt_8x8[] =
+{
+ #include "rotate2.h"
+};
+
+mb_taps mt[] =
+{
+ #include "rotate.h"
+};
+
+void predict_rotated_16x16(int rotation_index, unsigned char *src, int sp,
+ unsigned char *dst, int dp)
+{
+ int i, j, k, p = 0;
+
+ for (i = 0; i < 16; i++, dst += dp)
+ {
+ for (j = 0; j < 16; j++, p++)
+ {
+ unsigned int sum = 32768;
+
+ for (k = 0; k < 4; k++)
+ {
+ tap *tp = &mt[rotation_index].pt[p].pt[k];
+ sum += src[tp->y * sp + tp->x] * tp->t;
+ }
+ sum >>= 16;
+ dst[j] = sum;
+ }
+ }
+}
+void predict_rotated_8x8(int rotation_index, unsigned char *src, int sp,
+ unsigned char *dst, int dp)
+{
+ int i, j, k, p = 0;
+
+ for (i = 0; i < 8; i++, dst += dp)
+ {
+ for (j = 0; j < 8; j++, p++)
+ {
+ unsigned int sum = 32768;
+
+ for (k = 0; k < 4; k++)
+ {
+ tap *tp = &mt_8x8[rotation_index].pt[p].pt[k];
+ sum += src[tp->y * sp + tp->x] * tp->t;
+ }
+ sum >>= 16;
+ dst[j] = sum;
+ }
+ }
+}
+#endif
+
+
+
+
diff --git a/vp8/common/quant_common.c b/vp8/common/quant_common.c
index b8e6e2972..0bb44f588 100644
--- a/vp8/common/quant_common.c
+++ b/vp8/common/quant_common.c
@@ -11,57 +11,34 @@
#include "quant_common.h"
+static int dc_qlookup[QINDEX_RANGE];
+static int ac_qlookup[QINDEX_RANGE];
-#if !CONFIG_EXTEND_QRANGE
-static const int dc_qlookup[QINDEX_RANGE] =
-{
- 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 17,
- 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 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, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 91, 93, 95, 96, 98, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118,
- 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157,
-};
-
-static const int ac_qlookup[QINDEX_RANGE] =
-{
- 4, 5, 6, 7, 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, 60, 62, 64, 66, 68, 70, 72, 74, 76,
- 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108,
- 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152,
- 155, 158, 161, 164, 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209,
- 213, 217, 221, 225, 229, 234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284,
-};
-#else
-
-static const int dc_qlookup[QINDEX_RANGE] =
-{
- 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 34, 36, 38, 40, 42,
- 44, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88,
- 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152,
- 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 205, 210, 215, 220,
- 225, 230, 235, 240, 245, 250, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300,
- 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460,
- 472, 484, 496, 508, 520, 532, 544, 556, 572, 588, 608, 628, 648, 668, 692, 720,
-};
-
-static const int ac_qlookup[QINDEX_RANGE] =
+#define ACDC_MIN 4
+
+void vp8_init_quant_tables()
{
- 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 51,
- 54, 57, 60, 63, 66, 69, 72, 76, 80, 84, 88, 92, 96, 100, 105, 110,
- 115, 120, 125, 130, 135, 140, 146, 152, 158, 164, 170, 176, 182, 188, 194, 200,
- 206, 212, 218, 224, 232, 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320,
- 330, 340, 350, 360, 370, 380, 392, 404, 416, 428, 440, 454, 468, 482, 496, 510,
- 524, 540, 556, 572, 588, 604, 622, 640, 658, 676, 696, 716, 736, 756, 776, 796,
- 820, 844, 868, 892, 916, 944, 972, 1000, 1032, 1064, 1096, 1128, 1168, 1208, 1252, 1300
-};
-#endif
+ int i;
+ int current_val = 4;
+ int last_val = 4;
+ int ac_val;
+
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ ac_qlookup[i] = current_val;
+ current_val = (int)((double)current_val * 1.02);
+ if ( current_val == last_val )
+ current_val++;
+ last_val = current_val;
+
+ ac_val = ac_qlookup[i];
+ dc_qlookup[i] = (0.000000305 * ac_val * ac_val * ac_val) +
+ (-0.00065 * ac_val * ac_val) +
+ (0.9 * ac_val) + 0.5;
+ if ( dc_qlookup[i] < ACDC_MIN )
+ dc_qlookup[i] = ACDC_MIN;
+ }
+}
int vp8_dc_quant(int QIndex, int Delta)
{
@@ -69,8 +46,8 @@ int vp8_dc_quant(int QIndex, int Delta)
QIndex = QIndex + Delta;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
@@ -84,16 +61,13 @@ int vp8_dc2quant(int QIndex, int Delta)
QIndex = QIndex + Delta;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
-#if !CONFIG_EXTEND_QRANGE
- retval = dc_qlookup[ QIndex ] * 2;
-#else
retval = dc_qlookup[ QIndex ];
-#endif
+
return retval;
}
@@ -103,8 +77,8 @@ int vp8_dc_uv_quant(int QIndex, int Delta)
QIndex = QIndex + Delta;
- if (QIndex > 117)
- QIndex = 117;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
@@ -117,8 +91,8 @@ int vp8_ac_yquant(int QIndex)
{
int retval;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
@@ -132,17 +106,15 @@ int vp8_ac2quant(int QIndex, int Delta)
QIndex = QIndex + Delta;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
-#if !CONFIG_EXTEND_QRANGE
- retval = (ac_qlookup[ QIndex ] * 155) / 100;
- if (retval < 8)
- retval = 8;
-#else
- retval = ac_qlookup[ QIndex ];
-#endif
+
+ retval = (ac_qlookup[ QIndex ] * 775) / 1000;
+ if (retval < 4)
+ retval = 4;
+
return retval;
}
int vp8_ac_uv_quant(int QIndex, int Delta)
@@ -151,8 +123,8 @@ int vp8_ac_uv_quant(int QIndex, int Delta)
QIndex = QIndex + Delta;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
diff --git a/vp8/common/quant_common.h b/vp8/common/quant_common.h
index cb64d8eb8..0d8099e9b 100644
--- a/vp8/common/quant_common.h
+++ b/vp8/common/quant_common.h
@@ -13,6 +13,7 @@
#include "blockd.h"
#include "onyxc_int.h"
+extern void vp8_init_quant_tables();
extern int vp8_ac_yquant(int QIndex);
extern int vp8_dc_quant(int QIndex, int Delta);
extern int vp8_dc2quant(int QIndex, int Delta);
diff --git a/vp8/common/recon.c b/vp8/common/recon.c
index eebf6dcb9..279fbe82f 100644
--- a/vp8/common/recon.c
+++ b/vp8/common/recon.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "recon.h"
#include "blockd.h"
@@ -44,6 +44,36 @@ void vp8_recon_b_c
}
}
+void vp8_recon_uv_b_c
+(
+ unsigned char *pred_ptr,
+ short *diff_ptr,
+ unsigned char *dst_ptr,
+ int stride
+)
+{
+ int r, c;
+
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ int a = diff_ptr[c] + pred_ptr[c] ;
+
+ if (a < 0)
+ a = 0;
+
+ if (a > 255)
+ a = 255;
+
+ dst_ptr[c] = (unsigned char) a ;
+ }
+
+ dst_ptr += stride;
+ diff_ptr += 8;
+ pred_ptr += 8;
+ }
+}
void vp8_recon4b_c
(
unsigned char *pred_ptr,
diff --git a/vp8/common/recon.h b/vp8/common/recon.h
index 7cfc779cd..9fb12c85d 100644
--- a/vp8/common/recon.h
+++ b/vp8/common/recon.h
@@ -29,6 +29,11 @@
#define prototype_intra4x4_predict(sym) \
void sym(BLOCKD *x, int b_mode, unsigned char *predictor)
+#if CONFIG_COMP_INTRA_PRED
+#define prototype_comp_intra4x4_predict(sym) \
+ void sym(BLOCKD *x, int b_mode, int mode2, unsigned char *predictor)
+#endif
+
struct vp8_recon_rtcd_vtable;
#if ARCH_X86 || ARCH_X86_64
@@ -49,6 +54,16 @@ extern prototype_copy_block(vp8_recon_copy16x16);
#endif
extern prototype_copy_block(vp8_recon_copy8x8);
+#ifndef vp8_recon_avg16x16
+#define vp8_recon_avg16x16 vp8_avg_mem16x16_c
+#endif
+extern prototype_copy_block(vp8_recon_avg16x16);
+
+#ifndef vp8_recon_avg8x8
+#define vp8_recon_avg8x8 vp8_avg_mem8x8_c
+#endif
+extern prototype_copy_block(vp8_recon_avg8x8);
+
#ifndef vp8_recon_copy8x4
#define vp8_recon_copy8x4 vp8_copy_mem8x4_c
#endif
@@ -59,6 +74,12 @@ extern prototype_copy_block(vp8_recon_copy8x4);
#endif
extern prototype_recon_block(vp8_recon_recon);
+#ifndef vp8_recon_recon_uv
+#define vp8_recon_recon_uv vp8_recon_uv_b_c
+#endif
+extern prototype_recon_block(vp8_recon_recon_uv);
+
+extern prototype_recon_block(vp8_recon_recon);
#ifndef vp8_recon_recon2
#define vp8_recon_recon2 vp8_recon2b_c
#endif
@@ -85,6 +106,20 @@ extern prototype_recon_macroblock(vp8_recon_recon_mby);
extern prototype_build_intra_predictors\
(vp8_recon_build_intra_predictors_mby);
+#if CONFIG_COMP_INTRA_PRED
+#ifndef vp8_recon_build_comp_intra_predictors_mby
+#define vp8_recon_build_comp_intra_predictors_mby vp8_build_comp_intra_predictors_mby
+#endif
+extern prototype_build_intra_predictors\
+ (vp8_recon_build_comp_intra_predictors_mby);
+#endif
+
+#ifndef vp8_recon_build_intra8x8_predictors_mby
+#define vp8_recon_build_intra8x8_predictors_mby vp8_build_intra8x8_predictors_mby
+#endif
+extern prototype_build_intra_predictors\
+ (vp8_recon_build_intra8x8_predictors_mby);
+
#ifndef vp8_recon_build_intra_predictors_mby_s
#define vp8_recon_build_intra_predictors_mby_s vp8_build_intra_predictors_mby_s
#endif
@@ -97,39 +132,111 @@ extern prototype_build_intra_predictors\
extern prototype_build_intra_predictors\
(vp8_recon_build_intra_predictors_mbuv);
+#ifndef vp8_recon_build_intra8x8_predictors_mbuv
+#define vp8_recon_build_intra8x8_predictors_mbuv vp8_build_intra8x8_predictors_mbuv
+#endif
+extern prototype_build_intra_predictors\
+ (vp8_recon_build_intra8x8_predictors_mbuv);
+
#ifndef vp8_recon_build_intra_predictors_mbuv_s
#define vp8_recon_build_intra_predictors_mbuv_s vp8_build_intra_predictors_mbuv_s
#endif
extern prototype_build_intra_predictors\
(vp8_recon_build_intra_predictors_mbuv_s);
+#if CONFIG_COMP_INTRA_PRED
+#ifndef vp8_recon_build_comp_intra_predictors_mbuv
+#define vp8_recon_build_comp_intra_predictors_mbuv vp8_build_comp_intra_predictors_mbuv
+#endif
+extern prototype_build_intra_predictors\
+ (vp8_recon_build_comp_intra_predictors_mbuv);
+#endif
+
#ifndef vp8_recon_intra4x4_predict
#define vp8_recon_intra4x4_predict vp8_intra4x4_predict
#endif
extern prototype_intra4x4_predict\
(vp8_recon_intra4x4_predict);
+#if CONFIG_COMP_INTRA_PRED
+#ifndef vp8_recon_comp_intra4x4_predict
+#define vp8_recon_comp_intra4x4_predict vp8_comp_intra4x4_predict
+#endif
+extern prototype_comp_intra4x4_predict\
+ (vp8_recon_comp_intra4x4_predict);
+#endif
+
+#ifndef vp8_recon_intra8x8_predict
+#define vp8_recon_intra8x8_predict vp8_intra8x8_predict
+#endif
+extern prototype_intra4x4_predict\
+ (vp8_recon_intra8x8_predict);
+
+#if CONFIG_COMP_INTRA_PRED
+#ifndef vp8_recon_comp_intra8x8_predict
+#define vp8_recon_comp_intra8x8_predict vp8_comp_intra8x8_predict
+#endif
+extern prototype_comp_intra4x4_predict\
+ (vp8_recon_comp_intra8x8_predict);
+#endif
+
+#ifndef vp8_recon_intra_uv4x4_predict
+#define vp8_recon_intra_uv4x4_predict vp8_intra_uv4x4_predict
+#endif
+extern prototype_intra4x4_predict\
+ (vp8_recon_intra_uv4x4_predict);
+
+#if CONFIG_COMP_INTRA_PRED
+#ifndef vp8_recon_comp_intra_uv4x4_predict
+#define vp8_recon_comp_intra_uv4x4_predict vp8_comp_intra_uv4x4_predict
+#endif
+extern prototype_comp_intra4x4_predict\
+ (vp8_recon_comp_intra_uv4x4_predict);
+#endif
typedef prototype_copy_block((*vp8_copy_block_fn_t));
typedef prototype_recon_block((*vp8_recon_fn_t));
typedef prototype_recon_macroblock((*vp8_recon_mb_fn_t));
typedef prototype_build_intra_predictors((*vp8_build_intra_pred_fn_t));
typedef prototype_intra4x4_predict((*vp8_intra4x4_pred_fn_t));
+#if CONFIG_COMP_INTRA_PRED
+typedef prototype_comp_intra4x4_predict((*vp8_comp_intra4x4_pred_fn_t));
+#endif
typedef struct vp8_recon_rtcd_vtable
{
vp8_copy_block_fn_t copy16x16;
vp8_copy_block_fn_t copy8x8;
+ vp8_copy_block_fn_t avg16x16;
+ vp8_copy_block_fn_t avg8x8;
vp8_copy_block_fn_t copy8x4;
vp8_recon_fn_t recon;
+ vp8_recon_fn_t recon_uv;
vp8_recon_fn_t recon2;
vp8_recon_fn_t recon4;
vp8_recon_mb_fn_t recon_mb;
vp8_recon_mb_fn_t recon_mby;
vp8_build_intra_pred_fn_t build_intra_predictors_mby_s;
vp8_build_intra_pred_fn_t build_intra_predictors_mby;
+#if CONFIG_COMP_INTRA_PRED
+ vp8_build_intra_pred_fn_t build_comp_intra_predictors_mby;
+#endif
vp8_build_intra_pred_fn_t build_intra_predictors_mbuv_s;
vp8_build_intra_pred_fn_t build_intra_predictors_mbuv;
+#if CONFIG_COMP_INTRA_PRED
+ vp8_build_intra_pred_fn_t build_comp_intra_predictors_mbuv;
+#endif
vp8_intra4x4_pred_fn_t intra4x4_predict;
+#if CONFIG_COMP_INTRA_PRED
+ vp8_comp_intra4x4_pred_fn_t comp_intra4x4_predict;
+#endif
+ vp8_intra4x4_pred_fn_t intra8x8_predict;
+#if CONFIG_COMP_INTRA_PRED
+ vp8_comp_intra4x4_pred_fn_t comp_intra8x8_predict;
+#endif
+ vp8_intra4x4_pred_fn_t intra_uv4x4_predict;
+#if CONFIG_COMP_INTRA_PRED
+ vp8_comp_intra4x4_pred_fn_t comp_intra_uv4x4_predict;
+#endif
} vp8_recon_rtcd_vtable_t;
#if CONFIG_RUNTIME_CPU_DETECT
diff --git a/vp8/common/reconinter.c b/vp8/common/reconinter.c
index e4e8a80a4..bd08e7f2c 100644
--- a/vp8/common/reconinter.c
+++ b/vp8/common/reconinter.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx/vpx_integer.h"
#include "recon.h"
#include "subpixel.h"
@@ -62,6 +62,28 @@ void vp8_copy_mem16x16_c(
}
+void vp8_avg_mem16x16_c(
+ unsigned char *src,
+ int src_stride,
+ unsigned char *dst,
+ int dst_stride)
+{
+ int r;
+
+ for (r = 0; r < 16; r++)
+ {
+ int n;
+
+ for (n = 0; n < 16; n++)
+ {
+ dst[n] = (dst[n] + src[n] + 1) >> 1;
+ }
+
+ src += src_stride;
+ dst += dst_stride;
+ }
+}
+
void vp8_copy_mem8x8_c(
unsigned char *src,
int src_stride,
@@ -92,6 +114,28 @@ void vp8_copy_mem8x8_c(
}
+void vp8_avg_mem8x8_c(
+ unsigned char *src,
+ int src_stride,
+ unsigned char *dst,
+ int dst_stride)
+{
+ int r;
+
+ for (r = 0; r < 8; r++)
+ {
+ int n;
+
+ for (n = 0; n < 8; n++)
+ {
+ dst[n] = (dst[n] + src[n] + 1) >> 1;
+ }
+
+ src += src_stride;
+ dst += dst_stride;
+ }
+}
+
void vp8_copy_mem8x4_c(
unsigned char *src,
int src_stride,
@@ -136,7 +180,11 @@ void vp8_build_inter_predictors_b(BLOCKD *d, int pitch, vp8_subpix_fn_t sppf)
if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
{
ptr = ptr_base + d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ sppf(ptr, d->pre_stride, (d->bmi.mv.as_mv.col & 7)<<1, (d->bmi.mv.as_mv.row & 7)<<1, pred_ptr, pitch);
+#else
sppf(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+#endif
}
else
{
@@ -170,7 +218,11 @@ static void build_inter_predictors4b(MACROBLOCKD *x, BLOCKD *d, int pitch)
if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ x->subpixel_predict8x8(ptr, d->pre_stride, (d->bmi.mv.as_mv.col & 7)<<1, (d->bmi.mv.as_mv.row & 7)<<1, pred_ptr, pitch);
+#else
x->subpixel_predict8x8(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+#endif
}
else
{
@@ -189,7 +241,11 @@ static void build_inter_predictors2b(MACROBLOCKD *x, BLOCKD *d, int pitch)
if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ x->subpixel_predict8x4(ptr, d->pre_stride, (d->bmi.mv.as_mv.col & 7)<<1, (d->bmi.mv.as_mv.row & 7)<<1, pred_ptr, pitch);
+#else
x->subpixel_predict8x4(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+#endif
}
else
{
@@ -205,8 +261,10 @@ void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x)
unsigned char *upred_ptr = &x->predictor[256];
unsigned char *vpred_ptr = &x->predictor[320];
- int mv_row = x->mode_info_context->mbmi.mv.as_mv.row;
- int mv_col = x->mode_info_context->mbmi.mv.as_mv.col;
+ int omv_row = x->mode_info_context->mbmi.mv.as_mv.row;
+ int omv_col = x->mode_info_context->mbmi.mv.as_mv.col;
+ int mv_row = omv_row;
+ int mv_col = omv_col;
int offset;
int pre_stride = x->block[16].pre_stride;
@@ -231,11 +289,19 @@ void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x)
uptr = x->pre.u_buffer + offset;
vptr = x->pre.v_buffer + offset;
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ if ((omv_row | omv_col) & 15)
+ {
+ x->subpixel_predict8x8(uptr, pre_stride, omv_col & 15, omv_row & 15, upred_ptr, 8);
+ x->subpixel_predict8x8(vptr, pre_stride, omv_col & 15, omv_row & 15, vpred_ptr, 8);
+ }
+#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
if ((mv_row | mv_col) & 7)
{
x->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, 8);
x->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, 8);
}
+#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
else
{
RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, pre_stride, upred_ptr, 8);
@@ -317,7 +383,11 @@ void vp8_build_inter16x16_predictors_mby(MACROBLOCKD *x)
if ((mv_row | mv_col) & 7)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ x->subpixel_predict16x16(ptr, pre_stride, (mv_col & 7)<<1, (mv_row & 7)<<1, pred_ptr, 16);
+#else
x->subpixel_predict16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, pred_ptr, 16);
+#endif
}
else
{
@@ -336,31 +406,33 @@ static void clamp_mv_to_umv_border(MV *mv, const MACROBLOCKD *xd)
* filtering. The bottom and right edges use 16 pixels plus 2 pixels
* left of the central pixel when filtering.
*/
- if (mv->col < (xd->mb_to_left_edge - (19 << 3)))
+ if (mv->col < (xd->mb_to_left_edge - ((16+INTERP_EXTEND) << 3)))
mv->col = xd->mb_to_left_edge - (16 << 3);
- else if (mv->col > xd->mb_to_right_edge + (18 << 3))
+ else if (mv->col > xd->mb_to_right_edge + ((15+INTERP_EXTEND) << 3))
mv->col = xd->mb_to_right_edge + (16 << 3);
- if (mv->row < (xd->mb_to_top_edge - (19 << 3)))
+ if (mv->row < (xd->mb_to_top_edge - ((16+INTERP_EXTEND) << 3)))
mv->row = xd->mb_to_top_edge - (16 << 3);
- else if (mv->row > xd->mb_to_bottom_edge + (18 << 3))
+ else if (mv->row > xd->mb_to_bottom_edge + ((15+INTERP_EXTEND) << 3))
mv->row = xd->mb_to_bottom_edge + (16 << 3);
}
/* A version of the above function for chroma block MVs.*/
static void clamp_uvmv_to_umv_border(MV *mv, const MACROBLOCKD *xd)
{
- mv->col = (2*mv->col < (xd->mb_to_left_edge - (19 << 3))) ?
+ mv->col = (2*mv->col < (xd->mb_to_left_edge - ((16+INTERP_EXTEND) << 3))) ?
(xd->mb_to_left_edge - (16 << 3)) >> 1 : mv->col;
- mv->col = (2*mv->col > xd->mb_to_right_edge + (18 << 3)) ?
+ mv->col = (2*mv->col > xd->mb_to_right_edge + ((15+INTERP_EXTEND) << 3)) ?
(xd->mb_to_right_edge + (16 << 3)) >> 1 : mv->col;
- mv->row = (2*mv->row < (xd->mb_to_top_edge - (19 << 3))) ?
+ mv->row = (2*mv->row < (xd->mb_to_top_edge - ((16+INTERP_EXTEND) << 3))) ?
(xd->mb_to_top_edge - (16 << 3)) >> 1 : mv->row;
- mv->row = (2*mv->row > xd->mb_to_bottom_edge + (18 << 3)) ?
+ mv->row = (2*mv->row > xd->mb_to_bottom_edge + ((15+INTERP_EXTEND) << 3)) ?
(xd->mb_to_bottom_edge + (16 << 3)) >> 1 : mv->row;
}
+
+
void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
unsigned char *dst_y,
unsigned char *dst_u,
@@ -372,6 +444,7 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
unsigned char *ptr;
unsigned char *uptr, *vptr;
+ int_mv _o16x16mv;
int_mv _16x16mv;
unsigned char *ptr_base = x->pre.y_buffer;
@@ -388,13 +461,18 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
if ( _16x16mv.as_int & 0x00070007)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ x->subpixel_predict16x16(ptr, pre_stride, (_16x16mv.as_mv.col & 7)<<1, (_16x16mv.as_mv.row & 7)<<1, dst_y, dst_ystride);
+#else
x->subpixel_predict16x16(ptr, pre_stride, _16x16mv.as_mv.col & 7, _16x16mv.as_mv.row & 7, dst_y, dst_ystride);
+#endif
}
else
{
RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, dst_y, dst_ystride);
}
+ _o16x16mv = _16x16mv;
/* calc uv motion vectors */
if ( _16x16mv.as_mv.row < 0)
_16x16mv.as_mv.row -= 1;
@@ -417,16 +495,106 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
uptr = x->pre.u_buffer + offset;
vptr = x->pre.v_buffer + offset;
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ if ( _o16x16mv.as_int & 0x000f000f)
+ {
+ x->subpixel_predict8x8(uptr, pre_stride, _o16x16mv.as_mv.col & 15, _o16x16mv.as_mv.row & 15, dst_u, dst_uvstride);
+ x->subpixel_predict8x8(vptr, pre_stride, _o16x16mv.as_mv.col & 15, _o16x16mv.as_mv.row & 15, dst_v, dst_uvstride);
+ }
+#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
if ( _16x16mv.as_int & 0x00070007)
{
x->subpixel_predict8x8(uptr, pre_stride, _16x16mv.as_mv.col & 7, _16x16mv.as_mv.row & 7, dst_u, dst_uvstride);
x->subpixel_predict8x8(vptr, pre_stride, _16x16mv.as_mv.col & 7, _16x16mv.as_mv.row & 7, dst_v, dst_uvstride);
}
+#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
else
{
RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, pre_stride, dst_u, dst_uvstride);
RECON_INVOKE(&x->rtcd->recon, copy8x8)(vptr, pre_stride, dst_v, dst_uvstride);
}
+
+}
+
+/*
+ * This function should be called after an initial call to
+ * vp8_build_inter16x16_predictors_mb() or _mby()/_mbuv().
+ * It will run a second sixtap filter on a (different) ref
+ * frame and average the result with the output of the
+ * first sixtap filter. The second reference frame is stored
+ * in x->second_pre (the reference frame index is in
+ * x->mode_info_context->mbmi.second_ref_frame). The second
+ * motion vector is x->mode_info_context->mbmi.second_mv.
+ *
+ * This allows blending prediction from two reference frames
+ * which sometimes leads to better prediction than from a
+ * single reference framer.
+ */
+void vp8_build_2nd_inter16x16_predictors_mb(MACROBLOCKD *x,
+ unsigned char *dst_y,
+ unsigned char *dst_u,
+ unsigned char *dst_v,
+ int dst_ystride,
+ int dst_uvstride)
+{
+ int offset;
+ unsigned char *ptr;
+ unsigned char *uptr, *vptr;
+
+ int mv_row = x->mode_info_context->mbmi.second_mv.as_mv.row;
+ int mv_col = x->mode_info_context->mbmi.second_mv.as_mv.col;
+ int omv_row, omv_col;
+
+ unsigned char *ptr_base = x->second_pre.y_buffer;
+ int pre_stride = x->block[0].pre_stride;
+
+ ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
+
+ if ((mv_row | mv_col) & 7)
+ {
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ x->subpixel_predict_avg16x16(ptr, pre_stride, (mv_col & 7)<<1, (mv_row & 7)<<1, dst_y, dst_ystride);
+#else
+ x->subpixel_predict_avg16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, dst_y, dst_ystride);
+#endif
+ }
+ else
+ {
+ RECON_INVOKE(&x->rtcd->recon, avg16x16)(ptr, pre_stride, dst_y, dst_ystride);
+ }
+
+ /* calc uv motion vectors */
+ omv_row = mv_row;
+ omv_col = mv_col;
+ mv_row = (mv_row + (mv_row > 0)) >> 1;
+ mv_col = (mv_col + (mv_col > 0)) >> 1;
+
+ mv_row &= x->fullpixel_mask;
+ mv_col &= x->fullpixel_mask;
+
+ pre_stride >>= 1;
+ offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+ uptr = x->second_pre.u_buffer + offset;
+ vptr = x->second_pre.v_buffer + offset;
+
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ if ((omv_row | omv_col) & 15)
+ {
+ x->subpixel_predict_avg8x8(uptr, pre_stride, omv_col & 15, omv_row & 15, dst_u, dst_uvstride);
+ x->subpixel_predict_avg8x8(vptr, pre_stride, omv_col & 15, omv_row & 15, dst_v, dst_uvstride);
+ }
+#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
+ if ((mv_row | mv_col) & 7)
+ {
+ x->subpixel_predict_avg8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, dst_u, dst_uvstride);
+ x->subpixel_predict_avg8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, dst_v, dst_uvstride);
+ }
+#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
+ else
+ {
+ RECON_INVOKE(&x->rtcd->recon, avg8x8)(uptr, pre_stride, dst_u, dst_uvstride);
+ RECON_INVOKE(&x->rtcd->recon, avg8x8)(vptr, pre_stride, dst_v, dst_uvstride);
+ }
}
static void build_inter4x4_predictors_mb(MACROBLOCKD *x)
@@ -439,6 +607,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *x)
x->block[ 2].bmi = x->mode_info_context->bmi[ 2];
x->block[ 8].bmi = x->mode_info_context->bmi[ 8];
x->block[10].bmi = x->mode_info_context->bmi[10];
+
if (x->mode_info_context->mbmi.need_to_clamp_mvs)
{
clamp_mv_to_umv_border(&x->block[ 0].bmi.mv.as_mv, x);
@@ -447,6 +616,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *x)
clamp_mv_to_umv_border(&x->block[10].bmi.mv.as_mv, x);
}
+
build_inter_predictors4b(x, &x->block[ 0], 16);
build_inter_predictors4b(x, &x->block[ 2], 16);
build_inter_predictors4b(x, &x->block[ 8], 16);
@@ -461,6 +631,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *x)
x->block[i+0].bmi = x->mode_info_context->bmi[i+0];
x->block[i+1].bmi = x->mode_info_context->bmi[i+1];
+
if (x->mode_info_context->mbmi.need_to_clamp_mvs)
{
clamp_mv_to_umv_border(&x->block[i+0].bmi.mv.as_mv, x);
@@ -484,8 +655,6 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *x)
BLOCKD *d0 = &x->block[i];
BLOCKD *d1 = &x->block[i+1];
- /* Note: uv mvs already clamped in build_4x4uvmvs() */
-
if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
build_inter_predictors2b(x, d0, 8);
else
@@ -534,6 +703,9 @@ void build_4x4uvmvs(MACROBLOCKD *x)
if (x->mode_info_context->mbmi.need_to_clamp_mvs)
clamp_uvmv_to_umv_border(&x->block[uoffset].bmi.mv.as_mv, x);
+ if (x->mode_info_context->mbmi.need_to_clamp_mvs)
+ clamp_uvmv_to_umv_border(&x->block[uoffset].bmi.mv.as_mv, x);
+
x->block[voffset].bmi.mv.as_mv.row =
x->block[uoffset].bmi.mv.as_mv.row ;
x->block[voffset].bmi.mv.as_mv.col =
@@ -548,6 +720,16 @@ void vp8_build_inter_predictors_mb(MACROBLOCKD *x)
{
vp8_build_inter16x16_predictors_mb(x, x->predictor, &x->predictor[256],
&x->predictor[320], 16, 8);
+
+ if (x->mode_info_context->mbmi.second_ref_frame)
+ {
+ /* 256 = offset of U plane in Y+U+V buffer;
+ * 320 = offset of V plane in Y+U+V buffer.
+ * (256=16x16, 320=16x16+8x8). */
+ vp8_build_2nd_inter16x16_predictors_mb(x, x->predictor,
+ &x->predictor[256],
+ &x->predictor[320], 16, 8);
+ }
}
else
{
@@ -555,4 +737,3 @@ void vp8_build_inter_predictors_mb(MACROBLOCKD *x)
build_inter4x4_predictors_mb(x);
}
}
-
diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h
index 456812ecd..c8e2f803b 100644
--- a/vp8/common/reconinter.h
+++ b/vp8/common/reconinter.h
@@ -19,6 +19,12 @@ extern void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
unsigned char *dst_v,
int dst_ystride,
int dst_uvstride);
+extern void vp8_build_2nd_inter16x16_predictors_mb(MACROBLOCKD *x,
+ unsigned char *dst_y,
+ unsigned char *dst_u,
+ unsigned char *dst_v,
+ int dst_ystride,
+ int dst_uvstride);
extern void vp8_build_inter16x16_predictors_mby(MACROBLOCKD *x);
diff --git a/vp8/common/reconintra.c b/vp8/common/reconintra.c
index 16dadc47d..501eacab2 100644
--- a/vp8/common/reconintra.c
+++ b/vp8/common/reconintra.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "recon.h"
#include "reconintra.h"
#include "vpx_mem/vpx_mem.h"
@@ -28,13 +28,12 @@ void vp8_recon_intra_mbuv(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
}
}
-void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
+void vp8_build_intra_predictors_mby_internal(MACROBLOCKD *x, unsigned char *ypred_ptr, int y_stride, int mode)
{
unsigned char *yabove_row = x->dst.y_buffer - x->dst.y_stride;
unsigned char yleft_col[16];
unsigned char ytop_left = yabove_row[-1];
- unsigned char *ypred_ptr = x->predictor;
int r, c, i;
for (i = 0; i < 16; i++)
@@ -43,7 +42,7 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
}
/* for Y */
- switch (x->mode_info_context->mbmi.mode)
+ switch (mode)
{
case DC_PRED:
{
@@ -70,11 +69,7 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
{
average += yleft_col[i];
}
-
}
-
-
-
shift = 3 + x->up_available + x->left_available;
expected_dc = (average + (1 << (shift - 1))) >> shift;
}
@@ -83,7 +78,11 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
expected_dc = 128;
}
- vpx_memset(ypred_ptr, expected_dc, 256);
+ for (r = 0; r < 16; r++)
+ {
+ vpx_memset(ypred_ptr, expected_dc, 16);
+ ypred_ptr += y_stride; /*16;*/
+ }
}
break;
case V_PRED:
@@ -96,7 +95,7 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
((int *)ypred_ptr)[1] = ((int *)yabove_row)[1];
((int *)ypred_ptr)[2] = ((int *)yabove_row)[2];
((int *)ypred_ptr)[3] = ((int *)yabove_row)[3];
- ypred_ptr += 16;
+ ypred_ptr += y_stride;
}
}
break;
@@ -107,7 +106,7 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
{
vpx_memset(ypred_ptr, yleft_col[r], 16);
- ypred_ptr += 16;
+ ypred_ptr += y_stride;
}
}
@@ -130,11 +129,14 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
ypred_ptr[c] = pred;
}
- ypred_ptr += 16;
+ ypred_ptr += y_stride;
}
}
break;
+#if CONIFG_I8X8
+ case I8X8_PRED:
+#endif
case B_PRED:
case NEARESTMV:
case NEARMV:
@@ -146,133 +148,41 @@ void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
}
}
-void vp8_build_intra_predictors_mby_s(MACROBLOCKD *x)
+void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
{
+ vp8_build_intra_predictors_mby_internal(x, x->predictor, 16,
+ x->mode_info_context->mbmi.mode);
+}
- unsigned char *yabove_row = x->dst.y_buffer - x->dst.y_stride;
- unsigned char yleft_col[16];
- unsigned char ytop_left = yabove_row[-1];
- unsigned char *ypred_ptr = x->predictor;
- int r, c, i;
-
- int y_stride = x->dst.y_stride;
- ypred_ptr = x->dst.y_buffer; /*x->predictor;*/
-
- for (i = 0; i < 16; i++)
- {
- yleft_col[i] = x->dst.y_buffer [i* x->dst.y_stride -1];
- }
-
- /* for Y */
- switch (x->mode_info_context->mbmi.mode)
- {
- case DC_PRED:
- {
- int expected_dc;
- int i;
- int shift;
- int average = 0;
-
-
- if (x->up_available || x->left_available)
- {
- if (x->up_available)
- {
- for (i = 0; i < 16; i++)
- {
- average += yabove_row[i];
- }
- }
-
- if (x->left_available)
- {
-
- for (i = 0; i < 16; i++)
- {
- average += yleft_col[i];
- }
-
- }
-
-
-
- shift = 3 + x->up_available + x->left_available;
- expected_dc = (average + (1 << (shift - 1))) >> shift;
- }
- else
- {
- expected_dc = 128;
- }
-
- /*vpx_memset(ypred_ptr, expected_dc, 256);*/
- for (r = 0; r < 16; r++)
- {
- vpx_memset(ypred_ptr, expected_dc, 16);
- ypred_ptr += y_stride; /*16;*/
- }
- }
- break;
- case V_PRED:
- {
-
- for (r = 0; r < 16; r++)
- {
-
- ((int *)ypred_ptr)[0] = ((int *)yabove_row)[0];
- ((int *)ypred_ptr)[1] = ((int *)yabove_row)[1];
- ((int *)ypred_ptr)[2] = ((int *)yabove_row)[2];
- ((int *)ypred_ptr)[3] = ((int *)yabove_row)[3];
- ypred_ptr += y_stride; /*16;*/
- }
- }
- break;
- case H_PRED:
- {
+void vp8_build_intra_predictors_mby_s(MACROBLOCKD *x)
+{
+ vp8_build_intra_predictors_mby_internal(x, x->dst.y_buffer, x->dst.y_stride,
+ x->mode_info_context->mbmi.mode);
+}
- for (r = 0; r < 16; r++)
- {
+#if CONFIG_COMP_INTRA_PRED
+void vp8_build_comp_intra_predictors_mby(MACROBLOCKD *x)
+{
+ unsigned char predictor[2][256];
+ int i;
- vpx_memset(ypred_ptr, yleft_col[r], 16);
- ypred_ptr += y_stride; /*16;*/
- }
+ vp8_build_intra_predictors_mby_internal(x, predictor[0], 16,
+ x->mode_info_context->mbmi.mode);
+ vp8_build_intra_predictors_mby_internal(x, predictor[1], 16,
+ x->mode_info_context->mbmi.second_mode);
- }
- break;
- case TM_PRED:
+ for (i = 0; i < 256; i++)
{
-
- for (r = 0; r < 16; r++)
- {
- for (c = 0; c < 16; c++)
- {
- int pred = yleft_col[r] + yabove_row[ c] - ytop_left;
-
- if (pred < 0)
- pred = 0;
-
- if (pred > 255)
- pred = 255;
-
- ypred_ptr[c] = pred;
- }
-
- ypred_ptr += y_stride; /*16;*/
- }
-
- }
- break;
- case B_PRED:
- case NEARESTMV:
- case NEARMV:
- case ZEROMV:
- case NEWMV:
- case SPLITMV:
- case MB_MODE_COUNT:
- break;
+ x->predictor[i] = (predictor[0][i] + predictor[1][i] + 1) >> 1;
}
}
+#endif
-void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
+void vp8_build_intra_predictors_mbuv_internal(MACROBLOCKD *x,
+ unsigned char *upred_ptr,
+ unsigned char *vpred_ptr,
+ int uv_stride,
+ int mode)
{
unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
unsigned char uleft_col[16];
@@ -280,8 +190,7 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
unsigned char vleft_col[20];
unsigned char vtop_left = vabove_row[-1];
- unsigned char *upred_ptr = &x->predictor[256];
- unsigned char *vpred_ptr = &x->predictor[320];
+
int i, j;
for (i = 0; i < 8; i++)
@@ -290,7 +199,7 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
}
- switch (x->mode_info_context->mbmi.uv_mode)
+ switch (mode)
{
case DC_PRED:
{
@@ -332,10 +241,15 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
}
- vpx_memset(upred_ptr, expected_udc, 64);
- vpx_memset(vpred_ptr, expected_vdc, 64);
-
-
+ /*vpx_memset(upred_ptr,expected_udc,64);*/
+ /*vpx_memset(vpred_ptr,expected_vdc,64);*/
+ for (i = 0; i < 8; i++)
+ {
+ vpx_memset(upred_ptr, expected_udc, 8);
+ vpx_memset(vpred_ptr, expected_vdc, 8);
+ upred_ptr += uv_stride; /*8;*/
+ vpred_ptr += uv_stride; /*8;*/
+ }
}
break;
case V_PRED:
@@ -346,8 +260,8 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
{
vpx_memcpy(upred_ptr, uabove_row, 8);
vpx_memcpy(vpred_ptr, vabove_row, 8);
- upred_ptr += 8;
- vpred_ptr += 8;
+ upred_ptr += uv_stride; /*8;*/
+ vpred_ptr += uv_stride; /*8;*/
}
}
@@ -360,8 +274,8 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
{
vpx_memset(upred_ptr, uleft_col[i], 8);
vpx_memset(vpred_ptr, vleft_col[i], 8);
- upred_ptr += 8;
- vpred_ptr += 8;
+ upred_ptr += uv_stride; /*8;*/
+ vpred_ptr += uv_stride; /*8;*/
}
}
@@ -393,8 +307,8 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
vpred_ptr[j] = predv;
}
- upred_ptr += 8;
- vpred_ptr += 8;
+ upred_ptr += uv_stride; /*8;*/
+ vpred_ptr += uv_stride; /*8;*/
}
}
@@ -410,147 +324,260 @@ void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
}
}
+void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
+{
+ vp8_build_intra_predictors_mbuv_internal(x,
+ &x->predictor[256],
+ &x->predictor[320],
+ 8,
+ x->mode_info_context->mbmi.uv_mode);
+}
+
void vp8_build_intra_predictors_mbuv_s(MACROBLOCKD *x)
{
- unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
- unsigned char uleft_col[16];
- unsigned char utop_left = uabove_row[-1];
- unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
- unsigned char vleft_col[20];
- unsigned char vtop_left = vabove_row[-1];
- unsigned char *upred_ptr = x->dst.u_buffer; /*&x->predictor[256];*/
- unsigned char *vpred_ptr = x->dst.v_buffer; /*&x->predictor[320];*/
- int uv_stride = x->dst.uv_stride;
+ vp8_build_intra_predictors_mbuv_internal(x,
+ x->dst.u_buffer,
+ x->dst.v_buffer,
+ x->dst.uv_stride,
+ x->mode_info_context->mbmi.uv_mode);
+}
- int i, j;
+#if CONFIG_COMP_INTRA_PRED
+void vp8_build_comp_intra_predictors_mbuv(MACROBLOCKD *x)
+{
+ unsigned char predictor[2][2][64];
+ int i;
- for (i = 0; i < 8; i++)
+ vp8_build_intra_predictors_mbuv_internal(x, predictor[0][0], predictor[1][0], 8,
+ x->mode_info_context->mbmi.uv_mode);
+ vp8_build_intra_predictors_mbuv_internal(x, predictor[0][1], predictor[1][1], 8,
+ x->mode_info_context->mbmi.second_uv_mode);
+ for (i = 0; i < 64; i++)
{
- uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1];
- vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
+ x->predictor[256 + i] = (predictor[0][0][i] + predictor[0][1][i] + 1) >> 1;
+ x->predictor[256 + 64 + i] = (predictor[1][0][i] + predictor[1][1][i] + 1) >> 1;
}
+}
+#endif
+
+void vp8_intra8x8_predict(BLOCKD *x,
+ int mode,
+ unsigned char *predictor)
+{
- switch (x->mode_info_context->mbmi.uv_mode)
+ unsigned char *yabove_row = *(x->base_dst) + x->dst - x->dst_stride;
+ unsigned char yleft_col[8];
+ unsigned char ytop_left = yabove_row[-1];
+ int r, c, i;
+
+ for (i = 0; i < 8; i++)
{
- case DC_PRED:
+ yleft_col[i] = (*(x->base_dst))[x->dst - 1 + i * x->dst_stride];
+ }
+ switch (mode)
{
- int expected_udc;
- int expected_vdc;
- int i;
- int shift;
- int Uaverage = 0;
- int Vaverage = 0;
-
- if (x->up_available)
+ case DC_PRED:
{
+ int expected_dc = 0;
+
for (i = 0; i < 8; i++)
{
- Uaverage += uabove_row[i];
- Vaverage += vabove_row[i];
+ expected_dc += yabove_row[i];
+ expected_dc += yleft_col[i];
}
- }
+ expected_dc = (expected_dc + 8) >> 4;
- if (x->left_available)
- {
- for (i = 0; i < 8; i++)
+ for (r = 0; r < 8; r++)
{
- Uaverage += uleft_col[i];
- Vaverage += vleft_col[i];
+ for (c = 0; c < 8; c++)
+ {
+ predictor[c] = expected_dc;
+ }
+ predictor += 16;
}
}
-
- if (!x->up_available && !x->left_available)
+ break;
+ case V_PRED:
{
- expected_udc = 128;
- expected_vdc = 128;
+ for (r = 0; r < 8; r++)
+ {
+ for (c = 0; c < 8; c++)
+ {
+
+ predictor[c] = yabove_row[c];
+ }
+ predictor += 16;
+ }
+
}
- else
+ break;
+ case H_PRED:
{
- shift = 2 + x->up_available + x->left_available;
- expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
- expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
+
+ for (r = 0; r < 8; r++)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ predictor[c] = yleft_col[r];
+ }
+ predictor += 16;
+ }
}
+ break;
+ case TM_PRED:
+ {
+ /* prediction similar to true_motion prediction */
+ for (r = 0; r < 8; r++)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ int pred = yabove_row[c] - ytop_left + yleft_col[r];
+ if (pred < 0)
+ pred = 0;
+ if (pred > 255)
+ pred = 255;
+ predictor[c] = pred;
+ }
- /*vpx_memset(upred_ptr,expected_udc,64);*/
- /*vpx_memset(vpred_ptr,expected_vdc,64);*/
- for (i = 0; i < 8; i++)
- {
- vpx_memset(upred_ptr, expected_udc, 8);
- vpx_memset(vpred_ptr, expected_vdc, 8);
- upred_ptr += uv_stride; /*8;*/
- vpred_ptr += uv_stride; /*8;*/
+ predictor += 16;
+ }
}
+ break;
}
- break;
- case V_PRED:
- {
- int i;
+}
- for (i = 0; i < 8; i++)
- {
- vpx_memcpy(upred_ptr, uabove_row, 8);
- vpx_memcpy(vpred_ptr, vabove_row, 8);
- upred_ptr += uv_stride; /*8;*/
- vpred_ptr += uv_stride; /*8;*/
- }
+#if CONFIG_COMP_INTRA_PRED
+void vp8_comp_intra8x8_predict(BLOCKD *x,
+ int mode, int second_mode,
+ unsigned char *out_predictor)
+{
+
+ unsigned char predictor[2][8*16];
+ int i, j;
- }
- break;
- case H_PRED:
- {
- int i;
+ vp8_intra8x8_predict(x, mode, predictor[0]);
+ vp8_intra8x8_predict(x, second_mode, predictor[1]);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8*16; i += 16)
+ {
+ for (j = i; j < i + 8; j++)
{
- vpx_memset(upred_ptr, uleft_col[i], 8);
- vpx_memset(vpred_ptr, vleft_col[i], 8);
- upred_ptr += uv_stride; /*8;*/
- vpred_ptr += uv_stride; /*8;*/
+ out_predictor[j] = (predictor[0][j] + predictor[1][j] + 1) >> 1;
}
}
+}
+#endif
- break;
- case TM_PRED:
+void vp8_intra_uv4x4_predict(BLOCKD *x,
+ int mode,
+ unsigned char *predictor)
+{
+
+ unsigned char *above_row = *(x->base_dst) + x->dst - x->dst_stride;
+ unsigned char left_col[4];
+ unsigned char top_left = above_row[-1];
+ int r, c, i;
+
+ for (i = 0; i < 4; i++)
{
- int i;
+ left_col[i] = (*(x->base_dst))[x->dst - 1 + i * x->dst_stride];
+ }
+ switch (mode)
+ {
+ case DC_PRED:
+ {
+ int expected_dc = 0;
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 4; i++)
+ {
+ expected_dc += above_row[i];
+ expected_dc += left_col[i];
+ }
+ expected_dc = (expected_dc + 4) >> 3;
+
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ predictor[c] = expected_dc;
+ }
+ predictor += 8;
+ }
+ }
+ break;
+ case V_PRED:
{
- for (j = 0; j < 8; j++)
+ for (r = 0; r < 4; r++)
{
- int predu = uleft_col[i] + uabove_row[j] - utop_left;
- int predv = vleft_col[i] + vabove_row[j] - vtop_left;
+ for (c = 0; c < 4; c++)
+ {
- if (predu < 0)
- predu = 0;
+ predictor[c] = above_row[c];
+ }
+ predictor += 8;
+ }
- if (predu > 255)
- predu = 255;
+ }
+ break;
+ case H_PRED:
+ {
- if (predv < 0)
- predv = 0;
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ predictor[c] = left_col[r];
+ }
+ predictor += 8;
+ }
+ }
+ break;
+ case TM_PRED:
+ {
+ /* prediction similar to true_motion prediction */
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ int pred = above_row[c] - top_left + left_col[r];
+ if (pred < 0)
+ pred = 0;
- if (predv > 255)
- predv = 255;
+ if (pred > 255)
+ pred = 255;
+ predictor[c] = pred;
+ }
- upred_ptr[j] = predu;
- vpred_ptr[j] = predv;
+ predictor += 8;
}
-
- upred_ptr += uv_stride; /*8;*/
- vpred_ptr += uv_stride; /*8;*/
}
-
- }
- break;
- case B_PRED:
- case NEARESTMV:
- case NEARMV:
- case ZEROMV:
- case NEWMV:
- case SPLITMV:
- case MB_MODE_COUNT:
break;
}
}
+
+#if CONFIG_COMP_INTRA_PRED
+void vp8_comp_intra_uv4x4_predict(BLOCKD *x,
+ int mode, int mode2,
+ unsigned char *out_predictor)
+{
+ unsigned char predictor[2][8*4];
+ int i, j;
+
+ vp8_intra_uv4x4_predict(x, mode, predictor[0]);
+ vp8_intra_uv4x4_predict(x, mode2, predictor[1]);
+
+ for (i = 0; i < 4*8; i += 8)
+ {
+ for (j = i; j < i + 4; j++)
+ {
+ out_predictor[j] = (predictor[0][j] + predictor[1][j] + 1) >> 1;
+ }
+ }
+}
+#endif
+
+/* TODO: try different ways of use Y-UV mode correlation
+ Current code assumes that a uv 4x4 block use same mode
+ as corresponding Y 8x8 area
+ */
diff --git a/vp8/common/reconintra4x4.c b/vp8/common/reconintra4x4.c
index 3841227e3..ab8be4815 100644
--- a/vp8/common/reconintra4x4.c
+++ b/vp8/common/reconintra4x4.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "recon.h"
#include "vpx_mem/vpx_mem.h"
#include "reconintra.h"
@@ -295,6 +295,28 @@ void vp8_intra4x4_predict(BLOCKD *x,
}
}
+
+#if CONFIG_COMP_INTRA_PRED
+void vp8_comp_intra4x4_predict(BLOCKD *x,
+ int b_mode, int b_mode2,
+ unsigned char *out_predictor)
+{
+ unsigned char predictor[2][4*16];
+ int i, j;
+
+ vp8_intra4x4_predict(x, b_mode, predictor[0]);
+ vp8_intra4x4_predict(x, b_mode2, predictor[1]);
+
+ for (i = 0; i < 16*4; i += 16)
+ {
+ for (j = i; j < i + 4; j++)
+ {
+ out_predictor[j] = (predictor[0][j] + predictor[1][j] + 1) >> 1;
+ }
+ }
+}
+#endif
+
/* copy 4 bytes from the above right down so that the 4x4 prediction modes using pixels above and
* to the right prediction have filled in pixels to use.
*/
diff --git a/vp8/common/rotate.h b/vp8/common/rotate.h
new file mode 100644
index 000000000..580f55279
--- /dev/null
+++ b/vp8/common/rotate.h
@@ -0,0 +1,2827 @@
+ // angle of -2.5 degrees
+ -1, 0, 14696, -1, 1, 11702, 0, 0, 24063, 0, 1, 15075, // 0, 0
+ -1, 1, 13787, -1, 2, 11164, 0, 1, 25366, 0, 2, 15219, // 0, 1
+ -1, 2, 12938, -1, 3, 10637, 0, 2, 26660, 0, 3, 15301, // 0, 2
+ -1, 3, 12159, -1, 4, 10135, 0, 3, 27912, 0, 4, 15330, // 0, 3
+ -1, 4, 11461, -1, 5, 9673, 0, 4, 29078, 0, 5, 15324, // 0, 4
+ -1, 5, 10855, -1, 6, 9265, 0, 5, 30105, 0, 6, 15311, // 0, 5
+ -1, 6, 10351, -1, 7, 8927, 0, 6, 30939, 0, 7, 15319, // 0, 6
+ -1, 7, 9959, -1, 8, 8669, 0, 7, 31532, 0, 8, 15376, // 0, 7
+ 0, 8, 31444, 0, 9, 15301, 1, 8, 10065, 1, 9, 8726, // 0, 8
+ 0, 9, 30876, 0, 10, 15193, 1, 9, 10482, 1, 10, 8985, // 0, 9
+ 0, 10, 30064, 0, 11, 15135, 1, 10, 11013, 1, 11, 9324, // 0,10
+ 0, 11, 29055, 0, 12, 15100, 1, 11, 11652, 1, 12, 9729, // 0,11
+ 0, 12, 27903, 0, 13, 15060, 1, 12, 12388, 1, 13, 10185, // 0,12
+ 0, 13, 26660, 0, 14, 14990, 1, 13, 13211, 1, 14, 10675, // 0,13
+ 0, 14, 25368, 0, 15, 14872, 1, 14, 14109, 1, 15, 11187, // 0,14
+ 0, 15, 24063, 0, 16, 14696, 1, 15, 15076, 1, 16, 11701, // 0,15
+ 0, 0, 14872, 0, 1, 11187, 1, 0, 25368, 1, 1, 14109, // 1, 0
+ 0, 1, 13853, 0, 2, 10644, 1, 1, 26893, 1, 2, 14146, // 1, 1
+ 0, 2, 12897, 0, 3, 10102, 1, 2, 28430, 1, 3, 14107, // 1, 2
+ 0, 3, 12014, 0, 4, 9575, 1, 3, 29938, 1, 4, 14009, // 1, 3
+ 0, 4, 11218, 0, 5, 9082, 1, 4, 31361, 1, 5, 13875, // 1, 4
+ 0, 5, 10528, 0, 6, 8645, 1, 5, 32624, 1, 6, 13739, // 1, 5
+ 0, 6, 9961, 0, 7, 8286, 1, 6, 33642, 1, 7, 13647, // 1, 6
+ 0, 7, 9534, 0, 8, 8024, 1, 7, 34340, 1, 8, 13638, // 1, 7
+ 1, 8, 34261, 1, 9, 13582, 2, 8, 9626, 2, 9, 8067, // 1, 8
+ 1, 9, 33585, 1, 10, 13548, 2, 9, 10074, 2, 10, 8329, // 1, 9
+ 1, 10, 32586, 1, 11, 13600, 2, 10, 10665, 2, 11, 8685, // 1,10
+ 1, 11, 31339, 1, 12, 13694, 2, 11, 11385, 2, 12, 9118, // 1,11
+ 1, 12, 29928, 1, 13, 13789, 2, 12, 12216, 2, 13, 9603, // 1,12
+ 1, 13, 28427, 1, 14, 13850, 2, 13, 13141, 2, 14, 10118, // 1,13
+ 1, 14, 26893, 1, 15, 13853, 2, 14, 14145, 2, 15, 10645, // 1,14
+ 1, 15, 25366, 1, 16, 13787, 2, 15, 15220, 2, 16, 11163, // 1,15
+ 1, 0, 14990, 1, 1, 10676, 2, 0, 26660, 2, 1, 13210, // 2, 0
+ 1, 1, 13850, 1, 2, 10119, 2, 1, 28427, 2, 2, 13140, // 2, 1
+ 1, 2, 12769, 1, 3, 9546, 2, 2, 30239, 2, 3, 12982, // 2, 2
+ 1, 3, 11760, 1, 4, 8976, 2, 3, 32052, 2, 4, 12748, // 2, 3
+ 1, 4, 10842, 1, 5, 8432, 2, 4, 33795, 2, 5, 12467, // 2, 4
+ 1, 5, 10041, 1, 6, 7943, 2, 5, 35364, 2, 6, 12188, // 2, 5
+ 1, 6, 9390, 1, 7, 7543, 2, 6, 36631, 2, 7, 11972, // 2, 6
+ 1, 7, 8918, 1, 8, 7266, 2, 7, 37470, 2, 8, 11882, // 2, 7
+ 2, 8, 37402, 2, 9, 11842, 3, 8, 8994, 3, 9, 7298, // 2, 8
+ 2, 9, 36582, 2, 10, 11897, 3, 9, 9484, 3, 10, 7573, // 2, 9
+ 2, 10, 35332, 2, 11, 12079, 3, 10, 10156, 3, 11, 7969, // 2,10
+ 2, 11, 33777, 2, 12, 12323, 3, 11, 10983, 3, 12, 8453, // 2,11
+ 2, 12, 32045, 2, 13, 12569, 3, 12, 11934, 3, 13, 8988, // 2,12
+ 2, 13, 30239, 2, 14, 12769, 3, 13, 12982, 3, 14, 9546, // 2,13
+ 2, 14, 28430, 2, 15, 12897, 3, 14, 14107, 3, 15, 10102, // 2,14
+ 2, 15, 26660, 2, 16, 12938, 3, 15, 15301, 3, 16, 10637, // 2,15
+ 2, 0, 15060, 2, 1, 10185, 3, 0, 27903, 3, 1, 12388, // 3, 0
+ 2, 1, 13789, 2, 2, 9603, 3, 1, 29928, 3, 2, 12216, // 3, 1
+ 2, 2, 12569, 2, 3, 8988, 3, 2, 32045, 3, 3, 11934, // 3, 2
+ 2, 3, 11411, 2, 4, 8358, 3, 3, 34213, 3, 4, 11554, // 3, 3
+ 2, 4, 10337, 2, 5, 7737, 3, 4, 36354, 3, 5, 11108, // 3, 4
+ 2, 5, 9388, 2, 6, 7165, 3, 5, 38330, 3, 6, 10653, // 3, 5
+ 2, 6, 8617, 2, 7, 6695, 3, 6, 39949, 3, 7, 10275, // 3, 6
+ 2, 7, 8082, 2, 8, 6381, 3, 7, 40994, 3, 8, 10079, // 3, 7
+ 3, 8, 40940, 3, 9, 10051, 4, 8, 8141, 4, 9, 6404, // 3, 8
+ 3, 9, 39912, 3, 10, 10221, 4, 9, 8690, 4, 10, 6713, // 3, 9
+ 3, 10, 38307, 3, 11, 10569, 4, 10, 9479, 4, 11, 7181, // 3,10
+ 3, 11, 36343, 3, 12, 10995, 4, 11, 10452, 4, 12, 7746, // 3,11
+ 3, 12, 34213, 3, 13, 11411, 4, 12, 11554, 4, 13, 8358, // 3,12
+ 3, 13, 32052, 3, 14, 11760, 4, 13, 12747, 4, 14, 8977, // 3,13
+ 3, 14, 29938, 3, 15, 12014, 4, 14, 14009, 4, 15, 9575, // 3,14
+ 3, 15, 27912, 3, 16, 12159, 4, 15, 15330, 4, 16, 10135, // 3,15
+ 3, 0, 15100, 3, 1, 9728, 4, 0, 29055, 4, 1, 11653, // 4, 0
+ 3, 1, 13694, 3, 2, 9118, 4, 1, 31339, 4, 2, 11385, // 4, 1
+ 3, 2, 12323, 3, 3, 8452, 4, 2, 33777, 4, 3, 10984, // 4, 2
+ 3, 3, 10995, 3, 4, 7746, 4, 3, 36343, 4, 4, 10452, // 4, 3
+ 3, 4, 9730, 3, 5, 7022, 4, 4, 38966, 4, 5, 9818, // 4, 4
+ 3, 5, 8578, 3, 6, 6328, 4, 5, 41487, 4, 6, 9143, // 4, 5
+ 3, 6, 7626, 3, 7, 5739, 4, 6, 43626, 4, 7, 8545, // 4, 6
+ 3, 7, 6987, 3, 8, 5354, 4, 7, 44999, 4, 8, 8196, // 4, 7
+ 4, 8, 44962, 4, 9, 8177, 5, 8, 7029, 5, 9, 5368, // 4, 8
+ 4, 9, 43602, 4, 10, 8507, 5, 9, 7678, 5, 10, 5749, // 4, 9
+ 4, 10, 41475, 4, 11, 9081, 5, 10, 8646, 5, 11, 6334, // 4,10
+ 4, 11, 38966, 4, 12, 9730, 5, 11, 9818, 5, 12, 7022, // 4,11
+ 4, 12, 36354, 4, 13, 10337, 5, 12, 11108, 5, 13, 7737, // 4,12
+ 4, 13, 33795, 4, 14, 10842, 5, 13, 12467, 5, 14, 8432, // 4,13
+ 4, 14, 31361, 4, 15, 11218, 5, 14, 13875, 5, 15, 9082, // 4,14
+ 4, 15, 29078, 4, 16, 11461, 5, 15, 15325, 5, 16, 9672, // 4,15
+ 4, 0, 15135, 4, 1, 9323, 5, 0, 30064, 5, 1, 11014, // 5, 0
+ 4, 1, 13600, 4, 2, 8685, 5, 1, 32586, 5, 2, 10665, // 5, 1
+ 4, 2, 12079, 4, 3, 7969, 5, 2, 35332, 5, 3, 10156, // 5, 2
+ 4, 3, 10569, 4, 4, 7180, 5, 3, 38307, 5, 4, 9480, // 5, 3
+ 4, 4, 9081, 4, 5, 6334, 5, 4, 41475, 5, 5, 8646, // 5, 4
+ 4, 5, 7659, 4, 6, 5472, 5, 5, 44700, 5, 6, 7705, // 5, 5
+ 4, 6, 6422, 4, 7, 4690, 5, 6, 47630, 5, 7, 6794, // 5, 6
+ 4, 7, 5590, 4, 8, 4164, 5, 7, 49588, 5, 8, 6194, // 5, 7
+ 5, 8, 49566, 5, 9, 6183, 6, 8, 5615, 6, 9, 4172, // 5, 8
+ 5, 9, 47619, 5, 10, 6768, 6, 9, 6455, 6, 10, 4694, // 5, 9
+ 5, 10, 44700, 5, 11, 7659, 6, 10, 7705, 6, 11, 5472, // 5,10
+ 5, 11, 41487, 5, 12, 8578, 6, 11, 9143, 6, 12, 6328, // 5,11
+ 5, 12, 38330, 5, 13, 9388, 6, 12, 10653, 6, 13, 7165, // 5,12
+ 5, 13, 35364, 5, 14, 10041, 6, 13, 12188, 6, 14, 7943, // 5,13
+ 5, 14, 32624, 5, 15, 10528, 6, 14, 13740, 6, 15, 8644, // 5,14
+ 5, 15, 30105, 5, 16, 10855, 6, 15, 15311, 6, 16, 9265, // 5,15
+ 5, 0, 15193, 5, 1, 8986, 6, 0, 30876, 6, 1, 10481, // 6, 0
+ 5, 1, 13548, 5, 2, 8329, 6, 1, 33585, 6, 2, 10074, // 6, 1
+ 5, 2, 11897, 5, 3, 7573, 6, 2, 36582, 6, 3, 9484, // 6, 2
+ 5, 3, 10221, 5, 4, 6714, 6, 3, 39912, 6, 4, 8689, // 6, 3
+ 5, 4, 8507, 5, 5, 5749, 6, 4, 43602, 6, 5, 7678, // 6, 4
+ 5, 5, 6768, 5, 6, 4694, 6, 5, 47619, 6, 6, 6455, // 6, 5
+ 5, 6, 5099, 5, 7, 3620, 6, 6, 51701, 6, 7, 5116, // 6, 6
+ 5, 7, 3853, 5, 8, 2795, 6, 7, 54839, 6, 8, 4049, // 6, 7
+ 6, 8, 54831, 6, 9, 4044, 7, 8, 3864, 7, 9, 2797, // 6, 8
+ 6, 9, 51701, 6, 10, 5099, 7, 9, 5116, 7, 10, 3620, // 6, 9
+ 6, 10, 47630, 6, 11, 6422, 7, 10, 6794, 7, 11, 4690, // 6,10
+ 6, 11, 43626, 6, 12, 7626, 7, 11, 8545, 7, 12, 5739, // 6,11
+ 6, 12, 39949, 6, 13, 8617, 7, 12, 10275, 7, 13, 6695, // 6,12
+ 6, 13, 36631, 6, 14, 9390, 7, 13, 11972, 7, 14, 7543, // 6,13
+ 6, 14, 33642, 6, 15, 9961, 7, 14, 13647, 7, 15, 8286, // 6,14
+ 6, 15, 30939, 6, 16, 10351, 7, 15, 15319, 7, 16, 8927, // 6,15
+ 6, 0, 15301, 6, 1, 8727, 7, 0, 31444, 7, 1, 10064, // 7, 0
+ 6, 1, 13582, 6, 2, 8068, 7, 1, 34261, 7, 2, 9625, // 7, 1
+ 6, 2, 11842, 6, 3, 7298, 7, 2, 37402, 7, 3, 8994, // 7, 2
+ 6, 3, 10051, 6, 4, 6403, 7, 3, 40940, 7, 4, 8142, // 7, 3
+ 6, 4, 8177, 6, 5, 5368, 7, 4, 44962, 7, 5, 7029, // 7, 4
+ 6, 5, 6183, 6, 6, 4172, 7, 5, 49566, 7, 6, 5615, // 7, 5
+ 6, 6, 4044, 6, 7, 2797, 7, 6, 54831, 7, 7, 3864, // 7, 6
+ 6, 7, 1903, 6, 8, 1347, 7, 7, 60382, 7, 8, 1904, // 7, 7
+ 7, 8, 60382, 7, 9, 1903, 8, 8, 1905, 8, 9, 1346, // 7, 8
+ 7, 9, 54839, 7, 10, 3853, 8, 9, 4049, 8, 10, 2795, // 7, 9
+ 7, 10, 49588, 7, 11, 5590, 8, 10, 6193, 8, 11, 4165, // 7,10
+ 7, 11, 44999, 7, 12, 6987, 8, 11, 8195, 8, 12, 5355, // 7,11
+ 7, 12, 40994, 7, 13, 8082, 8, 12, 10079, 8, 13, 6381, // 7,12
+ 7, 13, 37470, 7, 14, 8918, 8, 13, 11883, 8, 14, 7265, // 7,13
+ 7, 14, 34340, 7, 15, 9534, 8, 14, 13638, 8, 15, 8024, // 7,14
+ 7, 15, 31532, 7, 16, 9959, 8, 15, 15376, 8, 16, 8669, // 7,15
+ 7, -1, 8669, 7, 0, 15376, 8, -1, 9959, 8, 0, 31532, // 8, 0
+ 7, 0, 8024, 7, 1, 13638, 8, 0, 9534, 8, 1, 34340, // 8, 1
+ 7, 1, 7266, 7, 2, 11883, 8, 1, 8918, 8, 2, 37469, // 8, 2
+ 7, 2, 6381, 7, 3, 10079, 8, 2, 8082, 8, 3, 40994, // 8, 3
+ 7, 3, 5354, 7, 4, 8195, 8, 3, 6987, 8, 4, 45000, // 8, 4
+ 7, 4, 4164, 7, 5, 6193, 8, 4, 5590, 8, 5, 49589, // 8, 5
+ 7, 5, 2795, 7, 6, 4049, 8, 5, 3853, 8, 6, 54839, // 8, 6
+ 7, 6, 1347, 7, 7, 1905, 8, 6, 1903, 8, 7, 60381, // 8, 7
+ 8, 7, 1905, 8, 8, 60382, 9, 7, 1347, 9, 8, 1902, // 8, 8
+ 8, 8, 3864, 8, 9, 54831, 9, 8, 2797, 9, 9, 4044, // 8, 9
+ 8, 9, 5615, 8, 10, 49566, 9, 9, 4172, 9, 10, 6183, // 8,10
+ 8, 10, 7029, 8, 11, 44962, 9, 10, 5368, 9, 11, 8177, // 8,11
+ 8, 11, 8141, 8, 12, 40940, 9, 11, 6403, 9, 12, 10052, // 8,12
+ 8, 12, 8994, 8, 13, 37402, 9, 12, 7298, 9, 13, 11842, // 8,13
+ 8, 13, 9626, 8, 14, 34261, 9, 13, 8068, 9, 14, 13581, // 8,14
+ 8, 14, 10065, 8, 15, 31444, 9, 14, 8727, 9, 15, 15300, // 8,15
+ 8, -1, 8927, 8, 0, 15319, 9, -1, 10351, 9, 0, 30939, // 9, 0
+ 8, 0, 8286, 8, 1, 13647, 9, 0, 9961, 9, 1, 33642, // 9, 1
+ 8, 1, 7543, 8, 2, 11972, 9, 1, 9390, 9, 2, 36631, // 9, 2
+ 8, 2, 6695, 8, 3, 10275, 9, 2, 8617, 9, 3, 39949, // 9, 3
+ 8, 3, 5739, 8, 4, 8545, 9, 3, 7626, 9, 4, 43626, // 9, 4
+ 8, 4, 4690, 8, 5, 6794, 9, 4, 6422, 9, 5, 47630, // 9, 5
+ 8, 5, 3620, 8, 6, 5116, 9, 5, 5099, 9, 6, 51701, // 9, 6
+ 8, 6, 2797, 8, 7, 3864, 9, 6, 4044, 9, 7, 54831, // 9, 7
+ 9, 7, 4049, 9, 8, 54839, 10, 7, 2795, 10, 8, 3853, // 9, 8
+ 9, 8, 5116, 9, 9, 51701, 10, 8, 3620, 10, 9, 5099, // 9, 9
+ 9, 9, 6455, 9, 10, 47619, 10, 9, 4694, 10, 10, 6768, // 9,10
+ 9, 10, 7678, 9, 11, 43602, 10, 10, 5749, 10, 11, 8507, // 9,11
+ 9, 11, 8690, 9, 12, 39912, 10, 11, 6714, 10, 12, 10220, // 9,12
+ 9, 12, 9484, 9, 13, 36582, 10, 12, 7573, 10, 13, 11897, // 9,13
+ 9, 13, 10074, 9, 14, 33585, 10, 13, 8329, 10, 14, 13548, // 9,14
+ 9, 14, 10482, 9, 15, 30876, 10, 14, 8986, 10, 15, 15192, // 9,15
+ 9, -1, 9265, 9, 0, 15311, 10, -1, 10855, 10, 0, 30105, // 10, 0
+ 9, 0, 8645, 9, 1, 13740, 10, 0, 10528, 10, 1, 32623, // 10, 1
+ 9, 1, 7943, 9, 2, 12188, 10, 1, 10041, 10, 2, 35364, // 10, 2
+ 9, 2, 7165, 9, 3, 10653, 10, 2, 9388, 10, 3, 38330, // 10, 3
+ 9, 3, 6328, 9, 4, 9143, 10, 3, 8578, 10, 4, 41487, // 10, 4
+ 9, 4, 5472, 9, 5, 7705, 10, 4, 7659, 10, 5, 44700, // 10, 5
+ 9, 5, 4694, 9, 6, 6455, 10, 5, 6768, 10, 6, 47619, // 10, 6
+ 9, 6, 4172, 9, 7, 5615, 10, 6, 6183, 10, 7, 49566, // 10, 7
+ 10, 7, 6193, 10, 8, 49588, 11, 7, 4164, 11, 8, 5591, // 10, 8
+ 10, 8, 6794, 10, 9, 47630, 11, 8, 4690, 11, 9, 6422, // 10, 9
+ 10, 9, 7705, 10, 10, 44700, 11, 9, 5472, 11, 10, 7659, // 10,10
+ 10, 10, 8646, 10, 11, 41475, 11, 10, 6334, 11, 11, 9081, // 10,11
+ 10, 11, 9479, 10, 12, 38307, 11, 11, 7180, 11, 12, 10570, // 10,12
+ 10, 12, 10156, 10, 13, 35332, 11, 12, 7969, 11, 13, 12079, // 10,13
+ 10, 13, 10665, 10, 14, 32586, 11, 13, 8685, 11, 14, 13600, // 10,14
+ 10, 14, 11013, 10, 15, 30064, 11, 14, 9323, 11, 15, 15136, // 10,15
+ 10, -1, 9673, 10, 0, 15325, 11, -1, 11461, 11, 0, 29077, // 11, 0
+ 10, 0, 9082, 10, 1, 13875, 11, 0, 11218, 11, 1, 31361, // 11, 1
+ 10, 1, 8432, 10, 2, 12467, 11, 1, 10842, 11, 2, 33795, // 11, 2
+ 10, 2, 7737, 10, 3, 11108, 11, 2, 10337, 11, 3, 36354, // 11, 3
+ 10, 3, 7022, 10, 4, 9818, 11, 3, 9730, 11, 4, 38966, // 11, 4
+ 10, 4, 6334, 10, 5, 8646, 11, 4, 9081, 11, 5, 41475, // 11, 5
+ 10, 5, 5749, 10, 6, 7678, 11, 5, 8507, 11, 6, 43602, // 11, 6
+ 10, 6, 5368, 10, 7, 7029, 11, 6, 8177, 11, 7, 44962, // 11, 7
+ 11, 7, 8195, 11, 8, 44999, 12, 7, 5354, 12, 8, 6988, // 11, 8
+ 11, 8, 8545, 11, 9, 43626, 12, 8, 5739, 12, 9, 7626, // 11, 9
+ 11, 9, 9143, 11, 10, 41487, 12, 9, 6328, 12, 10, 8578, // 11,10
+ 11, 10, 9818, 11, 11, 38966, 12, 10, 7022, 12, 11, 9730, // 11,11
+ 11, 11, 10452, 11, 12, 36343, 12, 11, 7746, 12, 12, 10995, // 11,12
+ 11, 12, 10983, 11, 13, 33777, 12, 12, 8452, 12, 13, 12324, // 11,13
+ 11, 13, 11385, 11, 14, 31339, 12, 13, 9118, 12, 14, 13694, // 11,14
+ 11, 14, 11652, 11, 15, 29055, 12, 14, 9728, 12, 15, 15101, // 11,15
+ 11, -1, 10135, 11, 0, 15330, 12, -1, 12159, 12, 0, 27912, // 12, 0
+ 11, 0, 9575, 11, 1, 14009, 12, 0, 12014, 12, 1, 29938, // 12, 1
+ 11, 1, 8976, 11, 2, 12747, 12, 1, 11760, 12, 2, 32053, // 12, 2
+ 11, 2, 8358, 11, 3, 11554, 12, 2, 11411, 12, 3, 34213, // 12, 3
+ 11, 3, 7746, 11, 4, 10452, 12, 3, 10995, 12, 4, 36343, // 12, 4
+ 11, 4, 7180, 11, 5, 9479, 12, 4, 10569, 12, 5, 38308, // 12, 5
+ 11, 5, 6714, 11, 6, 8690, 12, 5, 10221, 12, 6, 39911, // 12, 6
+ 11, 6, 6403, 11, 7, 8141, 12, 6, 10051, 12, 7, 40941, // 12, 7
+ 12, 7, 10079, 12, 8, 40994, 13, 7, 6381, 13, 8, 8082, // 12, 8
+ 12, 8, 10275, 12, 9, 39949, 13, 8, 6695, 13, 9, 8617, // 12, 9
+ 12, 9, 10653, 12, 10, 38330, 13, 9, 7165, 13, 10, 9388, // 12,10
+ 12, 10, 11108, 12, 11, 36354, 13, 10, 7737, 13, 11, 10337, // 12,11
+ 12, 11, 11554, 12, 12, 34213, 13, 11, 8358, 13, 12, 11411, // 12,12
+ 12, 12, 11934, 12, 13, 32045, 13, 12, 8988, 13, 13, 12569, // 12,13
+ 12, 13, 12216, 12, 14, 29928, 13, 13, 9603, 13, 14, 13789, // 12,14
+ 12, 14, 12388, 12, 15, 27903, 13, 14, 10185, 13, 15, 15060, // 12,15
+ 12, -1, 10637, 12, 0, 15301, 13, -1, 12938, 13, 0, 26660, // 13, 0
+ 12, 0, 10102, 12, 1, 14107, 13, 0, 12897, 13, 1, 28430, // 13, 1
+ 12, 1, 9546, 12, 2, 12982, 13, 1, 12769, 13, 2, 30239, // 13, 2
+ 12, 2, 8988, 12, 3, 11934, 13, 2, 12569, 13, 3, 32045, // 13, 3
+ 12, 3, 8452, 12, 4, 10983, 13, 3, 12323, 13, 4, 33778, // 13, 4
+ 12, 4, 7969, 12, 5, 10156, 13, 4, 12079, 13, 5, 35332, // 13, 5
+ 12, 5, 7573, 12, 6, 9484, 13, 5, 11897, 13, 6, 36582, // 13, 6
+ 12, 6, 7298, 12, 7, 8994, 13, 6, 11842, 13, 7, 37402, // 13, 7
+ 13, 7, 11883, 13, 8, 37470, 14, 7, 7266, 14, 8, 8917, // 13, 8
+ 13, 8, 11972, 13, 9, 36631, 14, 8, 7543, 14, 9, 9390, // 13, 9
+ 13, 9, 12188, 13, 10, 35364, 14, 9, 7943, 14, 10, 10041, // 13,10
+ 13, 10, 12467, 13, 11, 33795, 14, 10, 8432, 14, 11, 10842, // 13,11
+ 13, 11, 12747, 13, 12, 32052, 14, 11, 8976, 14, 12, 11761, // 13,12
+ 13, 12, 12982, 13, 13, 30239, 14, 12, 9546, 14, 13, 12769, // 13,13
+ 13, 13, 13141, 13, 14, 28427, 14, 13, 10119, 14, 14, 13849, // 13,14
+ 13, 14, 13211, 13, 15, 26660, 14, 14, 10676, 14, 15, 14989, // 13,15
+ 13, -1, 11164, 13, 0, 15220, 14, -1, 13787, 14, 0, 25365, // 14, 0
+ 13, 0, 10644, 13, 1, 14145, 14, 0, 13853, 14, 1, 26894, // 14, 1
+ 13, 1, 10119, 13, 2, 13141, 14, 1, 13850, 14, 2, 28426, // 14, 2
+ 13, 2, 9603, 13, 3, 12216, 14, 2, 13789, 14, 3, 29928, // 14, 3
+ 13, 3, 9118, 13, 4, 11385, 14, 3, 13694, 14, 4, 31339, // 14, 4
+ 13, 4, 8685, 13, 5, 10665, 14, 4, 13600, 14, 5, 32586, // 14, 5
+ 13, 5, 8329, 13, 6, 10074, 14, 5, 13548, 14, 6, 33585, // 14, 6
+ 13, 6, 8068, 13, 7, 9626, 14, 6, 13582, 14, 7, 34260, // 14, 7
+ 14, 7, 13638, 14, 8, 34340, 15, 7, 8024, 15, 8, 9534, // 14, 8
+ 14, 8, 13647, 14, 9, 33642, 15, 8, 8286, 15, 9, 9961, // 14, 9
+ 14, 9, 13740, 14, 10, 32624, 15, 9, 8645, 15, 10, 10527, // 14,10
+ 14, 10, 13875, 14, 11, 31361, 15, 10, 9082, 15, 11, 11218, // 14,11
+ 14, 11, 14009, 14, 12, 29938, 15, 11, 9575, 15, 12, 12014, // 14,12
+ 14, 12, 14107, 14, 13, 28430, 15, 12, 10102, 15, 13, 12897, // 14,13
+ 14, 13, 14145, 14, 14, 26893, 15, 13, 10644, 15, 14, 13854, // 14,14
+ 14, 14, 14109, 14, 15, 25368, 15, 14, 11187, 15, 15, 14872, // 14,15
+ 14, -1, 11702, 14, 0, 15076, 15, -1, 14696, 15, 0, 24062, // 15, 0
+ 14, 0, 11187, 14, 1, 14109, 15, 0, 14872, 15, 1, 25368, // 15, 1
+ 14, 1, 10676, 14, 2, 13211, 15, 1, 14990, 15, 2, 26659, // 15, 2
+ 14, 2, 10185, 14, 3, 12388, 15, 2, 15060, 15, 3, 27903, // 15, 3
+ 14, 3, 9728, 14, 4, 11652, 15, 3, 15100, 15, 4, 29056, // 15, 4
+ 14, 4, 9323, 14, 5, 11013, 15, 4, 15135, 15, 5, 30065, // 15, 5
+ 14, 5, 8986, 14, 6, 10482, 15, 5, 15193, 15, 6, 30875, // 15, 6
+ 14, 6, 8727, 14, 7, 10065, 15, 6, 15301, 15, 7, 31443, // 15, 7
+ 15, 7, 15376, 15, 8, 31532, 16, 7, 8669, 16, 8, 9959, // 15, 8
+ 15, 8, 15319, 15, 9, 30939, 16, 8, 8927, 16, 9, 10351, // 15, 9
+ 15, 9, 15311, 15, 10, 30105, 16, 9, 9265, 16, 10, 10855, // 15,10
+ 15, 10, 15325, 15, 11, 29078, 16, 10, 9673, 16, 11, 11460, // 15,11
+ 15, 11, 15330, 15, 12, 27912, 16, 11, 10135, 16, 12, 12159, // 15,12
+ 15, 12, 15301, 15, 13, 26660, 16, 12, 10637, 16, 13, 12938, // 15,13
+ 15, 13, 15220, 15, 14, 25366, 16, 13, 11164, 16, 14, 13786, // 15,14
+ 15, 14, 15076, 15, 15, 24063, 16, 14, 11702, 16, 15, 14695, // 15,15
+ // angle of -2.0 degrees
+ -1, 0, 13368, -1, 1, 10104, 0, 0, 28495, 0, 1, 13569, // 0, 0
+ -1, 1, 12574, -1, 2, 9662, 0, 1, 29831, 0, 2, 13469, // 0, 1
+ -1, 2, 11829, -1, 3, 9229, 0, 2, 31146, 0, 3, 13332, // 0, 2
+ -1, 3, 11143, -1, 4, 8816, 0, 3, 32406, 0, 4, 13171, // 0, 3
+ -1, 4, 10528, -1, 5, 8438, 0, 4, 33564, 0, 5, 13006, // 0, 4
+ -1, 5, 9995, -1, 6, 8107, 0, 5, 34567, 0, 6, 12867, // 0, 5
+ -1, 6, 9558, -1, 7, 7839, 0, 6, 35362, 0, 7, 12777, // 0, 6
+ -1, 7, 9224, -1, 8, 7643, 0, 7, 35905, 0, 8, 12764, // 0, 7
+ 0, 8, 35844, 0, 9, 12728, 1, 8, 9290, 1, 9, 7674, // 0, 8
+ 0, 9, 35315, 0, 10, 12717, 1, 9, 9635, 1, 10, 7869, // 0, 9
+ 0, 10, 34532, 0, 11, 12783, 1, 10, 10086, 1, 11, 8135, // 0,10
+ 0, 11, 33539, 0, 12, 12899, 1, 11, 10635, 1, 12, 8463, // 0,11
+ 0, 12, 32391, 0, 13, 13038, 1, 12, 11269, 1, 13, 8838, // 0,12
+ 0, 13, 31138, 0, 14, 13176, 1, 13, 11977, 1, 14, 9245, // 0,13
+ 0, 14, 29828, 0, 15, 13291, 1, 14, 12746, 1, 15, 9671, // 0,14
+ 0, 15, 28495, 0, 16, 13368, 1, 15, 13569, 1, 16, 10104, // 0,15
+ 0, 0, 13291, 0, 1, 9671, 1, 0, 29828, 1, 1, 12746, // 1, 0
+ 0, 1, 12412, 0, 2, 9202, 1, 1, 31358, 1, 2, 12564, // 1, 1
+ 0, 2, 11580, 0, 3, 8735, 1, 2, 32886, 1, 3, 12335, // 1, 2
+ 0, 3, 10808, 0, 4, 8284, 1, 3, 34369, 1, 4, 12075, // 1, 3
+ 0, 4, 10111, 0, 5, 7865, 1, 4, 35750, 1, 5, 11810, // 1, 4
+ 0, 5, 9509, 0, 6, 7497, 1, 5, 36955, 1, 6, 11575, // 1, 5
+ 0, 6, 9020, 0, 7, 7202, 1, 6, 37906, 1, 7, 11408, // 1, 6
+ 0, 7, 8662, 0, 8, 6997, 1, 7, 38534, 1, 8, 11343, // 1, 7
+ 1, 8, 38481, 1, 9, 11317, 2, 8, 8718, 2, 9, 7020, // 1, 8
+ 1, 9, 37866, 1, 10, 11360, 2, 9, 9086, 2, 10, 7224, // 1, 9
+ 1, 10, 36926, 1, 11, 11507, 2, 10, 9587, 2, 11, 7516, // 1,10
+ 1, 11, 35730, 1, 12, 11721, 2, 11, 10204, 2, 12, 7881, // 1,11
+ 1, 12, 34358, 1, 13, 11964, 2, 12, 10918, 2, 13, 8296, // 1,12
+ 1, 13, 32881, 1, 14, 12203, 2, 13, 11709, 2, 14, 8743, // 1,13
+ 1, 14, 31358, 1, 15, 12412, 2, 14, 12564, 2, 15, 9202, // 1,14
+ 1, 15, 29831, 1, 16, 12574, 2, 15, 13470, 2, 16, 9661, // 1,15
+ 1, 0, 13176, 1, 1, 9245, 2, 0, 31138, 2, 1, 11977, // 2, 0
+ 1, 1, 12203, 1, 2, 8742, 2, 1, 32881, 2, 2, 11710, // 2, 1
+ 1, 2, 11272, 1, 3, 8232, 2, 2, 34650, 2, 3, 11382, // 2, 2
+ 1, 3, 10397, 1, 4, 7728, 2, 3, 36399, 2, 4, 11012, // 2, 3
+ 1, 4, 9597, 1, 5, 7252, 2, 4, 38057, 2, 5, 10630, // 2, 4
+ 1, 5, 8902, 1, 6, 6829, 2, 5, 39526, 2, 6, 10279, // 2, 5
+ 1, 6, 8344, 1, 7, 6491, 2, 6, 40688, 2, 7, 10013, // 2, 6
+ 1, 7, 7951, 1, 8, 6266, 2, 7, 41432, 2, 8, 9887, // 2, 7
+ 2, 8, 41389, 2, 9, 9867, 3, 8, 7996, 3, 9, 6284, // 2, 8
+ 2, 9, 40656, 2, 10, 9977, 3, 9, 8397, 3, 10, 6506, // 2, 9
+ 2, 10, 39503, 2, 11, 10226, 3, 10, 8966, 3, 11, 6841, // 2,10
+ 2, 11, 38042, 2, 12, 10559, 3, 11, 9674, 3, 12, 7261, // 2,11
+ 2, 12, 36392, 2, 13, 10922, 3, 12, 10488, 3, 13, 7734, // 2,12
+ 2, 13, 34650, 2, 14, 11272, 3, 13, 11382, 3, 14, 8232, // 2,13
+ 2, 14, 32886, 2, 15, 11580, 3, 14, 12334, 3, 15, 8736, // 2,14
+ 2, 15, 31146, 2, 16, 11829, 3, 15, 13332, 3, 16, 9229, // 2,15
+ 2, 0, 13038, 2, 1, 8838, 3, 0, 32391, 3, 1, 11269, // 3, 0
+ 2, 1, 11964, 2, 2, 8296, 3, 1, 34358, 3, 2, 10918, // 3, 1
+ 2, 2, 10922, 2, 3, 7734, 3, 2, 36392, 3, 3, 10488, // 3, 2
+ 2, 3, 9924, 2, 4, 7164, 3, 3, 38450, 3, 4, 9998, // 3, 3
+ 2, 4, 8995, 2, 5, 6611, 3, 4, 40452, 3, 5, 9478, // 3, 4
+ 2, 5, 8175, 2, 6, 6108, 3, 5, 42271, 3, 6, 8982, // 3, 5
+ 2, 6, 7516, 2, 7, 5703, 3, 6, 43733, 3, 7, 8584, // 3, 6
+ 2, 7, 7072, 2, 8, 5443, 3, 7, 44649, 3, 8, 8372, // 3, 7
+ 3, 8, 44616, 3, 9, 8359, 4, 8, 7106, 4, 9, 5455, // 3, 8
+ 3, 9, 43710, 3, 10, 8558, 4, 9, 7556, 4, 10, 5712, // 3, 9
+ 3, 10, 42256, 3, 11, 8940, 4, 10, 8224, 4, 11, 6116, // 3,10
+ 3, 11, 40444, 3, 12, 9421, 4, 11, 9056, 4, 12, 6615, // 3,11
+ 3, 12, 38450, 3, 13, 9924, 4, 12, 9998, 4, 13, 7164, // 3,12
+ 3, 13, 36399, 3, 14, 10397, 4, 13, 11012, 4, 14, 7728, // 3,13
+ 3, 14, 34369, 3, 15, 10808, 4, 14, 12074, 4, 15, 8285, // 3,14
+ 3, 15, 32406, 3, 16, 11143, 4, 15, 13171, 4, 16, 8816, // 3,15
+ 3, 0, 12899, 3, 1, 8463, 4, 0, 33539, 4, 1, 10635, // 4, 0
+ 3, 1, 11721, 3, 2, 7881, 4, 1, 35730, 4, 2, 10204, // 4, 1
+ 3, 2, 10559, 3, 3, 7261, 4, 2, 38042, 4, 3, 9674, // 4, 2
+ 3, 3, 9421, 3, 4, 6615, 4, 3, 40444, 4, 4, 9056, // 4, 3
+ 3, 4, 8332, 3, 5, 5965, 4, 4, 42861, 4, 5, 8378, // 4, 4
+ 3, 5, 7342, 3, 6, 5350, 4, 5, 45146, 4, 6, 7698, // 4, 5
+ 3, 6, 6530, 3, 7, 4838, 4, 6, 47049, 4, 7, 7119, // 4, 6
+ 3, 7, 6000, 3, 8, 4513, 4, 7, 48240, 4, 8, 6783, // 4, 7
+ 4, 8, 48218, 4, 9, 6774, 5, 8, 6023, 5, 9, 4521, // 4, 8
+ 4, 9, 47035, 4, 10, 7100, 5, 9, 6558, 5, 10, 4843, // 4, 9
+ 4, 10, 45139, 4, 11, 7667, 5, 10, 7377, 5, 11, 5353, // 4,10
+ 4, 11, 42861, 4, 12, 8332, 5, 11, 8378, 5, 12, 5965, // 4,11
+ 4, 12, 40452, 4, 13, 8995, 5, 12, 9478, 5, 13, 6611, // 4,12
+ 4, 13, 38057, 4, 14, 9597, 5, 13, 10630, 5, 14, 7252, // 4,13
+ 4, 14, 35750, 4, 15, 10111, 5, 14, 11810, 5, 15, 7865, // 4,14
+ 4, 15, 33564, 4, 16, 10528, 5, 15, 13007, 5, 16, 8437, // 4,15
+ 4, 0, 12783, 4, 1, 8135, 5, 0, 34532, 5, 1, 10086, // 5, 0
+ 4, 1, 11507, 4, 2, 7517, 5, 1, 36926, 5, 2, 9586, // 5, 1
+ 4, 2, 10226, 4, 3, 6842, 5, 2, 39503, 5, 3, 8965, // 5, 2
+ 4, 3, 8940, 4, 4, 6116, 5, 3, 42256, 5, 4, 8224, // 5, 3
+ 4, 4, 7667, 4, 5, 5353, 5, 4, 45139, 5, 5, 7377, // 5, 4
+ 4, 5, 6451, 4, 6, 4591, 5, 5, 48019, 5, 6, 6475, // 5, 5
+ 4, 6, 5400, 4, 7, 3911, 5, 6, 50587, 5, 7, 5638, // 5, 6
+ 4, 7, 4708, 4, 8, 3466, 5, 7, 52266, 5, 8, 5096, // 5, 7
+ 5, 8, 52253, 5, 9, 5092, 6, 8, 4721, 6, 9, 3470, // 5, 8
+ 5, 9, 50581, 5, 10, 5624, 6, 9, 5418, 6, 10, 3913, // 5, 9
+ 5, 10, 48019, 5, 11, 6451, 6, 10, 6475, 6, 11, 4591, // 5,10
+ 5, 11, 45146, 5, 12, 7342, 6, 11, 7698, 6, 12, 5350, // 5,11
+ 5, 12, 42271, 5, 13, 8175, 6, 12, 8982, 6, 13, 6108, // 5,12
+ 5, 13, 39526, 5, 14, 8902, 6, 13, 10279, 6, 14, 6829, // 5,13
+ 5, 14, 36955, 5, 15, 9509, 6, 14, 11575, 6, 15, 7497, // 5,14
+ 5, 15, 34567, 5, 16, 9995, 6, 15, 12867, 6, 16, 8107, // 5,15
+ 5, 0, 12717, 5, 1, 7868, 6, 0, 35315, 6, 1, 9636, // 6, 0
+ 5, 1, 11360, 5, 2, 7224, 6, 1, 37866, 6, 2, 9086, // 6, 1
+ 5, 2, 9977, 5, 3, 6506, 6, 2, 40656, 6, 3, 8397, // 6, 2
+ 5, 3, 8558, 5, 4, 5712, 6, 3, 43710, 6, 4, 7556, // 6, 3
+ 5, 4, 7100, 5, 5, 4843, 6, 4, 47035, 6, 5, 6558, // 6, 4
+ 5, 5, 5624, 5, 6, 3913, 6, 5, 50581, 6, 6, 5418, // 6, 5
+ 5, 6, 4217, 5, 7, 2989, 6, 6, 54105, 6, 7, 4225, // 6, 6
+ 5, 7, 3180, 5, 8, 2294, 6, 7, 56756, 6, 8, 3306, // 6, 7
+ 6, 8, 56751, 6, 9, 3303, 7, 8, 3186, 7, 9, 2296, // 6, 8
+ 6, 9, 54105, 6, 10, 4217, 7, 9, 4225, 7, 10, 2989, // 6, 9
+ 6, 10, 50587, 6, 11, 5400, 7, 10, 5637, 7, 11, 3912, // 6,10
+ 6, 11, 47049, 6, 12, 6530, 7, 11, 7119, 7, 12, 4838, // 6,11
+ 6, 12, 43733, 6, 13, 7516, 7, 12, 8584, 7, 13, 5703, // 6,12
+ 6, 13, 40688, 6, 14, 8344, 7, 13, 10013, 7, 14, 6491, // 6,13
+ 6, 14, 37906, 6, 15, 9020, 7, 14, 11407, 7, 15, 7203, // 6,14
+ 6, 15, 35362, 6, 16, 9558, 7, 15, 12777, 7, 16, 7839, // 6,15
+ 6, 0, 12728, 6, 1, 7674, 7, 0, 35844, 7, 1, 9290, // 7, 0
+ 6, 1, 11317, 6, 2, 7020, 7, 1, 38481, 7, 2, 8718, // 7, 1
+ 6, 2, 9867, 6, 3, 6284, 7, 2, 41389, 7, 3, 7996, // 7, 2
+ 6, 3, 8359, 6, 4, 5454, 7, 3, 44616, 7, 4, 7107, // 7, 3
+ 6, 4, 6774, 6, 5, 4521, 7, 4, 48218, 7, 5, 6023, // 7, 4
+ 6, 5, 5092, 6, 6, 3470, 7, 5, 52253, 7, 6, 4721, // 7, 5
+ 6, 6, 3303, 6, 7, 2295, 7, 6, 56751, 7, 7, 3187, // 7, 6
+ 6, 7, 1541, 6, 8, 1090, 7, 7, 61364, 7, 8, 1541, // 7, 7
+ 7, 8, 61364, 7, 9, 1541, 8, 8, 1542, 8, 9, 1089, // 7, 8
+ 7, 9, 56756, 7, 10, 3180, 8, 9, 3306, 8, 10, 2294, // 7, 9
+ 7, 10, 52266, 7, 11, 4708, 8, 10, 5097, 8, 11, 3465, // 7,10
+ 7, 11, 48240, 7, 12, 6000, 8, 11, 6783, 8, 12, 4513, // 7,11
+ 7, 12, 44649, 7, 13, 7072, 8, 12, 8373, 8, 13, 5442, // 7,12
+ 7, 13, 41432, 7, 14, 7951, 8, 13, 9886, 8, 14, 6267, // 7,13
+ 7, 14, 38534, 7, 15, 8662, 8, 14, 11344, 8, 15, 6996, // 7,14
+ 7, 15, 35905, 7, 16, 9224, 8, 15, 12764, 8, 16, 7643, // 7,15
+ 7, -1, 7643, 7, 0, 12764, 8, -1, 9224, 8, 0, 35905, // 8, 0
+ 7, 0, 6997, 7, 1, 11344, 8, 0, 8662, 8, 1, 38533, // 8, 1
+ 7, 1, 6266, 7, 2, 9886, 8, 1, 7951, 8, 2, 41433, // 8, 2
+ 7, 2, 5443, 7, 3, 8373, 8, 2, 7072, 8, 3, 44648, // 8, 3
+ 7, 3, 4513, 7, 4, 6783, 8, 3, 6000, 8, 4, 48240, // 8, 4
+ 7, 4, 3466, 7, 5, 5097, 8, 4, 4708, 8, 5, 52265, // 8, 5
+ 7, 5, 2294, 7, 6, 3306, 8, 5, 3180, 8, 6, 56756, // 8, 6
+ 7, 6, 1090, 7, 7, 1542, 8, 6, 1541, 8, 7, 61363, // 8, 7
+ 8, 7, 1542, 8, 8, 61364, 9, 7, 1090, 9, 8, 1540, // 8, 8
+ 8, 8, 3186, 8, 9, 56751, 9, 8, 2295, 9, 9, 3304, // 8, 9
+ 8, 9, 4721, 8, 10, 52253, 9, 9, 3470, 9, 10, 5092, // 8,10
+ 8, 10, 6023, 8, 11, 48218, 9, 10, 4521, 9, 11, 6774, // 8,11
+ 8, 11, 7106, 8, 12, 44616, 9, 11, 5454, 9, 12, 8360, // 8,12
+ 8, 12, 7996, 8, 13, 41389, 9, 12, 6284, 9, 13, 9867, // 8,13
+ 8, 13, 8718, 8, 14, 38481, 9, 13, 7020, 9, 14, 11317, // 8,14
+ 8, 14, 9290, 8, 15, 35844, 9, 14, 7674, 9, 15, 12728, // 8,15
+ 8, -1, 7839, 8, 0, 12777, 9, -1, 9558, 9, 0, 35362, // 9, 0
+ 8, 0, 7202, 8, 1, 11407, 9, 0, 9020, 9, 1, 37907, // 9, 1
+ 8, 1, 6491, 8, 2, 10013, 9, 1, 8344, 9, 2, 40688, // 9, 2
+ 8, 2, 5703, 8, 3, 8584, 9, 2, 7516, 9, 3, 43733, // 9, 3
+ 8, 3, 4838, 8, 4, 7119, 9, 3, 6530, 9, 4, 47049, // 9, 4
+ 8, 4, 3911, 8, 5, 5637, 9, 4, 5400, 9, 5, 50588, // 9, 5
+ 8, 5, 2989, 8, 6, 4225, 9, 5, 4217, 9, 6, 54105, // 9, 6
+ 8, 6, 2295, 8, 7, 3186, 9, 6, 3303, 9, 7, 56752, // 9, 7
+ 9, 7, 3306, 9, 8, 56756, 10, 7, 2294, 10, 8, 3180, // 9, 8
+ 9, 8, 4225, 9, 9, 54105, 10, 8, 2989, 10, 9, 4217, // 9, 9
+ 9, 9, 5418, 9, 10, 50581, 10, 9, 3913, 10, 10, 5624, // 9,10
+ 9, 10, 6558, 9, 11, 47035, 10, 10, 4843, 10, 11, 7100, // 9,11
+ 9, 11, 7556, 9, 12, 43710, 10, 11, 5712, 10, 12, 8558, // 9,12
+ 9, 12, 8397, 9, 13, 40656, 10, 12, 6506, 10, 13, 9977, // 9,13
+ 9, 13, 9086, 9, 14, 37866, 10, 13, 7224, 10, 14, 11360, // 9,14
+ 9, 14, 9635, 9, 15, 35315, 10, 14, 7868, 10, 15, 12718, // 9,15
+ 9, -1, 8107, 9, 0, 12867, 10, -1, 9995, 10, 0, 34567, // 10, 0
+ 9, 0, 7497, 9, 1, 11575, 10, 0, 9509, 10, 1, 36955, // 10, 1
+ 9, 1, 6829, 9, 2, 10279, 10, 1, 8902, 10, 2, 39526, // 10, 2
+ 9, 2, 6108, 9, 3, 8982, 10, 2, 8175, 10, 3, 42271, // 10, 3
+ 9, 3, 5350, 9, 4, 7698, 10, 3, 7342, 10, 4, 45146, // 10, 4
+ 9, 4, 4591, 9, 5, 6475, 10, 4, 6451, 10, 5, 48019, // 10, 5
+ 9, 5, 3913, 9, 6, 5418, 10, 5, 5624, 10, 6, 50581, // 10, 6
+ 9, 6, 3470, 9, 7, 4721, 10, 6, 5092, 10, 7, 52253, // 10, 7
+ 10, 7, 5097, 10, 8, 52266, 11, 7, 3466, 11, 8, 4707, // 10, 8
+ 10, 8, 5637, 10, 9, 50587, 11, 8, 3911, 11, 9, 5401, // 10, 9
+ 10, 9, 6475, 10, 10, 48019, 11, 9, 4591, 11, 10, 6451, // 10,10
+ 10, 10, 7377, 10, 11, 45139, 11, 10, 5353, 11, 11, 7667, // 10,11
+ 10, 11, 8224, 10, 12, 42256, 11, 11, 6116, 11, 12, 8940, // 10,12
+ 10, 12, 8966, 10, 13, 39503, 11, 12, 6842, 11, 13, 10225, // 10,13
+ 10, 13, 9587, 10, 14, 36926, 11, 13, 7517, 11, 14, 11506, // 10,14
+ 10, 14, 10086, 10, 15, 34532, 11, 14, 8135, 11, 15, 12783, // 10,15
+ 10, -1, 8438, 10, 0, 13007, 11, -1, 10528, 11, 0, 33563, // 11, 0
+ 10, 0, 7865, 10, 1, 11810, 11, 0, 10111, 11, 1, 35750, // 11, 1
+ 10, 1, 7252, 10, 2, 10630, 11, 1, 9597, 11, 2, 38057, // 11, 2
+ 10, 2, 6611, 10, 3, 9478, 11, 2, 8995, 11, 3, 40452, // 11, 3
+ 10, 3, 5965, 10, 4, 8378, 11, 3, 8332, 11, 4, 42861, // 11, 4
+ 10, 4, 5353, 10, 5, 7377, 11, 4, 7667, 11, 5, 45139, // 11, 5
+ 10, 5, 4843, 10, 6, 6558, 11, 5, 7100, 11, 6, 47035, // 11, 6
+ 10, 6, 4521, 10, 7, 6023, 11, 6, 6774, 11, 7, 48218, // 11, 7
+ 11, 7, 6783, 11, 8, 48240, 12, 7, 4513, 12, 8, 6000, // 11, 8
+ 11, 8, 7119, 11, 9, 47049, 12, 8, 4838, 12, 9, 6530, // 11, 9
+ 11, 9, 7698, 11, 10, 45146, 12, 9, 5350, 12, 10, 7342, // 11,10
+ 11, 10, 8378, 11, 11, 42861, 12, 10, 5965, 12, 11, 8332, // 11,11
+ 11, 11, 9056, 11, 12, 40444, 12, 11, 6615, 12, 12, 9421, // 11,12
+ 11, 12, 9674, 11, 13, 38042, 12, 12, 7261, 12, 13, 10559, // 11,13
+ 11, 13, 10204, 11, 14, 35730, 12, 13, 7881, 12, 14, 11721, // 11,14
+ 11, 14, 10635, 11, 15, 33539, 12, 14, 8463, 12, 15, 12899, // 11,15
+ 11, -1, 8816, 11, 0, 13171, 12, -1, 11143, 12, 0, 32406, // 12, 0
+ 11, 0, 8284, 11, 1, 12074, 12, 0, 10808, 12, 1, 34370, // 12, 1
+ 11, 1, 7728, 11, 2, 11012, 12, 1, 10397, 12, 2, 36399, // 12, 2
+ 11, 2, 7164, 11, 3, 9998, 12, 2, 9924, 12, 3, 38450, // 12, 3
+ 11, 3, 6615, 11, 4, 9056, 12, 3, 9421, 12, 4, 40444, // 12, 4
+ 11, 4, 6116, 11, 5, 8224, 12, 4, 8940, 12, 5, 42256, // 12, 5
+ 11, 5, 5712, 11, 6, 7556, 12, 5, 8558, 12, 6, 43710, // 12, 6
+ 11, 6, 5454, 11, 7, 7106, 12, 6, 8359, 12, 7, 44617, // 12, 7
+ 12, 7, 8373, 12, 8, 44649, 13, 7, 5443, 13, 8, 7071, // 12, 8
+ 12, 8, 8584, 12, 9, 43733, 13, 8, 5703, 13, 9, 7516, // 12, 9
+ 12, 9, 8982, 12, 10, 42271, 13, 9, 6108, 13, 10, 8175, // 12,10
+ 12, 10, 9478, 12, 11, 40452, 13, 10, 6611, 13, 11, 8995, // 12,11
+ 12, 11, 9998, 12, 12, 38450, 13, 11, 7164, 13, 12, 9924, // 12,12
+ 12, 12, 10488, 12, 13, 36392, 13, 12, 7734, 13, 13, 10922, // 12,13
+ 12, 13, 10918, 12, 14, 34358, 13, 13, 8296, 13, 14, 11964, // 12,14
+ 12, 14, 11269, 12, 15, 32391, 13, 14, 8838, 13, 15, 13038, // 12,15
+ 12, -1, 9229, 12, 0, 13332, 13, -1, 11829, 13, 0, 31146, // 13, 0
+ 12, 0, 8735, 12, 1, 12334, 13, 0, 11580, 13, 1, 32887, // 13, 1
+ 12, 1, 8232, 12, 2, 11382, 13, 1, 11272, 13, 2, 34650, // 13, 2
+ 12, 2, 7734, 12, 3, 10488, 13, 2, 10922, 13, 3, 36392, // 13, 3
+ 12, 3, 7261, 12, 4, 9674, 13, 3, 10559, 13, 4, 38042, // 13, 4
+ 12, 4, 6842, 12, 5, 8966, 13, 4, 10226, 13, 5, 39502, // 13, 5
+ 12, 5, 6506, 12, 6, 8397, 13, 5, 9977, 13, 6, 40656, // 13, 6
+ 12, 6, 6284, 12, 7, 7996, 13, 6, 9867, 13, 7, 41389, // 13, 7
+ 13, 7, 9886, 13, 8, 41432, 14, 7, 6266, 14, 8, 7952, // 13, 8
+ 13, 8, 10013, 13, 9, 40688, 14, 8, 6491, 14, 9, 8344, // 13, 9
+ 13, 9, 10279, 13, 10, 39526, 14, 9, 6829, 14, 10, 8902, // 13,10
+ 13, 10, 10630, 13, 11, 38057, 14, 10, 7252, 14, 11, 9597, // 13,11
+ 13, 11, 11012, 13, 12, 36399, 14, 11, 7728, 14, 12, 10397, // 13,12
+ 13, 12, 11382, 13, 13, 34650, 14, 12, 8232, 14, 13, 11272, // 13,13
+ 13, 13, 11709, 13, 14, 32881, 14, 13, 8742, 14, 14, 12204, // 13,14
+ 13, 14, 11977, 13, 15, 31138, 14, 14, 9245, 14, 15, 13176, // 13,15
+ 13, -1, 9662, 13, 0, 13470, 14, -1, 12574, 14, 0, 29830, // 14, 0
+ 13, 0, 9202, 13, 1, 12564, 14, 0, 12412, 14, 1, 31358, // 14, 1
+ 13, 1, 8742, 13, 2, 11709, 14, 1, 12203, 14, 2, 32882, // 14, 2
+ 13, 2, 8296, 13, 3, 10918, 14, 2, 11964, 14, 3, 34358, // 14, 3
+ 13, 3, 7881, 13, 4, 10204, 14, 3, 11721, 14, 4, 35730, // 14, 4
+ 13, 4, 7517, 13, 5, 9587, 14, 4, 11507, 14, 5, 36925, // 14, 5
+ 13, 5, 7224, 13, 6, 9086, 14, 5, 11360, 14, 6, 37866, // 14, 6
+ 13, 6, 7020, 13, 7, 8718, 14, 6, 11317, 14, 7, 38481, // 14, 7
+ 14, 7, 11344, 14, 8, 38534, 15, 7, 6997, 15, 8, 8661, // 14, 8
+ 14, 8, 11407, 14, 9, 37906, 15, 8, 7202, 15, 9, 9021, // 14, 9
+ 14, 9, 11575, 14, 10, 36955, 15, 9, 7497, 15, 10, 9509, // 14,10
+ 14, 10, 11810, 14, 11, 35750, 15, 10, 7865, 15, 11, 10111, // 14,11
+ 14, 11, 12074, 14, 12, 34369, 15, 11, 8284, 15, 12, 10809, // 14,12
+ 14, 12, 12334, 14, 13, 32886, 15, 12, 8735, 15, 13, 11581, // 14,13
+ 14, 13, 12564, 14, 14, 31358, 15, 13, 9202, 15, 14, 12412, // 14,14
+ 14, 14, 12746, 14, 15, 29828, 15, 14, 9671, 15, 15, 13291, // 14,15
+ 14, -1, 10104, 14, 0, 13569, 15, -1, 13368, 15, 0, 28495, // 15, 0
+ 14, 0, 9671, 14, 1, 12746, 15, 0, 13291, 15, 1, 29828, // 15, 1
+ 14, 1, 9245, 14, 2, 11977, 15, 1, 13176, 15, 2, 31138, // 15, 2
+ 14, 2, 8838, 14, 3, 11269, 15, 2, 13038, 15, 3, 32391, // 15, 3
+ 14, 3, 8463, 14, 4, 10635, 15, 3, 12899, 15, 4, 33539, // 15, 4
+ 14, 4, 8135, 14, 5, 10086, 15, 4, 12783, 15, 5, 34532, // 15, 5
+ 14, 5, 7868, 14, 6, 9635, 15, 5, 12717, 15, 6, 35316, // 15, 6
+ 14, 6, 7674, 14, 7, 9290, 15, 6, 12728, 15, 7, 35844, // 15, 7
+ 15, 7, 12764, 15, 8, 35905, 16, 7, 7643, 16, 8, 9224, // 15, 8
+ 15, 8, 12777, 15, 9, 35362, 16, 8, 7839, 16, 9, 9558, // 15, 9
+ 15, 9, 12867, 15, 10, 34567, 16, 9, 8107, 16, 10, 9995, // 15,10
+ 15, 10, 13007, 15, 11, 33564, 16, 10, 8438, 16, 11, 10527, // 15,11
+ 15, 11, 13171, 15, 12, 32406, 16, 11, 8816, 16, 12, 11143, // 15,12
+ 15, 12, 13332, 15, 13, 31146, 16, 12, 9229, 16, 13, 11829, // 15,13
+ 15, 13, 13470, 15, 14, 29831, 16, 13, 9662, 16, 14, 12573, // 15,14
+ 15, 14, 13569, 15, 15, 28495, 16, 14, 10104, 16, 15, 13368, // 15,15
+ // angle of -1.5 degrees
+ -1, 0, 11440, -1, 1, 8358, 0, 0, 34212, 0, 1, 11526, // 0, 0
+ -1, 1, 10780, -1, 2, 7983, 0, 1, 35506, 0, 2, 11267, // 0, 1
+ -1, 2, 10158, -1, 3, 7620, 0, 2, 36764, 0, 3, 10994, // 0, 2
+ -1, 3, 9585, -1, 4, 7276, 0, 3, 37951, 0, 4, 10724, // 0, 3
+ -1, 4, 9072, -1, 5, 6965, 0, 4, 39026, 0, 5, 10473, // 0, 4
+ -1, 5, 8632, -1, 6, 6699, 0, 5, 39940, 0, 6, 10265, // 0, 5
+ -1, 6, 8278, -1, 7, 6489, 0, 6, 40646, 0, 7, 10123, // 0, 6
+ -1, 7, 8018, -1, 8, 6346, 0, 7, 41106, 0, 8, 10066, // 0, 7
+ 0, 8, 41072, 0, 9, 10052, 1, 8, 8052, 1, 9, 6360, // 0, 8
+ 0, 9, 40618, 0, 10, 10100, 1, 9, 8316, 1, 10, 6502, // 0, 9
+ 0, 10, 39918, 0, 11, 10232, 1, 10, 8676, 1, 11, 6710, // 0,10
+ 0, 11, 39009, 0, 12, 10430, 1, 11, 9122, 1, 12, 6975, // 0,11
+ 0, 12, 37939, 0, 13, 10670, 1, 12, 9642, 1, 13, 7285, // 0,12
+ 0, 13, 36756, 0, 14, 10930, 1, 13, 10224, 1, 14, 7626, // 0,13
+ 0, 14, 35502, 0, 15, 11192, 1, 14, 10855, 1, 15, 7987, // 0,14
+ 0, 15, 34212, 0, 16, 11440, 1, 15, 11526, 1, 16, 8358, // 0,15
+ 0, 0, 11192, 0, 1, 7987, 1, 0, 35502, 1, 1, 10855, // 1, 0
+ 0, 1, 10467, 0, 2, 7579, 1, 1, 36959, 1, 2, 10531, // 1, 1
+ 0, 2, 9777, 0, 3, 7177, 1, 2, 38394, 1, 3, 10188, // 1, 2
+ 0, 3, 9135, 0, 4, 6792, 1, 3, 39767, 1, 4, 9842, // 1, 3
+ 0, 4, 8557, 0, 5, 6440, 1, 4, 41026, 1, 5, 9513, // 1, 4
+ 0, 5, 8061, 0, 6, 6137, 1, 5, 42105, 1, 6, 9233, // 1, 5
+ 0, 6, 7667, 0, 7, 5900, 1, 6, 42936, 1, 7, 9033, // 1, 6
+ 0, 7, 7390, 0, 8, 5745, 1, 7, 43461, 1, 8, 8940, // 1, 7
+ 1, 8, 43433, 1, 9, 8929, 2, 8, 7418, 2, 9, 5756, // 1, 8
+ 1, 9, 42913, 1, 10, 9014, 2, 9, 7699, 2, 10, 5910, // 1, 9
+ 1, 10, 42087, 1, 11, 9206, 2, 10, 8098, 2, 11, 6145, // 1,10
+ 1, 11, 41013, 1, 12, 9478, 2, 11, 8599, 2, 12, 6446, // 1,11
+ 1, 12, 39759, 1, 13, 9796, 2, 12, 9184, 2, 13, 6797, // 1,12
+ 1, 13, 38390, 1, 14, 10133, 2, 13, 9834, 2, 14, 7179, // 1,13
+ 1, 14, 36959, 1, 15, 10467, 2, 14, 10532, 2, 15, 7578, // 1,14
+ 1, 15, 35506, 1, 16, 10780, 2, 15, 11267, 2, 16, 7983, // 1,15
+ 1, 0, 10930, 1, 1, 7626, 2, 0, 36756, 2, 1, 10224, // 2, 0
+ 1, 1, 10133, 1, 2, 7179, 2, 1, 38390, 2, 2, 9834, // 2, 1
+ 1, 2, 9366, 1, 3, 6732, 2, 2, 40025, 2, 3, 9413, // 2, 2
+ 1, 3, 8641, 1, 4, 6297, 2, 3, 41618, 2, 4, 8980, // 2, 3
+ 1, 4, 7981, 1, 5, 5891, 2, 4, 43105, 2, 5, 8559, // 2, 4
+ 1, 5, 7411, 1, 6, 5537, 2, 5, 44399, 2, 6, 8189, // 2, 5
+ 1, 6, 6961, 1, 7, 5261, 2, 6, 45401, 2, 7, 7913, // 2, 6
+ 1, 7, 6658, 1, 8, 5087, 2, 7, 46017, 2, 8, 7774, // 2, 7
+ 2, 8, 45995, 2, 9, 7766, 3, 8, 6680, 3, 9, 5095, // 2, 8
+ 2, 9, 45383, 2, 10, 7899, 3, 9, 6986, 3, 10, 5268, // 2, 9
+ 2, 10, 44386, 2, 11, 8167, 3, 10, 7440, 3, 11, 5543, // 2,10
+ 2, 11, 43096, 2, 12, 8530, 3, 11, 8015, 3, 12, 5895, // 2,11
+ 2, 12, 41614, 2, 13, 8941, 3, 12, 8681, 3, 13, 6300, // 2,12
+ 2, 13, 40025, 2, 14, 9366, 3, 13, 9413, 3, 14, 6732, // 2,13
+ 2, 14, 38394, 2, 15, 9777, 3, 14, 10188, 3, 15, 7177, // 2,14
+ 2, 15, 36764, 2, 16, 10158, 3, 15, 10994, 3, 16, 7620, // 2,15
+ 2, 0, 10670, 2, 1, 7285, 3, 0, 37939, 3, 1, 9642, // 3, 0
+ 2, 1, 9796, 2, 2, 6797, 3, 1, 39759, 3, 2, 9184, // 3, 1
+ 2, 2, 8941, 2, 3, 6299, 3, 2, 41614, 3, 3, 8682, // 3, 2
+ 2, 3, 8120, 2, 4, 5804, 3, 3, 43461, 3, 4, 8151, // 3, 3
+ 2, 4, 7356, 2, 5, 5330, 3, 4, 45229, 3, 5, 7621, // 3, 4
+ 2, 5, 6685, 2, 6, 4906, 3, 5, 46806, 3, 6, 7139, // 3, 5
+ 2, 6, 6154, 2, 7, 4572, 3, 6, 48049, 3, 7, 6761, // 3, 6
+ 2, 7, 5811, 2, 8, 4366, 3, 7, 48801, 3, 8, 6558, // 3, 7
+ 3, 8, 48785, 3, 9, 6552, 4, 8, 5827, 4, 9, 4372, // 3, 8
+ 3, 9, 48037, 3, 10, 6750, 4, 9, 6173, 4, 10, 4576, // 3, 9
+ 3, 10, 46798, 3, 11, 7121, 4, 10, 6707, 4, 11, 4910, // 3,10
+ 3, 11, 45224, 3, 12, 7598, 4, 11, 7382, 4, 12, 5332, // 3,11
+ 3, 12, 43461, 3, 13, 8120, 4, 12, 8151, 4, 13, 5804, // 3,12
+ 3, 13, 41618, 3, 14, 8641, 4, 13, 8979, 4, 14, 6298, // 3,13
+ 3, 14, 39767, 3, 15, 9135, 4, 14, 9841, 4, 15, 6793, // 3,14
+ 3, 15, 37951, 3, 16, 9585, 4, 15, 10723, 4, 16, 7277, // 3,15
+ 3, 0, 10430, 3, 1, 6975, 4, 0, 39009, 4, 1, 9122, // 4, 0
+ 3, 1, 9478, 3, 2, 6447, 4, 1, 41013, 4, 2, 8598, // 4, 1
+ 3, 2, 8530, 3, 3, 5895, 4, 2, 43096, 4, 3, 8015, // 4, 2
+ 3, 3, 7598, 3, 4, 5331, 4, 3, 45224, 4, 4, 7383, // 4, 3
+ 3, 4, 6708, 3, 5, 4774, 4, 4, 47328, 4, 5, 6726, // 4, 4
+ 3, 5, 5901, 3, 6, 4257, 4, 5, 49279, 4, 6, 6099, // 4, 5
+ 3, 6, 5248, 3, 7, 3834, 4, 6, 50873, 4, 7, 5581, // 4, 6
+ 3, 7, 4835, 3, 8, 3575, 4, 7, 51842, 4, 8, 5284, // 4, 7
+ 4, 8, 51832, 4, 9, 5280, 5, 8, 4846, 5, 9, 3578, // 4, 8
+ 4, 9, 50865, 4, 10, 5573, 5, 9, 5261, 5, 10, 3837, // 4, 9
+ 4, 10, 49275, 4, 11, 6086, 5, 10, 5917, 5, 11, 4258, // 4,10
+ 4, 11, 47328, 4, 12, 6708, 5, 11, 6727, 5, 12, 4773, // 4,11
+ 4, 12, 45229, 4, 13, 7356, 5, 12, 7622, 5, 13, 5329, // 4,12
+ 4, 13, 43105, 4, 14, 7981, 5, 13, 8559, 5, 14, 5891, // 4,13
+ 4, 14, 41026, 4, 15, 8557, 5, 14, 9513, 5, 15, 6440, // 4,14
+ 4, 15, 39026, 4, 16, 9072, 5, 15, 10473, 5, 16, 6965, // 4,15
+ 4, 0, 10232, 4, 1, 6710, 5, 0, 39918, 5, 1, 8676, // 5, 0
+ 4, 1, 9206, 4, 2, 6145, 5, 1, 42087, 5, 2, 8098, // 5, 1
+ 4, 2, 8167, 4, 3, 5543, 5, 2, 44386, 5, 3, 7440, // 5, 2
+ 4, 3, 7121, 4, 4, 4909, 5, 3, 46798, 5, 4, 6708, // 5, 3
+ 4, 4, 6086, 4, 5, 4258, 5, 4, 49275, 5, 5, 5917, // 5, 4
+ 4, 5, 5103, 4, 6, 3621, 5, 5, 51700, 5, 6, 5112, // 5, 5
+ 4, 6, 4262, 4, 7, 3064, 5, 6, 53816, 5, 7, 4394, // 5, 6
+ 4, 7, 3720, 4, 8, 2708, 5, 7, 55168, 5, 8, 3940, // 5, 7
+ 5, 8, 55162, 5, 9, 3938, 6, 8, 3726, 6, 9, 2710, // 5, 8
+ 5, 9, 53813, 5, 10, 4388, 6, 9, 4269, 6, 10, 3066, // 5, 9
+ 5, 10, 51700, 5, 11, 5103, 6, 10, 5113, 6, 11, 3620, // 5,10
+ 5, 11, 49279, 5, 12, 5901, 6, 11, 6099, 6, 12, 4257, // 5,11
+ 5, 12, 46806, 5, 13, 6685, 6, 12, 7138, 6, 13, 4907, // 5,12
+ 5, 13, 44399, 5, 14, 7411, 6, 13, 8189, 6, 14, 5537, // 5,13
+ 5, 14, 42105, 5, 15, 8061, 6, 14, 9233, 6, 15, 6137, // 5,14
+ 5, 15, 39940, 5, 16, 8632, 6, 15, 10265, 6, 16, 6699, // 5,15
+ 5, 0, 10100, 5, 1, 6502, 6, 0, 40618, 6, 1, 8316, // 6, 0
+ 5, 1, 9014, 5, 2, 5910, 6, 1, 42913, 6, 2, 7699, // 6, 1
+ 5, 2, 7899, 5, 3, 5268, 6, 2, 45383, 6, 3, 6986, // 6, 2
+ 5, 3, 6750, 5, 4, 4576, 6, 3, 48037, 6, 4, 6173, // 6, 3
+ 5, 4, 5573, 5, 5, 3837, 6, 4, 50865, 6, 5, 5261, // 6, 4
+ 5, 5, 4388, 5, 6, 3065, 6, 5, 53813, 6, 6, 4270, // 6, 5
+ 5, 6, 3271, 5, 7, 2316, 6, 6, 56673, 6, 7, 3276, // 6, 6
+ 5, 7, 2462, 5, 8, 1766, 6, 7, 58775, 6, 8, 2533, // 6, 7
+ 6, 8, 58773, 6, 9, 2532, 7, 8, 2464, 7, 9, 1767, // 6, 8
+ 6, 9, 56673, 6, 10, 3271, 7, 9, 3275, 7, 10, 2317, // 6, 9
+ 6, 10, 53816, 6, 11, 4262, 7, 10, 4394, 7, 11, 3064, // 6,10
+ 6, 11, 50873, 6, 12, 5248, 7, 11, 5581, 7, 12, 3834, // 6,11
+ 6, 12, 48049, 6, 13, 6154, 7, 12, 6761, 7, 13, 4572, // 6,12
+ 6, 13, 45401, 6, 14, 6961, 7, 13, 7913, 7, 14, 5261, // 6,13
+ 6, 14, 42936, 6, 15, 7667, 7, 14, 9032, 7, 15, 5901, // 6,14
+ 6, 15, 40646, 6, 16, 8278, 7, 15, 10123, 7, 16, 6489, // 6,15
+ 6, 0, 10052, 6, 1, 6360, 7, 0, 41072, 7, 1, 8052, // 7, 0
+ 6, 1, 8929, 6, 2, 5756, 7, 1, 43433, 7, 2, 7418, // 7, 1
+ 6, 2, 7766, 6, 3, 5095, 7, 2, 45995, 7, 3, 6680, // 7, 2
+ 6, 3, 6552, 6, 4, 4372, 7, 3, 48785, 7, 4, 5827, // 7, 3
+ 6, 4, 5280, 6, 5, 3579, 7, 4, 51832, 7, 5, 4845, // 7, 4
+ 6, 5, 3938, 6, 6, 2710, 7, 5, 55162, 7, 6, 3726, // 7, 5
+ 6, 6, 2532, 6, 7, 1767, 7, 6, 58773, 7, 7, 2464, // 7, 6
+ 6, 7, 1170, 6, 8, 827, 7, 7, 62369, 7, 8, 1170, // 7, 7
+ 7, 8, 62369, 7, 9, 1170, 8, 8, 1170, 8, 9, 827, // 7, 8
+ 7, 9, 58775, 7, 10, 2462, 8, 9, 2533, 8, 10, 1766, // 7, 9
+ 7, 10, 55168, 7, 11, 3720, 8, 10, 3940, 8, 11, 2708, // 7,10
+ 7, 11, 51842, 7, 12, 4835, 8, 11, 5283, 8, 12, 3576, // 7,11
+ 7, 12, 48801, 7, 13, 5811, 8, 12, 6558, 8, 13, 4366, // 7,12
+ 7, 13, 46017, 7, 14, 6658, 8, 13, 7773, 8, 14, 5088, // 7,13
+ 7, 14, 43461, 7, 15, 7390, 8, 14, 8939, 8, 15, 5746, // 7,14
+ 7, 15, 41106, 7, 16, 8018, 8, 15, 10066, 8, 16, 6346, // 7,15
+ 7, -1, 6346, 7, 0, 10066, 8, -1, 8018, 8, 0, 41106, // 8, 0
+ 7, 0, 5745, 7, 1, 8939, 8, 0, 7390, 8, 1, 43462, // 8, 1
+ 7, 1, 5087, 7, 2, 7773, 8, 1, 6658, 8, 2, 46018, // 8, 2
+ 7, 2, 4366, 7, 3, 6558, 8, 2, 5811, 8, 3, 48801, // 8, 3
+ 7, 3, 3575, 7, 4, 5283, 8, 3, 4835, 8, 4, 51843, // 8, 4
+ 7, 4, 2708, 7, 5, 3940, 8, 4, 3720, 8, 5, 55168, // 8, 5
+ 7, 5, 1766, 7, 6, 2533, 8, 5, 2462, 8, 6, 58775, // 8, 6
+ 7, 6, 827, 7, 7, 1170, 8, 6, 1170, 8, 7, 62369, // 8, 7
+ 8, 7, 1170, 8, 8, 62369, 9, 7, 827, 9, 8, 1170, // 8, 8
+ 8, 8, 2464, 8, 9, 58773, 9, 8, 1767, 9, 9, 2532, // 8, 9
+ 8, 9, 3726, 8, 10, 55162, 9, 9, 2710, 9, 10, 3938, // 8,10
+ 8, 10, 4846, 8, 11, 51832, 9, 10, 3579, 9, 11, 5279, // 8,11
+ 8, 11, 5827, 8, 12, 48785, 9, 11, 4372, 9, 12, 6552, // 8,12
+ 8, 12, 6680, 8, 13, 45995, 9, 12, 5095, 9, 13, 7766, // 8,13
+ 8, 13, 7418, 8, 14, 43433, 9, 13, 5756, 9, 14, 8929, // 8,14
+ 8, 14, 8052, 8, 15, 41072, 9, 14, 6360, 9, 15, 10052, // 8,15
+ 8, -1, 6489, 8, 0, 10123, 9, -1, 8278, 9, 0, 40646, // 9, 0
+ 8, 0, 5900, 8, 1, 9032, 9, 0, 7667, 9, 1, 42937, // 9, 1
+ 8, 1, 5261, 8, 2, 7913, 9, 1, 6961, 9, 2, 45401, // 9, 2
+ 8, 2, 4572, 8, 3, 6761, 9, 2, 6154, 9, 3, 48049, // 9, 3
+ 8, 3, 3834, 8, 4, 5581, 9, 3, 5248, 9, 4, 50873, // 9, 4
+ 8, 4, 3064, 8, 5, 4394, 9, 4, 4262, 9, 5, 53816, // 9, 5
+ 8, 5, 2316, 8, 6, 3275, 9, 5, 3271, 9, 6, 56674, // 9, 6
+ 8, 6, 1767, 8, 7, 2464, 9, 6, 2532, 9, 7, 58773, // 9, 7
+ 9, 7, 2533, 9, 8, 58775, 10, 7, 1766, 10, 8, 2462, // 9, 8
+ 9, 8, 3275, 9, 9, 56673, 10, 8, 2316, 10, 9, 3272, // 9, 9
+ 9, 9, 4269, 9, 10, 53813, 10, 9, 3065, 10, 10, 4389, // 9,10
+ 9, 10, 5261, 9, 11, 50865, 10, 10, 3837, 10, 11, 5573, // 9,11
+ 9, 11, 6173, 9, 12, 48037, 10, 11, 4576, 10, 12, 6750, // 9,12
+ 9, 12, 6986, 9, 13, 45383, 10, 12, 5268, 10, 13, 7899, // 9,13
+ 9, 13, 7699, 9, 14, 42913, 10, 13, 5910, 10, 14, 9014, // 9,14
+ 9, 14, 8316, 9, 15, 40618, 10, 14, 6502, 10, 15, 10100, // 9,15
+ 9, -1, 6699, 9, 0, 10265, 10, -1, 8632, 10, 0, 39940, // 10, 0
+ 9, 0, 6137, 9, 1, 9233, 10, 0, 8061, 10, 1, 42105, // 10, 1
+ 9, 1, 5537, 9, 2, 8189, 10, 1, 7411, 10, 2, 44399, // 10, 2
+ 9, 2, 4906, 9, 3, 7138, 10, 2, 6685, 10, 3, 46807, // 10, 3
+ 9, 3, 4257, 9, 4, 6099, 10, 3, 5901, 10, 4, 49279, // 10, 4
+ 9, 4, 3621, 9, 5, 5113, 10, 4, 5103, 10, 5, 51699, // 10, 5
+ 9, 5, 3065, 9, 6, 4269, 10, 5, 4388, 10, 6, 53814, // 10, 6
+ 9, 6, 2710, 9, 7, 3726, 10, 6, 3938, 10, 7, 55162, // 10, 7
+ 10, 7, 3940, 10, 8, 55168, 11, 7, 2708, 11, 8, 3720, // 10, 8
+ 10, 8, 4394, 10, 9, 53816, 11, 8, 3064, 11, 9, 4262, // 10, 9
+ 10, 9, 5113, 10, 10, 51700, 11, 9, 3621, 11, 10, 5102, // 10,10
+ 10, 10, 5917, 10, 11, 49275, 11, 10, 4258, 11, 11, 6086, // 10,11
+ 10, 11, 6707, 10, 12, 46798, 11, 11, 4909, 11, 12, 7122, // 10,12
+ 10, 12, 7440, 10, 13, 44386, 11, 12, 5543, 11, 13, 8167, // 10,13
+ 10, 13, 8098, 10, 14, 42087, 11, 13, 6145, 11, 14, 9206, // 10,14
+ 10, 14, 8676, 10, 15, 39918, 11, 14, 6710, 11, 15, 10232, // 10,15
+ 10, -1, 6965, 10, 0, 10473, 11, -1, 9072, 11, 0, 39026, // 11, 0
+ 10, 0, 6440, 10, 1, 9513, 11, 0, 8557, 11, 1, 41026, // 11, 1
+ 10, 1, 5891, 10, 2, 8559, 11, 1, 7981, 11, 2, 43105, // 11, 2
+ 10, 2, 5330, 10, 3, 7622, 11, 2, 7356, 11, 3, 45228, // 11, 3
+ 10, 3, 4774, 10, 4, 6727, 11, 3, 6708, 11, 4, 47327, // 11, 4
+ 10, 4, 4258, 10, 5, 5917, 11, 4, 6086, 11, 5, 49275, // 11, 5
+ 10, 5, 3837, 10, 6, 5261, 11, 5, 5573, 11, 6, 50865, // 11, 6
+ 10, 6, 3579, 10, 7, 4846, 11, 6, 5280, 11, 7, 51831, // 11, 7
+ 11, 7, 5283, 11, 8, 51842, 12, 7, 3575, 12, 8, 4836, // 11, 8
+ 11, 8, 5581, 11, 9, 50873, 12, 8, 3834, 12, 9, 5248, // 11, 9
+ 11, 9, 6099, 11, 10, 49279, 12, 9, 4257, 12, 10, 5901, // 11,10
+ 11, 10, 6727, 11, 11, 47328, 12, 10, 4774, 12, 11, 6707, // 11,11
+ 11, 11, 7382, 11, 12, 45224, 12, 11, 5331, 12, 12, 7599, // 11,12
+ 11, 12, 8015, 11, 13, 43096, 12, 12, 5895, 12, 13, 8530, // 11,13
+ 11, 13, 8599, 11, 14, 41013, 12, 13, 6447, 12, 14, 9477, // 11,14
+ 11, 14, 9122, 11, 15, 39009, 12, 14, 6975, 12, 15, 10430, // 11,15
+ 11, -1, 7276, 11, 0, 10723, 12, -1, 9585, 12, 0, 37952, // 12, 0
+ 11, 0, 6792, 11, 1, 9841, 12, 0, 9135, 12, 1, 39768, // 12, 1
+ 11, 1, 6297, 11, 2, 8979, 12, 1, 8641, 12, 2, 41619, // 12, 2
+ 11, 2, 5804, 11, 3, 8151, 12, 2, 8120, 12, 3, 43461, // 12, 3
+ 11, 3, 5331, 11, 4, 7382, 12, 3, 7598, 12, 4, 45225, // 12, 4
+ 11, 4, 4909, 11, 5, 6707, 12, 4, 7121, 12, 5, 46799, // 12, 5
+ 11, 5, 4576, 11, 6, 6173, 12, 5, 6750, 12, 6, 48037, // 12, 6
+ 11, 6, 4372, 11, 7, 5827, 12, 6, 6552, 12, 7, 48785, // 12, 7
+ 12, 7, 6558, 12, 8, 48801, 13, 7, 4366, 13, 8, 5811, // 12, 8
+ 12, 8, 6761, 12, 9, 48049, 13, 8, 4572, 13, 9, 6154, // 12, 9
+ 12, 9, 7138, 12, 10, 46806, 13, 9, 4906, 13, 10, 6686, // 12,10
+ 12, 10, 7622, 12, 11, 45229, 13, 10, 5330, 13, 11, 7355, // 12,11
+ 12, 11, 8151, 12, 12, 43461, 13, 11, 5804, 13, 12, 8120, // 12,12
+ 12, 12, 8681, 12, 13, 41614, 13, 12, 6299, 13, 13, 8942, // 12,13
+ 12, 13, 9184, 12, 14, 39759, 13, 13, 6797, 13, 14, 9796, // 12,14
+ 12, 14, 9642, 12, 15, 37939, 13, 14, 7285, 13, 15, 10670, // 12,15
+ 12, -1, 7620, 12, 0, 10994, 13, -1, 10158, 13, 0, 36764, // 13, 0
+ 12, 0, 7177, 12, 1, 10188, 13, 0, 9777, 13, 1, 38394, // 13, 1
+ 12, 1, 6732, 12, 2, 9413, 13, 1, 9366, 13, 2, 40025, // 13, 2
+ 12, 2, 6299, 12, 3, 8681, 13, 2, 8941, 13, 3, 41615, // 13, 3
+ 12, 3, 5895, 12, 4, 8015, 13, 3, 8530, 13, 4, 43096, // 13, 4
+ 12, 4, 5543, 12, 5, 7440, 13, 4, 8167, 13, 5, 44386, // 13, 5
+ 12, 5, 5268, 12, 6, 6986, 13, 5, 7899, 13, 6, 45383, // 13, 6
+ 12, 6, 5095, 12, 7, 6680, 13, 6, 7766, 13, 7, 45995, // 13, 7
+ 13, 7, 7773, 13, 8, 46017, 14, 7, 5087, 14, 8, 6659, // 13, 8
+ 13, 8, 7913, 13, 9, 45401, 14, 8, 5261, 14, 9, 6961, // 13, 9
+ 13, 9, 8189, 13, 10, 44399, 14, 9, 5537, 14, 10, 7411, // 13,10
+ 13, 10, 8559, 13, 11, 43105, 14, 10, 5891, 14, 11, 7981, // 13,11
+ 13, 11, 8979, 13, 12, 41618, 14, 11, 6297, 14, 12, 8642, // 13,12
+ 13, 12, 9413, 13, 13, 40025, 14, 12, 6732, 14, 13, 9366, // 13,13
+ 13, 13, 9834, 13, 14, 38390, 14, 13, 7179, 14, 14, 10133, // 13,14
+ 13, 14, 10224, 13, 15, 36756, 14, 14, 7626, 14, 15, 10930, // 13,15
+ 13, -1, 7983, 13, 0, 11267, 14, -1, 10780, 14, 0, 35506, // 14, 0
+ 13, 0, 7579, 13, 1, 10532, 14, 0, 10467, 14, 1, 36958, // 14, 1
+ 13, 1, 7179, 13, 2, 9834, 14, 1, 10133, 14, 2, 38390, // 14, 2
+ 13, 2, 6797, 13, 3, 9184, 14, 2, 9796, 14, 3, 39759, // 14, 3
+ 13, 3, 6447, 13, 4, 8599, 14, 3, 9478, 14, 4, 41012, // 14, 4
+ 13, 4, 6145, 13, 5, 8098, 14, 4, 9206, 14, 5, 42087, // 14, 5
+ 13, 5, 5910, 13, 6, 7699, 14, 5, 9014, 14, 6, 42913, // 14, 6
+ 13, 6, 5756, 13, 7, 7418, 14, 6, 8929, 14, 7, 43433, // 14, 7
+ 14, 7, 8939, 14, 8, 43461, 15, 7, 5745, 15, 8, 7391, // 14, 8
+ 14, 8, 9032, 14, 9, 42936, 15, 8, 5900, 15, 9, 7668, // 14, 9
+ 14, 9, 9233, 14, 10, 42105, 15, 9, 6137, 15, 10, 8061, // 14,10
+ 14, 10, 9513, 14, 11, 41026, 15, 10, 6440, 15, 11, 8557, // 14,11
+ 14, 11, 9841, 14, 12, 39767, 15, 11, 6792, 15, 12, 9136, // 14,12
+ 14, 12, 10188, 14, 13, 38394, 15, 12, 7177, 15, 13, 9777, // 14,13
+ 14, 13, 10532, 14, 14, 36959, 15, 13, 7579, 15, 14, 10466, // 14,14
+ 14, 14, 10855, 14, 15, 35502, 15, 14, 7987, 15, 15, 11192, // 14,15
+ 14, -1, 8358, 14, 0, 11526, 15, -1, 11440, 15, 0, 34212, // 15, 0
+ 14, 0, 7987, 14, 1, 10855, 15, 0, 11192, 15, 1, 35502, // 15, 1
+ 14, 1, 7626, 14, 2, 10224, 15, 1, 10930, 15, 2, 36756, // 15, 2
+ 14, 2, 7285, 14, 3, 9642, 15, 2, 10670, 15, 3, 37939, // 15, 3
+ 14, 3, 6975, 14, 4, 9122, 15, 3, 10430, 15, 4, 39009, // 15, 4
+ 14, 4, 6710, 14, 5, 8676, 15, 4, 10232, 15, 5, 39918, // 15, 5
+ 14, 5, 6502, 14, 6, 8316, 15, 5, 10100, 15, 6, 40618, // 15, 6
+ 14, 6, 6360, 14, 7, 8052, 15, 6, 10052, 15, 7, 41072, // 15, 7
+ 15, 7, 10066, 15, 8, 41106, 16, 7, 6346, 16, 8, 8018, // 15, 8
+ 15, 8, 10123, 15, 9, 40646, 16, 8, 6489, 16, 9, 8278, // 15, 9
+ 15, 9, 10265, 15, 10, 39940, 16, 9, 6699, 16, 10, 8632, // 15,10
+ 15, 10, 10473, 15, 11, 39026, 16, 10, 6965, 16, 11, 9072, // 15,11
+ 15, 11, 10723, 15, 12, 37951, 16, 11, 7276, 16, 12, 9586, // 15,12
+ 15, 12, 10994, 15, 13, 36764, 16, 12, 7620, 16, 13, 10158, // 15,13
+ 15, 13, 11267, 15, 14, 35506, 16, 13, 7983, 16, 14, 10780, // 15,14
+ 15, 14, 11526, 15, 15, 34212, 16, 14, 8358, 16, 15, 11440, // 15,15
+ // angle of -1.0 degrees
+ -1, 0, 8769, -1, 1, 6280, 0, 0, 41693, 0, 1, 8794, // 0, 0
+ -1, 1, 8265, -1, 2, 5974, 0, 1, 42823, 0, 2, 8474, // 0, 1
+ -1, 2, 7791, -1, 3, 5682, 0, 2, 43904, 0, 3, 8159, // 0, 2
+ -1, 3, 7356, -1, 4, 5410, 0, 3, 44907, 0, 4, 7863, // 0, 3
+ -1, 4, 6970, -1, 5, 5169, 0, 4, 45799, 0, 5, 7598, // 0, 4
+ -1, 5, 6644, -1, 6, 4967, 0, 5, 46541, 0, 6, 7384, // 0, 5
+ -1, 6, 6391, -1, 7, 4814, 0, 6, 47098, 0, 7, 7233, // 0, 6
+ -1, 7, 6217, -1, 8, 4718, 0, 7, 47440, 0, 8, 7161, // 0, 7
+ 0, 8, 47426, 0, 9, 7158, 1, 8, 6230, 1, 9, 4722, // 0, 8
+ 0, 9, 47086, 0, 10, 7227, 1, 9, 6405, 1, 10, 4818, // 0, 9
+ 0, 10, 46532, 0, 11, 7374, 1, 10, 6659, 1, 11, 4971, // 0,10
+ 0, 11, 45791, 0, 12, 7587, 1, 11, 6986, 1, 12, 5172, // 0,11
+ 0, 12, 44901, 0, 13, 7848, 1, 12, 7374, 1, 13, 5413, // 0,12
+ 0, 13, 43900, 0, 14, 8141, 1, 13, 7812, 1, 14, 5683, // 0,13
+ 0, 14, 42821, 0, 15, 8452, 1, 14, 8288, 1, 15, 5975, // 0,14
+ 0, 15, 41693, 0, 16, 8769, 1, 15, 8795, 1, 16, 6279, // 0,15
+ 0, 0, 8452, 0, 1, 5975, 1, 0, 42821, 1, 1, 8288, // 1, 0
+ 0, 1, 7901, 0, 2, 5640, 1, 1, 44074, 1, 2, 7921, // 1, 1
+ 0, 2, 7378, 0, 3, 5315, 1, 2, 45288, 1, 3, 7555, // 1, 2
+ 0, 3, 6892, 0, 4, 5009, 1, 3, 46430, 1, 4, 7205, // 1, 3
+ 0, 4, 6458, 0, 5, 4734, 1, 4, 47458, 1, 5, 6886, // 1, 4
+ 0, 5, 6092, 0, 6, 4502, 1, 5, 48322, 1, 6, 6620, // 1, 5
+ 0, 6, 5809, 0, 7, 4327, 1, 6, 48969, 1, 7, 6431, // 1, 6
+ 0, 7, 5623, 0, 8, 4221, 1, 7, 49358, 1, 8, 6334, // 1, 7
+ 1, 8, 49347, 1, 9, 6332, 2, 8, 5633, 2, 9, 4224, // 1, 8
+ 1, 9, 48960, 1, 10, 6425, 2, 9, 5820, 2, 10, 4331, // 1, 9
+ 1, 10, 48314, 1, 11, 6613, 2, 10, 6104, 2, 11, 4505, // 1,10
+ 1, 11, 47453, 1, 12, 6875, 2, 11, 6472, 2, 12, 4736, // 1,11
+ 1, 12, 46427, 1, 13, 7191, 2, 12, 6908, 2, 13, 5010, // 1,12
+ 1, 13, 45286, 1, 14, 7539, 2, 13, 7395, 2, 14, 5316, // 1,13
+ 1, 14, 44074, 1, 15, 7901, 2, 14, 7921, 2, 15, 5640, // 1,14
+ 1, 15, 42823, 1, 16, 8265, 2, 15, 8474, 2, 16, 5974, // 1,15
+ 1, 0, 8141, 1, 1, 5684, 2, 0, 43900, 2, 1, 7811, // 2, 0
+ 1, 1, 7539, 1, 2, 5316, 2, 1, 45286, 2, 2, 7395, // 2, 1
+ 1, 2, 6959, 1, 3, 4954, 2, 2, 46650, 2, 3, 6973, // 2, 2
+ 1, 3, 6414, 1, 4, 4607, 2, 3, 47955, 2, 4, 6560, // 2, 3
+ 1, 4, 5920, 1, 5, 4290, 2, 4, 49150, 2, 5, 6176, // 2, 4
+ 1, 5, 5499, 1, 6, 4019, 2, 5, 50171, 2, 6, 5847, // 2, 5
+ 1, 6, 5175, 1, 7, 3813, 2, 6, 50942, 2, 7, 5606, // 2, 6
+ 1, 7, 4970, 1, 8, 3691, 2, 7, 51395, 2, 8, 5480, // 2, 7
+ 2, 8, 51387, 2, 9, 5478, 3, 8, 4978, 3, 9, 3693, // 2, 8
+ 2, 9, 50935, 2, 10, 5602, 3, 9, 5184, 3, 10, 3815, // 2, 9
+ 2, 10, 50165, 2, 11, 5842, 3, 10, 5508, 3, 11, 4021, // 2,10
+ 2, 11, 49147, 2, 12, 6168, 3, 11, 5930, 3, 12, 4291, // 2,11
+ 2, 12, 47953, 2, 13, 6549, 3, 12, 6426, 3, 13, 4608, // 2,12
+ 2, 13, 46650, 2, 14, 6959, 3, 13, 6973, 3, 14, 4954, // 2,13
+ 2, 14, 45288, 2, 15, 7378, 3, 14, 7555, 3, 15, 5315, // 2,14
+ 2, 15, 43904, 2, 16, 7791, 3, 15, 8159, 3, 16, 5682, // 2,15
+ 2, 0, 7848, 2, 1, 5413, 3, 0, 44901, 3, 1, 7374, // 3, 0
+ 2, 1, 7191, 2, 2, 5011, 3, 1, 46427, 3, 2, 6907, // 3, 1
+ 2, 2, 6549, 2, 3, 4608, 3, 2, 47953, 3, 3, 6426, // 3, 2
+ 2, 3, 5934, 2, 4, 4214, 3, 3, 49445, 3, 4, 5943, // 3, 3
+ 2, 4, 5365, 2, 5, 3845, 3, 4, 50844, 3, 5, 5482, // 3, 4
+ 2, 5, 4872, 2, 6, 3522, 3, 5, 52069, 3, 6, 5073, // 3, 5
+ 2, 6, 4489, 2, 7, 3273, 3, 6, 53012, 3, 7, 4762, // 3, 6
+ 2, 7, 4254, 2, 8, 3126, 3, 7, 53562, 3, 8, 4594, // 3, 7
+ 3, 8, 53557, 3, 9, 4592, 4, 8, 4259, 4, 9, 3128, // 3, 8
+ 3, 9, 53008, 3, 10, 4759, 4, 9, 4495, 4, 10, 3274, // 3, 9
+ 3, 10, 52066, 3, 11, 5069, 4, 10, 4879, 4, 11, 3522, // 3,10
+ 3, 11, 50843, 3, 12, 5474, 4, 11, 5373, 4, 12, 3846, // 3,11
+ 3, 12, 49445, 3, 13, 5934, 4, 12, 5943, 4, 13, 4214, // 3,12
+ 3, 13, 47955, 3, 14, 6414, 4, 13, 6560, 4, 14, 4607, // 3,13
+ 3, 14, 46430, 3, 15, 6892, 4, 14, 7204, 4, 15, 5010, // 3,14
+ 3, 15, 44907, 3, 16, 7356, 4, 15, 7863, 4, 16, 5410, // 3,15
+ 3, 0, 7587, 3, 1, 5172, 4, 0, 45791, 4, 1, 6986, // 4, 0
+ 3, 1, 6875, 3, 2, 4736, 4, 1, 47453, 4, 2, 6472, // 4, 1
+ 3, 2, 6168, 3, 3, 4291, 4, 2, 49147, 4, 3, 5930, // 4, 2
+ 3, 3, 5474, 3, 4, 3846, 4, 3, 50843, 4, 4, 5373, // 4, 3
+ 3, 4, 4816, 3, 5, 3415, 4, 4, 52484, 4, 5, 4821, // 4, 4
+ 3, 5, 4226, 3, 6, 3023, 4, 5, 53975, 4, 6, 4312, // 4, 5
+ 3, 6, 3755, 3, 7, 2710, 4, 6, 55166, 4, 7, 3905, // 4, 6
+ 3, 7, 3469, 3, 8, 2524, 4, 7, 55870, 4, 8, 3673, // 4, 7
+ 4, 8, 55867, 4, 9, 3671, 5, 8, 3473, 5, 9, 2525, // 4, 8
+ 4, 9, 55164, 4, 10, 3902, 5, 9, 3759, 5, 10, 2711, // 4, 9
+ 4, 10, 53973, 4, 11, 4309, 5, 10, 4230, 5, 11, 3024, // 4,10
+ 4, 11, 52484, 4, 12, 4816, 5, 11, 4822, 5, 12, 3414, // 4,11
+ 4, 12, 50844, 4, 13, 5365, 5, 12, 5481, 5, 13, 3846, // 4,12
+ 4, 13, 49150, 4, 14, 5920, 5, 13, 6176, 5, 14, 4290, // 4,13
+ 4, 14, 47458, 4, 15, 6458, 5, 14, 6886, 5, 15, 4734, // 4,14
+ 4, 15, 45799, 4, 16, 6970, 5, 15, 7599, 5, 16, 5168, // 4,15
+ 4, 0, 7374, 4, 1, 4971, 5, 0, 46532, 5, 1, 6659, // 5, 0
+ 4, 1, 6613, 4, 2, 4505, 5, 1, 48314, 5, 2, 6104, // 5, 1
+ 4, 2, 5842, 4, 3, 4020, 5, 2, 50165, 5, 3, 5509, // 5, 2
+ 4, 3, 5069, 4, 4, 3523, 5, 3, 52066, 5, 4, 4878, // 5, 3
+ 4, 4, 4309, 4, 5, 3023, 5, 4, 53973, 5, 5, 4231, // 5, 4
+ 4, 5, 3595, 4, 6, 2546, 5, 5, 55798, 5, 6, 3597, // 5, 5
+ 4, 6, 2993, 4, 7, 2138, 5, 6, 57354, 5, 7, 3051, // 5, 6
+ 4, 7, 2615, 4, 8, 1884, 5, 7, 58324, 5, 8, 2713, // 5, 7
+ 5, 8, 58322, 5, 9, 2713, 6, 8, 2616, 6, 9, 1885, // 5, 8
+ 5, 9, 57353, 5, 10, 3050, 6, 9, 2995, 6, 10, 2138, // 5, 9
+ 5, 10, 55798, 5, 11, 3595, 6, 10, 3598, 6, 11, 2545, // 5,10
+ 5, 11, 53975, 5, 12, 4226, 6, 11, 4313, 6, 12, 3022, // 5,11
+ 5, 12, 52069, 5, 13, 4872, 6, 12, 5073, 6, 13, 3522, // 5,12
+ 5, 13, 50171, 5, 14, 5499, 6, 13, 5848, 6, 14, 4018, // 5,13
+ 5, 14, 48322, 5, 15, 6092, 6, 14, 6620, 6, 15, 4502, // 5,14
+ 5, 15, 46541, 5, 16, 6644, 6, 15, 7383, 6, 16, 4968, // 5,15
+ 5, 0, 7227, 5, 1, 4818, 6, 0, 47086, 6, 1, 6405, // 6, 0
+ 5, 1, 6425, 5, 2, 4330, 6, 1, 48960, 6, 2, 5821, // 6, 1
+ 5, 2, 5602, 5, 3, 3815, 6, 2, 50935, 6, 3, 5184, // 6, 2
+ 5, 3, 4759, 5, 4, 3274, 6, 3, 53008, 6, 4, 4495, // 6, 3
+ 5, 4, 3902, 5, 5, 2711, 6, 4, 55164, 6, 5, 3759, // 6, 4
+ 5, 5, 3050, 5, 6, 2138, 6, 5, 57353, 6, 6, 2995, // 6, 5
+ 5, 6, 2258, 5, 7, 1597, 6, 6, 59422, 6, 7, 2259, // 6, 6
+ 5, 7, 1695, 5, 8, 1209, 6, 7, 60906, 6, 8, 1726, // 6, 7
+ 6, 8, 60905, 6, 9, 1726, 7, 8, 1695, 7, 9, 1210, // 6, 8
+ 6, 9, 59422, 6, 10, 2258, 7, 9, 2259, 7, 10, 1597, // 6, 9
+ 6, 10, 57354, 6, 11, 2993, 7, 10, 3051, 7, 11, 2138, // 6,10
+ 6, 11, 55166, 6, 12, 3755, 7, 11, 3904, 7, 12, 2711, // 6,11
+ 6, 12, 53012, 6, 13, 4489, 7, 12, 4762, 7, 13, 3273, // 6,12
+ 6, 13, 50942, 6, 14, 5175, 7, 13, 5606, 7, 14, 3813, // 6,13
+ 6, 14, 48969, 6, 15, 5809, 7, 14, 6430, 7, 15, 4328, // 6,14
+ 6, 15, 47098, 6, 16, 6391, 7, 15, 7233, 7, 16, 4814, // 6,15
+ 6, 0, 7158, 6, 1, 4722, 7, 0, 47426, 7, 1, 6230, // 7, 0
+ 6, 1, 6332, 6, 2, 4224, 7, 1, 49347, 7, 2, 5633, // 7, 1
+ 6, 2, 5478, 6, 3, 3693, 7, 2, 51387, 7, 3, 4978, // 7, 2
+ 6, 3, 4592, 6, 4, 3128, 7, 3, 53557, 7, 4, 4259, // 7, 3
+ 6, 4, 3671, 6, 5, 2525, 7, 4, 55867, 7, 5, 3473, // 7, 4
+ 6, 5, 2713, 6, 6, 1884, 7, 5, 58322, 7, 6, 2617, // 7, 5
+ 6, 6, 1726, 6, 7, 1210, 7, 6, 60905, 7, 7, 1695, // 7, 6
+ 6, 7, 789, 6, 8, 558, 7, 7, 63399, 7, 8, 790, // 7, 7
+ 7, 8, 63399, 7, 9, 789, 8, 8, 789, 8, 9, 559, // 7, 8
+ 7, 9, 60906, 7, 10, 1695, 8, 9, 1726, 8, 10, 1209, // 7, 9
+ 7, 10, 58324, 7, 11, 2615, 8, 10, 2714, 8, 11, 1883, // 7,10
+ 7, 11, 55870, 7, 12, 3469, 8, 11, 3672, 8, 12, 2525, // 7,11
+ 7, 12, 53562, 7, 13, 4254, 8, 12, 4594, 8, 13, 3126, // 7,12
+ 7, 13, 51395, 7, 14, 4970, 8, 13, 5480, 8, 14, 3691, // 7,13
+ 7, 14, 49358, 7, 15, 5623, 8, 14, 6335, 8, 15, 4220, // 7,14
+ 7, 15, 47440, 7, 16, 6217, 8, 15, 7161, 8, 16, 4718, // 7,15
+ 7, -1, 4718, 7, 0, 7161, 8, -1, 6217, 8, 0, 47440, // 8, 0
+ 7, 0, 4221, 7, 1, 6335, 8, 0, 5623, 8, 1, 49357, // 8, 1
+ 7, 1, 3691, 7, 2, 5480, 8, 1, 4970, 8, 2, 51395, // 8, 2
+ 7, 2, 3126, 7, 3, 4594, 8, 2, 4254, 8, 3, 53562, // 8, 3
+ 7, 3, 2524, 7, 4, 3672, 8, 3, 3469, 8, 4, 55871, // 8, 4
+ 7, 4, 1884, 7, 5, 2714, 8, 4, 2615, 8, 5, 58323, // 8, 5
+ 7, 5, 1209, 7, 6, 1726, 8, 5, 1695, 8, 6, 60906, // 8, 6
+ 7, 6, 558, 7, 7, 789, 8, 6, 789, 8, 7, 63400, // 8, 7
+ 8, 7, 789, 8, 8, 63399, 9, 7, 558, 9, 8, 790, // 8, 8
+ 8, 8, 1695, 8, 9, 60905, 9, 8, 1210, 9, 9, 1726, // 8, 9
+ 8, 9, 2616, 8, 10, 58322, 9, 9, 1884, 9, 10, 2714, // 8,10
+ 8, 10, 3473, 8, 11, 55867, 9, 10, 2525, 9, 11, 3671, // 8,11
+ 8, 11, 4259, 8, 12, 53557, 9, 11, 3128, 9, 12, 4592, // 8,12
+ 8, 12, 4978, 8, 13, 51387, 9, 12, 3693, 9, 13, 5478, // 8,13
+ 8, 13, 5633, 8, 14, 49347, 9, 13, 4224, 9, 14, 6332, // 8,14
+ 8, 14, 6230, 8, 15, 47426, 9, 14, 4722, 9, 15, 7158, // 8,15
+ 8, -1, 4814, 8, 0, 7233, 9, -1, 6391, 9, 0, 47098, // 9, 0
+ 8, 0, 4327, 8, 1, 6430, 9, 0, 5809, 9, 1, 48970, // 9, 1
+ 8, 1, 3813, 8, 2, 5606, 9, 1, 5175, 9, 2, 50942, // 9, 2
+ 8, 2, 3273, 8, 3, 4762, 9, 2, 4489, 9, 3, 53012, // 9, 3
+ 8, 3, 2710, 8, 4, 3904, 9, 3, 3755, 9, 4, 55167, // 9, 4
+ 8, 4, 2138, 8, 5, 3051, 9, 4, 2993, 9, 5, 57354, // 9, 5
+ 8, 5, 1597, 8, 6, 2259, 9, 5, 2258, 9, 6, 59422, // 9, 6
+ 8, 6, 1210, 8, 7, 1695, 9, 6, 1726, 9, 7, 60905, // 9, 7
+ 9, 7, 1726, 9, 8, 60906, 10, 7, 1209, 10, 8, 1695, // 9, 8
+ 9, 8, 2259, 9, 9, 59422, 10, 8, 1597, 10, 9, 2258, // 9, 9
+ 9, 9, 2995, 9, 10, 57353, 10, 9, 2138, 10, 10, 3050, // 9,10
+ 9, 10, 3759, 9, 11, 55164, 10, 10, 2711, 10, 11, 3902, // 9,11
+ 9, 11, 4495, 9, 12, 53008, 10, 11, 3274, 10, 12, 4759, // 9,12
+ 9, 12, 5184, 9, 13, 50935, 10, 12, 3815, 10, 13, 5602, // 9,13
+ 9, 13, 5820, 9, 14, 48960, 10, 13, 4330, 10, 14, 6426, // 9,14
+ 9, 14, 6405, 9, 15, 47086, 10, 14, 4818, 10, 15, 7227, // 9,15
+ 9, -1, 4967, 9, 0, 7383, 10, -1, 6644, 10, 0, 46542, // 10, 0
+ 9, 0, 4502, 9, 1, 6620, 10, 0, 6092, 10, 1, 48322, // 10, 1
+ 9, 1, 4019, 9, 2, 5848, 10, 1, 5499, 10, 2, 50170, // 10, 2
+ 9, 2, 3522, 9, 3, 5073, 10, 2, 4872, 10, 3, 52069, // 10, 3
+ 9, 3, 3023, 9, 4, 4313, 10, 3, 4226, 10, 4, 53974, // 10, 4
+ 9, 4, 2546, 9, 5, 3598, 10, 4, 3595, 10, 5, 55797, // 10, 5
+ 9, 5, 2138, 9, 6, 2995, 10, 5, 3050, 10, 6, 57353, // 10, 6
+ 9, 6, 1884, 9, 7, 2616, 10, 6, 2713, 10, 7, 58323, // 10, 7
+ 10, 7, 2714, 10, 8, 58324, 11, 7, 1884, 11, 8, 2614, // 10, 8
+ 10, 8, 3051, 10, 9, 57354, 11, 8, 2138, 11, 9, 2993, // 10, 9
+ 10, 9, 3598, 10, 10, 55798, 11, 9, 2546, 11, 10, 3594, // 10,10
+ 10, 10, 4230, 10, 11, 53973, 11, 10, 3023, 11, 11, 4310, // 10,11
+ 10, 11, 4879, 10, 12, 52066, 11, 11, 3523, 11, 12, 5068, // 10,12
+ 10, 12, 5508, 10, 13, 50165, 11, 12, 4020, 11, 13, 5843, // 10,13
+ 10, 13, 6104, 10, 14, 48314, 11, 13, 4505, 11, 14, 6613, // 10,14
+ 10, 14, 6659, 10, 15, 46532, 11, 14, 4971, 11, 15, 7374, // 10,15
+ 10, -1, 5169, 10, 0, 7599, 11, -1, 6970, 11, 0, 45798, // 11, 0
+ 10, 0, 4734, 10, 1, 6886, 11, 0, 6458, 11, 1, 47458, // 11, 1
+ 10, 1, 4290, 10, 2, 6176, 11, 1, 5920, 11, 2, 49150, // 11, 2
+ 10, 2, 3845, 10, 3, 5481, 11, 2, 5365, 11, 3, 50845, // 11, 3
+ 10, 3, 3415, 10, 4, 4822, 11, 3, 4816, 11, 4, 52483, // 11, 4
+ 10, 4, 3023, 10, 5, 4230, 11, 4, 4309, 11, 5, 53974, // 11, 5
+ 10, 5, 2711, 10, 6, 3759, 11, 5, 3902, 11, 6, 55164, // 11, 6
+ 10, 6, 2525, 10, 7, 3473, 11, 6, 3671, 11, 7, 55867, // 11, 7
+ 11, 7, 3672, 11, 8, 55870, 12, 7, 2524, 12, 8, 3470, // 11, 8
+ 11, 8, 3904, 11, 9, 55166, 12, 8, 2710, 12, 9, 3756, // 11, 9
+ 11, 9, 4313, 11, 10, 53975, 12, 9, 3023, 12, 10, 4225, // 11,10
+ 11, 10, 4822, 11, 11, 52484, 12, 10, 3415, 12, 11, 4815, // 11,11
+ 11, 11, 5373, 11, 12, 50843, 12, 11, 3846, 12, 12, 5474, // 11,12
+ 11, 12, 5930, 11, 13, 49147, 12, 12, 4291, 12, 13, 6168, // 11,13
+ 11, 13, 6472, 11, 14, 47453, 12, 13, 4736, 12, 14, 6875, // 11,14
+ 11, 14, 6986, 11, 15, 45791, 12, 14, 5172, 12, 15, 7587, // 11,15
+ 11, -1, 5410, 11, 0, 7863, 12, -1, 7356, 12, 0, 44907, // 12, 0
+ 11, 0, 5009, 11, 1, 7204, 12, 0, 6892, 12, 1, 46431, // 12, 1
+ 11, 1, 4607, 11, 2, 6560, 12, 1, 6414, 12, 2, 47955, // 12, 2
+ 11, 2, 4214, 11, 3, 5943, 12, 2, 5934, 12, 3, 49445, // 12, 3
+ 11, 3, 3846, 11, 4, 5373, 12, 3, 5474, 12, 4, 50843, // 12, 4
+ 11, 4, 3523, 11, 5, 4879, 12, 4, 5069, 12, 5, 52065, // 12, 5
+ 11, 5, 3274, 11, 6, 4495, 12, 5, 4759, 12, 6, 53008, // 12, 6
+ 11, 6, 3128, 11, 7, 4259, 12, 6, 4592, 12, 7, 53557, // 12, 7
+ 12, 7, 4594, 12, 8, 53562, 13, 7, 3126, 13, 8, 4254, // 12, 8
+ 12, 8, 4762, 12, 9, 53012, 13, 8, 3273, 13, 9, 4489, // 12, 9
+ 12, 9, 5073, 12, 10, 52069, 13, 9, 3522, 13, 10, 4872, // 12,10
+ 12, 10, 5481, 12, 11, 50844, 13, 10, 3845, 13, 11, 5366, // 12,11
+ 12, 11, 5943, 12, 12, 49445, 13, 11, 4214, 13, 12, 5934, // 12,12
+ 12, 12, 6426, 12, 13, 47953, 13, 12, 4608, 13, 13, 6549, // 12,13
+ 12, 13, 6908, 12, 14, 46427, 13, 13, 5011, 13, 14, 7190, // 12,14
+ 12, 14, 7374, 12, 15, 44901, 13, 14, 5413, 13, 15, 7848, // 12,15
+ 12, -1, 5682, 12, 0, 8159, 13, -1, 7791, 13, 0, 43904, // 13, 0
+ 12, 0, 5315, 12, 1, 7555, 13, 0, 7378, 13, 1, 45288, // 13, 1
+ 12, 1, 4954, 12, 2, 6973, 13, 1, 6959, 13, 2, 46650, // 13, 2
+ 12, 2, 4608, 12, 3, 6426, 13, 2, 6549, 13, 3, 47953, // 13, 3
+ 12, 3, 4291, 12, 4, 5930, 13, 3, 6168, 13, 4, 49147, // 13, 4
+ 12, 4, 4020, 12, 5, 5508, 13, 4, 5842, 13, 5, 50166, // 13, 5
+ 12, 5, 3815, 12, 6, 5184, 13, 5, 5602, 13, 6, 50935, // 13, 6
+ 12, 6, 3693, 12, 7, 4978, 13, 6, 5478, 13, 7, 51387, // 13, 7
+ 13, 7, 5480, 13, 8, 51395, 14, 7, 3691, 14, 8, 4970, // 13, 8
+ 13, 8, 5606, 13, 9, 50942, 14, 8, 3813, 14, 9, 5175, // 13, 9
+ 13, 9, 5848, 13, 10, 50171, 14, 9, 4019, 14, 10, 5498, // 13,10
+ 13, 10, 6176, 13, 11, 49150, 14, 10, 4290, 14, 11, 5920, // 13,11
+ 13, 11, 6560, 13, 12, 47955, 14, 11, 4607, 14, 12, 6414, // 13,12
+ 13, 12, 6973, 13, 13, 46650, 14, 12, 4954, 14, 13, 6959, // 13,13
+ 13, 13, 7395, 13, 14, 45286, 14, 13, 5316, 14, 14, 7539, // 13,14
+ 13, 14, 7812, 13, 15, 43900, 14, 14, 5684, 14, 15, 8140, // 13,15
+ 13, -1, 5974, 13, 0, 8474, 14, -1, 8265, 14, 0, 42823, // 14, 0
+ 13, 0, 5640, 13, 1, 7921, 14, 0, 7901, 14, 1, 44074, // 14, 1
+ 13, 1, 5316, 13, 2, 7395, 14, 1, 7539, 14, 2, 45286, // 14, 2
+ 13, 2, 5011, 13, 3, 6908, 14, 2, 7191, 14, 3, 46426, // 14, 3
+ 13, 3, 4736, 13, 4, 6472, 14, 3, 6875, 14, 4, 47453, // 14, 4
+ 13, 4, 4505, 13, 5, 6104, 14, 4, 6613, 14, 5, 48314, // 14, 5
+ 13, 5, 4330, 13, 6, 5820, 14, 5, 6425, 14, 6, 48961, // 14, 6
+ 13, 6, 4224, 13, 7, 5633, 14, 6, 6332, 14, 7, 49347, // 14, 7
+ 14, 7, 6335, 14, 8, 49358, 15, 7, 4221, 15, 8, 5622, // 14, 8
+ 14, 8, 6430, 14, 9, 48969, 15, 8, 4327, 15, 9, 5810, // 14, 9
+ 14, 9, 6620, 14, 10, 48322, 15, 9, 4502, 15, 10, 6092, // 14,10
+ 14, 10, 6886, 14, 11, 47458, 15, 10, 4734, 15, 11, 6458, // 14,11
+ 14, 11, 7204, 14, 12, 46430, 15, 11, 5009, 15, 12, 6893, // 14,12
+ 14, 12, 7555, 14, 13, 45288, 15, 12, 5315, 15, 13, 7378, // 14,13
+ 14, 13, 7921, 14, 14, 44074, 15, 13, 5640, 15, 14, 7901, // 14,14
+ 14, 14, 8288, 14, 15, 42821, 15, 14, 5975, 15, 15, 8452, // 14,15
+ 14, -1, 6280, 14, 0, 8795, 15, -1, 8769, 15, 0, 41692, // 15, 0
+ 14, 0, 5975, 14, 1, 8288, 15, 0, 8452, 15, 1, 42821, // 15, 1
+ 14, 1, 5684, 14, 2, 7812, 15, 1, 8141, 15, 2, 43899, // 15, 2
+ 14, 2, 5413, 14, 3, 7374, 15, 2, 7848, 15, 3, 44901, // 15, 3
+ 14, 3, 5172, 14, 4, 6986, 15, 3, 7587, 15, 4, 45791, // 15, 4
+ 14, 4, 4971, 14, 5, 6659, 15, 4, 7374, 15, 5, 46532, // 15, 5
+ 14, 5, 4818, 14, 6, 6405, 15, 5, 7227, 15, 6, 47086, // 15, 6
+ 14, 6, 4722, 14, 7, 6230, 15, 6, 7158, 15, 7, 47426, // 15, 7
+ 15, 7, 7161, 15, 8, 47440, 16, 7, 4718, 16, 8, 6217, // 15, 8
+ 15, 8, 7233, 15, 9, 47098, 16, 8, 4814, 16, 9, 6391, // 15, 9
+ 15, 9, 7383, 15, 10, 46541, 16, 9, 4967, 16, 10, 6645, // 15,10
+ 15, 10, 7599, 15, 11, 45799, 16, 10, 5169, 16, 11, 6969, // 15,11
+ 15, 11, 7863, 15, 12, 44907, 16, 11, 5410, 16, 12, 7356, // 15,12
+ 15, 12, 8159, 15, 13, 43904, 16, 12, 5682, 16, 13, 7791, // 15,13
+ 15, 13, 8474, 15, 14, 42823, 16, 13, 5974, 16, 14, 8265, // 15,14
+ 15, 14, 8795, 15, 15, 41693, 16, 14, 6280, 16, 15, 8768, // 15,15
+ // angle of -0.5 degrees
+ -1, 0, 5106, -1, 1, 3621, 0, 0, 51699, 0, 1, 5110, // 0, 0
+ -1, 1, 4803, -1, 2, 3421, 0, 1, 52457, 0, 2, 4855, // 0, 1
+ -1, 2, 4521, -1, 3, 3235, 0, 2, 53168, 0, 3, 4612, // 0, 2
+ -1, 3, 4264, -1, 4, 3064, 0, 3, 53815, 0, 4, 4393, // 0, 3
+ -1, 4, 4041, -1, 5, 2916, 0, 4, 54378, 0, 5, 4201, // 0, 4
+ -1, 5, 3858, -1, 6, 2796, 0, 5, 54835, 0, 6, 4047, // 0, 5
+ -1, 6, 3722, -1, 7, 2709, 0, 6, 55166, 0, 7, 3939, // 0, 6
+ -1, 7, 3638, -1, 8, 2659, 0, 7, 55354, 0, 8, 3885, // 0, 7
+ 0, 8, 55352, 0, 9, 3885, 1, 8, 3640, 1, 9, 2659, // 0, 8
+ 0, 9, 55164, 0, 10, 3939, 1, 9, 3724, 1, 10, 2709, // 0, 9
+ 0, 10, 54833, 0, 11, 4046, 1, 10, 3860, 1, 11, 2797, // 0,10
+ 0, 11, 54376, 0, 12, 4200, 1, 11, 4043, 1, 12, 2917, // 0,11
+ 0, 12, 53814, 0, 13, 4390, 1, 12, 4267, 1, 13, 3065, // 0,12
+ 0, 13, 53168, 0, 14, 4610, 1, 13, 4523, 1, 14, 3235, // 0,13
+ 0, 14, 52457, 0, 15, 4851, 1, 14, 4806, 1, 15, 3422, // 0,14
+ 0, 15, 51699, 0, 16, 5106, 1, 15, 5110, 1, 16, 3621, // 0,15
+ 0, 0, 4851, 0, 1, 3422, 1, 0, 52457, 1, 1, 4806, // 1, 0
+ 0, 1, 4522, 0, 2, 3204, 1, 1, 53285, 1, 2, 4525, // 1, 1
+ 0, 2, 4212, 0, 3, 2998, 1, 2, 54072, 1, 3, 4254, // 1, 2
+ 0, 3, 3927, 0, 4, 2808, 1, 3, 54796, 1, 4, 4005, // 1, 3
+ 0, 4, 3677, 0, 5, 2640, 1, 4, 55435, 1, 5, 3784, // 1, 4
+ 0, 5, 3470, 0, 6, 2502, 1, 5, 55959, 1, 6, 3605, // 1, 5
+ 0, 6, 3317, 0, 7, 2402, 1, 6, 56340, 1, 7, 3477, // 1, 6
+ 0, 7, 3225, 0, 8, 2346, 1, 7, 56554, 1, 8, 3411, // 1, 7
+ 1, 8, 56552, 1, 9, 3411, 2, 8, 3227, 2, 9, 2346, // 1, 8
+ 1, 9, 56339, 1, 10, 3476, 2, 9, 3319, 2, 10, 2402, // 1, 9
+ 1, 10, 55958, 1, 11, 3604, 2, 10, 3472, 2, 11, 2502, // 1,10
+ 1, 11, 55434, 1, 12, 3783, 2, 11, 3678, 2, 12, 2641, // 1,11
+ 1, 12, 54796, 1, 13, 4003, 2, 12, 3929, 2, 13, 2808, // 1,12
+ 1, 13, 54071, 1, 14, 4253, 2, 13, 4214, 2, 14, 2998, // 1,13
+ 1, 14, 53285, 1, 15, 4522, 2, 14, 4525, 2, 15, 3204, // 1,14
+ 1, 15, 52457, 1, 16, 4803, 2, 15, 4854, 2, 16, 3422, // 1,15
+ 1, 0, 4610, 1, 1, 3235, 2, 0, 53168, 2, 1, 4523, // 2, 0
+ 1, 1, 4253, 1, 2, 2998, 2, 1, 54071, 2, 2, 4214, // 2, 1
+ 1, 2, 3911, 1, 3, 2770, 2, 2, 54941, 2, 3, 3914, // 2, 2
+ 1, 3, 3594, 1, 4, 2556, 2, 3, 55756, 2, 4, 3630, // 2, 3
+ 1, 4, 3310, 1, 5, 2365, 2, 4, 56487, 2, 5, 3374, // 2, 4
+ 1, 5, 3073, 1, 6, 2205, 2, 5, 57096, 2, 6, 3162, // 2, 5
+ 1, 6, 2897, 1, 7, 2088, 2, 6, 57545, 2, 7, 3006, // 2, 6
+ 1, 7, 2794, 1, 8, 2022, 2, 7, 57795, 2, 8, 2925, // 2, 7
+ 2, 8, 57793, 2, 9, 2926, 3, 8, 2795, 3, 9, 2022, // 2, 8
+ 2, 9, 57544, 2, 10, 3007, 3, 9, 2898, 3, 10, 2087, // 2, 9
+ 2, 10, 57095, 2, 11, 3161, 3, 10, 3074, 3, 11, 2206, // 2,10
+ 2, 11, 56486, 2, 12, 3373, 3, 11, 3311, 3, 12, 2366, // 2,11
+ 2, 12, 55756, 2, 13, 3628, 3, 12, 3595, 3, 13, 2557, // 2,12
+ 2, 13, 54941, 2, 14, 3911, 3, 13, 3913, 3, 14, 2771, // 2,13
+ 2, 14, 54072, 2, 15, 4212, 3, 14, 4255, 3, 15, 2997, // 2,14
+ 2, 15, 53168, 2, 16, 4521, 3, 15, 4612, 3, 16, 3235, // 2,15
+ 2, 0, 4390, 2, 1, 3065, 3, 0, 53814, 3, 1, 4267, // 3, 0
+ 2, 1, 4003, 2, 2, 2808, 3, 1, 54796, 3, 2, 3929, // 3, 1
+ 2, 2, 3628, 2, 3, 2557, 3, 2, 55756, 3, 3, 3595, // 3, 2
+ 2, 3, 3273, 2, 4, 2317, 3, 3, 56673, 3, 4, 3273, // 3, 3
+ 2, 4, 2948, 2, 5, 2096, 3, 4, 57514, 3, 5, 2978, // 3, 4
+ 2, 5, 2672, 2, 6, 1908, 3, 5, 58234, 3, 6, 2722, // 3, 5
+ 2, 6, 2463, 2, 7, 1766, 3, 6, 58775, 3, 7, 2532, // 3, 6
+ 2, 7, 2342, 2, 8, 1687, 3, 7, 59077, 3, 8, 2430, // 3, 7
+ 3, 8, 59076, 3, 9, 2430, 4, 8, 2343, 4, 9, 1687, // 3, 8
+ 3, 9, 58774, 3, 10, 2532, 4, 9, 2464, 4, 10, 1766, // 3, 9
+ 3, 10, 58233, 3, 11, 2722, 4, 10, 2673, 4, 11, 1908, // 3,10
+ 3, 11, 57514, 3, 12, 2976, 4, 11, 2950, 4, 12, 2096, // 3,11
+ 3, 12, 56673, 3, 13, 3273, 4, 12, 3274, 4, 13, 2316, // 3,12
+ 3, 13, 55756, 3, 14, 3594, 4, 13, 3630, 4, 14, 2556, // 3,13
+ 3, 14, 54796, 3, 15, 3927, 4, 14, 4005, 4, 15, 2808, // 3,14
+ 3, 15, 53815, 3, 16, 4264, 4, 15, 4392, 4, 16, 3065, // 3,15
+ 3, 0, 4200, 3, 1, 2917, 4, 0, 54376, 4, 1, 4043, // 4, 0
+ 3, 1, 3783, 3, 2, 2640, 4, 1, 55434, 4, 2, 3679, // 4, 1
+ 3, 2, 3373, 3, 3, 2365, 4, 2, 56486, 4, 3, 3312, // 4, 2
+ 3, 3, 2976, 3, 4, 2096, 4, 3, 57514, 4, 4, 2950, // 4, 3
+ 3, 4, 2604, 3, 5, 1843, 4, 4, 58484, 4, 5, 2605, // 4, 4
+ 3, 5, 2276, 3, 6, 1617, 4, 5, 59346, 4, 6, 2297, // 4, 5
+ 3, 6, 2020, 3, 7, 1442, 4, 6, 60018, 4, 7, 2056, // 4, 6
+ 3, 7, 1871, 3, 8, 1341, 4, 7, 60402, 4, 8, 1922, // 4, 7
+ 4, 8, 60402, 4, 9, 1922, 5, 8, 1871, 5, 9, 1341, // 4, 8
+ 4, 9, 60017, 4, 10, 2057, 5, 9, 2020, 5, 10, 1442, // 4, 9
+ 4, 10, 59345, 4, 11, 2297, 5, 10, 2276, 5, 11, 1618, // 4,10
+ 4, 11, 58484, 4, 12, 2604, 5, 11, 2605, 5, 12, 1843, // 4,11
+ 4, 12, 57514, 4, 13, 2948, 5, 12, 2977, 5, 13, 2097, // 4,12
+ 4, 13, 56487, 4, 14, 3310, 5, 13, 3374, 5, 14, 2365, // 4,13
+ 4, 14, 55435, 4, 15, 3677, 5, 14, 3785, 5, 15, 2639, // 4,14
+ 4, 15, 54378, 4, 16, 4041, 5, 15, 4201, 5, 16, 2916, // 4,15
+ 4, 0, 4046, 4, 1, 2797, 5, 0, 54833, 5, 1, 3860, // 5, 0
+ 4, 1, 3604, 4, 2, 2503, 5, 1, 55958, 5, 2, 3471, // 5, 1
+ 4, 2, 3161, 4, 3, 2205, 5, 2, 57095, 5, 3, 3075, // 5, 2
+ 4, 3, 2722, 4, 4, 1908, 5, 3, 58233, 5, 4, 2673, // 5, 3
+ 4, 4, 2297, 4, 5, 1617, 5, 4, 59345, 5, 5, 2277, // 5, 4
+ 4, 5, 1904, 4, 6, 1347, 5, 5, 60381, 5, 6, 1904, // 5, 5
+ 4, 6, 1578, 4, 7, 1121, 5, 6, 61243, 5, 7, 1594, // 5, 6
+ 4, 7, 1380, 4, 8, 985, 5, 7, 61767, 5, 8, 1404, // 5, 7
+ 5, 8, 61767, 5, 9, 1405, 6, 8, 1380, 6, 9, 984, // 5, 8
+ 5, 9, 61243, 5, 10, 1593, 6, 9, 1579, 6, 10, 1121, // 5, 9
+ 5, 10, 60381, 5, 11, 1904, 6, 10, 1904, 6, 11, 1347, // 5,10
+ 5, 11, 59346, 5, 12, 2276, 6, 11, 2297, 6, 12, 1617, // 5,11
+ 5, 12, 58234, 5, 13, 2672, 6, 12, 2723, 6, 13, 1907, // 5,12
+ 5, 13, 57096, 5, 14, 3073, 6, 13, 3161, 6, 14, 2206, // 5,13
+ 5, 14, 55959, 5, 15, 3470, 6, 14, 3605, 6, 15, 2502, // 5,14
+ 5, 15, 54835, 5, 16, 3858, 6, 15, 4047, 6, 16, 2796, // 5,15
+ 5, 0, 3939, 5, 1, 2709, 6, 0, 55164, 6, 1, 3724, // 6, 0
+ 5, 1, 3476, 5, 2, 2403, 6, 1, 56339, 6, 2, 3318, // 6, 1
+ 5, 2, 3007, 5, 3, 2088, 6, 2, 57544, 6, 3, 2897, // 6, 2
+ 5, 3, 2532, 5, 4, 1767, 6, 3, 58774, 6, 4, 2463, // 6, 3
+ 5, 4, 2057, 5, 5, 1442, 6, 4, 60017, 6, 5, 2020, // 6, 4
+ 5, 5, 1593, 5, 6, 1121, 6, 5, 61243, 6, 6, 1579, // 6, 5
+ 5, 6, 1170, 5, 7, 827, 6, 6, 62369, 6, 7, 1170, // 6, 6
+ 5, 7, 875, 5, 8, 622, 6, 7, 63156, 6, 8, 883, // 6, 7
+ 6, 8, 63156, 6, 9, 883, 7, 8, 875, 7, 9, 622, // 6, 8
+ 6, 9, 62369, 6, 10, 1170, 7, 9, 1170, 7, 10, 827, // 6, 9
+ 6, 10, 61243, 6, 11, 1578, 7, 10, 1593, 7, 11, 1122, // 6,10
+ 6, 11, 60018, 6, 12, 2020, 7, 11, 2057, 7, 12, 1441, // 6,11
+ 6, 12, 58775, 6, 13, 2463, 7, 12, 2532, 7, 13, 1766, // 6,12
+ 6, 13, 57545, 6, 14, 2897, 7, 13, 3007, 7, 14, 2087, // 6,13
+ 6, 14, 56340, 6, 15, 3317, 7, 14, 3477, 7, 15, 2402, // 6,14
+ 6, 15, 55166, 6, 16, 3722, 7, 15, 3940, 7, 16, 2708, // 6,15
+ 6, 0, 3885, 6, 1, 2659, 7, 0, 55352, 7, 1, 3640, // 7, 0
+ 6, 1, 3411, 6, 2, 2346, 7, 1, 56552, 7, 2, 3227, // 7, 1
+ 6, 2, 2926, 6, 3, 2022, 7, 2, 57793, 7, 3, 2795, // 7, 2
+ 6, 3, 2430, 6, 4, 1687, 7, 3, 59076, 7, 4, 2343, // 7, 3
+ 6, 4, 1922, 6, 5, 1341, 7, 4, 60402, 7, 5, 1871, // 7, 4
+ 6, 5, 1405, 6, 6, 985, 7, 5, 61767, 7, 6, 1379, // 7, 5
+ 6, 6, 883, 6, 7, 622, 7, 6, 63156, 7, 7, 875, // 7, 6
+ 6, 7, 399, 6, 8, 282, 7, 7, 64455, 7, 8, 400, // 7, 7
+ 7, 8, 64455, 7, 9, 399, 8, 8, 399, 8, 9, 283, // 7, 8
+ 7, 9, 63156, 7, 10, 875, 8, 9, 883, 8, 10, 622, // 7, 9
+ 7, 10, 61767, 7, 11, 1380, 8, 10, 1405, 8, 11, 984, // 7,10
+ 7, 11, 60402, 7, 12, 1871, 8, 11, 1922, 8, 12, 1341, // 7,11
+ 7, 12, 59077, 7, 13, 2342, 8, 12, 2430, 8, 13, 1687, // 7,12
+ 7, 13, 57795, 7, 14, 2794, 8, 13, 2926, 8, 14, 2021, // 7,13
+ 7, 14, 56554, 7, 15, 3225, 8, 14, 3411, 8, 15, 2346, // 7,14
+ 7, 15, 55354, 7, 16, 3638, 8, 15, 3885, 8, 16, 2659, // 7,15
+ 7, -1, 2659, 7, 0, 3885, 8, -1, 3638, 8, 0, 55354, // 8, 0
+ 7, 0, 2346, 7, 1, 3411, 8, 0, 3225, 8, 1, 56554, // 8, 1
+ 7, 1, 2022, 7, 2, 2926, 8, 1, 2794, 8, 2, 57794, // 8, 2
+ 7, 2, 1687, 7, 3, 2430, 8, 2, 2342, 8, 3, 59077, // 8, 3
+ 7, 3, 1341, 7, 4, 1922, 8, 3, 1871, 8, 4, 60402, // 8, 4
+ 7, 4, 985, 7, 5, 1405, 8, 4, 1380, 8, 5, 61766, // 8, 5
+ 7, 5, 622, 7, 6, 883, 8, 5, 875, 8, 6, 63156, // 8, 6
+ 7, 6, 282, 7, 7, 399, 8, 6, 399, 8, 7, 64456, // 8, 7
+ 8, 7, 399, 8, 8, 64455, 9, 7, 282, 9, 8, 400, // 8, 8
+ 8, 8, 875, 8, 9, 63156, 9, 8, 622, 9, 9, 883, // 8, 9
+ 8, 9, 1380, 8, 10, 61767, 9, 9, 985, 9, 10, 1404, // 8,10
+ 8, 10, 1871, 8, 11, 60402, 9, 10, 1341, 9, 11, 1922, // 8,11
+ 8, 11, 2343, 8, 12, 59076, 9, 11, 1687, 9, 12, 2430, // 8,12
+ 8, 12, 2795, 8, 13, 57793, 9, 12, 2022, 9, 13, 2926, // 8,13
+ 8, 13, 3227, 8, 14, 56552, 9, 13, 2346, 9, 14, 3411, // 8,14
+ 8, 14, 3640, 8, 15, 55352, 9, 14, 2659, 9, 15, 3885, // 8,15
+ 8, -1, 2709, 8, 0, 3940, 9, -1, 3722, 9, 0, 55165, // 9, 0
+ 8, 0, 2402, 8, 1, 3477, 9, 0, 3317, 9, 1, 56340, // 9, 1
+ 8, 1, 2088, 8, 2, 3007, 9, 1, 2897, 9, 2, 57544, // 9, 2
+ 8, 2, 1766, 8, 3, 2532, 9, 2, 2463, 9, 3, 58775, // 9, 3
+ 8, 3, 1442, 8, 4, 2057, 9, 3, 2020, 9, 4, 60017, // 9, 4
+ 8, 4, 1121, 8, 5, 1593, 9, 4, 1578, 9, 5, 61244, // 9, 5
+ 8, 5, 827, 8, 6, 1170, 9, 5, 1170, 9, 6, 62369, // 9, 6
+ 8, 6, 622, 8, 7, 875, 9, 6, 883, 9, 7, 63156, // 9, 7
+ 9, 7, 883, 9, 8, 63156, 10, 7, 622, 10, 8, 875, // 9, 8
+ 9, 8, 1170, 9, 9, 62369, 10, 8, 827, 10, 9, 1170, // 9, 9
+ 9, 9, 1579, 9, 10, 61243, 10, 9, 1121, 10, 10, 1593, // 9,10
+ 9, 10, 2020, 9, 11, 60017, 10, 10, 1442, 10, 11, 2057, // 9,11
+ 9, 11, 2464, 9, 12, 58774, 10, 11, 1767, 10, 12, 2531, // 9,12
+ 9, 12, 2898, 9, 13, 57544, 10, 12, 2088, 10, 13, 3006, // 9,13
+ 9, 13, 3319, 9, 14, 56339, 10, 13, 2403, 10, 14, 3475, // 9,14
+ 9, 14, 3724, 9, 15, 55164, 10, 14, 2709, 10, 15, 3939, // 9,15
+ 9, -1, 2796, 9, 0, 4047, 10, -1, 3858, 10, 0, 54835, // 10, 0
+ 9, 0, 2502, 9, 1, 3605, 10, 0, 3470, 10, 1, 55959, // 10, 1
+ 9, 1, 2205, 9, 2, 3161, 10, 1, 3073, 10, 2, 57097, // 10, 2
+ 9, 2, 1908, 9, 3, 2723, 10, 2, 2672, 10, 3, 58233, // 10, 3
+ 9, 3, 1617, 9, 4, 2297, 10, 3, 2276, 10, 4, 59346, // 10, 4
+ 9, 4, 1347, 9, 5, 1904, 10, 4, 1904, 10, 5, 60381, // 10, 5
+ 9, 5, 1121, 9, 6, 1579, 10, 5, 1593, 10, 6, 61243, // 10, 6
+ 9, 6, 985, 9, 7, 1380, 10, 6, 1405, 10, 7, 61766, // 10, 7
+ 10, 7, 1405, 10, 8, 61767, 11, 7, 985, 11, 8, 1379, // 10, 8
+ 10, 8, 1593, 10, 9, 61243, 11, 8, 1121, 11, 9, 1579, // 10, 9
+ 10, 9, 1904, 10, 10, 60381, 11, 9, 1347, 11, 10, 1904, // 10,10
+ 10, 10, 2276, 10, 11, 59345, 11, 10, 1617, 11, 11, 2298, // 10,11
+ 10, 11, 2673, 10, 12, 58233, 11, 11, 1908, 11, 12, 2722, // 10,12
+ 10, 12, 3074, 10, 13, 57095, 11, 12, 2205, 11, 13, 3162, // 10,13
+ 10, 13, 3472, 10, 14, 55958, 11, 13, 2503, 11, 14, 3603, // 10,14
+ 10, 14, 3860, 10, 15, 54833, 11, 14, 2797, 11, 15, 4046, // 10,15
+ 10, -1, 2916, 10, 0, 4201, 11, -1, 4041, 11, 0, 54378, // 11, 0
+ 10, 0, 2640, 10, 1, 3785, 11, 0, 3677, 11, 1, 55434, // 11, 1
+ 10, 1, 2365, 10, 2, 3374, 11, 1, 3310, 11, 2, 56487, // 11, 2
+ 10, 2, 2096, 10, 3, 2977, 11, 2, 2948, 11, 3, 57515, // 11, 3
+ 10, 3, 1843, 10, 4, 2605, 11, 3, 2604, 11, 4, 58484, // 11, 4
+ 10, 4, 1617, 10, 5, 2276, 11, 4, 2297, 11, 5, 59346, // 11, 5
+ 10, 5, 1442, 10, 6, 2020, 11, 5, 2057, 11, 6, 60017, // 11, 6
+ 10, 6, 1341, 10, 7, 1871, 11, 6, 1922, 11, 7, 60402, // 11, 7
+ 11, 7, 1922, 11, 8, 60402, 12, 7, 1341, 12, 8, 1871, // 11, 8
+ 11, 8, 2057, 11, 9, 60018, 12, 8, 1442, 12, 9, 2019, // 11, 9
+ 11, 9, 2297, 11, 10, 59346, 12, 9, 1617, 12, 10, 2276, // 11,10
+ 11, 10, 2605, 11, 11, 58484, 12, 10, 1843, 12, 11, 2604, // 11,11
+ 11, 11, 2950, 11, 12, 57514, 12, 11, 2096, 12, 12, 2976, // 11,12
+ 11, 12, 3311, 11, 13, 56486, 12, 12, 2365, 12, 13, 3374, // 11,13
+ 11, 13, 3678, 11, 14, 55434, 12, 13, 2640, 12, 14, 3784, // 11,14
+ 11, 14, 4043, 11, 15, 54376, 12, 14, 2917, 12, 15, 4200, // 11,15
+ 11, -1, 3064, 11, 0, 4392, 12, -1, 4264, 12, 0, 53816, // 12, 0
+ 11, 0, 2808, 11, 1, 4005, 12, 0, 3927, 12, 1, 54796, // 12, 1
+ 11, 1, 2556, 11, 2, 3630, 12, 1, 3594, 12, 2, 55756, // 12, 2
+ 11, 2, 2317, 11, 3, 3274, 12, 2, 3273, 12, 3, 56672, // 12, 3
+ 11, 3, 2096, 11, 4, 2950, 12, 3, 2976, 12, 4, 57514, // 12, 4
+ 11, 4, 1908, 11, 5, 2673, 12, 4, 2722, 12, 5, 58233, // 12, 5
+ 11, 5, 1767, 11, 6, 2464, 12, 5, 2532, 12, 6, 58773, // 12, 6
+ 11, 6, 1687, 11, 7, 2343, 12, 6, 2430, 12, 7, 59076, // 12, 7
+ 12, 7, 2430, 12, 8, 59077, 13, 7, 1687, 13, 8, 2342, // 12, 8
+ 12, 8, 2532, 12, 9, 58775, 13, 8, 1766, 13, 9, 2463, // 12, 9
+ 12, 9, 2723, 12, 10, 58234, 13, 9, 1908, 13, 10, 2671, // 12,10
+ 12, 10, 2977, 12, 11, 57514, 13, 10, 2096, 13, 11, 2949, // 12,11
+ 12, 11, 3274, 12, 12, 56673, 13, 11, 2317, 13, 12, 3272, // 12,12
+ 12, 12, 3595, 12, 13, 55756, 13, 12, 2557, 13, 13, 3628, // 12,13
+ 12, 13, 3929, 12, 14, 54796, 13, 13, 2808, 13, 14, 4003, // 12,14
+ 12, 14, 4267, 12, 15, 53814, 13, 14, 3065, 13, 15, 4390, // 12,15
+ 12, -1, 3235, 12, 0, 4612, 13, -1, 4521, 13, 0, 53168, // 13, 0
+ 12, 0, 2998, 12, 1, 4255, 13, 0, 4212, 13, 1, 54071, // 13, 1
+ 12, 1, 2770, 12, 2, 3913, 13, 1, 3911, 13, 2, 54942, // 13, 2
+ 12, 2, 2557, 12, 3, 3595, 13, 2, 3628, 13, 3, 55756, // 13, 3
+ 12, 3, 2365, 12, 4, 3311, 13, 3, 3373, 13, 4, 56487, // 13, 4
+ 12, 4, 2205, 12, 5, 3074, 13, 4, 3161, 13, 5, 57096, // 13, 5
+ 12, 5, 2088, 12, 6, 2898, 13, 5, 3007, 13, 6, 57543, // 13, 6
+ 12, 6, 2022, 12, 7, 2795, 13, 6, 2926, 13, 7, 57793, // 13, 7
+ 13, 7, 2926, 13, 8, 57795, 14, 7, 2022, 14, 8, 2793, // 13, 8
+ 13, 8, 3007, 13, 9, 57545, 14, 8, 2088, 14, 9, 2896, // 13, 9
+ 13, 9, 3161, 13, 10, 57096, 14, 9, 2205, 14, 10, 3074, // 13,10
+ 13, 10, 3374, 13, 11, 56487, 14, 10, 2365, 14, 11, 3310, // 13,11
+ 13, 11, 3630, 13, 12, 55756, 14, 11, 2556, 14, 12, 3594, // 13,12
+ 13, 12, 3913, 13, 13, 54941, 14, 12, 2770, 14, 13, 3912, // 13,13
+ 13, 13, 4214, 13, 14, 54071, 14, 13, 2998, 14, 14, 4253, // 13,14
+ 13, 14, 4523, 13, 15, 53168, 14, 14, 3235, 14, 15, 4610, // 13,15
+ 13, -1, 3421, 13, 0, 4854, 14, -1, 4803, 14, 0, 52458, // 14, 0
+ 13, 0, 3204, 13, 1, 4525, 14, 0, 4522, 14, 1, 53285, // 14, 1
+ 13, 1, 2998, 13, 2, 4214, 14, 1, 4253, 14, 2, 54071, // 14, 2
+ 13, 2, 2808, 13, 3, 3929, 14, 2, 4003, 14, 3, 54796, // 14, 3
+ 13, 3, 2640, 13, 4, 3678, 14, 3, 3783, 14, 4, 55435, // 14, 4
+ 13, 4, 2503, 13, 5, 3472, 14, 4, 3604, 14, 5, 55957, // 14, 5
+ 13, 5, 2403, 13, 6, 3319, 14, 5, 3476, 14, 6, 56338, // 14, 6
+ 13, 6, 2346, 13, 7, 3227, 14, 6, 3411, 14, 7, 56552, // 14, 7
+ 14, 7, 3411, 14, 8, 56554, 15, 7, 2346, 15, 8, 3225, // 14, 8
+ 14, 8, 3477, 14, 9, 56340, 15, 8, 2402, 15, 9, 3317, // 14, 9
+ 14, 9, 3605, 14, 10, 55959, 15, 9, 2502, 15, 10, 3470, // 14,10
+ 14, 10, 3785, 14, 11, 55435, 15, 10, 2640, 15, 11, 3676, // 14,11
+ 14, 11, 4005, 14, 12, 54796, 15, 11, 2808, 15, 12, 3927, // 14,12
+ 14, 12, 4255, 14, 13, 54072, 15, 12, 2998, 15, 13, 4211, // 14,13
+ 14, 13, 4525, 14, 14, 53285, 15, 13, 3204, 15, 14, 4522, // 14,14
+ 14, 14, 4806, 14, 15, 52457, 15, 14, 3422, 15, 15, 4851, // 14,15
+ 14, -1, 3621, 14, 0, 5110, 15, -1, 5106, 15, 0, 51699, // 15, 0
+ 14, 0, 3422, 14, 1, 4806, 15, 0, 4851, 15, 1, 52457, // 15, 1
+ 14, 1, 3235, 14, 2, 4523, 15, 1, 4610, 15, 2, 53168, // 15, 2
+ 14, 2, 3065, 14, 3, 4267, 15, 2, 4390, 15, 3, 53814, // 15, 3
+ 14, 3, 2917, 14, 4, 4043, 15, 3, 4200, 15, 4, 54376, // 15, 4
+ 14, 4, 2797, 14, 5, 3860, 15, 4, 4046, 15, 5, 54833, // 15, 5
+ 14, 5, 2709, 14, 6, 3724, 15, 5, 3939, 15, 6, 55164, // 15, 6
+ 14, 6, 2659, 14, 7, 3640, 15, 6, 3885, 15, 7, 55352, // 15, 7
+ 15, 7, 3885, 15, 8, 55354, 16, 7, 2659, 16, 8, 3638, // 15, 8
+ 15, 8, 3940, 15, 9, 55166, 16, 8, 2709, 16, 9, 3721, // 15, 9
+ 15, 9, 4047, 15, 10, 54835, 16, 9, 2796, 16, 10, 3858, // 15,10
+ 15, 10, 4201, 15, 11, 54378, 16, 10, 2916, 16, 11, 4041, // 15,11
+ 15, 11, 4392, 15, 12, 53815, 16, 11, 3064, 16, 12, 4265, // 15,12
+ 15, 12, 4612, 15, 13, 53168, 16, 12, 3235, 16, 13, 4521, // 15,13
+ 15, 13, 4854, 15, 14, 52457, 16, 13, 3421, 16, 14, 4804, // 15,14
+ 15, 14, 5110, 15, 15, 51699, 16, 14, 3621, 16, 15, 5106, // 15,15
+ // angle of 0.0 degrees
+ 0, 0, 16384, 0, 0, 16384, 0, 0, 16384, 0, 0, 16384, // 0, 0
+ 0, 1, 16384, 0, 1, 16384, 0, 1, 16384, 0, 1, 16384, // 0, 1
+ 0, 2, 16384, 0, 2, 16384, 0, 2, 16384, 0, 2, 16384, // 0, 2
+ 0, 3, 16384, 0, 3, 16384, 0, 3, 16384, 0, 3, 16384, // 0, 3
+ 0, 4, 16384, 0, 4, 16384, 0, 4, 16384, 0, 4, 16384, // 0, 4
+ 0, 5, 16384, 0, 5, 16384, 0, 5, 16384, 0, 5, 16384, // 0, 5
+ 0, 6, 16384, 0, 6, 16384, 0, 6, 16384, 0, 6, 16384, // 0, 6
+ 0, 7, 16384, 0, 7, 16384, 0, 7, 16384, 0, 7, 16384, // 0, 7
+ 0, 8, 16384, 0, 8, 16384, 0, 8, 16384, 0, 8, 16384, // 0, 8
+ 0, 9, 16384, 0, 9, 16384, 0, 9, 16384, 0, 9, 16384, // 0, 9
+ 0, 10, 16384, 0, 10, 16384, 0, 10, 16384, 0, 10, 16384, // 0,10
+ 0, 11, 16384, 0, 11, 16384, 0, 11, 16384, 0, 11, 16384, // 0,11
+ 0, 12, 16384, 0, 12, 16384, 0, 12, 16384, 0, 12, 16384, // 0,12
+ 0, 13, 16384, 0, 13, 16384, 0, 13, 16384, 0, 13, 16384, // 0,13
+ 0, 14, 16384, 0, 14, 16384, 0, 14, 16384, 0, 14, 16384, // 0,14
+ 0, 15, 16384, 0, 15, 16384, 0, 15, 16384, 0, 15, 16384, // 0,15
+ 1, 0, 16384, 1, 0, 16384, 1, 0, 16384, 1, 0, 16384, // 1, 0
+ 1, 1, 16384, 1, 1, 16384, 1, 1, 16384, 1, 1, 16384, // 1, 1
+ 1, 2, 16384, 1, 2, 16384, 1, 2, 16384, 1, 2, 16384, // 1, 2
+ 1, 3, 16384, 1, 3, 16384, 1, 3, 16384, 1, 3, 16384, // 1, 3
+ 1, 4, 16384, 1, 4, 16384, 1, 4, 16384, 1, 4, 16384, // 1, 4
+ 1, 5, 16384, 1, 5, 16384, 1, 5, 16384, 1, 5, 16384, // 1, 5
+ 1, 6, 16384, 1, 6, 16384, 1, 6, 16384, 1, 6, 16384, // 1, 6
+ 1, 7, 16384, 1, 7, 16384, 1, 7, 16384, 1, 7, 16384, // 1, 7
+ 1, 8, 16384, 1, 8, 16384, 1, 8, 16384, 1, 8, 16384, // 1, 8
+ 1, 9, 16384, 1, 9, 16384, 1, 9, 16384, 1, 9, 16384, // 1, 9
+ 1, 10, 16384, 1, 10, 16384, 1, 10, 16384, 1, 10, 16384, // 1,10
+ 1, 11, 16384, 1, 11, 16384, 1, 11, 16384, 1, 11, 16384, // 1,11
+ 1, 12, 16384, 1, 12, 16384, 1, 12, 16384, 1, 12, 16384, // 1,12
+ 1, 13, 16384, 1, 13, 16384, 1, 13, 16384, 1, 13, 16384, // 1,13
+ 1, 14, 16384, 1, 14, 16384, 1, 14, 16384, 1, 14, 16384, // 1,14
+ 1, 15, 16384, 1, 15, 16384, 1, 15, 16384, 1, 15, 16384, // 1,15
+ 2, 0, 16384, 2, 0, 16384, 2, 0, 16384, 2, 0, 16384, // 2, 0
+ 2, 1, 16384, 2, 1, 16384, 2, 1, 16384, 2, 1, 16384, // 2, 1
+ 2, 2, 16384, 2, 2, 16384, 2, 2, 16384, 2, 2, 16384, // 2, 2
+ 2, 3, 16384, 2, 3, 16384, 2, 3, 16384, 2, 3, 16384, // 2, 3
+ 2, 4, 16384, 2, 4, 16384, 2, 4, 16384, 2, 4, 16384, // 2, 4
+ 2, 5, 16384, 2, 5, 16384, 2, 5, 16384, 2, 5, 16384, // 2, 5
+ 2, 6, 16384, 2, 6, 16384, 2, 6, 16384, 2, 6, 16384, // 2, 6
+ 2, 7, 16384, 2, 7, 16384, 2, 7, 16384, 2, 7, 16384, // 2, 7
+ 2, 8, 16384, 2, 8, 16384, 2, 8, 16384, 2, 8, 16384, // 2, 8
+ 2, 9, 16384, 2, 9, 16384, 2, 9, 16384, 2, 9, 16384, // 2, 9
+ 2, 10, 16384, 2, 10, 16384, 2, 10, 16384, 2, 10, 16384, // 2,10
+ 2, 11, 16384, 2, 11, 16384, 2, 11, 16384, 2, 11, 16384, // 2,11
+ 2, 12, 16384, 2, 12, 16384, 2, 12, 16384, 2, 12, 16384, // 2,12
+ 2, 13, 16384, 2, 13, 16384, 2, 13, 16384, 2, 13, 16384, // 2,13
+ 2, 14, 16384, 2, 14, 16384, 2, 14, 16384, 2, 14, 16384, // 2,14
+ 2, 15, 16384, 2, 15, 16384, 2, 15, 16384, 2, 15, 16384, // 2,15
+ 3, 0, 16384, 3, 0, 16384, 3, 0, 16384, 3, 0, 16384, // 3, 0
+ 3, 1, 16384, 3, 1, 16384, 3, 1, 16384, 3, 1, 16384, // 3, 1
+ 3, 2, 16384, 3, 2, 16384, 3, 2, 16384, 3, 2, 16384, // 3, 2
+ 3, 3, 16384, 3, 3, 16384, 3, 3, 16384, 3, 3, 16384, // 3, 3
+ 3, 4, 16384, 3, 4, 16384, 3, 4, 16384, 3, 4, 16384, // 3, 4
+ 3, 5, 16384, 3, 5, 16384, 3, 5, 16384, 3, 5, 16384, // 3, 5
+ 3, 6, 16384, 3, 6, 16384, 3, 6, 16384, 3, 6, 16384, // 3, 6
+ 3, 7, 16384, 3, 7, 16384, 3, 7, 16384, 3, 7, 16384, // 3, 7
+ 3, 8, 16384, 3, 8, 16384, 3, 8, 16384, 3, 8, 16384, // 3, 8
+ 3, 9, 16384, 3, 9, 16384, 3, 9, 16384, 3, 9, 16384, // 3, 9
+ 3, 10, 16384, 3, 10, 16384, 3, 10, 16384, 3, 10, 16384, // 3,10
+ 3, 11, 16384, 3, 11, 16384, 3, 11, 16384, 3, 11, 16384, // 3,11
+ 3, 12, 16384, 3, 12, 16384, 3, 12, 16384, 3, 12, 16384, // 3,12
+ 3, 13, 16384, 3, 13, 16384, 3, 13, 16384, 3, 13, 16384, // 3,13
+ 3, 14, 16384, 3, 14, 16384, 3, 14, 16384, 3, 14, 16384, // 3,14
+ 3, 15, 16384, 3, 15, 16384, 3, 15, 16384, 3, 15, 16384, // 3,15
+ 4, 0, 16384, 4, 0, 16384, 4, 0, 16384, 4, 0, 16384, // 4, 0
+ 4, 1, 16384, 4, 1, 16384, 4, 1, 16384, 4, 1, 16384, // 4, 1
+ 4, 2, 16384, 4, 2, 16384, 4, 2, 16384, 4, 2, 16384, // 4, 2
+ 4, 3, 16384, 4, 3, 16384, 4, 3, 16384, 4, 3, 16384, // 4, 3
+ 4, 4, 16384, 4, 4, 16384, 4, 4, 16384, 4, 4, 16384, // 4, 4
+ 4, 5, 16384, 4, 5, 16384, 4, 5, 16384, 4, 5, 16384, // 4, 5
+ 4, 6, 16384, 4, 6, 16384, 4, 6, 16384, 4, 6, 16384, // 4, 6
+ 4, 7, 16384, 4, 7, 16384, 4, 7, 16384, 4, 7, 16384, // 4, 7
+ 4, 8, 16384, 4, 8, 16384, 4, 8, 16384, 4, 8, 16384, // 4, 8
+ 4, 9, 16384, 4, 9, 16384, 4, 9, 16384, 4, 9, 16384, // 4, 9
+ 4, 10, 16384, 4, 10, 16384, 4, 10, 16384, 4, 10, 16384, // 4,10
+ 4, 11, 16384, 4, 11, 16384, 4, 11, 16384, 4, 11, 16384, // 4,11
+ 4, 12, 16384, 4, 12, 16384, 4, 12, 16384, 4, 12, 16384, // 4,12
+ 4, 13, 16384, 4, 13, 16384, 4, 13, 16384, 4, 13, 16384, // 4,13
+ 4, 14, 16384, 4, 14, 16384, 4, 14, 16384, 4, 14, 16384, // 4,14
+ 4, 15, 16384, 4, 15, 16384, 4, 15, 16384, 4, 15, 16384, // 4,15
+ 5, 0, 16384, 5, 0, 16384, 5, 0, 16384, 5, 0, 16384, // 5, 0
+ 5, 1, 16384, 5, 1, 16384, 5, 1, 16384, 5, 1, 16384, // 5, 1
+ 5, 2, 16384, 5, 2, 16384, 5, 2, 16384, 5, 2, 16384, // 5, 2
+ 5, 3, 16384, 5, 3, 16384, 5, 3, 16384, 5, 3, 16384, // 5, 3
+ 5, 4, 16384, 5, 4, 16384, 5, 4, 16384, 5, 4, 16384, // 5, 4
+ 5, 5, 16384, 5, 5, 16384, 5, 5, 16384, 5, 5, 16384, // 5, 5
+ 5, 6, 16384, 5, 6, 16384, 5, 6, 16384, 5, 6, 16384, // 5, 6
+ 5, 7, 16384, 5, 7, 16384, 5, 7, 16384, 5, 7, 16384, // 5, 7
+ 5, 8, 16384, 5, 8, 16384, 5, 8, 16384, 5, 8, 16384, // 5, 8
+ 5, 9, 16384, 5, 9, 16384, 5, 9, 16384, 5, 9, 16384, // 5, 9
+ 5, 10, 16384, 5, 10, 16384, 5, 10, 16384, 5, 10, 16384, // 5,10
+ 5, 11, 16384, 5, 11, 16384, 5, 11, 16384, 5, 11, 16384, // 5,11
+ 5, 12, 16384, 5, 12, 16384, 5, 12, 16384, 5, 12, 16384, // 5,12
+ 5, 13, 16384, 5, 13, 16384, 5, 13, 16384, 5, 13, 16384, // 5,13
+ 5, 14, 16384, 5, 14, 16384, 5, 14, 16384, 5, 14, 16384, // 5,14
+ 5, 15, 16384, 5, 15, 16384, 5, 15, 16384, 5, 15, 16384, // 5,15
+ 6, 0, 16384, 6, 0, 16384, 6, 0, 16384, 6, 0, 16384, // 6, 0
+ 6, 1, 16384, 6, 1, 16384, 6, 1, 16384, 6, 1, 16384, // 6, 1
+ 6, 2, 16384, 6, 2, 16384, 6, 2, 16384, 6, 2, 16384, // 6, 2
+ 6, 3, 16384, 6, 3, 16384, 6, 3, 16384, 6, 3, 16384, // 6, 3
+ 6, 4, 16384, 6, 4, 16384, 6, 4, 16384, 6, 4, 16384, // 6, 4
+ 6, 5, 16384, 6, 5, 16384, 6, 5, 16384, 6, 5, 16384, // 6, 5
+ 6, 6, 16384, 6, 6, 16384, 6, 6, 16384, 6, 6, 16384, // 6, 6
+ 6, 7, 16384, 6, 7, 16384, 6, 7, 16384, 6, 7, 16384, // 6, 7
+ 6, 8, 16384, 6, 8, 16384, 6, 8, 16384, 6, 8, 16384, // 6, 8
+ 6, 9, 16384, 6, 9, 16384, 6, 9, 16384, 6, 9, 16384, // 6, 9
+ 6, 10, 16384, 6, 10, 16384, 6, 10, 16384, 6, 10, 16384, // 6,10
+ 6, 11, 16384, 6, 11, 16384, 6, 11, 16384, 6, 11, 16384, // 6,11
+ 6, 12, 16384, 6, 12, 16384, 6, 12, 16384, 6, 12, 16384, // 6,12
+ 6, 13, 16384, 6, 13, 16384, 6, 13, 16384, 6, 13, 16384, // 6,13
+ 6, 14, 16384, 6, 14, 16384, 6, 14, 16384, 6, 14, 16384, // 6,14
+ 6, 15, 16384, 6, 15, 16384, 6, 15, 16384, 6, 15, 16384, // 6,15
+ 7, 0, 16384, 7, 0, 16384, 7, 0, 16384, 7, 0, 16384, // 7, 0
+ 7, 1, 16384, 7, 1, 16384, 7, 1, 16384, 7, 1, 16384, // 7, 1
+ 7, 2, 16384, 7, 2, 16384, 7, 2, 16384, 7, 2, 16384, // 7, 2
+ 7, 3, 16384, 7, 3, 16384, 7, 3, 16384, 7, 3, 16384, // 7, 3
+ 7, 4, 16384, 7, 4, 16384, 7, 4, 16384, 7, 4, 16384, // 7, 4
+ 7, 5, 16384, 7, 5, 16384, 7, 5, 16384, 7, 5, 16384, // 7, 5
+ 7, 6, 16384, 7, 6, 16384, 7, 6, 16384, 7, 6, 16384, // 7, 6
+ 7, 7, 16384, 7, 7, 16384, 7, 7, 16384, 7, 7, 16384, // 7, 7
+ 7, 8, 16384, 7, 8, 16384, 7, 8, 16384, 7, 8, 16384, // 7, 8
+ 7, 9, 16384, 7, 9, 16384, 7, 9, 16384, 7, 9, 16384, // 7, 9
+ 7, 10, 16384, 7, 10, 16384, 7, 10, 16384, 7, 10, 16384, // 7,10
+ 7, 11, 16384, 7, 11, 16384, 7, 11, 16384, 7, 11, 16384, // 7,11
+ 7, 12, 16384, 7, 12, 16384, 7, 12, 16384, 7, 12, 16384, // 7,12
+ 7, 13, 16384, 7, 13, 16384, 7, 13, 16384, 7, 13, 16384, // 7,13
+ 7, 14, 16384, 7, 14, 16384, 7, 14, 16384, 7, 14, 16384, // 7,14
+ 7, 15, 16384, 7, 15, 16384, 7, 15, 16384, 7, 15, 16384, // 7,15
+ 8, 0, 16384, 8, 0, 16384, 8, 0, 16384, 8, 0, 16384, // 8, 0
+ 8, 1, 16384, 8, 1, 16384, 8, 1, 16384, 8, 1, 16384, // 8, 1
+ 8, 2, 16384, 8, 2, 16384, 8, 2, 16384, 8, 2, 16384, // 8, 2
+ 8, 3, 16384, 8, 3, 16384, 8, 3, 16384, 8, 3, 16384, // 8, 3
+ 8, 4, 16384, 8, 4, 16384, 8, 4, 16384, 8, 4, 16384, // 8, 4
+ 8, 5, 16384, 8, 5, 16384, 8, 5, 16384, 8, 5, 16384, // 8, 5
+ 8, 6, 16384, 8, 6, 16384, 8, 6, 16384, 8, 6, 16384, // 8, 6
+ 8, 7, 16384, 8, 7, 16384, 8, 7, 16384, 8, 7, 16384, // 8, 7
+ 8, 8, 16384, 8, 8, 16384, 8, 8, 16384, 8, 8, 16384, // 8, 8
+ 8, 9, 16384, 8, 9, 16384, 8, 9, 16384, 8, 9, 16384, // 8, 9
+ 8, 10, 16384, 8, 10, 16384, 8, 10, 16384, 8, 10, 16384, // 8,10
+ 8, 11, 16384, 8, 11, 16384, 8, 11, 16384, 8, 11, 16384, // 8,11
+ 8, 12, 16384, 8, 12, 16384, 8, 12, 16384, 8, 12, 16384, // 8,12
+ 8, 13, 16384, 8, 13, 16384, 8, 13, 16384, 8, 13, 16384, // 8,13
+ 8, 14, 16384, 8, 14, 16384, 8, 14, 16384, 8, 14, 16384, // 8,14
+ 8, 15, 16384, 8, 15, 16384, 8, 15, 16384, 8, 15, 16384, // 8,15
+ 9, 0, 16384, 9, 0, 16384, 9, 0, 16384, 9, 0, 16384, // 9, 0
+ 9, 1, 16384, 9, 1, 16384, 9, 1, 16384, 9, 1, 16384, // 9, 1
+ 9, 2, 16384, 9, 2, 16384, 9, 2, 16384, 9, 2, 16384, // 9, 2
+ 9, 3, 16384, 9, 3, 16384, 9, 3, 16384, 9, 3, 16384, // 9, 3
+ 9, 4, 16384, 9, 4, 16384, 9, 4, 16384, 9, 4, 16384, // 9, 4
+ 9, 5, 16384, 9, 5, 16384, 9, 5, 16384, 9, 5, 16384, // 9, 5
+ 9, 6, 16384, 9, 6, 16384, 9, 6, 16384, 9, 6, 16384, // 9, 6
+ 9, 7, 16384, 9, 7, 16384, 9, 7, 16384, 9, 7, 16384, // 9, 7
+ 9, 8, 16384, 9, 8, 16384, 9, 8, 16384, 9, 8, 16384, // 9, 8
+ 9, 9, 16384, 9, 9, 16384, 9, 9, 16384, 9, 9, 16384, // 9, 9
+ 9, 10, 16384, 9, 10, 16384, 9, 10, 16384, 9, 10, 16384, // 9,10
+ 9, 11, 16384, 9, 11, 16384, 9, 11, 16384, 9, 11, 16384, // 9,11
+ 9, 12, 16384, 9, 12, 16384, 9, 12, 16384, 9, 12, 16384, // 9,12
+ 9, 13, 16384, 9, 13, 16384, 9, 13, 16384, 9, 13, 16384, // 9,13
+ 9, 14, 16384, 9, 14, 16384, 9, 14, 16384, 9, 14, 16384, // 9,14
+ 9, 15, 16384, 9, 15, 16384, 9, 15, 16384, 9, 15, 16384, // 9,15
+ 10, 0, 16384, 10, 0, 16384, 10, 0, 16384, 10, 0, 16384, // 10, 0
+ 10, 1, 16384, 10, 1, 16384, 10, 1, 16384, 10, 1, 16384, // 10, 1
+ 10, 2, 16384, 10, 2, 16384, 10, 2, 16384, 10, 2, 16384, // 10, 2
+ 10, 3, 16384, 10, 3, 16384, 10, 3, 16384, 10, 3, 16384, // 10, 3
+ 10, 4, 16384, 10, 4, 16384, 10, 4, 16384, 10, 4, 16384, // 10, 4
+ 10, 5, 16384, 10, 5, 16384, 10, 5, 16384, 10, 5, 16384, // 10, 5
+ 10, 6, 16384, 10, 6, 16384, 10, 6, 16384, 10, 6, 16384, // 10, 6
+ 10, 7, 16384, 10, 7, 16384, 10, 7, 16384, 10, 7, 16384, // 10, 7
+ 10, 8, 16384, 10, 8, 16384, 10, 8, 16384, 10, 8, 16384, // 10, 8
+ 10, 9, 16384, 10, 9, 16384, 10, 9, 16384, 10, 9, 16384, // 10, 9
+ 10, 10, 16384, 10, 10, 16384, 10, 10, 16384, 10, 10, 16384, // 10,10
+ 10, 11, 16384, 10, 11, 16384, 10, 11, 16384, 10, 11, 16384, // 10,11
+ 10, 12, 16384, 10, 12, 16384, 10, 12, 16384, 10, 12, 16384, // 10,12
+ 10, 13, 16384, 10, 13, 16384, 10, 13, 16384, 10, 13, 16384, // 10,13
+ 10, 14, 16384, 10, 14, 16384, 10, 14, 16384, 10, 14, 16384, // 10,14
+ 10, 15, 16384, 10, 15, 16384, 10, 15, 16384, 10, 15, 16384, // 10,15
+ 11, 0, 16384, 11, 0, 16384, 11, 0, 16384, 11, 0, 16384, // 11, 0
+ 11, 1, 16384, 11, 1, 16384, 11, 1, 16384, 11, 1, 16384, // 11, 1
+ 11, 2, 16384, 11, 2, 16384, 11, 2, 16384, 11, 2, 16384, // 11, 2
+ 11, 3, 16384, 11, 3, 16384, 11, 3, 16384, 11, 3, 16384, // 11, 3
+ 11, 4, 16384, 11, 4, 16384, 11, 4, 16384, 11, 4, 16384, // 11, 4
+ 11, 5, 16384, 11, 5, 16384, 11, 5, 16384, 11, 5, 16384, // 11, 5
+ 11, 6, 16384, 11, 6, 16384, 11, 6, 16384, 11, 6, 16384, // 11, 6
+ 11, 7, 16384, 11, 7, 16384, 11, 7, 16384, 11, 7, 16384, // 11, 7
+ 11, 8, 16384, 11, 8, 16384, 11, 8, 16384, 11, 8, 16384, // 11, 8
+ 11, 9, 16384, 11, 9, 16384, 11, 9, 16384, 11, 9, 16384, // 11, 9
+ 11, 10, 16384, 11, 10, 16384, 11, 10, 16384, 11, 10, 16384, // 11,10
+ 11, 11, 16384, 11, 11, 16384, 11, 11, 16384, 11, 11, 16384, // 11,11
+ 11, 12, 16384, 11, 12, 16384, 11, 12, 16384, 11, 12, 16384, // 11,12
+ 11, 13, 16384, 11, 13, 16384, 11, 13, 16384, 11, 13, 16384, // 11,13
+ 11, 14, 16384, 11, 14, 16384, 11, 14, 16384, 11, 14, 16384, // 11,14
+ 11, 15, 16384, 11, 15, 16384, 11, 15, 16384, 11, 15, 16384, // 11,15
+ 12, 0, 16384, 12, 0, 16384, 12, 0, 16384, 12, 0, 16384, // 12, 0
+ 12, 1, 16384, 12, 1, 16384, 12, 1, 16384, 12, 1, 16384, // 12, 1
+ 12, 2, 16384, 12, 2, 16384, 12, 2, 16384, 12, 2, 16384, // 12, 2
+ 12, 3, 16384, 12, 3, 16384, 12, 3, 16384, 12, 3, 16384, // 12, 3
+ 12, 4, 16384, 12, 4, 16384, 12, 4, 16384, 12, 4, 16384, // 12, 4
+ 12, 5, 16384, 12, 5, 16384, 12, 5, 16384, 12, 5, 16384, // 12, 5
+ 12, 6, 16384, 12, 6, 16384, 12, 6, 16384, 12, 6, 16384, // 12, 6
+ 12, 7, 16384, 12, 7, 16384, 12, 7, 16384, 12, 7, 16384, // 12, 7
+ 12, 8, 16384, 12, 8, 16384, 12, 8, 16384, 12, 8, 16384, // 12, 8
+ 12, 9, 16384, 12, 9, 16384, 12, 9, 16384, 12, 9, 16384, // 12, 9
+ 12, 10, 16384, 12, 10, 16384, 12, 10, 16384, 12, 10, 16384, // 12,10
+ 12, 11, 16384, 12, 11, 16384, 12, 11, 16384, 12, 11, 16384, // 12,11
+ 12, 12, 16384, 12, 12, 16384, 12, 12, 16384, 12, 12, 16384, // 12,12
+ 12, 13, 16384, 12, 13, 16384, 12, 13, 16384, 12, 13, 16384, // 12,13
+ 12, 14, 16384, 12, 14, 16384, 12, 14, 16384, 12, 14, 16384, // 12,14
+ 12, 15, 16384, 12, 15, 16384, 12, 15, 16384, 12, 15, 16384, // 12,15
+ 13, 0, 16384, 13, 0, 16384, 13, 0, 16384, 13, 0, 16384, // 13, 0
+ 13, 1, 16384, 13, 1, 16384, 13, 1, 16384, 13, 1, 16384, // 13, 1
+ 13, 2, 16384, 13, 2, 16384, 13, 2, 16384, 13, 2, 16384, // 13, 2
+ 13, 3, 16384, 13, 3, 16384, 13, 3, 16384, 13, 3, 16384, // 13, 3
+ 13, 4, 16384, 13, 4, 16384, 13, 4, 16384, 13, 4, 16384, // 13, 4
+ 13, 5, 16384, 13, 5, 16384, 13, 5, 16384, 13, 5, 16384, // 13, 5
+ 13, 6, 16384, 13, 6, 16384, 13, 6, 16384, 13, 6, 16384, // 13, 6
+ 13, 7, 16384, 13, 7, 16384, 13, 7, 16384, 13, 7, 16384, // 13, 7
+ 13, 8, 16384, 13, 8, 16384, 13, 8, 16384, 13, 8, 16384, // 13, 8
+ 13, 9, 16384, 13, 9, 16384, 13, 9, 16384, 13, 9, 16384, // 13, 9
+ 13, 10, 16384, 13, 10, 16384, 13, 10, 16384, 13, 10, 16384, // 13,10
+ 13, 11, 16384, 13, 11, 16384, 13, 11, 16384, 13, 11, 16384, // 13,11
+ 13, 12, 16384, 13, 12, 16384, 13, 12, 16384, 13, 12, 16384, // 13,12
+ 13, 13, 16384, 13, 13, 16384, 13, 13, 16384, 13, 13, 16384, // 13,13
+ 13, 14, 16384, 13, 14, 16384, 13, 14, 16384, 13, 14, 16384, // 13,14
+ 13, 15, 16384, 13, 15, 16384, 13, 15, 16384, 13, 15, 16384, // 13,15
+ 14, 0, 16384, 14, 0, 16384, 14, 0, 16384, 14, 0, 16384, // 14, 0
+ 14, 1, 16384, 14, 1, 16384, 14, 1, 16384, 14, 1, 16384, // 14, 1
+ 14, 2, 16384, 14, 2, 16384, 14, 2, 16384, 14, 2, 16384, // 14, 2
+ 14, 3, 16384, 14, 3, 16384, 14, 3, 16384, 14, 3, 16384, // 14, 3
+ 14, 4, 16384, 14, 4, 16384, 14, 4, 16384, 14, 4, 16384, // 14, 4
+ 14, 5, 16384, 14, 5, 16384, 14, 5, 16384, 14, 5, 16384, // 14, 5
+ 14, 6, 16384, 14, 6, 16384, 14, 6, 16384, 14, 6, 16384, // 14, 6
+ 14, 7, 16384, 14, 7, 16384, 14, 7, 16384, 14, 7, 16384, // 14, 7
+ 14, 8, 16384, 14, 8, 16384, 14, 8, 16384, 14, 8, 16384, // 14, 8
+ 14, 9, 16384, 14, 9, 16384, 14, 9, 16384, 14, 9, 16384, // 14, 9
+ 14, 10, 16384, 14, 10, 16384, 14, 10, 16384, 14, 10, 16384, // 14,10
+ 14, 11, 16384, 14, 11, 16384, 14, 11, 16384, 14, 11, 16384, // 14,11
+ 14, 12, 16384, 14, 12, 16384, 14, 12, 16384, 14, 12, 16384, // 14,12
+ 14, 13, 16384, 14, 13, 16384, 14, 13, 16384, 14, 13, 16384, // 14,13
+ 14, 14, 16384, 14, 14, 16384, 14, 14, 16384, 14, 14, 16384, // 14,14
+ 14, 15, 16384, 14, 15, 16384, 14, 15, 16384, 14, 15, 16384, // 14,15
+ 15, 0, 16384, 15, 0, 16384, 15, 0, 16384, 15, 0, 16384, // 15, 0
+ 15, 1, 16384, 15, 1, 16384, 15, 1, 16384, 15, 1, 16384, // 15, 1
+ 15, 2, 16384, 15, 2, 16384, 15, 2, 16384, 15, 2, 16384, // 15, 2
+ 15, 3, 16384, 15, 3, 16384, 15, 3, 16384, 15, 3, 16384, // 15, 3
+ 15, 4, 16384, 15, 4, 16384, 15, 4, 16384, 15, 4, 16384, // 15, 4
+ 15, 5, 16384, 15, 5, 16384, 15, 5, 16384, 15, 5, 16384, // 15, 5
+ 15, 6, 16384, 15, 6, 16384, 15, 6, 16384, 15, 6, 16384, // 15, 6
+ 15, 7, 16384, 15, 7, 16384, 15, 7, 16384, 15, 7, 16384, // 15, 7
+ 15, 8, 16384, 15, 8, 16384, 15, 8, 16384, 15, 8, 16384, // 15, 8
+ 15, 9, 16384, 15, 9, 16384, 15, 9, 16384, 15, 9, 16384, // 15, 9
+ 15, 10, 16384, 15, 10, 16384, 15, 10, 16384, 15, 10, 16384, // 15,10
+ 15, 11, 16384, 15, 11, 16384, 15, 11, 16384, 15, 11, 16384, // 15,11
+ 15, 12, 16384, 15, 12, 16384, 15, 12, 16384, 15, 12, 16384, // 15,12
+ 15, 13, 16384, 15, 13, 16384, 15, 13, 16384, 15, 13, 16384, // 15,13
+ 15, 14, 16384, 15, 14, 16384, 15, 14, 16384, 15, 14, 16384, // 15,14
+ 15, 15, 16384, 15, 15, 16384, 15, 15, 16384, 15, 15, 16384, // 15,15
+ // angle of 0.5 degrees
+ 0, -1, 5106, 0, 0, 51699, 1, -1, 3621, 1, 0, 5110, // 0, 0
+ 0, 0, 4851, 0, 1, 52457, 1, 0, 3422, 1, 1, 4806, // 0, 1
+ 0, 1, 4610, 0, 2, 53168, 1, 1, 3235, 1, 2, 4523, // 0, 2
+ 0, 2, 4390, 0, 3, 53814, 1, 2, 3065, 1, 3, 4267, // 0, 3
+ 0, 3, 4200, 0, 4, 54376, 1, 3, 2917, 1, 4, 4043, // 0, 4
+ 0, 4, 4046, 0, 5, 54833, 1, 4, 2797, 1, 5, 3860, // 0, 5
+ 0, 5, 3939, 0, 6, 55164, 1, 5, 2709, 1, 6, 3724, // 0, 6
+ 0, 6, 3885, 0, 7, 55352, 1, 6, 2659, 1, 7, 3640, // 0, 7
+ -1, 7, 2659, -1, 8, 3638, 0, 7, 3885, 0, 8, 55354, // 0, 8
+ -1, 8, 2709, -1, 9, 3722, 0, 8, 3940, 0, 9, 55165, // 0, 9
+ -1, 9, 2796, -1, 10, 3858, 0, 9, 4047, 0, 10, 54835, // 0,10
+ -1, 10, 2916, -1, 11, 4041, 0, 10, 4201, 0, 11, 54378, // 0,11
+ -1, 11, 3064, -1, 12, 4264, 0, 11, 4392, 0, 12, 53816, // 0,12
+ -1, 12, 3235, -1, 13, 4521, 0, 12, 4612, 0, 13, 53168, // 0,13
+ -1, 13, 3421, -1, 14, 4803, 0, 13, 4854, 0, 14, 52458, // 0,14
+ -1, 14, 3621, -1, 15, 5106, 0, 14, 5110, 0, 15, 51699, // 0,15
+ 1, -1, 4803, 1, 0, 52457, 2, -1, 3421, 2, 0, 4855, // 1, 0
+ 1, 0, 4522, 1, 1, 53285, 2, 0, 3204, 2, 1, 4525, // 1, 1
+ 1, 1, 4253, 1, 2, 54071, 2, 1, 2998, 2, 2, 4214, // 1, 2
+ 1, 2, 4003, 1, 3, 54796, 2, 2, 2808, 2, 3, 3929, // 1, 3
+ 1, 3, 3783, 1, 4, 55434, 2, 3, 2640, 2, 4, 3679, // 1, 4
+ 1, 4, 3604, 1, 5, 55958, 2, 4, 2503, 2, 5, 3471, // 1, 5
+ 1, 5, 3476, 1, 6, 56339, 2, 5, 2403, 2, 6, 3318, // 1, 6
+ 1, 6, 3411, 1, 7, 56552, 2, 6, 2346, 2, 7, 3227, // 1, 7
+ 0, 7, 2346, 0, 8, 3225, 1, 7, 3411, 1, 8, 56554, // 1, 8
+ 0, 8, 2402, 0, 9, 3317, 1, 8, 3477, 1, 9, 56340, // 1, 9
+ 0, 9, 2502, 0, 10, 3470, 1, 9, 3605, 1, 10, 55959, // 1,10
+ 0, 10, 2640, 0, 11, 3677, 1, 10, 3785, 1, 11, 55434, // 1,11
+ 0, 11, 2808, 0, 12, 3927, 1, 11, 4005, 1, 12, 54796, // 1,12
+ 0, 12, 2998, 0, 13, 4212, 1, 12, 4255, 1, 13, 54071, // 1,13
+ 0, 13, 3204, 0, 14, 4522, 1, 13, 4525, 1, 14, 53285, // 1,14
+ 0, 14, 3422, 0, 15, 4851, 1, 14, 4806, 1, 15, 52457, // 1,15
+ 2, -1, 4521, 2, 0, 53168, 3, -1, 3235, 3, 0, 4612, // 2, 0
+ 2, 0, 4212, 2, 1, 54072, 3, 0, 2998, 3, 1, 4254, // 2, 1
+ 2, 1, 3911, 2, 2, 54941, 3, 1, 2770, 3, 2, 3914, // 2, 2
+ 2, 2, 3628, 2, 3, 55756, 3, 2, 2557, 3, 3, 3595, // 2, 3
+ 2, 3, 3373, 2, 4, 56486, 3, 3, 2365, 3, 4, 3312, // 2, 4
+ 2, 4, 3161, 2, 5, 57095, 3, 4, 2205, 3, 5, 3075, // 2, 5
+ 2, 5, 3007, 2, 6, 57544, 3, 5, 2088, 3, 6, 2897, // 2, 6
+ 2, 6, 2926, 2, 7, 57793, 3, 6, 2022, 3, 7, 2795, // 2, 7
+ 1, 7, 2022, 1, 8, 2794, 2, 7, 2926, 2, 8, 57794, // 2, 8
+ 1, 8, 2088, 1, 9, 2897, 2, 8, 3007, 2, 9, 57544, // 2, 9
+ 1, 9, 2205, 1, 10, 3073, 2, 9, 3161, 2, 10, 57097, // 2,10
+ 1, 10, 2365, 1, 11, 3310, 2, 10, 3374, 2, 11, 56487, // 2,11
+ 1, 11, 2556, 1, 12, 3594, 2, 11, 3630, 2, 12, 55756, // 2,12
+ 1, 12, 2770, 1, 13, 3911, 2, 12, 3913, 2, 13, 54942, // 2,13
+ 1, 13, 2998, 1, 14, 4253, 2, 13, 4214, 2, 14, 54071, // 2,14
+ 1, 14, 3235, 1, 15, 4610, 2, 14, 4523, 2, 15, 53168, // 2,15
+ 3, -1, 4264, 3, 0, 53815, 4, -1, 3064, 4, 0, 4393, // 3, 0
+ 3, 0, 3927, 3, 1, 54796, 4, 0, 2808, 4, 1, 4005, // 3, 1
+ 3, 1, 3594, 3, 2, 55756, 4, 1, 2556, 4, 2, 3630, // 3, 2
+ 3, 2, 3273, 3, 3, 56673, 4, 2, 2317, 4, 3, 3273, // 3, 3
+ 3, 3, 2976, 3, 4, 57514, 4, 3, 2096, 4, 4, 2950, // 3, 4
+ 3, 4, 2722, 3, 5, 58233, 4, 4, 1908, 4, 5, 2673, // 3, 5
+ 3, 5, 2532, 3, 6, 58774, 4, 5, 1767, 4, 6, 2463, // 3, 6
+ 3, 6, 2430, 3, 7, 59076, 4, 6, 1687, 4, 7, 2343, // 3, 7
+ 2, 7, 1687, 2, 8, 2342, 3, 7, 2430, 3, 8, 59077, // 3, 8
+ 2, 8, 1766, 2, 9, 2463, 3, 8, 2532, 3, 9, 58775, // 3, 9
+ 2, 9, 1908, 2, 10, 2672, 3, 9, 2723, 3, 10, 58233, // 3,10
+ 2, 10, 2096, 2, 11, 2948, 3, 10, 2977, 3, 11, 57515, // 3,11
+ 2, 11, 2317, 2, 12, 3273, 3, 11, 3274, 3, 12, 56672, // 3,12
+ 2, 12, 2557, 2, 13, 3628, 3, 12, 3595, 3, 13, 55756, // 3,13
+ 2, 13, 2808, 2, 14, 4003, 3, 13, 3929, 3, 14, 54796, // 3,14
+ 2, 14, 3065, 2, 15, 4390, 3, 14, 4267, 3, 15, 53814, // 3,15
+ 4, -1, 4041, 4, 0, 54378, 5, -1, 2916, 5, 0, 4201, // 4, 0
+ 4, 0, 3677, 4, 1, 55435, 5, 0, 2640, 5, 1, 3784, // 4, 1
+ 4, 1, 3310, 4, 2, 56487, 5, 1, 2365, 5, 2, 3374, // 4, 2
+ 4, 2, 2948, 4, 3, 57514, 5, 2, 2096, 5, 3, 2978, // 4, 3
+ 4, 3, 2604, 4, 4, 58484, 5, 3, 1843, 5, 4, 2605, // 4, 4
+ 4, 4, 2297, 4, 5, 59345, 5, 4, 1617, 5, 5, 2277, // 4, 5
+ 4, 5, 2057, 4, 6, 60017, 5, 5, 1442, 5, 6, 2020, // 4, 6
+ 4, 6, 1922, 4, 7, 60402, 5, 6, 1341, 5, 7, 1871, // 4, 7
+ 3, 7, 1341, 3, 8, 1871, 4, 7, 1922, 4, 8, 60402, // 4, 8
+ 3, 8, 1442, 3, 9, 2020, 4, 8, 2057, 4, 9, 60017, // 4, 9
+ 3, 9, 1617, 3, 10, 2276, 4, 9, 2297, 4, 10, 59346, // 4,10
+ 3, 10, 1843, 3, 11, 2604, 4, 10, 2605, 4, 11, 58484, // 4,11
+ 3, 11, 2096, 3, 12, 2976, 4, 11, 2950, 4, 12, 57514, // 4,12
+ 3, 12, 2365, 3, 13, 3373, 4, 12, 3311, 4, 13, 56487, // 4,13
+ 3, 13, 2640, 3, 14, 3783, 4, 13, 3678, 4, 14, 55435, // 4,14
+ 3, 14, 2917, 3, 15, 4200, 4, 14, 4043, 4, 15, 54376, // 4,15
+ 5, -1, 3858, 5, 0, 54835, 6, -1, 2796, 6, 0, 4047, // 5, 0
+ 5, 0, 3470, 5, 1, 55959, 6, 0, 2502, 6, 1, 3605, // 5, 1
+ 5, 1, 3073, 5, 2, 57096, 6, 1, 2205, 6, 2, 3162, // 5, 2
+ 5, 2, 2672, 5, 3, 58234, 6, 2, 1908, 6, 3, 2722, // 5, 3
+ 5, 3, 2276, 5, 4, 59346, 6, 3, 1617, 6, 4, 2297, // 5, 4
+ 5, 4, 1904, 5, 5, 60381, 6, 4, 1347, 6, 5, 1904, // 5, 5
+ 5, 5, 1593, 5, 6, 61243, 6, 5, 1121, 6, 6, 1579, // 5, 6
+ 5, 6, 1405, 5, 7, 61767, 6, 6, 985, 6, 7, 1379, // 5, 7
+ 4, 7, 985, 4, 8, 1380, 5, 7, 1405, 5, 8, 61766, // 5, 8
+ 4, 8, 1121, 4, 9, 1578, 5, 8, 1593, 5, 9, 61244, // 5, 9
+ 4, 9, 1347, 4, 10, 1904, 5, 9, 1904, 5, 10, 60381, // 5,10
+ 4, 10, 1617, 4, 11, 2297, 5, 10, 2276, 5, 11, 59346, // 5,11
+ 4, 11, 1908, 4, 12, 2722, 5, 11, 2673, 5, 12, 58233, // 5,12
+ 4, 12, 2205, 4, 13, 3161, 5, 12, 3074, 5, 13, 57096, // 5,13
+ 4, 13, 2503, 4, 14, 3604, 5, 13, 3472, 5, 14, 55957, // 5,14
+ 4, 14, 2797, 4, 15, 4046, 5, 14, 3860, 5, 15, 54833, // 5,15
+ 6, -1, 3722, 6, 0, 55166, 7, -1, 2709, 7, 0, 3939, // 6, 0
+ 6, 0, 3317, 6, 1, 56340, 7, 0, 2402, 7, 1, 3477, // 6, 1
+ 6, 1, 2897, 6, 2, 57545, 7, 1, 2088, 7, 2, 3006, // 6, 2
+ 6, 2, 2463, 6, 3, 58775, 7, 2, 1766, 7, 3, 2532, // 6, 3
+ 6, 3, 2020, 6, 4, 60018, 7, 3, 1442, 7, 4, 2056, // 6, 4
+ 6, 4, 1578, 6, 5, 61243, 7, 4, 1121, 7, 5, 1594, // 6, 5
+ 6, 5, 1170, 6, 6, 62369, 7, 5, 827, 7, 6, 1170, // 6, 6
+ 6, 6, 883, 6, 7, 63156, 7, 6, 622, 7, 7, 875, // 6, 7
+ 5, 7, 622, 5, 8, 875, 6, 7, 883, 6, 8, 63156, // 6, 8
+ 5, 8, 827, 5, 9, 1170, 6, 8, 1170, 6, 9, 62369, // 6, 9
+ 5, 9, 1121, 5, 10, 1593, 6, 9, 1579, 6, 10, 61243, // 6,10
+ 5, 10, 1442, 5, 11, 2057, 6, 10, 2020, 6, 11, 60017, // 6,11
+ 5, 11, 1767, 5, 12, 2532, 6, 11, 2464, 6, 12, 58773, // 6,12
+ 5, 12, 2088, 5, 13, 3007, 6, 12, 2898, 6, 13, 57543, // 6,13
+ 5, 13, 2403, 5, 14, 3476, 6, 13, 3319, 6, 14, 56338, // 6,14
+ 5, 14, 2709, 5, 15, 3939, 6, 14, 3724, 6, 15, 55164, // 6,15
+ 7, -1, 3638, 7, 0, 55354, 8, -1, 2659, 8, 0, 3885, // 7, 0
+ 7, 0, 3225, 7, 1, 56554, 8, 0, 2346, 8, 1, 3411, // 7, 1
+ 7, 1, 2794, 7, 2, 57795, 8, 1, 2022, 8, 2, 2925, // 7, 2
+ 7, 2, 2342, 7, 3, 59077, 8, 2, 1687, 8, 3, 2430, // 7, 3
+ 7, 3, 1871, 7, 4, 60402, 8, 3, 1341, 8, 4, 1922, // 7, 4
+ 7, 4, 1380, 7, 5, 61767, 8, 4, 985, 8, 5, 1404, // 7, 5
+ 7, 5, 875, 7, 6, 63156, 8, 5, 622, 8, 6, 883, // 7, 6
+ 7, 6, 399, 7, 7, 64455, 8, 6, 282, 8, 7, 400, // 7, 7
+ 6, 7, 282, 6, 8, 399, 7, 7, 399, 7, 8, 64456, // 7, 8
+ 6, 8, 622, 6, 9, 883, 7, 8, 875, 7, 9, 63156, // 7, 9
+ 6, 9, 985, 6, 10, 1405, 7, 9, 1380, 7, 10, 61766, // 7,10
+ 6, 10, 1341, 6, 11, 1922, 7, 10, 1871, 7, 11, 60402, // 7,11
+ 6, 11, 1687, 6, 12, 2430, 7, 11, 2343, 7, 12, 59076, // 7,12
+ 6, 12, 2022, 6, 13, 2926, 7, 12, 2795, 7, 13, 57793, // 7,13
+ 6, 13, 2346, 6, 14, 3411, 7, 13, 3227, 7, 14, 56552, // 7,14
+ 6, 14, 2659, 6, 15, 3885, 7, 14, 3640, 7, 15, 55352, // 7,15
+ 8, 0, 55352, 8, 1, 3640, 9, 0, 3885, 9, 1, 2659, // 8, 0
+ 8, 1, 56552, 8, 2, 3227, 9, 1, 3411, 9, 2, 2346, // 8, 1
+ 8, 2, 57793, 8, 3, 2795, 9, 2, 2926, 9, 3, 2022, // 8, 2
+ 8, 3, 59076, 8, 4, 2343, 9, 3, 2430, 9, 4, 1687, // 8, 3
+ 8, 4, 60402, 8, 5, 1871, 9, 4, 1922, 9, 5, 1341, // 8, 4
+ 8, 5, 61767, 8, 6, 1380, 9, 5, 1405, 9, 6, 984, // 8, 5
+ 8, 6, 63156, 8, 7, 875, 9, 6, 883, 9, 7, 622, // 8, 6
+ 8, 7, 64455, 8, 8, 399, 9, 7, 399, 9, 8, 283, // 8, 7
+ 7, 8, 399, 7, 9, 282, 8, 8, 64455, 8, 9, 400, // 8, 8
+ 7, 9, 883, 7, 10, 622, 8, 9, 63156, 8, 10, 875, // 8, 9
+ 7, 10, 1405, 7, 11, 985, 8, 10, 61767, 8, 11, 1379, // 8,10
+ 7, 11, 1922, 7, 12, 1341, 8, 11, 60402, 8, 12, 1871, // 8,11
+ 7, 12, 2430, 7, 13, 1687, 8, 12, 59077, 8, 13, 2342, // 8,12
+ 7, 13, 2926, 7, 14, 2022, 8, 13, 57795, 8, 14, 2793, // 8,13
+ 7, 14, 3411, 7, 15, 2346, 8, 14, 56554, 8, 15, 3225, // 8,14
+ 7, 15, 3885, 7, 16, 2659, 8, 15, 55354, 8, 16, 3638, // 8,15
+ 9, 0, 55164, 9, 1, 3724, 10, 0, 3939, 10, 1, 2709, // 9, 0
+ 9, 1, 56339, 9, 2, 3319, 10, 1, 3476, 10, 2, 2402, // 9, 1
+ 9, 2, 57544, 9, 3, 2898, 10, 2, 3007, 10, 3, 2087, // 9, 2
+ 9, 3, 58774, 9, 4, 2464, 10, 3, 2532, 10, 4, 1766, // 9, 3
+ 9, 4, 60017, 9, 5, 2020, 10, 4, 2057, 10, 5, 1442, // 9, 4
+ 9, 5, 61243, 9, 6, 1579, 10, 5, 1593, 10, 6, 1121, // 9, 5
+ 9, 6, 62369, 9, 7, 1170, 10, 6, 1170, 10, 7, 827, // 9, 6
+ 9, 7, 63156, 9, 8, 883, 10, 7, 875, 10, 8, 622, // 9, 7
+ 8, 8, 875, 8, 9, 622, 9, 8, 63156, 9, 9, 883, // 9, 8
+ 8, 9, 1170, 8, 10, 827, 9, 9, 62369, 9, 10, 1170, // 9, 9
+ 8, 10, 1593, 8, 11, 1121, 9, 10, 61243, 9, 11, 1579, // 9,10
+ 8, 11, 2057, 8, 12, 1442, 9, 11, 60018, 9, 12, 2019, // 9,11
+ 8, 12, 2532, 8, 13, 1766, 9, 12, 58775, 9, 13, 2463, // 9,12
+ 8, 13, 3007, 8, 14, 2088, 9, 13, 57545, 9, 14, 2896, // 9,13
+ 8, 14, 3477, 8, 15, 2402, 9, 14, 56340, 9, 15, 3317, // 9,14
+ 8, 15, 3940, 8, 16, 2709, 9, 15, 55166, 9, 16, 3721, // 9,15
+ 10, 0, 54833, 10, 1, 3860, 11, 0, 4046, 11, 1, 2797, // 10, 0
+ 10, 1, 55958, 10, 2, 3472, 11, 1, 3604, 11, 2, 2502, // 10, 1
+ 10, 2, 57095, 10, 3, 3074, 11, 2, 3161, 11, 3, 2206, // 10, 2
+ 10, 3, 58233, 10, 4, 2673, 11, 3, 2722, 11, 4, 1908, // 10, 3
+ 10, 4, 59345, 10, 5, 2276, 11, 4, 2297, 11, 5, 1618, // 10, 4
+ 10, 5, 60381, 10, 6, 1904, 11, 5, 1904, 11, 6, 1347, // 10, 5
+ 10, 6, 61243, 10, 7, 1593, 11, 6, 1578, 11, 7, 1122, // 10, 6
+ 10, 7, 61767, 10, 8, 1405, 11, 7, 1380, 11, 8, 984, // 10, 7
+ 9, 8, 1380, 9, 9, 985, 10, 8, 61767, 10, 9, 1404, // 10, 8
+ 9, 9, 1579, 9, 10, 1121, 10, 9, 61243, 10, 10, 1593, // 10, 9
+ 9, 10, 1904, 9, 11, 1347, 10, 10, 60381, 10, 11, 1904, // 10,10
+ 9, 11, 2297, 9, 12, 1617, 10, 11, 59346, 10, 12, 2276, // 10,11
+ 9, 12, 2723, 9, 13, 1908, 10, 12, 58234, 10, 13, 2671, // 10,12
+ 9, 13, 3161, 9, 14, 2205, 10, 13, 57096, 10, 14, 3074, // 10,13
+ 9, 14, 3605, 9, 15, 2502, 10, 14, 55959, 10, 15, 3470, // 10,14
+ 9, 15, 4047, 9, 16, 2796, 10, 15, 54835, 10, 16, 3858, // 10,15
+ 11, 0, 54376, 11, 1, 4043, 12, 0, 4200, 12, 1, 2917, // 11, 0
+ 11, 1, 55434, 11, 2, 3678, 12, 1, 3783, 12, 2, 2641, // 11, 1
+ 11, 2, 56486, 11, 3, 3311, 12, 2, 3373, 12, 3, 2366, // 11, 2
+ 11, 3, 57514, 11, 4, 2950, 12, 3, 2976, 12, 4, 2096, // 11, 3
+ 11, 4, 58484, 11, 5, 2605, 12, 4, 2604, 12, 5, 1843, // 11, 4
+ 11, 5, 59346, 11, 6, 2297, 12, 5, 2276, 12, 6, 1617, // 11, 5
+ 11, 6, 60018, 11, 7, 2057, 12, 6, 2020, 12, 7, 1441, // 11, 6
+ 11, 7, 60402, 11, 8, 1922, 12, 7, 1871, 12, 8, 1341, // 11, 7
+ 10, 8, 1871, 10, 9, 1341, 11, 8, 60402, 11, 9, 1922, // 11, 8
+ 10, 9, 2020, 10, 10, 1442, 11, 9, 60017, 11, 10, 2057, // 11, 9
+ 10, 10, 2276, 10, 11, 1617, 11, 10, 59345, 11, 11, 2298, // 11,10
+ 10, 11, 2605, 10, 12, 1843, 11, 11, 58484, 11, 12, 2604, // 11,11
+ 10, 12, 2977, 10, 13, 2096, 11, 12, 57514, 11, 13, 2949, // 11,12
+ 10, 13, 3374, 10, 14, 2365, 11, 13, 56487, 11, 14, 3310, // 11,13
+ 10, 14, 3785, 10, 15, 2640, 11, 14, 55435, 11, 15, 3676, // 11,14
+ 10, 15, 4201, 10, 16, 2916, 11, 15, 54378, 11, 16, 4041, // 11,15
+ 12, 0, 53814, 12, 1, 4267, 13, 0, 4390, 13, 1, 3065, // 12, 0
+ 12, 1, 54796, 12, 2, 3929, 13, 1, 4003, 13, 2, 2808, // 12, 1
+ 12, 2, 55756, 12, 3, 3595, 13, 2, 3628, 13, 3, 2557, // 12, 2
+ 12, 3, 56673, 12, 4, 3274, 13, 3, 3273, 13, 4, 2316, // 12, 3
+ 12, 4, 57514, 12, 5, 2977, 13, 4, 2948, 13, 5, 2097, // 12, 4
+ 12, 5, 58234, 12, 6, 2723, 13, 5, 2672, 13, 6, 1907, // 12, 5
+ 12, 6, 58775, 12, 7, 2532, 13, 6, 2463, 13, 7, 1766, // 12, 6
+ 12, 7, 59077, 12, 8, 2430, 13, 7, 2342, 13, 8, 1687, // 12, 7
+ 11, 8, 2343, 11, 9, 1687, 12, 8, 59076, 12, 9, 2430, // 12, 8
+ 11, 9, 2464, 11, 10, 1767, 12, 9, 58774, 12, 10, 2531, // 12, 9
+ 11, 10, 2673, 11, 11, 1908, 12, 10, 58233, 12, 11, 2722, // 12,10
+ 11, 11, 2950, 11, 12, 2096, 12, 11, 57514, 12, 12, 2976, // 12,11
+ 11, 12, 3274, 11, 13, 2317, 12, 12, 56673, 12, 13, 3272, // 12,12
+ 11, 13, 3630, 11, 14, 2556, 12, 13, 55756, 12, 14, 3594, // 12,13
+ 11, 14, 4005, 11, 15, 2808, 12, 14, 54796, 12, 15, 3927, // 12,14
+ 11, 15, 4392, 11, 16, 3064, 12, 15, 53815, 12, 16, 4265, // 12,15
+ 13, 0, 53168, 13, 1, 4523, 14, 0, 4610, 14, 1, 3235, // 13, 0
+ 13, 1, 54071, 13, 2, 4214, 14, 1, 4253, 14, 2, 2998, // 13, 1
+ 13, 2, 54941, 13, 3, 3913, 14, 2, 3911, 14, 3, 2771, // 13, 2
+ 13, 3, 55756, 13, 4, 3630, 14, 3, 3594, 14, 4, 2556, // 13, 3
+ 13, 4, 56487, 13, 5, 3374, 14, 4, 3310, 14, 5, 2365, // 13, 4
+ 13, 5, 57096, 13, 6, 3161, 14, 5, 3073, 14, 6, 2206, // 13, 5
+ 13, 6, 57545, 13, 7, 3007, 14, 6, 2897, 14, 7, 2087, // 13, 6
+ 13, 7, 57795, 13, 8, 2926, 14, 7, 2794, 14, 8, 2021, // 13, 7
+ 12, 8, 2795, 12, 9, 2022, 13, 8, 57793, 13, 9, 2926, // 13, 8
+ 12, 9, 2898, 12, 10, 2088, 13, 9, 57544, 13, 10, 3006, // 13, 9
+ 12, 10, 3074, 12, 11, 2205, 13, 10, 57095, 13, 11, 3162, // 13,10
+ 12, 11, 3311, 12, 12, 2365, 13, 11, 56486, 13, 12, 3374, // 13,11
+ 12, 12, 3595, 12, 13, 2557, 13, 12, 55756, 13, 13, 3628, // 13,12
+ 12, 13, 3913, 12, 14, 2770, 13, 13, 54941, 13, 14, 3912, // 13,13
+ 12, 14, 4255, 12, 15, 2998, 13, 14, 54072, 13, 15, 4211, // 13,14
+ 12, 15, 4612, 12, 16, 3235, 13, 15, 53168, 13, 16, 4521, // 13,15
+ 14, 0, 52457, 14, 1, 4806, 15, 0, 4851, 15, 1, 3422, // 14, 0
+ 14, 1, 53285, 14, 2, 4525, 15, 1, 4522, 15, 2, 3204, // 14, 1
+ 14, 2, 54072, 14, 3, 4255, 15, 2, 4212, 15, 3, 2997, // 14, 2
+ 14, 3, 54796, 14, 4, 4005, 15, 3, 3927, 15, 4, 2808, // 14, 3
+ 14, 4, 55435, 14, 5, 3785, 15, 4, 3677, 15, 5, 2639, // 14, 4
+ 14, 5, 55959, 14, 6, 3605, 15, 5, 3470, 15, 6, 2502, // 14, 5
+ 14, 6, 56340, 14, 7, 3477, 15, 6, 3317, 15, 7, 2402, // 14, 6
+ 14, 7, 56554, 14, 8, 3411, 15, 7, 3225, 15, 8, 2346, // 14, 7
+ 13, 8, 3227, 13, 9, 2346, 14, 8, 56552, 14, 9, 3411, // 14, 8
+ 13, 9, 3319, 13, 10, 2403, 14, 9, 56339, 14, 10, 3475, // 14, 9
+ 13, 10, 3472, 13, 11, 2503, 14, 10, 55958, 14, 11, 3603, // 14,10
+ 13, 11, 3678, 13, 12, 2640, 14, 11, 55434, 14, 12, 3784, // 14,11
+ 13, 12, 3929, 13, 13, 2808, 14, 12, 54796, 14, 13, 4003, // 14,12
+ 13, 13, 4214, 13, 14, 2998, 14, 13, 54071, 14, 14, 4253, // 14,13
+ 13, 14, 4525, 13, 15, 3204, 14, 14, 53285, 14, 15, 4522, // 14,14
+ 13, 15, 4854, 13, 16, 3421, 14, 15, 52457, 14, 16, 4804, // 14,15
+ 15, 0, 51699, 15, 1, 5110, 16, 0, 5106, 16, 1, 3621, // 15, 0
+ 15, 1, 52457, 15, 2, 4854, 16, 1, 4803, 16, 2, 3422, // 15, 1
+ 15, 2, 53168, 15, 3, 4612, 16, 2, 4521, 16, 3, 3235, // 15, 2
+ 15, 3, 53815, 15, 4, 4392, 16, 3, 4264, 16, 4, 3065, // 15, 3
+ 15, 4, 54378, 15, 5, 4201, 16, 4, 4041, 16, 5, 2916, // 15, 4
+ 15, 5, 54835, 15, 6, 4047, 16, 5, 3858, 16, 6, 2796, // 15, 5
+ 15, 6, 55166, 15, 7, 3940, 16, 6, 3722, 16, 7, 2708, // 15, 6
+ 15, 7, 55354, 15, 8, 3885, 16, 7, 3638, 16, 8, 2659, // 15, 7
+ 14, 8, 3640, 14, 9, 2659, 15, 8, 55352, 15, 9, 3885, // 15, 8
+ 14, 9, 3724, 14, 10, 2709, 15, 9, 55164, 15, 10, 3939, // 15, 9
+ 14, 10, 3860, 14, 11, 2797, 15, 10, 54833, 15, 11, 4046, // 15,10
+ 14, 11, 4043, 14, 12, 2917, 15, 11, 54376, 15, 12, 4200, // 15,11
+ 14, 12, 4267, 14, 13, 3065, 15, 12, 53814, 15, 13, 4390, // 15,12
+ 14, 13, 4523, 14, 14, 3235, 15, 13, 53168, 15, 14, 4610, // 15,13
+ 14, 14, 4806, 14, 15, 3422, 15, 14, 52457, 15, 15, 4851, // 15,14
+ 14, 15, 5110, 14, 16, 3621, 15, 15, 51699, 15, 16, 5106, // 15,15
+ // angle of 1.0 degrees
+ 0, -1, 8769, 0, 0, 41693, 1, -1, 6280, 1, 0, 8794, // 0, 0
+ 0, 0, 8452, 0, 1, 42821, 1, 0, 5975, 1, 1, 8288, // 0, 1
+ 0, 1, 8141, 0, 2, 43900, 1, 1, 5684, 1, 2, 7811, // 0, 2
+ 0, 2, 7848, 0, 3, 44901, 1, 2, 5413, 1, 3, 7374, // 0, 3
+ 0, 3, 7587, 0, 4, 45791, 1, 3, 5172, 1, 4, 6986, // 0, 4
+ 0, 4, 7374, 0, 5, 46532, 1, 4, 4971, 1, 5, 6659, // 0, 5
+ 0, 5, 7227, 0, 6, 47086, 1, 5, 4818, 1, 6, 6405, // 0, 6
+ 0, 6, 7158, 0, 7, 47426, 1, 6, 4722, 1, 7, 6230, // 0, 7
+ -1, 7, 4718, -1, 8, 6217, 0, 7, 7161, 0, 8, 47440, // 0, 8
+ -1, 8, 4814, -1, 9, 6391, 0, 8, 7233, 0, 9, 47098, // 0, 9
+ -1, 9, 4967, -1, 10, 6644, 0, 9, 7383, 0, 10, 46542, // 0,10
+ -1, 10, 5169, -1, 11, 6970, 0, 10, 7599, 0, 11, 45798, // 0,11
+ -1, 11, 5410, -1, 12, 7356, 0, 11, 7863, 0, 12, 44907, // 0,12
+ -1, 12, 5682, -1, 13, 7791, 0, 12, 8159, 0, 13, 43904, // 0,13
+ -1, 13, 5974, -1, 14, 8265, 0, 13, 8474, 0, 14, 42823, // 0,14
+ -1, 14, 6280, -1, 15, 8769, 0, 14, 8795, 0, 15, 41692, // 0,15
+ 1, -1, 8265, 1, 0, 42823, 2, -1, 5974, 2, 0, 8474, // 1, 0
+ 1, 0, 7901, 1, 1, 44074, 2, 0, 5640, 2, 1, 7921, // 1, 1
+ 1, 1, 7539, 1, 2, 45286, 2, 1, 5316, 2, 2, 7395, // 1, 2
+ 1, 2, 7191, 1, 3, 46427, 2, 2, 5011, 2, 3, 6907, // 1, 3
+ 1, 3, 6875, 1, 4, 47453, 2, 3, 4736, 2, 4, 6472, // 1, 4
+ 1, 4, 6613, 1, 5, 48314, 2, 4, 4505, 2, 5, 6104, // 1, 5
+ 1, 5, 6425, 1, 6, 48960, 2, 5, 4330, 2, 6, 5821, // 1, 6
+ 1, 6, 6332, 1, 7, 49347, 2, 6, 4224, 2, 7, 5633, // 1, 7
+ 0, 7, 4221, 0, 8, 5623, 1, 7, 6335, 1, 8, 49357, // 1, 8
+ 0, 8, 4327, 0, 9, 5809, 1, 8, 6430, 1, 9, 48970, // 1, 9
+ 0, 9, 4502, 0, 10, 6092, 1, 9, 6620, 1, 10, 48322, // 1,10
+ 0, 10, 4734, 0, 11, 6458, 1, 10, 6886, 1, 11, 47458, // 1,11
+ 0, 11, 5009, 0, 12, 6892, 1, 11, 7204, 1, 12, 46431, // 1,12
+ 0, 12, 5315, 0, 13, 7378, 1, 12, 7555, 1, 13, 45288, // 1,13
+ 0, 13, 5640, 0, 14, 7901, 1, 13, 7921, 1, 14, 44074, // 1,14
+ 0, 14, 5975, 0, 15, 8452, 1, 14, 8288, 1, 15, 42821, // 1,15
+ 2, -1, 7791, 2, 0, 43904, 3, -1, 5682, 3, 0, 8159, // 2, 0
+ 2, 0, 7378, 2, 1, 45288, 3, 0, 5315, 3, 1, 7555, // 2, 1
+ 2, 1, 6959, 2, 2, 46650, 3, 1, 4954, 3, 2, 6973, // 2, 2
+ 2, 2, 6549, 2, 3, 47953, 3, 2, 4608, 3, 3, 6426, // 2, 3
+ 2, 3, 6168, 2, 4, 49147, 3, 3, 4291, 3, 4, 5930, // 2, 4
+ 2, 4, 5842, 2, 5, 50165, 3, 4, 4020, 3, 5, 5509, // 2, 5
+ 2, 5, 5602, 2, 6, 50935, 3, 5, 3815, 3, 6, 5184, // 2, 6
+ 2, 6, 5478, 2, 7, 51387, 3, 6, 3693, 3, 7, 4978, // 2, 7
+ 1, 7, 3691, 1, 8, 4970, 2, 7, 5480, 2, 8, 51395, // 2, 8
+ 1, 8, 3813, 1, 9, 5175, 2, 8, 5606, 2, 9, 50942, // 2, 9
+ 1, 9, 4019, 1, 10, 5499, 2, 9, 5848, 2, 10, 50170, // 2,10
+ 1, 10, 4290, 1, 11, 5920, 2, 10, 6176, 2, 11, 49150, // 2,11
+ 1, 11, 4607, 1, 12, 6414, 2, 11, 6560, 2, 12, 47955, // 2,12
+ 1, 12, 4954, 1, 13, 6959, 2, 12, 6973, 2, 13, 46650, // 2,13
+ 1, 13, 5316, 1, 14, 7539, 2, 13, 7395, 2, 14, 45286, // 2,14
+ 1, 14, 5684, 1, 15, 8141, 2, 14, 7812, 2, 15, 43899, // 2,15
+ 3, -1, 7356, 3, 0, 44907, 4, -1, 5410, 4, 0, 7863, // 3, 0
+ 3, 0, 6892, 3, 1, 46430, 4, 0, 5009, 4, 1, 7205, // 3, 1
+ 3, 1, 6414, 3, 2, 47955, 4, 1, 4607, 4, 2, 6560, // 3, 2
+ 3, 2, 5934, 3, 3, 49445, 4, 2, 4214, 4, 3, 5943, // 3, 3
+ 3, 3, 5474, 3, 4, 50843, 4, 3, 3846, 4, 4, 5373, // 3, 4
+ 3, 4, 5069, 3, 5, 52066, 4, 4, 3523, 4, 5, 4878, // 3, 5
+ 3, 5, 4759, 3, 6, 53008, 4, 5, 3274, 4, 6, 4495, // 3, 6
+ 3, 6, 4592, 3, 7, 53557, 4, 6, 3128, 4, 7, 4259, // 3, 7
+ 2, 7, 3126, 2, 8, 4254, 3, 7, 4594, 3, 8, 53562, // 3, 8
+ 2, 8, 3273, 2, 9, 4489, 3, 8, 4762, 3, 9, 53012, // 3, 9
+ 2, 9, 3522, 2, 10, 4872, 3, 9, 5073, 3, 10, 52069, // 3,10
+ 2, 10, 3845, 2, 11, 5365, 3, 10, 5481, 3, 11, 50845, // 3,11
+ 2, 11, 4214, 2, 12, 5934, 3, 11, 5943, 3, 12, 49445, // 3,12
+ 2, 12, 4608, 2, 13, 6549, 3, 12, 6426, 3, 13, 47953, // 3,13
+ 2, 13, 5011, 2, 14, 7191, 3, 13, 6908, 3, 14, 46426, // 3,14
+ 2, 14, 5413, 2, 15, 7848, 3, 14, 7374, 3, 15, 44901, // 3,15
+ 4, -1, 6970, 4, 0, 45799, 5, -1, 5169, 5, 0, 7598, // 4, 0
+ 4, 0, 6458, 4, 1, 47458, 5, 0, 4734, 5, 1, 6886, // 4, 1
+ 4, 1, 5920, 4, 2, 49150, 5, 1, 4290, 5, 2, 6176, // 4, 2
+ 4, 2, 5365, 4, 3, 50844, 5, 2, 3845, 5, 3, 5482, // 4, 3
+ 4, 3, 4816, 4, 4, 52484, 5, 3, 3415, 5, 4, 4821, // 4, 4
+ 4, 4, 4309, 4, 5, 53973, 5, 4, 3023, 5, 5, 4231, // 4, 5
+ 4, 5, 3902, 4, 6, 55164, 5, 5, 2711, 5, 6, 3759, // 4, 6
+ 4, 6, 3671, 4, 7, 55867, 5, 6, 2525, 5, 7, 3473, // 4, 7
+ 3, 7, 2524, 3, 8, 3469, 4, 7, 3672, 4, 8, 55871, // 4, 8
+ 3, 8, 2710, 3, 9, 3755, 4, 8, 3904, 4, 9, 55167, // 4, 9
+ 3, 9, 3023, 3, 10, 4226, 4, 9, 4313, 4, 10, 53974, // 4,10
+ 3, 10, 3415, 3, 11, 4816, 4, 10, 4822, 4, 11, 52483, // 4,11
+ 3, 11, 3846, 3, 12, 5474, 4, 11, 5373, 4, 12, 50843, // 4,12
+ 3, 12, 4291, 3, 13, 6168, 4, 12, 5930, 4, 13, 49147, // 4,13
+ 3, 13, 4736, 3, 14, 6875, 4, 13, 6472, 4, 14, 47453, // 4,14
+ 3, 14, 5172, 3, 15, 7587, 4, 14, 6986, 4, 15, 45791, // 4,15
+ 5, -1, 6644, 5, 0, 46541, 6, -1, 4967, 6, 0, 7384, // 5, 0
+ 5, 0, 6092, 5, 1, 48322, 6, 0, 4502, 6, 1, 6620, // 5, 1
+ 5, 1, 5499, 5, 2, 50171, 6, 1, 4019, 6, 2, 5847, // 5, 2
+ 5, 2, 4872, 5, 3, 52069, 6, 2, 3522, 6, 3, 5073, // 5, 3
+ 5, 3, 4226, 5, 4, 53975, 6, 3, 3023, 6, 4, 4312, // 5, 4
+ 5, 4, 3595, 5, 5, 55798, 6, 4, 2546, 6, 5, 3597, // 5, 5
+ 5, 5, 3050, 5, 6, 57353, 6, 5, 2138, 6, 6, 2995, // 5, 6
+ 5, 6, 2713, 5, 7, 58322, 6, 6, 1884, 6, 7, 2617, // 5, 7
+ 4, 7, 1884, 4, 8, 2615, 5, 7, 2714, 5, 8, 58323, // 5, 8
+ 4, 8, 2138, 4, 9, 2993, 5, 8, 3051, 5, 9, 57354, // 5, 9
+ 4, 9, 2546, 4, 10, 3595, 5, 9, 3598, 5, 10, 55797, // 5,10
+ 4, 10, 3023, 4, 11, 4309, 5, 10, 4230, 5, 11, 53974, // 5,11
+ 4, 11, 3523, 4, 12, 5069, 5, 11, 4879, 5, 12, 52065, // 5,12
+ 4, 12, 4020, 4, 13, 5842, 5, 12, 5508, 5, 13, 50166, // 5,13
+ 4, 13, 4505, 4, 14, 6613, 5, 13, 6104, 5, 14, 48314, // 5,14
+ 4, 14, 4971, 4, 15, 7374, 5, 14, 6659, 5, 15, 46532, // 5,15
+ 6, -1, 6391, 6, 0, 47098, 7, -1, 4814, 7, 0, 7233, // 6, 0
+ 6, 0, 5809, 6, 1, 48969, 7, 0, 4327, 7, 1, 6431, // 6, 1
+ 6, 1, 5175, 6, 2, 50942, 7, 1, 3813, 7, 2, 5606, // 6, 2
+ 6, 2, 4489, 6, 3, 53012, 7, 2, 3273, 7, 3, 4762, // 6, 3
+ 6, 3, 3755, 6, 4, 55166, 7, 3, 2710, 7, 4, 3905, // 6, 4
+ 6, 4, 2993, 6, 5, 57354, 7, 4, 2138, 7, 5, 3051, // 6, 5
+ 6, 5, 2258, 6, 6, 59422, 7, 5, 1597, 7, 6, 2259, // 6, 6
+ 6, 6, 1726, 6, 7, 60905, 7, 6, 1210, 7, 7, 1695, // 6, 7
+ 5, 7, 1209, 5, 8, 1695, 6, 7, 1726, 6, 8, 60906, // 6, 8
+ 5, 8, 1597, 5, 9, 2258, 6, 8, 2259, 6, 9, 59422, // 6, 9
+ 5, 9, 2138, 5, 10, 3050, 6, 9, 2995, 6, 10, 57353, // 6,10
+ 5, 10, 2711, 5, 11, 3902, 6, 10, 3759, 6, 11, 55164, // 6,11
+ 5, 11, 3274, 5, 12, 4759, 6, 11, 4495, 6, 12, 53008, // 6,12
+ 5, 12, 3815, 5, 13, 5602, 6, 12, 5184, 6, 13, 50935, // 6,13
+ 5, 13, 4330, 5, 14, 6425, 6, 13, 5820, 6, 14, 48961, // 6,14
+ 5, 14, 4818, 5, 15, 7227, 6, 14, 6405, 6, 15, 47086, // 6,15
+ 7, -1, 6217, 7, 0, 47440, 8, -1, 4718, 8, 0, 7161, // 7, 0
+ 7, 0, 5623, 7, 1, 49358, 8, 0, 4221, 8, 1, 6334, // 7, 1
+ 7, 1, 4970, 7, 2, 51395, 8, 1, 3691, 8, 2, 5480, // 7, 2
+ 7, 2, 4254, 7, 3, 53562, 8, 2, 3126, 8, 3, 4594, // 7, 3
+ 7, 3, 3469, 7, 4, 55870, 8, 3, 2524, 8, 4, 3673, // 7, 4
+ 7, 4, 2615, 7, 5, 58324, 8, 4, 1884, 8, 5, 2713, // 7, 5
+ 7, 5, 1695, 7, 6, 60906, 8, 5, 1209, 8, 6, 1726, // 7, 6
+ 7, 6, 789, 7, 7, 63399, 8, 6, 558, 8, 7, 790, // 7, 7
+ 6, 7, 558, 6, 8, 789, 7, 7, 789, 7, 8, 63400, // 7, 8
+ 6, 8, 1210, 6, 9, 1726, 7, 8, 1695, 7, 9, 60905, // 7, 9
+ 6, 9, 1884, 6, 10, 2713, 7, 9, 2616, 7, 10, 58323, // 7,10
+ 6, 10, 2525, 6, 11, 3671, 7, 10, 3473, 7, 11, 55867, // 7,11
+ 6, 11, 3128, 6, 12, 4592, 7, 11, 4259, 7, 12, 53557, // 7,12
+ 6, 12, 3693, 6, 13, 5478, 7, 12, 4978, 7, 13, 51387, // 7,13
+ 6, 13, 4224, 6, 14, 6332, 7, 13, 5633, 7, 14, 49347, // 7,14
+ 6, 14, 4722, 6, 15, 7158, 7, 14, 6230, 7, 15, 47426, // 7,15
+ 8, 0, 47426, 8, 1, 6230, 9, 0, 7158, 9, 1, 4722, // 8, 0
+ 8, 1, 49347, 8, 2, 5633, 9, 1, 6332, 9, 2, 4224, // 8, 1
+ 8, 2, 51387, 8, 3, 4978, 9, 2, 5478, 9, 3, 3693, // 8, 2
+ 8, 3, 53557, 8, 4, 4259, 9, 3, 4592, 9, 4, 3128, // 8, 3
+ 8, 4, 55867, 8, 5, 3473, 9, 4, 3671, 9, 5, 2525, // 8, 4
+ 8, 5, 58322, 8, 6, 2616, 9, 5, 2713, 9, 6, 1885, // 8, 5
+ 8, 6, 60905, 8, 7, 1695, 9, 6, 1726, 9, 7, 1210, // 8, 6
+ 8, 7, 63399, 8, 8, 789, 9, 7, 789, 9, 8, 559, // 8, 7
+ 7, 8, 789, 7, 9, 558, 8, 8, 63399, 8, 9, 790, // 8, 8
+ 7, 9, 1726, 7, 10, 1209, 8, 9, 60906, 8, 10, 1695, // 8, 9
+ 7, 10, 2714, 7, 11, 1884, 8, 10, 58324, 8, 11, 2614, // 8,10
+ 7, 11, 3672, 7, 12, 2524, 8, 11, 55870, 8, 12, 3470, // 8,11
+ 7, 12, 4594, 7, 13, 3126, 8, 12, 53562, 8, 13, 4254, // 8,12
+ 7, 13, 5480, 7, 14, 3691, 8, 13, 51395, 8, 14, 4970, // 8,13
+ 7, 14, 6335, 7, 15, 4221, 8, 14, 49358, 8, 15, 5622, // 8,14
+ 7, 15, 7161, 7, 16, 4718, 8, 15, 47440, 8, 16, 6217, // 8,15
+ 9, 0, 47086, 9, 1, 6405, 10, 0, 7227, 10, 1, 4818, // 9, 0
+ 9, 1, 48960, 9, 2, 5820, 10, 1, 6425, 10, 2, 4331, // 9, 1
+ 9, 2, 50935, 9, 3, 5184, 10, 2, 5602, 10, 3, 3815, // 9, 2
+ 9, 3, 53008, 9, 4, 4495, 10, 3, 4759, 10, 4, 3274, // 9, 3
+ 9, 4, 55164, 9, 5, 3759, 10, 4, 3902, 10, 5, 2711, // 9, 4
+ 9, 5, 57353, 9, 6, 2995, 10, 5, 3050, 10, 6, 2138, // 9, 5
+ 9, 6, 59422, 9, 7, 2259, 10, 6, 2258, 10, 7, 1597, // 9, 6
+ 9, 7, 60906, 9, 8, 1726, 10, 7, 1695, 10, 8, 1209, // 9, 7
+ 8, 8, 1695, 8, 9, 1210, 9, 8, 60905, 9, 9, 1726, // 9, 8
+ 8, 9, 2259, 8, 10, 1597, 9, 9, 59422, 9, 10, 2258, // 9, 9
+ 8, 10, 3051, 8, 11, 2138, 9, 10, 57354, 9, 11, 2993, // 9,10
+ 8, 11, 3904, 8, 12, 2710, 9, 11, 55166, 9, 12, 3756, // 9,11
+ 8, 12, 4762, 8, 13, 3273, 9, 12, 53012, 9, 13, 4489, // 9,12
+ 8, 13, 5606, 8, 14, 3813, 9, 13, 50942, 9, 14, 5175, // 9,13
+ 8, 14, 6430, 8, 15, 4327, 9, 14, 48969, 9, 15, 5810, // 9,14
+ 8, 15, 7233, 8, 16, 4814, 9, 15, 47098, 9, 16, 6391, // 9,15
+ 10, 0, 46532, 10, 1, 6659, 11, 0, 7374, 11, 1, 4971, // 10, 0
+ 10, 1, 48314, 10, 2, 6104, 11, 1, 6613, 11, 2, 4505, // 10, 1
+ 10, 2, 50165, 10, 3, 5508, 11, 2, 5842, 11, 3, 4021, // 10, 2
+ 10, 3, 52066, 10, 4, 4879, 11, 3, 5069, 11, 4, 3522, // 10, 3
+ 10, 4, 53973, 10, 5, 4230, 11, 4, 4309, 11, 5, 3024, // 10, 4
+ 10, 5, 55798, 10, 6, 3598, 11, 5, 3595, 11, 6, 2545, // 10, 5
+ 10, 6, 57354, 10, 7, 3051, 11, 6, 2993, 11, 7, 2138, // 10, 6
+ 10, 7, 58324, 10, 8, 2714, 11, 7, 2615, 11, 8, 1883, // 10, 7
+ 9, 8, 2616, 9, 9, 1884, 10, 8, 58322, 10, 9, 2714, // 10, 8
+ 9, 9, 2995, 9, 10, 2138, 10, 9, 57353, 10, 10, 3050, // 10, 9
+ 9, 10, 3598, 9, 11, 2546, 10, 10, 55798, 10, 11, 3594, // 10,10
+ 9, 11, 4313, 9, 12, 3023, 10, 11, 53975, 10, 12, 4225, // 10,11
+ 9, 12, 5073, 9, 13, 3522, 10, 12, 52069, 10, 13, 4872, // 10,12
+ 9, 13, 5848, 9, 14, 4019, 10, 13, 50171, 10, 14, 5498, // 10,13
+ 9, 14, 6620, 9, 15, 4502, 10, 14, 48322, 10, 15, 6092, // 10,14
+ 9, 15, 7383, 9, 16, 4967, 10, 15, 46541, 10, 16, 6645, // 10,15
+ 11, 0, 45791, 11, 1, 6986, 12, 0, 7587, 12, 1, 5172, // 11, 0
+ 11, 1, 47453, 11, 2, 6472, 12, 1, 6875, 12, 2, 4736, // 11, 1
+ 11, 2, 49147, 11, 3, 5930, 12, 2, 6168, 12, 3, 4291, // 11, 2
+ 11, 3, 50843, 11, 4, 5373, 12, 3, 5474, 12, 4, 3846, // 11, 3
+ 11, 4, 52484, 11, 5, 4822, 12, 4, 4816, 12, 5, 3414, // 11, 4
+ 11, 5, 53975, 11, 6, 4313, 12, 5, 4226, 12, 6, 3022, // 11, 5
+ 11, 6, 55166, 11, 7, 3904, 12, 6, 3755, 12, 7, 2711, // 11, 6
+ 11, 7, 55870, 11, 8, 3672, 12, 7, 3469, 12, 8, 2525, // 11, 7
+ 10, 8, 3473, 10, 9, 2525, 11, 8, 55867, 11, 9, 3671, // 11, 8
+ 10, 9, 3759, 10, 10, 2711, 11, 9, 55164, 11, 10, 3902, // 11, 9
+ 10, 10, 4230, 10, 11, 3023, 11, 10, 53973, 11, 11, 4310, // 11,10
+ 10, 11, 4822, 10, 12, 3415, 11, 11, 52484, 11, 12, 4815, // 11,11
+ 10, 12, 5481, 10, 13, 3845, 11, 12, 50844, 11, 13, 5366, // 11,12
+ 10, 13, 6176, 10, 14, 4290, 11, 13, 49150, 11, 14, 5920, // 11,13
+ 10, 14, 6886, 10, 15, 4734, 11, 14, 47458, 11, 15, 6458, // 11,14
+ 10, 15, 7599, 10, 16, 5169, 11, 15, 45799, 11, 16, 6969, // 11,15
+ 12, 0, 44901, 12, 1, 7374, 13, 0, 7848, 13, 1, 5413, // 12, 0
+ 12, 1, 46427, 12, 2, 6908, 13, 1, 7191, 13, 2, 5010, // 12, 1
+ 12, 2, 47953, 12, 3, 6426, 13, 2, 6549, 13, 3, 4608, // 12, 2
+ 12, 3, 49445, 12, 4, 5943, 13, 3, 5934, 13, 4, 4214, // 12, 3
+ 12, 4, 50844, 12, 5, 5481, 13, 4, 5365, 13, 5, 3846, // 12, 4
+ 12, 5, 52069, 12, 6, 5073, 13, 5, 4872, 13, 6, 3522, // 12, 5
+ 12, 6, 53012, 12, 7, 4762, 13, 6, 4489, 13, 7, 3273, // 12, 6
+ 12, 7, 53562, 12, 8, 4594, 13, 7, 4254, 13, 8, 3126, // 12, 7
+ 11, 8, 4259, 11, 9, 3128, 12, 8, 53557, 12, 9, 4592, // 12, 8
+ 11, 9, 4495, 11, 10, 3274, 12, 9, 53008, 12, 10, 4759, // 12, 9
+ 11, 10, 4879, 11, 11, 3523, 12, 10, 52066, 12, 11, 5068, // 12,10
+ 11, 11, 5373, 11, 12, 3846, 12, 11, 50843, 12, 12, 5474, // 12,11
+ 11, 12, 5943, 11, 13, 4214, 12, 12, 49445, 12, 13, 5934, // 12,12
+ 11, 13, 6560, 11, 14, 4607, 12, 13, 47955, 12, 14, 6414, // 12,13
+ 11, 14, 7204, 11, 15, 5009, 12, 14, 46430, 12, 15, 6893, // 12,14
+ 11, 15, 7863, 11, 16, 5410, 12, 15, 44907, 12, 16, 7356, // 12,15
+ 13, 0, 43900, 13, 1, 7812, 14, 0, 8141, 14, 1, 5683, // 13, 0
+ 13, 1, 45286, 13, 2, 7395, 14, 1, 7539, 14, 2, 5316, // 13, 1
+ 13, 2, 46650, 13, 3, 6973, 14, 2, 6959, 14, 3, 4954, // 13, 2
+ 13, 3, 47955, 13, 4, 6560, 14, 3, 6414, 14, 4, 4607, // 13, 3
+ 13, 4, 49150, 13, 5, 6176, 14, 4, 5920, 14, 5, 4290, // 13, 4
+ 13, 5, 50171, 13, 6, 5848, 14, 5, 5499, 14, 6, 4018, // 13, 5
+ 13, 6, 50942, 13, 7, 5606, 14, 6, 5175, 14, 7, 3813, // 13, 6
+ 13, 7, 51395, 13, 8, 5480, 14, 7, 4970, 14, 8, 3691, // 13, 7
+ 12, 8, 4978, 12, 9, 3693, 13, 8, 51387, 13, 9, 5478, // 13, 8
+ 12, 9, 5184, 12, 10, 3815, 13, 9, 50935, 13, 10, 5602, // 13, 9
+ 12, 10, 5508, 12, 11, 4020, 13, 10, 50165, 13, 11, 5843, // 13,10
+ 12, 11, 5930, 12, 12, 4291, 13, 11, 49147, 13, 12, 6168, // 13,11
+ 12, 12, 6426, 12, 13, 4608, 13, 12, 47953, 13, 13, 6549, // 13,12
+ 12, 13, 6973, 12, 14, 4954, 13, 13, 46650, 13, 14, 6959, // 13,13
+ 12, 14, 7555, 12, 15, 5315, 13, 14, 45288, 13, 15, 7378, // 13,14
+ 12, 15, 8159, 12, 16, 5682, 13, 15, 43904, 13, 16, 7791, // 13,15
+ 14, 0, 42821, 14, 1, 8288, 15, 0, 8452, 15, 1, 5975, // 14, 0
+ 14, 1, 44074, 14, 2, 7921, 15, 1, 7901, 15, 2, 5640, // 14, 1
+ 14, 2, 45288, 14, 3, 7555, 15, 2, 7378, 15, 3, 5315, // 14, 2
+ 14, 3, 46430, 14, 4, 7204, 15, 3, 6892, 15, 4, 5010, // 14, 3
+ 14, 4, 47458, 14, 5, 6886, 15, 4, 6458, 15, 5, 4734, // 14, 4
+ 14, 5, 48322, 14, 6, 6620, 15, 5, 6092, 15, 6, 4502, // 14, 5
+ 14, 6, 48969, 14, 7, 6430, 15, 6, 5809, 15, 7, 4328, // 14, 6
+ 14, 7, 49358, 14, 8, 6335, 15, 7, 5623, 15, 8, 4220, // 14, 7
+ 13, 8, 5633, 13, 9, 4224, 14, 8, 49347, 14, 9, 6332, // 14, 8
+ 13, 9, 5820, 13, 10, 4330, 14, 9, 48960, 14, 10, 6426, // 14, 9
+ 13, 10, 6104, 13, 11, 4505, 14, 10, 48314, 14, 11, 6613, // 14,10
+ 13, 11, 6472, 13, 12, 4736, 14, 11, 47453, 14, 12, 6875, // 14,11
+ 13, 12, 6908, 13, 13, 5011, 14, 12, 46427, 14, 13, 7190, // 14,12
+ 13, 13, 7395, 13, 14, 5316, 14, 13, 45286, 14, 14, 7539, // 14,13
+ 13, 14, 7921, 13, 15, 5640, 14, 14, 44074, 14, 15, 7901, // 14,14
+ 13, 15, 8474, 13, 16, 5974, 14, 15, 42823, 14, 16, 8265, // 14,15
+ 15, 0, 41693, 15, 1, 8795, 16, 0, 8769, 16, 1, 6279, // 15, 0
+ 15, 1, 42823, 15, 2, 8474, 16, 1, 8265, 16, 2, 5974, // 15, 1
+ 15, 2, 43904, 15, 3, 8159, 16, 2, 7791, 16, 3, 5682, // 15, 2
+ 15, 3, 44907, 15, 4, 7863, 16, 3, 7356, 16, 4, 5410, // 15, 3
+ 15, 4, 45799, 15, 5, 7599, 16, 4, 6970, 16, 5, 5168, // 15, 4
+ 15, 5, 46541, 15, 6, 7383, 16, 5, 6644, 16, 6, 4968, // 15, 5
+ 15, 6, 47098, 15, 7, 7233, 16, 6, 6391, 16, 7, 4814, // 15, 6
+ 15, 7, 47440, 15, 8, 7161, 16, 7, 6217, 16, 8, 4718, // 15, 7
+ 14, 8, 6230, 14, 9, 4722, 15, 8, 47426, 15, 9, 7158, // 15, 8
+ 14, 9, 6405, 14, 10, 4818, 15, 9, 47086, 15, 10, 7227, // 15, 9
+ 14, 10, 6659, 14, 11, 4971, 15, 10, 46532, 15, 11, 7374, // 15,10
+ 14, 11, 6986, 14, 12, 5172, 15, 11, 45791, 15, 12, 7587, // 15,11
+ 14, 12, 7374, 14, 13, 5413, 15, 12, 44901, 15, 13, 7848, // 15,12
+ 14, 13, 7812, 14, 14, 5684, 15, 13, 43900, 15, 14, 8140, // 15,13
+ 14, 14, 8288, 14, 15, 5975, 15, 14, 42821, 15, 15, 8452, // 15,14
+ 14, 15, 8795, 14, 16, 6280, 15, 15, 41693, 15, 16, 8768, // 15,15
+ // angle of 1.5 degrees
+ 0, -1, 11440, 0, 0, 34212, 1, -1, 8358, 1, 0, 11526, // 0, 0
+ 0, 0, 11192, 0, 1, 35502, 1, 0, 7987, 1, 1, 10855, // 0, 1
+ 0, 1, 10930, 0, 2, 36756, 1, 1, 7626, 1, 2, 10224, // 0, 2
+ 0, 2, 10670, 0, 3, 37939, 1, 2, 7285, 1, 3, 9642, // 0, 3
+ 0, 3, 10430, 0, 4, 39009, 1, 3, 6975, 1, 4, 9122, // 0, 4
+ 0, 4, 10232, 0, 5, 39918, 1, 4, 6710, 1, 5, 8676, // 0, 5
+ 0, 5, 10100, 0, 6, 40618, 1, 5, 6502, 1, 6, 8316, // 0, 6
+ 0, 6, 10052, 0, 7, 41072, 1, 6, 6360, 1, 7, 8052, // 0, 7
+ -1, 7, 6346, -1, 8, 8018, 0, 7, 10066, 0, 8, 41106, // 0, 8
+ -1, 8, 6489, -1, 9, 8278, 0, 8, 10123, 0, 9, 40646, // 0, 9
+ -1, 9, 6699, -1, 10, 8632, 0, 9, 10265, 0, 10, 39940, // 0,10
+ -1, 10, 6965, -1, 11, 9072, 0, 10, 10473, 0, 11, 39026, // 0,11
+ -1, 11, 7276, -1, 12, 9585, 0, 11, 10723, 0, 12, 37952, // 0,12
+ -1, 12, 7620, -1, 13, 10158, 0, 12, 10994, 0, 13, 36764, // 0,13
+ -1, 13, 7983, -1, 14, 10780, 0, 13, 11267, 0, 14, 35506, // 0,14
+ -1, 14, 8358, -1, 15, 11440, 0, 14, 11526, 0, 15, 34212, // 0,15
+ 1, -1, 10780, 1, 0, 35506, 2, -1, 7983, 2, 0, 11267, // 1, 0
+ 1, 0, 10467, 1, 1, 36959, 2, 0, 7579, 2, 1, 10531, // 1, 1
+ 1, 1, 10133, 1, 2, 38390, 2, 1, 7179, 2, 2, 9834, // 1, 2
+ 1, 2, 9796, 1, 3, 39759, 2, 2, 6797, 2, 3, 9184, // 1, 3
+ 1, 3, 9478, 1, 4, 41013, 2, 3, 6447, 2, 4, 8598, // 1, 4
+ 1, 4, 9206, 1, 5, 42087, 2, 4, 6145, 2, 5, 8098, // 1, 5
+ 1, 5, 9014, 1, 6, 42913, 2, 5, 5910, 2, 6, 7699, // 1, 6
+ 1, 6, 8929, 1, 7, 43433, 2, 6, 5756, 2, 7, 7418, // 1, 7
+ 0, 7, 5745, 0, 8, 7390, 1, 7, 8939, 1, 8, 43462, // 1, 8
+ 0, 8, 5900, 0, 9, 7667, 1, 8, 9032, 1, 9, 42937, // 1, 9
+ 0, 9, 6137, 0, 10, 8061, 1, 9, 9233, 1, 10, 42105, // 1,10
+ 0, 10, 6440, 0, 11, 8557, 1, 10, 9513, 1, 11, 41026, // 1,11
+ 0, 11, 6792, 0, 12, 9135, 1, 11, 9841, 1, 12, 39768, // 1,12
+ 0, 12, 7177, 0, 13, 9777, 1, 12, 10188, 1, 13, 38394, // 1,13
+ 0, 13, 7579, 0, 14, 10467, 1, 13, 10532, 1, 14, 36958, // 1,14
+ 0, 14, 7987, 0, 15, 11192, 1, 14, 10855, 1, 15, 35502, // 1,15
+ 2, -1, 10158, 2, 0, 36764, 3, -1, 7620, 3, 0, 10994, // 2, 0
+ 2, 0, 9777, 2, 1, 38394, 3, 0, 7177, 3, 1, 10188, // 2, 1
+ 2, 1, 9366, 2, 2, 40025, 3, 1, 6732, 3, 2, 9413, // 2, 2
+ 2, 2, 8941, 2, 3, 41614, 3, 2, 6299, 3, 3, 8682, // 2, 3
+ 2, 3, 8530, 2, 4, 43096, 3, 3, 5895, 3, 4, 8015, // 2, 4
+ 2, 4, 8167, 2, 5, 44386, 3, 4, 5543, 3, 5, 7440, // 2, 5
+ 2, 5, 7899, 2, 6, 45383, 3, 5, 5268, 3, 6, 6986, // 2, 6
+ 2, 6, 7766, 2, 7, 45995, 3, 6, 5095, 3, 7, 6680, // 2, 7
+ 1, 7, 5087, 1, 8, 6658, 2, 7, 7773, 2, 8, 46018, // 2, 8
+ 1, 8, 5261, 1, 9, 6961, 2, 8, 7913, 2, 9, 45401, // 2, 9
+ 1, 9, 5537, 1, 10, 7411, 2, 9, 8189, 2, 10, 44399, // 2,10
+ 1, 10, 5891, 1, 11, 7981, 2, 10, 8559, 2, 11, 43105, // 2,11
+ 1, 11, 6297, 1, 12, 8641, 2, 11, 8979, 2, 12, 41619, // 2,12
+ 1, 12, 6732, 1, 13, 9366, 2, 12, 9413, 2, 13, 40025, // 2,13
+ 1, 13, 7179, 1, 14, 10133, 2, 13, 9834, 2, 14, 38390, // 2,14
+ 1, 14, 7626, 1, 15, 10930, 2, 14, 10224, 2, 15, 36756, // 2,15
+ 3, -1, 9585, 3, 0, 37951, 4, -1, 7276, 4, 0, 10724, // 3, 0
+ 3, 0, 9135, 3, 1, 39767, 4, 0, 6792, 4, 1, 9842, // 3, 1
+ 3, 1, 8641, 3, 2, 41618, 4, 1, 6297, 4, 2, 8980, // 3, 2
+ 3, 2, 8120, 3, 3, 43461, 4, 2, 5804, 4, 3, 8151, // 3, 3
+ 3, 3, 7598, 3, 4, 45224, 4, 3, 5331, 4, 4, 7383, // 3, 4
+ 3, 4, 7121, 3, 5, 46798, 4, 4, 4909, 4, 5, 6708, // 3, 5
+ 3, 5, 6750, 3, 6, 48037, 4, 5, 4576, 4, 6, 6173, // 3, 6
+ 3, 6, 6552, 3, 7, 48785, 4, 6, 4372, 4, 7, 5827, // 3, 7
+ 2, 7, 4366, 2, 8, 5811, 3, 7, 6558, 3, 8, 48801, // 3, 8
+ 2, 8, 4572, 2, 9, 6154, 3, 8, 6761, 3, 9, 48049, // 3, 9
+ 2, 9, 4906, 2, 10, 6685, 3, 9, 7138, 3, 10, 46807, // 3,10
+ 2, 10, 5330, 2, 11, 7356, 3, 10, 7622, 3, 11, 45228, // 3,11
+ 2, 11, 5804, 2, 12, 8120, 3, 11, 8151, 3, 12, 43461, // 3,12
+ 2, 12, 6299, 2, 13, 8941, 3, 12, 8681, 3, 13, 41615, // 3,13
+ 2, 13, 6797, 2, 14, 9796, 3, 13, 9184, 3, 14, 39759, // 3,14
+ 2, 14, 7285, 2, 15, 10670, 3, 14, 9642, 3, 15, 37939, // 3,15
+ 4, -1, 9072, 4, 0, 39026, 5, -1, 6965, 5, 0, 10473, // 4, 0
+ 4, 0, 8557, 4, 1, 41026, 5, 0, 6440, 5, 1, 9513, // 4, 1
+ 4, 1, 7981, 4, 2, 43105, 5, 1, 5891, 5, 2, 8559, // 4, 2
+ 4, 2, 7356, 4, 3, 45229, 5, 2, 5330, 5, 3, 7621, // 4, 3
+ 4, 3, 6708, 4, 4, 47328, 5, 3, 4774, 5, 4, 6726, // 4, 4
+ 4, 4, 6086, 4, 5, 49275, 5, 4, 4258, 5, 5, 5917, // 4, 5
+ 4, 5, 5573, 4, 6, 50865, 5, 5, 3837, 5, 6, 5261, // 4, 6
+ 4, 6, 5280, 4, 7, 51832, 5, 6, 3579, 5, 7, 4845, // 4, 7
+ 3, 7, 3575, 3, 8, 4835, 4, 7, 5283, 4, 8, 51843, // 4, 8
+ 3, 8, 3834, 3, 9, 5248, 4, 8, 5581, 4, 9, 50873, // 4, 9
+ 3, 9, 4257, 3, 10, 5901, 4, 9, 6099, 4, 10, 49279, // 4,10
+ 3, 10, 4774, 3, 11, 6708, 4, 10, 6727, 4, 11, 47327, // 4,11
+ 3, 11, 5331, 3, 12, 7598, 4, 11, 7382, 4, 12, 45225, // 4,12
+ 3, 12, 5895, 3, 13, 8530, 4, 12, 8015, 4, 13, 43096, // 4,13
+ 3, 13, 6447, 3, 14, 9478, 4, 13, 8599, 4, 14, 41012, // 4,14
+ 3, 14, 6975, 3, 15, 10430, 4, 14, 9122, 4, 15, 39009, // 4,15
+ 5, -1, 8632, 5, 0, 39940, 6, -1, 6699, 6, 0, 10265, // 5, 0
+ 5, 0, 8061, 5, 1, 42105, 6, 0, 6137, 6, 1, 9233, // 5, 1
+ 5, 1, 7411, 5, 2, 44399, 6, 1, 5537, 6, 2, 8189, // 5, 2
+ 5, 2, 6685, 5, 3, 46806, 6, 2, 4906, 6, 3, 7139, // 5, 3
+ 5, 3, 5901, 5, 4, 49279, 6, 3, 4257, 6, 4, 6099, // 5, 4
+ 5, 4, 5103, 5, 5, 51700, 6, 4, 3621, 6, 5, 5112, // 5, 5
+ 5, 5, 4388, 5, 6, 53813, 6, 5, 3065, 6, 6, 4270, // 5, 6
+ 5, 6, 3938, 5, 7, 55162, 6, 6, 2710, 6, 7, 3726, // 5, 7
+ 4, 7, 2708, 4, 8, 3720, 5, 7, 3940, 5, 8, 55168, // 5, 8
+ 4, 8, 3064, 4, 9, 4262, 5, 8, 4394, 5, 9, 53816, // 5, 9
+ 4, 9, 3621, 4, 10, 5103, 5, 9, 5113, 5, 10, 51699, // 5,10
+ 4, 10, 4258, 4, 11, 6086, 5, 10, 5917, 5, 11, 49275, // 5,11
+ 4, 11, 4909, 4, 12, 7121, 5, 11, 6707, 5, 12, 46799, // 5,12
+ 4, 12, 5543, 4, 13, 8167, 5, 12, 7440, 5, 13, 44386, // 5,13
+ 4, 13, 6145, 4, 14, 9206, 5, 13, 8098, 5, 14, 42087, // 5,14
+ 4, 14, 6710, 4, 15, 10232, 5, 14, 8676, 5, 15, 39918, // 5,15
+ 6, -1, 8278, 6, 0, 40646, 7, -1, 6489, 7, 0, 10123, // 6, 0
+ 6, 0, 7667, 6, 1, 42936, 7, 0, 5900, 7, 1, 9033, // 6, 1
+ 6, 1, 6961, 6, 2, 45401, 7, 1, 5261, 7, 2, 7913, // 6, 2
+ 6, 2, 6154, 6, 3, 48049, 7, 2, 4572, 7, 3, 6761, // 6, 3
+ 6, 3, 5248, 6, 4, 50873, 7, 3, 3834, 7, 4, 5581, // 6, 4
+ 6, 4, 4262, 6, 5, 53816, 7, 4, 3064, 7, 5, 4394, // 6, 5
+ 6, 5, 3271, 6, 6, 56673, 7, 5, 2316, 7, 6, 3276, // 6, 6
+ 6, 6, 2532, 6, 7, 58773, 7, 6, 1767, 7, 7, 2464, // 6, 7
+ 5, 7, 1766, 5, 8, 2462, 6, 7, 2533, 6, 8, 58775, // 6, 8
+ 5, 8, 2316, 5, 9, 3271, 6, 8, 3275, 6, 9, 56674, // 6, 9
+ 5, 9, 3065, 5, 10, 4388, 6, 9, 4269, 6, 10, 53814, // 6,10
+ 5, 10, 3837, 5, 11, 5573, 6, 10, 5261, 6, 11, 50865, // 6,11
+ 5, 11, 4576, 5, 12, 6750, 6, 11, 6173, 6, 12, 48037, // 6,12
+ 5, 12, 5268, 5, 13, 7899, 6, 12, 6986, 6, 13, 45383, // 6,13
+ 5, 13, 5910, 5, 14, 9014, 6, 13, 7699, 6, 14, 42913, // 6,14
+ 5, 14, 6502, 5, 15, 10100, 6, 14, 8316, 6, 15, 40618, // 6,15
+ 7, -1, 8018, 7, 0, 41106, 8, -1, 6346, 8, 0, 10066, // 7, 0
+ 7, 0, 7390, 7, 1, 43461, 8, 0, 5745, 8, 1, 8940, // 7, 1
+ 7, 1, 6658, 7, 2, 46017, 8, 1, 5087, 8, 2, 7774, // 7, 2
+ 7, 2, 5811, 7, 3, 48801, 8, 2, 4366, 8, 3, 6558, // 7, 3
+ 7, 3, 4835, 7, 4, 51842, 8, 3, 3575, 8, 4, 5284, // 7, 4
+ 7, 4, 3720, 7, 5, 55168, 8, 4, 2708, 8, 5, 3940, // 7, 5
+ 7, 5, 2462, 7, 6, 58775, 8, 5, 1766, 8, 6, 2533, // 7, 6
+ 7, 6, 1170, 7, 7, 62369, 8, 6, 827, 8, 7, 1170, // 7, 7
+ 6, 7, 827, 6, 8, 1170, 7, 7, 1170, 7, 8, 62369, // 7, 8
+ 6, 8, 1767, 6, 9, 2532, 7, 8, 2464, 7, 9, 58773, // 7, 9
+ 6, 9, 2710, 6, 10, 3938, 7, 9, 3726, 7, 10, 55162, // 7,10
+ 6, 10, 3579, 6, 11, 5280, 7, 10, 4846, 7, 11, 51831, // 7,11
+ 6, 11, 4372, 6, 12, 6552, 7, 11, 5827, 7, 12, 48785, // 7,12
+ 6, 12, 5095, 6, 13, 7766, 7, 12, 6680, 7, 13, 45995, // 7,13
+ 6, 13, 5756, 6, 14, 8929, 7, 13, 7418, 7, 14, 43433, // 7,14
+ 6, 14, 6360, 6, 15, 10052, 7, 14, 8052, 7, 15, 41072, // 7,15
+ 8, 0, 41072, 8, 1, 8052, 9, 0, 10052, 9, 1, 6360, // 8, 0
+ 8, 1, 43433, 8, 2, 7418, 9, 1, 8929, 9, 2, 5756, // 8, 1
+ 8, 2, 45995, 8, 3, 6680, 9, 2, 7766, 9, 3, 5095, // 8, 2
+ 8, 3, 48785, 8, 4, 5827, 9, 3, 6552, 9, 4, 4372, // 8, 3
+ 8, 4, 51832, 8, 5, 4846, 9, 4, 5280, 9, 5, 3578, // 8, 4
+ 8, 5, 55162, 8, 6, 3726, 9, 5, 3938, 9, 6, 2710, // 8, 5
+ 8, 6, 58773, 8, 7, 2464, 9, 6, 2532, 9, 7, 1767, // 8, 6
+ 8, 7, 62369, 8, 8, 1170, 9, 7, 1170, 9, 8, 827, // 8, 7
+ 7, 8, 1170, 7, 9, 827, 8, 8, 62369, 8, 9, 1170, // 8, 8
+ 7, 9, 2533, 7, 10, 1766, 8, 9, 58775, 8, 10, 2462, // 8, 9
+ 7, 10, 3940, 7, 11, 2708, 8, 10, 55168, 8, 11, 3720, // 8,10
+ 7, 11, 5283, 7, 12, 3575, 8, 11, 51842, 8, 12, 4836, // 8,11
+ 7, 12, 6558, 7, 13, 4366, 8, 12, 48801, 8, 13, 5811, // 8,12
+ 7, 13, 7773, 7, 14, 5087, 8, 13, 46017, 8, 14, 6659, // 8,13
+ 7, 14, 8939, 7, 15, 5745, 8, 14, 43461, 8, 15, 7391, // 8,14
+ 7, 15, 10066, 7, 16, 6346, 8, 15, 41106, 8, 16, 8018, // 8,15
+ 9, 0, 40618, 9, 1, 8316, 10, 0, 10100, 10, 1, 6502, // 9, 0
+ 9, 1, 42913, 9, 2, 7699, 10, 1, 9014, 10, 2, 5910, // 9, 1
+ 9, 2, 45383, 9, 3, 6986, 10, 2, 7899, 10, 3, 5268, // 9, 2
+ 9, 3, 48037, 9, 4, 6173, 10, 3, 6750, 10, 4, 4576, // 9, 3
+ 9, 4, 50865, 9, 5, 5261, 10, 4, 5573, 10, 5, 3837, // 9, 4
+ 9, 5, 53813, 9, 6, 4269, 10, 5, 4388, 10, 6, 3066, // 9, 5
+ 9, 6, 56673, 9, 7, 3275, 10, 6, 3271, 10, 7, 2317, // 9, 6
+ 9, 7, 58775, 9, 8, 2533, 10, 7, 2462, 10, 8, 1766, // 9, 7
+ 8, 8, 2464, 8, 9, 1767, 9, 8, 58773, 9, 9, 2532, // 9, 8
+ 8, 9, 3275, 8, 10, 2316, 9, 9, 56673, 9, 10, 3272, // 9, 9
+ 8, 10, 4394, 8, 11, 3064, 9, 10, 53816, 9, 11, 4262, // 9,10
+ 8, 11, 5581, 8, 12, 3834, 9, 11, 50873, 9, 12, 5248, // 9,11
+ 8, 12, 6761, 8, 13, 4572, 9, 12, 48049, 9, 13, 6154, // 9,12
+ 8, 13, 7913, 8, 14, 5261, 9, 13, 45401, 9, 14, 6961, // 9,13
+ 8, 14, 9032, 8, 15, 5900, 9, 14, 42936, 9, 15, 7668, // 9,14
+ 8, 15, 10123, 8, 16, 6489, 9, 15, 40646, 9, 16, 8278, // 9,15
+ 10, 0, 39918, 10, 1, 8676, 11, 0, 10232, 11, 1, 6710, // 10, 0
+ 10, 1, 42087, 10, 2, 8098, 11, 1, 9206, 11, 2, 6145, // 10, 1
+ 10, 2, 44386, 10, 3, 7440, 11, 2, 8167, 11, 3, 5543, // 10, 2
+ 10, 3, 46798, 10, 4, 6707, 11, 3, 7121, 11, 4, 4910, // 10, 3
+ 10, 4, 49275, 10, 5, 5917, 11, 4, 6086, 11, 5, 4258, // 10, 4
+ 10, 5, 51700, 10, 6, 5113, 11, 5, 5103, 11, 6, 3620, // 10, 5
+ 10, 6, 53816, 10, 7, 4394, 11, 6, 4262, 11, 7, 3064, // 10, 6
+ 10, 7, 55168, 10, 8, 3940, 11, 7, 3720, 11, 8, 2708, // 10, 7
+ 9, 8, 3726, 9, 9, 2710, 10, 8, 55162, 10, 9, 3938, // 10, 8
+ 9, 9, 4269, 9, 10, 3065, 10, 9, 53813, 10, 10, 4389, // 10, 9
+ 9, 10, 5113, 9, 11, 3621, 10, 10, 51700, 10, 11, 5102, // 10,10
+ 9, 11, 6099, 9, 12, 4257, 10, 11, 49279, 10, 12, 5901, // 10,11
+ 9, 12, 7138, 9, 13, 4906, 10, 12, 46806, 10, 13, 6686, // 10,12
+ 9, 13, 8189, 9, 14, 5537, 10, 13, 44399, 10, 14, 7411, // 10,13
+ 9, 14, 9233, 9, 15, 6137, 10, 14, 42105, 10, 15, 8061, // 10,14
+ 9, 15, 10265, 9, 16, 6699, 10, 15, 39940, 10, 16, 8632, // 10,15
+ 11, 0, 39009, 11, 1, 9122, 12, 0, 10430, 12, 1, 6975, // 11, 0
+ 11, 1, 41013, 11, 2, 8599, 12, 1, 9478, 12, 2, 6446, // 11, 1
+ 11, 2, 43096, 11, 3, 8015, 12, 2, 8530, 12, 3, 5895, // 11, 2
+ 11, 3, 45224, 11, 4, 7382, 12, 3, 7598, 12, 4, 5332, // 11, 3
+ 11, 4, 47328, 11, 5, 6727, 12, 4, 6708, 12, 5, 4773, // 11, 4
+ 11, 5, 49279, 11, 6, 6099, 12, 5, 5901, 12, 6, 4257, // 11, 5
+ 11, 6, 50873, 11, 7, 5581, 12, 6, 5248, 12, 7, 3834, // 11, 6
+ 11, 7, 51842, 11, 8, 5283, 12, 7, 4835, 12, 8, 3576, // 11, 7
+ 10, 8, 4846, 10, 9, 3579, 11, 8, 51832, 11, 9, 5279, // 11, 8
+ 10, 9, 5261, 10, 10, 3837, 11, 9, 50865, 11, 10, 5573, // 11, 9
+ 10, 10, 5917, 10, 11, 4258, 11, 10, 49275, 11, 11, 6086, // 11,10
+ 10, 11, 6727, 10, 12, 4774, 11, 11, 47328, 11, 12, 6707, // 11,11
+ 10, 12, 7622, 10, 13, 5330, 11, 12, 45229, 11, 13, 7355, // 11,12
+ 10, 13, 8559, 10, 14, 5891, 11, 13, 43105, 11, 14, 7981, // 11,13
+ 10, 14, 9513, 10, 15, 6440, 11, 14, 41026, 11, 15, 8557, // 11,14
+ 10, 15, 10473, 10, 16, 6965, 11, 15, 39026, 11, 16, 9072, // 11,15
+ 12, 0, 37939, 12, 1, 9642, 13, 0, 10670, 13, 1, 7285, // 12, 0
+ 12, 1, 39759, 12, 2, 9184, 13, 1, 9796, 13, 2, 6797, // 12, 1
+ 12, 2, 41614, 12, 3, 8681, 13, 2, 8941, 13, 3, 6300, // 12, 2
+ 12, 3, 43461, 12, 4, 8151, 13, 3, 8120, 13, 4, 5804, // 12, 3
+ 12, 4, 45229, 12, 5, 7622, 13, 4, 7356, 13, 5, 5329, // 12, 4
+ 12, 5, 46806, 12, 6, 7138, 13, 5, 6685, 13, 6, 4907, // 12, 5
+ 12, 6, 48049, 12, 7, 6761, 13, 6, 6154, 13, 7, 4572, // 12, 6
+ 12, 7, 48801, 12, 8, 6558, 13, 7, 5811, 13, 8, 4366, // 12, 7
+ 11, 8, 5827, 11, 9, 4372, 12, 8, 48785, 12, 9, 6552, // 12, 8
+ 11, 9, 6173, 11, 10, 4576, 12, 9, 48037, 12, 10, 6750, // 12, 9
+ 11, 10, 6707, 11, 11, 4909, 12, 10, 46798, 12, 11, 7122, // 12,10
+ 11, 11, 7382, 11, 12, 5331, 12, 11, 45224, 12, 12, 7599, // 12,11
+ 11, 12, 8151, 11, 13, 5804, 12, 12, 43461, 12, 13, 8120, // 12,12
+ 11, 13, 8979, 11, 14, 6297, 12, 13, 41618, 12, 14, 8642, // 12,13
+ 11, 14, 9841, 11, 15, 6792, 12, 14, 39767, 12, 15, 9136, // 12,14
+ 11, 15, 10723, 11, 16, 7276, 12, 15, 37951, 12, 16, 9586, // 12,15
+ 13, 0, 36756, 13, 1, 10224, 14, 0, 10930, 14, 1, 7626, // 13, 0
+ 13, 1, 38390, 13, 2, 9834, 14, 1, 10133, 14, 2, 7179, // 13, 1
+ 13, 2, 40025, 13, 3, 9413, 14, 2, 9366, 14, 3, 6732, // 13, 2
+ 13, 3, 41618, 13, 4, 8979, 14, 3, 8641, 14, 4, 6298, // 13, 3
+ 13, 4, 43105, 13, 5, 8559, 14, 4, 7981, 14, 5, 5891, // 13, 4
+ 13, 5, 44399, 13, 6, 8189, 14, 5, 7411, 14, 6, 5537, // 13, 5
+ 13, 6, 45401, 13, 7, 7913, 14, 6, 6961, 14, 7, 5261, // 13, 6
+ 13, 7, 46017, 13, 8, 7773, 14, 7, 6658, 14, 8, 5088, // 13, 7
+ 12, 8, 6680, 12, 9, 5095, 13, 8, 45995, 13, 9, 7766, // 13, 8
+ 12, 9, 6986, 12, 10, 5268, 13, 9, 45383, 13, 10, 7899, // 13, 9
+ 12, 10, 7440, 12, 11, 5543, 13, 10, 44386, 13, 11, 8167, // 13,10
+ 12, 11, 8015, 12, 12, 5895, 13, 11, 43096, 13, 12, 8530, // 13,11
+ 12, 12, 8681, 12, 13, 6299, 13, 12, 41614, 13, 13, 8942, // 13,12
+ 12, 13, 9413, 12, 14, 6732, 13, 13, 40025, 13, 14, 9366, // 13,13
+ 12, 14, 10188, 12, 15, 7177, 13, 14, 38394, 13, 15, 9777, // 13,14
+ 12, 15, 10994, 12, 16, 7620, 13, 15, 36764, 13, 16, 10158, // 13,15
+ 14, 0, 35502, 14, 1, 10855, 15, 0, 11192, 15, 1, 7987, // 14, 0
+ 14, 1, 36959, 14, 2, 10532, 15, 1, 10467, 15, 2, 7578, // 14, 1
+ 14, 2, 38394, 14, 3, 10188, 15, 2, 9777, 15, 3, 7177, // 14, 2
+ 14, 3, 39767, 14, 4, 9841, 15, 3, 9135, 15, 4, 6793, // 14, 3
+ 14, 4, 41026, 14, 5, 9513, 15, 4, 8557, 15, 5, 6440, // 14, 4
+ 14, 5, 42105, 14, 6, 9233, 15, 5, 8061, 15, 6, 6137, // 14, 5
+ 14, 6, 42936, 14, 7, 9032, 15, 6, 7667, 15, 7, 5901, // 14, 6
+ 14, 7, 43461, 14, 8, 8939, 15, 7, 7390, 15, 8, 5746, // 14, 7
+ 13, 8, 7418, 13, 9, 5756, 14, 8, 43433, 14, 9, 8929, // 14, 8
+ 13, 9, 7699, 13, 10, 5910, 14, 9, 42913, 14, 10, 9014, // 14, 9
+ 13, 10, 8098, 13, 11, 6145, 14, 10, 42087, 14, 11, 9206, // 14,10
+ 13, 11, 8599, 13, 12, 6447, 14, 11, 41013, 14, 12, 9477, // 14,11
+ 13, 12, 9184, 13, 13, 6797, 14, 12, 39759, 14, 13, 9796, // 14,12
+ 13, 13, 9834, 13, 14, 7179, 14, 13, 38390, 14, 14, 10133, // 14,13
+ 13, 14, 10532, 13, 15, 7579, 14, 14, 36959, 14, 15, 10466, // 14,14
+ 13, 15, 11267, 13, 16, 7983, 14, 15, 35506, 14, 16, 10780, // 14,15
+ 15, 0, 34212, 15, 1, 11526, 16, 0, 11440, 16, 1, 8358, // 15, 0
+ 15, 1, 35506, 15, 2, 11267, 16, 1, 10780, 16, 2, 7983, // 15, 1
+ 15, 2, 36764, 15, 3, 10994, 16, 2, 10158, 16, 3, 7620, // 15, 2
+ 15, 3, 37951, 15, 4, 10723, 16, 3, 9585, 16, 4, 7277, // 15, 3
+ 15, 4, 39026, 15, 5, 10473, 16, 4, 9072, 16, 5, 6965, // 15, 4
+ 15, 5, 39940, 15, 6, 10265, 16, 5, 8632, 16, 6, 6699, // 15, 5
+ 15, 6, 40646, 15, 7, 10123, 16, 6, 8278, 16, 7, 6489, // 15, 6
+ 15, 7, 41106, 15, 8, 10066, 16, 7, 8018, 16, 8, 6346, // 15, 7
+ 14, 8, 8052, 14, 9, 6360, 15, 8, 41072, 15, 9, 10052, // 15, 8
+ 14, 9, 8316, 14, 10, 6502, 15, 9, 40618, 15, 10, 10100, // 15, 9
+ 14, 10, 8676, 14, 11, 6710, 15, 10, 39918, 15, 11, 10232, // 15,10
+ 14, 11, 9122, 14, 12, 6975, 15, 11, 39009, 15, 12, 10430, // 15,11
+ 14, 12, 9642, 14, 13, 7285, 15, 12, 37939, 15, 13, 10670, // 15,12
+ 14, 13, 10224, 14, 14, 7626, 15, 13, 36756, 15, 14, 10930, // 15,13
+ 14, 14, 10855, 14, 15, 7987, 15, 14, 35502, 15, 15, 11192, // 15,14
+ 14, 15, 11526, 14, 16, 8358, 15, 15, 34212, 15, 16, 11440, // 15,15
+ // angle of 2.0 degrees
+ 0, -1, 13368, 0, 0, 28495, 1, -1, 10104, 1, 0, 13569, // 0, 0
+ 0, 0, 13291, 0, 1, 29828, 1, 0, 9671, 1, 1, 12746, // 0, 1
+ 0, 1, 13176, 0, 2, 31138, 1, 1, 9245, 1, 2, 11977, // 0, 2
+ 0, 2, 13038, 0, 3, 32391, 1, 2, 8838, 1, 3, 11269, // 0, 3
+ 0, 3, 12899, 0, 4, 33539, 1, 3, 8463, 1, 4, 10635, // 0, 4
+ 0, 4, 12783, 0, 5, 34532, 1, 4, 8135, 1, 5, 10086, // 0, 5
+ 0, 5, 12717, 0, 6, 35315, 1, 5, 7868, 1, 6, 9636, // 0, 6
+ 0, 6, 12728, 0, 7, 35844, 1, 6, 7674, 1, 7, 9290, // 0, 7
+ -1, 7, 7643, -1, 8, 9224, 0, 7, 12764, 0, 8, 35905, // 0, 8
+ -1, 8, 7839, -1, 9, 9558, 0, 8, 12777, 0, 9, 35362, // 0, 9
+ -1, 9, 8107, -1, 10, 9995, 0, 9, 12867, 0, 10, 34567, // 0,10
+ -1, 10, 8438, -1, 11, 10528, 0, 10, 13007, 0, 11, 33563, // 0,11
+ -1, 11, 8816, -1, 12, 11143, 0, 11, 13171, 0, 12, 32406, // 0,12
+ -1, 12, 9229, -1, 13, 11829, 0, 12, 13332, 0, 13, 31146, // 0,13
+ -1, 13, 9662, -1, 14, 12574, 0, 13, 13470, 0, 14, 29830, // 0,14
+ -1, 14, 10104, -1, 15, 13368, 0, 14, 13569, 0, 15, 28495, // 0,15
+ 1, -1, 12574, 1, 0, 29831, 2, -1, 9662, 2, 0, 13469, // 1, 0
+ 1, 0, 12412, 1, 1, 31358, 2, 0, 9202, 2, 1, 12564, // 1, 1
+ 1, 1, 12203, 1, 2, 32881, 2, 1, 8742, 2, 2, 11710, // 1, 2
+ 1, 2, 11964, 1, 3, 34358, 2, 2, 8296, 2, 3, 10918, // 1, 3
+ 1, 3, 11721, 1, 4, 35730, 2, 3, 7881, 2, 4, 10204, // 1, 4
+ 1, 4, 11507, 1, 5, 36926, 2, 4, 7517, 2, 5, 9586, // 1, 5
+ 1, 5, 11360, 1, 6, 37866, 2, 5, 7224, 2, 6, 9086, // 1, 6
+ 1, 6, 11317, 1, 7, 38481, 2, 6, 7020, 2, 7, 8718, // 1, 7
+ 0, 7, 6997, 0, 8, 8662, 1, 7, 11344, 1, 8, 38533, // 1, 8
+ 0, 8, 7202, 0, 9, 9020, 1, 8, 11407, 1, 9, 37907, // 1, 9
+ 0, 9, 7497, 0, 10, 9509, 1, 9, 11575, 1, 10, 36955, // 1,10
+ 0, 10, 7865, 0, 11, 10111, 1, 10, 11810, 1, 11, 35750, // 1,11
+ 0, 11, 8284, 0, 12, 10808, 1, 11, 12074, 1, 12, 34370, // 1,12
+ 0, 12, 8735, 0, 13, 11580, 1, 12, 12334, 1, 13, 32887, // 1,13
+ 0, 13, 9202, 0, 14, 12412, 1, 13, 12564, 1, 14, 31358, // 1,14
+ 0, 14, 9671, 0, 15, 13291, 1, 14, 12746, 1, 15, 29828, // 1,15
+ 2, -1, 11829, 2, 0, 31146, 3, -1, 9229, 3, 0, 13332, // 2, 0
+ 2, 0, 11580, 2, 1, 32886, 3, 0, 8735, 3, 1, 12335, // 2, 1
+ 2, 1, 11272, 2, 2, 34650, 3, 1, 8232, 3, 2, 11382, // 2, 2
+ 2, 2, 10922, 2, 3, 36392, 3, 2, 7734, 3, 3, 10488, // 2, 3
+ 2, 3, 10559, 2, 4, 38042, 3, 3, 7261, 3, 4, 9674, // 2, 4
+ 2, 4, 10226, 2, 5, 39503, 3, 4, 6842, 3, 5, 8965, // 2, 5
+ 2, 5, 9977, 2, 6, 40656, 3, 5, 6506, 3, 6, 8397, // 2, 6
+ 2, 6, 9867, 2, 7, 41389, 3, 6, 6284, 3, 7, 7996, // 2, 7
+ 1, 7, 6266, 1, 8, 7951, 2, 7, 9886, 2, 8, 41433, // 2, 8
+ 1, 8, 6491, 1, 9, 8344, 2, 8, 10013, 2, 9, 40688, // 2, 9
+ 1, 9, 6829, 1, 10, 8902, 2, 9, 10279, 2, 10, 39526, // 2,10
+ 1, 10, 7252, 1, 11, 9597, 2, 10, 10630, 2, 11, 38057, // 2,11
+ 1, 11, 7728, 1, 12, 10397, 2, 11, 11012, 2, 12, 36399, // 2,12
+ 1, 12, 8232, 1, 13, 11272, 2, 12, 11382, 2, 13, 34650, // 2,13
+ 1, 13, 8742, 1, 14, 12203, 2, 13, 11709, 2, 14, 32882, // 2,14
+ 1, 14, 9245, 1, 15, 13176, 2, 14, 11977, 2, 15, 31138, // 2,15
+ 3, -1, 11143, 3, 0, 32406, 4, -1, 8816, 4, 0, 13171, // 3, 0
+ 3, 0, 10808, 3, 1, 34369, 4, 0, 8284, 4, 1, 12075, // 3, 1
+ 3, 1, 10397, 3, 2, 36399, 4, 1, 7728, 4, 2, 11012, // 3, 2
+ 3, 2, 9924, 3, 3, 38450, 4, 2, 7164, 4, 3, 9998, // 3, 3
+ 3, 3, 9421, 3, 4, 40444, 4, 3, 6615, 4, 4, 9056, // 3, 4
+ 3, 4, 8940, 3, 5, 42256, 4, 4, 6116, 4, 5, 8224, // 3, 5
+ 3, 5, 8558, 3, 6, 43710, 4, 5, 5712, 4, 6, 7556, // 3, 6
+ 3, 6, 8359, 3, 7, 44616, 4, 6, 5454, 4, 7, 7107, // 3, 7
+ 2, 7, 5443, 2, 8, 7072, 3, 7, 8373, 3, 8, 44648, // 3, 8
+ 2, 8, 5703, 2, 9, 7516, 3, 8, 8584, 3, 9, 43733, // 3, 9
+ 2, 9, 6108, 2, 10, 8175, 3, 9, 8982, 3, 10, 42271, // 3,10
+ 2, 10, 6611, 2, 11, 8995, 3, 10, 9478, 3, 11, 40452, // 3,11
+ 2, 11, 7164, 2, 12, 9924, 3, 11, 9998, 3, 12, 38450, // 3,12
+ 2, 12, 7734, 2, 13, 10922, 3, 12, 10488, 3, 13, 36392, // 3,13
+ 2, 13, 8296, 2, 14, 11964, 3, 13, 10918, 3, 14, 34358, // 3,14
+ 2, 14, 8838, 2, 15, 13038, 3, 14, 11269, 3, 15, 32391, // 3,15
+ 4, -1, 10528, 4, 0, 33564, 5, -1, 8438, 5, 0, 13006, // 4, 0
+ 4, 0, 10111, 4, 1, 35750, 5, 0, 7865, 5, 1, 11810, // 4, 1
+ 4, 1, 9597, 4, 2, 38057, 5, 1, 7252, 5, 2, 10630, // 4, 2
+ 4, 2, 8995, 4, 3, 40452, 5, 2, 6611, 5, 3, 9478, // 4, 3
+ 4, 3, 8332, 4, 4, 42861, 5, 3, 5965, 5, 4, 8378, // 4, 4
+ 4, 4, 7667, 4, 5, 45139, 5, 4, 5353, 5, 5, 7377, // 4, 5
+ 4, 5, 7100, 4, 6, 47035, 5, 5, 4843, 5, 6, 6558, // 4, 6
+ 4, 6, 6774, 4, 7, 48218, 5, 6, 4521, 5, 7, 6023, // 4, 7
+ 3, 7, 4513, 3, 8, 6000, 4, 7, 6783, 4, 8, 48240, // 4, 8
+ 3, 8, 4838, 3, 9, 6530, 4, 8, 7119, 4, 9, 47049, // 4, 9
+ 3, 9, 5350, 3, 10, 7342, 4, 9, 7698, 4, 10, 45146, // 4,10
+ 3, 10, 5965, 3, 11, 8332, 4, 10, 8378, 4, 11, 42861, // 4,11
+ 3, 11, 6615, 3, 12, 9421, 4, 11, 9056, 4, 12, 40444, // 4,12
+ 3, 12, 7261, 3, 13, 10559, 4, 12, 9674, 4, 13, 38042, // 4,13
+ 3, 13, 7881, 3, 14, 11721, 4, 13, 10204, 4, 14, 35730, // 4,14
+ 3, 14, 8463, 3, 15, 12899, 4, 14, 10635, 4, 15, 33539, // 4,15
+ 5, -1, 9995, 5, 0, 34567, 6, -1, 8107, 6, 0, 12867, // 5, 0
+ 5, 0, 9509, 5, 1, 36955, 6, 0, 7497, 6, 1, 11575, // 5, 1
+ 5, 1, 8902, 5, 2, 39526, 6, 1, 6829, 6, 2, 10279, // 5, 2
+ 5, 2, 8175, 5, 3, 42271, 6, 2, 6108, 6, 3, 8982, // 5, 3
+ 5, 3, 7342, 5, 4, 45146, 6, 3, 5350, 6, 4, 7698, // 5, 4
+ 5, 4, 6451, 5, 5, 48019, 6, 4, 4591, 6, 5, 6475, // 5, 5
+ 5, 5, 5624, 5, 6, 50581, 6, 5, 3913, 6, 6, 5418, // 5, 6
+ 5, 6, 5092, 5, 7, 52253, 6, 6, 3470, 6, 7, 4721, // 5, 7
+ 4, 7, 3466, 4, 8, 4708, 5, 7, 5097, 5, 8, 52265, // 5, 8
+ 4, 8, 3911, 4, 9, 5400, 5, 8, 5637, 5, 9, 50588, // 5, 9
+ 4, 9, 4591, 4, 10, 6451, 5, 9, 6475, 5, 10, 48019, // 5,10
+ 4, 10, 5353, 4, 11, 7667, 5, 10, 7377, 5, 11, 45139, // 5,11
+ 4, 11, 6116, 4, 12, 8940, 5, 11, 8224, 5, 12, 42256, // 5,12
+ 4, 12, 6842, 4, 13, 10226, 5, 12, 8966, 5, 13, 39502, // 5,13
+ 4, 13, 7517, 4, 14, 11507, 5, 13, 9587, 5, 14, 36925, // 5,14
+ 4, 14, 8135, 4, 15, 12783, 5, 14, 10086, 5, 15, 34532, // 5,15
+ 6, -1, 9558, 6, 0, 35362, 7, -1, 7839, 7, 0, 12777, // 6, 0
+ 6, 0, 9020, 6, 1, 37906, 7, 0, 7202, 7, 1, 11408, // 6, 1
+ 6, 1, 8344, 6, 2, 40688, 7, 1, 6491, 7, 2, 10013, // 6, 2
+ 6, 2, 7516, 6, 3, 43733, 7, 2, 5703, 7, 3, 8584, // 6, 3
+ 6, 3, 6530, 6, 4, 47049, 7, 3, 4838, 7, 4, 7119, // 6, 4
+ 6, 4, 5400, 6, 5, 50587, 7, 4, 3911, 7, 5, 5638, // 6, 5
+ 6, 5, 4217, 6, 6, 54105, 7, 5, 2989, 7, 6, 4225, // 6, 6
+ 6, 6, 3303, 6, 7, 56751, 7, 6, 2295, 7, 7, 3187, // 6, 7
+ 5, 7, 2294, 5, 8, 3180, 6, 7, 3306, 6, 8, 56756, // 6, 8
+ 5, 8, 2989, 5, 9, 4217, 6, 8, 4225, 6, 9, 54105, // 6, 9
+ 5, 9, 3913, 5, 10, 5624, 6, 9, 5418, 6, 10, 50581, // 6,10
+ 5, 10, 4843, 5, 11, 7100, 6, 10, 6558, 6, 11, 47035, // 6,11
+ 5, 11, 5712, 5, 12, 8558, 6, 11, 7556, 6, 12, 43710, // 6,12
+ 5, 12, 6506, 5, 13, 9977, 6, 12, 8397, 6, 13, 40656, // 6,13
+ 5, 13, 7224, 5, 14, 11360, 6, 13, 9086, 6, 14, 37866, // 6,14
+ 5, 14, 7868, 5, 15, 12717, 6, 14, 9635, 6, 15, 35316, // 6,15
+ 7, -1, 9224, 7, 0, 35905, 8, -1, 7643, 8, 0, 12764, // 7, 0
+ 7, 0, 8662, 7, 1, 38534, 8, 0, 6997, 8, 1, 11343, // 7, 1
+ 7, 1, 7951, 7, 2, 41432, 8, 1, 6266, 8, 2, 9887, // 7, 2
+ 7, 2, 7072, 7, 3, 44649, 8, 2, 5443, 8, 3, 8372, // 7, 3
+ 7, 3, 6000, 7, 4, 48240, 8, 3, 4513, 8, 4, 6783, // 7, 4
+ 7, 4, 4708, 7, 5, 52266, 8, 4, 3466, 8, 5, 5096, // 7, 5
+ 7, 5, 3180, 7, 6, 56756, 8, 5, 2294, 8, 6, 3306, // 7, 6
+ 7, 6, 1541, 7, 7, 61364, 8, 6, 1090, 8, 7, 1541, // 7, 7
+ 6, 7, 1090, 6, 8, 1541, 7, 7, 1542, 7, 8, 61363, // 7, 8
+ 6, 8, 2295, 6, 9, 3303, 7, 8, 3186, 7, 9, 56752, // 7, 9
+ 6, 9, 3470, 6, 10, 5092, 7, 9, 4721, 7, 10, 52253, // 7,10
+ 6, 10, 4521, 6, 11, 6774, 7, 10, 6023, 7, 11, 48218, // 7,11
+ 6, 11, 5454, 6, 12, 8359, 7, 11, 7106, 7, 12, 44617, // 7,12
+ 6, 12, 6284, 6, 13, 9867, 7, 12, 7996, 7, 13, 41389, // 7,13
+ 6, 13, 7020, 6, 14, 11317, 7, 13, 8718, 7, 14, 38481, // 7,14
+ 6, 14, 7674, 6, 15, 12728, 7, 14, 9290, 7, 15, 35844, // 7,15
+ 8, 0, 35844, 8, 1, 9290, 9, 0, 12728, 9, 1, 7674, // 8, 0
+ 8, 1, 38481, 8, 2, 8718, 9, 1, 11317, 9, 2, 7020, // 8, 1
+ 8, 2, 41389, 8, 3, 7996, 9, 2, 9867, 9, 3, 6284, // 8, 2
+ 8, 3, 44616, 8, 4, 7106, 9, 3, 8359, 9, 4, 5455, // 8, 3
+ 8, 4, 48218, 8, 5, 6023, 9, 4, 6774, 9, 5, 4521, // 8, 4
+ 8, 5, 52253, 8, 6, 4721, 9, 5, 5092, 9, 6, 3470, // 8, 5
+ 8, 6, 56751, 8, 7, 3186, 9, 6, 3303, 9, 7, 2296, // 8, 6
+ 8, 7, 61364, 8, 8, 1542, 9, 7, 1541, 9, 8, 1089, // 8, 7
+ 7, 8, 1542, 7, 9, 1090, 8, 8, 61364, 8, 9, 1540, // 8, 8
+ 7, 9, 3306, 7, 10, 2294, 8, 9, 56756, 8, 10, 3180, // 8, 9
+ 7, 10, 5097, 7, 11, 3466, 8, 10, 52266, 8, 11, 4707, // 8,10
+ 7, 11, 6783, 7, 12, 4513, 8, 11, 48240, 8, 12, 6000, // 8,11
+ 7, 12, 8373, 7, 13, 5443, 8, 12, 44649, 8, 13, 7071, // 8,12
+ 7, 13, 9886, 7, 14, 6266, 8, 13, 41432, 8, 14, 7952, // 8,13
+ 7, 14, 11344, 7, 15, 6997, 8, 14, 38534, 8, 15, 8661, // 8,14
+ 7, 15, 12764, 7, 16, 7643, 8, 15, 35905, 8, 16, 9224, // 8,15
+ 9, 0, 35315, 9, 1, 9635, 10, 0, 12717, 10, 1, 7869, // 9, 0
+ 9, 1, 37866, 9, 2, 9086, 10, 1, 11360, 10, 2, 7224, // 9, 1
+ 9, 2, 40656, 9, 3, 8397, 10, 2, 9977, 10, 3, 6506, // 9, 2
+ 9, 3, 43710, 9, 4, 7556, 10, 3, 8558, 10, 4, 5712, // 9, 3
+ 9, 4, 47035, 9, 5, 6558, 10, 4, 7100, 10, 5, 4843, // 9, 4
+ 9, 5, 50581, 9, 6, 5418, 10, 5, 5624, 10, 6, 3913, // 9, 5
+ 9, 6, 54105, 9, 7, 4225, 10, 6, 4217, 10, 7, 2989, // 9, 6
+ 9, 7, 56756, 9, 8, 3306, 10, 7, 3180, 10, 8, 2294, // 9, 7
+ 8, 8, 3186, 8, 9, 2295, 9, 8, 56751, 9, 9, 3304, // 9, 8
+ 8, 9, 4225, 8, 10, 2989, 9, 9, 54105, 9, 10, 4217, // 9, 9
+ 8, 10, 5637, 8, 11, 3911, 9, 10, 50587, 9, 11, 5401, // 9,10
+ 8, 11, 7119, 8, 12, 4838, 9, 11, 47049, 9, 12, 6530, // 9,11
+ 8, 12, 8584, 8, 13, 5703, 9, 12, 43733, 9, 13, 7516, // 9,12
+ 8, 13, 10013, 8, 14, 6491, 9, 13, 40688, 9, 14, 8344, // 9,13
+ 8, 14, 11407, 8, 15, 7202, 9, 14, 37906, 9, 15, 9021, // 9,14
+ 8, 15, 12777, 8, 16, 7839, 9, 15, 35362, 9, 16, 9558, // 9,15
+ 10, 0, 34532, 10, 1, 10086, 11, 0, 12783, 11, 1, 8135, // 10, 0
+ 10, 1, 36926, 10, 2, 9587, 11, 1, 11507, 11, 2, 7516, // 10, 1
+ 10, 2, 39503, 10, 3, 8966, 11, 2, 10226, 11, 3, 6841, // 10, 2
+ 10, 3, 42256, 10, 4, 8224, 11, 3, 8940, 11, 4, 6116, // 10, 3
+ 10, 4, 45139, 10, 5, 7377, 11, 4, 7667, 11, 5, 5353, // 10, 4
+ 10, 5, 48019, 10, 6, 6475, 11, 5, 6451, 11, 6, 4591, // 10, 5
+ 10, 6, 50587, 10, 7, 5637, 11, 6, 5400, 11, 7, 3912, // 10, 6
+ 10, 7, 52266, 10, 8, 5097, 11, 7, 4708, 11, 8, 3465, // 10, 7
+ 9, 8, 4721, 9, 9, 3470, 10, 8, 52253, 10, 9, 5092, // 10, 8
+ 9, 9, 5418, 9, 10, 3913, 10, 9, 50581, 10, 10, 5624, // 10, 9
+ 9, 10, 6475, 9, 11, 4591, 10, 10, 48019, 10, 11, 6451, // 10,10
+ 9, 11, 7698, 9, 12, 5350, 10, 11, 45146, 10, 12, 7342, // 10,11
+ 9, 12, 8982, 9, 13, 6108, 10, 12, 42271, 10, 13, 8175, // 10,12
+ 9, 13, 10279, 9, 14, 6829, 10, 13, 39526, 10, 14, 8902, // 10,13
+ 9, 14, 11575, 9, 15, 7497, 10, 14, 36955, 10, 15, 9509, // 10,14
+ 9, 15, 12867, 9, 16, 8107, 10, 15, 34567, 10, 16, 9995, // 10,15
+ 11, 0, 33539, 11, 1, 10635, 12, 0, 12899, 12, 1, 8463, // 11, 0
+ 11, 1, 35730, 11, 2, 10204, 12, 1, 11721, 12, 2, 7881, // 11, 1
+ 11, 2, 38042, 11, 3, 9674, 12, 2, 10559, 12, 3, 7261, // 11, 2
+ 11, 3, 40444, 11, 4, 9056, 12, 3, 9421, 12, 4, 6615, // 11, 3
+ 11, 4, 42861, 11, 5, 8378, 12, 4, 8332, 12, 5, 5965, // 11, 4
+ 11, 5, 45146, 11, 6, 7698, 12, 5, 7342, 12, 6, 5350, // 11, 5
+ 11, 6, 47049, 11, 7, 7119, 12, 6, 6530, 12, 7, 4838, // 11, 6
+ 11, 7, 48240, 11, 8, 6783, 12, 7, 6000, 12, 8, 4513, // 11, 7
+ 10, 8, 6023, 10, 9, 4521, 11, 8, 48218, 11, 9, 6774, // 11, 8
+ 10, 9, 6558, 10, 10, 4843, 11, 9, 47035, 11, 10, 7100, // 11, 9
+ 10, 10, 7377, 10, 11, 5353, 11, 10, 45139, 11, 11, 7667, // 11,10
+ 10, 11, 8378, 10, 12, 5965, 11, 11, 42861, 11, 12, 8332, // 11,11
+ 10, 12, 9478, 10, 13, 6611, 11, 12, 40452, 11, 13, 8995, // 11,12
+ 10, 13, 10630, 10, 14, 7252, 11, 13, 38057, 11, 14, 9597, // 11,13
+ 10, 14, 11810, 10, 15, 7865, 11, 14, 35750, 11, 15, 10111, // 11,14
+ 10, 15, 13007, 10, 16, 8438, 11, 15, 33564, 11, 16, 10527, // 11,15
+ 12, 0, 32391, 12, 1, 11269, 13, 0, 13038, 13, 1, 8838, // 12, 0
+ 12, 1, 34358, 12, 2, 10918, 13, 1, 11964, 13, 2, 8296, // 12, 1
+ 12, 2, 36392, 12, 3, 10488, 13, 2, 10922, 13, 3, 7734, // 12, 2
+ 12, 3, 38450, 12, 4, 9998, 13, 3, 9924, 13, 4, 7164, // 12, 3
+ 12, 4, 40452, 12, 5, 9478, 13, 4, 8995, 13, 5, 6611, // 12, 4
+ 12, 5, 42271, 12, 6, 8982, 13, 5, 8175, 13, 6, 6108, // 12, 5
+ 12, 6, 43733, 12, 7, 8584, 13, 6, 7516, 13, 7, 5703, // 12, 6
+ 12, 7, 44649, 12, 8, 8373, 13, 7, 7072, 13, 8, 5442, // 12, 7
+ 11, 8, 7106, 11, 9, 5454, 12, 8, 44616, 12, 9, 8360, // 12, 8
+ 11, 9, 7556, 11, 10, 5712, 12, 9, 43710, 12, 10, 8558, // 12, 9
+ 11, 10, 8224, 11, 11, 6116, 12, 10, 42256, 12, 11, 8940, // 12,10
+ 11, 11, 9056, 11, 12, 6615, 12, 11, 40444, 12, 12, 9421, // 12,11
+ 11, 12, 9998, 11, 13, 7164, 12, 12, 38450, 12, 13, 9924, // 12,12
+ 11, 13, 11012, 11, 14, 7728, 12, 13, 36399, 12, 14, 10397, // 12,13
+ 11, 14, 12074, 11, 15, 8284, 12, 14, 34369, 12, 15, 10809, // 12,14
+ 11, 15, 13171, 11, 16, 8816, 12, 15, 32406, 12, 16, 11143, // 12,15
+ 13, 0, 31138, 13, 1, 11977, 14, 0, 13176, 14, 1, 9245, // 13, 0
+ 13, 1, 32881, 13, 2, 11709, 14, 1, 12203, 14, 2, 8743, // 13, 1
+ 13, 2, 34650, 13, 3, 11382, 14, 2, 11272, 14, 3, 8232, // 13, 2
+ 13, 3, 36399, 13, 4, 11012, 14, 3, 10397, 14, 4, 7728, // 13, 3
+ 13, 4, 38057, 13, 5, 10630, 14, 4, 9597, 14, 5, 7252, // 13, 4
+ 13, 5, 39526, 13, 6, 10279, 14, 5, 8902, 14, 6, 6829, // 13, 5
+ 13, 6, 40688, 13, 7, 10013, 14, 6, 8344, 14, 7, 6491, // 13, 6
+ 13, 7, 41432, 13, 8, 9886, 14, 7, 7951, 14, 8, 6267, // 13, 7
+ 12, 8, 7996, 12, 9, 6284, 13, 8, 41389, 13, 9, 9867, // 13, 8
+ 12, 9, 8397, 12, 10, 6506, 13, 9, 40656, 13, 10, 9977, // 13, 9
+ 12, 10, 8966, 12, 11, 6842, 13, 10, 39503, 13, 11, 10225, // 13,10
+ 12, 11, 9674, 12, 12, 7261, 13, 11, 38042, 13, 12, 10559, // 13,11
+ 12, 12, 10488, 12, 13, 7734, 13, 12, 36392, 13, 13, 10922, // 13,12
+ 12, 13, 11382, 12, 14, 8232, 13, 13, 34650, 13, 14, 11272, // 13,13
+ 12, 14, 12334, 12, 15, 8735, 13, 14, 32886, 13, 15, 11581, // 13,14
+ 12, 15, 13332, 12, 16, 9229, 13, 15, 31146, 13, 16, 11829, // 13,15
+ 14, 0, 29828, 14, 1, 12746, 15, 0, 13291, 15, 1, 9671, // 14, 0
+ 14, 1, 31358, 14, 2, 12564, 15, 1, 12412, 15, 2, 9202, // 14, 1
+ 14, 2, 32886, 14, 3, 12334, 15, 2, 11580, 15, 3, 8736, // 14, 2
+ 14, 3, 34369, 14, 4, 12074, 15, 3, 10808, 15, 4, 8285, // 14, 3
+ 14, 4, 35750, 14, 5, 11810, 15, 4, 10111, 15, 5, 7865, // 14, 4
+ 14, 5, 36955, 14, 6, 11575, 15, 5, 9509, 15, 6, 7497, // 14, 5
+ 14, 6, 37906, 14, 7, 11407, 15, 6, 9020, 15, 7, 7203, // 14, 6
+ 14, 7, 38534, 14, 8, 11344, 15, 7, 8662, 15, 8, 6996, // 14, 7
+ 13, 8, 8718, 13, 9, 7020, 14, 8, 38481, 14, 9, 11317, // 14, 8
+ 13, 9, 9086, 13, 10, 7224, 14, 9, 37866, 14, 10, 11360, // 14, 9
+ 13, 10, 9587, 13, 11, 7517, 14, 10, 36926, 14, 11, 11506, // 14,10
+ 13, 11, 10204, 13, 12, 7881, 14, 11, 35730, 14, 12, 11721, // 14,11
+ 13, 12, 10918, 13, 13, 8296, 14, 12, 34358, 14, 13, 11964, // 14,12
+ 13, 13, 11709, 13, 14, 8742, 14, 13, 32881, 14, 14, 12204, // 14,13
+ 13, 14, 12564, 13, 15, 9202, 14, 14, 31358, 14, 15, 12412, // 14,14
+ 13, 15, 13470, 13, 16, 9662, 14, 15, 29831, 14, 16, 12573, // 14,15
+ 15, 0, 28495, 15, 1, 13569, 16, 0, 13368, 16, 1, 10104, // 15, 0
+ 15, 1, 29831, 15, 2, 13470, 16, 1, 12574, 16, 2, 9661, // 15, 1
+ 15, 2, 31146, 15, 3, 13332, 16, 2, 11829, 16, 3, 9229, // 15, 2
+ 15, 3, 32406, 15, 4, 13171, 16, 3, 11143, 16, 4, 8816, // 15, 3
+ 15, 4, 33564, 15, 5, 13007, 16, 4, 10528, 16, 5, 8437, // 15, 4
+ 15, 5, 34567, 15, 6, 12867, 16, 5, 9995, 16, 6, 8107, // 15, 5
+ 15, 6, 35362, 15, 7, 12777, 16, 6, 9558, 16, 7, 7839, // 15, 6
+ 15, 7, 35905, 15, 8, 12764, 16, 7, 9224, 16, 8, 7643, // 15, 7
+ 14, 8, 9290, 14, 9, 7674, 15, 8, 35844, 15, 9, 12728, // 15, 8
+ 14, 9, 9635, 14, 10, 7868, 15, 9, 35315, 15, 10, 12718, // 15, 9
+ 14, 10, 10086, 14, 11, 8135, 15, 10, 34532, 15, 11, 12783, // 15,10
+ 14, 11, 10635, 14, 12, 8463, 15, 11, 33539, 15, 12, 12899, // 15,11
+ 14, 12, 11269, 14, 13, 8838, 15, 12, 32391, 15, 13, 13038, // 15,12
+ 14, 13, 11977, 14, 14, 9245, 15, 13, 31138, 15, 14, 13176, // 15,13
+ 14, 14, 12746, 14, 15, 9671, 15, 14, 29828, 15, 15, 13291, // 15,14
+ 14, 15, 13569, 14, 16, 10104, 15, 15, 28495, 15, 16, 13368, // 15,15
+ // angle of 2.5 degrees
+ 0, -1, 14696, 0, 0, 24063, 1, -1, 11702, 1, 0, 15075, // 0, 0
+ 0, 0, 14872, 0, 1, 25368, 1, 0, 11187, 1, 1, 14109, // 0, 1
+ 0, 1, 14990, 0, 2, 26660, 1, 1, 10676, 1, 2, 13210, // 0, 2
+ 0, 2, 15060, 0, 3, 27903, 1, 2, 10185, 1, 3, 12388, // 0, 3
+ 0, 3, 15100, 0, 4, 29055, 1, 3, 9728, 1, 4, 11653, // 0, 4
+ 0, 4, 15135, 0, 5, 30064, 1, 4, 9323, 1, 5, 11014, // 0, 5
+ 0, 5, 15193, 0, 6, 30876, 1, 5, 8986, 1, 6, 10481, // 0, 6
+ 0, 6, 15301, 0, 7, 31444, 1, 6, 8727, 1, 7, 10064, // 0, 7
+ -1, 7, 8669, -1, 8, 9959, 0, 7, 15376, 0, 8, 31532, // 0, 8
+ -1, 8, 8927, -1, 9, 10351, 0, 8, 15319, 0, 9, 30939, // 0, 9
+ -1, 9, 9265, -1, 10, 10855, 0, 9, 15311, 0, 10, 30105, // 0,10
+ -1, 10, 9673, -1, 11, 11461, 0, 10, 15325, 0, 11, 29077, // 0,11
+ -1, 11, 10135, -1, 12, 12159, 0, 11, 15330, 0, 12, 27912, // 0,12
+ -1, 12, 10637, -1, 13, 12938, 0, 12, 15301, 0, 13, 26660, // 0,13
+ -1, 13, 11164, -1, 14, 13787, 0, 13, 15220, 0, 14, 25365, // 0,14
+ -1, 14, 11702, -1, 15, 14696, 0, 14, 15076, 0, 15, 24062, // 0,15
+ 1, -1, 13787, 1, 0, 25366, 2, -1, 11164, 2, 0, 15219, // 1, 0
+ 1, 0, 13853, 1, 1, 26893, 2, 0, 10644, 2, 1, 14146, // 1, 1
+ 1, 1, 13850, 1, 2, 28427, 2, 1, 10119, 2, 2, 13140, // 1, 2
+ 1, 2, 13789, 1, 3, 29928, 2, 2, 9603, 2, 3, 12216, // 1, 3
+ 1, 3, 13694, 1, 4, 31339, 2, 3, 9118, 2, 4, 11385, // 1, 4
+ 1, 4, 13600, 1, 5, 32586, 2, 4, 8685, 2, 5, 10665, // 1, 5
+ 1, 5, 13548, 1, 6, 33585, 2, 5, 8329, 2, 6, 10074, // 1, 6
+ 1, 6, 13582, 1, 7, 34261, 2, 6, 8068, 2, 7, 9625, // 1, 7
+ 0, 7, 8024, 0, 8, 9534, 1, 7, 13638, 1, 8, 34340, // 1, 8
+ 0, 8, 8286, 0, 9, 9961, 1, 8, 13647, 1, 9, 33642, // 1, 9
+ 0, 9, 8645, 0, 10, 10528, 1, 9, 13740, 1, 10, 32623, // 1,10
+ 0, 10, 9082, 0, 11, 11218, 1, 10, 13875, 1, 11, 31361, // 1,11
+ 0, 11, 9575, 0, 12, 12014, 1, 11, 14009, 1, 12, 29938, // 1,12
+ 0, 12, 10102, 0, 13, 12897, 1, 12, 14107, 1, 13, 28430, // 1,13
+ 0, 13, 10644, 0, 14, 13853, 1, 13, 14145, 1, 14, 26894, // 1,14
+ 0, 14, 11187, 0, 15, 14872, 1, 14, 14109, 1, 15, 25368, // 1,15
+ 2, -1, 12938, 2, 0, 26660, 3, -1, 10637, 3, 0, 15301, // 2, 0
+ 2, 0, 12897, 2, 1, 28430, 3, 0, 10102, 3, 1, 14107, // 2, 1
+ 2, 1, 12769, 2, 2, 30239, 3, 1, 9546, 3, 2, 12982, // 2, 2
+ 2, 2, 12569, 2, 3, 32045, 3, 2, 8988, 3, 3, 11934, // 2, 3
+ 2, 3, 12323, 2, 4, 33777, 3, 3, 8452, 3, 4, 10984, // 2, 4
+ 2, 4, 12079, 2, 5, 35332, 3, 4, 7969, 3, 5, 10156, // 2, 5
+ 2, 5, 11897, 2, 6, 36582, 3, 5, 7573, 3, 6, 9484, // 2, 6
+ 2, 6, 11842, 2, 7, 37402, 3, 6, 7298, 3, 7, 8994, // 2, 7
+ 1, 7, 7266, 1, 8, 8918, 2, 7, 11883, 2, 8, 37469, // 2, 8
+ 1, 8, 7543, 1, 9, 9390, 2, 8, 11972, 2, 9, 36631, // 2, 9
+ 1, 9, 7943, 1, 10, 10041, 2, 9, 12188, 2, 10, 35364, // 2,10
+ 1, 10, 8432, 1, 11, 10842, 2, 10, 12467, 2, 11, 33795, // 2,11
+ 1, 11, 8976, 1, 12, 11760, 2, 11, 12747, 2, 12, 32053, // 2,12
+ 1, 12, 9546, 1, 13, 12769, 2, 12, 12982, 2, 13, 30239, // 2,13
+ 1, 13, 10119, 1, 14, 13850, 2, 13, 13141, 2, 14, 28426, // 2,14
+ 1, 14, 10676, 1, 15, 14990, 2, 14, 13211, 2, 15, 26659, // 2,15
+ 3, -1, 12159, 3, 0, 27912, 4, -1, 10135, 4, 0, 15330, // 3, 0
+ 3, 0, 12014, 3, 1, 29938, 4, 0, 9575, 4, 1, 14009, // 3, 1
+ 3, 1, 11760, 3, 2, 32052, 4, 1, 8976, 4, 2, 12748, // 3, 2
+ 3, 2, 11411, 3, 3, 34213, 4, 2, 8358, 4, 3, 11554, // 3, 3
+ 3, 3, 10995, 3, 4, 36343, 4, 3, 7746, 4, 4, 10452, // 3, 4
+ 3, 4, 10569, 3, 5, 38307, 4, 4, 7180, 4, 5, 9480, // 3, 5
+ 3, 5, 10221, 3, 6, 39912, 4, 5, 6714, 4, 6, 8689, // 3, 6
+ 3, 6, 10051, 3, 7, 40940, 4, 6, 6403, 4, 7, 8142, // 3, 7
+ 2, 7, 6381, 2, 8, 8082, 3, 7, 10079, 3, 8, 40994, // 3, 8
+ 2, 8, 6695, 2, 9, 8617, 3, 8, 10275, 3, 9, 39949, // 3, 9
+ 2, 9, 7165, 2, 10, 9388, 3, 9, 10653, 3, 10, 38330, // 3,10
+ 2, 10, 7737, 2, 11, 10337, 3, 10, 11108, 3, 11, 36354, // 3,11
+ 2, 11, 8358, 2, 12, 11411, 3, 11, 11554, 3, 12, 34213, // 3,12
+ 2, 12, 8988, 2, 13, 12569, 3, 12, 11934, 3, 13, 32045, // 3,13
+ 2, 13, 9603, 2, 14, 13789, 3, 13, 12216, 3, 14, 29928, // 3,14
+ 2, 14, 10185, 2, 15, 15060, 3, 14, 12388, 3, 15, 27903, // 3,15
+ 4, -1, 11461, 4, 0, 29078, 5, -1, 9673, 5, 0, 15324, // 4, 0
+ 4, 0, 11218, 4, 1, 31361, 5, 0, 9082, 5, 1, 13875, // 4, 1
+ 4, 1, 10842, 4, 2, 33795, 5, 1, 8432, 5, 2, 12467, // 4, 2
+ 4, 2, 10337, 4, 3, 36354, 5, 2, 7737, 5, 3, 11108, // 4, 3
+ 4, 3, 9730, 4, 4, 38966, 5, 3, 7022, 5, 4, 9818, // 4, 4
+ 4, 4, 9081, 4, 5, 41475, 5, 4, 6334, 5, 5, 8646, // 4, 5
+ 4, 5, 8507, 4, 6, 43602, 5, 5, 5749, 5, 6, 7678, // 4, 6
+ 4, 6, 8177, 4, 7, 44962, 5, 6, 5368, 5, 7, 7029, // 4, 7
+ 3, 7, 5354, 3, 8, 6987, 4, 7, 8195, 4, 8, 45000, // 4, 8
+ 3, 8, 5739, 3, 9, 7626, 4, 8, 8545, 4, 9, 43626, // 4, 9
+ 3, 9, 6328, 3, 10, 8578, 4, 9, 9143, 4, 10, 41487, // 4,10
+ 3, 10, 7022, 3, 11, 9730, 4, 10, 9818, 4, 11, 38966, // 4,11
+ 3, 11, 7746, 3, 12, 10995, 4, 11, 10452, 4, 12, 36343, // 4,12
+ 3, 12, 8452, 3, 13, 12323, 4, 12, 10983, 4, 13, 33778, // 4,13
+ 3, 13, 9118, 3, 14, 13694, 4, 13, 11385, 4, 14, 31339, // 4,14
+ 3, 14, 9728, 3, 15, 15100, 4, 14, 11652, 4, 15, 29056, // 4,15
+ 5, -1, 10855, 5, 0, 30105, 6, -1, 9265, 6, 0, 15311, // 5, 0
+ 5, 0, 10528, 5, 1, 32624, 6, 0, 8645, 6, 1, 13739, // 5, 1
+ 5, 1, 10041, 5, 2, 35364, 6, 1, 7943, 6, 2, 12188, // 5, 2
+ 5, 2, 9388, 5, 3, 38330, 6, 2, 7165, 6, 3, 10653, // 5, 3
+ 5, 3, 8578, 5, 4, 41487, 6, 3, 6328, 6, 4, 9143, // 5, 4
+ 5, 4, 7659, 5, 5, 44700, 6, 4, 5472, 6, 5, 7705, // 5, 5
+ 5, 5, 6768, 5, 6, 47619, 6, 5, 4694, 6, 6, 6455, // 5, 6
+ 5, 6, 6183, 5, 7, 49566, 6, 6, 4172, 6, 7, 5615, // 5, 7
+ 4, 7, 4164, 4, 8, 5590, 5, 7, 6193, 5, 8, 49589, // 5, 8
+ 4, 8, 4690, 4, 9, 6422, 5, 8, 6794, 5, 9, 47630, // 5, 9
+ 4, 9, 5472, 4, 10, 7659, 5, 9, 7705, 5, 10, 44700, // 5,10
+ 4, 10, 6334, 4, 11, 9081, 5, 10, 8646, 5, 11, 41475, // 5,11
+ 4, 11, 7180, 4, 12, 10569, 5, 11, 9479, 5, 12, 38308, // 5,12
+ 4, 12, 7969, 4, 13, 12079, 5, 12, 10156, 5, 13, 35332, // 5,13
+ 4, 13, 8685, 4, 14, 13600, 5, 13, 10665, 5, 14, 32586, // 5,14
+ 4, 14, 9323, 4, 15, 15135, 5, 14, 11013, 5, 15, 30065, // 5,15
+ 6, -1, 10351, 6, 0, 30939, 7, -1, 8927, 7, 0, 15319, // 6, 0
+ 6, 0, 9961, 6, 1, 33642, 7, 0, 8286, 7, 1, 13647, // 6, 1
+ 6, 1, 9390, 6, 2, 36631, 7, 1, 7543, 7, 2, 11972, // 6, 2
+ 6, 2, 8617, 6, 3, 39949, 7, 2, 6695, 7, 3, 10275, // 6, 3
+ 6, 3, 7626, 6, 4, 43626, 7, 3, 5739, 7, 4, 8545, // 6, 4
+ 6, 4, 6422, 6, 5, 47630, 7, 4, 4690, 7, 5, 6794, // 6, 5
+ 6, 5, 5099, 6, 6, 51701, 7, 5, 3620, 7, 6, 5116, // 6, 6
+ 6, 6, 4044, 6, 7, 54831, 7, 6, 2797, 7, 7, 3864, // 6, 7
+ 5, 7, 2795, 5, 8, 3853, 6, 7, 4049, 6, 8, 54839, // 6, 8
+ 5, 8, 3620, 5, 9, 5099, 6, 8, 5116, 6, 9, 51701, // 6, 9
+ 5, 9, 4694, 5, 10, 6768, 6, 9, 6455, 6, 10, 47619, // 6,10
+ 5, 10, 5749, 5, 11, 8507, 6, 10, 7678, 6, 11, 43602, // 6,11
+ 5, 11, 6714, 5, 12, 10221, 6, 11, 8690, 6, 12, 39911, // 6,12
+ 5, 12, 7573, 5, 13, 11897, 6, 12, 9484, 6, 13, 36582, // 6,13
+ 5, 13, 8329, 5, 14, 13548, 6, 13, 10074, 6, 14, 33585, // 6,14
+ 5, 14, 8986, 5, 15, 15193, 6, 14, 10482, 6, 15, 30875, // 6,15
+ 7, -1, 9959, 7, 0, 31532, 8, -1, 8669, 8, 0, 15376, // 7, 0
+ 7, 0, 9534, 7, 1, 34340, 8, 0, 8024, 8, 1, 13638, // 7, 1
+ 7, 1, 8918, 7, 2, 37470, 8, 1, 7266, 8, 2, 11882, // 7, 2
+ 7, 2, 8082, 7, 3, 40994, 8, 2, 6381, 8, 3, 10079, // 7, 3
+ 7, 3, 6987, 7, 4, 44999, 8, 3, 5354, 8, 4, 8196, // 7, 4
+ 7, 4, 5590, 7, 5, 49588, 8, 4, 4164, 8, 5, 6194, // 7, 5
+ 7, 5, 3853, 7, 6, 54839, 8, 5, 2795, 8, 6, 4049, // 7, 6
+ 7, 6, 1903, 7, 7, 60382, 8, 6, 1347, 8, 7, 1904, // 7, 7
+ 6, 7, 1347, 6, 8, 1903, 7, 7, 1905, 7, 8, 60381, // 7, 8
+ 6, 8, 2797, 6, 9, 4044, 7, 8, 3864, 7, 9, 54831, // 7, 9
+ 6, 9, 4172, 6, 10, 6183, 7, 9, 5615, 7, 10, 49566, // 7,10
+ 6, 10, 5368, 6, 11, 8177, 7, 10, 7029, 7, 11, 44962, // 7,11
+ 6, 11, 6403, 6, 12, 10051, 7, 11, 8141, 7, 12, 40941, // 7,12
+ 6, 12, 7298, 6, 13, 11842, 7, 12, 8994, 7, 13, 37402, // 7,13
+ 6, 13, 8068, 6, 14, 13582, 7, 13, 9626, 7, 14, 34260, // 7,14
+ 6, 14, 8727, 6, 15, 15301, 7, 14, 10065, 7, 15, 31443, // 7,15
+ 8, 0, 31444, 8, 1, 10065, 9, 0, 15301, 9, 1, 8726, // 8, 0
+ 8, 1, 34261, 8, 2, 9626, 9, 1, 13582, 9, 2, 8067, // 8, 1
+ 8, 2, 37402, 8, 3, 8994, 9, 2, 11842, 9, 3, 7298, // 8, 2
+ 8, 3, 40940, 8, 4, 8141, 9, 3, 10051, 9, 4, 6404, // 8, 3
+ 8, 4, 44962, 8, 5, 7029, 9, 4, 8177, 9, 5, 5368, // 8, 4
+ 8, 5, 49566, 8, 6, 5615, 9, 5, 6183, 9, 6, 4172, // 8, 5
+ 8, 6, 54831, 8, 7, 3864, 9, 6, 4044, 9, 7, 2797, // 8, 6
+ 8, 7, 60382, 8, 8, 1905, 9, 7, 1903, 9, 8, 1346, // 8, 7
+ 7, 8, 1905, 7, 9, 1347, 8, 8, 60382, 8, 9, 1902, // 8, 8
+ 7, 9, 4049, 7, 10, 2795, 8, 9, 54839, 8, 10, 3853, // 8, 9
+ 7, 10, 6193, 7, 11, 4164, 8, 10, 49588, 8, 11, 5591, // 8,10
+ 7, 11, 8195, 7, 12, 5354, 8, 11, 44999, 8, 12, 6988, // 8,11
+ 7, 12, 10079, 7, 13, 6381, 8, 12, 40994, 8, 13, 8082, // 8,12
+ 7, 13, 11883, 7, 14, 7266, 8, 13, 37470, 8, 14, 8917, // 8,13
+ 7, 14, 13638, 7, 15, 8024, 8, 14, 34340, 8, 15, 9534, // 8,14
+ 7, 15, 15376, 7, 16, 8669, 8, 15, 31532, 8, 16, 9959, // 8,15
+ 9, 0, 30876, 9, 1, 10482, 10, 0, 15193, 10, 1, 8985, // 9, 0
+ 9, 1, 33585, 9, 2, 10074, 10, 1, 13548, 10, 2, 8329, // 9, 1
+ 9, 2, 36582, 9, 3, 9484, 10, 2, 11897, 10, 3, 7573, // 9, 2
+ 9, 3, 39912, 9, 4, 8690, 10, 3, 10221, 10, 4, 6713, // 9, 3
+ 9, 4, 43602, 9, 5, 7678, 10, 4, 8507, 10, 5, 5749, // 9, 4
+ 9, 5, 47619, 9, 6, 6455, 10, 5, 6768, 10, 6, 4694, // 9, 5
+ 9, 6, 51701, 9, 7, 5116, 10, 6, 5099, 10, 7, 3620, // 9, 6
+ 9, 7, 54839, 9, 8, 4049, 10, 7, 3853, 10, 8, 2795, // 9, 7
+ 8, 8, 3864, 8, 9, 2797, 9, 8, 54831, 9, 9, 4044, // 9, 8
+ 8, 9, 5116, 8, 10, 3620, 9, 9, 51701, 9, 10, 5099, // 9, 9
+ 8, 10, 6794, 8, 11, 4690, 9, 10, 47630, 9, 11, 6422, // 9,10
+ 8, 11, 8545, 8, 12, 5739, 9, 11, 43626, 9, 12, 7626, // 9,11
+ 8, 12, 10275, 8, 13, 6695, 9, 12, 39949, 9, 13, 8617, // 9,12
+ 8, 13, 11972, 8, 14, 7543, 9, 13, 36631, 9, 14, 9390, // 9,13
+ 8, 14, 13647, 8, 15, 8286, 9, 14, 33642, 9, 15, 9961, // 9,14
+ 8, 15, 15319, 8, 16, 8927, 9, 15, 30939, 9, 16, 10351, // 9,15
+ 10, 0, 30064, 10, 1, 11013, 11, 0, 15135, 11, 1, 9324, // 10, 0
+ 10, 1, 32586, 10, 2, 10665, 11, 1, 13600, 11, 2, 8685, // 10, 1
+ 10, 2, 35332, 10, 3, 10156, 11, 2, 12079, 11, 3, 7969, // 10, 2
+ 10, 3, 38307, 10, 4, 9479, 11, 3, 10569, 11, 4, 7181, // 10, 3
+ 10, 4, 41475, 10, 5, 8646, 11, 4, 9081, 11, 5, 6334, // 10, 4
+ 10, 5, 44700, 10, 6, 7705, 11, 5, 7659, 11, 6, 5472, // 10, 5
+ 10, 6, 47630, 10, 7, 6794, 11, 6, 6422, 11, 7, 4690, // 10, 6
+ 10, 7, 49588, 10, 8, 6193, 11, 7, 5590, 11, 8, 4165, // 10, 7
+ 9, 8, 5615, 9, 9, 4172, 10, 8, 49566, 10, 9, 6183, // 10, 8
+ 9, 9, 6455, 9, 10, 4694, 10, 9, 47619, 10, 10, 6768, // 10, 9
+ 9, 10, 7705, 9, 11, 5472, 10, 10, 44700, 10, 11, 7659, // 10,10
+ 9, 11, 9143, 9, 12, 6328, 10, 11, 41487, 10, 12, 8578, // 10,11
+ 9, 12, 10653, 9, 13, 7165, 10, 12, 38330, 10, 13, 9388, // 10,12
+ 9, 13, 12188, 9, 14, 7943, 10, 13, 35364, 10, 14, 10041, // 10,13
+ 9, 14, 13740, 9, 15, 8645, 10, 14, 32624, 10, 15, 10527, // 10,14
+ 9, 15, 15311, 9, 16, 9265, 10, 15, 30105, 10, 16, 10855, // 10,15
+ 11, 0, 29055, 11, 1, 11652, 12, 0, 15100, 12, 1, 9729, // 11, 0
+ 11, 1, 31339, 11, 2, 11385, 12, 1, 13694, 12, 2, 9118, // 11, 1
+ 11, 2, 33777, 11, 3, 10983, 12, 2, 12323, 12, 3, 8453, // 11, 2
+ 11, 3, 36343, 11, 4, 10452, 12, 3, 10995, 12, 4, 7746, // 11, 3
+ 11, 4, 38966, 11, 5, 9818, 12, 4, 9730, 12, 5, 7022, // 11, 4
+ 11, 5, 41487, 11, 6, 9143, 12, 5, 8578, 12, 6, 6328, // 11, 5
+ 11, 6, 43626, 11, 7, 8545, 12, 6, 7626, 12, 7, 5739, // 11, 6
+ 11, 7, 44999, 11, 8, 8195, 12, 7, 6987, 12, 8, 5355, // 11, 7
+ 10, 8, 7029, 10, 9, 5368, 11, 8, 44962, 11, 9, 8177, // 11, 8
+ 10, 9, 7678, 10, 10, 5749, 11, 9, 43602, 11, 10, 8507, // 11, 9
+ 10, 10, 8646, 10, 11, 6334, 11, 10, 41475, 11, 11, 9081, // 11,10
+ 10, 11, 9818, 10, 12, 7022, 11, 11, 38966, 11, 12, 9730, // 11,11
+ 10, 12, 11108, 10, 13, 7737, 11, 12, 36354, 11, 13, 10337, // 11,12
+ 10, 13, 12467, 10, 14, 8432, 11, 13, 33795, 11, 14, 10842, // 11,13
+ 10, 14, 13875, 10, 15, 9082, 11, 14, 31361, 11, 15, 11218, // 11,14
+ 10, 15, 15325, 10, 16, 9673, 11, 15, 29078, 11, 16, 11460, // 11,15
+ 12, 0, 27903, 12, 1, 12388, 13, 0, 15060, 13, 1, 10185, // 12, 0
+ 12, 1, 29928, 12, 2, 12216, 13, 1, 13789, 13, 2, 9603, // 12, 1
+ 12, 2, 32045, 12, 3, 11934, 13, 2, 12569, 13, 3, 8988, // 12, 2
+ 12, 3, 34213, 12, 4, 11554, 13, 3, 11411, 13, 4, 8358, // 12, 3
+ 12, 4, 36354, 12, 5, 11108, 13, 4, 10337, 13, 5, 7737, // 12, 4
+ 12, 5, 38330, 12, 6, 10653, 13, 5, 9388, 13, 6, 7165, // 12, 5
+ 12, 6, 39949, 12, 7, 10275, 13, 6, 8617, 13, 7, 6695, // 12, 6
+ 12, 7, 40994, 12, 8, 10079, 13, 7, 8082, 13, 8, 6381, // 12, 7
+ 11, 8, 8141, 11, 9, 6403, 12, 8, 40940, 12, 9, 10052, // 12, 8
+ 11, 9, 8690, 11, 10, 6714, 12, 9, 39912, 12, 10, 10220, // 12, 9
+ 11, 10, 9479, 11, 11, 7180, 12, 10, 38307, 12, 11, 10570, // 12,10
+ 11, 11, 10452, 11, 12, 7746, 12, 11, 36343, 12, 12, 10995, // 12,11
+ 11, 12, 11554, 11, 13, 8358, 12, 12, 34213, 12, 13, 11411, // 12,12
+ 11, 13, 12747, 11, 14, 8976, 12, 13, 32052, 12, 14, 11761, // 12,13
+ 11, 14, 14009, 11, 15, 9575, 12, 14, 29938, 12, 15, 12014, // 12,14
+ 11, 15, 15330, 11, 16, 10135, 12, 15, 27912, 12, 16, 12159, // 12,15
+ 13, 0, 26660, 13, 1, 13211, 14, 0, 14990, 14, 1, 10675, // 13, 0
+ 13, 1, 28427, 13, 2, 13141, 14, 1, 13850, 14, 2, 10118, // 13, 1
+ 13, 2, 30239, 13, 3, 12982, 14, 2, 12769, 14, 3, 9546, // 13, 2
+ 13, 3, 32052, 13, 4, 12747, 14, 3, 11760, 14, 4, 8977, // 13, 3
+ 13, 4, 33795, 13, 5, 12467, 14, 4, 10842, 14, 5, 8432, // 13, 4
+ 13, 5, 35364, 13, 6, 12188, 14, 5, 10041, 14, 6, 7943, // 13, 5
+ 13, 6, 36631, 13, 7, 11972, 14, 6, 9390, 14, 7, 7543, // 13, 6
+ 13, 7, 37470, 13, 8, 11883, 14, 7, 8918, 14, 8, 7265, // 13, 7
+ 12, 8, 8994, 12, 9, 7298, 13, 8, 37402, 13, 9, 11842, // 13, 8
+ 12, 9, 9484, 12, 10, 7573, 13, 9, 36582, 13, 10, 11897, // 13, 9
+ 12, 10, 10156, 12, 11, 7969, 13, 10, 35332, 13, 11, 12079, // 13,10
+ 12, 11, 10983, 12, 12, 8452, 13, 11, 33777, 13, 12, 12324, // 13,11
+ 12, 12, 11934, 12, 13, 8988, 13, 12, 32045, 13, 13, 12569, // 13,12
+ 12, 13, 12982, 12, 14, 9546, 13, 13, 30239, 13, 14, 12769, // 13,13
+ 12, 14, 14107, 12, 15, 10102, 13, 14, 28430, 13, 15, 12897, // 13,14
+ 12, 15, 15301, 12, 16, 10637, 13, 15, 26660, 13, 16, 12938, // 13,15
+ 14, 0, 25368, 14, 1, 14109, 15, 0, 14872, 15, 1, 11187, // 14, 0
+ 14, 1, 26893, 14, 2, 14145, 15, 1, 13853, 15, 2, 10645, // 14, 1
+ 14, 2, 28430, 14, 3, 14107, 15, 2, 12897, 15, 3, 10102, // 14, 2
+ 14, 3, 29938, 14, 4, 14009, 15, 3, 12014, 15, 4, 9575, // 14, 3
+ 14, 4, 31361, 14, 5, 13875, 15, 4, 11218, 15, 5, 9082, // 14, 4
+ 14, 5, 32624, 14, 6, 13740, 15, 5, 10528, 15, 6, 8644, // 14, 5
+ 14, 6, 33642, 14, 7, 13647, 15, 6, 9961, 15, 7, 8286, // 14, 6
+ 14, 7, 34340, 14, 8, 13638, 15, 7, 9534, 15, 8, 8024, // 14, 7
+ 13, 8, 9626, 13, 9, 8068, 14, 8, 34261, 14, 9, 13581, // 14, 8
+ 13, 9, 10074, 13, 10, 8329, 14, 9, 33585, 14, 10, 13548, // 14, 9
+ 13, 10, 10665, 13, 11, 8685, 14, 10, 32586, 14, 11, 13600, // 14,10
+ 13, 11, 11385, 13, 12, 9118, 14, 11, 31339, 14, 12, 13694, // 14,11
+ 13, 12, 12216, 13, 13, 9603, 14, 12, 29928, 14, 13, 13789, // 14,12
+ 13, 13, 13141, 13, 14, 10119, 14, 13, 28427, 14, 14, 13849, // 14,13
+ 13, 14, 14145, 13, 15, 10644, 14, 14, 26893, 14, 15, 13854, // 14,14
+ 13, 15, 15220, 13, 16, 11164, 14, 15, 25366, 14, 16, 13786, // 14,15
+ 15, 0, 24063, 15, 1, 15076, 16, 0, 14696, 16, 1, 11701, // 15, 0
+ 15, 1, 25366, 15, 2, 15220, 16, 1, 13787, 16, 2, 11163, // 15, 1
+ 15, 2, 26660, 15, 3, 15301, 16, 2, 12938, 16, 3, 10637, // 15, 2
+ 15, 3, 27912, 15, 4, 15330, 16, 3, 12159, 16, 4, 10135, // 15, 3
+ 15, 4, 29078, 15, 5, 15325, 16, 4, 11461, 16, 5, 9672, // 15, 4
+ 15, 5, 30105, 15, 6, 15311, 16, 5, 10855, 16, 6, 9265, // 15, 5
+ 15, 6, 30939, 15, 7, 15319, 16, 6, 10351, 16, 7, 8927, // 15, 6
+ 15, 7, 31532, 15, 8, 15376, 16, 7, 9959, 16, 8, 8669, // 15, 7
+ 14, 8, 10065, 14, 9, 8727, 15, 8, 31444, 15, 9, 15300, // 15, 8
+ 14, 9, 10482, 14, 10, 8986, 15, 9, 30876, 15, 10, 15192, // 15, 9
+ 14, 10, 11013, 14, 11, 9323, 15, 10, 30064, 15, 11, 15136, // 15,10
+ 14, 11, 11652, 14, 12, 9728, 15, 11, 29055, 15, 12, 15101, // 15,11
+ 14, 12, 12388, 14, 13, 10185, 15, 12, 27903, 15, 13, 15060, // 15,12
+ 14, 13, 13211, 14, 14, 10676, 15, 13, 26660, 15, 14, 14989, // 15,13
+ 14, 14, 14109, 14, 15, 11187, 15, 14, 25368, 15, 15, 14872, // 15,14
+ 14, 15, 15076, 14, 16, 11702, 15, 15, 24063, 15, 16, 14695, // 15,15
diff --git a/vp8/common/rotate2.h b/vp8/common/rotate2.h
new file mode 100644
index 000000000..580f55279
--- /dev/null
+++ b/vp8/common/rotate2.h
@@ -0,0 +1,2827 @@
+ // angle of -2.5 degrees
+ -1, 0, 14696, -1, 1, 11702, 0, 0, 24063, 0, 1, 15075, // 0, 0
+ -1, 1, 13787, -1, 2, 11164, 0, 1, 25366, 0, 2, 15219, // 0, 1
+ -1, 2, 12938, -1, 3, 10637, 0, 2, 26660, 0, 3, 15301, // 0, 2
+ -1, 3, 12159, -1, 4, 10135, 0, 3, 27912, 0, 4, 15330, // 0, 3
+ -1, 4, 11461, -1, 5, 9673, 0, 4, 29078, 0, 5, 15324, // 0, 4
+ -1, 5, 10855, -1, 6, 9265, 0, 5, 30105, 0, 6, 15311, // 0, 5
+ -1, 6, 10351, -1, 7, 8927, 0, 6, 30939, 0, 7, 15319, // 0, 6
+ -1, 7, 9959, -1, 8, 8669, 0, 7, 31532, 0, 8, 15376, // 0, 7
+ 0, 8, 31444, 0, 9, 15301, 1, 8, 10065, 1, 9, 8726, // 0, 8
+ 0, 9, 30876, 0, 10, 15193, 1, 9, 10482, 1, 10, 8985, // 0, 9
+ 0, 10, 30064, 0, 11, 15135, 1, 10, 11013, 1, 11, 9324, // 0,10
+ 0, 11, 29055, 0, 12, 15100, 1, 11, 11652, 1, 12, 9729, // 0,11
+ 0, 12, 27903, 0, 13, 15060, 1, 12, 12388, 1, 13, 10185, // 0,12
+ 0, 13, 26660, 0, 14, 14990, 1, 13, 13211, 1, 14, 10675, // 0,13
+ 0, 14, 25368, 0, 15, 14872, 1, 14, 14109, 1, 15, 11187, // 0,14
+ 0, 15, 24063, 0, 16, 14696, 1, 15, 15076, 1, 16, 11701, // 0,15
+ 0, 0, 14872, 0, 1, 11187, 1, 0, 25368, 1, 1, 14109, // 1, 0
+ 0, 1, 13853, 0, 2, 10644, 1, 1, 26893, 1, 2, 14146, // 1, 1
+ 0, 2, 12897, 0, 3, 10102, 1, 2, 28430, 1, 3, 14107, // 1, 2
+ 0, 3, 12014, 0, 4, 9575, 1, 3, 29938, 1, 4, 14009, // 1, 3
+ 0, 4, 11218, 0, 5, 9082, 1, 4, 31361, 1, 5, 13875, // 1, 4
+ 0, 5, 10528, 0, 6, 8645, 1, 5, 32624, 1, 6, 13739, // 1, 5
+ 0, 6, 9961, 0, 7, 8286, 1, 6, 33642, 1, 7, 13647, // 1, 6
+ 0, 7, 9534, 0, 8, 8024, 1, 7, 34340, 1, 8, 13638, // 1, 7
+ 1, 8, 34261, 1, 9, 13582, 2, 8, 9626, 2, 9, 8067, // 1, 8
+ 1, 9, 33585, 1, 10, 13548, 2, 9, 10074, 2, 10, 8329, // 1, 9
+ 1, 10, 32586, 1, 11, 13600, 2, 10, 10665, 2, 11, 8685, // 1,10
+ 1, 11, 31339, 1, 12, 13694, 2, 11, 11385, 2, 12, 9118, // 1,11
+ 1, 12, 29928, 1, 13, 13789, 2, 12, 12216, 2, 13, 9603, // 1,12
+ 1, 13, 28427, 1, 14, 13850, 2, 13, 13141, 2, 14, 10118, // 1,13
+ 1, 14, 26893, 1, 15, 13853, 2, 14, 14145, 2, 15, 10645, // 1,14
+ 1, 15, 25366, 1, 16, 13787, 2, 15, 15220, 2, 16, 11163, // 1,15
+ 1, 0, 14990, 1, 1, 10676, 2, 0, 26660, 2, 1, 13210, // 2, 0
+ 1, 1, 13850, 1, 2, 10119, 2, 1, 28427, 2, 2, 13140, // 2, 1
+ 1, 2, 12769, 1, 3, 9546, 2, 2, 30239, 2, 3, 12982, // 2, 2
+ 1, 3, 11760, 1, 4, 8976, 2, 3, 32052, 2, 4, 12748, // 2, 3
+ 1, 4, 10842, 1, 5, 8432, 2, 4, 33795, 2, 5, 12467, // 2, 4
+ 1, 5, 10041, 1, 6, 7943, 2, 5, 35364, 2, 6, 12188, // 2, 5
+ 1, 6, 9390, 1, 7, 7543, 2, 6, 36631, 2, 7, 11972, // 2, 6
+ 1, 7, 8918, 1, 8, 7266, 2, 7, 37470, 2, 8, 11882, // 2, 7
+ 2, 8, 37402, 2, 9, 11842, 3, 8, 8994, 3, 9, 7298, // 2, 8
+ 2, 9, 36582, 2, 10, 11897, 3, 9, 9484, 3, 10, 7573, // 2, 9
+ 2, 10, 35332, 2, 11, 12079, 3, 10, 10156, 3, 11, 7969, // 2,10
+ 2, 11, 33777, 2, 12, 12323, 3, 11, 10983, 3, 12, 8453, // 2,11
+ 2, 12, 32045, 2, 13, 12569, 3, 12, 11934, 3, 13, 8988, // 2,12
+ 2, 13, 30239, 2, 14, 12769, 3, 13, 12982, 3, 14, 9546, // 2,13
+ 2, 14, 28430, 2, 15, 12897, 3, 14, 14107, 3, 15, 10102, // 2,14
+ 2, 15, 26660, 2, 16, 12938, 3, 15, 15301, 3, 16, 10637, // 2,15
+ 2, 0, 15060, 2, 1, 10185, 3, 0, 27903, 3, 1, 12388, // 3, 0
+ 2, 1, 13789, 2, 2, 9603, 3, 1, 29928, 3, 2, 12216, // 3, 1
+ 2, 2, 12569, 2, 3, 8988, 3, 2, 32045, 3, 3, 11934, // 3, 2
+ 2, 3, 11411, 2, 4, 8358, 3, 3, 34213, 3, 4, 11554, // 3, 3
+ 2, 4, 10337, 2, 5, 7737, 3, 4, 36354, 3, 5, 11108, // 3, 4
+ 2, 5, 9388, 2, 6, 7165, 3, 5, 38330, 3, 6, 10653, // 3, 5
+ 2, 6, 8617, 2, 7, 6695, 3, 6, 39949, 3, 7, 10275, // 3, 6
+ 2, 7, 8082, 2, 8, 6381, 3, 7, 40994, 3, 8, 10079, // 3, 7
+ 3, 8, 40940, 3, 9, 10051, 4, 8, 8141, 4, 9, 6404, // 3, 8
+ 3, 9, 39912, 3, 10, 10221, 4, 9, 8690, 4, 10, 6713, // 3, 9
+ 3, 10, 38307, 3, 11, 10569, 4, 10, 9479, 4, 11, 7181, // 3,10
+ 3, 11, 36343, 3, 12, 10995, 4, 11, 10452, 4, 12, 7746, // 3,11
+ 3, 12, 34213, 3, 13, 11411, 4, 12, 11554, 4, 13, 8358, // 3,12
+ 3, 13, 32052, 3, 14, 11760, 4, 13, 12747, 4, 14, 8977, // 3,13
+ 3, 14, 29938, 3, 15, 12014, 4, 14, 14009, 4, 15, 9575, // 3,14
+ 3, 15, 27912, 3, 16, 12159, 4, 15, 15330, 4, 16, 10135, // 3,15
+ 3, 0, 15100, 3, 1, 9728, 4, 0, 29055, 4, 1, 11653, // 4, 0
+ 3, 1, 13694, 3, 2, 9118, 4, 1, 31339, 4, 2, 11385, // 4, 1
+ 3, 2, 12323, 3, 3, 8452, 4, 2, 33777, 4, 3, 10984, // 4, 2
+ 3, 3, 10995, 3, 4, 7746, 4, 3, 36343, 4, 4, 10452, // 4, 3
+ 3, 4, 9730, 3, 5, 7022, 4, 4, 38966, 4, 5, 9818, // 4, 4
+ 3, 5, 8578, 3, 6, 6328, 4, 5, 41487, 4, 6, 9143, // 4, 5
+ 3, 6, 7626, 3, 7, 5739, 4, 6, 43626, 4, 7, 8545, // 4, 6
+ 3, 7, 6987, 3, 8, 5354, 4, 7, 44999, 4, 8, 8196, // 4, 7
+ 4, 8, 44962, 4, 9, 8177, 5, 8, 7029, 5, 9, 5368, // 4, 8
+ 4, 9, 43602, 4, 10, 8507, 5, 9, 7678, 5, 10, 5749, // 4, 9
+ 4, 10, 41475, 4, 11, 9081, 5, 10, 8646, 5, 11, 6334, // 4,10
+ 4, 11, 38966, 4, 12, 9730, 5, 11, 9818, 5, 12, 7022, // 4,11
+ 4, 12, 36354, 4, 13, 10337, 5, 12, 11108, 5, 13, 7737, // 4,12
+ 4, 13, 33795, 4, 14, 10842, 5, 13, 12467, 5, 14, 8432, // 4,13
+ 4, 14, 31361, 4, 15, 11218, 5, 14, 13875, 5, 15, 9082, // 4,14
+ 4, 15, 29078, 4, 16, 11461, 5, 15, 15325, 5, 16, 9672, // 4,15
+ 4, 0, 15135, 4, 1, 9323, 5, 0, 30064, 5, 1, 11014, // 5, 0
+ 4, 1, 13600, 4, 2, 8685, 5, 1, 32586, 5, 2, 10665, // 5, 1
+ 4, 2, 12079, 4, 3, 7969, 5, 2, 35332, 5, 3, 10156, // 5, 2
+ 4, 3, 10569, 4, 4, 7180, 5, 3, 38307, 5, 4, 9480, // 5, 3
+ 4, 4, 9081, 4, 5, 6334, 5, 4, 41475, 5, 5, 8646, // 5, 4
+ 4, 5, 7659, 4, 6, 5472, 5, 5, 44700, 5, 6, 7705, // 5, 5
+ 4, 6, 6422, 4, 7, 4690, 5, 6, 47630, 5, 7, 6794, // 5, 6
+ 4, 7, 5590, 4, 8, 4164, 5, 7, 49588, 5, 8, 6194, // 5, 7
+ 5, 8, 49566, 5, 9, 6183, 6, 8, 5615, 6, 9, 4172, // 5, 8
+ 5, 9, 47619, 5, 10, 6768, 6, 9, 6455, 6, 10, 4694, // 5, 9
+ 5, 10, 44700, 5, 11, 7659, 6, 10, 7705, 6, 11, 5472, // 5,10
+ 5, 11, 41487, 5, 12, 8578, 6, 11, 9143, 6, 12, 6328, // 5,11
+ 5, 12, 38330, 5, 13, 9388, 6, 12, 10653, 6, 13, 7165, // 5,12
+ 5, 13, 35364, 5, 14, 10041, 6, 13, 12188, 6, 14, 7943, // 5,13
+ 5, 14, 32624, 5, 15, 10528, 6, 14, 13740, 6, 15, 8644, // 5,14
+ 5, 15, 30105, 5, 16, 10855, 6, 15, 15311, 6, 16, 9265, // 5,15
+ 5, 0, 15193, 5, 1, 8986, 6, 0, 30876, 6, 1, 10481, // 6, 0
+ 5, 1, 13548, 5, 2, 8329, 6, 1, 33585, 6, 2, 10074, // 6, 1
+ 5, 2, 11897, 5, 3, 7573, 6, 2, 36582, 6, 3, 9484, // 6, 2
+ 5, 3, 10221, 5, 4, 6714, 6, 3, 39912, 6, 4, 8689, // 6, 3
+ 5, 4, 8507, 5, 5, 5749, 6, 4, 43602, 6, 5, 7678, // 6, 4
+ 5, 5, 6768, 5, 6, 4694, 6, 5, 47619, 6, 6, 6455, // 6, 5
+ 5, 6, 5099, 5, 7, 3620, 6, 6, 51701, 6, 7, 5116, // 6, 6
+ 5, 7, 3853, 5, 8, 2795, 6, 7, 54839, 6, 8, 4049, // 6, 7
+ 6, 8, 54831, 6, 9, 4044, 7, 8, 3864, 7, 9, 2797, // 6, 8
+ 6, 9, 51701, 6, 10, 5099, 7, 9, 5116, 7, 10, 3620, // 6, 9
+ 6, 10, 47630, 6, 11, 6422, 7, 10, 6794, 7, 11, 4690, // 6,10
+ 6, 11, 43626, 6, 12, 7626, 7, 11, 8545, 7, 12, 5739, // 6,11
+ 6, 12, 39949, 6, 13, 8617, 7, 12, 10275, 7, 13, 6695, // 6,12
+ 6, 13, 36631, 6, 14, 9390, 7, 13, 11972, 7, 14, 7543, // 6,13
+ 6, 14, 33642, 6, 15, 9961, 7, 14, 13647, 7, 15, 8286, // 6,14
+ 6, 15, 30939, 6, 16, 10351, 7, 15, 15319, 7, 16, 8927, // 6,15
+ 6, 0, 15301, 6, 1, 8727, 7, 0, 31444, 7, 1, 10064, // 7, 0
+ 6, 1, 13582, 6, 2, 8068, 7, 1, 34261, 7, 2, 9625, // 7, 1
+ 6, 2, 11842, 6, 3, 7298, 7, 2, 37402, 7, 3, 8994, // 7, 2
+ 6, 3, 10051, 6, 4, 6403, 7, 3, 40940, 7, 4, 8142, // 7, 3
+ 6, 4, 8177, 6, 5, 5368, 7, 4, 44962, 7, 5, 7029, // 7, 4
+ 6, 5, 6183, 6, 6, 4172, 7, 5, 49566, 7, 6, 5615, // 7, 5
+ 6, 6, 4044, 6, 7, 2797, 7, 6, 54831, 7, 7, 3864, // 7, 6
+ 6, 7, 1903, 6, 8, 1347, 7, 7, 60382, 7, 8, 1904, // 7, 7
+ 7, 8, 60382, 7, 9, 1903, 8, 8, 1905, 8, 9, 1346, // 7, 8
+ 7, 9, 54839, 7, 10, 3853, 8, 9, 4049, 8, 10, 2795, // 7, 9
+ 7, 10, 49588, 7, 11, 5590, 8, 10, 6193, 8, 11, 4165, // 7,10
+ 7, 11, 44999, 7, 12, 6987, 8, 11, 8195, 8, 12, 5355, // 7,11
+ 7, 12, 40994, 7, 13, 8082, 8, 12, 10079, 8, 13, 6381, // 7,12
+ 7, 13, 37470, 7, 14, 8918, 8, 13, 11883, 8, 14, 7265, // 7,13
+ 7, 14, 34340, 7, 15, 9534, 8, 14, 13638, 8, 15, 8024, // 7,14
+ 7, 15, 31532, 7, 16, 9959, 8, 15, 15376, 8, 16, 8669, // 7,15
+ 7, -1, 8669, 7, 0, 15376, 8, -1, 9959, 8, 0, 31532, // 8, 0
+ 7, 0, 8024, 7, 1, 13638, 8, 0, 9534, 8, 1, 34340, // 8, 1
+ 7, 1, 7266, 7, 2, 11883, 8, 1, 8918, 8, 2, 37469, // 8, 2
+ 7, 2, 6381, 7, 3, 10079, 8, 2, 8082, 8, 3, 40994, // 8, 3
+ 7, 3, 5354, 7, 4, 8195, 8, 3, 6987, 8, 4, 45000, // 8, 4
+ 7, 4, 4164, 7, 5, 6193, 8, 4, 5590, 8, 5, 49589, // 8, 5
+ 7, 5, 2795, 7, 6, 4049, 8, 5, 3853, 8, 6, 54839, // 8, 6
+ 7, 6, 1347, 7, 7, 1905, 8, 6, 1903, 8, 7, 60381, // 8, 7
+ 8, 7, 1905, 8, 8, 60382, 9, 7, 1347, 9, 8, 1902, // 8, 8
+ 8, 8, 3864, 8, 9, 54831, 9, 8, 2797, 9, 9, 4044, // 8, 9
+ 8, 9, 5615, 8, 10, 49566, 9, 9, 4172, 9, 10, 6183, // 8,10
+ 8, 10, 7029, 8, 11, 44962, 9, 10, 5368, 9, 11, 8177, // 8,11
+ 8, 11, 8141, 8, 12, 40940, 9, 11, 6403, 9, 12, 10052, // 8,12
+ 8, 12, 8994, 8, 13, 37402, 9, 12, 7298, 9, 13, 11842, // 8,13
+ 8, 13, 9626, 8, 14, 34261, 9, 13, 8068, 9, 14, 13581, // 8,14
+ 8, 14, 10065, 8, 15, 31444, 9, 14, 8727, 9, 15, 15300, // 8,15
+ 8, -1, 8927, 8, 0, 15319, 9, -1, 10351, 9, 0, 30939, // 9, 0
+ 8, 0, 8286, 8, 1, 13647, 9, 0, 9961, 9, 1, 33642, // 9, 1
+ 8, 1, 7543, 8, 2, 11972, 9, 1, 9390, 9, 2, 36631, // 9, 2
+ 8, 2, 6695, 8, 3, 10275, 9, 2, 8617, 9, 3, 39949, // 9, 3
+ 8, 3, 5739, 8, 4, 8545, 9, 3, 7626, 9, 4, 43626, // 9, 4
+ 8, 4, 4690, 8, 5, 6794, 9, 4, 6422, 9, 5, 47630, // 9, 5
+ 8, 5, 3620, 8, 6, 5116, 9, 5, 5099, 9, 6, 51701, // 9, 6
+ 8, 6, 2797, 8, 7, 3864, 9, 6, 4044, 9, 7, 54831, // 9, 7
+ 9, 7, 4049, 9, 8, 54839, 10, 7, 2795, 10, 8, 3853, // 9, 8
+ 9, 8, 5116, 9, 9, 51701, 10, 8, 3620, 10, 9, 5099, // 9, 9
+ 9, 9, 6455, 9, 10, 47619, 10, 9, 4694, 10, 10, 6768, // 9,10
+ 9, 10, 7678, 9, 11, 43602, 10, 10, 5749, 10, 11, 8507, // 9,11
+ 9, 11, 8690, 9, 12, 39912, 10, 11, 6714, 10, 12, 10220, // 9,12
+ 9, 12, 9484, 9, 13, 36582, 10, 12, 7573, 10, 13, 11897, // 9,13
+ 9, 13, 10074, 9, 14, 33585, 10, 13, 8329, 10, 14, 13548, // 9,14
+ 9, 14, 10482, 9, 15, 30876, 10, 14, 8986, 10, 15, 15192, // 9,15
+ 9, -1, 9265, 9, 0, 15311, 10, -1, 10855, 10, 0, 30105, // 10, 0
+ 9, 0, 8645, 9, 1, 13740, 10, 0, 10528, 10, 1, 32623, // 10, 1
+ 9, 1, 7943, 9, 2, 12188, 10, 1, 10041, 10, 2, 35364, // 10, 2
+ 9, 2, 7165, 9, 3, 10653, 10, 2, 9388, 10, 3, 38330, // 10, 3
+ 9, 3, 6328, 9, 4, 9143, 10, 3, 8578, 10, 4, 41487, // 10, 4
+ 9, 4, 5472, 9, 5, 7705, 10, 4, 7659, 10, 5, 44700, // 10, 5
+ 9, 5, 4694, 9, 6, 6455, 10, 5, 6768, 10, 6, 47619, // 10, 6
+ 9, 6, 4172, 9, 7, 5615, 10, 6, 6183, 10, 7, 49566, // 10, 7
+ 10, 7, 6193, 10, 8, 49588, 11, 7, 4164, 11, 8, 5591, // 10, 8
+ 10, 8, 6794, 10, 9, 47630, 11, 8, 4690, 11, 9, 6422, // 10, 9
+ 10, 9, 7705, 10, 10, 44700, 11, 9, 5472, 11, 10, 7659, // 10,10
+ 10, 10, 8646, 10, 11, 41475, 11, 10, 6334, 11, 11, 9081, // 10,11
+ 10, 11, 9479, 10, 12, 38307, 11, 11, 7180, 11, 12, 10570, // 10,12
+ 10, 12, 10156, 10, 13, 35332, 11, 12, 7969, 11, 13, 12079, // 10,13
+ 10, 13, 10665, 10, 14, 32586, 11, 13, 8685, 11, 14, 13600, // 10,14
+ 10, 14, 11013, 10, 15, 30064, 11, 14, 9323, 11, 15, 15136, // 10,15
+ 10, -1, 9673, 10, 0, 15325, 11, -1, 11461, 11, 0, 29077, // 11, 0
+ 10, 0, 9082, 10, 1, 13875, 11, 0, 11218, 11, 1, 31361, // 11, 1
+ 10, 1, 8432, 10, 2, 12467, 11, 1, 10842, 11, 2, 33795, // 11, 2
+ 10, 2, 7737, 10, 3, 11108, 11, 2, 10337, 11, 3, 36354, // 11, 3
+ 10, 3, 7022, 10, 4, 9818, 11, 3, 9730, 11, 4, 38966, // 11, 4
+ 10, 4, 6334, 10, 5, 8646, 11, 4, 9081, 11, 5, 41475, // 11, 5
+ 10, 5, 5749, 10, 6, 7678, 11, 5, 8507, 11, 6, 43602, // 11, 6
+ 10, 6, 5368, 10, 7, 7029, 11, 6, 8177, 11, 7, 44962, // 11, 7
+ 11, 7, 8195, 11, 8, 44999, 12, 7, 5354, 12, 8, 6988, // 11, 8
+ 11, 8, 8545, 11, 9, 43626, 12, 8, 5739, 12, 9, 7626, // 11, 9
+ 11, 9, 9143, 11, 10, 41487, 12, 9, 6328, 12, 10, 8578, // 11,10
+ 11, 10, 9818, 11, 11, 38966, 12, 10, 7022, 12, 11, 9730, // 11,11
+ 11, 11, 10452, 11, 12, 36343, 12, 11, 7746, 12, 12, 10995, // 11,12
+ 11, 12, 10983, 11, 13, 33777, 12, 12, 8452, 12, 13, 12324, // 11,13
+ 11, 13, 11385, 11, 14, 31339, 12, 13, 9118, 12, 14, 13694, // 11,14
+ 11, 14, 11652, 11, 15, 29055, 12, 14, 9728, 12, 15, 15101, // 11,15
+ 11, -1, 10135, 11, 0, 15330, 12, -1, 12159, 12, 0, 27912, // 12, 0
+ 11, 0, 9575, 11, 1, 14009, 12, 0, 12014, 12, 1, 29938, // 12, 1
+ 11, 1, 8976, 11, 2, 12747, 12, 1, 11760, 12, 2, 32053, // 12, 2
+ 11, 2, 8358, 11, 3, 11554, 12, 2, 11411, 12, 3, 34213, // 12, 3
+ 11, 3, 7746, 11, 4, 10452, 12, 3, 10995, 12, 4, 36343, // 12, 4
+ 11, 4, 7180, 11, 5, 9479, 12, 4, 10569, 12, 5, 38308, // 12, 5
+ 11, 5, 6714, 11, 6, 8690, 12, 5, 10221, 12, 6, 39911, // 12, 6
+ 11, 6, 6403, 11, 7, 8141, 12, 6, 10051, 12, 7, 40941, // 12, 7
+ 12, 7, 10079, 12, 8, 40994, 13, 7, 6381, 13, 8, 8082, // 12, 8
+ 12, 8, 10275, 12, 9, 39949, 13, 8, 6695, 13, 9, 8617, // 12, 9
+ 12, 9, 10653, 12, 10, 38330, 13, 9, 7165, 13, 10, 9388, // 12,10
+ 12, 10, 11108, 12, 11, 36354, 13, 10, 7737, 13, 11, 10337, // 12,11
+ 12, 11, 11554, 12, 12, 34213, 13, 11, 8358, 13, 12, 11411, // 12,12
+ 12, 12, 11934, 12, 13, 32045, 13, 12, 8988, 13, 13, 12569, // 12,13
+ 12, 13, 12216, 12, 14, 29928, 13, 13, 9603, 13, 14, 13789, // 12,14
+ 12, 14, 12388, 12, 15, 27903, 13, 14, 10185, 13, 15, 15060, // 12,15
+ 12, -1, 10637, 12, 0, 15301, 13, -1, 12938, 13, 0, 26660, // 13, 0
+ 12, 0, 10102, 12, 1, 14107, 13, 0, 12897, 13, 1, 28430, // 13, 1
+ 12, 1, 9546, 12, 2, 12982, 13, 1, 12769, 13, 2, 30239, // 13, 2
+ 12, 2, 8988, 12, 3, 11934, 13, 2, 12569, 13, 3, 32045, // 13, 3
+ 12, 3, 8452, 12, 4, 10983, 13, 3, 12323, 13, 4, 33778, // 13, 4
+ 12, 4, 7969, 12, 5, 10156, 13, 4, 12079, 13, 5, 35332, // 13, 5
+ 12, 5, 7573, 12, 6, 9484, 13, 5, 11897, 13, 6, 36582, // 13, 6
+ 12, 6, 7298, 12, 7, 8994, 13, 6, 11842, 13, 7, 37402, // 13, 7
+ 13, 7, 11883, 13, 8, 37470, 14, 7, 7266, 14, 8, 8917, // 13, 8
+ 13, 8, 11972, 13, 9, 36631, 14, 8, 7543, 14, 9, 9390, // 13, 9
+ 13, 9, 12188, 13, 10, 35364, 14, 9, 7943, 14, 10, 10041, // 13,10
+ 13, 10, 12467, 13, 11, 33795, 14, 10, 8432, 14, 11, 10842, // 13,11
+ 13, 11, 12747, 13, 12, 32052, 14, 11, 8976, 14, 12, 11761, // 13,12
+ 13, 12, 12982, 13, 13, 30239, 14, 12, 9546, 14, 13, 12769, // 13,13
+ 13, 13, 13141, 13, 14, 28427, 14, 13, 10119, 14, 14, 13849, // 13,14
+ 13, 14, 13211, 13, 15, 26660, 14, 14, 10676, 14, 15, 14989, // 13,15
+ 13, -1, 11164, 13, 0, 15220, 14, -1, 13787, 14, 0, 25365, // 14, 0
+ 13, 0, 10644, 13, 1, 14145, 14, 0, 13853, 14, 1, 26894, // 14, 1
+ 13, 1, 10119, 13, 2, 13141, 14, 1, 13850, 14, 2, 28426, // 14, 2
+ 13, 2, 9603, 13, 3, 12216, 14, 2, 13789, 14, 3, 29928, // 14, 3
+ 13, 3, 9118, 13, 4, 11385, 14, 3, 13694, 14, 4, 31339, // 14, 4
+ 13, 4, 8685, 13, 5, 10665, 14, 4, 13600, 14, 5, 32586, // 14, 5
+ 13, 5, 8329, 13, 6, 10074, 14, 5, 13548, 14, 6, 33585, // 14, 6
+ 13, 6, 8068, 13, 7, 9626, 14, 6, 13582, 14, 7, 34260, // 14, 7
+ 14, 7, 13638, 14, 8, 34340, 15, 7, 8024, 15, 8, 9534, // 14, 8
+ 14, 8, 13647, 14, 9, 33642, 15, 8, 8286, 15, 9, 9961, // 14, 9
+ 14, 9, 13740, 14, 10, 32624, 15, 9, 8645, 15, 10, 10527, // 14,10
+ 14, 10, 13875, 14, 11, 31361, 15, 10, 9082, 15, 11, 11218, // 14,11
+ 14, 11, 14009, 14, 12, 29938, 15, 11, 9575, 15, 12, 12014, // 14,12
+ 14, 12, 14107, 14, 13, 28430, 15, 12, 10102, 15, 13, 12897, // 14,13
+ 14, 13, 14145, 14, 14, 26893, 15, 13, 10644, 15, 14, 13854, // 14,14
+ 14, 14, 14109, 14, 15, 25368, 15, 14, 11187, 15, 15, 14872, // 14,15
+ 14, -1, 11702, 14, 0, 15076, 15, -1, 14696, 15, 0, 24062, // 15, 0
+ 14, 0, 11187, 14, 1, 14109, 15, 0, 14872, 15, 1, 25368, // 15, 1
+ 14, 1, 10676, 14, 2, 13211, 15, 1, 14990, 15, 2, 26659, // 15, 2
+ 14, 2, 10185, 14, 3, 12388, 15, 2, 15060, 15, 3, 27903, // 15, 3
+ 14, 3, 9728, 14, 4, 11652, 15, 3, 15100, 15, 4, 29056, // 15, 4
+ 14, 4, 9323, 14, 5, 11013, 15, 4, 15135, 15, 5, 30065, // 15, 5
+ 14, 5, 8986, 14, 6, 10482, 15, 5, 15193, 15, 6, 30875, // 15, 6
+ 14, 6, 8727, 14, 7, 10065, 15, 6, 15301, 15, 7, 31443, // 15, 7
+ 15, 7, 15376, 15, 8, 31532, 16, 7, 8669, 16, 8, 9959, // 15, 8
+ 15, 8, 15319, 15, 9, 30939, 16, 8, 8927, 16, 9, 10351, // 15, 9
+ 15, 9, 15311, 15, 10, 30105, 16, 9, 9265, 16, 10, 10855, // 15,10
+ 15, 10, 15325, 15, 11, 29078, 16, 10, 9673, 16, 11, 11460, // 15,11
+ 15, 11, 15330, 15, 12, 27912, 16, 11, 10135, 16, 12, 12159, // 15,12
+ 15, 12, 15301, 15, 13, 26660, 16, 12, 10637, 16, 13, 12938, // 15,13
+ 15, 13, 15220, 15, 14, 25366, 16, 13, 11164, 16, 14, 13786, // 15,14
+ 15, 14, 15076, 15, 15, 24063, 16, 14, 11702, 16, 15, 14695, // 15,15
+ // angle of -2.0 degrees
+ -1, 0, 13368, -1, 1, 10104, 0, 0, 28495, 0, 1, 13569, // 0, 0
+ -1, 1, 12574, -1, 2, 9662, 0, 1, 29831, 0, 2, 13469, // 0, 1
+ -1, 2, 11829, -1, 3, 9229, 0, 2, 31146, 0, 3, 13332, // 0, 2
+ -1, 3, 11143, -1, 4, 8816, 0, 3, 32406, 0, 4, 13171, // 0, 3
+ -1, 4, 10528, -1, 5, 8438, 0, 4, 33564, 0, 5, 13006, // 0, 4
+ -1, 5, 9995, -1, 6, 8107, 0, 5, 34567, 0, 6, 12867, // 0, 5
+ -1, 6, 9558, -1, 7, 7839, 0, 6, 35362, 0, 7, 12777, // 0, 6
+ -1, 7, 9224, -1, 8, 7643, 0, 7, 35905, 0, 8, 12764, // 0, 7
+ 0, 8, 35844, 0, 9, 12728, 1, 8, 9290, 1, 9, 7674, // 0, 8
+ 0, 9, 35315, 0, 10, 12717, 1, 9, 9635, 1, 10, 7869, // 0, 9
+ 0, 10, 34532, 0, 11, 12783, 1, 10, 10086, 1, 11, 8135, // 0,10
+ 0, 11, 33539, 0, 12, 12899, 1, 11, 10635, 1, 12, 8463, // 0,11
+ 0, 12, 32391, 0, 13, 13038, 1, 12, 11269, 1, 13, 8838, // 0,12
+ 0, 13, 31138, 0, 14, 13176, 1, 13, 11977, 1, 14, 9245, // 0,13
+ 0, 14, 29828, 0, 15, 13291, 1, 14, 12746, 1, 15, 9671, // 0,14
+ 0, 15, 28495, 0, 16, 13368, 1, 15, 13569, 1, 16, 10104, // 0,15
+ 0, 0, 13291, 0, 1, 9671, 1, 0, 29828, 1, 1, 12746, // 1, 0
+ 0, 1, 12412, 0, 2, 9202, 1, 1, 31358, 1, 2, 12564, // 1, 1
+ 0, 2, 11580, 0, 3, 8735, 1, 2, 32886, 1, 3, 12335, // 1, 2
+ 0, 3, 10808, 0, 4, 8284, 1, 3, 34369, 1, 4, 12075, // 1, 3
+ 0, 4, 10111, 0, 5, 7865, 1, 4, 35750, 1, 5, 11810, // 1, 4
+ 0, 5, 9509, 0, 6, 7497, 1, 5, 36955, 1, 6, 11575, // 1, 5
+ 0, 6, 9020, 0, 7, 7202, 1, 6, 37906, 1, 7, 11408, // 1, 6
+ 0, 7, 8662, 0, 8, 6997, 1, 7, 38534, 1, 8, 11343, // 1, 7
+ 1, 8, 38481, 1, 9, 11317, 2, 8, 8718, 2, 9, 7020, // 1, 8
+ 1, 9, 37866, 1, 10, 11360, 2, 9, 9086, 2, 10, 7224, // 1, 9
+ 1, 10, 36926, 1, 11, 11507, 2, 10, 9587, 2, 11, 7516, // 1,10
+ 1, 11, 35730, 1, 12, 11721, 2, 11, 10204, 2, 12, 7881, // 1,11
+ 1, 12, 34358, 1, 13, 11964, 2, 12, 10918, 2, 13, 8296, // 1,12
+ 1, 13, 32881, 1, 14, 12203, 2, 13, 11709, 2, 14, 8743, // 1,13
+ 1, 14, 31358, 1, 15, 12412, 2, 14, 12564, 2, 15, 9202, // 1,14
+ 1, 15, 29831, 1, 16, 12574, 2, 15, 13470, 2, 16, 9661, // 1,15
+ 1, 0, 13176, 1, 1, 9245, 2, 0, 31138, 2, 1, 11977, // 2, 0
+ 1, 1, 12203, 1, 2, 8742, 2, 1, 32881, 2, 2, 11710, // 2, 1
+ 1, 2, 11272, 1, 3, 8232, 2, 2, 34650, 2, 3, 11382, // 2, 2
+ 1, 3, 10397, 1, 4, 7728, 2, 3, 36399, 2, 4, 11012, // 2, 3
+ 1, 4, 9597, 1, 5, 7252, 2, 4, 38057, 2, 5, 10630, // 2, 4
+ 1, 5, 8902, 1, 6, 6829, 2, 5, 39526, 2, 6, 10279, // 2, 5
+ 1, 6, 8344, 1, 7, 6491, 2, 6, 40688, 2, 7, 10013, // 2, 6
+ 1, 7, 7951, 1, 8, 6266, 2, 7, 41432, 2, 8, 9887, // 2, 7
+ 2, 8, 41389, 2, 9, 9867, 3, 8, 7996, 3, 9, 6284, // 2, 8
+ 2, 9, 40656, 2, 10, 9977, 3, 9, 8397, 3, 10, 6506, // 2, 9
+ 2, 10, 39503, 2, 11, 10226, 3, 10, 8966, 3, 11, 6841, // 2,10
+ 2, 11, 38042, 2, 12, 10559, 3, 11, 9674, 3, 12, 7261, // 2,11
+ 2, 12, 36392, 2, 13, 10922, 3, 12, 10488, 3, 13, 7734, // 2,12
+ 2, 13, 34650, 2, 14, 11272, 3, 13, 11382, 3, 14, 8232, // 2,13
+ 2, 14, 32886, 2, 15, 11580, 3, 14, 12334, 3, 15, 8736, // 2,14
+ 2, 15, 31146, 2, 16, 11829, 3, 15, 13332, 3, 16, 9229, // 2,15
+ 2, 0, 13038, 2, 1, 8838, 3, 0, 32391, 3, 1, 11269, // 3, 0
+ 2, 1, 11964, 2, 2, 8296, 3, 1, 34358, 3, 2, 10918, // 3, 1
+ 2, 2, 10922, 2, 3, 7734, 3, 2, 36392, 3, 3, 10488, // 3, 2
+ 2, 3, 9924, 2, 4, 7164, 3, 3, 38450, 3, 4, 9998, // 3, 3
+ 2, 4, 8995, 2, 5, 6611, 3, 4, 40452, 3, 5, 9478, // 3, 4
+ 2, 5, 8175, 2, 6, 6108, 3, 5, 42271, 3, 6, 8982, // 3, 5
+ 2, 6, 7516, 2, 7, 5703, 3, 6, 43733, 3, 7, 8584, // 3, 6
+ 2, 7, 7072, 2, 8, 5443, 3, 7, 44649, 3, 8, 8372, // 3, 7
+ 3, 8, 44616, 3, 9, 8359, 4, 8, 7106, 4, 9, 5455, // 3, 8
+ 3, 9, 43710, 3, 10, 8558, 4, 9, 7556, 4, 10, 5712, // 3, 9
+ 3, 10, 42256, 3, 11, 8940, 4, 10, 8224, 4, 11, 6116, // 3,10
+ 3, 11, 40444, 3, 12, 9421, 4, 11, 9056, 4, 12, 6615, // 3,11
+ 3, 12, 38450, 3, 13, 9924, 4, 12, 9998, 4, 13, 7164, // 3,12
+ 3, 13, 36399, 3, 14, 10397, 4, 13, 11012, 4, 14, 7728, // 3,13
+ 3, 14, 34369, 3, 15, 10808, 4, 14, 12074, 4, 15, 8285, // 3,14
+ 3, 15, 32406, 3, 16, 11143, 4, 15, 13171, 4, 16, 8816, // 3,15
+ 3, 0, 12899, 3, 1, 8463, 4, 0, 33539, 4, 1, 10635, // 4, 0
+ 3, 1, 11721, 3, 2, 7881, 4, 1, 35730, 4, 2, 10204, // 4, 1
+ 3, 2, 10559, 3, 3, 7261, 4, 2, 38042, 4, 3, 9674, // 4, 2
+ 3, 3, 9421, 3, 4, 6615, 4, 3, 40444, 4, 4, 9056, // 4, 3
+ 3, 4, 8332, 3, 5, 5965, 4, 4, 42861, 4, 5, 8378, // 4, 4
+ 3, 5, 7342, 3, 6, 5350, 4, 5, 45146, 4, 6, 7698, // 4, 5
+ 3, 6, 6530, 3, 7, 4838, 4, 6, 47049, 4, 7, 7119, // 4, 6
+ 3, 7, 6000, 3, 8, 4513, 4, 7, 48240, 4, 8, 6783, // 4, 7
+ 4, 8, 48218, 4, 9, 6774, 5, 8, 6023, 5, 9, 4521, // 4, 8
+ 4, 9, 47035, 4, 10, 7100, 5, 9, 6558, 5, 10, 4843, // 4, 9
+ 4, 10, 45139, 4, 11, 7667, 5, 10, 7377, 5, 11, 5353, // 4,10
+ 4, 11, 42861, 4, 12, 8332, 5, 11, 8378, 5, 12, 5965, // 4,11
+ 4, 12, 40452, 4, 13, 8995, 5, 12, 9478, 5, 13, 6611, // 4,12
+ 4, 13, 38057, 4, 14, 9597, 5, 13, 10630, 5, 14, 7252, // 4,13
+ 4, 14, 35750, 4, 15, 10111, 5, 14, 11810, 5, 15, 7865, // 4,14
+ 4, 15, 33564, 4, 16, 10528, 5, 15, 13007, 5, 16, 8437, // 4,15
+ 4, 0, 12783, 4, 1, 8135, 5, 0, 34532, 5, 1, 10086, // 5, 0
+ 4, 1, 11507, 4, 2, 7517, 5, 1, 36926, 5, 2, 9586, // 5, 1
+ 4, 2, 10226, 4, 3, 6842, 5, 2, 39503, 5, 3, 8965, // 5, 2
+ 4, 3, 8940, 4, 4, 6116, 5, 3, 42256, 5, 4, 8224, // 5, 3
+ 4, 4, 7667, 4, 5, 5353, 5, 4, 45139, 5, 5, 7377, // 5, 4
+ 4, 5, 6451, 4, 6, 4591, 5, 5, 48019, 5, 6, 6475, // 5, 5
+ 4, 6, 5400, 4, 7, 3911, 5, 6, 50587, 5, 7, 5638, // 5, 6
+ 4, 7, 4708, 4, 8, 3466, 5, 7, 52266, 5, 8, 5096, // 5, 7
+ 5, 8, 52253, 5, 9, 5092, 6, 8, 4721, 6, 9, 3470, // 5, 8
+ 5, 9, 50581, 5, 10, 5624, 6, 9, 5418, 6, 10, 3913, // 5, 9
+ 5, 10, 48019, 5, 11, 6451, 6, 10, 6475, 6, 11, 4591, // 5,10
+ 5, 11, 45146, 5, 12, 7342, 6, 11, 7698, 6, 12, 5350, // 5,11
+ 5, 12, 42271, 5, 13, 8175, 6, 12, 8982, 6, 13, 6108, // 5,12
+ 5, 13, 39526, 5, 14, 8902, 6, 13, 10279, 6, 14, 6829, // 5,13
+ 5, 14, 36955, 5, 15, 9509, 6, 14, 11575, 6, 15, 7497, // 5,14
+ 5, 15, 34567, 5, 16, 9995, 6, 15, 12867, 6, 16, 8107, // 5,15
+ 5, 0, 12717, 5, 1, 7868, 6, 0, 35315, 6, 1, 9636, // 6, 0
+ 5, 1, 11360, 5, 2, 7224, 6, 1, 37866, 6, 2, 9086, // 6, 1
+ 5, 2, 9977, 5, 3, 6506, 6, 2, 40656, 6, 3, 8397, // 6, 2
+ 5, 3, 8558, 5, 4, 5712, 6, 3, 43710, 6, 4, 7556, // 6, 3
+ 5, 4, 7100, 5, 5, 4843, 6, 4, 47035, 6, 5, 6558, // 6, 4
+ 5, 5, 5624, 5, 6, 3913, 6, 5, 50581, 6, 6, 5418, // 6, 5
+ 5, 6, 4217, 5, 7, 2989, 6, 6, 54105, 6, 7, 4225, // 6, 6
+ 5, 7, 3180, 5, 8, 2294, 6, 7, 56756, 6, 8, 3306, // 6, 7
+ 6, 8, 56751, 6, 9, 3303, 7, 8, 3186, 7, 9, 2296, // 6, 8
+ 6, 9, 54105, 6, 10, 4217, 7, 9, 4225, 7, 10, 2989, // 6, 9
+ 6, 10, 50587, 6, 11, 5400, 7, 10, 5637, 7, 11, 3912, // 6,10
+ 6, 11, 47049, 6, 12, 6530, 7, 11, 7119, 7, 12, 4838, // 6,11
+ 6, 12, 43733, 6, 13, 7516, 7, 12, 8584, 7, 13, 5703, // 6,12
+ 6, 13, 40688, 6, 14, 8344, 7, 13, 10013, 7, 14, 6491, // 6,13
+ 6, 14, 37906, 6, 15, 9020, 7, 14, 11407, 7, 15, 7203, // 6,14
+ 6, 15, 35362, 6, 16, 9558, 7, 15, 12777, 7, 16, 7839, // 6,15
+ 6, 0, 12728, 6, 1, 7674, 7, 0, 35844, 7, 1, 9290, // 7, 0
+ 6, 1, 11317, 6, 2, 7020, 7, 1, 38481, 7, 2, 8718, // 7, 1
+ 6, 2, 9867, 6, 3, 6284, 7, 2, 41389, 7, 3, 7996, // 7, 2
+ 6, 3, 8359, 6, 4, 5454, 7, 3, 44616, 7, 4, 7107, // 7, 3
+ 6, 4, 6774, 6, 5, 4521, 7, 4, 48218, 7, 5, 6023, // 7, 4
+ 6, 5, 5092, 6, 6, 3470, 7, 5, 52253, 7, 6, 4721, // 7, 5
+ 6, 6, 3303, 6, 7, 2295, 7, 6, 56751, 7, 7, 3187, // 7, 6
+ 6, 7, 1541, 6, 8, 1090, 7, 7, 61364, 7, 8, 1541, // 7, 7
+ 7, 8, 61364, 7, 9, 1541, 8, 8, 1542, 8, 9, 1089, // 7, 8
+ 7, 9, 56756, 7, 10, 3180, 8, 9, 3306, 8, 10, 2294, // 7, 9
+ 7, 10, 52266, 7, 11, 4708, 8, 10, 5097, 8, 11, 3465, // 7,10
+ 7, 11, 48240, 7, 12, 6000, 8, 11, 6783, 8, 12, 4513, // 7,11
+ 7, 12, 44649, 7, 13, 7072, 8, 12, 8373, 8, 13, 5442, // 7,12
+ 7, 13, 41432, 7, 14, 7951, 8, 13, 9886, 8, 14, 6267, // 7,13
+ 7, 14, 38534, 7, 15, 8662, 8, 14, 11344, 8, 15, 6996, // 7,14
+ 7, 15, 35905, 7, 16, 9224, 8, 15, 12764, 8, 16, 7643, // 7,15
+ 7, -1, 7643, 7, 0, 12764, 8, -1, 9224, 8, 0, 35905, // 8, 0
+ 7, 0, 6997, 7, 1, 11344, 8, 0, 8662, 8, 1, 38533, // 8, 1
+ 7, 1, 6266, 7, 2, 9886, 8, 1, 7951, 8, 2, 41433, // 8, 2
+ 7, 2, 5443, 7, 3, 8373, 8, 2, 7072, 8, 3, 44648, // 8, 3
+ 7, 3, 4513, 7, 4, 6783, 8, 3, 6000, 8, 4, 48240, // 8, 4
+ 7, 4, 3466, 7, 5, 5097, 8, 4, 4708, 8, 5, 52265, // 8, 5
+ 7, 5, 2294, 7, 6, 3306, 8, 5, 3180, 8, 6, 56756, // 8, 6
+ 7, 6, 1090, 7, 7, 1542, 8, 6, 1541, 8, 7, 61363, // 8, 7
+ 8, 7, 1542, 8, 8, 61364, 9, 7, 1090, 9, 8, 1540, // 8, 8
+ 8, 8, 3186, 8, 9, 56751, 9, 8, 2295, 9, 9, 3304, // 8, 9
+ 8, 9, 4721, 8, 10, 52253, 9, 9, 3470, 9, 10, 5092, // 8,10
+ 8, 10, 6023, 8, 11, 48218, 9, 10, 4521, 9, 11, 6774, // 8,11
+ 8, 11, 7106, 8, 12, 44616, 9, 11, 5454, 9, 12, 8360, // 8,12
+ 8, 12, 7996, 8, 13, 41389, 9, 12, 6284, 9, 13, 9867, // 8,13
+ 8, 13, 8718, 8, 14, 38481, 9, 13, 7020, 9, 14, 11317, // 8,14
+ 8, 14, 9290, 8, 15, 35844, 9, 14, 7674, 9, 15, 12728, // 8,15
+ 8, -1, 7839, 8, 0, 12777, 9, -1, 9558, 9, 0, 35362, // 9, 0
+ 8, 0, 7202, 8, 1, 11407, 9, 0, 9020, 9, 1, 37907, // 9, 1
+ 8, 1, 6491, 8, 2, 10013, 9, 1, 8344, 9, 2, 40688, // 9, 2
+ 8, 2, 5703, 8, 3, 8584, 9, 2, 7516, 9, 3, 43733, // 9, 3
+ 8, 3, 4838, 8, 4, 7119, 9, 3, 6530, 9, 4, 47049, // 9, 4
+ 8, 4, 3911, 8, 5, 5637, 9, 4, 5400, 9, 5, 50588, // 9, 5
+ 8, 5, 2989, 8, 6, 4225, 9, 5, 4217, 9, 6, 54105, // 9, 6
+ 8, 6, 2295, 8, 7, 3186, 9, 6, 3303, 9, 7, 56752, // 9, 7
+ 9, 7, 3306, 9, 8, 56756, 10, 7, 2294, 10, 8, 3180, // 9, 8
+ 9, 8, 4225, 9, 9, 54105, 10, 8, 2989, 10, 9, 4217, // 9, 9
+ 9, 9, 5418, 9, 10, 50581, 10, 9, 3913, 10, 10, 5624, // 9,10
+ 9, 10, 6558, 9, 11, 47035, 10, 10, 4843, 10, 11, 7100, // 9,11
+ 9, 11, 7556, 9, 12, 43710, 10, 11, 5712, 10, 12, 8558, // 9,12
+ 9, 12, 8397, 9, 13, 40656, 10, 12, 6506, 10, 13, 9977, // 9,13
+ 9, 13, 9086, 9, 14, 37866, 10, 13, 7224, 10, 14, 11360, // 9,14
+ 9, 14, 9635, 9, 15, 35315, 10, 14, 7868, 10, 15, 12718, // 9,15
+ 9, -1, 8107, 9, 0, 12867, 10, -1, 9995, 10, 0, 34567, // 10, 0
+ 9, 0, 7497, 9, 1, 11575, 10, 0, 9509, 10, 1, 36955, // 10, 1
+ 9, 1, 6829, 9, 2, 10279, 10, 1, 8902, 10, 2, 39526, // 10, 2
+ 9, 2, 6108, 9, 3, 8982, 10, 2, 8175, 10, 3, 42271, // 10, 3
+ 9, 3, 5350, 9, 4, 7698, 10, 3, 7342, 10, 4, 45146, // 10, 4
+ 9, 4, 4591, 9, 5, 6475, 10, 4, 6451, 10, 5, 48019, // 10, 5
+ 9, 5, 3913, 9, 6, 5418, 10, 5, 5624, 10, 6, 50581, // 10, 6
+ 9, 6, 3470, 9, 7, 4721, 10, 6, 5092, 10, 7, 52253, // 10, 7
+ 10, 7, 5097, 10, 8, 52266, 11, 7, 3466, 11, 8, 4707, // 10, 8
+ 10, 8, 5637, 10, 9, 50587, 11, 8, 3911, 11, 9, 5401, // 10, 9
+ 10, 9, 6475, 10, 10, 48019, 11, 9, 4591, 11, 10, 6451, // 10,10
+ 10, 10, 7377, 10, 11, 45139, 11, 10, 5353, 11, 11, 7667, // 10,11
+ 10, 11, 8224, 10, 12, 42256, 11, 11, 6116, 11, 12, 8940, // 10,12
+ 10, 12, 8966, 10, 13, 39503, 11, 12, 6842, 11, 13, 10225, // 10,13
+ 10, 13, 9587, 10, 14, 36926, 11, 13, 7517, 11, 14, 11506, // 10,14
+ 10, 14, 10086, 10, 15, 34532, 11, 14, 8135, 11, 15, 12783, // 10,15
+ 10, -1, 8438, 10, 0, 13007, 11, -1, 10528, 11, 0, 33563, // 11, 0
+ 10, 0, 7865, 10, 1, 11810, 11, 0, 10111, 11, 1, 35750, // 11, 1
+ 10, 1, 7252, 10, 2, 10630, 11, 1, 9597, 11, 2, 38057, // 11, 2
+ 10, 2, 6611, 10, 3, 9478, 11, 2, 8995, 11, 3, 40452, // 11, 3
+ 10, 3, 5965, 10, 4, 8378, 11, 3, 8332, 11, 4, 42861, // 11, 4
+ 10, 4, 5353, 10, 5, 7377, 11, 4, 7667, 11, 5, 45139, // 11, 5
+ 10, 5, 4843, 10, 6, 6558, 11, 5, 7100, 11, 6, 47035, // 11, 6
+ 10, 6, 4521, 10, 7, 6023, 11, 6, 6774, 11, 7, 48218, // 11, 7
+ 11, 7, 6783, 11, 8, 48240, 12, 7, 4513, 12, 8, 6000, // 11, 8
+ 11, 8, 7119, 11, 9, 47049, 12, 8, 4838, 12, 9, 6530, // 11, 9
+ 11, 9, 7698, 11, 10, 45146, 12, 9, 5350, 12, 10, 7342, // 11,10
+ 11, 10, 8378, 11, 11, 42861, 12, 10, 5965, 12, 11, 8332, // 11,11
+ 11, 11, 9056, 11, 12, 40444, 12, 11, 6615, 12, 12, 9421, // 11,12
+ 11, 12, 9674, 11, 13, 38042, 12, 12, 7261, 12, 13, 10559, // 11,13
+ 11, 13, 10204, 11, 14, 35730, 12, 13, 7881, 12, 14, 11721, // 11,14
+ 11, 14, 10635, 11, 15, 33539, 12, 14, 8463, 12, 15, 12899, // 11,15
+ 11, -1, 8816, 11, 0, 13171, 12, -1, 11143, 12, 0, 32406, // 12, 0
+ 11, 0, 8284, 11, 1, 12074, 12, 0, 10808, 12, 1, 34370, // 12, 1
+ 11, 1, 7728, 11, 2, 11012, 12, 1, 10397, 12, 2, 36399, // 12, 2
+ 11, 2, 7164, 11, 3, 9998, 12, 2, 9924, 12, 3, 38450, // 12, 3
+ 11, 3, 6615, 11, 4, 9056, 12, 3, 9421, 12, 4, 40444, // 12, 4
+ 11, 4, 6116, 11, 5, 8224, 12, 4, 8940, 12, 5, 42256, // 12, 5
+ 11, 5, 5712, 11, 6, 7556, 12, 5, 8558, 12, 6, 43710, // 12, 6
+ 11, 6, 5454, 11, 7, 7106, 12, 6, 8359, 12, 7, 44617, // 12, 7
+ 12, 7, 8373, 12, 8, 44649, 13, 7, 5443, 13, 8, 7071, // 12, 8
+ 12, 8, 8584, 12, 9, 43733, 13, 8, 5703, 13, 9, 7516, // 12, 9
+ 12, 9, 8982, 12, 10, 42271, 13, 9, 6108, 13, 10, 8175, // 12,10
+ 12, 10, 9478, 12, 11, 40452, 13, 10, 6611, 13, 11, 8995, // 12,11
+ 12, 11, 9998, 12, 12, 38450, 13, 11, 7164, 13, 12, 9924, // 12,12
+ 12, 12, 10488, 12, 13, 36392, 13, 12, 7734, 13, 13, 10922, // 12,13
+ 12, 13, 10918, 12, 14, 34358, 13, 13, 8296, 13, 14, 11964, // 12,14
+ 12, 14, 11269, 12, 15, 32391, 13, 14, 8838, 13, 15, 13038, // 12,15
+ 12, -1, 9229, 12, 0, 13332, 13, -1, 11829, 13, 0, 31146, // 13, 0
+ 12, 0, 8735, 12, 1, 12334, 13, 0, 11580, 13, 1, 32887, // 13, 1
+ 12, 1, 8232, 12, 2, 11382, 13, 1, 11272, 13, 2, 34650, // 13, 2
+ 12, 2, 7734, 12, 3, 10488, 13, 2, 10922, 13, 3, 36392, // 13, 3
+ 12, 3, 7261, 12, 4, 9674, 13, 3, 10559, 13, 4, 38042, // 13, 4
+ 12, 4, 6842, 12, 5, 8966, 13, 4, 10226, 13, 5, 39502, // 13, 5
+ 12, 5, 6506, 12, 6, 8397, 13, 5, 9977, 13, 6, 40656, // 13, 6
+ 12, 6, 6284, 12, 7, 7996, 13, 6, 9867, 13, 7, 41389, // 13, 7
+ 13, 7, 9886, 13, 8, 41432, 14, 7, 6266, 14, 8, 7952, // 13, 8
+ 13, 8, 10013, 13, 9, 40688, 14, 8, 6491, 14, 9, 8344, // 13, 9
+ 13, 9, 10279, 13, 10, 39526, 14, 9, 6829, 14, 10, 8902, // 13,10
+ 13, 10, 10630, 13, 11, 38057, 14, 10, 7252, 14, 11, 9597, // 13,11
+ 13, 11, 11012, 13, 12, 36399, 14, 11, 7728, 14, 12, 10397, // 13,12
+ 13, 12, 11382, 13, 13, 34650, 14, 12, 8232, 14, 13, 11272, // 13,13
+ 13, 13, 11709, 13, 14, 32881, 14, 13, 8742, 14, 14, 12204, // 13,14
+ 13, 14, 11977, 13, 15, 31138, 14, 14, 9245, 14, 15, 13176, // 13,15
+ 13, -1, 9662, 13, 0, 13470, 14, -1, 12574, 14, 0, 29830, // 14, 0
+ 13, 0, 9202, 13, 1, 12564, 14, 0, 12412, 14, 1, 31358, // 14, 1
+ 13, 1, 8742, 13, 2, 11709, 14, 1, 12203, 14, 2, 32882, // 14, 2
+ 13, 2, 8296, 13, 3, 10918, 14, 2, 11964, 14, 3, 34358, // 14, 3
+ 13, 3, 7881, 13, 4, 10204, 14, 3, 11721, 14, 4, 35730, // 14, 4
+ 13, 4, 7517, 13, 5, 9587, 14, 4, 11507, 14, 5, 36925, // 14, 5
+ 13, 5, 7224, 13, 6, 9086, 14, 5, 11360, 14, 6, 37866, // 14, 6
+ 13, 6, 7020, 13, 7, 8718, 14, 6, 11317, 14, 7, 38481, // 14, 7
+ 14, 7, 11344, 14, 8, 38534, 15, 7, 6997, 15, 8, 8661, // 14, 8
+ 14, 8, 11407, 14, 9, 37906, 15, 8, 7202, 15, 9, 9021, // 14, 9
+ 14, 9, 11575, 14, 10, 36955, 15, 9, 7497, 15, 10, 9509, // 14,10
+ 14, 10, 11810, 14, 11, 35750, 15, 10, 7865, 15, 11, 10111, // 14,11
+ 14, 11, 12074, 14, 12, 34369, 15, 11, 8284, 15, 12, 10809, // 14,12
+ 14, 12, 12334, 14, 13, 32886, 15, 12, 8735, 15, 13, 11581, // 14,13
+ 14, 13, 12564, 14, 14, 31358, 15, 13, 9202, 15, 14, 12412, // 14,14
+ 14, 14, 12746, 14, 15, 29828, 15, 14, 9671, 15, 15, 13291, // 14,15
+ 14, -1, 10104, 14, 0, 13569, 15, -1, 13368, 15, 0, 28495, // 15, 0
+ 14, 0, 9671, 14, 1, 12746, 15, 0, 13291, 15, 1, 29828, // 15, 1
+ 14, 1, 9245, 14, 2, 11977, 15, 1, 13176, 15, 2, 31138, // 15, 2
+ 14, 2, 8838, 14, 3, 11269, 15, 2, 13038, 15, 3, 32391, // 15, 3
+ 14, 3, 8463, 14, 4, 10635, 15, 3, 12899, 15, 4, 33539, // 15, 4
+ 14, 4, 8135, 14, 5, 10086, 15, 4, 12783, 15, 5, 34532, // 15, 5
+ 14, 5, 7868, 14, 6, 9635, 15, 5, 12717, 15, 6, 35316, // 15, 6
+ 14, 6, 7674, 14, 7, 9290, 15, 6, 12728, 15, 7, 35844, // 15, 7
+ 15, 7, 12764, 15, 8, 35905, 16, 7, 7643, 16, 8, 9224, // 15, 8
+ 15, 8, 12777, 15, 9, 35362, 16, 8, 7839, 16, 9, 9558, // 15, 9
+ 15, 9, 12867, 15, 10, 34567, 16, 9, 8107, 16, 10, 9995, // 15,10
+ 15, 10, 13007, 15, 11, 33564, 16, 10, 8438, 16, 11, 10527, // 15,11
+ 15, 11, 13171, 15, 12, 32406, 16, 11, 8816, 16, 12, 11143, // 15,12
+ 15, 12, 13332, 15, 13, 31146, 16, 12, 9229, 16, 13, 11829, // 15,13
+ 15, 13, 13470, 15, 14, 29831, 16, 13, 9662, 16, 14, 12573, // 15,14
+ 15, 14, 13569, 15, 15, 28495, 16, 14, 10104, 16, 15, 13368, // 15,15
+ // angle of -1.5 degrees
+ -1, 0, 11440, -1, 1, 8358, 0, 0, 34212, 0, 1, 11526, // 0, 0
+ -1, 1, 10780, -1, 2, 7983, 0, 1, 35506, 0, 2, 11267, // 0, 1
+ -1, 2, 10158, -1, 3, 7620, 0, 2, 36764, 0, 3, 10994, // 0, 2
+ -1, 3, 9585, -1, 4, 7276, 0, 3, 37951, 0, 4, 10724, // 0, 3
+ -1, 4, 9072, -1, 5, 6965, 0, 4, 39026, 0, 5, 10473, // 0, 4
+ -1, 5, 8632, -1, 6, 6699, 0, 5, 39940, 0, 6, 10265, // 0, 5
+ -1, 6, 8278, -1, 7, 6489, 0, 6, 40646, 0, 7, 10123, // 0, 6
+ -1, 7, 8018, -1, 8, 6346, 0, 7, 41106, 0, 8, 10066, // 0, 7
+ 0, 8, 41072, 0, 9, 10052, 1, 8, 8052, 1, 9, 6360, // 0, 8
+ 0, 9, 40618, 0, 10, 10100, 1, 9, 8316, 1, 10, 6502, // 0, 9
+ 0, 10, 39918, 0, 11, 10232, 1, 10, 8676, 1, 11, 6710, // 0,10
+ 0, 11, 39009, 0, 12, 10430, 1, 11, 9122, 1, 12, 6975, // 0,11
+ 0, 12, 37939, 0, 13, 10670, 1, 12, 9642, 1, 13, 7285, // 0,12
+ 0, 13, 36756, 0, 14, 10930, 1, 13, 10224, 1, 14, 7626, // 0,13
+ 0, 14, 35502, 0, 15, 11192, 1, 14, 10855, 1, 15, 7987, // 0,14
+ 0, 15, 34212, 0, 16, 11440, 1, 15, 11526, 1, 16, 8358, // 0,15
+ 0, 0, 11192, 0, 1, 7987, 1, 0, 35502, 1, 1, 10855, // 1, 0
+ 0, 1, 10467, 0, 2, 7579, 1, 1, 36959, 1, 2, 10531, // 1, 1
+ 0, 2, 9777, 0, 3, 7177, 1, 2, 38394, 1, 3, 10188, // 1, 2
+ 0, 3, 9135, 0, 4, 6792, 1, 3, 39767, 1, 4, 9842, // 1, 3
+ 0, 4, 8557, 0, 5, 6440, 1, 4, 41026, 1, 5, 9513, // 1, 4
+ 0, 5, 8061, 0, 6, 6137, 1, 5, 42105, 1, 6, 9233, // 1, 5
+ 0, 6, 7667, 0, 7, 5900, 1, 6, 42936, 1, 7, 9033, // 1, 6
+ 0, 7, 7390, 0, 8, 5745, 1, 7, 43461, 1, 8, 8940, // 1, 7
+ 1, 8, 43433, 1, 9, 8929, 2, 8, 7418, 2, 9, 5756, // 1, 8
+ 1, 9, 42913, 1, 10, 9014, 2, 9, 7699, 2, 10, 5910, // 1, 9
+ 1, 10, 42087, 1, 11, 9206, 2, 10, 8098, 2, 11, 6145, // 1,10
+ 1, 11, 41013, 1, 12, 9478, 2, 11, 8599, 2, 12, 6446, // 1,11
+ 1, 12, 39759, 1, 13, 9796, 2, 12, 9184, 2, 13, 6797, // 1,12
+ 1, 13, 38390, 1, 14, 10133, 2, 13, 9834, 2, 14, 7179, // 1,13
+ 1, 14, 36959, 1, 15, 10467, 2, 14, 10532, 2, 15, 7578, // 1,14
+ 1, 15, 35506, 1, 16, 10780, 2, 15, 11267, 2, 16, 7983, // 1,15
+ 1, 0, 10930, 1, 1, 7626, 2, 0, 36756, 2, 1, 10224, // 2, 0
+ 1, 1, 10133, 1, 2, 7179, 2, 1, 38390, 2, 2, 9834, // 2, 1
+ 1, 2, 9366, 1, 3, 6732, 2, 2, 40025, 2, 3, 9413, // 2, 2
+ 1, 3, 8641, 1, 4, 6297, 2, 3, 41618, 2, 4, 8980, // 2, 3
+ 1, 4, 7981, 1, 5, 5891, 2, 4, 43105, 2, 5, 8559, // 2, 4
+ 1, 5, 7411, 1, 6, 5537, 2, 5, 44399, 2, 6, 8189, // 2, 5
+ 1, 6, 6961, 1, 7, 5261, 2, 6, 45401, 2, 7, 7913, // 2, 6
+ 1, 7, 6658, 1, 8, 5087, 2, 7, 46017, 2, 8, 7774, // 2, 7
+ 2, 8, 45995, 2, 9, 7766, 3, 8, 6680, 3, 9, 5095, // 2, 8
+ 2, 9, 45383, 2, 10, 7899, 3, 9, 6986, 3, 10, 5268, // 2, 9
+ 2, 10, 44386, 2, 11, 8167, 3, 10, 7440, 3, 11, 5543, // 2,10
+ 2, 11, 43096, 2, 12, 8530, 3, 11, 8015, 3, 12, 5895, // 2,11
+ 2, 12, 41614, 2, 13, 8941, 3, 12, 8681, 3, 13, 6300, // 2,12
+ 2, 13, 40025, 2, 14, 9366, 3, 13, 9413, 3, 14, 6732, // 2,13
+ 2, 14, 38394, 2, 15, 9777, 3, 14, 10188, 3, 15, 7177, // 2,14
+ 2, 15, 36764, 2, 16, 10158, 3, 15, 10994, 3, 16, 7620, // 2,15
+ 2, 0, 10670, 2, 1, 7285, 3, 0, 37939, 3, 1, 9642, // 3, 0
+ 2, 1, 9796, 2, 2, 6797, 3, 1, 39759, 3, 2, 9184, // 3, 1
+ 2, 2, 8941, 2, 3, 6299, 3, 2, 41614, 3, 3, 8682, // 3, 2
+ 2, 3, 8120, 2, 4, 5804, 3, 3, 43461, 3, 4, 8151, // 3, 3
+ 2, 4, 7356, 2, 5, 5330, 3, 4, 45229, 3, 5, 7621, // 3, 4
+ 2, 5, 6685, 2, 6, 4906, 3, 5, 46806, 3, 6, 7139, // 3, 5
+ 2, 6, 6154, 2, 7, 4572, 3, 6, 48049, 3, 7, 6761, // 3, 6
+ 2, 7, 5811, 2, 8, 4366, 3, 7, 48801, 3, 8, 6558, // 3, 7
+ 3, 8, 48785, 3, 9, 6552, 4, 8, 5827, 4, 9, 4372, // 3, 8
+ 3, 9, 48037, 3, 10, 6750, 4, 9, 6173, 4, 10, 4576, // 3, 9
+ 3, 10, 46798, 3, 11, 7121, 4, 10, 6707, 4, 11, 4910, // 3,10
+ 3, 11, 45224, 3, 12, 7598, 4, 11, 7382, 4, 12, 5332, // 3,11
+ 3, 12, 43461, 3, 13, 8120, 4, 12, 8151, 4, 13, 5804, // 3,12
+ 3, 13, 41618, 3, 14, 8641, 4, 13, 8979, 4, 14, 6298, // 3,13
+ 3, 14, 39767, 3, 15, 9135, 4, 14, 9841, 4, 15, 6793, // 3,14
+ 3, 15, 37951, 3, 16, 9585, 4, 15, 10723, 4, 16, 7277, // 3,15
+ 3, 0, 10430, 3, 1, 6975, 4, 0, 39009, 4, 1, 9122, // 4, 0
+ 3, 1, 9478, 3, 2, 6447, 4, 1, 41013, 4, 2, 8598, // 4, 1
+ 3, 2, 8530, 3, 3, 5895, 4, 2, 43096, 4, 3, 8015, // 4, 2
+ 3, 3, 7598, 3, 4, 5331, 4, 3, 45224, 4, 4, 7383, // 4, 3
+ 3, 4, 6708, 3, 5, 4774, 4, 4, 47328, 4, 5, 6726, // 4, 4
+ 3, 5, 5901, 3, 6, 4257, 4, 5, 49279, 4, 6, 6099, // 4, 5
+ 3, 6, 5248, 3, 7, 3834, 4, 6, 50873, 4, 7, 5581, // 4, 6
+ 3, 7, 4835, 3, 8, 3575, 4, 7, 51842, 4, 8, 5284, // 4, 7
+ 4, 8, 51832, 4, 9, 5280, 5, 8, 4846, 5, 9, 3578, // 4, 8
+ 4, 9, 50865, 4, 10, 5573, 5, 9, 5261, 5, 10, 3837, // 4, 9
+ 4, 10, 49275, 4, 11, 6086, 5, 10, 5917, 5, 11, 4258, // 4,10
+ 4, 11, 47328, 4, 12, 6708, 5, 11, 6727, 5, 12, 4773, // 4,11
+ 4, 12, 45229, 4, 13, 7356, 5, 12, 7622, 5, 13, 5329, // 4,12
+ 4, 13, 43105, 4, 14, 7981, 5, 13, 8559, 5, 14, 5891, // 4,13
+ 4, 14, 41026, 4, 15, 8557, 5, 14, 9513, 5, 15, 6440, // 4,14
+ 4, 15, 39026, 4, 16, 9072, 5, 15, 10473, 5, 16, 6965, // 4,15
+ 4, 0, 10232, 4, 1, 6710, 5, 0, 39918, 5, 1, 8676, // 5, 0
+ 4, 1, 9206, 4, 2, 6145, 5, 1, 42087, 5, 2, 8098, // 5, 1
+ 4, 2, 8167, 4, 3, 5543, 5, 2, 44386, 5, 3, 7440, // 5, 2
+ 4, 3, 7121, 4, 4, 4909, 5, 3, 46798, 5, 4, 6708, // 5, 3
+ 4, 4, 6086, 4, 5, 4258, 5, 4, 49275, 5, 5, 5917, // 5, 4
+ 4, 5, 5103, 4, 6, 3621, 5, 5, 51700, 5, 6, 5112, // 5, 5
+ 4, 6, 4262, 4, 7, 3064, 5, 6, 53816, 5, 7, 4394, // 5, 6
+ 4, 7, 3720, 4, 8, 2708, 5, 7, 55168, 5, 8, 3940, // 5, 7
+ 5, 8, 55162, 5, 9, 3938, 6, 8, 3726, 6, 9, 2710, // 5, 8
+ 5, 9, 53813, 5, 10, 4388, 6, 9, 4269, 6, 10, 3066, // 5, 9
+ 5, 10, 51700, 5, 11, 5103, 6, 10, 5113, 6, 11, 3620, // 5,10
+ 5, 11, 49279, 5, 12, 5901, 6, 11, 6099, 6, 12, 4257, // 5,11
+ 5, 12, 46806, 5, 13, 6685, 6, 12, 7138, 6, 13, 4907, // 5,12
+ 5, 13, 44399, 5, 14, 7411, 6, 13, 8189, 6, 14, 5537, // 5,13
+ 5, 14, 42105, 5, 15, 8061, 6, 14, 9233, 6, 15, 6137, // 5,14
+ 5, 15, 39940, 5, 16, 8632, 6, 15, 10265, 6, 16, 6699, // 5,15
+ 5, 0, 10100, 5, 1, 6502, 6, 0, 40618, 6, 1, 8316, // 6, 0
+ 5, 1, 9014, 5, 2, 5910, 6, 1, 42913, 6, 2, 7699, // 6, 1
+ 5, 2, 7899, 5, 3, 5268, 6, 2, 45383, 6, 3, 6986, // 6, 2
+ 5, 3, 6750, 5, 4, 4576, 6, 3, 48037, 6, 4, 6173, // 6, 3
+ 5, 4, 5573, 5, 5, 3837, 6, 4, 50865, 6, 5, 5261, // 6, 4
+ 5, 5, 4388, 5, 6, 3065, 6, 5, 53813, 6, 6, 4270, // 6, 5
+ 5, 6, 3271, 5, 7, 2316, 6, 6, 56673, 6, 7, 3276, // 6, 6
+ 5, 7, 2462, 5, 8, 1766, 6, 7, 58775, 6, 8, 2533, // 6, 7
+ 6, 8, 58773, 6, 9, 2532, 7, 8, 2464, 7, 9, 1767, // 6, 8
+ 6, 9, 56673, 6, 10, 3271, 7, 9, 3275, 7, 10, 2317, // 6, 9
+ 6, 10, 53816, 6, 11, 4262, 7, 10, 4394, 7, 11, 3064, // 6,10
+ 6, 11, 50873, 6, 12, 5248, 7, 11, 5581, 7, 12, 3834, // 6,11
+ 6, 12, 48049, 6, 13, 6154, 7, 12, 6761, 7, 13, 4572, // 6,12
+ 6, 13, 45401, 6, 14, 6961, 7, 13, 7913, 7, 14, 5261, // 6,13
+ 6, 14, 42936, 6, 15, 7667, 7, 14, 9032, 7, 15, 5901, // 6,14
+ 6, 15, 40646, 6, 16, 8278, 7, 15, 10123, 7, 16, 6489, // 6,15
+ 6, 0, 10052, 6, 1, 6360, 7, 0, 41072, 7, 1, 8052, // 7, 0
+ 6, 1, 8929, 6, 2, 5756, 7, 1, 43433, 7, 2, 7418, // 7, 1
+ 6, 2, 7766, 6, 3, 5095, 7, 2, 45995, 7, 3, 6680, // 7, 2
+ 6, 3, 6552, 6, 4, 4372, 7, 3, 48785, 7, 4, 5827, // 7, 3
+ 6, 4, 5280, 6, 5, 3579, 7, 4, 51832, 7, 5, 4845, // 7, 4
+ 6, 5, 3938, 6, 6, 2710, 7, 5, 55162, 7, 6, 3726, // 7, 5
+ 6, 6, 2532, 6, 7, 1767, 7, 6, 58773, 7, 7, 2464, // 7, 6
+ 6, 7, 1170, 6, 8, 827, 7, 7, 62369, 7, 8, 1170, // 7, 7
+ 7, 8, 62369, 7, 9, 1170, 8, 8, 1170, 8, 9, 827, // 7, 8
+ 7, 9, 58775, 7, 10, 2462, 8, 9, 2533, 8, 10, 1766, // 7, 9
+ 7, 10, 55168, 7, 11, 3720, 8, 10, 3940, 8, 11, 2708, // 7,10
+ 7, 11, 51842, 7, 12, 4835, 8, 11, 5283, 8, 12, 3576, // 7,11
+ 7, 12, 48801, 7, 13, 5811, 8, 12, 6558, 8, 13, 4366, // 7,12
+ 7, 13, 46017, 7, 14, 6658, 8, 13, 7773, 8, 14, 5088, // 7,13
+ 7, 14, 43461, 7, 15, 7390, 8, 14, 8939, 8, 15, 5746, // 7,14
+ 7, 15, 41106, 7, 16, 8018, 8, 15, 10066, 8, 16, 6346, // 7,15
+ 7, -1, 6346, 7, 0, 10066, 8, -1, 8018, 8, 0, 41106, // 8, 0
+ 7, 0, 5745, 7, 1, 8939, 8, 0, 7390, 8, 1, 43462, // 8, 1
+ 7, 1, 5087, 7, 2, 7773, 8, 1, 6658, 8, 2, 46018, // 8, 2
+ 7, 2, 4366, 7, 3, 6558, 8, 2, 5811, 8, 3, 48801, // 8, 3
+ 7, 3, 3575, 7, 4, 5283, 8, 3, 4835, 8, 4, 51843, // 8, 4
+ 7, 4, 2708, 7, 5, 3940, 8, 4, 3720, 8, 5, 55168, // 8, 5
+ 7, 5, 1766, 7, 6, 2533, 8, 5, 2462, 8, 6, 58775, // 8, 6
+ 7, 6, 827, 7, 7, 1170, 8, 6, 1170, 8, 7, 62369, // 8, 7
+ 8, 7, 1170, 8, 8, 62369, 9, 7, 827, 9, 8, 1170, // 8, 8
+ 8, 8, 2464, 8, 9, 58773, 9, 8, 1767, 9, 9, 2532, // 8, 9
+ 8, 9, 3726, 8, 10, 55162, 9, 9, 2710, 9, 10, 3938, // 8,10
+ 8, 10, 4846, 8, 11, 51832, 9, 10, 3579, 9, 11, 5279, // 8,11
+ 8, 11, 5827, 8, 12, 48785, 9, 11, 4372, 9, 12, 6552, // 8,12
+ 8, 12, 6680, 8, 13, 45995, 9, 12, 5095, 9, 13, 7766, // 8,13
+ 8, 13, 7418, 8, 14, 43433, 9, 13, 5756, 9, 14, 8929, // 8,14
+ 8, 14, 8052, 8, 15, 41072, 9, 14, 6360, 9, 15, 10052, // 8,15
+ 8, -1, 6489, 8, 0, 10123, 9, -1, 8278, 9, 0, 40646, // 9, 0
+ 8, 0, 5900, 8, 1, 9032, 9, 0, 7667, 9, 1, 42937, // 9, 1
+ 8, 1, 5261, 8, 2, 7913, 9, 1, 6961, 9, 2, 45401, // 9, 2
+ 8, 2, 4572, 8, 3, 6761, 9, 2, 6154, 9, 3, 48049, // 9, 3
+ 8, 3, 3834, 8, 4, 5581, 9, 3, 5248, 9, 4, 50873, // 9, 4
+ 8, 4, 3064, 8, 5, 4394, 9, 4, 4262, 9, 5, 53816, // 9, 5
+ 8, 5, 2316, 8, 6, 3275, 9, 5, 3271, 9, 6, 56674, // 9, 6
+ 8, 6, 1767, 8, 7, 2464, 9, 6, 2532, 9, 7, 58773, // 9, 7
+ 9, 7, 2533, 9, 8, 58775, 10, 7, 1766, 10, 8, 2462, // 9, 8
+ 9, 8, 3275, 9, 9, 56673, 10, 8, 2316, 10, 9, 3272, // 9, 9
+ 9, 9, 4269, 9, 10, 53813, 10, 9, 3065, 10, 10, 4389, // 9,10
+ 9, 10, 5261, 9, 11, 50865, 10, 10, 3837, 10, 11, 5573, // 9,11
+ 9, 11, 6173, 9, 12, 48037, 10, 11, 4576, 10, 12, 6750, // 9,12
+ 9, 12, 6986, 9, 13, 45383, 10, 12, 5268, 10, 13, 7899, // 9,13
+ 9, 13, 7699, 9, 14, 42913, 10, 13, 5910, 10, 14, 9014, // 9,14
+ 9, 14, 8316, 9, 15, 40618, 10, 14, 6502, 10, 15, 10100, // 9,15
+ 9, -1, 6699, 9, 0, 10265, 10, -1, 8632, 10, 0, 39940, // 10, 0
+ 9, 0, 6137, 9, 1, 9233, 10, 0, 8061, 10, 1, 42105, // 10, 1
+ 9, 1, 5537, 9, 2, 8189, 10, 1, 7411, 10, 2, 44399, // 10, 2
+ 9, 2, 4906, 9, 3, 7138, 10, 2, 6685, 10, 3, 46807, // 10, 3
+ 9, 3, 4257, 9, 4, 6099, 10, 3, 5901, 10, 4, 49279, // 10, 4
+ 9, 4, 3621, 9, 5, 5113, 10, 4, 5103, 10, 5, 51699, // 10, 5
+ 9, 5, 3065, 9, 6, 4269, 10, 5, 4388, 10, 6, 53814, // 10, 6
+ 9, 6, 2710, 9, 7, 3726, 10, 6, 3938, 10, 7, 55162, // 10, 7
+ 10, 7, 3940, 10, 8, 55168, 11, 7, 2708, 11, 8, 3720, // 10, 8
+ 10, 8, 4394, 10, 9, 53816, 11, 8, 3064, 11, 9, 4262, // 10, 9
+ 10, 9, 5113, 10, 10, 51700, 11, 9, 3621, 11, 10, 5102, // 10,10
+ 10, 10, 5917, 10, 11, 49275, 11, 10, 4258, 11, 11, 6086, // 10,11
+ 10, 11, 6707, 10, 12, 46798, 11, 11, 4909, 11, 12, 7122, // 10,12
+ 10, 12, 7440, 10, 13, 44386, 11, 12, 5543, 11, 13, 8167, // 10,13
+ 10, 13, 8098, 10, 14, 42087, 11, 13, 6145, 11, 14, 9206, // 10,14
+ 10, 14, 8676, 10, 15, 39918, 11, 14, 6710, 11, 15, 10232, // 10,15
+ 10, -1, 6965, 10, 0, 10473, 11, -1, 9072, 11, 0, 39026, // 11, 0
+ 10, 0, 6440, 10, 1, 9513, 11, 0, 8557, 11, 1, 41026, // 11, 1
+ 10, 1, 5891, 10, 2, 8559, 11, 1, 7981, 11, 2, 43105, // 11, 2
+ 10, 2, 5330, 10, 3, 7622, 11, 2, 7356, 11, 3, 45228, // 11, 3
+ 10, 3, 4774, 10, 4, 6727, 11, 3, 6708, 11, 4, 47327, // 11, 4
+ 10, 4, 4258, 10, 5, 5917, 11, 4, 6086, 11, 5, 49275, // 11, 5
+ 10, 5, 3837, 10, 6, 5261, 11, 5, 5573, 11, 6, 50865, // 11, 6
+ 10, 6, 3579, 10, 7, 4846, 11, 6, 5280, 11, 7, 51831, // 11, 7
+ 11, 7, 5283, 11, 8, 51842, 12, 7, 3575, 12, 8, 4836, // 11, 8
+ 11, 8, 5581, 11, 9, 50873, 12, 8, 3834, 12, 9, 5248, // 11, 9
+ 11, 9, 6099, 11, 10, 49279, 12, 9, 4257, 12, 10, 5901, // 11,10
+ 11, 10, 6727, 11, 11, 47328, 12, 10, 4774, 12, 11, 6707, // 11,11
+ 11, 11, 7382, 11, 12, 45224, 12, 11, 5331, 12, 12, 7599, // 11,12
+ 11, 12, 8015, 11, 13, 43096, 12, 12, 5895, 12, 13, 8530, // 11,13
+ 11, 13, 8599, 11, 14, 41013, 12, 13, 6447, 12, 14, 9477, // 11,14
+ 11, 14, 9122, 11, 15, 39009, 12, 14, 6975, 12, 15, 10430, // 11,15
+ 11, -1, 7276, 11, 0, 10723, 12, -1, 9585, 12, 0, 37952, // 12, 0
+ 11, 0, 6792, 11, 1, 9841, 12, 0, 9135, 12, 1, 39768, // 12, 1
+ 11, 1, 6297, 11, 2, 8979, 12, 1, 8641, 12, 2, 41619, // 12, 2
+ 11, 2, 5804, 11, 3, 8151, 12, 2, 8120, 12, 3, 43461, // 12, 3
+ 11, 3, 5331, 11, 4, 7382, 12, 3, 7598, 12, 4, 45225, // 12, 4
+ 11, 4, 4909, 11, 5, 6707, 12, 4, 7121, 12, 5, 46799, // 12, 5
+ 11, 5, 4576, 11, 6, 6173, 12, 5, 6750, 12, 6, 48037, // 12, 6
+ 11, 6, 4372, 11, 7, 5827, 12, 6, 6552, 12, 7, 48785, // 12, 7
+ 12, 7, 6558, 12, 8, 48801, 13, 7, 4366, 13, 8, 5811, // 12, 8
+ 12, 8, 6761, 12, 9, 48049, 13, 8, 4572, 13, 9, 6154, // 12, 9
+ 12, 9, 7138, 12, 10, 46806, 13, 9, 4906, 13, 10, 6686, // 12,10
+ 12, 10, 7622, 12, 11, 45229, 13, 10, 5330, 13, 11, 7355, // 12,11
+ 12, 11, 8151, 12, 12, 43461, 13, 11, 5804, 13, 12, 8120, // 12,12
+ 12, 12, 8681, 12, 13, 41614, 13, 12, 6299, 13, 13, 8942, // 12,13
+ 12, 13, 9184, 12, 14, 39759, 13, 13, 6797, 13, 14, 9796, // 12,14
+ 12, 14, 9642, 12, 15, 37939, 13, 14, 7285, 13, 15, 10670, // 12,15
+ 12, -1, 7620, 12, 0, 10994, 13, -1, 10158, 13, 0, 36764, // 13, 0
+ 12, 0, 7177, 12, 1, 10188, 13, 0, 9777, 13, 1, 38394, // 13, 1
+ 12, 1, 6732, 12, 2, 9413, 13, 1, 9366, 13, 2, 40025, // 13, 2
+ 12, 2, 6299, 12, 3, 8681, 13, 2, 8941, 13, 3, 41615, // 13, 3
+ 12, 3, 5895, 12, 4, 8015, 13, 3, 8530, 13, 4, 43096, // 13, 4
+ 12, 4, 5543, 12, 5, 7440, 13, 4, 8167, 13, 5, 44386, // 13, 5
+ 12, 5, 5268, 12, 6, 6986, 13, 5, 7899, 13, 6, 45383, // 13, 6
+ 12, 6, 5095, 12, 7, 6680, 13, 6, 7766, 13, 7, 45995, // 13, 7
+ 13, 7, 7773, 13, 8, 46017, 14, 7, 5087, 14, 8, 6659, // 13, 8
+ 13, 8, 7913, 13, 9, 45401, 14, 8, 5261, 14, 9, 6961, // 13, 9
+ 13, 9, 8189, 13, 10, 44399, 14, 9, 5537, 14, 10, 7411, // 13,10
+ 13, 10, 8559, 13, 11, 43105, 14, 10, 5891, 14, 11, 7981, // 13,11
+ 13, 11, 8979, 13, 12, 41618, 14, 11, 6297, 14, 12, 8642, // 13,12
+ 13, 12, 9413, 13, 13, 40025, 14, 12, 6732, 14, 13, 9366, // 13,13
+ 13, 13, 9834, 13, 14, 38390, 14, 13, 7179, 14, 14, 10133, // 13,14
+ 13, 14, 10224, 13, 15, 36756, 14, 14, 7626, 14, 15, 10930, // 13,15
+ 13, -1, 7983, 13, 0, 11267, 14, -1, 10780, 14, 0, 35506, // 14, 0
+ 13, 0, 7579, 13, 1, 10532, 14, 0, 10467, 14, 1, 36958, // 14, 1
+ 13, 1, 7179, 13, 2, 9834, 14, 1, 10133, 14, 2, 38390, // 14, 2
+ 13, 2, 6797, 13, 3, 9184, 14, 2, 9796, 14, 3, 39759, // 14, 3
+ 13, 3, 6447, 13, 4, 8599, 14, 3, 9478, 14, 4, 41012, // 14, 4
+ 13, 4, 6145, 13, 5, 8098, 14, 4, 9206, 14, 5, 42087, // 14, 5
+ 13, 5, 5910, 13, 6, 7699, 14, 5, 9014, 14, 6, 42913, // 14, 6
+ 13, 6, 5756, 13, 7, 7418, 14, 6, 8929, 14, 7, 43433, // 14, 7
+ 14, 7, 8939, 14, 8, 43461, 15, 7, 5745, 15, 8, 7391, // 14, 8
+ 14, 8, 9032, 14, 9, 42936, 15, 8, 5900, 15, 9, 7668, // 14, 9
+ 14, 9, 9233, 14, 10, 42105, 15, 9, 6137, 15, 10, 8061, // 14,10
+ 14, 10, 9513, 14, 11, 41026, 15, 10, 6440, 15, 11, 8557, // 14,11
+ 14, 11, 9841, 14, 12, 39767, 15, 11, 6792, 15, 12, 9136, // 14,12
+ 14, 12, 10188, 14, 13, 38394, 15, 12, 7177, 15, 13, 9777, // 14,13
+ 14, 13, 10532, 14, 14, 36959, 15, 13, 7579, 15, 14, 10466, // 14,14
+ 14, 14, 10855, 14, 15, 35502, 15, 14, 7987, 15, 15, 11192, // 14,15
+ 14, -1, 8358, 14, 0, 11526, 15, -1, 11440, 15, 0, 34212, // 15, 0
+ 14, 0, 7987, 14, 1, 10855, 15, 0, 11192, 15, 1, 35502, // 15, 1
+ 14, 1, 7626, 14, 2, 10224, 15, 1, 10930, 15, 2, 36756, // 15, 2
+ 14, 2, 7285, 14, 3, 9642, 15, 2, 10670, 15, 3, 37939, // 15, 3
+ 14, 3, 6975, 14, 4, 9122, 15, 3, 10430, 15, 4, 39009, // 15, 4
+ 14, 4, 6710, 14, 5, 8676, 15, 4, 10232, 15, 5, 39918, // 15, 5
+ 14, 5, 6502, 14, 6, 8316, 15, 5, 10100, 15, 6, 40618, // 15, 6
+ 14, 6, 6360, 14, 7, 8052, 15, 6, 10052, 15, 7, 41072, // 15, 7
+ 15, 7, 10066, 15, 8, 41106, 16, 7, 6346, 16, 8, 8018, // 15, 8
+ 15, 8, 10123, 15, 9, 40646, 16, 8, 6489, 16, 9, 8278, // 15, 9
+ 15, 9, 10265, 15, 10, 39940, 16, 9, 6699, 16, 10, 8632, // 15,10
+ 15, 10, 10473, 15, 11, 39026, 16, 10, 6965, 16, 11, 9072, // 15,11
+ 15, 11, 10723, 15, 12, 37951, 16, 11, 7276, 16, 12, 9586, // 15,12
+ 15, 12, 10994, 15, 13, 36764, 16, 12, 7620, 16, 13, 10158, // 15,13
+ 15, 13, 11267, 15, 14, 35506, 16, 13, 7983, 16, 14, 10780, // 15,14
+ 15, 14, 11526, 15, 15, 34212, 16, 14, 8358, 16, 15, 11440, // 15,15
+ // angle of -1.0 degrees
+ -1, 0, 8769, -1, 1, 6280, 0, 0, 41693, 0, 1, 8794, // 0, 0
+ -1, 1, 8265, -1, 2, 5974, 0, 1, 42823, 0, 2, 8474, // 0, 1
+ -1, 2, 7791, -1, 3, 5682, 0, 2, 43904, 0, 3, 8159, // 0, 2
+ -1, 3, 7356, -1, 4, 5410, 0, 3, 44907, 0, 4, 7863, // 0, 3
+ -1, 4, 6970, -1, 5, 5169, 0, 4, 45799, 0, 5, 7598, // 0, 4
+ -1, 5, 6644, -1, 6, 4967, 0, 5, 46541, 0, 6, 7384, // 0, 5
+ -1, 6, 6391, -1, 7, 4814, 0, 6, 47098, 0, 7, 7233, // 0, 6
+ -1, 7, 6217, -1, 8, 4718, 0, 7, 47440, 0, 8, 7161, // 0, 7
+ 0, 8, 47426, 0, 9, 7158, 1, 8, 6230, 1, 9, 4722, // 0, 8
+ 0, 9, 47086, 0, 10, 7227, 1, 9, 6405, 1, 10, 4818, // 0, 9
+ 0, 10, 46532, 0, 11, 7374, 1, 10, 6659, 1, 11, 4971, // 0,10
+ 0, 11, 45791, 0, 12, 7587, 1, 11, 6986, 1, 12, 5172, // 0,11
+ 0, 12, 44901, 0, 13, 7848, 1, 12, 7374, 1, 13, 5413, // 0,12
+ 0, 13, 43900, 0, 14, 8141, 1, 13, 7812, 1, 14, 5683, // 0,13
+ 0, 14, 42821, 0, 15, 8452, 1, 14, 8288, 1, 15, 5975, // 0,14
+ 0, 15, 41693, 0, 16, 8769, 1, 15, 8795, 1, 16, 6279, // 0,15
+ 0, 0, 8452, 0, 1, 5975, 1, 0, 42821, 1, 1, 8288, // 1, 0
+ 0, 1, 7901, 0, 2, 5640, 1, 1, 44074, 1, 2, 7921, // 1, 1
+ 0, 2, 7378, 0, 3, 5315, 1, 2, 45288, 1, 3, 7555, // 1, 2
+ 0, 3, 6892, 0, 4, 5009, 1, 3, 46430, 1, 4, 7205, // 1, 3
+ 0, 4, 6458, 0, 5, 4734, 1, 4, 47458, 1, 5, 6886, // 1, 4
+ 0, 5, 6092, 0, 6, 4502, 1, 5, 48322, 1, 6, 6620, // 1, 5
+ 0, 6, 5809, 0, 7, 4327, 1, 6, 48969, 1, 7, 6431, // 1, 6
+ 0, 7, 5623, 0, 8, 4221, 1, 7, 49358, 1, 8, 6334, // 1, 7
+ 1, 8, 49347, 1, 9, 6332, 2, 8, 5633, 2, 9, 4224, // 1, 8
+ 1, 9, 48960, 1, 10, 6425, 2, 9, 5820, 2, 10, 4331, // 1, 9
+ 1, 10, 48314, 1, 11, 6613, 2, 10, 6104, 2, 11, 4505, // 1,10
+ 1, 11, 47453, 1, 12, 6875, 2, 11, 6472, 2, 12, 4736, // 1,11
+ 1, 12, 46427, 1, 13, 7191, 2, 12, 6908, 2, 13, 5010, // 1,12
+ 1, 13, 45286, 1, 14, 7539, 2, 13, 7395, 2, 14, 5316, // 1,13
+ 1, 14, 44074, 1, 15, 7901, 2, 14, 7921, 2, 15, 5640, // 1,14
+ 1, 15, 42823, 1, 16, 8265, 2, 15, 8474, 2, 16, 5974, // 1,15
+ 1, 0, 8141, 1, 1, 5684, 2, 0, 43900, 2, 1, 7811, // 2, 0
+ 1, 1, 7539, 1, 2, 5316, 2, 1, 45286, 2, 2, 7395, // 2, 1
+ 1, 2, 6959, 1, 3, 4954, 2, 2, 46650, 2, 3, 6973, // 2, 2
+ 1, 3, 6414, 1, 4, 4607, 2, 3, 47955, 2, 4, 6560, // 2, 3
+ 1, 4, 5920, 1, 5, 4290, 2, 4, 49150, 2, 5, 6176, // 2, 4
+ 1, 5, 5499, 1, 6, 4019, 2, 5, 50171, 2, 6, 5847, // 2, 5
+ 1, 6, 5175, 1, 7, 3813, 2, 6, 50942, 2, 7, 5606, // 2, 6
+ 1, 7, 4970, 1, 8, 3691, 2, 7, 51395, 2, 8, 5480, // 2, 7
+ 2, 8, 51387, 2, 9, 5478, 3, 8, 4978, 3, 9, 3693, // 2, 8
+ 2, 9, 50935, 2, 10, 5602, 3, 9, 5184, 3, 10, 3815, // 2, 9
+ 2, 10, 50165, 2, 11, 5842, 3, 10, 5508, 3, 11, 4021, // 2,10
+ 2, 11, 49147, 2, 12, 6168, 3, 11, 5930, 3, 12, 4291, // 2,11
+ 2, 12, 47953, 2, 13, 6549, 3, 12, 6426, 3, 13, 4608, // 2,12
+ 2, 13, 46650, 2, 14, 6959, 3, 13, 6973, 3, 14, 4954, // 2,13
+ 2, 14, 45288, 2, 15, 7378, 3, 14, 7555, 3, 15, 5315, // 2,14
+ 2, 15, 43904, 2, 16, 7791, 3, 15, 8159, 3, 16, 5682, // 2,15
+ 2, 0, 7848, 2, 1, 5413, 3, 0, 44901, 3, 1, 7374, // 3, 0
+ 2, 1, 7191, 2, 2, 5011, 3, 1, 46427, 3, 2, 6907, // 3, 1
+ 2, 2, 6549, 2, 3, 4608, 3, 2, 47953, 3, 3, 6426, // 3, 2
+ 2, 3, 5934, 2, 4, 4214, 3, 3, 49445, 3, 4, 5943, // 3, 3
+ 2, 4, 5365, 2, 5, 3845, 3, 4, 50844, 3, 5, 5482, // 3, 4
+ 2, 5, 4872, 2, 6, 3522, 3, 5, 52069, 3, 6, 5073, // 3, 5
+ 2, 6, 4489, 2, 7, 3273, 3, 6, 53012, 3, 7, 4762, // 3, 6
+ 2, 7, 4254, 2, 8, 3126, 3, 7, 53562, 3, 8, 4594, // 3, 7
+ 3, 8, 53557, 3, 9, 4592, 4, 8, 4259, 4, 9, 3128, // 3, 8
+ 3, 9, 53008, 3, 10, 4759, 4, 9, 4495, 4, 10, 3274, // 3, 9
+ 3, 10, 52066, 3, 11, 5069, 4, 10, 4879, 4, 11, 3522, // 3,10
+ 3, 11, 50843, 3, 12, 5474, 4, 11, 5373, 4, 12, 3846, // 3,11
+ 3, 12, 49445, 3, 13, 5934, 4, 12, 5943, 4, 13, 4214, // 3,12
+ 3, 13, 47955, 3, 14, 6414, 4, 13, 6560, 4, 14, 4607, // 3,13
+ 3, 14, 46430, 3, 15, 6892, 4, 14, 7204, 4, 15, 5010, // 3,14
+ 3, 15, 44907, 3, 16, 7356, 4, 15, 7863, 4, 16, 5410, // 3,15
+ 3, 0, 7587, 3, 1, 5172, 4, 0, 45791, 4, 1, 6986, // 4, 0
+ 3, 1, 6875, 3, 2, 4736, 4, 1, 47453, 4, 2, 6472, // 4, 1
+ 3, 2, 6168, 3, 3, 4291, 4, 2, 49147, 4, 3, 5930, // 4, 2
+ 3, 3, 5474, 3, 4, 3846, 4, 3, 50843, 4, 4, 5373, // 4, 3
+ 3, 4, 4816, 3, 5, 3415, 4, 4, 52484, 4, 5, 4821, // 4, 4
+ 3, 5, 4226, 3, 6, 3023, 4, 5, 53975, 4, 6, 4312, // 4, 5
+ 3, 6, 3755, 3, 7, 2710, 4, 6, 55166, 4, 7, 3905, // 4, 6
+ 3, 7, 3469, 3, 8, 2524, 4, 7, 55870, 4, 8, 3673, // 4, 7
+ 4, 8, 55867, 4, 9, 3671, 5, 8, 3473, 5, 9, 2525, // 4, 8
+ 4, 9, 55164, 4, 10, 3902, 5, 9, 3759, 5, 10, 2711, // 4, 9
+ 4, 10, 53973, 4, 11, 4309, 5, 10, 4230, 5, 11, 3024, // 4,10
+ 4, 11, 52484, 4, 12, 4816, 5, 11, 4822, 5, 12, 3414, // 4,11
+ 4, 12, 50844, 4, 13, 5365, 5, 12, 5481, 5, 13, 3846, // 4,12
+ 4, 13, 49150, 4, 14, 5920, 5, 13, 6176, 5, 14, 4290, // 4,13
+ 4, 14, 47458, 4, 15, 6458, 5, 14, 6886, 5, 15, 4734, // 4,14
+ 4, 15, 45799, 4, 16, 6970, 5, 15, 7599, 5, 16, 5168, // 4,15
+ 4, 0, 7374, 4, 1, 4971, 5, 0, 46532, 5, 1, 6659, // 5, 0
+ 4, 1, 6613, 4, 2, 4505, 5, 1, 48314, 5, 2, 6104, // 5, 1
+ 4, 2, 5842, 4, 3, 4020, 5, 2, 50165, 5, 3, 5509, // 5, 2
+ 4, 3, 5069, 4, 4, 3523, 5, 3, 52066, 5, 4, 4878, // 5, 3
+ 4, 4, 4309, 4, 5, 3023, 5, 4, 53973, 5, 5, 4231, // 5, 4
+ 4, 5, 3595, 4, 6, 2546, 5, 5, 55798, 5, 6, 3597, // 5, 5
+ 4, 6, 2993, 4, 7, 2138, 5, 6, 57354, 5, 7, 3051, // 5, 6
+ 4, 7, 2615, 4, 8, 1884, 5, 7, 58324, 5, 8, 2713, // 5, 7
+ 5, 8, 58322, 5, 9, 2713, 6, 8, 2616, 6, 9, 1885, // 5, 8
+ 5, 9, 57353, 5, 10, 3050, 6, 9, 2995, 6, 10, 2138, // 5, 9
+ 5, 10, 55798, 5, 11, 3595, 6, 10, 3598, 6, 11, 2545, // 5,10
+ 5, 11, 53975, 5, 12, 4226, 6, 11, 4313, 6, 12, 3022, // 5,11
+ 5, 12, 52069, 5, 13, 4872, 6, 12, 5073, 6, 13, 3522, // 5,12
+ 5, 13, 50171, 5, 14, 5499, 6, 13, 5848, 6, 14, 4018, // 5,13
+ 5, 14, 48322, 5, 15, 6092, 6, 14, 6620, 6, 15, 4502, // 5,14
+ 5, 15, 46541, 5, 16, 6644, 6, 15, 7383, 6, 16, 4968, // 5,15
+ 5, 0, 7227, 5, 1, 4818, 6, 0, 47086, 6, 1, 6405, // 6, 0
+ 5, 1, 6425, 5, 2, 4330, 6, 1, 48960, 6, 2, 5821, // 6, 1
+ 5, 2, 5602, 5, 3, 3815, 6, 2, 50935, 6, 3, 5184, // 6, 2
+ 5, 3, 4759, 5, 4, 3274, 6, 3, 53008, 6, 4, 4495, // 6, 3
+ 5, 4, 3902, 5, 5, 2711, 6, 4, 55164, 6, 5, 3759, // 6, 4
+ 5, 5, 3050, 5, 6, 2138, 6, 5, 57353, 6, 6, 2995, // 6, 5
+ 5, 6, 2258, 5, 7, 1597, 6, 6, 59422, 6, 7, 2259, // 6, 6
+ 5, 7, 1695, 5, 8, 1209, 6, 7, 60906, 6, 8, 1726, // 6, 7
+ 6, 8, 60905, 6, 9, 1726, 7, 8, 1695, 7, 9, 1210, // 6, 8
+ 6, 9, 59422, 6, 10, 2258, 7, 9, 2259, 7, 10, 1597, // 6, 9
+ 6, 10, 57354, 6, 11, 2993, 7, 10, 3051, 7, 11, 2138, // 6,10
+ 6, 11, 55166, 6, 12, 3755, 7, 11, 3904, 7, 12, 2711, // 6,11
+ 6, 12, 53012, 6, 13, 4489, 7, 12, 4762, 7, 13, 3273, // 6,12
+ 6, 13, 50942, 6, 14, 5175, 7, 13, 5606, 7, 14, 3813, // 6,13
+ 6, 14, 48969, 6, 15, 5809, 7, 14, 6430, 7, 15, 4328, // 6,14
+ 6, 15, 47098, 6, 16, 6391, 7, 15, 7233, 7, 16, 4814, // 6,15
+ 6, 0, 7158, 6, 1, 4722, 7, 0, 47426, 7, 1, 6230, // 7, 0
+ 6, 1, 6332, 6, 2, 4224, 7, 1, 49347, 7, 2, 5633, // 7, 1
+ 6, 2, 5478, 6, 3, 3693, 7, 2, 51387, 7, 3, 4978, // 7, 2
+ 6, 3, 4592, 6, 4, 3128, 7, 3, 53557, 7, 4, 4259, // 7, 3
+ 6, 4, 3671, 6, 5, 2525, 7, 4, 55867, 7, 5, 3473, // 7, 4
+ 6, 5, 2713, 6, 6, 1884, 7, 5, 58322, 7, 6, 2617, // 7, 5
+ 6, 6, 1726, 6, 7, 1210, 7, 6, 60905, 7, 7, 1695, // 7, 6
+ 6, 7, 789, 6, 8, 558, 7, 7, 63399, 7, 8, 790, // 7, 7
+ 7, 8, 63399, 7, 9, 789, 8, 8, 789, 8, 9, 559, // 7, 8
+ 7, 9, 60906, 7, 10, 1695, 8, 9, 1726, 8, 10, 1209, // 7, 9
+ 7, 10, 58324, 7, 11, 2615, 8, 10, 2714, 8, 11, 1883, // 7,10
+ 7, 11, 55870, 7, 12, 3469, 8, 11, 3672, 8, 12, 2525, // 7,11
+ 7, 12, 53562, 7, 13, 4254, 8, 12, 4594, 8, 13, 3126, // 7,12
+ 7, 13, 51395, 7, 14, 4970, 8, 13, 5480, 8, 14, 3691, // 7,13
+ 7, 14, 49358, 7, 15, 5623, 8, 14, 6335, 8, 15, 4220, // 7,14
+ 7, 15, 47440, 7, 16, 6217, 8, 15, 7161, 8, 16, 4718, // 7,15
+ 7, -1, 4718, 7, 0, 7161, 8, -1, 6217, 8, 0, 47440, // 8, 0
+ 7, 0, 4221, 7, 1, 6335, 8, 0, 5623, 8, 1, 49357, // 8, 1
+ 7, 1, 3691, 7, 2, 5480, 8, 1, 4970, 8, 2, 51395, // 8, 2
+ 7, 2, 3126, 7, 3, 4594, 8, 2, 4254, 8, 3, 53562, // 8, 3
+ 7, 3, 2524, 7, 4, 3672, 8, 3, 3469, 8, 4, 55871, // 8, 4
+ 7, 4, 1884, 7, 5, 2714, 8, 4, 2615, 8, 5, 58323, // 8, 5
+ 7, 5, 1209, 7, 6, 1726, 8, 5, 1695, 8, 6, 60906, // 8, 6
+ 7, 6, 558, 7, 7, 789, 8, 6, 789, 8, 7, 63400, // 8, 7
+ 8, 7, 789, 8, 8, 63399, 9, 7, 558, 9, 8, 790, // 8, 8
+ 8, 8, 1695, 8, 9, 60905, 9, 8, 1210, 9, 9, 1726, // 8, 9
+ 8, 9, 2616, 8, 10, 58322, 9, 9, 1884, 9, 10, 2714, // 8,10
+ 8, 10, 3473, 8, 11, 55867, 9, 10, 2525, 9, 11, 3671, // 8,11
+ 8, 11, 4259, 8, 12, 53557, 9, 11, 3128, 9, 12, 4592, // 8,12
+ 8, 12, 4978, 8, 13, 51387, 9, 12, 3693, 9, 13, 5478, // 8,13
+ 8, 13, 5633, 8, 14, 49347, 9, 13, 4224, 9, 14, 6332, // 8,14
+ 8, 14, 6230, 8, 15, 47426, 9, 14, 4722, 9, 15, 7158, // 8,15
+ 8, -1, 4814, 8, 0, 7233, 9, -1, 6391, 9, 0, 47098, // 9, 0
+ 8, 0, 4327, 8, 1, 6430, 9, 0, 5809, 9, 1, 48970, // 9, 1
+ 8, 1, 3813, 8, 2, 5606, 9, 1, 5175, 9, 2, 50942, // 9, 2
+ 8, 2, 3273, 8, 3, 4762, 9, 2, 4489, 9, 3, 53012, // 9, 3
+ 8, 3, 2710, 8, 4, 3904, 9, 3, 3755, 9, 4, 55167, // 9, 4
+ 8, 4, 2138, 8, 5, 3051, 9, 4, 2993, 9, 5, 57354, // 9, 5
+ 8, 5, 1597, 8, 6, 2259, 9, 5, 2258, 9, 6, 59422, // 9, 6
+ 8, 6, 1210, 8, 7, 1695, 9, 6, 1726, 9, 7, 60905, // 9, 7
+ 9, 7, 1726, 9, 8, 60906, 10, 7, 1209, 10, 8, 1695, // 9, 8
+ 9, 8, 2259, 9, 9, 59422, 10, 8, 1597, 10, 9, 2258, // 9, 9
+ 9, 9, 2995, 9, 10, 57353, 10, 9, 2138, 10, 10, 3050, // 9,10
+ 9, 10, 3759, 9, 11, 55164, 10, 10, 2711, 10, 11, 3902, // 9,11
+ 9, 11, 4495, 9, 12, 53008, 10, 11, 3274, 10, 12, 4759, // 9,12
+ 9, 12, 5184, 9, 13, 50935, 10, 12, 3815, 10, 13, 5602, // 9,13
+ 9, 13, 5820, 9, 14, 48960, 10, 13, 4330, 10, 14, 6426, // 9,14
+ 9, 14, 6405, 9, 15, 47086, 10, 14, 4818, 10, 15, 7227, // 9,15
+ 9, -1, 4967, 9, 0, 7383, 10, -1, 6644, 10, 0, 46542, // 10, 0
+ 9, 0, 4502, 9, 1, 6620, 10, 0, 6092, 10, 1, 48322, // 10, 1
+ 9, 1, 4019, 9, 2, 5848, 10, 1, 5499, 10, 2, 50170, // 10, 2
+ 9, 2, 3522, 9, 3, 5073, 10, 2, 4872, 10, 3, 52069, // 10, 3
+ 9, 3, 3023, 9, 4, 4313, 10, 3, 4226, 10, 4, 53974, // 10, 4
+ 9, 4, 2546, 9, 5, 3598, 10, 4, 3595, 10, 5, 55797, // 10, 5
+ 9, 5, 2138, 9, 6, 2995, 10, 5, 3050, 10, 6, 57353, // 10, 6
+ 9, 6, 1884, 9, 7, 2616, 10, 6, 2713, 10, 7, 58323, // 10, 7
+ 10, 7, 2714, 10, 8, 58324, 11, 7, 1884, 11, 8, 2614, // 10, 8
+ 10, 8, 3051, 10, 9, 57354, 11, 8, 2138, 11, 9, 2993, // 10, 9
+ 10, 9, 3598, 10, 10, 55798, 11, 9, 2546, 11, 10, 3594, // 10,10
+ 10, 10, 4230, 10, 11, 53973, 11, 10, 3023, 11, 11, 4310, // 10,11
+ 10, 11, 4879, 10, 12, 52066, 11, 11, 3523, 11, 12, 5068, // 10,12
+ 10, 12, 5508, 10, 13, 50165, 11, 12, 4020, 11, 13, 5843, // 10,13
+ 10, 13, 6104, 10, 14, 48314, 11, 13, 4505, 11, 14, 6613, // 10,14
+ 10, 14, 6659, 10, 15, 46532, 11, 14, 4971, 11, 15, 7374, // 10,15
+ 10, -1, 5169, 10, 0, 7599, 11, -1, 6970, 11, 0, 45798, // 11, 0
+ 10, 0, 4734, 10, 1, 6886, 11, 0, 6458, 11, 1, 47458, // 11, 1
+ 10, 1, 4290, 10, 2, 6176, 11, 1, 5920, 11, 2, 49150, // 11, 2
+ 10, 2, 3845, 10, 3, 5481, 11, 2, 5365, 11, 3, 50845, // 11, 3
+ 10, 3, 3415, 10, 4, 4822, 11, 3, 4816, 11, 4, 52483, // 11, 4
+ 10, 4, 3023, 10, 5, 4230, 11, 4, 4309, 11, 5, 53974, // 11, 5
+ 10, 5, 2711, 10, 6, 3759, 11, 5, 3902, 11, 6, 55164, // 11, 6
+ 10, 6, 2525, 10, 7, 3473, 11, 6, 3671, 11, 7, 55867, // 11, 7
+ 11, 7, 3672, 11, 8, 55870, 12, 7, 2524, 12, 8, 3470, // 11, 8
+ 11, 8, 3904, 11, 9, 55166, 12, 8, 2710, 12, 9, 3756, // 11, 9
+ 11, 9, 4313, 11, 10, 53975, 12, 9, 3023, 12, 10, 4225, // 11,10
+ 11, 10, 4822, 11, 11, 52484, 12, 10, 3415, 12, 11, 4815, // 11,11
+ 11, 11, 5373, 11, 12, 50843, 12, 11, 3846, 12, 12, 5474, // 11,12
+ 11, 12, 5930, 11, 13, 49147, 12, 12, 4291, 12, 13, 6168, // 11,13
+ 11, 13, 6472, 11, 14, 47453, 12, 13, 4736, 12, 14, 6875, // 11,14
+ 11, 14, 6986, 11, 15, 45791, 12, 14, 5172, 12, 15, 7587, // 11,15
+ 11, -1, 5410, 11, 0, 7863, 12, -1, 7356, 12, 0, 44907, // 12, 0
+ 11, 0, 5009, 11, 1, 7204, 12, 0, 6892, 12, 1, 46431, // 12, 1
+ 11, 1, 4607, 11, 2, 6560, 12, 1, 6414, 12, 2, 47955, // 12, 2
+ 11, 2, 4214, 11, 3, 5943, 12, 2, 5934, 12, 3, 49445, // 12, 3
+ 11, 3, 3846, 11, 4, 5373, 12, 3, 5474, 12, 4, 50843, // 12, 4
+ 11, 4, 3523, 11, 5, 4879, 12, 4, 5069, 12, 5, 52065, // 12, 5
+ 11, 5, 3274, 11, 6, 4495, 12, 5, 4759, 12, 6, 53008, // 12, 6
+ 11, 6, 3128, 11, 7, 4259, 12, 6, 4592, 12, 7, 53557, // 12, 7
+ 12, 7, 4594, 12, 8, 53562, 13, 7, 3126, 13, 8, 4254, // 12, 8
+ 12, 8, 4762, 12, 9, 53012, 13, 8, 3273, 13, 9, 4489, // 12, 9
+ 12, 9, 5073, 12, 10, 52069, 13, 9, 3522, 13, 10, 4872, // 12,10
+ 12, 10, 5481, 12, 11, 50844, 13, 10, 3845, 13, 11, 5366, // 12,11
+ 12, 11, 5943, 12, 12, 49445, 13, 11, 4214, 13, 12, 5934, // 12,12
+ 12, 12, 6426, 12, 13, 47953, 13, 12, 4608, 13, 13, 6549, // 12,13
+ 12, 13, 6908, 12, 14, 46427, 13, 13, 5011, 13, 14, 7190, // 12,14
+ 12, 14, 7374, 12, 15, 44901, 13, 14, 5413, 13, 15, 7848, // 12,15
+ 12, -1, 5682, 12, 0, 8159, 13, -1, 7791, 13, 0, 43904, // 13, 0
+ 12, 0, 5315, 12, 1, 7555, 13, 0, 7378, 13, 1, 45288, // 13, 1
+ 12, 1, 4954, 12, 2, 6973, 13, 1, 6959, 13, 2, 46650, // 13, 2
+ 12, 2, 4608, 12, 3, 6426, 13, 2, 6549, 13, 3, 47953, // 13, 3
+ 12, 3, 4291, 12, 4, 5930, 13, 3, 6168, 13, 4, 49147, // 13, 4
+ 12, 4, 4020, 12, 5, 5508, 13, 4, 5842, 13, 5, 50166, // 13, 5
+ 12, 5, 3815, 12, 6, 5184, 13, 5, 5602, 13, 6, 50935, // 13, 6
+ 12, 6, 3693, 12, 7, 4978, 13, 6, 5478, 13, 7, 51387, // 13, 7
+ 13, 7, 5480, 13, 8, 51395, 14, 7, 3691, 14, 8, 4970, // 13, 8
+ 13, 8, 5606, 13, 9, 50942, 14, 8, 3813, 14, 9, 5175, // 13, 9
+ 13, 9, 5848, 13, 10, 50171, 14, 9, 4019, 14, 10, 5498, // 13,10
+ 13, 10, 6176, 13, 11, 49150, 14, 10, 4290, 14, 11, 5920, // 13,11
+ 13, 11, 6560, 13, 12, 47955, 14, 11, 4607, 14, 12, 6414, // 13,12
+ 13, 12, 6973, 13, 13, 46650, 14, 12, 4954, 14, 13, 6959, // 13,13
+ 13, 13, 7395, 13, 14, 45286, 14, 13, 5316, 14, 14, 7539, // 13,14
+ 13, 14, 7812, 13, 15, 43900, 14, 14, 5684, 14, 15, 8140, // 13,15
+ 13, -1, 5974, 13, 0, 8474, 14, -1, 8265, 14, 0, 42823, // 14, 0
+ 13, 0, 5640, 13, 1, 7921, 14, 0, 7901, 14, 1, 44074, // 14, 1
+ 13, 1, 5316, 13, 2, 7395, 14, 1, 7539, 14, 2, 45286, // 14, 2
+ 13, 2, 5011, 13, 3, 6908, 14, 2, 7191, 14, 3, 46426, // 14, 3
+ 13, 3, 4736, 13, 4, 6472, 14, 3, 6875, 14, 4, 47453, // 14, 4
+ 13, 4, 4505, 13, 5, 6104, 14, 4, 6613, 14, 5, 48314, // 14, 5
+ 13, 5, 4330, 13, 6, 5820, 14, 5, 6425, 14, 6, 48961, // 14, 6
+ 13, 6, 4224, 13, 7, 5633, 14, 6, 6332, 14, 7, 49347, // 14, 7
+ 14, 7, 6335, 14, 8, 49358, 15, 7, 4221, 15, 8, 5622, // 14, 8
+ 14, 8, 6430, 14, 9, 48969, 15, 8, 4327, 15, 9, 5810, // 14, 9
+ 14, 9, 6620, 14, 10, 48322, 15, 9, 4502, 15, 10, 6092, // 14,10
+ 14, 10, 6886, 14, 11, 47458, 15, 10, 4734, 15, 11, 6458, // 14,11
+ 14, 11, 7204, 14, 12, 46430, 15, 11, 5009, 15, 12, 6893, // 14,12
+ 14, 12, 7555, 14, 13, 45288, 15, 12, 5315, 15, 13, 7378, // 14,13
+ 14, 13, 7921, 14, 14, 44074, 15, 13, 5640, 15, 14, 7901, // 14,14
+ 14, 14, 8288, 14, 15, 42821, 15, 14, 5975, 15, 15, 8452, // 14,15
+ 14, -1, 6280, 14, 0, 8795, 15, -1, 8769, 15, 0, 41692, // 15, 0
+ 14, 0, 5975, 14, 1, 8288, 15, 0, 8452, 15, 1, 42821, // 15, 1
+ 14, 1, 5684, 14, 2, 7812, 15, 1, 8141, 15, 2, 43899, // 15, 2
+ 14, 2, 5413, 14, 3, 7374, 15, 2, 7848, 15, 3, 44901, // 15, 3
+ 14, 3, 5172, 14, 4, 6986, 15, 3, 7587, 15, 4, 45791, // 15, 4
+ 14, 4, 4971, 14, 5, 6659, 15, 4, 7374, 15, 5, 46532, // 15, 5
+ 14, 5, 4818, 14, 6, 6405, 15, 5, 7227, 15, 6, 47086, // 15, 6
+ 14, 6, 4722, 14, 7, 6230, 15, 6, 7158, 15, 7, 47426, // 15, 7
+ 15, 7, 7161, 15, 8, 47440, 16, 7, 4718, 16, 8, 6217, // 15, 8
+ 15, 8, 7233, 15, 9, 47098, 16, 8, 4814, 16, 9, 6391, // 15, 9
+ 15, 9, 7383, 15, 10, 46541, 16, 9, 4967, 16, 10, 6645, // 15,10
+ 15, 10, 7599, 15, 11, 45799, 16, 10, 5169, 16, 11, 6969, // 15,11
+ 15, 11, 7863, 15, 12, 44907, 16, 11, 5410, 16, 12, 7356, // 15,12
+ 15, 12, 8159, 15, 13, 43904, 16, 12, 5682, 16, 13, 7791, // 15,13
+ 15, 13, 8474, 15, 14, 42823, 16, 13, 5974, 16, 14, 8265, // 15,14
+ 15, 14, 8795, 15, 15, 41693, 16, 14, 6280, 16, 15, 8768, // 15,15
+ // angle of -0.5 degrees
+ -1, 0, 5106, -1, 1, 3621, 0, 0, 51699, 0, 1, 5110, // 0, 0
+ -1, 1, 4803, -1, 2, 3421, 0, 1, 52457, 0, 2, 4855, // 0, 1
+ -1, 2, 4521, -1, 3, 3235, 0, 2, 53168, 0, 3, 4612, // 0, 2
+ -1, 3, 4264, -1, 4, 3064, 0, 3, 53815, 0, 4, 4393, // 0, 3
+ -1, 4, 4041, -1, 5, 2916, 0, 4, 54378, 0, 5, 4201, // 0, 4
+ -1, 5, 3858, -1, 6, 2796, 0, 5, 54835, 0, 6, 4047, // 0, 5
+ -1, 6, 3722, -1, 7, 2709, 0, 6, 55166, 0, 7, 3939, // 0, 6
+ -1, 7, 3638, -1, 8, 2659, 0, 7, 55354, 0, 8, 3885, // 0, 7
+ 0, 8, 55352, 0, 9, 3885, 1, 8, 3640, 1, 9, 2659, // 0, 8
+ 0, 9, 55164, 0, 10, 3939, 1, 9, 3724, 1, 10, 2709, // 0, 9
+ 0, 10, 54833, 0, 11, 4046, 1, 10, 3860, 1, 11, 2797, // 0,10
+ 0, 11, 54376, 0, 12, 4200, 1, 11, 4043, 1, 12, 2917, // 0,11
+ 0, 12, 53814, 0, 13, 4390, 1, 12, 4267, 1, 13, 3065, // 0,12
+ 0, 13, 53168, 0, 14, 4610, 1, 13, 4523, 1, 14, 3235, // 0,13
+ 0, 14, 52457, 0, 15, 4851, 1, 14, 4806, 1, 15, 3422, // 0,14
+ 0, 15, 51699, 0, 16, 5106, 1, 15, 5110, 1, 16, 3621, // 0,15
+ 0, 0, 4851, 0, 1, 3422, 1, 0, 52457, 1, 1, 4806, // 1, 0
+ 0, 1, 4522, 0, 2, 3204, 1, 1, 53285, 1, 2, 4525, // 1, 1
+ 0, 2, 4212, 0, 3, 2998, 1, 2, 54072, 1, 3, 4254, // 1, 2
+ 0, 3, 3927, 0, 4, 2808, 1, 3, 54796, 1, 4, 4005, // 1, 3
+ 0, 4, 3677, 0, 5, 2640, 1, 4, 55435, 1, 5, 3784, // 1, 4
+ 0, 5, 3470, 0, 6, 2502, 1, 5, 55959, 1, 6, 3605, // 1, 5
+ 0, 6, 3317, 0, 7, 2402, 1, 6, 56340, 1, 7, 3477, // 1, 6
+ 0, 7, 3225, 0, 8, 2346, 1, 7, 56554, 1, 8, 3411, // 1, 7
+ 1, 8, 56552, 1, 9, 3411, 2, 8, 3227, 2, 9, 2346, // 1, 8
+ 1, 9, 56339, 1, 10, 3476, 2, 9, 3319, 2, 10, 2402, // 1, 9
+ 1, 10, 55958, 1, 11, 3604, 2, 10, 3472, 2, 11, 2502, // 1,10
+ 1, 11, 55434, 1, 12, 3783, 2, 11, 3678, 2, 12, 2641, // 1,11
+ 1, 12, 54796, 1, 13, 4003, 2, 12, 3929, 2, 13, 2808, // 1,12
+ 1, 13, 54071, 1, 14, 4253, 2, 13, 4214, 2, 14, 2998, // 1,13
+ 1, 14, 53285, 1, 15, 4522, 2, 14, 4525, 2, 15, 3204, // 1,14
+ 1, 15, 52457, 1, 16, 4803, 2, 15, 4854, 2, 16, 3422, // 1,15
+ 1, 0, 4610, 1, 1, 3235, 2, 0, 53168, 2, 1, 4523, // 2, 0
+ 1, 1, 4253, 1, 2, 2998, 2, 1, 54071, 2, 2, 4214, // 2, 1
+ 1, 2, 3911, 1, 3, 2770, 2, 2, 54941, 2, 3, 3914, // 2, 2
+ 1, 3, 3594, 1, 4, 2556, 2, 3, 55756, 2, 4, 3630, // 2, 3
+ 1, 4, 3310, 1, 5, 2365, 2, 4, 56487, 2, 5, 3374, // 2, 4
+ 1, 5, 3073, 1, 6, 2205, 2, 5, 57096, 2, 6, 3162, // 2, 5
+ 1, 6, 2897, 1, 7, 2088, 2, 6, 57545, 2, 7, 3006, // 2, 6
+ 1, 7, 2794, 1, 8, 2022, 2, 7, 57795, 2, 8, 2925, // 2, 7
+ 2, 8, 57793, 2, 9, 2926, 3, 8, 2795, 3, 9, 2022, // 2, 8
+ 2, 9, 57544, 2, 10, 3007, 3, 9, 2898, 3, 10, 2087, // 2, 9
+ 2, 10, 57095, 2, 11, 3161, 3, 10, 3074, 3, 11, 2206, // 2,10
+ 2, 11, 56486, 2, 12, 3373, 3, 11, 3311, 3, 12, 2366, // 2,11
+ 2, 12, 55756, 2, 13, 3628, 3, 12, 3595, 3, 13, 2557, // 2,12
+ 2, 13, 54941, 2, 14, 3911, 3, 13, 3913, 3, 14, 2771, // 2,13
+ 2, 14, 54072, 2, 15, 4212, 3, 14, 4255, 3, 15, 2997, // 2,14
+ 2, 15, 53168, 2, 16, 4521, 3, 15, 4612, 3, 16, 3235, // 2,15
+ 2, 0, 4390, 2, 1, 3065, 3, 0, 53814, 3, 1, 4267, // 3, 0
+ 2, 1, 4003, 2, 2, 2808, 3, 1, 54796, 3, 2, 3929, // 3, 1
+ 2, 2, 3628, 2, 3, 2557, 3, 2, 55756, 3, 3, 3595, // 3, 2
+ 2, 3, 3273, 2, 4, 2317, 3, 3, 56673, 3, 4, 3273, // 3, 3
+ 2, 4, 2948, 2, 5, 2096, 3, 4, 57514, 3, 5, 2978, // 3, 4
+ 2, 5, 2672, 2, 6, 1908, 3, 5, 58234, 3, 6, 2722, // 3, 5
+ 2, 6, 2463, 2, 7, 1766, 3, 6, 58775, 3, 7, 2532, // 3, 6
+ 2, 7, 2342, 2, 8, 1687, 3, 7, 59077, 3, 8, 2430, // 3, 7
+ 3, 8, 59076, 3, 9, 2430, 4, 8, 2343, 4, 9, 1687, // 3, 8
+ 3, 9, 58774, 3, 10, 2532, 4, 9, 2464, 4, 10, 1766, // 3, 9
+ 3, 10, 58233, 3, 11, 2722, 4, 10, 2673, 4, 11, 1908, // 3,10
+ 3, 11, 57514, 3, 12, 2976, 4, 11, 2950, 4, 12, 2096, // 3,11
+ 3, 12, 56673, 3, 13, 3273, 4, 12, 3274, 4, 13, 2316, // 3,12
+ 3, 13, 55756, 3, 14, 3594, 4, 13, 3630, 4, 14, 2556, // 3,13
+ 3, 14, 54796, 3, 15, 3927, 4, 14, 4005, 4, 15, 2808, // 3,14
+ 3, 15, 53815, 3, 16, 4264, 4, 15, 4392, 4, 16, 3065, // 3,15
+ 3, 0, 4200, 3, 1, 2917, 4, 0, 54376, 4, 1, 4043, // 4, 0
+ 3, 1, 3783, 3, 2, 2640, 4, 1, 55434, 4, 2, 3679, // 4, 1
+ 3, 2, 3373, 3, 3, 2365, 4, 2, 56486, 4, 3, 3312, // 4, 2
+ 3, 3, 2976, 3, 4, 2096, 4, 3, 57514, 4, 4, 2950, // 4, 3
+ 3, 4, 2604, 3, 5, 1843, 4, 4, 58484, 4, 5, 2605, // 4, 4
+ 3, 5, 2276, 3, 6, 1617, 4, 5, 59346, 4, 6, 2297, // 4, 5
+ 3, 6, 2020, 3, 7, 1442, 4, 6, 60018, 4, 7, 2056, // 4, 6
+ 3, 7, 1871, 3, 8, 1341, 4, 7, 60402, 4, 8, 1922, // 4, 7
+ 4, 8, 60402, 4, 9, 1922, 5, 8, 1871, 5, 9, 1341, // 4, 8
+ 4, 9, 60017, 4, 10, 2057, 5, 9, 2020, 5, 10, 1442, // 4, 9
+ 4, 10, 59345, 4, 11, 2297, 5, 10, 2276, 5, 11, 1618, // 4,10
+ 4, 11, 58484, 4, 12, 2604, 5, 11, 2605, 5, 12, 1843, // 4,11
+ 4, 12, 57514, 4, 13, 2948, 5, 12, 2977, 5, 13, 2097, // 4,12
+ 4, 13, 56487, 4, 14, 3310, 5, 13, 3374, 5, 14, 2365, // 4,13
+ 4, 14, 55435, 4, 15, 3677, 5, 14, 3785, 5, 15, 2639, // 4,14
+ 4, 15, 54378, 4, 16, 4041, 5, 15, 4201, 5, 16, 2916, // 4,15
+ 4, 0, 4046, 4, 1, 2797, 5, 0, 54833, 5, 1, 3860, // 5, 0
+ 4, 1, 3604, 4, 2, 2503, 5, 1, 55958, 5, 2, 3471, // 5, 1
+ 4, 2, 3161, 4, 3, 2205, 5, 2, 57095, 5, 3, 3075, // 5, 2
+ 4, 3, 2722, 4, 4, 1908, 5, 3, 58233, 5, 4, 2673, // 5, 3
+ 4, 4, 2297, 4, 5, 1617, 5, 4, 59345, 5, 5, 2277, // 5, 4
+ 4, 5, 1904, 4, 6, 1347, 5, 5, 60381, 5, 6, 1904, // 5, 5
+ 4, 6, 1578, 4, 7, 1121, 5, 6, 61243, 5, 7, 1594, // 5, 6
+ 4, 7, 1380, 4, 8, 985, 5, 7, 61767, 5, 8, 1404, // 5, 7
+ 5, 8, 61767, 5, 9, 1405, 6, 8, 1380, 6, 9, 984, // 5, 8
+ 5, 9, 61243, 5, 10, 1593, 6, 9, 1579, 6, 10, 1121, // 5, 9
+ 5, 10, 60381, 5, 11, 1904, 6, 10, 1904, 6, 11, 1347, // 5,10
+ 5, 11, 59346, 5, 12, 2276, 6, 11, 2297, 6, 12, 1617, // 5,11
+ 5, 12, 58234, 5, 13, 2672, 6, 12, 2723, 6, 13, 1907, // 5,12
+ 5, 13, 57096, 5, 14, 3073, 6, 13, 3161, 6, 14, 2206, // 5,13
+ 5, 14, 55959, 5, 15, 3470, 6, 14, 3605, 6, 15, 2502, // 5,14
+ 5, 15, 54835, 5, 16, 3858, 6, 15, 4047, 6, 16, 2796, // 5,15
+ 5, 0, 3939, 5, 1, 2709, 6, 0, 55164, 6, 1, 3724, // 6, 0
+ 5, 1, 3476, 5, 2, 2403, 6, 1, 56339, 6, 2, 3318, // 6, 1
+ 5, 2, 3007, 5, 3, 2088, 6, 2, 57544, 6, 3, 2897, // 6, 2
+ 5, 3, 2532, 5, 4, 1767, 6, 3, 58774, 6, 4, 2463, // 6, 3
+ 5, 4, 2057, 5, 5, 1442, 6, 4, 60017, 6, 5, 2020, // 6, 4
+ 5, 5, 1593, 5, 6, 1121, 6, 5, 61243, 6, 6, 1579, // 6, 5
+ 5, 6, 1170, 5, 7, 827, 6, 6, 62369, 6, 7, 1170, // 6, 6
+ 5, 7, 875, 5, 8, 622, 6, 7, 63156, 6, 8, 883, // 6, 7
+ 6, 8, 63156, 6, 9, 883, 7, 8, 875, 7, 9, 622, // 6, 8
+ 6, 9, 62369, 6, 10, 1170, 7, 9, 1170, 7, 10, 827, // 6, 9
+ 6, 10, 61243, 6, 11, 1578, 7, 10, 1593, 7, 11, 1122, // 6,10
+ 6, 11, 60018, 6, 12, 2020, 7, 11, 2057, 7, 12, 1441, // 6,11
+ 6, 12, 58775, 6, 13, 2463, 7, 12, 2532, 7, 13, 1766, // 6,12
+ 6, 13, 57545, 6, 14, 2897, 7, 13, 3007, 7, 14, 2087, // 6,13
+ 6, 14, 56340, 6, 15, 3317, 7, 14, 3477, 7, 15, 2402, // 6,14
+ 6, 15, 55166, 6, 16, 3722, 7, 15, 3940, 7, 16, 2708, // 6,15
+ 6, 0, 3885, 6, 1, 2659, 7, 0, 55352, 7, 1, 3640, // 7, 0
+ 6, 1, 3411, 6, 2, 2346, 7, 1, 56552, 7, 2, 3227, // 7, 1
+ 6, 2, 2926, 6, 3, 2022, 7, 2, 57793, 7, 3, 2795, // 7, 2
+ 6, 3, 2430, 6, 4, 1687, 7, 3, 59076, 7, 4, 2343, // 7, 3
+ 6, 4, 1922, 6, 5, 1341, 7, 4, 60402, 7, 5, 1871, // 7, 4
+ 6, 5, 1405, 6, 6, 985, 7, 5, 61767, 7, 6, 1379, // 7, 5
+ 6, 6, 883, 6, 7, 622, 7, 6, 63156, 7, 7, 875, // 7, 6
+ 6, 7, 399, 6, 8, 282, 7, 7, 64455, 7, 8, 400, // 7, 7
+ 7, 8, 64455, 7, 9, 399, 8, 8, 399, 8, 9, 283, // 7, 8
+ 7, 9, 63156, 7, 10, 875, 8, 9, 883, 8, 10, 622, // 7, 9
+ 7, 10, 61767, 7, 11, 1380, 8, 10, 1405, 8, 11, 984, // 7,10
+ 7, 11, 60402, 7, 12, 1871, 8, 11, 1922, 8, 12, 1341, // 7,11
+ 7, 12, 59077, 7, 13, 2342, 8, 12, 2430, 8, 13, 1687, // 7,12
+ 7, 13, 57795, 7, 14, 2794, 8, 13, 2926, 8, 14, 2021, // 7,13
+ 7, 14, 56554, 7, 15, 3225, 8, 14, 3411, 8, 15, 2346, // 7,14
+ 7, 15, 55354, 7, 16, 3638, 8, 15, 3885, 8, 16, 2659, // 7,15
+ 7, -1, 2659, 7, 0, 3885, 8, -1, 3638, 8, 0, 55354, // 8, 0
+ 7, 0, 2346, 7, 1, 3411, 8, 0, 3225, 8, 1, 56554, // 8, 1
+ 7, 1, 2022, 7, 2, 2926, 8, 1, 2794, 8, 2, 57794, // 8, 2
+ 7, 2, 1687, 7, 3, 2430, 8, 2, 2342, 8, 3, 59077, // 8, 3
+ 7, 3, 1341, 7, 4, 1922, 8, 3, 1871, 8, 4, 60402, // 8, 4
+ 7, 4, 985, 7, 5, 1405, 8, 4, 1380, 8, 5, 61766, // 8, 5
+ 7, 5, 622, 7, 6, 883, 8, 5, 875, 8, 6, 63156, // 8, 6
+ 7, 6, 282, 7, 7, 399, 8, 6, 399, 8, 7, 64456, // 8, 7
+ 8, 7, 399, 8, 8, 64455, 9, 7, 282, 9, 8, 400, // 8, 8
+ 8, 8, 875, 8, 9, 63156, 9, 8, 622, 9, 9, 883, // 8, 9
+ 8, 9, 1380, 8, 10, 61767, 9, 9, 985, 9, 10, 1404, // 8,10
+ 8, 10, 1871, 8, 11, 60402, 9, 10, 1341, 9, 11, 1922, // 8,11
+ 8, 11, 2343, 8, 12, 59076, 9, 11, 1687, 9, 12, 2430, // 8,12
+ 8, 12, 2795, 8, 13, 57793, 9, 12, 2022, 9, 13, 2926, // 8,13
+ 8, 13, 3227, 8, 14, 56552, 9, 13, 2346, 9, 14, 3411, // 8,14
+ 8, 14, 3640, 8, 15, 55352, 9, 14, 2659, 9, 15, 3885, // 8,15
+ 8, -1, 2709, 8, 0, 3940, 9, -1, 3722, 9, 0, 55165, // 9, 0
+ 8, 0, 2402, 8, 1, 3477, 9, 0, 3317, 9, 1, 56340, // 9, 1
+ 8, 1, 2088, 8, 2, 3007, 9, 1, 2897, 9, 2, 57544, // 9, 2
+ 8, 2, 1766, 8, 3, 2532, 9, 2, 2463, 9, 3, 58775, // 9, 3
+ 8, 3, 1442, 8, 4, 2057, 9, 3, 2020, 9, 4, 60017, // 9, 4
+ 8, 4, 1121, 8, 5, 1593, 9, 4, 1578, 9, 5, 61244, // 9, 5
+ 8, 5, 827, 8, 6, 1170, 9, 5, 1170, 9, 6, 62369, // 9, 6
+ 8, 6, 622, 8, 7, 875, 9, 6, 883, 9, 7, 63156, // 9, 7
+ 9, 7, 883, 9, 8, 63156, 10, 7, 622, 10, 8, 875, // 9, 8
+ 9, 8, 1170, 9, 9, 62369, 10, 8, 827, 10, 9, 1170, // 9, 9
+ 9, 9, 1579, 9, 10, 61243, 10, 9, 1121, 10, 10, 1593, // 9,10
+ 9, 10, 2020, 9, 11, 60017, 10, 10, 1442, 10, 11, 2057, // 9,11
+ 9, 11, 2464, 9, 12, 58774, 10, 11, 1767, 10, 12, 2531, // 9,12
+ 9, 12, 2898, 9, 13, 57544, 10, 12, 2088, 10, 13, 3006, // 9,13
+ 9, 13, 3319, 9, 14, 56339, 10, 13, 2403, 10, 14, 3475, // 9,14
+ 9, 14, 3724, 9, 15, 55164, 10, 14, 2709, 10, 15, 3939, // 9,15
+ 9, -1, 2796, 9, 0, 4047, 10, -1, 3858, 10, 0, 54835, // 10, 0
+ 9, 0, 2502, 9, 1, 3605, 10, 0, 3470, 10, 1, 55959, // 10, 1
+ 9, 1, 2205, 9, 2, 3161, 10, 1, 3073, 10, 2, 57097, // 10, 2
+ 9, 2, 1908, 9, 3, 2723, 10, 2, 2672, 10, 3, 58233, // 10, 3
+ 9, 3, 1617, 9, 4, 2297, 10, 3, 2276, 10, 4, 59346, // 10, 4
+ 9, 4, 1347, 9, 5, 1904, 10, 4, 1904, 10, 5, 60381, // 10, 5
+ 9, 5, 1121, 9, 6, 1579, 10, 5, 1593, 10, 6, 61243, // 10, 6
+ 9, 6, 985, 9, 7, 1380, 10, 6, 1405, 10, 7, 61766, // 10, 7
+ 10, 7, 1405, 10, 8, 61767, 11, 7, 985, 11, 8, 1379, // 10, 8
+ 10, 8, 1593, 10, 9, 61243, 11, 8, 1121, 11, 9, 1579, // 10, 9
+ 10, 9, 1904, 10, 10, 60381, 11, 9, 1347, 11, 10, 1904, // 10,10
+ 10, 10, 2276, 10, 11, 59345, 11, 10, 1617, 11, 11, 2298, // 10,11
+ 10, 11, 2673, 10, 12, 58233, 11, 11, 1908, 11, 12, 2722, // 10,12
+ 10, 12, 3074, 10, 13, 57095, 11, 12, 2205, 11, 13, 3162, // 10,13
+ 10, 13, 3472, 10, 14, 55958, 11, 13, 2503, 11, 14, 3603, // 10,14
+ 10, 14, 3860, 10, 15, 54833, 11, 14, 2797, 11, 15, 4046, // 10,15
+ 10, -1, 2916, 10, 0, 4201, 11, -1, 4041, 11, 0, 54378, // 11, 0
+ 10, 0, 2640, 10, 1, 3785, 11, 0, 3677, 11, 1, 55434, // 11, 1
+ 10, 1, 2365, 10, 2, 3374, 11, 1, 3310, 11, 2, 56487, // 11, 2
+ 10, 2, 2096, 10, 3, 2977, 11, 2, 2948, 11, 3, 57515, // 11, 3
+ 10, 3, 1843, 10, 4, 2605, 11, 3, 2604, 11, 4, 58484, // 11, 4
+ 10, 4, 1617, 10, 5, 2276, 11, 4, 2297, 11, 5, 59346, // 11, 5
+ 10, 5, 1442, 10, 6, 2020, 11, 5, 2057, 11, 6, 60017, // 11, 6
+ 10, 6, 1341, 10, 7, 1871, 11, 6, 1922, 11, 7, 60402, // 11, 7
+ 11, 7, 1922, 11, 8, 60402, 12, 7, 1341, 12, 8, 1871, // 11, 8
+ 11, 8, 2057, 11, 9, 60018, 12, 8, 1442, 12, 9, 2019, // 11, 9
+ 11, 9, 2297, 11, 10, 59346, 12, 9, 1617, 12, 10, 2276, // 11,10
+ 11, 10, 2605, 11, 11, 58484, 12, 10, 1843, 12, 11, 2604, // 11,11
+ 11, 11, 2950, 11, 12, 57514, 12, 11, 2096, 12, 12, 2976, // 11,12
+ 11, 12, 3311, 11, 13, 56486, 12, 12, 2365, 12, 13, 3374, // 11,13
+ 11, 13, 3678, 11, 14, 55434, 12, 13, 2640, 12, 14, 3784, // 11,14
+ 11, 14, 4043, 11, 15, 54376, 12, 14, 2917, 12, 15, 4200, // 11,15
+ 11, -1, 3064, 11, 0, 4392, 12, -1, 4264, 12, 0, 53816, // 12, 0
+ 11, 0, 2808, 11, 1, 4005, 12, 0, 3927, 12, 1, 54796, // 12, 1
+ 11, 1, 2556, 11, 2, 3630, 12, 1, 3594, 12, 2, 55756, // 12, 2
+ 11, 2, 2317, 11, 3, 3274, 12, 2, 3273, 12, 3, 56672, // 12, 3
+ 11, 3, 2096, 11, 4, 2950, 12, 3, 2976, 12, 4, 57514, // 12, 4
+ 11, 4, 1908, 11, 5, 2673, 12, 4, 2722, 12, 5, 58233, // 12, 5
+ 11, 5, 1767, 11, 6, 2464, 12, 5, 2532, 12, 6, 58773, // 12, 6
+ 11, 6, 1687, 11, 7, 2343, 12, 6, 2430, 12, 7, 59076, // 12, 7
+ 12, 7, 2430, 12, 8, 59077, 13, 7, 1687, 13, 8, 2342, // 12, 8
+ 12, 8, 2532, 12, 9, 58775, 13, 8, 1766, 13, 9, 2463, // 12, 9
+ 12, 9, 2723, 12, 10, 58234, 13, 9, 1908, 13, 10, 2671, // 12,10
+ 12, 10, 2977, 12, 11, 57514, 13, 10, 2096, 13, 11, 2949, // 12,11
+ 12, 11, 3274, 12, 12, 56673, 13, 11, 2317, 13, 12, 3272, // 12,12
+ 12, 12, 3595, 12, 13, 55756, 13, 12, 2557, 13, 13, 3628, // 12,13
+ 12, 13, 3929, 12, 14, 54796, 13, 13, 2808, 13, 14, 4003, // 12,14
+ 12, 14, 4267, 12, 15, 53814, 13, 14, 3065, 13, 15, 4390, // 12,15
+ 12, -1, 3235, 12, 0, 4612, 13, -1, 4521, 13, 0, 53168, // 13, 0
+ 12, 0, 2998, 12, 1, 4255, 13, 0, 4212, 13, 1, 54071, // 13, 1
+ 12, 1, 2770, 12, 2, 3913, 13, 1, 3911, 13, 2, 54942, // 13, 2
+ 12, 2, 2557, 12, 3, 3595, 13, 2, 3628, 13, 3, 55756, // 13, 3
+ 12, 3, 2365, 12, 4, 3311, 13, 3, 3373, 13, 4, 56487, // 13, 4
+ 12, 4, 2205, 12, 5, 3074, 13, 4, 3161, 13, 5, 57096, // 13, 5
+ 12, 5, 2088, 12, 6, 2898, 13, 5, 3007, 13, 6, 57543, // 13, 6
+ 12, 6, 2022, 12, 7, 2795, 13, 6, 2926, 13, 7, 57793, // 13, 7
+ 13, 7, 2926, 13, 8, 57795, 14, 7, 2022, 14, 8, 2793, // 13, 8
+ 13, 8, 3007, 13, 9, 57545, 14, 8, 2088, 14, 9, 2896, // 13, 9
+ 13, 9, 3161, 13, 10, 57096, 14, 9, 2205, 14, 10, 3074, // 13,10
+ 13, 10, 3374, 13, 11, 56487, 14, 10, 2365, 14, 11, 3310, // 13,11
+ 13, 11, 3630, 13, 12, 55756, 14, 11, 2556, 14, 12, 3594, // 13,12
+ 13, 12, 3913, 13, 13, 54941, 14, 12, 2770, 14, 13, 3912, // 13,13
+ 13, 13, 4214, 13, 14, 54071, 14, 13, 2998, 14, 14, 4253, // 13,14
+ 13, 14, 4523, 13, 15, 53168, 14, 14, 3235, 14, 15, 4610, // 13,15
+ 13, -1, 3421, 13, 0, 4854, 14, -1, 4803, 14, 0, 52458, // 14, 0
+ 13, 0, 3204, 13, 1, 4525, 14, 0, 4522, 14, 1, 53285, // 14, 1
+ 13, 1, 2998, 13, 2, 4214, 14, 1, 4253, 14, 2, 54071, // 14, 2
+ 13, 2, 2808, 13, 3, 3929, 14, 2, 4003, 14, 3, 54796, // 14, 3
+ 13, 3, 2640, 13, 4, 3678, 14, 3, 3783, 14, 4, 55435, // 14, 4
+ 13, 4, 2503, 13, 5, 3472, 14, 4, 3604, 14, 5, 55957, // 14, 5
+ 13, 5, 2403, 13, 6, 3319, 14, 5, 3476, 14, 6, 56338, // 14, 6
+ 13, 6, 2346, 13, 7, 3227, 14, 6, 3411, 14, 7, 56552, // 14, 7
+ 14, 7, 3411, 14, 8, 56554, 15, 7, 2346, 15, 8, 3225, // 14, 8
+ 14, 8, 3477, 14, 9, 56340, 15, 8, 2402, 15, 9, 3317, // 14, 9
+ 14, 9, 3605, 14, 10, 55959, 15, 9, 2502, 15, 10, 3470, // 14,10
+ 14, 10, 3785, 14, 11, 55435, 15, 10, 2640, 15, 11, 3676, // 14,11
+ 14, 11, 4005, 14, 12, 54796, 15, 11, 2808, 15, 12, 3927, // 14,12
+ 14, 12, 4255, 14, 13, 54072, 15, 12, 2998, 15, 13, 4211, // 14,13
+ 14, 13, 4525, 14, 14, 53285, 15, 13, 3204, 15, 14, 4522, // 14,14
+ 14, 14, 4806, 14, 15, 52457, 15, 14, 3422, 15, 15, 4851, // 14,15
+ 14, -1, 3621, 14, 0, 5110, 15, -1, 5106, 15, 0, 51699, // 15, 0
+ 14, 0, 3422, 14, 1, 4806, 15, 0, 4851, 15, 1, 52457, // 15, 1
+ 14, 1, 3235, 14, 2, 4523, 15, 1, 4610, 15, 2, 53168, // 15, 2
+ 14, 2, 3065, 14, 3, 4267, 15, 2, 4390, 15, 3, 53814, // 15, 3
+ 14, 3, 2917, 14, 4, 4043, 15, 3, 4200, 15, 4, 54376, // 15, 4
+ 14, 4, 2797, 14, 5, 3860, 15, 4, 4046, 15, 5, 54833, // 15, 5
+ 14, 5, 2709, 14, 6, 3724, 15, 5, 3939, 15, 6, 55164, // 15, 6
+ 14, 6, 2659, 14, 7, 3640, 15, 6, 3885, 15, 7, 55352, // 15, 7
+ 15, 7, 3885, 15, 8, 55354, 16, 7, 2659, 16, 8, 3638, // 15, 8
+ 15, 8, 3940, 15, 9, 55166, 16, 8, 2709, 16, 9, 3721, // 15, 9
+ 15, 9, 4047, 15, 10, 54835, 16, 9, 2796, 16, 10, 3858, // 15,10
+ 15, 10, 4201, 15, 11, 54378, 16, 10, 2916, 16, 11, 4041, // 15,11
+ 15, 11, 4392, 15, 12, 53815, 16, 11, 3064, 16, 12, 4265, // 15,12
+ 15, 12, 4612, 15, 13, 53168, 16, 12, 3235, 16, 13, 4521, // 15,13
+ 15, 13, 4854, 15, 14, 52457, 16, 13, 3421, 16, 14, 4804, // 15,14
+ 15, 14, 5110, 15, 15, 51699, 16, 14, 3621, 16, 15, 5106, // 15,15
+ // angle of 0.0 degrees
+ 0, 0, 16384, 0, 0, 16384, 0, 0, 16384, 0, 0, 16384, // 0, 0
+ 0, 1, 16384, 0, 1, 16384, 0, 1, 16384, 0, 1, 16384, // 0, 1
+ 0, 2, 16384, 0, 2, 16384, 0, 2, 16384, 0, 2, 16384, // 0, 2
+ 0, 3, 16384, 0, 3, 16384, 0, 3, 16384, 0, 3, 16384, // 0, 3
+ 0, 4, 16384, 0, 4, 16384, 0, 4, 16384, 0, 4, 16384, // 0, 4
+ 0, 5, 16384, 0, 5, 16384, 0, 5, 16384, 0, 5, 16384, // 0, 5
+ 0, 6, 16384, 0, 6, 16384, 0, 6, 16384, 0, 6, 16384, // 0, 6
+ 0, 7, 16384, 0, 7, 16384, 0, 7, 16384, 0, 7, 16384, // 0, 7
+ 0, 8, 16384, 0, 8, 16384, 0, 8, 16384, 0, 8, 16384, // 0, 8
+ 0, 9, 16384, 0, 9, 16384, 0, 9, 16384, 0, 9, 16384, // 0, 9
+ 0, 10, 16384, 0, 10, 16384, 0, 10, 16384, 0, 10, 16384, // 0,10
+ 0, 11, 16384, 0, 11, 16384, 0, 11, 16384, 0, 11, 16384, // 0,11
+ 0, 12, 16384, 0, 12, 16384, 0, 12, 16384, 0, 12, 16384, // 0,12
+ 0, 13, 16384, 0, 13, 16384, 0, 13, 16384, 0, 13, 16384, // 0,13
+ 0, 14, 16384, 0, 14, 16384, 0, 14, 16384, 0, 14, 16384, // 0,14
+ 0, 15, 16384, 0, 15, 16384, 0, 15, 16384, 0, 15, 16384, // 0,15
+ 1, 0, 16384, 1, 0, 16384, 1, 0, 16384, 1, 0, 16384, // 1, 0
+ 1, 1, 16384, 1, 1, 16384, 1, 1, 16384, 1, 1, 16384, // 1, 1
+ 1, 2, 16384, 1, 2, 16384, 1, 2, 16384, 1, 2, 16384, // 1, 2
+ 1, 3, 16384, 1, 3, 16384, 1, 3, 16384, 1, 3, 16384, // 1, 3
+ 1, 4, 16384, 1, 4, 16384, 1, 4, 16384, 1, 4, 16384, // 1, 4
+ 1, 5, 16384, 1, 5, 16384, 1, 5, 16384, 1, 5, 16384, // 1, 5
+ 1, 6, 16384, 1, 6, 16384, 1, 6, 16384, 1, 6, 16384, // 1, 6
+ 1, 7, 16384, 1, 7, 16384, 1, 7, 16384, 1, 7, 16384, // 1, 7
+ 1, 8, 16384, 1, 8, 16384, 1, 8, 16384, 1, 8, 16384, // 1, 8
+ 1, 9, 16384, 1, 9, 16384, 1, 9, 16384, 1, 9, 16384, // 1, 9
+ 1, 10, 16384, 1, 10, 16384, 1, 10, 16384, 1, 10, 16384, // 1,10
+ 1, 11, 16384, 1, 11, 16384, 1, 11, 16384, 1, 11, 16384, // 1,11
+ 1, 12, 16384, 1, 12, 16384, 1, 12, 16384, 1, 12, 16384, // 1,12
+ 1, 13, 16384, 1, 13, 16384, 1, 13, 16384, 1, 13, 16384, // 1,13
+ 1, 14, 16384, 1, 14, 16384, 1, 14, 16384, 1, 14, 16384, // 1,14
+ 1, 15, 16384, 1, 15, 16384, 1, 15, 16384, 1, 15, 16384, // 1,15
+ 2, 0, 16384, 2, 0, 16384, 2, 0, 16384, 2, 0, 16384, // 2, 0
+ 2, 1, 16384, 2, 1, 16384, 2, 1, 16384, 2, 1, 16384, // 2, 1
+ 2, 2, 16384, 2, 2, 16384, 2, 2, 16384, 2, 2, 16384, // 2, 2
+ 2, 3, 16384, 2, 3, 16384, 2, 3, 16384, 2, 3, 16384, // 2, 3
+ 2, 4, 16384, 2, 4, 16384, 2, 4, 16384, 2, 4, 16384, // 2, 4
+ 2, 5, 16384, 2, 5, 16384, 2, 5, 16384, 2, 5, 16384, // 2, 5
+ 2, 6, 16384, 2, 6, 16384, 2, 6, 16384, 2, 6, 16384, // 2, 6
+ 2, 7, 16384, 2, 7, 16384, 2, 7, 16384, 2, 7, 16384, // 2, 7
+ 2, 8, 16384, 2, 8, 16384, 2, 8, 16384, 2, 8, 16384, // 2, 8
+ 2, 9, 16384, 2, 9, 16384, 2, 9, 16384, 2, 9, 16384, // 2, 9
+ 2, 10, 16384, 2, 10, 16384, 2, 10, 16384, 2, 10, 16384, // 2,10
+ 2, 11, 16384, 2, 11, 16384, 2, 11, 16384, 2, 11, 16384, // 2,11
+ 2, 12, 16384, 2, 12, 16384, 2, 12, 16384, 2, 12, 16384, // 2,12
+ 2, 13, 16384, 2, 13, 16384, 2, 13, 16384, 2, 13, 16384, // 2,13
+ 2, 14, 16384, 2, 14, 16384, 2, 14, 16384, 2, 14, 16384, // 2,14
+ 2, 15, 16384, 2, 15, 16384, 2, 15, 16384, 2, 15, 16384, // 2,15
+ 3, 0, 16384, 3, 0, 16384, 3, 0, 16384, 3, 0, 16384, // 3, 0
+ 3, 1, 16384, 3, 1, 16384, 3, 1, 16384, 3, 1, 16384, // 3, 1
+ 3, 2, 16384, 3, 2, 16384, 3, 2, 16384, 3, 2, 16384, // 3, 2
+ 3, 3, 16384, 3, 3, 16384, 3, 3, 16384, 3, 3, 16384, // 3, 3
+ 3, 4, 16384, 3, 4, 16384, 3, 4, 16384, 3, 4, 16384, // 3, 4
+ 3, 5, 16384, 3, 5, 16384, 3, 5, 16384, 3, 5, 16384, // 3, 5
+ 3, 6, 16384, 3, 6, 16384, 3, 6, 16384, 3, 6, 16384, // 3, 6
+ 3, 7, 16384, 3, 7, 16384, 3, 7, 16384, 3, 7, 16384, // 3, 7
+ 3, 8, 16384, 3, 8, 16384, 3, 8, 16384, 3, 8, 16384, // 3, 8
+ 3, 9, 16384, 3, 9, 16384, 3, 9, 16384, 3, 9, 16384, // 3, 9
+ 3, 10, 16384, 3, 10, 16384, 3, 10, 16384, 3, 10, 16384, // 3,10
+ 3, 11, 16384, 3, 11, 16384, 3, 11, 16384, 3, 11, 16384, // 3,11
+ 3, 12, 16384, 3, 12, 16384, 3, 12, 16384, 3, 12, 16384, // 3,12
+ 3, 13, 16384, 3, 13, 16384, 3, 13, 16384, 3, 13, 16384, // 3,13
+ 3, 14, 16384, 3, 14, 16384, 3, 14, 16384, 3, 14, 16384, // 3,14
+ 3, 15, 16384, 3, 15, 16384, 3, 15, 16384, 3, 15, 16384, // 3,15
+ 4, 0, 16384, 4, 0, 16384, 4, 0, 16384, 4, 0, 16384, // 4, 0
+ 4, 1, 16384, 4, 1, 16384, 4, 1, 16384, 4, 1, 16384, // 4, 1
+ 4, 2, 16384, 4, 2, 16384, 4, 2, 16384, 4, 2, 16384, // 4, 2
+ 4, 3, 16384, 4, 3, 16384, 4, 3, 16384, 4, 3, 16384, // 4, 3
+ 4, 4, 16384, 4, 4, 16384, 4, 4, 16384, 4, 4, 16384, // 4, 4
+ 4, 5, 16384, 4, 5, 16384, 4, 5, 16384, 4, 5, 16384, // 4, 5
+ 4, 6, 16384, 4, 6, 16384, 4, 6, 16384, 4, 6, 16384, // 4, 6
+ 4, 7, 16384, 4, 7, 16384, 4, 7, 16384, 4, 7, 16384, // 4, 7
+ 4, 8, 16384, 4, 8, 16384, 4, 8, 16384, 4, 8, 16384, // 4, 8
+ 4, 9, 16384, 4, 9, 16384, 4, 9, 16384, 4, 9, 16384, // 4, 9
+ 4, 10, 16384, 4, 10, 16384, 4, 10, 16384, 4, 10, 16384, // 4,10
+ 4, 11, 16384, 4, 11, 16384, 4, 11, 16384, 4, 11, 16384, // 4,11
+ 4, 12, 16384, 4, 12, 16384, 4, 12, 16384, 4, 12, 16384, // 4,12
+ 4, 13, 16384, 4, 13, 16384, 4, 13, 16384, 4, 13, 16384, // 4,13
+ 4, 14, 16384, 4, 14, 16384, 4, 14, 16384, 4, 14, 16384, // 4,14
+ 4, 15, 16384, 4, 15, 16384, 4, 15, 16384, 4, 15, 16384, // 4,15
+ 5, 0, 16384, 5, 0, 16384, 5, 0, 16384, 5, 0, 16384, // 5, 0
+ 5, 1, 16384, 5, 1, 16384, 5, 1, 16384, 5, 1, 16384, // 5, 1
+ 5, 2, 16384, 5, 2, 16384, 5, 2, 16384, 5, 2, 16384, // 5, 2
+ 5, 3, 16384, 5, 3, 16384, 5, 3, 16384, 5, 3, 16384, // 5, 3
+ 5, 4, 16384, 5, 4, 16384, 5, 4, 16384, 5, 4, 16384, // 5, 4
+ 5, 5, 16384, 5, 5, 16384, 5, 5, 16384, 5, 5, 16384, // 5, 5
+ 5, 6, 16384, 5, 6, 16384, 5, 6, 16384, 5, 6, 16384, // 5, 6
+ 5, 7, 16384, 5, 7, 16384, 5, 7, 16384, 5, 7, 16384, // 5, 7
+ 5, 8, 16384, 5, 8, 16384, 5, 8, 16384, 5, 8, 16384, // 5, 8
+ 5, 9, 16384, 5, 9, 16384, 5, 9, 16384, 5, 9, 16384, // 5, 9
+ 5, 10, 16384, 5, 10, 16384, 5, 10, 16384, 5, 10, 16384, // 5,10
+ 5, 11, 16384, 5, 11, 16384, 5, 11, 16384, 5, 11, 16384, // 5,11
+ 5, 12, 16384, 5, 12, 16384, 5, 12, 16384, 5, 12, 16384, // 5,12
+ 5, 13, 16384, 5, 13, 16384, 5, 13, 16384, 5, 13, 16384, // 5,13
+ 5, 14, 16384, 5, 14, 16384, 5, 14, 16384, 5, 14, 16384, // 5,14
+ 5, 15, 16384, 5, 15, 16384, 5, 15, 16384, 5, 15, 16384, // 5,15
+ 6, 0, 16384, 6, 0, 16384, 6, 0, 16384, 6, 0, 16384, // 6, 0
+ 6, 1, 16384, 6, 1, 16384, 6, 1, 16384, 6, 1, 16384, // 6, 1
+ 6, 2, 16384, 6, 2, 16384, 6, 2, 16384, 6, 2, 16384, // 6, 2
+ 6, 3, 16384, 6, 3, 16384, 6, 3, 16384, 6, 3, 16384, // 6, 3
+ 6, 4, 16384, 6, 4, 16384, 6, 4, 16384, 6, 4, 16384, // 6, 4
+ 6, 5, 16384, 6, 5, 16384, 6, 5, 16384, 6, 5, 16384, // 6, 5
+ 6, 6, 16384, 6, 6, 16384, 6, 6, 16384, 6, 6, 16384, // 6, 6
+ 6, 7, 16384, 6, 7, 16384, 6, 7, 16384, 6, 7, 16384, // 6, 7
+ 6, 8, 16384, 6, 8, 16384, 6, 8, 16384, 6, 8, 16384, // 6, 8
+ 6, 9, 16384, 6, 9, 16384, 6, 9, 16384, 6, 9, 16384, // 6, 9
+ 6, 10, 16384, 6, 10, 16384, 6, 10, 16384, 6, 10, 16384, // 6,10
+ 6, 11, 16384, 6, 11, 16384, 6, 11, 16384, 6, 11, 16384, // 6,11
+ 6, 12, 16384, 6, 12, 16384, 6, 12, 16384, 6, 12, 16384, // 6,12
+ 6, 13, 16384, 6, 13, 16384, 6, 13, 16384, 6, 13, 16384, // 6,13
+ 6, 14, 16384, 6, 14, 16384, 6, 14, 16384, 6, 14, 16384, // 6,14
+ 6, 15, 16384, 6, 15, 16384, 6, 15, 16384, 6, 15, 16384, // 6,15
+ 7, 0, 16384, 7, 0, 16384, 7, 0, 16384, 7, 0, 16384, // 7, 0
+ 7, 1, 16384, 7, 1, 16384, 7, 1, 16384, 7, 1, 16384, // 7, 1
+ 7, 2, 16384, 7, 2, 16384, 7, 2, 16384, 7, 2, 16384, // 7, 2
+ 7, 3, 16384, 7, 3, 16384, 7, 3, 16384, 7, 3, 16384, // 7, 3
+ 7, 4, 16384, 7, 4, 16384, 7, 4, 16384, 7, 4, 16384, // 7, 4
+ 7, 5, 16384, 7, 5, 16384, 7, 5, 16384, 7, 5, 16384, // 7, 5
+ 7, 6, 16384, 7, 6, 16384, 7, 6, 16384, 7, 6, 16384, // 7, 6
+ 7, 7, 16384, 7, 7, 16384, 7, 7, 16384, 7, 7, 16384, // 7, 7
+ 7, 8, 16384, 7, 8, 16384, 7, 8, 16384, 7, 8, 16384, // 7, 8
+ 7, 9, 16384, 7, 9, 16384, 7, 9, 16384, 7, 9, 16384, // 7, 9
+ 7, 10, 16384, 7, 10, 16384, 7, 10, 16384, 7, 10, 16384, // 7,10
+ 7, 11, 16384, 7, 11, 16384, 7, 11, 16384, 7, 11, 16384, // 7,11
+ 7, 12, 16384, 7, 12, 16384, 7, 12, 16384, 7, 12, 16384, // 7,12
+ 7, 13, 16384, 7, 13, 16384, 7, 13, 16384, 7, 13, 16384, // 7,13
+ 7, 14, 16384, 7, 14, 16384, 7, 14, 16384, 7, 14, 16384, // 7,14
+ 7, 15, 16384, 7, 15, 16384, 7, 15, 16384, 7, 15, 16384, // 7,15
+ 8, 0, 16384, 8, 0, 16384, 8, 0, 16384, 8, 0, 16384, // 8, 0
+ 8, 1, 16384, 8, 1, 16384, 8, 1, 16384, 8, 1, 16384, // 8, 1
+ 8, 2, 16384, 8, 2, 16384, 8, 2, 16384, 8, 2, 16384, // 8, 2
+ 8, 3, 16384, 8, 3, 16384, 8, 3, 16384, 8, 3, 16384, // 8, 3
+ 8, 4, 16384, 8, 4, 16384, 8, 4, 16384, 8, 4, 16384, // 8, 4
+ 8, 5, 16384, 8, 5, 16384, 8, 5, 16384, 8, 5, 16384, // 8, 5
+ 8, 6, 16384, 8, 6, 16384, 8, 6, 16384, 8, 6, 16384, // 8, 6
+ 8, 7, 16384, 8, 7, 16384, 8, 7, 16384, 8, 7, 16384, // 8, 7
+ 8, 8, 16384, 8, 8, 16384, 8, 8, 16384, 8, 8, 16384, // 8, 8
+ 8, 9, 16384, 8, 9, 16384, 8, 9, 16384, 8, 9, 16384, // 8, 9
+ 8, 10, 16384, 8, 10, 16384, 8, 10, 16384, 8, 10, 16384, // 8,10
+ 8, 11, 16384, 8, 11, 16384, 8, 11, 16384, 8, 11, 16384, // 8,11
+ 8, 12, 16384, 8, 12, 16384, 8, 12, 16384, 8, 12, 16384, // 8,12
+ 8, 13, 16384, 8, 13, 16384, 8, 13, 16384, 8, 13, 16384, // 8,13
+ 8, 14, 16384, 8, 14, 16384, 8, 14, 16384, 8, 14, 16384, // 8,14
+ 8, 15, 16384, 8, 15, 16384, 8, 15, 16384, 8, 15, 16384, // 8,15
+ 9, 0, 16384, 9, 0, 16384, 9, 0, 16384, 9, 0, 16384, // 9, 0
+ 9, 1, 16384, 9, 1, 16384, 9, 1, 16384, 9, 1, 16384, // 9, 1
+ 9, 2, 16384, 9, 2, 16384, 9, 2, 16384, 9, 2, 16384, // 9, 2
+ 9, 3, 16384, 9, 3, 16384, 9, 3, 16384, 9, 3, 16384, // 9, 3
+ 9, 4, 16384, 9, 4, 16384, 9, 4, 16384, 9, 4, 16384, // 9, 4
+ 9, 5, 16384, 9, 5, 16384, 9, 5, 16384, 9, 5, 16384, // 9, 5
+ 9, 6, 16384, 9, 6, 16384, 9, 6, 16384, 9, 6, 16384, // 9, 6
+ 9, 7, 16384, 9, 7, 16384, 9, 7, 16384, 9, 7, 16384, // 9, 7
+ 9, 8, 16384, 9, 8, 16384, 9, 8, 16384, 9, 8, 16384, // 9, 8
+ 9, 9, 16384, 9, 9, 16384, 9, 9, 16384, 9, 9, 16384, // 9, 9
+ 9, 10, 16384, 9, 10, 16384, 9, 10, 16384, 9, 10, 16384, // 9,10
+ 9, 11, 16384, 9, 11, 16384, 9, 11, 16384, 9, 11, 16384, // 9,11
+ 9, 12, 16384, 9, 12, 16384, 9, 12, 16384, 9, 12, 16384, // 9,12
+ 9, 13, 16384, 9, 13, 16384, 9, 13, 16384, 9, 13, 16384, // 9,13
+ 9, 14, 16384, 9, 14, 16384, 9, 14, 16384, 9, 14, 16384, // 9,14
+ 9, 15, 16384, 9, 15, 16384, 9, 15, 16384, 9, 15, 16384, // 9,15
+ 10, 0, 16384, 10, 0, 16384, 10, 0, 16384, 10, 0, 16384, // 10, 0
+ 10, 1, 16384, 10, 1, 16384, 10, 1, 16384, 10, 1, 16384, // 10, 1
+ 10, 2, 16384, 10, 2, 16384, 10, 2, 16384, 10, 2, 16384, // 10, 2
+ 10, 3, 16384, 10, 3, 16384, 10, 3, 16384, 10, 3, 16384, // 10, 3
+ 10, 4, 16384, 10, 4, 16384, 10, 4, 16384, 10, 4, 16384, // 10, 4
+ 10, 5, 16384, 10, 5, 16384, 10, 5, 16384, 10, 5, 16384, // 10, 5
+ 10, 6, 16384, 10, 6, 16384, 10, 6, 16384, 10, 6, 16384, // 10, 6
+ 10, 7, 16384, 10, 7, 16384, 10, 7, 16384, 10, 7, 16384, // 10, 7
+ 10, 8, 16384, 10, 8, 16384, 10, 8, 16384, 10, 8, 16384, // 10, 8
+ 10, 9, 16384, 10, 9, 16384, 10, 9, 16384, 10, 9, 16384, // 10, 9
+ 10, 10, 16384, 10, 10, 16384, 10, 10, 16384, 10, 10, 16384, // 10,10
+ 10, 11, 16384, 10, 11, 16384, 10, 11, 16384, 10, 11, 16384, // 10,11
+ 10, 12, 16384, 10, 12, 16384, 10, 12, 16384, 10, 12, 16384, // 10,12
+ 10, 13, 16384, 10, 13, 16384, 10, 13, 16384, 10, 13, 16384, // 10,13
+ 10, 14, 16384, 10, 14, 16384, 10, 14, 16384, 10, 14, 16384, // 10,14
+ 10, 15, 16384, 10, 15, 16384, 10, 15, 16384, 10, 15, 16384, // 10,15
+ 11, 0, 16384, 11, 0, 16384, 11, 0, 16384, 11, 0, 16384, // 11, 0
+ 11, 1, 16384, 11, 1, 16384, 11, 1, 16384, 11, 1, 16384, // 11, 1
+ 11, 2, 16384, 11, 2, 16384, 11, 2, 16384, 11, 2, 16384, // 11, 2
+ 11, 3, 16384, 11, 3, 16384, 11, 3, 16384, 11, 3, 16384, // 11, 3
+ 11, 4, 16384, 11, 4, 16384, 11, 4, 16384, 11, 4, 16384, // 11, 4
+ 11, 5, 16384, 11, 5, 16384, 11, 5, 16384, 11, 5, 16384, // 11, 5
+ 11, 6, 16384, 11, 6, 16384, 11, 6, 16384, 11, 6, 16384, // 11, 6
+ 11, 7, 16384, 11, 7, 16384, 11, 7, 16384, 11, 7, 16384, // 11, 7
+ 11, 8, 16384, 11, 8, 16384, 11, 8, 16384, 11, 8, 16384, // 11, 8
+ 11, 9, 16384, 11, 9, 16384, 11, 9, 16384, 11, 9, 16384, // 11, 9
+ 11, 10, 16384, 11, 10, 16384, 11, 10, 16384, 11, 10, 16384, // 11,10
+ 11, 11, 16384, 11, 11, 16384, 11, 11, 16384, 11, 11, 16384, // 11,11
+ 11, 12, 16384, 11, 12, 16384, 11, 12, 16384, 11, 12, 16384, // 11,12
+ 11, 13, 16384, 11, 13, 16384, 11, 13, 16384, 11, 13, 16384, // 11,13
+ 11, 14, 16384, 11, 14, 16384, 11, 14, 16384, 11, 14, 16384, // 11,14
+ 11, 15, 16384, 11, 15, 16384, 11, 15, 16384, 11, 15, 16384, // 11,15
+ 12, 0, 16384, 12, 0, 16384, 12, 0, 16384, 12, 0, 16384, // 12, 0
+ 12, 1, 16384, 12, 1, 16384, 12, 1, 16384, 12, 1, 16384, // 12, 1
+ 12, 2, 16384, 12, 2, 16384, 12, 2, 16384, 12, 2, 16384, // 12, 2
+ 12, 3, 16384, 12, 3, 16384, 12, 3, 16384, 12, 3, 16384, // 12, 3
+ 12, 4, 16384, 12, 4, 16384, 12, 4, 16384, 12, 4, 16384, // 12, 4
+ 12, 5, 16384, 12, 5, 16384, 12, 5, 16384, 12, 5, 16384, // 12, 5
+ 12, 6, 16384, 12, 6, 16384, 12, 6, 16384, 12, 6, 16384, // 12, 6
+ 12, 7, 16384, 12, 7, 16384, 12, 7, 16384, 12, 7, 16384, // 12, 7
+ 12, 8, 16384, 12, 8, 16384, 12, 8, 16384, 12, 8, 16384, // 12, 8
+ 12, 9, 16384, 12, 9, 16384, 12, 9, 16384, 12, 9, 16384, // 12, 9
+ 12, 10, 16384, 12, 10, 16384, 12, 10, 16384, 12, 10, 16384, // 12,10
+ 12, 11, 16384, 12, 11, 16384, 12, 11, 16384, 12, 11, 16384, // 12,11
+ 12, 12, 16384, 12, 12, 16384, 12, 12, 16384, 12, 12, 16384, // 12,12
+ 12, 13, 16384, 12, 13, 16384, 12, 13, 16384, 12, 13, 16384, // 12,13
+ 12, 14, 16384, 12, 14, 16384, 12, 14, 16384, 12, 14, 16384, // 12,14
+ 12, 15, 16384, 12, 15, 16384, 12, 15, 16384, 12, 15, 16384, // 12,15
+ 13, 0, 16384, 13, 0, 16384, 13, 0, 16384, 13, 0, 16384, // 13, 0
+ 13, 1, 16384, 13, 1, 16384, 13, 1, 16384, 13, 1, 16384, // 13, 1
+ 13, 2, 16384, 13, 2, 16384, 13, 2, 16384, 13, 2, 16384, // 13, 2
+ 13, 3, 16384, 13, 3, 16384, 13, 3, 16384, 13, 3, 16384, // 13, 3
+ 13, 4, 16384, 13, 4, 16384, 13, 4, 16384, 13, 4, 16384, // 13, 4
+ 13, 5, 16384, 13, 5, 16384, 13, 5, 16384, 13, 5, 16384, // 13, 5
+ 13, 6, 16384, 13, 6, 16384, 13, 6, 16384, 13, 6, 16384, // 13, 6
+ 13, 7, 16384, 13, 7, 16384, 13, 7, 16384, 13, 7, 16384, // 13, 7
+ 13, 8, 16384, 13, 8, 16384, 13, 8, 16384, 13, 8, 16384, // 13, 8
+ 13, 9, 16384, 13, 9, 16384, 13, 9, 16384, 13, 9, 16384, // 13, 9
+ 13, 10, 16384, 13, 10, 16384, 13, 10, 16384, 13, 10, 16384, // 13,10
+ 13, 11, 16384, 13, 11, 16384, 13, 11, 16384, 13, 11, 16384, // 13,11
+ 13, 12, 16384, 13, 12, 16384, 13, 12, 16384, 13, 12, 16384, // 13,12
+ 13, 13, 16384, 13, 13, 16384, 13, 13, 16384, 13, 13, 16384, // 13,13
+ 13, 14, 16384, 13, 14, 16384, 13, 14, 16384, 13, 14, 16384, // 13,14
+ 13, 15, 16384, 13, 15, 16384, 13, 15, 16384, 13, 15, 16384, // 13,15
+ 14, 0, 16384, 14, 0, 16384, 14, 0, 16384, 14, 0, 16384, // 14, 0
+ 14, 1, 16384, 14, 1, 16384, 14, 1, 16384, 14, 1, 16384, // 14, 1
+ 14, 2, 16384, 14, 2, 16384, 14, 2, 16384, 14, 2, 16384, // 14, 2
+ 14, 3, 16384, 14, 3, 16384, 14, 3, 16384, 14, 3, 16384, // 14, 3
+ 14, 4, 16384, 14, 4, 16384, 14, 4, 16384, 14, 4, 16384, // 14, 4
+ 14, 5, 16384, 14, 5, 16384, 14, 5, 16384, 14, 5, 16384, // 14, 5
+ 14, 6, 16384, 14, 6, 16384, 14, 6, 16384, 14, 6, 16384, // 14, 6
+ 14, 7, 16384, 14, 7, 16384, 14, 7, 16384, 14, 7, 16384, // 14, 7
+ 14, 8, 16384, 14, 8, 16384, 14, 8, 16384, 14, 8, 16384, // 14, 8
+ 14, 9, 16384, 14, 9, 16384, 14, 9, 16384, 14, 9, 16384, // 14, 9
+ 14, 10, 16384, 14, 10, 16384, 14, 10, 16384, 14, 10, 16384, // 14,10
+ 14, 11, 16384, 14, 11, 16384, 14, 11, 16384, 14, 11, 16384, // 14,11
+ 14, 12, 16384, 14, 12, 16384, 14, 12, 16384, 14, 12, 16384, // 14,12
+ 14, 13, 16384, 14, 13, 16384, 14, 13, 16384, 14, 13, 16384, // 14,13
+ 14, 14, 16384, 14, 14, 16384, 14, 14, 16384, 14, 14, 16384, // 14,14
+ 14, 15, 16384, 14, 15, 16384, 14, 15, 16384, 14, 15, 16384, // 14,15
+ 15, 0, 16384, 15, 0, 16384, 15, 0, 16384, 15, 0, 16384, // 15, 0
+ 15, 1, 16384, 15, 1, 16384, 15, 1, 16384, 15, 1, 16384, // 15, 1
+ 15, 2, 16384, 15, 2, 16384, 15, 2, 16384, 15, 2, 16384, // 15, 2
+ 15, 3, 16384, 15, 3, 16384, 15, 3, 16384, 15, 3, 16384, // 15, 3
+ 15, 4, 16384, 15, 4, 16384, 15, 4, 16384, 15, 4, 16384, // 15, 4
+ 15, 5, 16384, 15, 5, 16384, 15, 5, 16384, 15, 5, 16384, // 15, 5
+ 15, 6, 16384, 15, 6, 16384, 15, 6, 16384, 15, 6, 16384, // 15, 6
+ 15, 7, 16384, 15, 7, 16384, 15, 7, 16384, 15, 7, 16384, // 15, 7
+ 15, 8, 16384, 15, 8, 16384, 15, 8, 16384, 15, 8, 16384, // 15, 8
+ 15, 9, 16384, 15, 9, 16384, 15, 9, 16384, 15, 9, 16384, // 15, 9
+ 15, 10, 16384, 15, 10, 16384, 15, 10, 16384, 15, 10, 16384, // 15,10
+ 15, 11, 16384, 15, 11, 16384, 15, 11, 16384, 15, 11, 16384, // 15,11
+ 15, 12, 16384, 15, 12, 16384, 15, 12, 16384, 15, 12, 16384, // 15,12
+ 15, 13, 16384, 15, 13, 16384, 15, 13, 16384, 15, 13, 16384, // 15,13
+ 15, 14, 16384, 15, 14, 16384, 15, 14, 16384, 15, 14, 16384, // 15,14
+ 15, 15, 16384, 15, 15, 16384, 15, 15, 16384, 15, 15, 16384, // 15,15
+ // angle of 0.5 degrees
+ 0, -1, 5106, 0, 0, 51699, 1, -1, 3621, 1, 0, 5110, // 0, 0
+ 0, 0, 4851, 0, 1, 52457, 1, 0, 3422, 1, 1, 4806, // 0, 1
+ 0, 1, 4610, 0, 2, 53168, 1, 1, 3235, 1, 2, 4523, // 0, 2
+ 0, 2, 4390, 0, 3, 53814, 1, 2, 3065, 1, 3, 4267, // 0, 3
+ 0, 3, 4200, 0, 4, 54376, 1, 3, 2917, 1, 4, 4043, // 0, 4
+ 0, 4, 4046, 0, 5, 54833, 1, 4, 2797, 1, 5, 3860, // 0, 5
+ 0, 5, 3939, 0, 6, 55164, 1, 5, 2709, 1, 6, 3724, // 0, 6
+ 0, 6, 3885, 0, 7, 55352, 1, 6, 2659, 1, 7, 3640, // 0, 7
+ -1, 7, 2659, -1, 8, 3638, 0, 7, 3885, 0, 8, 55354, // 0, 8
+ -1, 8, 2709, -1, 9, 3722, 0, 8, 3940, 0, 9, 55165, // 0, 9
+ -1, 9, 2796, -1, 10, 3858, 0, 9, 4047, 0, 10, 54835, // 0,10
+ -1, 10, 2916, -1, 11, 4041, 0, 10, 4201, 0, 11, 54378, // 0,11
+ -1, 11, 3064, -1, 12, 4264, 0, 11, 4392, 0, 12, 53816, // 0,12
+ -1, 12, 3235, -1, 13, 4521, 0, 12, 4612, 0, 13, 53168, // 0,13
+ -1, 13, 3421, -1, 14, 4803, 0, 13, 4854, 0, 14, 52458, // 0,14
+ -1, 14, 3621, -1, 15, 5106, 0, 14, 5110, 0, 15, 51699, // 0,15
+ 1, -1, 4803, 1, 0, 52457, 2, -1, 3421, 2, 0, 4855, // 1, 0
+ 1, 0, 4522, 1, 1, 53285, 2, 0, 3204, 2, 1, 4525, // 1, 1
+ 1, 1, 4253, 1, 2, 54071, 2, 1, 2998, 2, 2, 4214, // 1, 2
+ 1, 2, 4003, 1, 3, 54796, 2, 2, 2808, 2, 3, 3929, // 1, 3
+ 1, 3, 3783, 1, 4, 55434, 2, 3, 2640, 2, 4, 3679, // 1, 4
+ 1, 4, 3604, 1, 5, 55958, 2, 4, 2503, 2, 5, 3471, // 1, 5
+ 1, 5, 3476, 1, 6, 56339, 2, 5, 2403, 2, 6, 3318, // 1, 6
+ 1, 6, 3411, 1, 7, 56552, 2, 6, 2346, 2, 7, 3227, // 1, 7
+ 0, 7, 2346, 0, 8, 3225, 1, 7, 3411, 1, 8, 56554, // 1, 8
+ 0, 8, 2402, 0, 9, 3317, 1, 8, 3477, 1, 9, 56340, // 1, 9
+ 0, 9, 2502, 0, 10, 3470, 1, 9, 3605, 1, 10, 55959, // 1,10
+ 0, 10, 2640, 0, 11, 3677, 1, 10, 3785, 1, 11, 55434, // 1,11
+ 0, 11, 2808, 0, 12, 3927, 1, 11, 4005, 1, 12, 54796, // 1,12
+ 0, 12, 2998, 0, 13, 4212, 1, 12, 4255, 1, 13, 54071, // 1,13
+ 0, 13, 3204, 0, 14, 4522, 1, 13, 4525, 1, 14, 53285, // 1,14
+ 0, 14, 3422, 0, 15, 4851, 1, 14, 4806, 1, 15, 52457, // 1,15
+ 2, -1, 4521, 2, 0, 53168, 3, -1, 3235, 3, 0, 4612, // 2, 0
+ 2, 0, 4212, 2, 1, 54072, 3, 0, 2998, 3, 1, 4254, // 2, 1
+ 2, 1, 3911, 2, 2, 54941, 3, 1, 2770, 3, 2, 3914, // 2, 2
+ 2, 2, 3628, 2, 3, 55756, 3, 2, 2557, 3, 3, 3595, // 2, 3
+ 2, 3, 3373, 2, 4, 56486, 3, 3, 2365, 3, 4, 3312, // 2, 4
+ 2, 4, 3161, 2, 5, 57095, 3, 4, 2205, 3, 5, 3075, // 2, 5
+ 2, 5, 3007, 2, 6, 57544, 3, 5, 2088, 3, 6, 2897, // 2, 6
+ 2, 6, 2926, 2, 7, 57793, 3, 6, 2022, 3, 7, 2795, // 2, 7
+ 1, 7, 2022, 1, 8, 2794, 2, 7, 2926, 2, 8, 57794, // 2, 8
+ 1, 8, 2088, 1, 9, 2897, 2, 8, 3007, 2, 9, 57544, // 2, 9
+ 1, 9, 2205, 1, 10, 3073, 2, 9, 3161, 2, 10, 57097, // 2,10
+ 1, 10, 2365, 1, 11, 3310, 2, 10, 3374, 2, 11, 56487, // 2,11
+ 1, 11, 2556, 1, 12, 3594, 2, 11, 3630, 2, 12, 55756, // 2,12
+ 1, 12, 2770, 1, 13, 3911, 2, 12, 3913, 2, 13, 54942, // 2,13
+ 1, 13, 2998, 1, 14, 4253, 2, 13, 4214, 2, 14, 54071, // 2,14
+ 1, 14, 3235, 1, 15, 4610, 2, 14, 4523, 2, 15, 53168, // 2,15
+ 3, -1, 4264, 3, 0, 53815, 4, -1, 3064, 4, 0, 4393, // 3, 0
+ 3, 0, 3927, 3, 1, 54796, 4, 0, 2808, 4, 1, 4005, // 3, 1
+ 3, 1, 3594, 3, 2, 55756, 4, 1, 2556, 4, 2, 3630, // 3, 2
+ 3, 2, 3273, 3, 3, 56673, 4, 2, 2317, 4, 3, 3273, // 3, 3
+ 3, 3, 2976, 3, 4, 57514, 4, 3, 2096, 4, 4, 2950, // 3, 4
+ 3, 4, 2722, 3, 5, 58233, 4, 4, 1908, 4, 5, 2673, // 3, 5
+ 3, 5, 2532, 3, 6, 58774, 4, 5, 1767, 4, 6, 2463, // 3, 6
+ 3, 6, 2430, 3, 7, 59076, 4, 6, 1687, 4, 7, 2343, // 3, 7
+ 2, 7, 1687, 2, 8, 2342, 3, 7, 2430, 3, 8, 59077, // 3, 8
+ 2, 8, 1766, 2, 9, 2463, 3, 8, 2532, 3, 9, 58775, // 3, 9
+ 2, 9, 1908, 2, 10, 2672, 3, 9, 2723, 3, 10, 58233, // 3,10
+ 2, 10, 2096, 2, 11, 2948, 3, 10, 2977, 3, 11, 57515, // 3,11
+ 2, 11, 2317, 2, 12, 3273, 3, 11, 3274, 3, 12, 56672, // 3,12
+ 2, 12, 2557, 2, 13, 3628, 3, 12, 3595, 3, 13, 55756, // 3,13
+ 2, 13, 2808, 2, 14, 4003, 3, 13, 3929, 3, 14, 54796, // 3,14
+ 2, 14, 3065, 2, 15, 4390, 3, 14, 4267, 3, 15, 53814, // 3,15
+ 4, -1, 4041, 4, 0, 54378, 5, -1, 2916, 5, 0, 4201, // 4, 0
+ 4, 0, 3677, 4, 1, 55435, 5, 0, 2640, 5, 1, 3784, // 4, 1
+ 4, 1, 3310, 4, 2, 56487, 5, 1, 2365, 5, 2, 3374, // 4, 2
+ 4, 2, 2948, 4, 3, 57514, 5, 2, 2096, 5, 3, 2978, // 4, 3
+ 4, 3, 2604, 4, 4, 58484, 5, 3, 1843, 5, 4, 2605, // 4, 4
+ 4, 4, 2297, 4, 5, 59345, 5, 4, 1617, 5, 5, 2277, // 4, 5
+ 4, 5, 2057, 4, 6, 60017, 5, 5, 1442, 5, 6, 2020, // 4, 6
+ 4, 6, 1922, 4, 7, 60402, 5, 6, 1341, 5, 7, 1871, // 4, 7
+ 3, 7, 1341, 3, 8, 1871, 4, 7, 1922, 4, 8, 60402, // 4, 8
+ 3, 8, 1442, 3, 9, 2020, 4, 8, 2057, 4, 9, 60017, // 4, 9
+ 3, 9, 1617, 3, 10, 2276, 4, 9, 2297, 4, 10, 59346, // 4,10
+ 3, 10, 1843, 3, 11, 2604, 4, 10, 2605, 4, 11, 58484, // 4,11
+ 3, 11, 2096, 3, 12, 2976, 4, 11, 2950, 4, 12, 57514, // 4,12
+ 3, 12, 2365, 3, 13, 3373, 4, 12, 3311, 4, 13, 56487, // 4,13
+ 3, 13, 2640, 3, 14, 3783, 4, 13, 3678, 4, 14, 55435, // 4,14
+ 3, 14, 2917, 3, 15, 4200, 4, 14, 4043, 4, 15, 54376, // 4,15
+ 5, -1, 3858, 5, 0, 54835, 6, -1, 2796, 6, 0, 4047, // 5, 0
+ 5, 0, 3470, 5, 1, 55959, 6, 0, 2502, 6, 1, 3605, // 5, 1
+ 5, 1, 3073, 5, 2, 57096, 6, 1, 2205, 6, 2, 3162, // 5, 2
+ 5, 2, 2672, 5, 3, 58234, 6, 2, 1908, 6, 3, 2722, // 5, 3
+ 5, 3, 2276, 5, 4, 59346, 6, 3, 1617, 6, 4, 2297, // 5, 4
+ 5, 4, 1904, 5, 5, 60381, 6, 4, 1347, 6, 5, 1904, // 5, 5
+ 5, 5, 1593, 5, 6, 61243, 6, 5, 1121, 6, 6, 1579, // 5, 6
+ 5, 6, 1405, 5, 7, 61767, 6, 6, 985, 6, 7, 1379, // 5, 7
+ 4, 7, 985, 4, 8, 1380, 5, 7, 1405, 5, 8, 61766, // 5, 8
+ 4, 8, 1121, 4, 9, 1578, 5, 8, 1593, 5, 9, 61244, // 5, 9
+ 4, 9, 1347, 4, 10, 1904, 5, 9, 1904, 5, 10, 60381, // 5,10
+ 4, 10, 1617, 4, 11, 2297, 5, 10, 2276, 5, 11, 59346, // 5,11
+ 4, 11, 1908, 4, 12, 2722, 5, 11, 2673, 5, 12, 58233, // 5,12
+ 4, 12, 2205, 4, 13, 3161, 5, 12, 3074, 5, 13, 57096, // 5,13
+ 4, 13, 2503, 4, 14, 3604, 5, 13, 3472, 5, 14, 55957, // 5,14
+ 4, 14, 2797, 4, 15, 4046, 5, 14, 3860, 5, 15, 54833, // 5,15
+ 6, -1, 3722, 6, 0, 55166, 7, -1, 2709, 7, 0, 3939, // 6, 0
+ 6, 0, 3317, 6, 1, 56340, 7, 0, 2402, 7, 1, 3477, // 6, 1
+ 6, 1, 2897, 6, 2, 57545, 7, 1, 2088, 7, 2, 3006, // 6, 2
+ 6, 2, 2463, 6, 3, 58775, 7, 2, 1766, 7, 3, 2532, // 6, 3
+ 6, 3, 2020, 6, 4, 60018, 7, 3, 1442, 7, 4, 2056, // 6, 4
+ 6, 4, 1578, 6, 5, 61243, 7, 4, 1121, 7, 5, 1594, // 6, 5
+ 6, 5, 1170, 6, 6, 62369, 7, 5, 827, 7, 6, 1170, // 6, 6
+ 6, 6, 883, 6, 7, 63156, 7, 6, 622, 7, 7, 875, // 6, 7
+ 5, 7, 622, 5, 8, 875, 6, 7, 883, 6, 8, 63156, // 6, 8
+ 5, 8, 827, 5, 9, 1170, 6, 8, 1170, 6, 9, 62369, // 6, 9
+ 5, 9, 1121, 5, 10, 1593, 6, 9, 1579, 6, 10, 61243, // 6,10
+ 5, 10, 1442, 5, 11, 2057, 6, 10, 2020, 6, 11, 60017, // 6,11
+ 5, 11, 1767, 5, 12, 2532, 6, 11, 2464, 6, 12, 58773, // 6,12
+ 5, 12, 2088, 5, 13, 3007, 6, 12, 2898, 6, 13, 57543, // 6,13
+ 5, 13, 2403, 5, 14, 3476, 6, 13, 3319, 6, 14, 56338, // 6,14
+ 5, 14, 2709, 5, 15, 3939, 6, 14, 3724, 6, 15, 55164, // 6,15
+ 7, -1, 3638, 7, 0, 55354, 8, -1, 2659, 8, 0, 3885, // 7, 0
+ 7, 0, 3225, 7, 1, 56554, 8, 0, 2346, 8, 1, 3411, // 7, 1
+ 7, 1, 2794, 7, 2, 57795, 8, 1, 2022, 8, 2, 2925, // 7, 2
+ 7, 2, 2342, 7, 3, 59077, 8, 2, 1687, 8, 3, 2430, // 7, 3
+ 7, 3, 1871, 7, 4, 60402, 8, 3, 1341, 8, 4, 1922, // 7, 4
+ 7, 4, 1380, 7, 5, 61767, 8, 4, 985, 8, 5, 1404, // 7, 5
+ 7, 5, 875, 7, 6, 63156, 8, 5, 622, 8, 6, 883, // 7, 6
+ 7, 6, 399, 7, 7, 64455, 8, 6, 282, 8, 7, 400, // 7, 7
+ 6, 7, 282, 6, 8, 399, 7, 7, 399, 7, 8, 64456, // 7, 8
+ 6, 8, 622, 6, 9, 883, 7, 8, 875, 7, 9, 63156, // 7, 9
+ 6, 9, 985, 6, 10, 1405, 7, 9, 1380, 7, 10, 61766, // 7,10
+ 6, 10, 1341, 6, 11, 1922, 7, 10, 1871, 7, 11, 60402, // 7,11
+ 6, 11, 1687, 6, 12, 2430, 7, 11, 2343, 7, 12, 59076, // 7,12
+ 6, 12, 2022, 6, 13, 2926, 7, 12, 2795, 7, 13, 57793, // 7,13
+ 6, 13, 2346, 6, 14, 3411, 7, 13, 3227, 7, 14, 56552, // 7,14
+ 6, 14, 2659, 6, 15, 3885, 7, 14, 3640, 7, 15, 55352, // 7,15
+ 8, 0, 55352, 8, 1, 3640, 9, 0, 3885, 9, 1, 2659, // 8, 0
+ 8, 1, 56552, 8, 2, 3227, 9, 1, 3411, 9, 2, 2346, // 8, 1
+ 8, 2, 57793, 8, 3, 2795, 9, 2, 2926, 9, 3, 2022, // 8, 2
+ 8, 3, 59076, 8, 4, 2343, 9, 3, 2430, 9, 4, 1687, // 8, 3
+ 8, 4, 60402, 8, 5, 1871, 9, 4, 1922, 9, 5, 1341, // 8, 4
+ 8, 5, 61767, 8, 6, 1380, 9, 5, 1405, 9, 6, 984, // 8, 5
+ 8, 6, 63156, 8, 7, 875, 9, 6, 883, 9, 7, 622, // 8, 6
+ 8, 7, 64455, 8, 8, 399, 9, 7, 399, 9, 8, 283, // 8, 7
+ 7, 8, 399, 7, 9, 282, 8, 8, 64455, 8, 9, 400, // 8, 8
+ 7, 9, 883, 7, 10, 622, 8, 9, 63156, 8, 10, 875, // 8, 9
+ 7, 10, 1405, 7, 11, 985, 8, 10, 61767, 8, 11, 1379, // 8,10
+ 7, 11, 1922, 7, 12, 1341, 8, 11, 60402, 8, 12, 1871, // 8,11
+ 7, 12, 2430, 7, 13, 1687, 8, 12, 59077, 8, 13, 2342, // 8,12
+ 7, 13, 2926, 7, 14, 2022, 8, 13, 57795, 8, 14, 2793, // 8,13
+ 7, 14, 3411, 7, 15, 2346, 8, 14, 56554, 8, 15, 3225, // 8,14
+ 7, 15, 3885, 7, 16, 2659, 8, 15, 55354, 8, 16, 3638, // 8,15
+ 9, 0, 55164, 9, 1, 3724, 10, 0, 3939, 10, 1, 2709, // 9, 0
+ 9, 1, 56339, 9, 2, 3319, 10, 1, 3476, 10, 2, 2402, // 9, 1
+ 9, 2, 57544, 9, 3, 2898, 10, 2, 3007, 10, 3, 2087, // 9, 2
+ 9, 3, 58774, 9, 4, 2464, 10, 3, 2532, 10, 4, 1766, // 9, 3
+ 9, 4, 60017, 9, 5, 2020, 10, 4, 2057, 10, 5, 1442, // 9, 4
+ 9, 5, 61243, 9, 6, 1579, 10, 5, 1593, 10, 6, 1121, // 9, 5
+ 9, 6, 62369, 9, 7, 1170, 10, 6, 1170, 10, 7, 827, // 9, 6
+ 9, 7, 63156, 9, 8, 883, 10, 7, 875, 10, 8, 622, // 9, 7
+ 8, 8, 875, 8, 9, 622, 9, 8, 63156, 9, 9, 883, // 9, 8
+ 8, 9, 1170, 8, 10, 827, 9, 9, 62369, 9, 10, 1170, // 9, 9
+ 8, 10, 1593, 8, 11, 1121, 9, 10, 61243, 9, 11, 1579, // 9,10
+ 8, 11, 2057, 8, 12, 1442, 9, 11, 60018, 9, 12, 2019, // 9,11
+ 8, 12, 2532, 8, 13, 1766, 9, 12, 58775, 9, 13, 2463, // 9,12
+ 8, 13, 3007, 8, 14, 2088, 9, 13, 57545, 9, 14, 2896, // 9,13
+ 8, 14, 3477, 8, 15, 2402, 9, 14, 56340, 9, 15, 3317, // 9,14
+ 8, 15, 3940, 8, 16, 2709, 9, 15, 55166, 9, 16, 3721, // 9,15
+ 10, 0, 54833, 10, 1, 3860, 11, 0, 4046, 11, 1, 2797, // 10, 0
+ 10, 1, 55958, 10, 2, 3472, 11, 1, 3604, 11, 2, 2502, // 10, 1
+ 10, 2, 57095, 10, 3, 3074, 11, 2, 3161, 11, 3, 2206, // 10, 2
+ 10, 3, 58233, 10, 4, 2673, 11, 3, 2722, 11, 4, 1908, // 10, 3
+ 10, 4, 59345, 10, 5, 2276, 11, 4, 2297, 11, 5, 1618, // 10, 4
+ 10, 5, 60381, 10, 6, 1904, 11, 5, 1904, 11, 6, 1347, // 10, 5
+ 10, 6, 61243, 10, 7, 1593, 11, 6, 1578, 11, 7, 1122, // 10, 6
+ 10, 7, 61767, 10, 8, 1405, 11, 7, 1380, 11, 8, 984, // 10, 7
+ 9, 8, 1380, 9, 9, 985, 10, 8, 61767, 10, 9, 1404, // 10, 8
+ 9, 9, 1579, 9, 10, 1121, 10, 9, 61243, 10, 10, 1593, // 10, 9
+ 9, 10, 1904, 9, 11, 1347, 10, 10, 60381, 10, 11, 1904, // 10,10
+ 9, 11, 2297, 9, 12, 1617, 10, 11, 59346, 10, 12, 2276, // 10,11
+ 9, 12, 2723, 9, 13, 1908, 10, 12, 58234, 10, 13, 2671, // 10,12
+ 9, 13, 3161, 9, 14, 2205, 10, 13, 57096, 10, 14, 3074, // 10,13
+ 9, 14, 3605, 9, 15, 2502, 10, 14, 55959, 10, 15, 3470, // 10,14
+ 9, 15, 4047, 9, 16, 2796, 10, 15, 54835, 10, 16, 3858, // 10,15
+ 11, 0, 54376, 11, 1, 4043, 12, 0, 4200, 12, 1, 2917, // 11, 0
+ 11, 1, 55434, 11, 2, 3678, 12, 1, 3783, 12, 2, 2641, // 11, 1
+ 11, 2, 56486, 11, 3, 3311, 12, 2, 3373, 12, 3, 2366, // 11, 2
+ 11, 3, 57514, 11, 4, 2950, 12, 3, 2976, 12, 4, 2096, // 11, 3
+ 11, 4, 58484, 11, 5, 2605, 12, 4, 2604, 12, 5, 1843, // 11, 4
+ 11, 5, 59346, 11, 6, 2297, 12, 5, 2276, 12, 6, 1617, // 11, 5
+ 11, 6, 60018, 11, 7, 2057, 12, 6, 2020, 12, 7, 1441, // 11, 6
+ 11, 7, 60402, 11, 8, 1922, 12, 7, 1871, 12, 8, 1341, // 11, 7
+ 10, 8, 1871, 10, 9, 1341, 11, 8, 60402, 11, 9, 1922, // 11, 8
+ 10, 9, 2020, 10, 10, 1442, 11, 9, 60017, 11, 10, 2057, // 11, 9
+ 10, 10, 2276, 10, 11, 1617, 11, 10, 59345, 11, 11, 2298, // 11,10
+ 10, 11, 2605, 10, 12, 1843, 11, 11, 58484, 11, 12, 2604, // 11,11
+ 10, 12, 2977, 10, 13, 2096, 11, 12, 57514, 11, 13, 2949, // 11,12
+ 10, 13, 3374, 10, 14, 2365, 11, 13, 56487, 11, 14, 3310, // 11,13
+ 10, 14, 3785, 10, 15, 2640, 11, 14, 55435, 11, 15, 3676, // 11,14
+ 10, 15, 4201, 10, 16, 2916, 11, 15, 54378, 11, 16, 4041, // 11,15
+ 12, 0, 53814, 12, 1, 4267, 13, 0, 4390, 13, 1, 3065, // 12, 0
+ 12, 1, 54796, 12, 2, 3929, 13, 1, 4003, 13, 2, 2808, // 12, 1
+ 12, 2, 55756, 12, 3, 3595, 13, 2, 3628, 13, 3, 2557, // 12, 2
+ 12, 3, 56673, 12, 4, 3274, 13, 3, 3273, 13, 4, 2316, // 12, 3
+ 12, 4, 57514, 12, 5, 2977, 13, 4, 2948, 13, 5, 2097, // 12, 4
+ 12, 5, 58234, 12, 6, 2723, 13, 5, 2672, 13, 6, 1907, // 12, 5
+ 12, 6, 58775, 12, 7, 2532, 13, 6, 2463, 13, 7, 1766, // 12, 6
+ 12, 7, 59077, 12, 8, 2430, 13, 7, 2342, 13, 8, 1687, // 12, 7
+ 11, 8, 2343, 11, 9, 1687, 12, 8, 59076, 12, 9, 2430, // 12, 8
+ 11, 9, 2464, 11, 10, 1767, 12, 9, 58774, 12, 10, 2531, // 12, 9
+ 11, 10, 2673, 11, 11, 1908, 12, 10, 58233, 12, 11, 2722, // 12,10
+ 11, 11, 2950, 11, 12, 2096, 12, 11, 57514, 12, 12, 2976, // 12,11
+ 11, 12, 3274, 11, 13, 2317, 12, 12, 56673, 12, 13, 3272, // 12,12
+ 11, 13, 3630, 11, 14, 2556, 12, 13, 55756, 12, 14, 3594, // 12,13
+ 11, 14, 4005, 11, 15, 2808, 12, 14, 54796, 12, 15, 3927, // 12,14
+ 11, 15, 4392, 11, 16, 3064, 12, 15, 53815, 12, 16, 4265, // 12,15
+ 13, 0, 53168, 13, 1, 4523, 14, 0, 4610, 14, 1, 3235, // 13, 0
+ 13, 1, 54071, 13, 2, 4214, 14, 1, 4253, 14, 2, 2998, // 13, 1
+ 13, 2, 54941, 13, 3, 3913, 14, 2, 3911, 14, 3, 2771, // 13, 2
+ 13, 3, 55756, 13, 4, 3630, 14, 3, 3594, 14, 4, 2556, // 13, 3
+ 13, 4, 56487, 13, 5, 3374, 14, 4, 3310, 14, 5, 2365, // 13, 4
+ 13, 5, 57096, 13, 6, 3161, 14, 5, 3073, 14, 6, 2206, // 13, 5
+ 13, 6, 57545, 13, 7, 3007, 14, 6, 2897, 14, 7, 2087, // 13, 6
+ 13, 7, 57795, 13, 8, 2926, 14, 7, 2794, 14, 8, 2021, // 13, 7
+ 12, 8, 2795, 12, 9, 2022, 13, 8, 57793, 13, 9, 2926, // 13, 8
+ 12, 9, 2898, 12, 10, 2088, 13, 9, 57544, 13, 10, 3006, // 13, 9
+ 12, 10, 3074, 12, 11, 2205, 13, 10, 57095, 13, 11, 3162, // 13,10
+ 12, 11, 3311, 12, 12, 2365, 13, 11, 56486, 13, 12, 3374, // 13,11
+ 12, 12, 3595, 12, 13, 2557, 13, 12, 55756, 13, 13, 3628, // 13,12
+ 12, 13, 3913, 12, 14, 2770, 13, 13, 54941, 13, 14, 3912, // 13,13
+ 12, 14, 4255, 12, 15, 2998, 13, 14, 54072, 13, 15, 4211, // 13,14
+ 12, 15, 4612, 12, 16, 3235, 13, 15, 53168, 13, 16, 4521, // 13,15
+ 14, 0, 52457, 14, 1, 4806, 15, 0, 4851, 15, 1, 3422, // 14, 0
+ 14, 1, 53285, 14, 2, 4525, 15, 1, 4522, 15, 2, 3204, // 14, 1
+ 14, 2, 54072, 14, 3, 4255, 15, 2, 4212, 15, 3, 2997, // 14, 2
+ 14, 3, 54796, 14, 4, 4005, 15, 3, 3927, 15, 4, 2808, // 14, 3
+ 14, 4, 55435, 14, 5, 3785, 15, 4, 3677, 15, 5, 2639, // 14, 4
+ 14, 5, 55959, 14, 6, 3605, 15, 5, 3470, 15, 6, 2502, // 14, 5
+ 14, 6, 56340, 14, 7, 3477, 15, 6, 3317, 15, 7, 2402, // 14, 6
+ 14, 7, 56554, 14, 8, 3411, 15, 7, 3225, 15, 8, 2346, // 14, 7
+ 13, 8, 3227, 13, 9, 2346, 14, 8, 56552, 14, 9, 3411, // 14, 8
+ 13, 9, 3319, 13, 10, 2403, 14, 9, 56339, 14, 10, 3475, // 14, 9
+ 13, 10, 3472, 13, 11, 2503, 14, 10, 55958, 14, 11, 3603, // 14,10
+ 13, 11, 3678, 13, 12, 2640, 14, 11, 55434, 14, 12, 3784, // 14,11
+ 13, 12, 3929, 13, 13, 2808, 14, 12, 54796, 14, 13, 4003, // 14,12
+ 13, 13, 4214, 13, 14, 2998, 14, 13, 54071, 14, 14, 4253, // 14,13
+ 13, 14, 4525, 13, 15, 3204, 14, 14, 53285, 14, 15, 4522, // 14,14
+ 13, 15, 4854, 13, 16, 3421, 14, 15, 52457, 14, 16, 4804, // 14,15
+ 15, 0, 51699, 15, 1, 5110, 16, 0, 5106, 16, 1, 3621, // 15, 0
+ 15, 1, 52457, 15, 2, 4854, 16, 1, 4803, 16, 2, 3422, // 15, 1
+ 15, 2, 53168, 15, 3, 4612, 16, 2, 4521, 16, 3, 3235, // 15, 2
+ 15, 3, 53815, 15, 4, 4392, 16, 3, 4264, 16, 4, 3065, // 15, 3
+ 15, 4, 54378, 15, 5, 4201, 16, 4, 4041, 16, 5, 2916, // 15, 4
+ 15, 5, 54835, 15, 6, 4047, 16, 5, 3858, 16, 6, 2796, // 15, 5
+ 15, 6, 55166, 15, 7, 3940, 16, 6, 3722, 16, 7, 2708, // 15, 6
+ 15, 7, 55354, 15, 8, 3885, 16, 7, 3638, 16, 8, 2659, // 15, 7
+ 14, 8, 3640, 14, 9, 2659, 15, 8, 55352, 15, 9, 3885, // 15, 8
+ 14, 9, 3724, 14, 10, 2709, 15, 9, 55164, 15, 10, 3939, // 15, 9
+ 14, 10, 3860, 14, 11, 2797, 15, 10, 54833, 15, 11, 4046, // 15,10
+ 14, 11, 4043, 14, 12, 2917, 15, 11, 54376, 15, 12, 4200, // 15,11
+ 14, 12, 4267, 14, 13, 3065, 15, 12, 53814, 15, 13, 4390, // 15,12
+ 14, 13, 4523, 14, 14, 3235, 15, 13, 53168, 15, 14, 4610, // 15,13
+ 14, 14, 4806, 14, 15, 3422, 15, 14, 52457, 15, 15, 4851, // 15,14
+ 14, 15, 5110, 14, 16, 3621, 15, 15, 51699, 15, 16, 5106, // 15,15
+ // angle of 1.0 degrees
+ 0, -1, 8769, 0, 0, 41693, 1, -1, 6280, 1, 0, 8794, // 0, 0
+ 0, 0, 8452, 0, 1, 42821, 1, 0, 5975, 1, 1, 8288, // 0, 1
+ 0, 1, 8141, 0, 2, 43900, 1, 1, 5684, 1, 2, 7811, // 0, 2
+ 0, 2, 7848, 0, 3, 44901, 1, 2, 5413, 1, 3, 7374, // 0, 3
+ 0, 3, 7587, 0, 4, 45791, 1, 3, 5172, 1, 4, 6986, // 0, 4
+ 0, 4, 7374, 0, 5, 46532, 1, 4, 4971, 1, 5, 6659, // 0, 5
+ 0, 5, 7227, 0, 6, 47086, 1, 5, 4818, 1, 6, 6405, // 0, 6
+ 0, 6, 7158, 0, 7, 47426, 1, 6, 4722, 1, 7, 6230, // 0, 7
+ -1, 7, 4718, -1, 8, 6217, 0, 7, 7161, 0, 8, 47440, // 0, 8
+ -1, 8, 4814, -1, 9, 6391, 0, 8, 7233, 0, 9, 47098, // 0, 9
+ -1, 9, 4967, -1, 10, 6644, 0, 9, 7383, 0, 10, 46542, // 0,10
+ -1, 10, 5169, -1, 11, 6970, 0, 10, 7599, 0, 11, 45798, // 0,11
+ -1, 11, 5410, -1, 12, 7356, 0, 11, 7863, 0, 12, 44907, // 0,12
+ -1, 12, 5682, -1, 13, 7791, 0, 12, 8159, 0, 13, 43904, // 0,13
+ -1, 13, 5974, -1, 14, 8265, 0, 13, 8474, 0, 14, 42823, // 0,14
+ -1, 14, 6280, -1, 15, 8769, 0, 14, 8795, 0, 15, 41692, // 0,15
+ 1, -1, 8265, 1, 0, 42823, 2, -1, 5974, 2, 0, 8474, // 1, 0
+ 1, 0, 7901, 1, 1, 44074, 2, 0, 5640, 2, 1, 7921, // 1, 1
+ 1, 1, 7539, 1, 2, 45286, 2, 1, 5316, 2, 2, 7395, // 1, 2
+ 1, 2, 7191, 1, 3, 46427, 2, 2, 5011, 2, 3, 6907, // 1, 3
+ 1, 3, 6875, 1, 4, 47453, 2, 3, 4736, 2, 4, 6472, // 1, 4
+ 1, 4, 6613, 1, 5, 48314, 2, 4, 4505, 2, 5, 6104, // 1, 5
+ 1, 5, 6425, 1, 6, 48960, 2, 5, 4330, 2, 6, 5821, // 1, 6
+ 1, 6, 6332, 1, 7, 49347, 2, 6, 4224, 2, 7, 5633, // 1, 7
+ 0, 7, 4221, 0, 8, 5623, 1, 7, 6335, 1, 8, 49357, // 1, 8
+ 0, 8, 4327, 0, 9, 5809, 1, 8, 6430, 1, 9, 48970, // 1, 9
+ 0, 9, 4502, 0, 10, 6092, 1, 9, 6620, 1, 10, 48322, // 1,10
+ 0, 10, 4734, 0, 11, 6458, 1, 10, 6886, 1, 11, 47458, // 1,11
+ 0, 11, 5009, 0, 12, 6892, 1, 11, 7204, 1, 12, 46431, // 1,12
+ 0, 12, 5315, 0, 13, 7378, 1, 12, 7555, 1, 13, 45288, // 1,13
+ 0, 13, 5640, 0, 14, 7901, 1, 13, 7921, 1, 14, 44074, // 1,14
+ 0, 14, 5975, 0, 15, 8452, 1, 14, 8288, 1, 15, 42821, // 1,15
+ 2, -1, 7791, 2, 0, 43904, 3, -1, 5682, 3, 0, 8159, // 2, 0
+ 2, 0, 7378, 2, 1, 45288, 3, 0, 5315, 3, 1, 7555, // 2, 1
+ 2, 1, 6959, 2, 2, 46650, 3, 1, 4954, 3, 2, 6973, // 2, 2
+ 2, 2, 6549, 2, 3, 47953, 3, 2, 4608, 3, 3, 6426, // 2, 3
+ 2, 3, 6168, 2, 4, 49147, 3, 3, 4291, 3, 4, 5930, // 2, 4
+ 2, 4, 5842, 2, 5, 50165, 3, 4, 4020, 3, 5, 5509, // 2, 5
+ 2, 5, 5602, 2, 6, 50935, 3, 5, 3815, 3, 6, 5184, // 2, 6
+ 2, 6, 5478, 2, 7, 51387, 3, 6, 3693, 3, 7, 4978, // 2, 7
+ 1, 7, 3691, 1, 8, 4970, 2, 7, 5480, 2, 8, 51395, // 2, 8
+ 1, 8, 3813, 1, 9, 5175, 2, 8, 5606, 2, 9, 50942, // 2, 9
+ 1, 9, 4019, 1, 10, 5499, 2, 9, 5848, 2, 10, 50170, // 2,10
+ 1, 10, 4290, 1, 11, 5920, 2, 10, 6176, 2, 11, 49150, // 2,11
+ 1, 11, 4607, 1, 12, 6414, 2, 11, 6560, 2, 12, 47955, // 2,12
+ 1, 12, 4954, 1, 13, 6959, 2, 12, 6973, 2, 13, 46650, // 2,13
+ 1, 13, 5316, 1, 14, 7539, 2, 13, 7395, 2, 14, 45286, // 2,14
+ 1, 14, 5684, 1, 15, 8141, 2, 14, 7812, 2, 15, 43899, // 2,15
+ 3, -1, 7356, 3, 0, 44907, 4, -1, 5410, 4, 0, 7863, // 3, 0
+ 3, 0, 6892, 3, 1, 46430, 4, 0, 5009, 4, 1, 7205, // 3, 1
+ 3, 1, 6414, 3, 2, 47955, 4, 1, 4607, 4, 2, 6560, // 3, 2
+ 3, 2, 5934, 3, 3, 49445, 4, 2, 4214, 4, 3, 5943, // 3, 3
+ 3, 3, 5474, 3, 4, 50843, 4, 3, 3846, 4, 4, 5373, // 3, 4
+ 3, 4, 5069, 3, 5, 52066, 4, 4, 3523, 4, 5, 4878, // 3, 5
+ 3, 5, 4759, 3, 6, 53008, 4, 5, 3274, 4, 6, 4495, // 3, 6
+ 3, 6, 4592, 3, 7, 53557, 4, 6, 3128, 4, 7, 4259, // 3, 7
+ 2, 7, 3126, 2, 8, 4254, 3, 7, 4594, 3, 8, 53562, // 3, 8
+ 2, 8, 3273, 2, 9, 4489, 3, 8, 4762, 3, 9, 53012, // 3, 9
+ 2, 9, 3522, 2, 10, 4872, 3, 9, 5073, 3, 10, 52069, // 3,10
+ 2, 10, 3845, 2, 11, 5365, 3, 10, 5481, 3, 11, 50845, // 3,11
+ 2, 11, 4214, 2, 12, 5934, 3, 11, 5943, 3, 12, 49445, // 3,12
+ 2, 12, 4608, 2, 13, 6549, 3, 12, 6426, 3, 13, 47953, // 3,13
+ 2, 13, 5011, 2, 14, 7191, 3, 13, 6908, 3, 14, 46426, // 3,14
+ 2, 14, 5413, 2, 15, 7848, 3, 14, 7374, 3, 15, 44901, // 3,15
+ 4, -1, 6970, 4, 0, 45799, 5, -1, 5169, 5, 0, 7598, // 4, 0
+ 4, 0, 6458, 4, 1, 47458, 5, 0, 4734, 5, 1, 6886, // 4, 1
+ 4, 1, 5920, 4, 2, 49150, 5, 1, 4290, 5, 2, 6176, // 4, 2
+ 4, 2, 5365, 4, 3, 50844, 5, 2, 3845, 5, 3, 5482, // 4, 3
+ 4, 3, 4816, 4, 4, 52484, 5, 3, 3415, 5, 4, 4821, // 4, 4
+ 4, 4, 4309, 4, 5, 53973, 5, 4, 3023, 5, 5, 4231, // 4, 5
+ 4, 5, 3902, 4, 6, 55164, 5, 5, 2711, 5, 6, 3759, // 4, 6
+ 4, 6, 3671, 4, 7, 55867, 5, 6, 2525, 5, 7, 3473, // 4, 7
+ 3, 7, 2524, 3, 8, 3469, 4, 7, 3672, 4, 8, 55871, // 4, 8
+ 3, 8, 2710, 3, 9, 3755, 4, 8, 3904, 4, 9, 55167, // 4, 9
+ 3, 9, 3023, 3, 10, 4226, 4, 9, 4313, 4, 10, 53974, // 4,10
+ 3, 10, 3415, 3, 11, 4816, 4, 10, 4822, 4, 11, 52483, // 4,11
+ 3, 11, 3846, 3, 12, 5474, 4, 11, 5373, 4, 12, 50843, // 4,12
+ 3, 12, 4291, 3, 13, 6168, 4, 12, 5930, 4, 13, 49147, // 4,13
+ 3, 13, 4736, 3, 14, 6875, 4, 13, 6472, 4, 14, 47453, // 4,14
+ 3, 14, 5172, 3, 15, 7587, 4, 14, 6986, 4, 15, 45791, // 4,15
+ 5, -1, 6644, 5, 0, 46541, 6, -1, 4967, 6, 0, 7384, // 5, 0
+ 5, 0, 6092, 5, 1, 48322, 6, 0, 4502, 6, 1, 6620, // 5, 1
+ 5, 1, 5499, 5, 2, 50171, 6, 1, 4019, 6, 2, 5847, // 5, 2
+ 5, 2, 4872, 5, 3, 52069, 6, 2, 3522, 6, 3, 5073, // 5, 3
+ 5, 3, 4226, 5, 4, 53975, 6, 3, 3023, 6, 4, 4312, // 5, 4
+ 5, 4, 3595, 5, 5, 55798, 6, 4, 2546, 6, 5, 3597, // 5, 5
+ 5, 5, 3050, 5, 6, 57353, 6, 5, 2138, 6, 6, 2995, // 5, 6
+ 5, 6, 2713, 5, 7, 58322, 6, 6, 1884, 6, 7, 2617, // 5, 7
+ 4, 7, 1884, 4, 8, 2615, 5, 7, 2714, 5, 8, 58323, // 5, 8
+ 4, 8, 2138, 4, 9, 2993, 5, 8, 3051, 5, 9, 57354, // 5, 9
+ 4, 9, 2546, 4, 10, 3595, 5, 9, 3598, 5, 10, 55797, // 5,10
+ 4, 10, 3023, 4, 11, 4309, 5, 10, 4230, 5, 11, 53974, // 5,11
+ 4, 11, 3523, 4, 12, 5069, 5, 11, 4879, 5, 12, 52065, // 5,12
+ 4, 12, 4020, 4, 13, 5842, 5, 12, 5508, 5, 13, 50166, // 5,13
+ 4, 13, 4505, 4, 14, 6613, 5, 13, 6104, 5, 14, 48314, // 5,14
+ 4, 14, 4971, 4, 15, 7374, 5, 14, 6659, 5, 15, 46532, // 5,15
+ 6, -1, 6391, 6, 0, 47098, 7, -1, 4814, 7, 0, 7233, // 6, 0
+ 6, 0, 5809, 6, 1, 48969, 7, 0, 4327, 7, 1, 6431, // 6, 1
+ 6, 1, 5175, 6, 2, 50942, 7, 1, 3813, 7, 2, 5606, // 6, 2
+ 6, 2, 4489, 6, 3, 53012, 7, 2, 3273, 7, 3, 4762, // 6, 3
+ 6, 3, 3755, 6, 4, 55166, 7, 3, 2710, 7, 4, 3905, // 6, 4
+ 6, 4, 2993, 6, 5, 57354, 7, 4, 2138, 7, 5, 3051, // 6, 5
+ 6, 5, 2258, 6, 6, 59422, 7, 5, 1597, 7, 6, 2259, // 6, 6
+ 6, 6, 1726, 6, 7, 60905, 7, 6, 1210, 7, 7, 1695, // 6, 7
+ 5, 7, 1209, 5, 8, 1695, 6, 7, 1726, 6, 8, 60906, // 6, 8
+ 5, 8, 1597, 5, 9, 2258, 6, 8, 2259, 6, 9, 59422, // 6, 9
+ 5, 9, 2138, 5, 10, 3050, 6, 9, 2995, 6, 10, 57353, // 6,10
+ 5, 10, 2711, 5, 11, 3902, 6, 10, 3759, 6, 11, 55164, // 6,11
+ 5, 11, 3274, 5, 12, 4759, 6, 11, 4495, 6, 12, 53008, // 6,12
+ 5, 12, 3815, 5, 13, 5602, 6, 12, 5184, 6, 13, 50935, // 6,13
+ 5, 13, 4330, 5, 14, 6425, 6, 13, 5820, 6, 14, 48961, // 6,14
+ 5, 14, 4818, 5, 15, 7227, 6, 14, 6405, 6, 15, 47086, // 6,15
+ 7, -1, 6217, 7, 0, 47440, 8, -1, 4718, 8, 0, 7161, // 7, 0
+ 7, 0, 5623, 7, 1, 49358, 8, 0, 4221, 8, 1, 6334, // 7, 1
+ 7, 1, 4970, 7, 2, 51395, 8, 1, 3691, 8, 2, 5480, // 7, 2
+ 7, 2, 4254, 7, 3, 53562, 8, 2, 3126, 8, 3, 4594, // 7, 3
+ 7, 3, 3469, 7, 4, 55870, 8, 3, 2524, 8, 4, 3673, // 7, 4
+ 7, 4, 2615, 7, 5, 58324, 8, 4, 1884, 8, 5, 2713, // 7, 5
+ 7, 5, 1695, 7, 6, 60906, 8, 5, 1209, 8, 6, 1726, // 7, 6
+ 7, 6, 789, 7, 7, 63399, 8, 6, 558, 8, 7, 790, // 7, 7
+ 6, 7, 558, 6, 8, 789, 7, 7, 789, 7, 8, 63400, // 7, 8
+ 6, 8, 1210, 6, 9, 1726, 7, 8, 1695, 7, 9, 60905, // 7, 9
+ 6, 9, 1884, 6, 10, 2713, 7, 9, 2616, 7, 10, 58323, // 7,10
+ 6, 10, 2525, 6, 11, 3671, 7, 10, 3473, 7, 11, 55867, // 7,11
+ 6, 11, 3128, 6, 12, 4592, 7, 11, 4259, 7, 12, 53557, // 7,12
+ 6, 12, 3693, 6, 13, 5478, 7, 12, 4978, 7, 13, 51387, // 7,13
+ 6, 13, 4224, 6, 14, 6332, 7, 13, 5633, 7, 14, 49347, // 7,14
+ 6, 14, 4722, 6, 15, 7158, 7, 14, 6230, 7, 15, 47426, // 7,15
+ 8, 0, 47426, 8, 1, 6230, 9, 0, 7158, 9, 1, 4722, // 8, 0
+ 8, 1, 49347, 8, 2, 5633, 9, 1, 6332, 9, 2, 4224, // 8, 1
+ 8, 2, 51387, 8, 3, 4978, 9, 2, 5478, 9, 3, 3693, // 8, 2
+ 8, 3, 53557, 8, 4, 4259, 9, 3, 4592, 9, 4, 3128, // 8, 3
+ 8, 4, 55867, 8, 5, 3473, 9, 4, 3671, 9, 5, 2525, // 8, 4
+ 8, 5, 58322, 8, 6, 2616, 9, 5, 2713, 9, 6, 1885, // 8, 5
+ 8, 6, 60905, 8, 7, 1695, 9, 6, 1726, 9, 7, 1210, // 8, 6
+ 8, 7, 63399, 8, 8, 789, 9, 7, 789, 9, 8, 559, // 8, 7
+ 7, 8, 789, 7, 9, 558, 8, 8, 63399, 8, 9, 790, // 8, 8
+ 7, 9, 1726, 7, 10, 1209, 8, 9, 60906, 8, 10, 1695, // 8, 9
+ 7, 10, 2714, 7, 11, 1884, 8, 10, 58324, 8, 11, 2614, // 8,10
+ 7, 11, 3672, 7, 12, 2524, 8, 11, 55870, 8, 12, 3470, // 8,11
+ 7, 12, 4594, 7, 13, 3126, 8, 12, 53562, 8, 13, 4254, // 8,12
+ 7, 13, 5480, 7, 14, 3691, 8, 13, 51395, 8, 14, 4970, // 8,13
+ 7, 14, 6335, 7, 15, 4221, 8, 14, 49358, 8, 15, 5622, // 8,14
+ 7, 15, 7161, 7, 16, 4718, 8, 15, 47440, 8, 16, 6217, // 8,15
+ 9, 0, 47086, 9, 1, 6405, 10, 0, 7227, 10, 1, 4818, // 9, 0
+ 9, 1, 48960, 9, 2, 5820, 10, 1, 6425, 10, 2, 4331, // 9, 1
+ 9, 2, 50935, 9, 3, 5184, 10, 2, 5602, 10, 3, 3815, // 9, 2
+ 9, 3, 53008, 9, 4, 4495, 10, 3, 4759, 10, 4, 3274, // 9, 3
+ 9, 4, 55164, 9, 5, 3759, 10, 4, 3902, 10, 5, 2711, // 9, 4
+ 9, 5, 57353, 9, 6, 2995, 10, 5, 3050, 10, 6, 2138, // 9, 5
+ 9, 6, 59422, 9, 7, 2259, 10, 6, 2258, 10, 7, 1597, // 9, 6
+ 9, 7, 60906, 9, 8, 1726, 10, 7, 1695, 10, 8, 1209, // 9, 7
+ 8, 8, 1695, 8, 9, 1210, 9, 8, 60905, 9, 9, 1726, // 9, 8
+ 8, 9, 2259, 8, 10, 1597, 9, 9, 59422, 9, 10, 2258, // 9, 9
+ 8, 10, 3051, 8, 11, 2138, 9, 10, 57354, 9, 11, 2993, // 9,10
+ 8, 11, 3904, 8, 12, 2710, 9, 11, 55166, 9, 12, 3756, // 9,11
+ 8, 12, 4762, 8, 13, 3273, 9, 12, 53012, 9, 13, 4489, // 9,12
+ 8, 13, 5606, 8, 14, 3813, 9, 13, 50942, 9, 14, 5175, // 9,13
+ 8, 14, 6430, 8, 15, 4327, 9, 14, 48969, 9, 15, 5810, // 9,14
+ 8, 15, 7233, 8, 16, 4814, 9, 15, 47098, 9, 16, 6391, // 9,15
+ 10, 0, 46532, 10, 1, 6659, 11, 0, 7374, 11, 1, 4971, // 10, 0
+ 10, 1, 48314, 10, 2, 6104, 11, 1, 6613, 11, 2, 4505, // 10, 1
+ 10, 2, 50165, 10, 3, 5508, 11, 2, 5842, 11, 3, 4021, // 10, 2
+ 10, 3, 52066, 10, 4, 4879, 11, 3, 5069, 11, 4, 3522, // 10, 3
+ 10, 4, 53973, 10, 5, 4230, 11, 4, 4309, 11, 5, 3024, // 10, 4
+ 10, 5, 55798, 10, 6, 3598, 11, 5, 3595, 11, 6, 2545, // 10, 5
+ 10, 6, 57354, 10, 7, 3051, 11, 6, 2993, 11, 7, 2138, // 10, 6
+ 10, 7, 58324, 10, 8, 2714, 11, 7, 2615, 11, 8, 1883, // 10, 7
+ 9, 8, 2616, 9, 9, 1884, 10, 8, 58322, 10, 9, 2714, // 10, 8
+ 9, 9, 2995, 9, 10, 2138, 10, 9, 57353, 10, 10, 3050, // 10, 9
+ 9, 10, 3598, 9, 11, 2546, 10, 10, 55798, 10, 11, 3594, // 10,10
+ 9, 11, 4313, 9, 12, 3023, 10, 11, 53975, 10, 12, 4225, // 10,11
+ 9, 12, 5073, 9, 13, 3522, 10, 12, 52069, 10, 13, 4872, // 10,12
+ 9, 13, 5848, 9, 14, 4019, 10, 13, 50171, 10, 14, 5498, // 10,13
+ 9, 14, 6620, 9, 15, 4502, 10, 14, 48322, 10, 15, 6092, // 10,14
+ 9, 15, 7383, 9, 16, 4967, 10, 15, 46541, 10, 16, 6645, // 10,15
+ 11, 0, 45791, 11, 1, 6986, 12, 0, 7587, 12, 1, 5172, // 11, 0
+ 11, 1, 47453, 11, 2, 6472, 12, 1, 6875, 12, 2, 4736, // 11, 1
+ 11, 2, 49147, 11, 3, 5930, 12, 2, 6168, 12, 3, 4291, // 11, 2
+ 11, 3, 50843, 11, 4, 5373, 12, 3, 5474, 12, 4, 3846, // 11, 3
+ 11, 4, 52484, 11, 5, 4822, 12, 4, 4816, 12, 5, 3414, // 11, 4
+ 11, 5, 53975, 11, 6, 4313, 12, 5, 4226, 12, 6, 3022, // 11, 5
+ 11, 6, 55166, 11, 7, 3904, 12, 6, 3755, 12, 7, 2711, // 11, 6
+ 11, 7, 55870, 11, 8, 3672, 12, 7, 3469, 12, 8, 2525, // 11, 7
+ 10, 8, 3473, 10, 9, 2525, 11, 8, 55867, 11, 9, 3671, // 11, 8
+ 10, 9, 3759, 10, 10, 2711, 11, 9, 55164, 11, 10, 3902, // 11, 9
+ 10, 10, 4230, 10, 11, 3023, 11, 10, 53973, 11, 11, 4310, // 11,10
+ 10, 11, 4822, 10, 12, 3415, 11, 11, 52484, 11, 12, 4815, // 11,11
+ 10, 12, 5481, 10, 13, 3845, 11, 12, 50844, 11, 13, 5366, // 11,12
+ 10, 13, 6176, 10, 14, 4290, 11, 13, 49150, 11, 14, 5920, // 11,13
+ 10, 14, 6886, 10, 15, 4734, 11, 14, 47458, 11, 15, 6458, // 11,14
+ 10, 15, 7599, 10, 16, 5169, 11, 15, 45799, 11, 16, 6969, // 11,15
+ 12, 0, 44901, 12, 1, 7374, 13, 0, 7848, 13, 1, 5413, // 12, 0
+ 12, 1, 46427, 12, 2, 6908, 13, 1, 7191, 13, 2, 5010, // 12, 1
+ 12, 2, 47953, 12, 3, 6426, 13, 2, 6549, 13, 3, 4608, // 12, 2
+ 12, 3, 49445, 12, 4, 5943, 13, 3, 5934, 13, 4, 4214, // 12, 3
+ 12, 4, 50844, 12, 5, 5481, 13, 4, 5365, 13, 5, 3846, // 12, 4
+ 12, 5, 52069, 12, 6, 5073, 13, 5, 4872, 13, 6, 3522, // 12, 5
+ 12, 6, 53012, 12, 7, 4762, 13, 6, 4489, 13, 7, 3273, // 12, 6
+ 12, 7, 53562, 12, 8, 4594, 13, 7, 4254, 13, 8, 3126, // 12, 7
+ 11, 8, 4259, 11, 9, 3128, 12, 8, 53557, 12, 9, 4592, // 12, 8
+ 11, 9, 4495, 11, 10, 3274, 12, 9, 53008, 12, 10, 4759, // 12, 9
+ 11, 10, 4879, 11, 11, 3523, 12, 10, 52066, 12, 11, 5068, // 12,10
+ 11, 11, 5373, 11, 12, 3846, 12, 11, 50843, 12, 12, 5474, // 12,11
+ 11, 12, 5943, 11, 13, 4214, 12, 12, 49445, 12, 13, 5934, // 12,12
+ 11, 13, 6560, 11, 14, 4607, 12, 13, 47955, 12, 14, 6414, // 12,13
+ 11, 14, 7204, 11, 15, 5009, 12, 14, 46430, 12, 15, 6893, // 12,14
+ 11, 15, 7863, 11, 16, 5410, 12, 15, 44907, 12, 16, 7356, // 12,15
+ 13, 0, 43900, 13, 1, 7812, 14, 0, 8141, 14, 1, 5683, // 13, 0
+ 13, 1, 45286, 13, 2, 7395, 14, 1, 7539, 14, 2, 5316, // 13, 1
+ 13, 2, 46650, 13, 3, 6973, 14, 2, 6959, 14, 3, 4954, // 13, 2
+ 13, 3, 47955, 13, 4, 6560, 14, 3, 6414, 14, 4, 4607, // 13, 3
+ 13, 4, 49150, 13, 5, 6176, 14, 4, 5920, 14, 5, 4290, // 13, 4
+ 13, 5, 50171, 13, 6, 5848, 14, 5, 5499, 14, 6, 4018, // 13, 5
+ 13, 6, 50942, 13, 7, 5606, 14, 6, 5175, 14, 7, 3813, // 13, 6
+ 13, 7, 51395, 13, 8, 5480, 14, 7, 4970, 14, 8, 3691, // 13, 7
+ 12, 8, 4978, 12, 9, 3693, 13, 8, 51387, 13, 9, 5478, // 13, 8
+ 12, 9, 5184, 12, 10, 3815, 13, 9, 50935, 13, 10, 5602, // 13, 9
+ 12, 10, 5508, 12, 11, 4020, 13, 10, 50165, 13, 11, 5843, // 13,10
+ 12, 11, 5930, 12, 12, 4291, 13, 11, 49147, 13, 12, 6168, // 13,11
+ 12, 12, 6426, 12, 13, 4608, 13, 12, 47953, 13, 13, 6549, // 13,12
+ 12, 13, 6973, 12, 14, 4954, 13, 13, 46650, 13, 14, 6959, // 13,13
+ 12, 14, 7555, 12, 15, 5315, 13, 14, 45288, 13, 15, 7378, // 13,14
+ 12, 15, 8159, 12, 16, 5682, 13, 15, 43904, 13, 16, 7791, // 13,15
+ 14, 0, 42821, 14, 1, 8288, 15, 0, 8452, 15, 1, 5975, // 14, 0
+ 14, 1, 44074, 14, 2, 7921, 15, 1, 7901, 15, 2, 5640, // 14, 1
+ 14, 2, 45288, 14, 3, 7555, 15, 2, 7378, 15, 3, 5315, // 14, 2
+ 14, 3, 46430, 14, 4, 7204, 15, 3, 6892, 15, 4, 5010, // 14, 3
+ 14, 4, 47458, 14, 5, 6886, 15, 4, 6458, 15, 5, 4734, // 14, 4
+ 14, 5, 48322, 14, 6, 6620, 15, 5, 6092, 15, 6, 4502, // 14, 5
+ 14, 6, 48969, 14, 7, 6430, 15, 6, 5809, 15, 7, 4328, // 14, 6
+ 14, 7, 49358, 14, 8, 6335, 15, 7, 5623, 15, 8, 4220, // 14, 7
+ 13, 8, 5633, 13, 9, 4224, 14, 8, 49347, 14, 9, 6332, // 14, 8
+ 13, 9, 5820, 13, 10, 4330, 14, 9, 48960, 14, 10, 6426, // 14, 9
+ 13, 10, 6104, 13, 11, 4505, 14, 10, 48314, 14, 11, 6613, // 14,10
+ 13, 11, 6472, 13, 12, 4736, 14, 11, 47453, 14, 12, 6875, // 14,11
+ 13, 12, 6908, 13, 13, 5011, 14, 12, 46427, 14, 13, 7190, // 14,12
+ 13, 13, 7395, 13, 14, 5316, 14, 13, 45286, 14, 14, 7539, // 14,13
+ 13, 14, 7921, 13, 15, 5640, 14, 14, 44074, 14, 15, 7901, // 14,14
+ 13, 15, 8474, 13, 16, 5974, 14, 15, 42823, 14, 16, 8265, // 14,15
+ 15, 0, 41693, 15, 1, 8795, 16, 0, 8769, 16, 1, 6279, // 15, 0
+ 15, 1, 42823, 15, 2, 8474, 16, 1, 8265, 16, 2, 5974, // 15, 1
+ 15, 2, 43904, 15, 3, 8159, 16, 2, 7791, 16, 3, 5682, // 15, 2
+ 15, 3, 44907, 15, 4, 7863, 16, 3, 7356, 16, 4, 5410, // 15, 3
+ 15, 4, 45799, 15, 5, 7599, 16, 4, 6970, 16, 5, 5168, // 15, 4
+ 15, 5, 46541, 15, 6, 7383, 16, 5, 6644, 16, 6, 4968, // 15, 5
+ 15, 6, 47098, 15, 7, 7233, 16, 6, 6391, 16, 7, 4814, // 15, 6
+ 15, 7, 47440, 15, 8, 7161, 16, 7, 6217, 16, 8, 4718, // 15, 7
+ 14, 8, 6230, 14, 9, 4722, 15, 8, 47426, 15, 9, 7158, // 15, 8
+ 14, 9, 6405, 14, 10, 4818, 15, 9, 47086, 15, 10, 7227, // 15, 9
+ 14, 10, 6659, 14, 11, 4971, 15, 10, 46532, 15, 11, 7374, // 15,10
+ 14, 11, 6986, 14, 12, 5172, 15, 11, 45791, 15, 12, 7587, // 15,11
+ 14, 12, 7374, 14, 13, 5413, 15, 12, 44901, 15, 13, 7848, // 15,12
+ 14, 13, 7812, 14, 14, 5684, 15, 13, 43900, 15, 14, 8140, // 15,13
+ 14, 14, 8288, 14, 15, 5975, 15, 14, 42821, 15, 15, 8452, // 15,14
+ 14, 15, 8795, 14, 16, 6280, 15, 15, 41693, 15, 16, 8768, // 15,15
+ // angle of 1.5 degrees
+ 0, -1, 11440, 0, 0, 34212, 1, -1, 8358, 1, 0, 11526, // 0, 0
+ 0, 0, 11192, 0, 1, 35502, 1, 0, 7987, 1, 1, 10855, // 0, 1
+ 0, 1, 10930, 0, 2, 36756, 1, 1, 7626, 1, 2, 10224, // 0, 2
+ 0, 2, 10670, 0, 3, 37939, 1, 2, 7285, 1, 3, 9642, // 0, 3
+ 0, 3, 10430, 0, 4, 39009, 1, 3, 6975, 1, 4, 9122, // 0, 4
+ 0, 4, 10232, 0, 5, 39918, 1, 4, 6710, 1, 5, 8676, // 0, 5
+ 0, 5, 10100, 0, 6, 40618, 1, 5, 6502, 1, 6, 8316, // 0, 6
+ 0, 6, 10052, 0, 7, 41072, 1, 6, 6360, 1, 7, 8052, // 0, 7
+ -1, 7, 6346, -1, 8, 8018, 0, 7, 10066, 0, 8, 41106, // 0, 8
+ -1, 8, 6489, -1, 9, 8278, 0, 8, 10123, 0, 9, 40646, // 0, 9
+ -1, 9, 6699, -1, 10, 8632, 0, 9, 10265, 0, 10, 39940, // 0,10
+ -1, 10, 6965, -1, 11, 9072, 0, 10, 10473, 0, 11, 39026, // 0,11
+ -1, 11, 7276, -1, 12, 9585, 0, 11, 10723, 0, 12, 37952, // 0,12
+ -1, 12, 7620, -1, 13, 10158, 0, 12, 10994, 0, 13, 36764, // 0,13
+ -1, 13, 7983, -1, 14, 10780, 0, 13, 11267, 0, 14, 35506, // 0,14
+ -1, 14, 8358, -1, 15, 11440, 0, 14, 11526, 0, 15, 34212, // 0,15
+ 1, -1, 10780, 1, 0, 35506, 2, -1, 7983, 2, 0, 11267, // 1, 0
+ 1, 0, 10467, 1, 1, 36959, 2, 0, 7579, 2, 1, 10531, // 1, 1
+ 1, 1, 10133, 1, 2, 38390, 2, 1, 7179, 2, 2, 9834, // 1, 2
+ 1, 2, 9796, 1, 3, 39759, 2, 2, 6797, 2, 3, 9184, // 1, 3
+ 1, 3, 9478, 1, 4, 41013, 2, 3, 6447, 2, 4, 8598, // 1, 4
+ 1, 4, 9206, 1, 5, 42087, 2, 4, 6145, 2, 5, 8098, // 1, 5
+ 1, 5, 9014, 1, 6, 42913, 2, 5, 5910, 2, 6, 7699, // 1, 6
+ 1, 6, 8929, 1, 7, 43433, 2, 6, 5756, 2, 7, 7418, // 1, 7
+ 0, 7, 5745, 0, 8, 7390, 1, 7, 8939, 1, 8, 43462, // 1, 8
+ 0, 8, 5900, 0, 9, 7667, 1, 8, 9032, 1, 9, 42937, // 1, 9
+ 0, 9, 6137, 0, 10, 8061, 1, 9, 9233, 1, 10, 42105, // 1,10
+ 0, 10, 6440, 0, 11, 8557, 1, 10, 9513, 1, 11, 41026, // 1,11
+ 0, 11, 6792, 0, 12, 9135, 1, 11, 9841, 1, 12, 39768, // 1,12
+ 0, 12, 7177, 0, 13, 9777, 1, 12, 10188, 1, 13, 38394, // 1,13
+ 0, 13, 7579, 0, 14, 10467, 1, 13, 10532, 1, 14, 36958, // 1,14
+ 0, 14, 7987, 0, 15, 11192, 1, 14, 10855, 1, 15, 35502, // 1,15
+ 2, -1, 10158, 2, 0, 36764, 3, -1, 7620, 3, 0, 10994, // 2, 0
+ 2, 0, 9777, 2, 1, 38394, 3, 0, 7177, 3, 1, 10188, // 2, 1
+ 2, 1, 9366, 2, 2, 40025, 3, 1, 6732, 3, 2, 9413, // 2, 2
+ 2, 2, 8941, 2, 3, 41614, 3, 2, 6299, 3, 3, 8682, // 2, 3
+ 2, 3, 8530, 2, 4, 43096, 3, 3, 5895, 3, 4, 8015, // 2, 4
+ 2, 4, 8167, 2, 5, 44386, 3, 4, 5543, 3, 5, 7440, // 2, 5
+ 2, 5, 7899, 2, 6, 45383, 3, 5, 5268, 3, 6, 6986, // 2, 6
+ 2, 6, 7766, 2, 7, 45995, 3, 6, 5095, 3, 7, 6680, // 2, 7
+ 1, 7, 5087, 1, 8, 6658, 2, 7, 7773, 2, 8, 46018, // 2, 8
+ 1, 8, 5261, 1, 9, 6961, 2, 8, 7913, 2, 9, 45401, // 2, 9
+ 1, 9, 5537, 1, 10, 7411, 2, 9, 8189, 2, 10, 44399, // 2,10
+ 1, 10, 5891, 1, 11, 7981, 2, 10, 8559, 2, 11, 43105, // 2,11
+ 1, 11, 6297, 1, 12, 8641, 2, 11, 8979, 2, 12, 41619, // 2,12
+ 1, 12, 6732, 1, 13, 9366, 2, 12, 9413, 2, 13, 40025, // 2,13
+ 1, 13, 7179, 1, 14, 10133, 2, 13, 9834, 2, 14, 38390, // 2,14
+ 1, 14, 7626, 1, 15, 10930, 2, 14, 10224, 2, 15, 36756, // 2,15
+ 3, -1, 9585, 3, 0, 37951, 4, -1, 7276, 4, 0, 10724, // 3, 0
+ 3, 0, 9135, 3, 1, 39767, 4, 0, 6792, 4, 1, 9842, // 3, 1
+ 3, 1, 8641, 3, 2, 41618, 4, 1, 6297, 4, 2, 8980, // 3, 2
+ 3, 2, 8120, 3, 3, 43461, 4, 2, 5804, 4, 3, 8151, // 3, 3
+ 3, 3, 7598, 3, 4, 45224, 4, 3, 5331, 4, 4, 7383, // 3, 4
+ 3, 4, 7121, 3, 5, 46798, 4, 4, 4909, 4, 5, 6708, // 3, 5
+ 3, 5, 6750, 3, 6, 48037, 4, 5, 4576, 4, 6, 6173, // 3, 6
+ 3, 6, 6552, 3, 7, 48785, 4, 6, 4372, 4, 7, 5827, // 3, 7
+ 2, 7, 4366, 2, 8, 5811, 3, 7, 6558, 3, 8, 48801, // 3, 8
+ 2, 8, 4572, 2, 9, 6154, 3, 8, 6761, 3, 9, 48049, // 3, 9
+ 2, 9, 4906, 2, 10, 6685, 3, 9, 7138, 3, 10, 46807, // 3,10
+ 2, 10, 5330, 2, 11, 7356, 3, 10, 7622, 3, 11, 45228, // 3,11
+ 2, 11, 5804, 2, 12, 8120, 3, 11, 8151, 3, 12, 43461, // 3,12
+ 2, 12, 6299, 2, 13, 8941, 3, 12, 8681, 3, 13, 41615, // 3,13
+ 2, 13, 6797, 2, 14, 9796, 3, 13, 9184, 3, 14, 39759, // 3,14
+ 2, 14, 7285, 2, 15, 10670, 3, 14, 9642, 3, 15, 37939, // 3,15
+ 4, -1, 9072, 4, 0, 39026, 5, -1, 6965, 5, 0, 10473, // 4, 0
+ 4, 0, 8557, 4, 1, 41026, 5, 0, 6440, 5, 1, 9513, // 4, 1
+ 4, 1, 7981, 4, 2, 43105, 5, 1, 5891, 5, 2, 8559, // 4, 2
+ 4, 2, 7356, 4, 3, 45229, 5, 2, 5330, 5, 3, 7621, // 4, 3
+ 4, 3, 6708, 4, 4, 47328, 5, 3, 4774, 5, 4, 6726, // 4, 4
+ 4, 4, 6086, 4, 5, 49275, 5, 4, 4258, 5, 5, 5917, // 4, 5
+ 4, 5, 5573, 4, 6, 50865, 5, 5, 3837, 5, 6, 5261, // 4, 6
+ 4, 6, 5280, 4, 7, 51832, 5, 6, 3579, 5, 7, 4845, // 4, 7
+ 3, 7, 3575, 3, 8, 4835, 4, 7, 5283, 4, 8, 51843, // 4, 8
+ 3, 8, 3834, 3, 9, 5248, 4, 8, 5581, 4, 9, 50873, // 4, 9
+ 3, 9, 4257, 3, 10, 5901, 4, 9, 6099, 4, 10, 49279, // 4,10
+ 3, 10, 4774, 3, 11, 6708, 4, 10, 6727, 4, 11, 47327, // 4,11
+ 3, 11, 5331, 3, 12, 7598, 4, 11, 7382, 4, 12, 45225, // 4,12
+ 3, 12, 5895, 3, 13, 8530, 4, 12, 8015, 4, 13, 43096, // 4,13
+ 3, 13, 6447, 3, 14, 9478, 4, 13, 8599, 4, 14, 41012, // 4,14
+ 3, 14, 6975, 3, 15, 10430, 4, 14, 9122, 4, 15, 39009, // 4,15
+ 5, -1, 8632, 5, 0, 39940, 6, -1, 6699, 6, 0, 10265, // 5, 0
+ 5, 0, 8061, 5, 1, 42105, 6, 0, 6137, 6, 1, 9233, // 5, 1
+ 5, 1, 7411, 5, 2, 44399, 6, 1, 5537, 6, 2, 8189, // 5, 2
+ 5, 2, 6685, 5, 3, 46806, 6, 2, 4906, 6, 3, 7139, // 5, 3
+ 5, 3, 5901, 5, 4, 49279, 6, 3, 4257, 6, 4, 6099, // 5, 4
+ 5, 4, 5103, 5, 5, 51700, 6, 4, 3621, 6, 5, 5112, // 5, 5
+ 5, 5, 4388, 5, 6, 53813, 6, 5, 3065, 6, 6, 4270, // 5, 6
+ 5, 6, 3938, 5, 7, 55162, 6, 6, 2710, 6, 7, 3726, // 5, 7
+ 4, 7, 2708, 4, 8, 3720, 5, 7, 3940, 5, 8, 55168, // 5, 8
+ 4, 8, 3064, 4, 9, 4262, 5, 8, 4394, 5, 9, 53816, // 5, 9
+ 4, 9, 3621, 4, 10, 5103, 5, 9, 5113, 5, 10, 51699, // 5,10
+ 4, 10, 4258, 4, 11, 6086, 5, 10, 5917, 5, 11, 49275, // 5,11
+ 4, 11, 4909, 4, 12, 7121, 5, 11, 6707, 5, 12, 46799, // 5,12
+ 4, 12, 5543, 4, 13, 8167, 5, 12, 7440, 5, 13, 44386, // 5,13
+ 4, 13, 6145, 4, 14, 9206, 5, 13, 8098, 5, 14, 42087, // 5,14
+ 4, 14, 6710, 4, 15, 10232, 5, 14, 8676, 5, 15, 39918, // 5,15
+ 6, -1, 8278, 6, 0, 40646, 7, -1, 6489, 7, 0, 10123, // 6, 0
+ 6, 0, 7667, 6, 1, 42936, 7, 0, 5900, 7, 1, 9033, // 6, 1
+ 6, 1, 6961, 6, 2, 45401, 7, 1, 5261, 7, 2, 7913, // 6, 2
+ 6, 2, 6154, 6, 3, 48049, 7, 2, 4572, 7, 3, 6761, // 6, 3
+ 6, 3, 5248, 6, 4, 50873, 7, 3, 3834, 7, 4, 5581, // 6, 4
+ 6, 4, 4262, 6, 5, 53816, 7, 4, 3064, 7, 5, 4394, // 6, 5
+ 6, 5, 3271, 6, 6, 56673, 7, 5, 2316, 7, 6, 3276, // 6, 6
+ 6, 6, 2532, 6, 7, 58773, 7, 6, 1767, 7, 7, 2464, // 6, 7
+ 5, 7, 1766, 5, 8, 2462, 6, 7, 2533, 6, 8, 58775, // 6, 8
+ 5, 8, 2316, 5, 9, 3271, 6, 8, 3275, 6, 9, 56674, // 6, 9
+ 5, 9, 3065, 5, 10, 4388, 6, 9, 4269, 6, 10, 53814, // 6,10
+ 5, 10, 3837, 5, 11, 5573, 6, 10, 5261, 6, 11, 50865, // 6,11
+ 5, 11, 4576, 5, 12, 6750, 6, 11, 6173, 6, 12, 48037, // 6,12
+ 5, 12, 5268, 5, 13, 7899, 6, 12, 6986, 6, 13, 45383, // 6,13
+ 5, 13, 5910, 5, 14, 9014, 6, 13, 7699, 6, 14, 42913, // 6,14
+ 5, 14, 6502, 5, 15, 10100, 6, 14, 8316, 6, 15, 40618, // 6,15
+ 7, -1, 8018, 7, 0, 41106, 8, -1, 6346, 8, 0, 10066, // 7, 0
+ 7, 0, 7390, 7, 1, 43461, 8, 0, 5745, 8, 1, 8940, // 7, 1
+ 7, 1, 6658, 7, 2, 46017, 8, 1, 5087, 8, 2, 7774, // 7, 2
+ 7, 2, 5811, 7, 3, 48801, 8, 2, 4366, 8, 3, 6558, // 7, 3
+ 7, 3, 4835, 7, 4, 51842, 8, 3, 3575, 8, 4, 5284, // 7, 4
+ 7, 4, 3720, 7, 5, 55168, 8, 4, 2708, 8, 5, 3940, // 7, 5
+ 7, 5, 2462, 7, 6, 58775, 8, 5, 1766, 8, 6, 2533, // 7, 6
+ 7, 6, 1170, 7, 7, 62369, 8, 6, 827, 8, 7, 1170, // 7, 7
+ 6, 7, 827, 6, 8, 1170, 7, 7, 1170, 7, 8, 62369, // 7, 8
+ 6, 8, 1767, 6, 9, 2532, 7, 8, 2464, 7, 9, 58773, // 7, 9
+ 6, 9, 2710, 6, 10, 3938, 7, 9, 3726, 7, 10, 55162, // 7,10
+ 6, 10, 3579, 6, 11, 5280, 7, 10, 4846, 7, 11, 51831, // 7,11
+ 6, 11, 4372, 6, 12, 6552, 7, 11, 5827, 7, 12, 48785, // 7,12
+ 6, 12, 5095, 6, 13, 7766, 7, 12, 6680, 7, 13, 45995, // 7,13
+ 6, 13, 5756, 6, 14, 8929, 7, 13, 7418, 7, 14, 43433, // 7,14
+ 6, 14, 6360, 6, 15, 10052, 7, 14, 8052, 7, 15, 41072, // 7,15
+ 8, 0, 41072, 8, 1, 8052, 9, 0, 10052, 9, 1, 6360, // 8, 0
+ 8, 1, 43433, 8, 2, 7418, 9, 1, 8929, 9, 2, 5756, // 8, 1
+ 8, 2, 45995, 8, 3, 6680, 9, 2, 7766, 9, 3, 5095, // 8, 2
+ 8, 3, 48785, 8, 4, 5827, 9, 3, 6552, 9, 4, 4372, // 8, 3
+ 8, 4, 51832, 8, 5, 4846, 9, 4, 5280, 9, 5, 3578, // 8, 4
+ 8, 5, 55162, 8, 6, 3726, 9, 5, 3938, 9, 6, 2710, // 8, 5
+ 8, 6, 58773, 8, 7, 2464, 9, 6, 2532, 9, 7, 1767, // 8, 6
+ 8, 7, 62369, 8, 8, 1170, 9, 7, 1170, 9, 8, 827, // 8, 7
+ 7, 8, 1170, 7, 9, 827, 8, 8, 62369, 8, 9, 1170, // 8, 8
+ 7, 9, 2533, 7, 10, 1766, 8, 9, 58775, 8, 10, 2462, // 8, 9
+ 7, 10, 3940, 7, 11, 2708, 8, 10, 55168, 8, 11, 3720, // 8,10
+ 7, 11, 5283, 7, 12, 3575, 8, 11, 51842, 8, 12, 4836, // 8,11
+ 7, 12, 6558, 7, 13, 4366, 8, 12, 48801, 8, 13, 5811, // 8,12
+ 7, 13, 7773, 7, 14, 5087, 8, 13, 46017, 8, 14, 6659, // 8,13
+ 7, 14, 8939, 7, 15, 5745, 8, 14, 43461, 8, 15, 7391, // 8,14
+ 7, 15, 10066, 7, 16, 6346, 8, 15, 41106, 8, 16, 8018, // 8,15
+ 9, 0, 40618, 9, 1, 8316, 10, 0, 10100, 10, 1, 6502, // 9, 0
+ 9, 1, 42913, 9, 2, 7699, 10, 1, 9014, 10, 2, 5910, // 9, 1
+ 9, 2, 45383, 9, 3, 6986, 10, 2, 7899, 10, 3, 5268, // 9, 2
+ 9, 3, 48037, 9, 4, 6173, 10, 3, 6750, 10, 4, 4576, // 9, 3
+ 9, 4, 50865, 9, 5, 5261, 10, 4, 5573, 10, 5, 3837, // 9, 4
+ 9, 5, 53813, 9, 6, 4269, 10, 5, 4388, 10, 6, 3066, // 9, 5
+ 9, 6, 56673, 9, 7, 3275, 10, 6, 3271, 10, 7, 2317, // 9, 6
+ 9, 7, 58775, 9, 8, 2533, 10, 7, 2462, 10, 8, 1766, // 9, 7
+ 8, 8, 2464, 8, 9, 1767, 9, 8, 58773, 9, 9, 2532, // 9, 8
+ 8, 9, 3275, 8, 10, 2316, 9, 9, 56673, 9, 10, 3272, // 9, 9
+ 8, 10, 4394, 8, 11, 3064, 9, 10, 53816, 9, 11, 4262, // 9,10
+ 8, 11, 5581, 8, 12, 3834, 9, 11, 50873, 9, 12, 5248, // 9,11
+ 8, 12, 6761, 8, 13, 4572, 9, 12, 48049, 9, 13, 6154, // 9,12
+ 8, 13, 7913, 8, 14, 5261, 9, 13, 45401, 9, 14, 6961, // 9,13
+ 8, 14, 9032, 8, 15, 5900, 9, 14, 42936, 9, 15, 7668, // 9,14
+ 8, 15, 10123, 8, 16, 6489, 9, 15, 40646, 9, 16, 8278, // 9,15
+ 10, 0, 39918, 10, 1, 8676, 11, 0, 10232, 11, 1, 6710, // 10, 0
+ 10, 1, 42087, 10, 2, 8098, 11, 1, 9206, 11, 2, 6145, // 10, 1
+ 10, 2, 44386, 10, 3, 7440, 11, 2, 8167, 11, 3, 5543, // 10, 2
+ 10, 3, 46798, 10, 4, 6707, 11, 3, 7121, 11, 4, 4910, // 10, 3
+ 10, 4, 49275, 10, 5, 5917, 11, 4, 6086, 11, 5, 4258, // 10, 4
+ 10, 5, 51700, 10, 6, 5113, 11, 5, 5103, 11, 6, 3620, // 10, 5
+ 10, 6, 53816, 10, 7, 4394, 11, 6, 4262, 11, 7, 3064, // 10, 6
+ 10, 7, 55168, 10, 8, 3940, 11, 7, 3720, 11, 8, 2708, // 10, 7
+ 9, 8, 3726, 9, 9, 2710, 10, 8, 55162, 10, 9, 3938, // 10, 8
+ 9, 9, 4269, 9, 10, 3065, 10, 9, 53813, 10, 10, 4389, // 10, 9
+ 9, 10, 5113, 9, 11, 3621, 10, 10, 51700, 10, 11, 5102, // 10,10
+ 9, 11, 6099, 9, 12, 4257, 10, 11, 49279, 10, 12, 5901, // 10,11
+ 9, 12, 7138, 9, 13, 4906, 10, 12, 46806, 10, 13, 6686, // 10,12
+ 9, 13, 8189, 9, 14, 5537, 10, 13, 44399, 10, 14, 7411, // 10,13
+ 9, 14, 9233, 9, 15, 6137, 10, 14, 42105, 10, 15, 8061, // 10,14
+ 9, 15, 10265, 9, 16, 6699, 10, 15, 39940, 10, 16, 8632, // 10,15
+ 11, 0, 39009, 11, 1, 9122, 12, 0, 10430, 12, 1, 6975, // 11, 0
+ 11, 1, 41013, 11, 2, 8599, 12, 1, 9478, 12, 2, 6446, // 11, 1
+ 11, 2, 43096, 11, 3, 8015, 12, 2, 8530, 12, 3, 5895, // 11, 2
+ 11, 3, 45224, 11, 4, 7382, 12, 3, 7598, 12, 4, 5332, // 11, 3
+ 11, 4, 47328, 11, 5, 6727, 12, 4, 6708, 12, 5, 4773, // 11, 4
+ 11, 5, 49279, 11, 6, 6099, 12, 5, 5901, 12, 6, 4257, // 11, 5
+ 11, 6, 50873, 11, 7, 5581, 12, 6, 5248, 12, 7, 3834, // 11, 6
+ 11, 7, 51842, 11, 8, 5283, 12, 7, 4835, 12, 8, 3576, // 11, 7
+ 10, 8, 4846, 10, 9, 3579, 11, 8, 51832, 11, 9, 5279, // 11, 8
+ 10, 9, 5261, 10, 10, 3837, 11, 9, 50865, 11, 10, 5573, // 11, 9
+ 10, 10, 5917, 10, 11, 4258, 11, 10, 49275, 11, 11, 6086, // 11,10
+ 10, 11, 6727, 10, 12, 4774, 11, 11, 47328, 11, 12, 6707, // 11,11
+ 10, 12, 7622, 10, 13, 5330, 11, 12, 45229, 11, 13, 7355, // 11,12
+ 10, 13, 8559, 10, 14, 5891, 11, 13, 43105, 11, 14, 7981, // 11,13
+ 10, 14, 9513, 10, 15, 6440, 11, 14, 41026, 11, 15, 8557, // 11,14
+ 10, 15, 10473, 10, 16, 6965, 11, 15, 39026, 11, 16, 9072, // 11,15
+ 12, 0, 37939, 12, 1, 9642, 13, 0, 10670, 13, 1, 7285, // 12, 0
+ 12, 1, 39759, 12, 2, 9184, 13, 1, 9796, 13, 2, 6797, // 12, 1
+ 12, 2, 41614, 12, 3, 8681, 13, 2, 8941, 13, 3, 6300, // 12, 2
+ 12, 3, 43461, 12, 4, 8151, 13, 3, 8120, 13, 4, 5804, // 12, 3
+ 12, 4, 45229, 12, 5, 7622, 13, 4, 7356, 13, 5, 5329, // 12, 4
+ 12, 5, 46806, 12, 6, 7138, 13, 5, 6685, 13, 6, 4907, // 12, 5
+ 12, 6, 48049, 12, 7, 6761, 13, 6, 6154, 13, 7, 4572, // 12, 6
+ 12, 7, 48801, 12, 8, 6558, 13, 7, 5811, 13, 8, 4366, // 12, 7
+ 11, 8, 5827, 11, 9, 4372, 12, 8, 48785, 12, 9, 6552, // 12, 8
+ 11, 9, 6173, 11, 10, 4576, 12, 9, 48037, 12, 10, 6750, // 12, 9
+ 11, 10, 6707, 11, 11, 4909, 12, 10, 46798, 12, 11, 7122, // 12,10
+ 11, 11, 7382, 11, 12, 5331, 12, 11, 45224, 12, 12, 7599, // 12,11
+ 11, 12, 8151, 11, 13, 5804, 12, 12, 43461, 12, 13, 8120, // 12,12
+ 11, 13, 8979, 11, 14, 6297, 12, 13, 41618, 12, 14, 8642, // 12,13
+ 11, 14, 9841, 11, 15, 6792, 12, 14, 39767, 12, 15, 9136, // 12,14
+ 11, 15, 10723, 11, 16, 7276, 12, 15, 37951, 12, 16, 9586, // 12,15
+ 13, 0, 36756, 13, 1, 10224, 14, 0, 10930, 14, 1, 7626, // 13, 0
+ 13, 1, 38390, 13, 2, 9834, 14, 1, 10133, 14, 2, 7179, // 13, 1
+ 13, 2, 40025, 13, 3, 9413, 14, 2, 9366, 14, 3, 6732, // 13, 2
+ 13, 3, 41618, 13, 4, 8979, 14, 3, 8641, 14, 4, 6298, // 13, 3
+ 13, 4, 43105, 13, 5, 8559, 14, 4, 7981, 14, 5, 5891, // 13, 4
+ 13, 5, 44399, 13, 6, 8189, 14, 5, 7411, 14, 6, 5537, // 13, 5
+ 13, 6, 45401, 13, 7, 7913, 14, 6, 6961, 14, 7, 5261, // 13, 6
+ 13, 7, 46017, 13, 8, 7773, 14, 7, 6658, 14, 8, 5088, // 13, 7
+ 12, 8, 6680, 12, 9, 5095, 13, 8, 45995, 13, 9, 7766, // 13, 8
+ 12, 9, 6986, 12, 10, 5268, 13, 9, 45383, 13, 10, 7899, // 13, 9
+ 12, 10, 7440, 12, 11, 5543, 13, 10, 44386, 13, 11, 8167, // 13,10
+ 12, 11, 8015, 12, 12, 5895, 13, 11, 43096, 13, 12, 8530, // 13,11
+ 12, 12, 8681, 12, 13, 6299, 13, 12, 41614, 13, 13, 8942, // 13,12
+ 12, 13, 9413, 12, 14, 6732, 13, 13, 40025, 13, 14, 9366, // 13,13
+ 12, 14, 10188, 12, 15, 7177, 13, 14, 38394, 13, 15, 9777, // 13,14
+ 12, 15, 10994, 12, 16, 7620, 13, 15, 36764, 13, 16, 10158, // 13,15
+ 14, 0, 35502, 14, 1, 10855, 15, 0, 11192, 15, 1, 7987, // 14, 0
+ 14, 1, 36959, 14, 2, 10532, 15, 1, 10467, 15, 2, 7578, // 14, 1
+ 14, 2, 38394, 14, 3, 10188, 15, 2, 9777, 15, 3, 7177, // 14, 2
+ 14, 3, 39767, 14, 4, 9841, 15, 3, 9135, 15, 4, 6793, // 14, 3
+ 14, 4, 41026, 14, 5, 9513, 15, 4, 8557, 15, 5, 6440, // 14, 4
+ 14, 5, 42105, 14, 6, 9233, 15, 5, 8061, 15, 6, 6137, // 14, 5
+ 14, 6, 42936, 14, 7, 9032, 15, 6, 7667, 15, 7, 5901, // 14, 6
+ 14, 7, 43461, 14, 8, 8939, 15, 7, 7390, 15, 8, 5746, // 14, 7
+ 13, 8, 7418, 13, 9, 5756, 14, 8, 43433, 14, 9, 8929, // 14, 8
+ 13, 9, 7699, 13, 10, 5910, 14, 9, 42913, 14, 10, 9014, // 14, 9
+ 13, 10, 8098, 13, 11, 6145, 14, 10, 42087, 14, 11, 9206, // 14,10
+ 13, 11, 8599, 13, 12, 6447, 14, 11, 41013, 14, 12, 9477, // 14,11
+ 13, 12, 9184, 13, 13, 6797, 14, 12, 39759, 14, 13, 9796, // 14,12
+ 13, 13, 9834, 13, 14, 7179, 14, 13, 38390, 14, 14, 10133, // 14,13
+ 13, 14, 10532, 13, 15, 7579, 14, 14, 36959, 14, 15, 10466, // 14,14
+ 13, 15, 11267, 13, 16, 7983, 14, 15, 35506, 14, 16, 10780, // 14,15
+ 15, 0, 34212, 15, 1, 11526, 16, 0, 11440, 16, 1, 8358, // 15, 0
+ 15, 1, 35506, 15, 2, 11267, 16, 1, 10780, 16, 2, 7983, // 15, 1
+ 15, 2, 36764, 15, 3, 10994, 16, 2, 10158, 16, 3, 7620, // 15, 2
+ 15, 3, 37951, 15, 4, 10723, 16, 3, 9585, 16, 4, 7277, // 15, 3
+ 15, 4, 39026, 15, 5, 10473, 16, 4, 9072, 16, 5, 6965, // 15, 4
+ 15, 5, 39940, 15, 6, 10265, 16, 5, 8632, 16, 6, 6699, // 15, 5
+ 15, 6, 40646, 15, 7, 10123, 16, 6, 8278, 16, 7, 6489, // 15, 6
+ 15, 7, 41106, 15, 8, 10066, 16, 7, 8018, 16, 8, 6346, // 15, 7
+ 14, 8, 8052, 14, 9, 6360, 15, 8, 41072, 15, 9, 10052, // 15, 8
+ 14, 9, 8316, 14, 10, 6502, 15, 9, 40618, 15, 10, 10100, // 15, 9
+ 14, 10, 8676, 14, 11, 6710, 15, 10, 39918, 15, 11, 10232, // 15,10
+ 14, 11, 9122, 14, 12, 6975, 15, 11, 39009, 15, 12, 10430, // 15,11
+ 14, 12, 9642, 14, 13, 7285, 15, 12, 37939, 15, 13, 10670, // 15,12
+ 14, 13, 10224, 14, 14, 7626, 15, 13, 36756, 15, 14, 10930, // 15,13
+ 14, 14, 10855, 14, 15, 7987, 15, 14, 35502, 15, 15, 11192, // 15,14
+ 14, 15, 11526, 14, 16, 8358, 15, 15, 34212, 15, 16, 11440, // 15,15
+ // angle of 2.0 degrees
+ 0, -1, 13368, 0, 0, 28495, 1, -1, 10104, 1, 0, 13569, // 0, 0
+ 0, 0, 13291, 0, 1, 29828, 1, 0, 9671, 1, 1, 12746, // 0, 1
+ 0, 1, 13176, 0, 2, 31138, 1, 1, 9245, 1, 2, 11977, // 0, 2
+ 0, 2, 13038, 0, 3, 32391, 1, 2, 8838, 1, 3, 11269, // 0, 3
+ 0, 3, 12899, 0, 4, 33539, 1, 3, 8463, 1, 4, 10635, // 0, 4
+ 0, 4, 12783, 0, 5, 34532, 1, 4, 8135, 1, 5, 10086, // 0, 5
+ 0, 5, 12717, 0, 6, 35315, 1, 5, 7868, 1, 6, 9636, // 0, 6
+ 0, 6, 12728, 0, 7, 35844, 1, 6, 7674, 1, 7, 9290, // 0, 7
+ -1, 7, 7643, -1, 8, 9224, 0, 7, 12764, 0, 8, 35905, // 0, 8
+ -1, 8, 7839, -1, 9, 9558, 0, 8, 12777, 0, 9, 35362, // 0, 9
+ -1, 9, 8107, -1, 10, 9995, 0, 9, 12867, 0, 10, 34567, // 0,10
+ -1, 10, 8438, -1, 11, 10528, 0, 10, 13007, 0, 11, 33563, // 0,11
+ -1, 11, 8816, -1, 12, 11143, 0, 11, 13171, 0, 12, 32406, // 0,12
+ -1, 12, 9229, -1, 13, 11829, 0, 12, 13332, 0, 13, 31146, // 0,13
+ -1, 13, 9662, -1, 14, 12574, 0, 13, 13470, 0, 14, 29830, // 0,14
+ -1, 14, 10104, -1, 15, 13368, 0, 14, 13569, 0, 15, 28495, // 0,15
+ 1, -1, 12574, 1, 0, 29831, 2, -1, 9662, 2, 0, 13469, // 1, 0
+ 1, 0, 12412, 1, 1, 31358, 2, 0, 9202, 2, 1, 12564, // 1, 1
+ 1, 1, 12203, 1, 2, 32881, 2, 1, 8742, 2, 2, 11710, // 1, 2
+ 1, 2, 11964, 1, 3, 34358, 2, 2, 8296, 2, 3, 10918, // 1, 3
+ 1, 3, 11721, 1, 4, 35730, 2, 3, 7881, 2, 4, 10204, // 1, 4
+ 1, 4, 11507, 1, 5, 36926, 2, 4, 7517, 2, 5, 9586, // 1, 5
+ 1, 5, 11360, 1, 6, 37866, 2, 5, 7224, 2, 6, 9086, // 1, 6
+ 1, 6, 11317, 1, 7, 38481, 2, 6, 7020, 2, 7, 8718, // 1, 7
+ 0, 7, 6997, 0, 8, 8662, 1, 7, 11344, 1, 8, 38533, // 1, 8
+ 0, 8, 7202, 0, 9, 9020, 1, 8, 11407, 1, 9, 37907, // 1, 9
+ 0, 9, 7497, 0, 10, 9509, 1, 9, 11575, 1, 10, 36955, // 1,10
+ 0, 10, 7865, 0, 11, 10111, 1, 10, 11810, 1, 11, 35750, // 1,11
+ 0, 11, 8284, 0, 12, 10808, 1, 11, 12074, 1, 12, 34370, // 1,12
+ 0, 12, 8735, 0, 13, 11580, 1, 12, 12334, 1, 13, 32887, // 1,13
+ 0, 13, 9202, 0, 14, 12412, 1, 13, 12564, 1, 14, 31358, // 1,14
+ 0, 14, 9671, 0, 15, 13291, 1, 14, 12746, 1, 15, 29828, // 1,15
+ 2, -1, 11829, 2, 0, 31146, 3, -1, 9229, 3, 0, 13332, // 2, 0
+ 2, 0, 11580, 2, 1, 32886, 3, 0, 8735, 3, 1, 12335, // 2, 1
+ 2, 1, 11272, 2, 2, 34650, 3, 1, 8232, 3, 2, 11382, // 2, 2
+ 2, 2, 10922, 2, 3, 36392, 3, 2, 7734, 3, 3, 10488, // 2, 3
+ 2, 3, 10559, 2, 4, 38042, 3, 3, 7261, 3, 4, 9674, // 2, 4
+ 2, 4, 10226, 2, 5, 39503, 3, 4, 6842, 3, 5, 8965, // 2, 5
+ 2, 5, 9977, 2, 6, 40656, 3, 5, 6506, 3, 6, 8397, // 2, 6
+ 2, 6, 9867, 2, 7, 41389, 3, 6, 6284, 3, 7, 7996, // 2, 7
+ 1, 7, 6266, 1, 8, 7951, 2, 7, 9886, 2, 8, 41433, // 2, 8
+ 1, 8, 6491, 1, 9, 8344, 2, 8, 10013, 2, 9, 40688, // 2, 9
+ 1, 9, 6829, 1, 10, 8902, 2, 9, 10279, 2, 10, 39526, // 2,10
+ 1, 10, 7252, 1, 11, 9597, 2, 10, 10630, 2, 11, 38057, // 2,11
+ 1, 11, 7728, 1, 12, 10397, 2, 11, 11012, 2, 12, 36399, // 2,12
+ 1, 12, 8232, 1, 13, 11272, 2, 12, 11382, 2, 13, 34650, // 2,13
+ 1, 13, 8742, 1, 14, 12203, 2, 13, 11709, 2, 14, 32882, // 2,14
+ 1, 14, 9245, 1, 15, 13176, 2, 14, 11977, 2, 15, 31138, // 2,15
+ 3, -1, 11143, 3, 0, 32406, 4, -1, 8816, 4, 0, 13171, // 3, 0
+ 3, 0, 10808, 3, 1, 34369, 4, 0, 8284, 4, 1, 12075, // 3, 1
+ 3, 1, 10397, 3, 2, 36399, 4, 1, 7728, 4, 2, 11012, // 3, 2
+ 3, 2, 9924, 3, 3, 38450, 4, 2, 7164, 4, 3, 9998, // 3, 3
+ 3, 3, 9421, 3, 4, 40444, 4, 3, 6615, 4, 4, 9056, // 3, 4
+ 3, 4, 8940, 3, 5, 42256, 4, 4, 6116, 4, 5, 8224, // 3, 5
+ 3, 5, 8558, 3, 6, 43710, 4, 5, 5712, 4, 6, 7556, // 3, 6
+ 3, 6, 8359, 3, 7, 44616, 4, 6, 5454, 4, 7, 7107, // 3, 7
+ 2, 7, 5443, 2, 8, 7072, 3, 7, 8373, 3, 8, 44648, // 3, 8
+ 2, 8, 5703, 2, 9, 7516, 3, 8, 8584, 3, 9, 43733, // 3, 9
+ 2, 9, 6108, 2, 10, 8175, 3, 9, 8982, 3, 10, 42271, // 3,10
+ 2, 10, 6611, 2, 11, 8995, 3, 10, 9478, 3, 11, 40452, // 3,11
+ 2, 11, 7164, 2, 12, 9924, 3, 11, 9998, 3, 12, 38450, // 3,12
+ 2, 12, 7734, 2, 13, 10922, 3, 12, 10488, 3, 13, 36392, // 3,13
+ 2, 13, 8296, 2, 14, 11964, 3, 13, 10918, 3, 14, 34358, // 3,14
+ 2, 14, 8838, 2, 15, 13038, 3, 14, 11269, 3, 15, 32391, // 3,15
+ 4, -1, 10528, 4, 0, 33564, 5, -1, 8438, 5, 0, 13006, // 4, 0
+ 4, 0, 10111, 4, 1, 35750, 5, 0, 7865, 5, 1, 11810, // 4, 1
+ 4, 1, 9597, 4, 2, 38057, 5, 1, 7252, 5, 2, 10630, // 4, 2
+ 4, 2, 8995, 4, 3, 40452, 5, 2, 6611, 5, 3, 9478, // 4, 3
+ 4, 3, 8332, 4, 4, 42861, 5, 3, 5965, 5, 4, 8378, // 4, 4
+ 4, 4, 7667, 4, 5, 45139, 5, 4, 5353, 5, 5, 7377, // 4, 5
+ 4, 5, 7100, 4, 6, 47035, 5, 5, 4843, 5, 6, 6558, // 4, 6
+ 4, 6, 6774, 4, 7, 48218, 5, 6, 4521, 5, 7, 6023, // 4, 7
+ 3, 7, 4513, 3, 8, 6000, 4, 7, 6783, 4, 8, 48240, // 4, 8
+ 3, 8, 4838, 3, 9, 6530, 4, 8, 7119, 4, 9, 47049, // 4, 9
+ 3, 9, 5350, 3, 10, 7342, 4, 9, 7698, 4, 10, 45146, // 4,10
+ 3, 10, 5965, 3, 11, 8332, 4, 10, 8378, 4, 11, 42861, // 4,11
+ 3, 11, 6615, 3, 12, 9421, 4, 11, 9056, 4, 12, 40444, // 4,12
+ 3, 12, 7261, 3, 13, 10559, 4, 12, 9674, 4, 13, 38042, // 4,13
+ 3, 13, 7881, 3, 14, 11721, 4, 13, 10204, 4, 14, 35730, // 4,14
+ 3, 14, 8463, 3, 15, 12899, 4, 14, 10635, 4, 15, 33539, // 4,15
+ 5, -1, 9995, 5, 0, 34567, 6, -1, 8107, 6, 0, 12867, // 5, 0
+ 5, 0, 9509, 5, 1, 36955, 6, 0, 7497, 6, 1, 11575, // 5, 1
+ 5, 1, 8902, 5, 2, 39526, 6, 1, 6829, 6, 2, 10279, // 5, 2
+ 5, 2, 8175, 5, 3, 42271, 6, 2, 6108, 6, 3, 8982, // 5, 3
+ 5, 3, 7342, 5, 4, 45146, 6, 3, 5350, 6, 4, 7698, // 5, 4
+ 5, 4, 6451, 5, 5, 48019, 6, 4, 4591, 6, 5, 6475, // 5, 5
+ 5, 5, 5624, 5, 6, 50581, 6, 5, 3913, 6, 6, 5418, // 5, 6
+ 5, 6, 5092, 5, 7, 52253, 6, 6, 3470, 6, 7, 4721, // 5, 7
+ 4, 7, 3466, 4, 8, 4708, 5, 7, 5097, 5, 8, 52265, // 5, 8
+ 4, 8, 3911, 4, 9, 5400, 5, 8, 5637, 5, 9, 50588, // 5, 9
+ 4, 9, 4591, 4, 10, 6451, 5, 9, 6475, 5, 10, 48019, // 5,10
+ 4, 10, 5353, 4, 11, 7667, 5, 10, 7377, 5, 11, 45139, // 5,11
+ 4, 11, 6116, 4, 12, 8940, 5, 11, 8224, 5, 12, 42256, // 5,12
+ 4, 12, 6842, 4, 13, 10226, 5, 12, 8966, 5, 13, 39502, // 5,13
+ 4, 13, 7517, 4, 14, 11507, 5, 13, 9587, 5, 14, 36925, // 5,14
+ 4, 14, 8135, 4, 15, 12783, 5, 14, 10086, 5, 15, 34532, // 5,15
+ 6, -1, 9558, 6, 0, 35362, 7, -1, 7839, 7, 0, 12777, // 6, 0
+ 6, 0, 9020, 6, 1, 37906, 7, 0, 7202, 7, 1, 11408, // 6, 1
+ 6, 1, 8344, 6, 2, 40688, 7, 1, 6491, 7, 2, 10013, // 6, 2
+ 6, 2, 7516, 6, 3, 43733, 7, 2, 5703, 7, 3, 8584, // 6, 3
+ 6, 3, 6530, 6, 4, 47049, 7, 3, 4838, 7, 4, 7119, // 6, 4
+ 6, 4, 5400, 6, 5, 50587, 7, 4, 3911, 7, 5, 5638, // 6, 5
+ 6, 5, 4217, 6, 6, 54105, 7, 5, 2989, 7, 6, 4225, // 6, 6
+ 6, 6, 3303, 6, 7, 56751, 7, 6, 2295, 7, 7, 3187, // 6, 7
+ 5, 7, 2294, 5, 8, 3180, 6, 7, 3306, 6, 8, 56756, // 6, 8
+ 5, 8, 2989, 5, 9, 4217, 6, 8, 4225, 6, 9, 54105, // 6, 9
+ 5, 9, 3913, 5, 10, 5624, 6, 9, 5418, 6, 10, 50581, // 6,10
+ 5, 10, 4843, 5, 11, 7100, 6, 10, 6558, 6, 11, 47035, // 6,11
+ 5, 11, 5712, 5, 12, 8558, 6, 11, 7556, 6, 12, 43710, // 6,12
+ 5, 12, 6506, 5, 13, 9977, 6, 12, 8397, 6, 13, 40656, // 6,13
+ 5, 13, 7224, 5, 14, 11360, 6, 13, 9086, 6, 14, 37866, // 6,14
+ 5, 14, 7868, 5, 15, 12717, 6, 14, 9635, 6, 15, 35316, // 6,15
+ 7, -1, 9224, 7, 0, 35905, 8, -1, 7643, 8, 0, 12764, // 7, 0
+ 7, 0, 8662, 7, 1, 38534, 8, 0, 6997, 8, 1, 11343, // 7, 1
+ 7, 1, 7951, 7, 2, 41432, 8, 1, 6266, 8, 2, 9887, // 7, 2
+ 7, 2, 7072, 7, 3, 44649, 8, 2, 5443, 8, 3, 8372, // 7, 3
+ 7, 3, 6000, 7, 4, 48240, 8, 3, 4513, 8, 4, 6783, // 7, 4
+ 7, 4, 4708, 7, 5, 52266, 8, 4, 3466, 8, 5, 5096, // 7, 5
+ 7, 5, 3180, 7, 6, 56756, 8, 5, 2294, 8, 6, 3306, // 7, 6
+ 7, 6, 1541, 7, 7, 61364, 8, 6, 1090, 8, 7, 1541, // 7, 7
+ 6, 7, 1090, 6, 8, 1541, 7, 7, 1542, 7, 8, 61363, // 7, 8
+ 6, 8, 2295, 6, 9, 3303, 7, 8, 3186, 7, 9, 56752, // 7, 9
+ 6, 9, 3470, 6, 10, 5092, 7, 9, 4721, 7, 10, 52253, // 7,10
+ 6, 10, 4521, 6, 11, 6774, 7, 10, 6023, 7, 11, 48218, // 7,11
+ 6, 11, 5454, 6, 12, 8359, 7, 11, 7106, 7, 12, 44617, // 7,12
+ 6, 12, 6284, 6, 13, 9867, 7, 12, 7996, 7, 13, 41389, // 7,13
+ 6, 13, 7020, 6, 14, 11317, 7, 13, 8718, 7, 14, 38481, // 7,14
+ 6, 14, 7674, 6, 15, 12728, 7, 14, 9290, 7, 15, 35844, // 7,15
+ 8, 0, 35844, 8, 1, 9290, 9, 0, 12728, 9, 1, 7674, // 8, 0
+ 8, 1, 38481, 8, 2, 8718, 9, 1, 11317, 9, 2, 7020, // 8, 1
+ 8, 2, 41389, 8, 3, 7996, 9, 2, 9867, 9, 3, 6284, // 8, 2
+ 8, 3, 44616, 8, 4, 7106, 9, 3, 8359, 9, 4, 5455, // 8, 3
+ 8, 4, 48218, 8, 5, 6023, 9, 4, 6774, 9, 5, 4521, // 8, 4
+ 8, 5, 52253, 8, 6, 4721, 9, 5, 5092, 9, 6, 3470, // 8, 5
+ 8, 6, 56751, 8, 7, 3186, 9, 6, 3303, 9, 7, 2296, // 8, 6
+ 8, 7, 61364, 8, 8, 1542, 9, 7, 1541, 9, 8, 1089, // 8, 7
+ 7, 8, 1542, 7, 9, 1090, 8, 8, 61364, 8, 9, 1540, // 8, 8
+ 7, 9, 3306, 7, 10, 2294, 8, 9, 56756, 8, 10, 3180, // 8, 9
+ 7, 10, 5097, 7, 11, 3466, 8, 10, 52266, 8, 11, 4707, // 8,10
+ 7, 11, 6783, 7, 12, 4513, 8, 11, 48240, 8, 12, 6000, // 8,11
+ 7, 12, 8373, 7, 13, 5443, 8, 12, 44649, 8, 13, 7071, // 8,12
+ 7, 13, 9886, 7, 14, 6266, 8, 13, 41432, 8, 14, 7952, // 8,13
+ 7, 14, 11344, 7, 15, 6997, 8, 14, 38534, 8, 15, 8661, // 8,14
+ 7, 15, 12764, 7, 16, 7643, 8, 15, 35905, 8, 16, 9224, // 8,15
+ 9, 0, 35315, 9, 1, 9635, 10, 0, 12717, 10, 1, 7869, // 9, 0
+ 9, 1, 37866, 9, 2, 9086, 10, 1, 11360, 10, 2, 7224, // 9, 1
+ 9, 2, 40656, 9, 3, 8397, 10, 2, 9977, 10, 3, 6506, // 9, 2
+ 9, 3, 43710, 9, 4, 7556, 10, 3, 8558, 10, 4, 5712, // 9, 3
+ 9, 4, 47035, 9, 5, 6558, 10, 4, 7100, 10, 5, 4843, // 9, 4
+ 9, 5, 50581, 9, 6, 5418, 10, 5, 5624, 10, 6, 3913, // 9, 5
+ 9, 6, 54105, 9, 7, 4225, 10, 6, 4217, 10, 7, 2989, // 9, 6
+ 9, 7, 56756, 9, 8, 3306, 10, 7, 3180, 10, 8, 2294, // 9, 7
+ 8, 8, 3186, 8, 9, 2295, 9, 8, 56751, 9, 9, 3304, // 9, 8
+ 8, 9, 4225, 8, 10, 2989, 9, 9, 54105, 9, 10, 4217, // 9, 9
+ 8, 10, 5637, 8, 11, 3911, 9, 10, 50587, 9, 11, 5401, // 9,10
+ 8, 11, 7119, 8, 12, 4838, 9, 11, 47049, 9, 12, 6530, // 9,11
+ 8, 12, 8584, 8, 13, 5703, 9, 12, 43733, 9, 13, 7516, // 9,12
+ 8, 13, 10013, 8, 14, 6491, 9, 13, 40688, 9, 14, 8344, // 9,13
+ 8, 14, 11407, 8, 15, 7202, 9, 14, 37906, 9, 15, 9021, // 9,14
+ 8, 15, 12777, 8, 16, 7839, 9, 15, 35362, 9, 16, 9558, // 9,15
+ 10, 0, 34532, 10, 1, 10086, 11, 0, 12783, 11, 1, 8135, // 10, 0
+ 10, 1, 36926, 10, 2, 9587, 11, 1, 11507, 11, 2, 7516, // 10, 1
+ 10, 2, 39503, 10, 3, 8966, 11, 2, 10226, 11, 3, 6841, // 10, 2
+ 10, 3, 42256, 10, 4, 8224, 11, 3, 8940, 11, 4, 6116, // 10, 3
+ 10, 4, 45139, 10, 5, 7377, 11, 4, 7667, 11, 5, 5353, // 10, 4
+ 10, 5, 48019, 10, 6, 6475, 11, 5, 6451, 11, 6, 4591, // 10, 5
+ 10, 6, 50587, 10, 7, 5637, 11, 6, 5400, 11, 7, 3912, // 10, 6
+ 10, 7, 52266, 10, 8, 5097, 11, 7, 4708, 11, 8, 3465, // 10, 7
+ 9, 8, 4721, 9, 9, 3470, 10, 8, 52253, 10, 9, 5092, // 10, 8
+ 9, 9, 5418, 9, 10, 3913, 10, 9, 50581, 10, 10, 5624, // 10, 9
+ 9, 10, 6475, 9, 11, 4591, 10, 10, 48019, 10, 11, 6451, // 10,10
+ 9, 11, 7698, 9, 12, 5350, 10, 11, 45146, 10, 12, 7342, // 10,11
+ 9, 12, 8982, 9, 13, 6108, 10, 12, 42271, 10, 13, 8175, // 10,12
+ 9, 13, 10279, 9, 14, 6829, 10, 13, 39526, 10, 14, 8902, // 10,13
+ 9, 14, 11575, 9, 15, 7497, 10, 14, 36955, 10, 15, 9509, // 10,14
+ 9, 15, 12867, 9, 16, 8107, 10, 15, 34567, 10, 16, 9995, // 10,15
+ 11, 0, 33539, 11, 1, 10635, 12, 0, 12899, 12, 1, 8463, // 11, 0
+ 11, 1, 35730, 11, 2, 10204, 12, 1, 11721, 12, 2, 7881, // 11, 1
+ 11, 2, 38042, 11, 3, 9674, 12, 2, 10559, 12, 3, 7261, // 11, 2
+ 11, 3, 40444, 11, 4, 9056, 12, 3, 9421, 12, 4, 6615, // 11, 3
+ 11, 4, 42861, 11, 5, 8378, 12, 4, 8332, 12, 5, 5965, // 11, 4
+ 11, 5, 45146, 11, 6, 7698, 12, 5, 7342, 12, 6, 5350, // 11, 5
+ 11, 6, 47049, 11, 7, 7119, 12, 6, 6530, 12, 7, 4838, // 11, 6
+ 11, 7, 48240, 11, 8, 6783, 12, 7, 6000, 12, 8, 4513, // 11, 7
+ 10, 8, 6023, 10, 9, 4521, 11, 8, 48218, 11, 9, 6774, // 11, 8
+ 10, 9, 6558, 10, 10, 4843, 11, 9, 47035, 11, 10, 7100, // 11, 9
+ 10, 10, 7377, 10, 11, 5353, 11, 10, 45139, 11, 11, 7667, // 11,10
+ 10, 11, 8378, 10, 12, 5965, 11, 11, 42861, 11, 12, 8332, // 11,11
+ 10, 12, 9478, 10, 13, 6611, 11, 12, 40452, 11, 13, 8995, // 11,12
+ 10, 13, 10630, 10, 14, 7252, 11, 13, 38057, 11, 14, 9597, // 11,13
+ 10, 14, 11810, 10, 15, 7865, 11, 14, 35750, 11, 15, 10111, // 11,14
+ 10, 15, 13007, 10, 16, 8438, 11, 15, 33564, 11, 16, 10527, // 11,15
+ 12, 0, 32391, 12, 1, 11269, 13, 0, 13038, 13, 1, 8838, // 12, 0
+ 12, 1, 34358, 12, 2, 10918, 13, 1, 11964, 13, 2, 8296, // 12, 1
+ 12, 2, 36392, 12, 3, 10488, 13, 2, 10922, 13, 3, 7734, // 12, 2
+ 12, 3, 38450, 12, 4, 9998, 13, 3, 9924, 13, 4, 7164, // 12, 3
+ 12, 4, 40452, 12, 5, 9478, 13, 4, 8995, 13, 5, 6611, // 12, 4
+ 12, 5, 42271, 12, 6, 8982, 13, 5, 8175, 13, 6, 6108, // 12, 5
+ 12, 6, 43733, 12, 7, 8584, 13, 6, 7516, 13, 7, 5703, // 12, 6
+ 12, 7, 44649, 12, 8, 8373, 13, 7, 7072, 13, 8, 5442, // 12, 7
+ 11, 8, 7106, 11, 9, 5454, 12, 8, 44616, 12, 9, 8360, // 12, 8
+ 11, 9, 7556, 11, 10, 5712, 12, 9, 43710, 12, 10, 8558, // 12, 9
+ 11, 10, 8224, 11, 11, 6116, 12, 10, 42256, 12, 11, 8940, // 12,10
+ 11, 11, 9056, 11, 12, 6615, 12, 11, 40444, 12, 12, 9421, // 12,11
+ 11, 12, 9998, 11, 13, 7164, 12, 12, 38450, 12, 13, 9924, // 12,12
+ 11, 13, 11012, 11, 14, 7728, 12, 13, 36399, 12, 14, 10397, // 12,13
+ 11, 14, 12074, 11, 15, 8284, 12, 14, 34369, 12, 15, 10809, // 12,14
+ 11, 15, 13171, 11, 16, 8816, 12, 15, 32406, 12, 16, 11143, // 12,15
+ 13, 0, 31138, 13, 1, 11977, 14, 0, 13176, 14, 1, 9245, // 13, 0
+ 13, 1, 32881, 13, 2, 11709, 14, 1, 12203, 14, 2, 8743, // 13, 1
+ 13, 2, 34650, 13, 3, 11382, 14, 2, 11272, 14, 3, 8232, // 13, 2
+ 13, 3, 36399, 13, 4, 11012, 14, 3, 10397, 14, 4, 7728, // 13, 3
+ 13, 4, 38057, 13, 5, 10630, 14, 4, 9597, 14, 5, 7252, // 13, 4
+ 13, 5, 39526, 13, 6, 10279, 14, 5, 8902, 14, 6, 6829, // 13, 5
+ 13, 6, 40688, 13, 7, 10013, 14, 6, 8344, 14, 7, 6491, // 13, 6
+ 13, 7, 41432, 13, 8, 9886, 14, 7, 7951, 14, 8, 6267, // 13, 7
+ 12, 8, 7996, 12, 9, 6284, 13, 8, 41389, 13, 9, 9867, // 13, 8
+ 12, 9, 8397, 12, 10, 6506, 13, 9, 40656, 13, 10, 9977, // 13, 9
+ 12, 10, 8966, 12, 11, 6842, 13, 10, 39503, 13, 11, 10225, // 13,10
+ 12, 11, 9674, 12, 12, 7261, 13, 11, 38042, 13, 12, 10559, // 13,11
+ 12, 12, 10488, 12, 13, 7734, 13, 12, 36392, 13, 13, 10922, // 13,12
+ 12, 13, 11382, 12, 14, 8232, 13, 13, 34650, 13, 14, 11272, // 13,13
+ 12, 14, 12334, 12, 15, 8735, 13, 14, 32886, 13, 15, 11581, // 13,14
+ 12, 15, 13332, 12, 16, 9229, 13, 15, 31146, 13, 16, 11829, // 13,15
+ 14, 0, 29828, 14, 1, 12746, 15, 0, 13291, 15, 1, 9671, // 14, 0
+ 14, 1, 31358, 14, 2, 12564, 15, 1, 12412, 15, 2, 9202, // 14, 1
+ 14, 2, 32886, 14, 3, 12334, 15, 2, 11580, 15, 3, 8736, // 14, 2
+ 14, 3, 34369, 14, 4, 12074, 15, 3, 10808, 15, 4, 8285, // 14, 3
+ 14, 4, 35750, 14, 5, 11810, 15, 4, 10111, 15, 5, 7865, // 14, 4
+ 14, 5, 36955, 14, 6, 11575, 15, 5, 9509, 15, 6, 7497, // 14, 5
+ 14, 6, 37906, 14, 7, 11407, 15, 6, 9020, 15, 7, 7203, // 14, 6
+ 14, 7, 38534, 14, 8, 11344, 15, 7, 8662, 15, 8, 6996, // 14, 7
+ 13, 8, 8718, 13, 9, 7020, 14, 8, 38481, 14, 9, 11317, // 14, 8
+ 13, 9, 9086, 13, 10, 7224, 14, 9, 37866, 14, 10, 11360, // 14, 9
+ 13, 10, 9587, 13, 11, 7517, 14, 10, 36926, 14, 11, 11506, // 14,10
+ 13, 11, 10204, 13, 12, 7881, 14, 11, 35730, 14, 12, 11721, // 14,11
+ 13, 12, 10918, 13, 13, 8296, 14, 12, 34358, 14, 13, 11964, // 14,12
+ 13, 13, 11709, 13, 14, 8742, 14, 13, 32881, 14, 14, 12204, // 14,13
+ 13, 14, 12564, 13, 15, 9202, 14, 14, 31358, 14, 15, 12412, // 14,14
+ 13, 15, 13470, 13, 16, 9662, 14, 15, 29831, 14, 16, 12573, // 14,15
+ 15, 0, 28495, 15, 1, 13569, 16, 0, 13368, 16, 1, 10104, // 15, 0
+ 15, 1, 29831, 15, 2, 13470, 16, 1, 12574, 16, 2, 9661, // 15, 1
+ 15, 2, 31146, 15, 3, 13332, 16, 2, 11829, 16, 3, 9229, // 15, 2
+ 15, 3, 32406, 15, 4, 13171, 16, 3, 11143, 16, 4, 8816, // 15, 3
+ 15, 4, 33564, 15, 5, 13007, 16, 4, 10528, 16, 5, 8437, // 15, 4
+ 15, 5, 34567, 15, 6, 12867, 16, 5, 9995, 16, 6, 8107, // 15, 5
+ 15, 6, 35362, 15, 7, 12777, 16, 6, 9558, 16, 7, 7839, // 15, 6
+ 15, 7, 35905, 15, 8, 12764, 16, 7, 9224, 16, 8, 7643, // 15, 7
+ 14, 8, 9290, 14, 9, 7674, 15, 8, 35844, 15, 9, 12728, // 15, 8
+ 14, 9, 9635, 14, 10, 7868, 15, 9, 35315, 15, 10, 12718, // 15, 9
+ 14, 10, 10086, 14, 11, 8135, 15, 10, 34532, 15, 11, 12783, // 15,10
+ 14, 11, 10635, 14, 12, 8463, 15, 11, 33539, 15, 12, 12899, // 15,11
+ 14, 12, 11269, 14, 13, 8838, 15, 12, 32391, 15, 13, 13038, // 15,12
+ 14, 13, 11977, 14, 14, 9245, 15, 13, 31138, 15, 14, 13176, // 15,13
+ 14, 14, 12746, 14, 15, 9671, 15, 14, 29828, 15, 15, 13291, // 15,14
+ 14, 15, 13569, 14, 16, 10104, 15, 15, 28495, 15, 16, 13368, // 15,15
+ // angle of 2.5 degrees
+ 0, -1, 14696, 0, 0, 24063, 1, -1, 11702, 1, 0, 15075, // 0, 0
+ 0, 0, 14872, 0, 1, 25368, 1, 0, 11187, 1, 1, 14109, // 0, 1
+ 0, 1, 14990, 0, 2, 26660, 1, 1, 10676, 1, 2, 13210, // 0, 2
+ 0, 2, 15060, 0, 3, 27903, 1, 2, 10185, 1, 3, 12388, // 0, 3
+ 0, 3, 15100, 0, 4, 29055, 1, 3, 9728, 1, 4, 11653, // 0, 4
+ 0, 4, 15135, 0, 5, 30064, 1, 4, 9323, 1, 5, 11014, // 0, 5
+ 0, 5, 15193, 0, 6, 30876, 1, 5, 8986, 1, 6, 10481, // 0, 6
+ 0, 6, 15301, 0, 7, 31444, 1, 6, 8727, 1, 7, 10064, // 0, 7
+ -1, 7, 8669, -1, 8, 9959, 0, 7, 15376, 0, 8, 31532, // 0, 8
+ -1, 8, 8927, -1, 9, 10351, 0, 8, 15319, 0, 9, 30939, // 0, 9
+ -1, 9, 9265, -1, 10, 10855, 0, 9, 15311, 0, 10, 30105, // 0,10
+ -1, 10, 9673, -1, 11, 11461, 0, 10, 15325, 0, 11, 29077, // 0,11
+ -1, 11, 10135, -1, 12, 12159, 0, 11, 15330, 0, 12, 27912, // 0,12
+ -1, 12, 10637, -1, 13, 12938, 0, 12, 15301, 0, 13, 26660, // 0,13
+ -1, 13, 11164, -1, 14, 13787, 0, 13, 15220, 0, 14, 25365, // 0,14
+ -1, 14, 11702, -1, 15, 14696, 0, 14, 15076, 0, 15, 24062, // 0,15
+ 1, -1, 13787, 1, 0, 25366, 2, -1, 11164, 2, 0, 15219, // 1, 0
+ 1, 0, 13853, 1, 1, 26893, 2, 0, 10644, 2, 1, 14146, // 1, 1
+ 1, 1, 13850, 1, 2, 28427, 2, 1, 10119, 2, 2, 13140, // 1, 2
+ 1, 2, 13789, 1, 3, 29928, 2, 2, 9603, 2, 3, 12216, // 1, 3
+ 1, 3, 13694, 1, 4, 31339, 2, 3, 9118, 2, 4, 11385, // 1, 4
+ 1, 4, 13600, 1, 5, 32586, 2, 4, 8685, 2, 5, 10665, // 1, 5
+ 1, 5, 13548, 1, 6, 33585, 2, 5, 8329, 2, 6, 10074, // 1, 6
+ 1, 6, 13582, 1, 7, 34261, 2, 6, 8068, 2, 7, 9625, // 1, 7
+ 0, 7, 8024, 0, 8, 9534, 1, 7, 13638, 1, 8, 34340, // 1, 8
+ 0, 8, 8286, 0, 9, 9961, 1, 8, 13647, 1, 9, 33642, // 1, 9
+ 0, 9, 8645, 0, 10, 10528, 1, 9, 13740, 1, 10, 32623, // 1,10
+ 0, 10, 9082, 0, 11, 11218, 1, 10, 13875, 1, 11, 31361, // 1,11
+ 0, 11, 9575, 0, 12, 12014, 1, 11, 14009, 1, 12, 29938, // 1,12
+ 0, 12, 10102, 0, 13, 12897, 1, 12, 14107, 1, 13, 28430, // 1,13
+ 0, 13, 10644, 0, 14, 13853, 1, 13, 14145, 1, 14, 26894, // 1,14
+ 0, 14, 11187, 0, 15, 14872, 1, 14, 14109, 1, 15, 25368, // 1,15
+ 2, -1, 12938, 2, 0, 26660, 3, -1, 10637, 3, 0, 15301, // 2, 0
+ 2, 0, 12897, 2, 1, 28430, 3, 0, 10102, 3, 1, 14107, // 2, 1
+ 2, 1, 12769, 2, 2, 30239, 3, 1, 9546, 3, 2, 12982, // 2, 2
+ 2, 2, 12569, 2, 3, 32045, 3, 2, 8988, 3, 3, 11934, // 2, 3
+ 2, 3, 12323, 2, 4, 33777, 3, 3, 8452, 3, 4, 10984, // 2, 4
+ 2, 4, 12079, 2, 5, 35332, 3, 4, 7969, 3, 5, 10156, // 2, 5
+ 2, 5, 11897, 2, 6, 36582, 3, 5, 7573, 3, 6, 9484, // 2, 6
+ 2, 6, 11842, 2, 7, 37402, 3, 6, 7298, 3, 7, 8994, // 2, 7
+ 1, 7, 7266, 1, 8, 8918, 2, 7, 11883, 2, 8, 37469, // 2, 8
+ 1, 8, 7543, 1, 9, 9390, 2, 8, 11972, 2, 9, 36631, // 2, 9
+ 1, 9, 7943, 1, 10, 10041, 2, 9, 12188, 2, 10, 35364, // 2,10
+ 1, 10, 8432, 1, 11, 10842, 2, 10, 12467, 2, 11, 33795, // 2,11
+ 1, 11, 8976, 1, 12, 11760, 2, 11, 12747, 2, 12, 32053, // 2,12
+ 1, 12, 9546, 1, 13, 12769, 2, 12, 12982, 2, 13, 30239, // 2,13
+ 1, 13, 10119, 1, 14, 13850, 2, 13, 13141, 2, 14, 28426, // 2,14
+ 1, 14, 10676, 1, 15, 14990, 2, 14, 13211, 2, 15, 26659, // 2,15
+ 3, -1, 12159, 3, 0, 27912, 4, -1, 10135, 4, 0, 15330, // 3, 0
+ 3, 0, 12014, 3, 1, 29938, 4, 0, 9575, 4, 1, 14009, // 3, 1
+ 3, 1, 11760, 3, 2, 32052, 4, 1, 8976, 4, 2, 12748, // 3, 2
+ 3, 2, 11411, 3, 3, 34213, 4, 2, 8358, 4, 3, 11554, // 3, 3
+ 3, 3, 10995, 3, 4, 36343, 4, 3, 7746, 4, 4, 10452, // 3, 4
+ 3, 4, 10569, 3, 5, 38307, 4, 4, 7180, 4, 5, 9480, // 3, 5
+ 3, 5, 10221, 3, 6, 39912, 4, 5, 6714, 4, 6, 8689, // 3, 6
+ 3, 6, 10051, 3, 7, 40940, 4, 6, 6403, 4, 7, 8142, // 3, 7
+ 2, 7, 6381, 2, 8, 8082, 3, 7, 10079, 3, 8, 40994, // 3, 8
+ 2, 8, 6695, 2, 9, 8617, 3, 8, 10275, 3, 9, 39949, // 3, 9
+ 2, 9, 7165, 2, 10, 9388, 3, 9, 10653, 3, 10, 38330, // 3,10
+ 2, 10, 7737, 2, 11, 10337, 3, 10, 11108, 3, 11, 36354, // 3,11
+ 2, 11, 8358, 2, 12, 11411, 3, 11, 11554, 3, 12, 34213, // 3,12
+ 2, 12, 8988, 2, 13, 12569, 3, 12, 11934, 3, 13, 32045, // 3,13
+ 2, 13, 9603, 2, 14, 13789, 3, 13, 12216, 3, 14, 29928, // 3,14
+ 2, 14, 10185, 2, 15, 15060, 3, 14, 12388, 3, 15, 27903, // 3,15
+ 4, -1, 11461, 4, 0, 29078, 5, -1, 9673, 5, 0, 15324, // 4, 0
+ 4, 0, 11218, 4, 1, 31361, 5, 0, 9082, 5, 1, 13875, // 4, 1
+ 4, 1, 10842, 4, 2, 33795, 5, 1, 8432, 5, 2, 12467, // 4, 2
+ 4, 2, 10337, 4, 3, 36354, 5, 2, 7737, 5, 3, 11108, // 4, 3
+ 4, 3, 9730, 4, 4, 38966, 5, 3, 7022, 5, 4, 9818, // 4, 4
+ 4, 4, 9081, 4, 5, 41475, 5, 4, 6334, 5, 5, 8646, // 4, 5
+ 4, 5, 8507, 4, 6, 43602, 5, 5, 5749, 5, 6, 7678, // 4, 6
+ 4, 6, 8177, 4, 7, 44962, 5, 6, 5368, 5, 7, 7029, // 4, 7
+ 3, 7, 5354, 3, 8, 6987, 4, 7, 8195, 4, 8, 45000, // 4, 8
+ 3, 8, 5739, 3, 9, 7626, 4, 8, 8545, 4, 9, 43626, // 4, 9
+ 3, 9, 6328, 3, 10, 8578, 4, 9, 9143, 4, 10, 41487, // 4,10
+ 3, 10, 7022, 3, 11, 9730, 4, 10, 9818, 4, 11, 38966, // 4,11
+ 3, 11, 7746, 3, 12, 10995, 4, 11, 10452, 4, 12, 36343, // 4,12
+ 3, 12, 8452, 3, 13, 12323, 4, 12, 10983, 4, 13, 33778, // 4,13
+ 3, 13, 9118, 3, 14, 13694, 4, 13, 11385, 4, 14, 31339, // 4,14
+ 3, 14, 9728, 3, 15, 15100, 4, 14, 11652, 4, 15, 29056, // 4,15
+ 5, -1, 10855, 5, 0, 30105, 6, -1, 9265, 6, 0, 15311, // 5, 0
+ 5, 0, 10528, 5, 1, 32624, 6, 0, 8645, 6, 1, 13739, // 5, 1
+ 5, 1, 10041, 5, 2, 35364, 6, 1, 7943, 6, 2, 12188, // 5, 2
+ 5, 2, 9388, 5, 3, 38330, 6, 2, 7165, 6, 3, 10653, // 5, 3
+ 5, 3, 8578, 5, 4, 41487, 6, 3, 6328, 6, 4, 9143, // 5, 4
+ 5, 4, 7659, 5, 5, 44700, 6, 4, 5472, 6, 5, 7705, // 5, 5
+ 5, 5, 6768, 5, 6, 47619, 6, 5, 4694, 6, 6, 6455, // 5, 6
+ 5, 6, 6183, 5, 7, 49566, 6, 6, 4172, 6, 7, 5615, // 5, 7
+ 4, 7, 4164, 4, 8, 5590, 5, 7, 6193, 5, 8, 49589, // 5, 8
+ 4, 8, 4690, 4, 9, 6422, 5, 8, 6794, 5, 9, 47630, // 5, 9
+ 4, 9, 5472, 4, 10, 7659, 5, 9, 7705, 5, 10, 44700, // 5,10
+ 4, 10, 6334, 4, 11, 9081, 5, 10, 8646, 5, 11, 41475, // 5,11
+ 4, 11, 7180, 4, 12, 10569, 5, 11, 9479, 5, 12, 38308, // 5,12
+ 4, 12, 7969, 4, 13, 12079, 5, 12, 10156, 5, 13, 35332, // 5,13
+ 4, 13, 8685, 4, 14, 13600, 5, 13, 10665, 5, 14, 32586, // 5,14
+ 4, 14, 9323, 4, 15, 15135, 5, 14, 11013, 5, 15, 30065, // 5,15
+ 6, -1, 10351, 6, 0, 30939, 7, -1, 8927, 7, 0, 15319, // 6, 0
+ 6, 0, 9961, 6, 1, 33642, 7, 0, 8286, 7, 1, 13647, // 6, 1
+ 6, 1, 9390, 6, 2, 36631, 7, 1, 7543, 7, 2, 11972, // 6, 2
+ 6, 2, 8617, 6, 3, 39949, 7, 2, 6695, 7, 3, 10275, // 6, 3
+ 6, 3, 7626, 6, 4, 43626, 7, 3, 5739, 7, 4, 8545, // 6, 4
+ 6, 4, 6422, 6, 5, 47630, 7, 4, 4690, 7, 5, 6794, // 6, 5
+ 6, 5, 5099, 6, 6, 51701, 7, 5, 3620, 7, 6, 5116, // 6, 6
+ 6, 6, 4044, 6, 7, 54831, 7, 6, 2797, 7, 7, 3864, // 6, 7
+ 5, 7, 2795, 5, 8, 3853, 6, 7, 4049, 6, 8, 54839, // 6, 8
+ 5, 8, 3620, 5, 9, 5099, 6, 8, 5116, 6, 9, 51701, // 6, 9
+ 5, 9, 4694, 5, 10, 6768, 6, 9, 6455, 6, 10, 47619, // 6,10
+ 5, 10, 5749, 5, 11, 8507, 6, 10, 7678, 6, 11, 43602, // 6,11
+ 5, 11, 6714, 5, 12, 10221, 6, 11, 8690, 6, 12, 39911, // 6,12
+ 5, 12, 7573, 5, 13, 11897, 6, 12, 9484, 6, 13, 36582, // 6,13
+ 5, 13, 8329, 5, 14, 13548, 6, 13, 10074, 6, 14, 33585, // 6,14
+ 5, 14, 8986, 5, 15, 15193, 6, 14, 10482, 6, 15, 30875, // 6,15
+ 7, -1, 9959, 7, 0, 31532, 8, -1, 8669, 8, 0, 15376, // 7, 0
+ 7, 0, 9534, 7, 1, 34340, 8, 0, 8024, 8, 1, 13638, // 7, 1
+ 7, 1, 8918, 7, 2, 37470, 8, 1, 7266, 8, 2, 11882, // 7, 2
+ 7, 2, 8082, 7, 3, 40994, 8, 2, 6381, 8, 3, 10079, // 7, 3
+ 7, 3, 6987, 7, 4, 44999, 8, 3, 5354, 8, 4, 8196, // 7, 4
+ 7, 4, 5590, 7, 5, 49588, 8, 4, 4164, 8, 5, 6194, // 7, 5
+ 7, 5, 3853, 7, 6, 54839, 8, 5, 2795, 8, 6, 4049, // 7, 6
+ 7, 6, 1903, 7, 7, 60382, 8, 6, 1347, 8, 7, 1904, // 7, 7
+ 6, 7, 1347, 6, 8, 1903, 7, 7, 1905, 7, 8, 60381, // 7, 8
+ 6, 8, 2797, 6, 9, 4044, 7, 8, 3864, 7, 9, 54831, // 7, 9
+ 6, 9, 4172, 6, 10, 6183, 7, 9, 5615, 7, 10, 49566, // 7,10
+ 6, 10, 5368, 6, 11, 8177, 7, 10, 7029, 7, 11, 44962, // 7,11
+ 6, 11, 6403, 6, 12, 10051, 7, 11, 8141, 7, 12, 40941, // 7,12
+ 6, 12, 7298, 6, 13, 11842, 7, 12, 8994, 7, 13, 37402, // 7,13
+ 6, 13, 8068, 6, 14, 13582, 7, 13, 9626, 7, 14, 34260, // 7,14
+ 6, 14, 8727, 6, 15, 15301, 7, 14, 10065, 7, 15, 31443, // 7,15
+ 8, 0, 31444, 8, 1, 10065, 9, 0, 15301, 9, 1, 8726, // 8, 0
+ 8, 1, 34261, 8, 2, 9626, 9, 1, 13582, 9, 2, 8067, // 8, 1
+ 8, 2, 37402, 8, 3, 8994, 9, 2, 11842, 9, 3, 7298, // 8, 2
+ 8, 3, 40940, 8, 4, 8141, 9, 3, 10051, 9, 4, 6404, // 8, 3
+ 8, 4, 44962, 8, 5, 7029, 9, 4, 8177, 9, 5, 5368, // 8, 4
+ 8, 5, 49566, 8, 6, 5615, 9, 5, 6183, 9, 6, 4172, // 8, 5
+ 8, 6, 54831, 8, 7, 3864, 9, 6, 4044, 9, 7, 2797, // 8, 6
+ 8, 7, 60382, 8, 8, 1905, 9, 7, 1903, 9, 8, 1346, // 8, 7
+ 7, 8, 1905, 7, 9, 1347, 8, 8, 60382, 8, 9, 1902, // 8, 8
+ 7, 9, 4049, 7, 10, 2795, 8, 9, 54839, 8, 10, 3853, // 8, 9
+ 7, 10, 6193, 7, 11, 4164, 8, 10, 49588, 8, 11, 5591, // 8,10
+ 7, 11, 8195, 7, 12, 5354, 8, 11, 44999, 8, 12, 6988, // 8,11
+ 7, 12, 10079, 7, 13, 6381, 8, 12, 40994, 8, 13, 8082, // 8,12
+ 7, 13, 11883, 7, 14, 7266, 8, 13, 37470, 8, 14, 8917, // 8,13
+ 7, 14, 13638, 7, 15, 8024, 8, 14, 34340, 8, 15, 9534, // 8,14
+ 7, 15, 15376, 7, 16, 8669, 8, 15, 31532, 8, 16, 9959, // 8,15
+ 9, 0, 30876, 9, 1, 10482, 10, 0, 15193, 10, 1, 8985, // 9, 0
+ 9, 1, 33585, 9, 2, 10074, 10, 1, 13548, 10, 2, 8329, // 9, 1
+ 9, 2, 36582, 9, 3, 9484, 10, 2, 11897, 10, 3, 7573, // 9, 2
+ 9, 3, 39912, 9, 4, 8690, 10, 3, 10221, 10, 4, 6713, // 9, 3
+ 9, 4, 43602, 9, 5, 7678, 10, 4, 8507, 10, 5, 5749, // 9, 4
+ 9, 5, 47619, 9, 6, 6455, 10, 5, 6768, 10, 6, 4694, // 9, 5
+ 9, 6, 51701, 9, 7, 5116, 10, 6, 5099, 10, 7, 3620, // 9, 6
+ 9, 7, 54839, 9, 8, 4049, 10, 7, 3853, 10, 8, 2795, // 9, 7
+ 8, 8, 3864, 8, 9, 2797, 9, 8, 54831, 9, 9, 4044, // 9, 8
+ 8, 9, 5116, 8, 10, 3620, 9, 9, 51701, 9, 10, 5099, // 9, 9
+ 8, 10, 6794, 8, 11, 4690, 9, 10, 47630, 9, 11, 6422, // 9,10
+ 8, 11, 8545, 8, 12, 5739, 9, 11, 43626, 9, 12, 7626, // 9,11
+ 8, 12, 10275, 8, 13, 6695, 9, 12, 39949, 9, 13, 8617, // 9,12
+ 8, 13, 11972, 8, 14, 7543, 9, 13, 36631, 9, 14, 9390, // 9,13
+ 8, 14, 13647, 8, 15, 8286, 9, 14, 33642, 9, 15, 9961, // 9,14
+ 8, 15, 15319, 8, 16, 8927, 9, 15, 30939, 9, 16, 10351, // 9,15
+ 10, 0, 30064, 10, 1, 11013, 11, 0, 15135, 11, 1, 9324, // 10, 0
+ 10, 1, 32586, 10, 2, 10665, 11, 1, 13600, 11, 2, 8685, // 10, 1
+ 10, 2, 35332, 10, 3, 10156, 11, 2, 12079, 11, 3, 7969, // 10, 2
+ 10, 3, 38307, 10, 4, 9479, 11, 3, 10569, 11, 4, 7181, // 10, 3
+ 10, 4, 41475, 10, 5, 8646, 11, 4, 9081, 11, 5, 6334, // 10, 4
+ 10, 5, 44700, 10, 6, 7705, 11, 5, 7659, 11, 6, 5472, // 10, 5
+ 10, 6, 47630, 10, 7, 6794, 11, 6, 6422, 11, 7, 4690, // 10, 6
+ 10, 7, 49588, 10, 8, 6193, 11, 7, 5590, 11, 8, 4165, // 10, 7
+ 9, 8, 5615, 9, 9, 4172, 10, 8, 49566, 10, 9, 6183, // 10, 8
+ 9, 9, 6455, 9, 10, 4694, 10, 9, 47619, 10, 10, 6768, // 10, 9
+ 9, 10, 7705, 9, 11, 5472, 10, 10, 44700, 10, 11, 7659, // 10,10
+ 9, 11, 9143, 9, 12, 6328, 10, 11, 41487, 10, 12, 8578, // 10,11
+ 9, 12, 10653, 9, 13, 7165, 10, 12, 38330, 10, 13, 9388, // 10,12
+ 9, 13, 12188, 9, 14, 7943, 10, 13, 35364, 10, 14, 10041, // 10,13
+ 9, 14, 13740, 9, 15, 8645, 10, 14, 32624, 10, 15, 10527, // 10,14
+ 9, 15, 15311, 9, 16, 9265, 10, 15, 30105, 10, 16, 10855, // 10,15
+ 11, 0, 29055, 11, 1, 11652, 12, 0, 15100, 12, 1, 9729, // 11, 0
+ 11, 1, 31339, 11, 2, 11385, 12, 1, 13694, 12, 2, 9118, // 11, 1
+ 11, 2, 33777, 11, 3, 10983, 12, 2, 12323, 12, 3, 8453, // 11, 2
+ 11, 3, 36343, 11, 4, 10452, 12, 3, 10995, 12, 4, 7746, // 11, 3
+ 11, 4, 38966, 11, 5, 9818, 12, 4, 9730, 12, 5, 7022, // 11, 4
+ 11, 5, 41487, 11, 6, 9143, 12, 5, 8578, 12, 6, 6328, // 11, 5
+ 11, 6, 43626, 11, 7, 8545, 12, 6, 7626, 12, 7, 5739, // 11, 6
+ 11, 7, 44999, 11, 8, 8195, 12, 7, 6987, 12, 8, 5355, // 11, 7
+ 10, 8, 7029, 10, 9, 5368, 11, 8, 44962, 11, 9, 8177, // 11, 8
+ 10, 9, 7678, 10, 10, 5749, 11, 9, 43602, 11, 10, 8507, // 11, 9
+ 10, 10, 8646, 10, 11, 6334, 11, 10, 41475, 11, 11, 9081, // 11,10
+ 10, 11, 9818, 10, 12, 7022, 11, 11, 38966, 11, 12, 9730, // 11,11
+ 10, 12, 11108, 10, 13, 7737, 11, 12, 36354, 11, 13, 10337, // 11,12
+ 10, 13, 12467, 10, 14, 8432, 11, 13, 33795, 11, 14, 10842, // 11,13
+ 10, 14, 13875, 10, 15, 9082, 11, 14, 31361, 11, 15, 11218, // 11,14
+ 10, 15, 15325, 10, 16, 9673, 11, 15, 29078, 11, 16, 11460, // 11,15
+ 12, 0, 27903, 12, 1, 12388, 13, 0, 15060, 13, 1, 10185, // 12, 0
+ 12, 1, 29928, 12, 2, 12216, 13, 1, 13789, 13, 2, 9603, // 12, 1
+ 12, 2, 32045, 12, 3, 11934, 13, 2, 12569, 13, 3, 8988, // 12, 2
+ 12, 3, 34213, 12, 4, 11554, 13, 3, 11411, 13, 4, 8358, // 12, 3
+ 12, 4, 36354, 12, 5, 11108, 13, 4, 10337, 13, 5, 7737, // 12, 4
+ 12, 5, 38330, 12, 6, 10653, 13, 5, 9388, 13, 6, 7165, // 12, 5
+ 12, 6, 39949, 12, 7, 10275, 13, 6, 8617, 13, 7, 6695, // 12, 6
+ 12, 7, 40994, 12, 8, 10079, 13, 7, 8082, 13, 8, 6381, // 12, 7
+ 11, 8, 8141, 11, 9, 6403, 12, 8, 40940, 12, 9, 10052, // 12, 8
+ 11, 9, 8690, 11, 10, 6714, 12, 9, 39912, 12, 10, 10220, // 12, 9
+ 11, 10, 9479, 11, 11, 7180, 12, 10, 38307, 12, 11, 10570, // 12,10
+ 11, 11, 10452, 11, 12, 7746, 12, 11, 36343, 12, 12, 10995, // 12,11
+ 11, 12, 11554, 11, 13, 8358, 12, 12, 34213, 12, 13, 11411, // 12,12
+ 11, 13, 12747, 11, 14, 8976, 12, 13, 32052, 12, 14, 11761, // 12,13
+ 11, 14, 14009, 11, 15, 9575, 12, 14, 29938, 12, 15, 12014, // 12,14
+ 11, 15, 15330, 11, 16, 10135, 12, 15, 27912, 12, 16, 12159, // 12,15
+ 13, 0, 26660, 13, 1, 13211, 14, 0, 14990, 14, 1, 10675, // 13, 0
+ 13, 1, 28427, 13, 2, 13141, 14, 1, 13850, 14, 2, 10118, // 13, 1
+ 13, 2, 30239, 13, 3, 12982, 14, 2, 12769, 14, 3, 9546, // 13, 2
+ 13, 3, 32052, 13, 4, 12747, 14, 3, 11760, 14, 4, 8977, // 13, 3
+ 13, 4, 33795, 13, 5, 12467, 14, 4, 10842, 14, 5, 8432, // 13, 4
+ 13, 5, 35364, 13, 6, 12188, 14, 5, 10041, 14, 6, 7943, // 13, 5
+ 13, 6, 36631, 13, 7, 11972, 14, 6, 9390, 14, 7, 7543, // 13, 6
+ 13, 7, 37470, 13, 8, 11883, 14, 7, 8918, 14, 8, 7265, // 13, 7
+ 12, 8, 8994, 12, 9, 7298, 13, 8, 37402, 13, 9, 11842, // 13, 8
+ 12, 9, 9484, 12, 10, 7573, 13, 9, 36582, 13, 10, 11897, // 13, 9
+ 12, 10, 10156, 12, 11, 7969, 13, 10, 35332, 13, 11, 12079, // 13,10
+ 12, 11, 10983, 12, 12, 8452, 13, 11, 33777, 13, 12, 12324, // 13,11
+ 12, 12, 11934, 12, 13, 8988, 13, 12, 32045, 13, 13, 12569, // 13,12
+ 12, 13, 12982, 12, 14, 9546, 13, 13, 30239, 13, 14, 12769, // 13,13
+ 12, 14, 14107, 12, 15, 10102, 13, 14, 28430, 13, 15, 12897, // 13,14
+ 12, 15, 15301, 12, 16, 10637, 13, 15, 26660, 13, 16, 12938, // 13,15
+ 14, 0, 25368, 14, 1, 14109, 15, 0, 14872, 15, 1, 11187, // 14, 0
+ 14, 1, 26893, 14, 2, 14145, 15, 1, 13853, 15, 2, 10645, // 14, 1
+ 14, 2, 28430, 14, 3, 14107, 15, 2, 12897, 15, 3, 10102, // 14, 2
+ 14, 3, 29938, 14, 4, 14009, 15, 3, 12014, 15, 4, 9575, // 14, 3
+ 14, 4, 31361, 14, 5, 13875, 15, 4, 11218, 15, 5, 9082, // 14, 4
+ 14, 5, 32624, 14, 6, 13740, 15, 5, 10528, 15, 6, 8644, // 14, 5
+ 14, 6, 33642, 14, 7, 13647, 15, 6, 9961, 15, 7, 8286, // 14, 6
+ 14, 7, 34340, 14, 8, 13638, 15, 7, 9534, 15, 8, 8024, // 14, 7
+ 13, 8, 9626, 13, 9, 8068, 14, 8, 34261, 14, 9, 13581, // 14, 8
+ 13, 9, 10074, 13, 10, 8329, 14, 9, 33585, 14, 10, 13548, // 14, 9
+ 13, 10, 10665, 13, 11, 8685, 14, 10, 32586, 14, 11, 13600, // 14,10
+ 13, 11, 11385, 13, 12, 9118, 14, 11, 31339, 14, 12, 13694, // 14,11
+ 13, 12, 12216, 13, 13, 9603, 14, 12, 29928, 14, 13, 13789, // 14,12
+ 13, 13, 13141, 13, 14, 10119, 14, 13, 28427, 14, 14, 13849, // 14,13
+ 13, 14, 14145, 13, 15, 10644, 14, 14, 26893, 14, 15, 13854, // 14,14
+ 13, 15, 15220, 13, 16, 11164, 14, 15, 25366, 14, 16, 13786, // 14,15
+ 15, 0, 24063, 15, 1, 15076, 16, 0, 14696, 16, 1, 11701, // 15, 0
+ 15, 1, 25366, 15, 2, 15220, 16, 1, 13787, 16, 2, 11163, // 15, 1
+ 15, 2, 26660, 15, 3, 15301, 16, 2, 12938, 16, 3, 10637, // 15, 2
+ 15, 3, 27912, 15, 4, 15330, 16, 3, 12159, 16, 4, 10135, // 15, 3
+ 15, 4, 29078, 15, 5, 15325, 16, 4, 11461, 16, 5, 9672, // 15, 4
+ 15, 5, 30105, 15, 6, 15311, 16, 5, 10855, 16, 6, 9265, // 15, 5
+ 15, 6, 30939, 15, 7, 15319, 16, 6, 10351, 16, 7, 8927, // 15, 6
+ 15, 7, 31532, 15, 8, 15376, 16, 7, 9959, 16, 8, 8669, // 15, 7
+ 14, 8, 10065, 14, 9, 8727, 15, 8, 31444, 15, 9, 15300, // 15, 8
+ 14, 9, 10482, 14, 10, 8986, 15, 9, 30876, 15, 10, 15192, // 15, 9
+ 14, 10, 11013, 14, 11, 9323, 15, 10, 30064, 15, 11, 15136, // 15,10
+ 14, 11, 11652, 14, 12, 9728, 15, 11, 29055, 15, 12, 15101, // 15,11
+ 14, 12, 12388, 14, 13, 10185, 15, 12, 27903, 15, 13, 15060, // 15,12
+ 14, 13, 13211, 14, 14, 10676, 15, 13, 26660, 15, 14, 14989, // 15,13
+ 14, 14, 14109, 14, 15, 11187, 15, 14, 25368, 15, 15, 14872, // 15,14
+ 14, 15, 15076, 14, 16, 11702, 15, 15, 24063, 15, 16, 14695, // 15,15
diff --git a/vp8/common/seg_common.c b/vp8/common/seg_common.c
new file mode 100644
index 000000000..3ba374a49
--- /dev/null
+++ b/vp8/common/seg_common.c
@@ -0,0 +1,167 @@
+/*
+ * 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 "vp8/common/seg_common.h"
+
+const int segfeaturedata_signed[SEG_LVL_MAX] = {1, 1, 0, 0, 0, 0};
+const int vp8_seg_feature_data_bits[SEG_LVL_MAX] =
+ {QINDEX_BITS, 6, 4, 4, 6, 2};
+
+// 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.
+
+int segfeature_active( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ // Return true if mask bit set and segmentation enabled.
+ return ( xd->segmentation_enabled &&
+ ( xd->segment_feature_mask[segment_id] &
+ (0x01 << feature_id) ) );
+}
+
+void clearall_segfeatures( MACROBLOCKD *xd )
+{
+ vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
+ vpx_memset(xd->segment_feature_mask, 0, sizeof(xd->segment_feature_mask));
+}
+
+void enable_segfeature( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ xd->segment_feature_mask[segment_id] |= (0x01 << feature_id);
+}
+
+void disable_segfeature( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ xd->segment_feature_mask[segment_id] &= ~(1 << feature_id);
+}
+
+int seg_feature_data_bits( SEG_LVL_FEATURES feature_id )
+{
+ return vp8_seg_feature_data_bits[feature_id];
+}
+
+int is_segfeature_signed( SEG_LVL_FEATURES feature_id )
+{
+ return ( segfeaturedata_signed[feature_id] );
+}
+
+void clear_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id)
+{
+ xd->segment_feature_data[segment_id][feature_id] = 0;
+}
+
+void set_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id,
+ int seg_data )
+{
+ xd->segment_feature_data[segment_id][feature_id] = seg_data;
+}
+
+int get_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ return xd->segment_feature_data[segment_id][feature_id];
+}
+#if CONFIG_FEATUREUPDATES
+int old_segfeature_active( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ // Return true if mask bit set and segmentation enabled.
+ return ( xd->segmentation_enabled &&
+ ( xd->old_segment_feature_mask[segment_id] &
+ (0x01 << feature_id) ) );
+}
+
+int get_old_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ return xd->old_segment_feature_data[segment_id][feature_id];
+}
+
+int segfeature_changed( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id )
+{
+ // Return true if mask bit or data is different from last time
+ return
+ ( xd->segmentation_enabled &&
+ (
+ (xd->old_segment_feature_mask[segment_id] & (1 << feature_id) ) !=
+ (xd->segment_feature_mask[segment_id] & (1 << feature_id) )
+ || xd->old_segment_feature_data[segment_id][feature_id] !=
+ xd->segment_feature_data[segment_id][feature_id]
+ )
+ );
+}
+
+void save_segment_info ( MACROBLOCKD *xd )
+{
+ int i,j;
+ for (i = 0; i < MAX_MB_SEGMENTS; i++)
+ {
+ xd->old_segment_feature_mask[i] = xd->segment_feature_mask[i];
+
+ // For each segmentation codable feature...
+ for (j = 0; j < SEG_LVL_MAX; j++)
+ {
+ xd->old_segment_feature_data[i][j]=xd->segment_feature_data[i][j];
+
+ }
+ }
+}
+#endif
+void clear_segref( MACROBLOCKD *xd, int segment_id )
+{
+ xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] = 0;
+}
+
+void set_segref( MACROBLOCKD *xd,
+ int segment_id,
+ MV_REFERENCE_FRAME ref_frame )
+{
+ xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] |=
+ (1 << ref_frame);
+}
+
+int check_segref( MACROBLOCKD *xd,
+ int segment_id,
+ MV_REFERENCE_FRAME ref_frame )
+{
+ return ( xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] &
+ (1 << ref_frame) ) ? 1 : 0;
+}
+
+int check_segref_inter(MACROBLOCKD *xd, int segment_id)
+{
+ return ( xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] &
+ ~(1 << INTRA_FRAME) ) ? 1 : 0;
+}
+
+int get_seg_tx_type(MACROBLOCKD *xd, int segment_id)
+{
+ if ( segfeature_active(xd, segment_id, SEG_LVL_TRANSFORM) )
+ return get_segdata(xd, segment_id, SEG_LVL_TRANSFORM);
+ else
+ return TX_4X4;
+}
+// TBD? Functions to read and write segment data with range / validity checking
diff --git a/vp8/common/seg_common.h b/vp8/common/seg_common.h
new file mode 100644
index 000000000..bfd364e6d
--- /dev/null
+++ b/vp8/common/seg_common.h
@@ -0,0 +1,85 @@
+/*
+ * 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 "type_aliases.h"
+#include "onyxc_int.h"
+#include "vp8/common/blockd.h"
+
+#ifndef __INC_SEG_COMMON_H__
+#define __INC_SEG_COMMON_H__ 1
+
+int segfeature_active( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+void clearall_segfeatures( MACROBLOCKD *xd );
+
+void enable_segfeature( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+void disable_segfeature( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+int seg_feature_data_bits( SEG_LVL_FEATURES feature_id );
+
+int is_segfeature_signed( SEG_LVL_FEATURES feature_id );
+
+void clear_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id);
+
+void set_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id,
+ int seg_data );
+
+int get_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+#if CONFIG_FEATUREUPDATES
+
+int old_segfeature_active( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+int get_old_segdata( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+void save_segment_info ( MACROBLOCKD *xd );
+
+int segfeature_changed( MACROBLOCKD *xd,
+ int segment_id,
+ SEG_LVL_FEATURES feature_id );
+
+
+
+#endif
+
+
+void clear_segref( MACROBLOCKD *xd, int segment_id );
+
+void set_segref( MACROBLOCKD *xd,
+ int segment_id,
+ MV_REFERENCE_FRAME ref_frame );
+
+int check_segref( MACROBLOCKD *xd,
+ int segment_id,
+ MV_REFERENCE_FRAME ref_frame );
+
+int check_segref_inter(MACROBLOCKD *xd, int segment_id);
+
+int get_seg_tx_type(MACROBLOCKD *xd, int segment_id);
+
+#endif /* __INC_SEG_COMMON_H__ */
+
diff --git a/vp8/common/subpixel.h b/vp8/common/subpixel.h
index acdeec3bc..0b1b72fa0 100644
--- a/vp8/common/subpixel.h
+++ b/vp8/common/subpixel.h
@@ -34,6 +34,15 @@ extern prototype_subpixel_predict(vp8_subpix_sixtap16x16);
#endif
extern prototype_subpixel_predict(vp8_subpix_sixtap8x8);
+#ifndef vp8_subpix_sixtap_avg16x16
+#define vp8_subpix_sixtap_avg16x16 vp8_sixtap_predict_avg16x16_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_sixtap_avg16x16);
+
+#ifndef vp8_subpix_sixtap_avg8x8
+#define vp8_subpix_sixtap_avg8x8 vp8_sixtap_predict_avg8x8_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_sixtap_avg8x8);
#ifndef vp8_subpix_sixtap8x4
#define vp8_subpix_sixtap8x4 vp8_sixtap_predict8x4_c
#endif
@@ -54,6 +63,16 @@ extern prototype_subpixel_predict(vp8_subpix_bilinear16x16);
#endif
extern prototype_subpixel_predict(vp8_subpix_bilinear8x8);
+#ifndef vp8_subpix_bilinear_avg16x16
+#define vp8_subpix_bilinear_avg16x16 vp8_bilinear_predict_avg16x16_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_bilinear_avg16x16);
+
+#ifndef vp8_subpix_bilinear_avg8x8
+#define vp8_subpix_bilinear_avg8x8 vp8_bilinear_predict_avg8x8_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_bilinear_avg8x8);
+
#ifndef vp8_subpix_bilinear8x4
#define vp8_subpix_bilinear8x4 vp8_bilinear_predict8x4_c
#endif
@@ -69,10 +88,14 @@ typedef struct
{
vp8_subpix_fn_t sixtap16x16;
vp8_subpix_fn_t sixtap8x8;
+ vp8_subpix_fn_t sixtap_avg16x16;
+ vp8_subpix_fn_t sixtap_avg8x8;
vp8_subpix_fn_t sixtap8x4;
vp8_subpix_fn_t sixtap4x4;
vp8_subpix_fn_t bilinear16x16;
vp8_subpix_fn_t bilinear8x8;
+ vp8_subpix_fn_t bilinear_avg16x16;
+ vp8_subpix_fn_t bilinear_avg8x8;
vp8_subpix_fn_t bilinear8x4;
vp8_subpix_fn_t bilinear4x4;
} vp8_subpix_rtcd_vtable_t;
diff --git a/vp8/common/systemdependent.h b/vp8/common/systemdependent.h
index f99c4bb2a..db996987a 100644
--- a/vp8/common/systemdependent.h
+++ b/vp8/common/systemdependent.h
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#if ARCH_X86 || ARCH_X86_64
void vpx_reset_mmx_state(void);
#define vp8_clear_system_state() vpx_reset_mmx_state()
diff --git a/vp8/common/tapify.py b/vp8/common/tapify.py
new file mode 100644
index 000000000..99529cff0
--- /dev/null
+++ b/vp8/common/tapify.py
@@ -0,0 +1,106 @@
+"""
+ * 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.
+"""
+#!/usr/bin/env python
+import sys,string,os,re,math,numpy
+scale = 2**16
+def dist(p1,p2):
+ x1,y1 = p1
+ x2,y2 = p2
+ if x1==x2 and y1==y2 :
+ return 1.0
+ return 1/ math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
+
+def gettaps(p):
+ def l(b):
+ return int(math.floor(b))
+ def h(b):
+ return int(math.ceil(b))
+ def t(b,p,s):
+ return int((scale*dist(b,p)+s/2)/s)
+ r,c = p
+ ul=[l(r),l(c)]
+ ur=[l(r),h(c)]
+ ll=[h(r),l(c)]
+ lr=[h(r),h(c)]
+ sum = dist(ul,p)+dist(ur,p)+dist(ll,p)+dist(lr,p)
+ t4 = scale - t(ul,p,sum) - t(ur,p,sum) - t(ll,p,sum);
+ return [[ul,t(ul,p,sum)],[ur,t(ur,p,sum)],
+ [ll,t(ll,p,sum)],[lr,t4]]
+
+def print_mb_taps(angle,blocksize):
+ theta = angle / 57.2957795;
+ affine = [[math.cos(theta),-math.sin(theta)],
+ [math.sin(theta),math.cos(theta)]]
+ radius = (float(blocksize)-1)/2
+ print " // angle of",angle,"degrees"
+ for y in range(blocksize) :
+ for x in range(blocksize) :
+ r,c = numpy.dot(affine,[y-radius, x-radius])
+ tps = gettaps([r+radius,c+radius])
+ for t in tps :
+ p,t = t
+ tr,tc = p
+ print " %2d, %2d, %5d, " % (tr,tc,t,),
+ print " // %2d,%2d " % (y,x)
+
+i=float(sys.argv[1])
+while i <= float(sys.argv[2]) :
+ print_mb_taps(i,float(sys.argv[4]))
+ i=i+float(sys.argv[3])
+"""
+
+taps = []
+pt=dict()
+ptr=dict()
+for y in range(16) :
+ for x in range(16) :
+ r,c = numpy.dot(affine,[y-7.5, x-7.5])
+ tps = gettaps([r+7.5,c+7.5])
+ j=0
+ for tp in tps :
+ p,i = tp
+ r,c = p
+ pt[y,x,j]= [p,i]
+ try:
+ ptr[r,j,c].append([y,x])
+ except:
+ ptr[r,j,c]=[[y,x]]
+ j = j+1
+
+for key in sorted(pt.keys()) :
+ print key,pt[key]
+
+lr = -99
+lj = -99
+lc = 0
+
+shuf=""
+mask=""
+for r,j,c in sorted(ptr.keys()) :
+ for y,x in ptr[r,j,c] :
+ if lr != r or lj != j :
+ print "shuf_"+str(lr)+"_"+str(lj)+"_"+shuf.ljust(16,"0"), lc
+ shuf=""
+ lc = 0
+ for i in range(lc,c-1) :
+ shuf = shuf +"0"
+ shuf = shuf + hex(x)[2]
+ lc =c
+ break
+ lr = r
+ lj = j
+# print r,j,c,ptr[r,j,c]
+# print
+
+for r,j,c in sorted(ptr.keys()) :
+ for y,x in ptr[r,j,c] :
+ print r,j,c,y,x
+ break
+"""
diff --git a/vp8/common/threading.h b/vp8/common/threading.h
deleted file mode 100644
index 5927cb165..000000000
--- a/vp8/common/threading.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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 _PTHREAD_EMULATION
-#define _PTHREAD_EMULATION
-
-#if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD
-
-/* Thread management macros */
-#ifdef _WIN32
-/* Win32 */
-#define _WIN32_WINNT 0x500 /* WINBASE.H - Enable signal_object_and_wait */
-#include <process.h>
-#include <windows.h>
-#define THREAD_FUNCTION DWORD WINAPI
-#define THREAD_FUNCTION_RETURN DWORD
-#define THREAD_SPECIFIC_INDEX DWORD
-#define pthread_t HANDLE
-#define pthread_attr_t DWORD
-#define pthread_create(thhandle,attr,thfunc,tharg) (int)((*thhandle=(HANDLE)_beginthreadex(NULL,0,(unsigned int (__stdcall *)(void *))thfunc,tharg,0,NULL))==NULL)
-#define pthread_join(thread, result) ((WaitForSingleObject((thread),INFINITE)!=WAIT_OBJECT_0) || !CloseHandle(thread))
-#define pthread_detach(thread) if(thread!=NULL)CloseHandle(thread)
-#define thread_sleep(nms) Sleep(nms)
-#define pthread_cancel(thread) terminate_thread(thread,0)
-#define ts_key_create(ts_key, destructor) {ts_key = TlsAlloc();};
-#define pthread_getspecific(ts_key) TlsGetValue(ts_key)
-#define pthread_setspecific(ts_key, value) TlsSetValue(ts_key, (void *)value)
-#define pthread_self() GetCurrentThreadId()
-#else
-#ifdef __APPLE__
-#include <mach/mach_init.h>
-#include <mach/semaphore.h>
-#include <mach/task.h>
-#include <time.h>
-#include <unistd.h>
-
-#else
-#include <semaphore.h>
-#endif
-
-#include <pthread.h>
-/* pthreads */
-/* Nearly everything is already defined */
-#define THREAD_FUNCTION void *
-#define THREAD_FUNCTION_RETURN void *
-#define THREAD_SPECIFIC_INDEX pthread_key_t
-#define ts_key_create(ts_key, destructor) pthread_key_create (&(ts_key), destructor);
-#endif
-
-/* Syncrhronization macros: Win32 and Pthreads */
-#ifdef _WIN32
-#define sem_t HANDLE
-#define pause(voidpara) __asm PAUSE
-#define sem_init(sem, sem_attr1, sem_init_value) (int)((*sem = CreateSemaphore(NULL,0,32768,NULL))==NULL)
-#define sem_wait(sem) (int)(WAIT_OBJECT_0 != WaitForSingleObject(*sem,INFINITE))
-#define sem_post(sem) ReleaseSemaphore(*sem,1,NULL)
-#define sem_destroy(sem) if(*sem)((int)(CloseHandle(*sem))==TRUE)
-#define thread_sleep(nms) Sleep(nms)
-
-#else
-
-#ifdef __APPLE__
-#define sem_t semaphore_t
-#define sem_init(X,Y,Z) semaphore_create(mach_task_self(), X, SYNC_POLICY_FIFO, Z)
-#define sem_wait(sem) (semaphore_wait(*sem) )
-#define sem_post(sem) semaphore_signal(*sem)
-#define sem_destroy(sem) semaphore_destroy(mach_task_self(),*sem)
-#define thread_sleep(nms) /* { struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);} */
-#else
-#include <unistd.h>
-#include <sched.h>
-#define thread_sleep(nms) sched_yield();/* {struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);} */
-#endif
-/* Not Windows. Assume pthreads */
-
-#endif
-
-#if ARCH_X86 || ARCH_X86_64
-#include "vpx_ports/x86.h"
-#else
-#define x86_pause_hint()
-#endif
-
-#endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */
-
-#endif
diff --git a/vp8/common/x86/mask_sse3.asm b/vp8/common/x86/mask_sse3.asm
new file mode 100644
index 000000000..0d90cfa86
--- /dev/null
+++ b/vp8/common/x86/mask_sse3.asm
@@ -0,0 +1,484 @@
+;
+; 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_ports/x86_abi_support.asm"
+
+;void int vp8_makemask_sse3(
+; unsigned char *y,
+; unsigned char *u,
+; unsigned char *v,
+; unsigned char *ym,
+; unsigned char *uvm,
+; int yp,
+; int uvp,
+; int ys,
+; int us,
+; int vs,
+; int yt,
+; int ut,
+; int vt)
+global sym(vp8_makemask_sse3)
+sym(vp8_makemask_sse3):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 14
+ push rsi
+ push rdi
+ ; end prolog
+
+ mov rsi, arg(0) ;y
+ mov rdi, arg(1) ;u
+ mov rcx, arg(2) ;v
+ mov rax, arg(3) ;ym
+ movsxd rbx, dword arg(4) ;yp
+ movsxd rdx, dword arg(5) ;uvp
+
+ pxor xmm0,xmm0
+
+ ;make 16 copies of the center y value
+ movd xmm1, arg(6)
+ pshufb xmm1, xmm0
+
+ ; make 16 copies of the center u value
+ movd xmm2, arg(7)
+ pshufb xmm2, xmm0
+
+ ; make 16 copies of the center v value
+ movd xmm3, arg(8)
+ pshufb xmm3, xmm0
+ unpcklpd xmm2, xmm3
+
+ ;make 16 copies of the y tolerance
+ movd xmm3, arg(9)
+ pshufb xmm3, xmm0
+
+ ;make 16 copies of the u tolerance
+ movd xmm4, arg(10)
+ pshufb xmm4, xmm0
+
+ ;make 16 copies of the v tolerance
+ movd xmm5, arg(11)
+ pshufb xmm5, xmm0
+ unpckhpd xmm4, xmm5
+
+ mov r8,8
+
+NextPairOfRows:
+
+ ;grab the y source values
+ movdqu xmm0, [rsi]
+
+ ;compute abs difference between source and y target
+ movdqa xmm6, xmm1
+ movdqa xmm7, xmm0
+ psubusb xmm0, xmm1
+ psubusb xmm6, xmm7
+ por xmm0, xmm6
+
+ ;compute abs difference between
+ movdqa xmm6, xmm3
+ pcmpgtb xmm6, xmm0
+
+ ;grab the y source values
+ add rsi, rbx
+ movdqu xmm0, [rsi]
+
+ ;compute abs difference between source and y target
+ movdqa xmm11, xmm1
+ movdqa xmm7, xmm0
+ psubusb xmm0, xmm1
+ psubusb xmm11, xmm7
+ por xmm0, xmm11
+
+ ;compute abs difference between
+ movdqa xmm11, xmm3
+ pcmpgtb xmm11, xmm0
+
+
+ ;grab the u and v source values
+ movdqu xmm7, [rdi]
+ movdqu xmm8, [rcx]
+ unpcklpd xmm7, xmm8
+
+ ;compute abs difference between source and uv targets
+ movdqa xmm9, xmm2
+ movdqa xmm10, xmm7
+ psubusb xmm7, xmm2
+ psubusb xmm9, xmm10
+ por xmm7, xmm9
+
+ ;check whether the number is < tolerance
+ movdqa xmm0, xmm4
+ pcmpgtb xmm0, xmm7
+
+ ;double u and v masks
+ movdqa xmm8, xmm0
+ punpckhbw xmm0, xmm0
+ punpcklbw xmm8, xmm8
+
+ ;mask row 0 and output
+ pand xmm6, xmm8
+ pand xmm6, xmm0
+ movdqa [rax],xmm6
+
+ ;mask row 1 and output
+ pand xmm11, xmm8
+ pand xmm11, xmm0
+ movdqa [rax+16],xmm11
+
+
+ ; to the next row or set of rows
+ add rsi, rbx
+ add rdi, rdx
+ add rcx, rdx
+ add rax,32
+ dec r8
+ jnz NextPairOfRows
+
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+;GROW_HORIZ (register for result, source register or mem local)
+; takes source and shifts left and ors with source
+; then shifts right and ors with source
+%macro GROW_HORIZ 2
+ movdqa %1, %2
+ movdqa xmm14, %1
+ movdqa xmm15, %1
+ pslldq xmm14, 1
+ psrldq xmm15, 1
+ por %1,xmm14
+ por %1,xmm15
+%endmacro
+;GROW_VERT (result, center row, above row, below row)
+%macro GROW_VERT 4
+ movdqa %1,%2
+ por %1,%3
+ por %1,%4
+%endmacro
+
+;GROW_NEXTLINE (new line to grow, new source, line to write)
+%macro GROW_NEXTLINE 3
+ GROW_HORIZ %1, %2
+ GROW_VERT xmm3, xmm0, xmm1, xmm2
+ movdqa %3,xmm3
+%endmacro
+
+
+;void int vp8_growmaskmb_sse3(
+; unsigned char *om,
+; unsigned char *nm,
+global sym(vp8_growmaskmb_sse3)
+sym(vp8_growmaskmb_sse3):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 2
+ push rsi
+ push rdi
+ ; end prolog
+
+ mov rsi, arg(0) ;src
+ mov rdi, arg(1) ;rst
+
+ GROW_HORIZ xmm0, [rsi]
+ GROW_HORIZ xmm1, [rsi+16]
+ GROW_HORIZ xmm2, [rsi+32]
+
+ GROW_VERT xmm3, xmm0, xmm1, xmm2
+ por xmm0,xmm1
+ movdqa [rdi], xmm0
+ movdqa [rdi+16],xmm3
+
+ GROW_NEXTLINE xmm0,[rsi+48],[rdi+32]
+ GROW_NEXTLINE xmm1,[rsi+64],[rdi+48]
+ GROW_NEXTLINE xmm2,[rsi+80],[rdi+64]
+ GROW_NEXTLINE xmm0,[rsi+96],[rdi+80]
+ GROW_NEXTLINE xmm1,[rsi+112],[rdi+96]
+ GROW_NEXTLINE xmm2,[rsi+128],[rdi+112]
+ GROW_NEXTLINE xmm0,[rsi+144],[rdi+128]
+ GROW_NEXTLINE xmm1,[rsi+160],[rdi+144]
+ GROW_NEXTLINE xmm2,[rsi+176],[rdi+160]
+ GROW_NEXTLINE xmm0,[rsi+192],[rdi+176]
+ GROW_NEXTLINE xmm1,[rsi+208],[rdi+192]
+ GROW_NEXTLINE xmm2,[rsi+224],[rdi+208]
+ GROW_NEXTLINE xmm0,[rsi+240],[rdi+224]
+
+ por xmm0,xmm2
+ movdqa [rdi+240], xmm0
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+
+;unsigned int vp8_sad16x16_masked_wmt(
+; unsigned char *src_ptr,
+; int src_stride,
+; unsigned char *ref_ptr,
+; int ref_stride,
+; unsigned char *mask)
+global sym(vp8_sad16x16_masked_wmt)
+sym(vp8_sad16x16_masked_wmt):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 5
+ push rsi
+ push rdi
+ ; end prolog
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(2) ;ref_ptr
+
+ mov rbx, arg(4) ;mask
+ movsxd rax, dword ptr arg(1) ;src_stride
+ movsxd rdx, dword ptr arg(3) ;ref_stride
+
+ mov rcx, 16
+
+ pxor xmm3, xmm3
+
+NextSadRow:
+ movdqu xmm0, [rsi]
+ movdqu xmm1, [rdi]
+ movdqu xmm2, [rbx]
+ pand xmm0, xmm2
+ pand xmm1, xmm2
+
+ psadbw xmm0, xmm1
+ paddw xmm3, xmm0
+
+ add rsi, rax
+ add rdi, rdx
+ add rbx, 16
+
+ dec rcx
+ jnz NextSadRow
+
+ movdqa xmm4 , xmm3
+ psrldq xmm4, 8
+ paddw xmm3, xmm4
+ movq rax, xmm3
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+;unsigned int vp8_sad16x16_unmasked_wmt(
+; unsigned char *src_ptr,
+; int src_stride,
+; unsigned char *ref_ptr,
+; int ref_stride,
+; unsigned char *mask)
+global sym(vp8_sad16x16_unmasked_wmt)
+sym(vp8_sad16x16_unmasked_wmt):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 5
+ push rsi
+ push rdi
+ ; end prolog
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(2) ;ref_ptr
+
+ mov rbx, arg(4) ;mask
+ movsxd rax, dword ptr arg(1) ;src_stride
+ movsxd rdx, dword ptr arg(3) ;ref_stride
+
+ mov rcx, 16
+
+ pxor xmm3, xmm3
+
+next_vp8_sad16x16_unmasked_wmt:
+ movdqu xmm0, [rsi]
+ movdqu xmm1, [rdi]
+ movdqu xmm2, [rbx]
+ por xmm0, xmm2
+ por xmm1, xmm2
+
+ psadbw xmm0, xmm1
+ paddw xmm3, xmm0
+
+ add rsi, rax
+ add rdi, rdx
+ add rbx, 16
+
+ dec rcx
+ jnz next_vp8_sad16x16_unmasked_wmt
+
+ movdqa xmm4 , xmm3
+ psrldq xmm4, 8
+ paddw xmm3, xmm4
+ movq rax, xmm3
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+;unsigned int vp8_masked_predictor_wmt(
+; unsigned char *masked,
+; unsigned char *unmasked,
+; int src_stride,
+; unsigned char *dst_ptr,
+; int dst_stride,
+; unsigned char *mask)
+global sym(vp8_masked_predictor_wmt)
+sym(vp8_masked_predictor_wmt):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(1) ;ref_ptr
+
+ mov rbx, arg(5) ;mask
+ movsxd rax, dword ptr arg(2) ;src_stride
+ mov r11, arg(3) ; destination
+ movsxd rdx, dword ptr arg(4) ;dst_stride
+
+ mov rcx, 16
+
+ pxor xmm3, xmm3
+
+next_vp8_masked_predictor_wmt:
+ movdqu xmm0, [rsi]
+ movdqu xmm1, [rdi]
+ movdqu xmm2, [rbx]
+
+ pand xmm0, xmm2
+ pandn xmm2, xmm1
+ por xmm0, xmm2
+ movdqu [r11], xmm0
+
+ add r11, rdx
+ add rsi, rax
+ add rdi, rdx
+ add rbx, 16
+
+ dec rcx
+ jnz next_vp8_masked_predictor_wmt
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+;unsigned int vp8_masked_predictor_uv_wmt(
+; unsigned char *masked,
+; unsigned char *unmasked,
+; int src_stride,
+; unsigned char *dst_ptr,
+; int dst_stride,
+; unsigned char *mask)
+global sym(vp8_masked_predictor_uv_wmt)
+sym(vp8_masked_predictor_uv_wmt):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(1) ;ref_ptr
+
+ mov rbx, arg(5) ;mask
+ movsxd rax, dword ptr arg(2) ;src_stride
+ mov r11, arg(3) ; destination
+ movsxd rdx, dword ptr arg(4) ;dst_stride
+
+ mov rcx, 8
+
+ pxor xmm3, xmm3
+
+next_vp8_masked_predictor_uv_wmt:
+ movq xmm0, [rsi]
+ movq xmm1, [rdi]
+ movq xmm2, [rbx]
+
+ pand xmm0, xmm2
+ pandn xmm2, xmm1
+ por xmm0, xmm2
+ movq [r11], xmm0
+
+ add r11, rdx
+ add rsi, rax
+ add rdi, rax
+ add rbx, 8
+
+ dec rcx
+ jnz next_vp8_masked_predictor_uv_wmt
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+;unsigned int vp8_uv_from_y_mask(
+; unsigned char *ymask,
+; unsigned char *uvmask)
+global sym(vp8_uv_from_y_mask)
+sym(vp8_uv_from_y_mask):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
+ push rsi
+ push rdi
+ ; end prolog
+ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(1) ;dst_ptr
+
+
+ mov rcx, 8
+
+ pxor xmm3, xmm3
+
+next_p8_uv_from_y_mask:
+ movdqu xmm0, [rsi]
+ pshufb xmm0, [shuf1b] ;[GLOBAL(shuf1b)]
+ movq [rdi],xmm0
+ add rdi, 8
+ add rsi,32
+
+ dec rcx
+ jnz next_p8_uv_from_y_mask
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+SECTION_RODATA
+align 16
+shuf1b:
+ db 0, 2, 4, 6, 8, 10, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0
+
diff --git a/vp8/common/x86/recon_wrapper_sse2.c b/vp8/common/x86/recon_wrapper_sse2.c
index fcc75a901..cb7b69c08 100644
--- a/vp8/common/x86/recon_wrapper_sse2.c
+++ b/vp8/common/x86/recon_wrapper_sse2.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/recon.h"
#include "recon_x86.h"
#include "vpx_mem/vpx_mem.h"
diff --git a/vp8/common/x86/subpixel_ssse3.asm b/vp8/common/x86/subpixel_ssse3.asm
index 6bca82bfb..39f4f7b88 100644
--- a/vp8/common/x86/subpixel_ssse3.asm
+++ b/vp8/common/x86/subpixel_ssse3.asm
@@ -1495,13 +1495,33 @@ k2_k4:
times 8 db 36, -11
times 8 db 12, -6
align 16
+%if CONFIG_SIXTEENTH_SUBPEL_UV
vp8_bilinear_filters_ssse3:
times 8 db 128, 0
+ times 8 db 120, 8
times 8 db 112, 16
+ times 8 db 104, 24
times 8 db 96, 32
+ times 8 db 88, 40
times 8 db 80, 48
+ times 8 db 72, 56
times 8 db 64, 64
+ times 8 db 56, 72
times 8 db 48, 80
+ times 8 db 40, 88
times 8 db 32, 96
+ times 8 db 24, 104
times 8 db 16, 112
+ times 8 db 8, 120
+%else
+vp8_bilinear_filters_ssse3:
+ times 8 db 128, 0
+ times 8 db 112, 16
+ times 8 db 96, 32
+ times 8 db 80, 48
+ times 8 db 64, 64
+ times 8 db 48, 80
+ times 8 db 32, 96
+ times 8 db 16, 112
+%endif
diff --git a/vp8/common/x86/vp8_asm_stubs.c b/vp8/common/x86/vp8_asm_stubs.c
index bce7bc38e..458b3f638 100644
--- a/vp8/common/x86/vp8_asm_stubs.c
+++ b/vp8/common/x86/vp8_asm_stubs.c
@@ -9,12 +9,19 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/mem.h"
#include "vp8/common/subpixel.h"
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+extern const short vp8_six_tap_mmx[16][6*8];
+extern const short vp8_bilinear_filters_mmx[16][2*8];
+#else
extern const short vp8_six_tap_mmx[8][6*8];
extern const short vp8_bilinear_filters_mmx[8][2*8];
+#endif
+
+//#define ANNOUNCE_FUNCTION
extern void vp8_filter_block1d_h6_mmx
(
@@ -128,6 +135,9 @@ void vp8_sixtap_predict4x4_mmx
int dst_pitch
)
{
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict4x4_mmx\n");
+#endif
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 16*16); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
HFilter = vp8_six_tap_mmx[xoffset];
@@ -149,6 +159,9 @@ void vp8_sixtap_predict16x16_mmx
)
{
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict16x16_mmx\n");
+#endif
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 24*24); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
@@ -181,6 +194,9 @@ void vp8_sixtap_predict8x8_mmx
)
{
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x8_mmx\n");
+#endif
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
@@ -206,7 +222,9 @@ void vp8_sixtap_predict8x4_mmx
int dst_pitch
)
{
-
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x4_mmx\n");
+#endif
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
@@ -256,6 +274,9 @@ void vp8_sixtap_predict16x16_sse2
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 24*24); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict16x16_sse2\n");
+#endif
if (xoffset)
{
@@ -295,6 +316,9 @@ void vp8_sixtap_predict8x8_sse2
{
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x8_sse2\n");
+#endif
if (xoffset)
{
@@ -333,6 +357,9 @@ void vp8_sixtap_predict8x4_sse2
{
DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256); /* Temp data bufffer used in filtering */
const short *HFilter, *VFilter;
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x4_sse2\n");
+#endif
if (xoffset)
{
@@ -434,6 +461,9 @@ void vp8_sixtap_predict16x16_ssse3
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 24*24);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict16x16_ssse3\n");
+#endif
if (xoffset)
{
@@ -466,6 +496,9 @@ void vp8_sixtap_predict8x8_ssse3
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 256);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x8_ssse3\n");
+#endif
if (xoffset)
{
@@ -498,6 +531,9 @@ void vp8_sixtap_predict8x4_ssse3
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 256);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x4_ssse3\n");
+#endif
if (xoffset)
{
@@ -530,6 +566,9 @@ void vp8_sixtap_predict4x4_ssse3
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 4*9);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict4x4_ssse3\n");
+#endif
if (xoffset)
{
diff --git a/vp8/common/x86/x86_systemdependent.c b/vp8/common/x86/x86_systemdependent.c
index 33a984b79..53009502c 100644
--- a/vp8/common/x86/x86_systemdependent.c
+++ b/vp8/common/x86/x86_systemdependent.c
@@ -43,17 +43,17 @@ void vp8_arch_x86_common_init(VP8_COMMON *ctx)
rtcd->idct.iwalsh16 = vp8_short_inv_walsh4x4_mmx;
rtcd->idct.iwalsh1 = vp8_short_inv_walsh4x4_1_mmx;
-
-
rtcd->recon.recon = vp8_recon_b_mmx;
rtcd->recon.copy8x8 = vp8_copy_mem8x8_mmx;
rtcd->recon.copy8x4 = vp8_copy_mem8x4_mmx;
rtcd->recon.copy16x16 = vp8_copy_mem16x16_mmx;
+#if CONFIG_ENHANCED_INTERP == 0 && CONFIG_HIGH_PRECISION_MV == 0 && CONFIG_SIXTEENTH_SUBPEL_UV == 0
rtcd->subpix.sixtap16x16 = vp8_sixtap_predict16x16_mmx;
rtcd->subpix.sixtap8x8 = vp8_sixtap_predict8x8_mmx;
rtcd->subpix.sixtap8x4 = vp8_sixtap_predict8x4_mmx;
rtcd->subpix.sixtap4x4 = vp8_sixtap_predict4x4_mmx;
+#endif
rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_mmx;
rtcd->subpix.bilinear8x8 = vp8_bilinear_predict8x8_mmx;
rtcd->subpix.bilinear8x4 = vp8_bilinear_predict8x4_mmx;
@@ -91,9 +91,11 @@ void vp8_arch_x86_common_init(VP8_COMMON *ctx)
rtcd->idct.iwalsh16 = vp8_short_inv_walsh4x4_sse2;
+#if CONFIG_ENHANCED_INTERP == 0 && CONFIG_HIGH_PRECISION_MV == 0 && CONFIG_SIXTEENTH_SUBPEL_UV == 0
rtcd->subpix.sixtap16x16 = vp8_sixtap_predict16x16_sse2;
rtcd->subpix.sixtap8x8 = vp8_sixtap_predict8x8_sse2;
rtcd->subpix.sixtap8x4 = vp8_sixtap_predict8x4_sse2;
+#endif
rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_sse2;
rtcd->subpix.bilinear8x8 = vp8_bilinear_predict8x8_sse2;
@@ -120,12 +122,14 @@ void vp8_arch_x86_common_init(VP8_COMMON *ctx)
if (flags & HAS_SSSE3)
{
+#if CONFIG_ENHANCED_INTERP == 0 && CONFIG_HIGH_PRECISION_MV == 0
rtcd->subpix.sixtap16x16 = vp8_sixtap_predict16x16_ssse3;
rtcd->subpix.sixtap8x8 = vp8_sixtap_predict8x8_ssse3;
rtcd->subpix.sixtap8x4 = vp8_sixtap_predict8x4_ssse3;
rtcd->subpix.sixtap4x4 = vp8_sixtap_predict4x4_ssse3;
rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_ssse3;
rtcd->subpix.bilinear8x8 = vp8_bilinear_predict8x8_ssse3;
+#endif
rtcd->recon.build_intra_predictors_mbuv =
vp8_build_intra_predictors_mbuv_ssse3;
diff --git a/vp8/decoder/arm/arm_dsystemdependent.c b/vp8/decoder/arm/arm_dsystemdependent.c
index 1b0091cdb..6ce471217 100644
--- a/vp8/decoder/arm/arm_dsystemdependent.c
+++ b/vp8/decoder/arm/arm_dsystemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/arm.h"
#include "vp8/common/blockd.h"
#include "vp8/common/pragmas.h"
diff --git a/vp8/decoder/arm/armv6/idct_blk_v6.c b/vp8/decoder/arm/armv6/idct_blk_v6.c
index 5c7592f35..57c344698 100644
--- a/vp8/decoder/arm/armv6/idct_blk_v6.c
+++ b/vp8/decoder/arm/armv6/idct_blk_v6.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "vp8/decoder/dequantize.h"
diff --git a/vp8/decoder/arm/dequantize_arm.c b/vp8/decoder/arm/dequantize_arm.c
index 2918e0512..98db6eeff 100644
--- a/vp8/decoder/arm/dequantize_arm.c
+++ b/vp8/decoder/arm/dequantize_arm.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/decoder/dequantize.h"
#include "vp8/common/idct.h"
#include "vpx_mem/vpx_mem.h"
diff --git a/vp8/decoder/arm/neon/idct_blk_neon.c b/vp8/decoder/arm/neon/idct_blk_neon.c
index f31654060..ee3500425 100644
--- a/vp8/decoder/arm/neon/idct_blk_neon.c
+++ b/vp8/decoder/arm/neon/idct_blk_neon.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "vp8/decoder/dequantize.h"
diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h
index 880c18522..853c10f14 100644
--- a/vp8/decoder/dboolhuff.h
+++ b/vp8/decoder/dboolhuff.h
@@ -13,7 +13,7 @@
#define DBOOLHUFF_H
#include <stddef.h>
#include <limits.h>
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/mem.h"
#include "vpx/vpx_integer.h"
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
index 54547d95c..8539ff25c 100644
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ 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
@@ -15,9 +15,18 @@
#include "onyxd_int.h"
#include "vp8/common/findnearmv.h"
+#include "vp8/common/seg_common.h"
+#include "vp8/common/pred_common.h"
+
#if CONFIG_DEBUG
#include <assert.h>
#endif
+
+//#define DEBUG_DEC_MV
+#ifdef DEBUG_DEC_MV
+int dec_mvcount = 0;
+#endif
+
static int vp8_read_bmode(vp8_reader *bc, const vp8_prob *p)
{
const int i = vp8_treed_read(bc, vp8_bmode_tree, p);
@@ -39,7 +48,12 @@ static int vp8_kfread_ymode(vp8_reader *bc, const vp8_prob *p)
return i;
}
+static int vp8_read_i8x8_mode(vp8_reader *bc, const vp8_prob *p)
+{
+ const int i = vp8_treed_read(bc, vp8_i8x8_mode_tree, p);
+ return i;
+}
static int vp8_read_uv_mode(vp8_reader *bc, const vp8_prob *p)
@@ -49,7 +63,9 @@ static int vp8_read_uv_mode(vp8_reader *bc, const vp8_prob *p)
return i;
}
-static void vp8_read_mb_features(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x)
+// This function reads the current macro block's segnent id from the bitstream
+// It should only be called if a segment map update is indicated.
+static void vp8_read_mb_segid(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x)
{
/* Is segmentation enabled */
if (x->segmentation_enabled && x->update_mb_segmentation_map)
@@ -61,49 +77,120 @@ static void vp8_read_mb_features(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x
mi->segment_id = (unsigned char)(vp8_read(r, x->mb_segment_tree_probs[1]));
}
}
-
-static void vp8_kfread_modes(VP8D_COMP *pbi, MODE_INFO *m, int mb_row, int mb_col)
+extern const int vp8_i8x8_block[4];
+static void vp8_kfread_modes(VP8D_COMP *pbi,
+ MODE_INFO *m,
+ int mb_row,
+ int mb_col)
{
vp8_reader *const bc = & pbi->bc;
const int mis = pbi->common.mode_info_stride;
+ int map_index = mb_row * pbi->common.mb_cols + mb_col;
+ MB_PREDICTION_MODE y_mode;
+ // Read the Macroblock segmentation map if it is being updated explicitly
+ // this frame (reset to 0 by default).
+ m->mbmi.segment_id = 0;
+ if (pbi->mb.update_mb_segmentation_map)
+ {
+ vp8_read_mb_segid(bc, &m->mbmi, &pbi->mb);
+ pbi->common.last_frame_seg_map[map_index] = m->mbmi.segment_id;
+ }
+
+ if ( pbi->common.mb_no_coeff_skip &&
+ ( !segfeature_active( &pbi->mb,
+ m->mbmi.segment_id, SEG_LVL_EOB ) ||
+ ( get_segdata( &pbi->mb,
+ m->mbmi.segment_id, SEG_LVL_EOB ) != 0 ) ) )
+ {
+ m->mbmi.mb_skip_coeff = vp8_read(bc, pbi->prob_skip_false);
+ }
+ else
+ {
+ if ( segfeature_active( &pbi->mb,
+ m->mbmi.segment_id, SEG_LVL_EOB ) &&
+ ( get_segdata( &pbi->mb,
+ m->mbmi.segment_id, SEG_LVL_EOB ) == 0 ) )
{
- MB_PREDICTION_MODE y_mode;
+ m->mbmi.mb_skip_coeff = 1;
+ }
+ else
+ m->mbmi.mb_skip_coeff = 0;
+ }
- /* Read the Macroblock segmentation map if it is being updated explicitly this frame (reset to 0 above by default)
- * By default on a key frame reset all MBs to segment 0
- */
- m->mbmi.segment_id = 0;
+#if CONFIG_QIMODE
+ y_mode = (MB_PREDICTION_MODE) vp8_kfread_ymode(bc,
+ pbi->common.kf_ymode_prob[pbi->common.kf_ymode_probs_index]);
+#else
+ y_mode = (MB_PREDICTION_MODE) vp8_kfread_ymode(
+ bc, pbi->common.kf_ymode_prob);
+#endif
+#if CONFIG_COMP_INTRA_PRED
+ m->mbmi.second_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
- if (pbi->mb.update_mb_segmentation_map)
- vp8_read_mb_features(bc, &m->mbmi, &pbi->mb);
+ m->mbmi.ref_frame = INTRA_FRAME;
- /* Read the macroblock coeff skip flag if this feature is in use, else default to 0 */
- if (pbi->common.mb_no_coeff_skip)
- m->mbmi.mb_skip_coeff = vp8_read(bc, pbi->prob_skip_false);
+ if ((m->mbmi.mode = y_mode) == B_PRED)
+ {
+ int i = 0;
+#if CONFIG_COMP_INTRA_PRED
+ int use_comp_pred = vp8_read(bc, 128);
+#endif
+ do
+ {
+ const B_PREDICTION_MODE A = above_block_mode(m, i, mis);
+ const B_PREDICTION_MODE L = left_block_mode(m, i);
+
+ m->bmi[i].as_mode.first =
+ (B_PREDICTION_MODE) vp8_read_bmode(
+ bc, pbi->common.kf_bmode_prob [A] [L]);
+#if CONFIG_COMP_INTRA_PRED
+ if (use_comp_pred)
+ {
+ m->bmi[i].as_mode.second =
+ (B_PREDICTION_MODE) vp8_read_bmode(
+ bc, pbi->common.kf_bmode_prob [A] [L]);
+ }
else
- m->mbmi.mb_skip_coeff = 0;
-
- y_mode = (MB_PREDICTION_MODE) vp8_kfread_ymode(bc, pbi->common.kf_ymode_prob);
-
- m->mbmi.ref_frame = INTRA_FRAME;
-
- if ((m->mbmi.mode = y_mode) == B_PRED)
{
- int i = 0;
-
- do
- {
- const B_PREDICTION_MODE A = above_block_mode(m, i, mis);
- const B_PREDICTION_MODE L = left_block_mode(m, i);
-
- m->bmi[i].as_mode = (B_PREDICTION_MODE) vp8_read_bmode(bc, pbi->common.kf_bmode_prob [A] [L]);
- }
- while (++i < 16);
+ m->bmi[i].as_mode.second = (B_PREDICTION_MODE) (B_DC_PRED - 1);
}
-
- m->mbmi.uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc, pbi->common.kf_uv_mode_prob);
+#endif
}
+ while (++i < 16);
+ }
+ if((m->mbmi.mode = y_mode) == I8X8_PRED)
+ {
+ int i;
+ int mode8x8;
+ for(i=0;i<4;i++)
+ {
+ int ib = vp8_i8x8_block[i];
+ mode8x8 = vp8_read_i8x8_mode(bc, pbi->common.i8x8_mode_prob);
+ m->bmi[ib+0].as_mode.first= mode8x8;
+ m->bmi[ib+1].as_mode.first= mode8x8;
+ m->bmi[ib+4].as_mode.first= mode8x8;
+ m->bmi[ib+5].as_mode.first= mode8x8;
+#if CONFIG_COMP_INTRA_PRED
+ m->bmi[ib+0].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+ m->bmi[ib+1].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+ m->bmi[ib+4].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+ m->bmi[ib+5].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
+ }
+ }
+ else
+#if CONFIG_UVINTRA
+ m->mbmi.uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc,
+ pbi->common.kf_uv_mode_prob[m->mbmi.mode]);
+#else
+ m->mbmi.uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc,
+ pbi->common.kf_uv_mode_prob);
+#endif
+#if CONFIG_COMP_INTRA_PRED
+ m->mbmi.second_uv_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
}
static int read_mvcomponent(vp8_reader *r, const MV_CONTEXT *mvc)
@@ -119,7 +206,7 @@ static int read_mvcomponent(vp8_reader *r, const MV_CONTEXT *mvc)
{
x += vp8_read(r, p [MVPbits + i]) << i;
}
- while (++i < 3);
+ while (++i < mvnum_short_bits);
i = mvlong_width - 1; /* Skip bit 3, which is sometimes implicit */
@@ -127,10 +214,10 @@ static int read_mvcomponent(vp8_reader *r, const MV_CONTEXT *mvc)
{
x += vp8_read(r, p [MVPbits + i]) << i;
}
- while (--i > 3);
+ while (--i > mvnum_short_bits);
- if (!(x & 0xFFF0) || vp8_read(r, p [MVPbits + 3]))
- x += 8;
+ if (!(x & ~((2<<mvnum_short_bits)-1)) || vp8_read(r, p [MVPbits + mvnum_short_bits]))
+ x += (mvnum_short);
}
else /* small */
x = vp8_treed_read(r, vp8_small_mvtree, p + MVPshort);
@@ -145,6 +232,12 @@ static void read_mv(vp8_reader *r, MV *mv, const MV_CONTEXT *mvc)
{
mv->row = (short)(read_mvcomponent(r, mvc) << 1);
mv->col = (short)(read_mvcomponent(r, ++mvc) << 1);
+#ifdef DEBUG_DEC_MV
+ int i;
+ printf("%d (np): %d %d\n", dec_mvcount++, mv->row, mv->col);
+ //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[-1])->prob[i]); printf("\n");
+ //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[0])->prob[i]); printf("\n");
+#endif
}
@@ -172,6 +265,206 @@ static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc)
while (++i < 2);
}
+#if CONFIG_HIGH_PRECISION_MV
+static int read_mvcomponent_hp(vp8_reader *r, const MV_CONTEXT_HP *mvc)
+{
+ const vp8_prob *const p = (const vp8_prob *) mvc;
+ int x = 0;
+
+ if (vp8_read(r, p [mvpis_short_hp])) /* Large */
+ {
+ int i = 0;
+
+ do
+ {
+ x += vp8_read(r, p [MVPbits_hp + i]) << i;
+ }
+ while (++i < mvnum_short_bits_hp);
+
+ i = mvlong_width_hp - 1; /* Skip bit 3, which is sometimes implicit */
+
+ do
+ {
+ x += vp8_read(r, p [MVPbits_hp + i]) << i;
+ }
+ while (--i > mvnum_short_bits_hp);
+
+ if (!(x & ~((2<<mvnum_short_bits_hp)-1)) || vp8_read(r, p [MVPbits_hp + mvnum_short_bits_hp]))
+ x += (mvnum_short_hp);
+ }
+ else /* small */
+ x = vp8_treed_read(r, vp8_small_mvtree_hp, p + MVPshort_hp);
+
+ if (x && vp8_read(r, p [MVPsign_hp]))
+ x = -x;
+
+ return x;
+}
+
+static void read_mv_hp(vp8_reader *r, MV *mv, const MV_CONTEXT_HP *mvc)
+{
+ mv->row = (short)(read_mvcomponent_hp(r, mvc));
+ mv->col = (short)(read_mvcomponent_hp(r, ++mvc));
+#ifdef DEBUG_DEC_MV
+ int i;
+ printf("%d (hp): %d %d\n", dec_mvcount++, mv->row, mv->col);
+ //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[-1])->prob[i]); printf("\n");
+ //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[0])->prob[i]); printf("\n");
+#endif
+}
+
+static void read_mvcontexts_hp(vp8_reader *bc, MV_CONTEXT_HP *mvc)
+{
+ int i = 0;
+
+ do
+ {
+ const vp8_prob *up = vp8_mv_update_probs_hp[i].prob;
+ vp8_prob *p = (vp8_prob *)(mvc + i);
+ vp8_prob *const pstop = p + MVPcount_hp;
+
+ do
+ {
+ if (vp8_read(bc, *up++))
+ {
+ const vp8_prob x = (vp8_prob)vp8_read_literal(bc, 7);
+
+ *p = x ? x << 1 : 1;
+ }
+ }
+ while (++p < pstop);
+ }
+ while (++i < 2);
+}
+#endif /* CONFIG_HIGH_PRECISION_MV */
+
+// Read the referncence frame
+static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
+ vp8_reader *const bc,
+ unsigned char segment_id )
+{
+ MV_REFERENCE_FRAME ref_frame;
+ int seg_ref_active;
+ int seg_ref_count = 0;
+
+ VP8_COMMON *const cm = & pbi->common;
+ MACROBLOCKD *const xd = &pbi->mb;
+
+ seg_ref_active = segfeature_active( xd,
+ segment_id,
+ SEG_LVL_REF_FRAME );
+
+ // If segment coding enabled does the segment allow for more than one
+ // possible reference frame
+ if ( seg_ref_active )
+ {
+ seg_ref_count = check_segref( xd, segment_id, INTRA_FRAME ) +
+ check_segref( xd, segment_id, LAST_FRAME ) +
+ check_segref( xd, segment_id, GOLDEN_FRAME ) +
+ check_segref( xd, segment_id, ALTREF_FRAME );
+ }
+
+ // Segment reference frame features not available or allows for
+ // multiple reference frame options
+ if ( !seg_ref_active || (seg_ref_count > 1) )
+ {
+ // Values used in prediction model coding
+ unsigned char prediction_flag;
+ vp8_prob pred_prob;
+ MV_REFERENCE_FRAME pred_ref;
+
+ // Get the context probability the prediction flag
+ pred_prob = get_pred_prob( cm, xd, PRED_REF );
+
+ // Read the prediction status flag
+ prediction_flag = (unsigned char)vp8_read( bc, pred_prob );
+
+ // Store the prediction flag.
+ set_pred_flag( xd, PRED_REF, prediction_flag );
+
+ // Get the predicted reference frame.
+ pred_ref = get_pred_ref( cm, xd );
+
+ // If correctly predicted then use the predicted value
+ if ( prediction_flag )
+ {
+ ref_frame = pred_ref;
+ }
+ // else decode the explicitly coded value
+ else
+ {
+ vp8_prob mod_refprobs[PREDICTION_PROBS];
+ vpx_memcpy( mod_refprobs,
+ cm->mod_refprobs[pred_ref], sizeof(mod_refprobs) );
+
+ // If segment coding enabled blank out options that cant occur by
+ // setting the branch probability to 0.
+ if ( seg_ref_active )
+ {
+ mod_refprobs[INTRA_FRAME] *=
+ check_segref( xd, segment_id, INTRA_FRAME );
+ mod_refprobs[LAST_FRAME] *=
+ check_segref( xd, segment_id, LAST_FRAME );
+ mod_refprobs[GOLDEN_FRAME] *=
+ ( check_segref( xd, segment_id, GOLDEN_FRAME ) *
+ check_segref( xd, segment_id, ALTREF_FRAME ) );
+ }
+
+ // Default to INTRA_FRAME (value 0)
+ ref_frame = INTRA_FRAME;
+
+ // Do we need to decode the Intra/Inter branch
+ if ( mod_refprobs[0] )
+ ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, mod_refprobs[0]);
+ else
+ ref_frame ++;
+
+ if (ref_frame)
+ {
+ // Do we need to decode the Last/Gf_Arf branch
+ if ( mod_refprobs[1] )
+ ref_frame += vp8_read(bc, mod_refprobs[1]);
+ else
+ ref_frame++;
+
+ if ( ref_frame > 1 )
+ {
+ // Do we need to decode the GF/Arf branch
+ if ( mod_refprobs[2] )
+ ref_frame += vp8_read(bc, mod_refprobs[2]);
+ else
+ {
+ if ( seg_ref_active )
+ {
+ if ( (pred_ref == GOLDEN_FRAME) ||
+ !check_segref( xd, segment_id, GOLDEN_FRAME) )
+ {
+ ref_frame = ALTREF_FRAME;
+ }
+ else
+ ref_frame = GOLDEN_FRAME;
+ }
+ else
+ ref_frame = (pred_ref == GOLDEN_FRAME)
+ ? ALTREF_FRAME : GOLDEN_FRAME;
+ }
+ }
+ }
+ }
+ }
+
+ // Segment reference frame features are enabled
+ else
+ {
+ // The reference frame for the mb is considered as correclty predicted
+ // if it is signaled at the segment level for the purposes of the
+ // common prediction model
+ set_pred_flag( xd, PRED_REF, 1 );
+ ref_frame = get_pred_ref( cm, xd );
+ }
+
+ return (MV_REFERENCE_FRAME)ref_frame;
+}
static MB_PREDICTION_MODE read_mv_ref(vp8_reader *bc, const vp8_prob *p)
{
@@ -208,27 +501,40 @@ static const unsigned char mbsplit_fill_offset[4][16] = {
-
static void mb_mode_mv_init(VP8D_COMP *pbi)
{
+ VP8_COMMON *const cm = & pbi->common;
vp8_reader *const bc = & pbi->bc;
MV_CONTEXT *const mvc = pbi->common.fc.mvc;
-
-#if CONFIG_ERROR_CONCEALMENT
- /* Default is that no macroblock is corrupt, therefore we initialize
- * mvs_corrupt_from_mb to something very big, which we can be sure is
- * outside the frame. */
- pbi->mvs_corrupt_from_mb = UINT_MAX;
+#if CONFIG_HIGH_PRECISION_MV
+ MV_CONTEXT_HP *const mvc_hp = pbi->common.fc.mvc_hp;
+ MACROBLOCKD *const xd = & pbi->mb;
#endif
+
pbi->prob_skip_false = 0;
if (pbi->common.mb_no_coeff_skip)
pbi->prob_skip_false = (vp8_prob)vp8_read_literal(bc, 8);
if(pbi->common.frame_type != KEY_FRAME)
{
- pbi->prob_intra = (vp8_prob)vp8_read_literal(bc, 8);
- pbi->prob_last = (vp8_prob)vp8_read_literal(bc, 8);
- pbi->prob_gf = (vp8_prob)vp8_read_literal(bc, 8);
+ // Decode the baseline probabilities for decoding reference frame
+ cm->prob_intra_coded = (vp8_prob)vp8_read_literal(bc, 8);
+ cm->prob_last_coded = (vp8_prob)vp8_read_literal(bc, 8);
+ cm->prob_gf_coded = (vp8_prob)vp8_read_literal(bc, 8);
+
+ // Computes a modified set of probabilities for use when reference
+ // frame prediction fails.
+ compute_mod_refprobs( cm );
+
+ pbi->common.comp_pred_mode = vp8_read(bc, 128);
+ if (cm->comp_pred_mode)
+ cm->comp_pred_mode += vp8_read(bc, 128);
+ if (cm->comp_pred_mode == HYBRID_PREDICTION)
+ {
+ int i;
+ for ( i = 0; i < COMP_PRED_CONTEXTS; i++ )
+ cm->prob_comppred[i] = (vp8_prob)vp8_read_literal(bc, 8);
+ }
if (vp8_read_bit(bc))
{
@@ -236,84 +542,191 @@ static void mb_mode_mv_init(VP8D_COMP *pbi)
do
{
- pbi->common.fc.ymode_prob[i] = (vp8_prob) vp8_read_literal(bc, 8);
+ cm->fc.ymode_prob[i] = (vp8_prob) vp8_read_literal(bc, 8);
}
- while (++i < 4);
+ while (++i < VP8_YMODES-1);
}
-
+#if CONFIG_UVINTRA
+ //vp8_read_bit(bc);
+#else
if (vp8_read_bit(bc))
{
int i = 0;
do
{
- pbi->common.fc.uv_mode_prob[i] = (vp8_prob) vp8_read_literal(bc, 8);
+ cm->fc.uv_mode_prob[i] = (vp8_prob) vp8_read_literal(bc, 8);
}
- while (++i < 3);
+ while (++i < VP8_UV_MODES-1);
}
-
+#endif /* CONFIG_UVINTRA */
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ read_mvcontexts_hp(bc, mvc_hp);
+ else
+#endif
read_mvcontexts(bc, mvc);
}
}
+// This function either reads the segment id for the current macroblock from
+// the bitstream or if the value is temporally predicted asserts the predicted
+// value
+static void read_mb_segment_id ( VP8D_COMP *pbi,
+ int mb_row, int mb_col )
+{
+ vp8_reader *const bc = & pbi->bc;
+ VP8_COMMON *const cm = & pbi->common;
+ MACROBLOCKD *const xd = & pbi->mb;
+ MODE_INFO *mi = xd->mode_info_context;
+ MB_MODE_INFO *mbmi = &mi->mbmi;
+ int index = mb_row * pbi->common.mb_cols + mb_col;
+
+ if (xd->segmentation_enabled)
+ {
+ if (xd->update_mb_segmentation_map)
+ {
+ // Is temporal coding of the segment id for this mb enabled.
+ if (cm->temporal_update)
+ {
+ // Get the context based probability for reading the
+ // prediction status flag
+ vp8_prob pred_prob =
+ get_pred_prob( cm, xd, PRED_SEG_ID );
+
+ // Read the prediction status flag
+ unsigned char seg_pred_flag =
+ (unsigned char)vp8_read(bc, pred_prob );
+
+ // Store the prediction flag.
+ set_pred_flag( xd, PRED_SEG_ID, seg_pred_flag );
+
+ // If the value is flagged as correctly predicted
+ // then use the predicted value
+ if ( seg_pred_flag )
+ {
+ mbmi->segment_id = get_pred_mb_segid( cm, index );
+ }
+ // Else .... decode it explicitly
+ else
+ {
+ vp8_read_mb_segid(bc, mbmi, xd );
+ cm->last_frame_seg_map[index] = mbmi->segment_id;
+ }
+
+ }
+ // Normal unpredicted coding mode
+ else
+ {
+ vp8_read_mb_segid(bc, mbmi, xd);
+ cm->last_frame_seg_map[index] = mbmi->segment_id;
+ }
+ }
+ }
+ else
+ {
+ // The encoder explicitly sets the segment_id to 0
+ // when segmentation is disabled
+ mbmi->segment_id = 0;
+ }
+}
static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
- int mb_row, int mb_col)
+ MODE_INFO *prev_mi,
+ int mb_row, int mb_col)
{
+ VP8_COMMON *const cm = & pbi->common;
vp8_reader *const bc = & pbi->bc;
MV_CONTEXT *const mvc = pbi->common.fc.mvc;
+#if CONFIG_HIGH_PRECISION_MV
+ MV_CONTEXT_HP *const mvc_hp = pbi->common.fc.mvc_hp;
+#endif
const int mis = pbi->common.mode_info_stride;
+ MACROBLOCKD *const xd = & pbi->mb;
+ int index = mb_row * pbi->common.mb_cols + mb_col;
int_mv *const mv = & mbmi->mv;
int mb_to_left_edge;
int mb_to_right_edge;
int mb_to_top_edge;
int mb_to_bottom_edge;
- mb_to_top_edge = pbi->mb.mb_to_top_edge;
- mb_to_bottom_edge = pbi->mb.mb_to_bottom_edge;
+ mb_to_top_edge = xd->mb_to_top_edge;
+ mb_to_bottom_edge = xd->mb_to_bottom_edge;
mb_to_top_edge -= LEFT_TOP_MARGIN;
mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
-
mbmi->need_to_clamp_mvs = 0;
+ mbmi->second_ref_frame = 0;
/* Distance of Mb to the various image edges.
* These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
*/
- pbi->mb.mb_to_left_edge =
+ xd->mb_to_left_edge =
mb_to_left_edge = -((mb_col * 16) << 3);
mb_to_left_edge -= LEFT_TOP_MARGIN;
- pbi->mb.mb_to_right_edge =
+ xd->mb_to_right_edge =
mb_to_right_edge = ((pbi->common.mb_cols - 1 - mb_col) * 16) << 3;
mb_to_right_edge += RIGHT_BOTTOM_MARGIN;
- /* If required read in new segmentation data for this MB */
- if (pbi->mb.update_mb_segmentation_map)
- vp8_read_mb_features(bc, mbmi, &pbi->mb);
+ // Make sure the MACROBLOCKD mode info pointer is pointed at the
+ // correct entry for the current macroblock.
+ xd->mode_info_context = mi;
- /* Read the macroblock coeff skip flag if this feature is in use, else default to 0 */
- if (pbi->common.mb_no_coeff_skip)
+ // Read the macroblock segment id.
+ read_mb_segment_id ( pbi, mb_row, mb_col );
+
+ if ( pbi->common.mb_no_coeff_skip &&
+ ( !segfeature_active( xd,
+ mbmi->segment_id, SEG_LVL_EOB ) ||
+ (get_segdata( xd, mbmi->segment_id, SEG_LVL_EOB ) != 0) ) )
+ {
+ // Read the macroblock coeff skip flag if this feature is in use,
+ // else default to 0
mbmi->mb_skip_coeff = vp8_read(bc, pbi->prob_skip_false);
+ }
else
- mbmi->mb_skip_coeff = 0;
+ {
+ if ( segfeature_active( xd,
+ mbmi->segment_id, SEG_LVL_EOB ) &&
+ (get_segdata( xd, mbmi->segment_id, SEG_LVL_EOB ) == 0) )
+ {
+ mbmi->mb_skip_coeff = 1;
+ }
+ else
+ mbmi->mb_skip_coeff = 0;
+ }
+
+ // Read the reference frame
+ mbmi->ref_frame = read_ref_frame( pbi, bc, mbmi->segment_id );
- if ((mbmi->ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra))) /* inter MB */
+ // If reference frame is an Inter frame
+ if (mbmi->ref_frame)
{
int rct[4];
- vp8_prob mv_ref_p [VP8_MVREFS-1];
int_mv nearest, nearby, best_mv;
+ vp8_prob mv_ref_p [VP8_MVREFS-1];
+
+ vp8_find_near_mvs(xd, mi,
+ prev_mi,
+ &nearest, &nearby, &best_mv, rct,
+ mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
+ vp8_mv_ref_probs(&pbi->common, mv_ref_p, rct);
- if (vp8_read(bc, pbi->prob_last))
+ // Is the segment level mode feature enabled for this segment
+ if ( segfeature_active( xd, mbmi->segment_id, SEG_LVL_MODE ) )
{
- mbmi->ref_frame = (MV_REFERENCE_FRAME)((int)mbmi->ref_frame + (int)(1 + vp8_read(bc, pbi->prob_gf)));
+ mbmi->mode =
+ get_segdata( xd, mbmi->segment_id, SEG_LVL_MODE );
}
+ else
+ {
+ mbmi->mode = read_mv_ref(bc, mv_ref_p);
- vp8_find_near_mvs(&pbi->mb, mi, &nearest, &nearby, &best_mv, rct, mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
-
- vp8_mv_ref_probs(mv_ref_p, rct);
+ vp8_accum_mv_refs(&pbi->common, mbmi->mode, rct);
+ }
mbmi->uv_mode = DC_PRED;
- switch (mbmi->mode = read_mv_ref(bc, mv_ref_p))
+ switch (mbmi->mode)
{
case SPLITMV:
{
@@ -322,6 +735,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
const int num_p = vp8_mbsplit_count [s];
int j = 0;
+ mbmi->need_to_clamp_mvs = 0;
do /* for each subset j */
{
int_mv leftmv, abovemv;
@@ -337,6 +751,11 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
switch (sub_mv_ref(bc, vp8_sub_mv_ref_prob2 [mv_contz])) /*pc->fc.sub_mv_ref_prob))*/
{
case NEW4X4:
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ read_mv_hp(bc, &blockmv.as_mv, (const MV_CONTEXT_HP *) mvc_hp);
+ else
+#endif
read_mv(bc, &blockmv.as_mv, (const MV_CONTEXT *) mvc);
blockmv.as_mv.row += best_mv.as_mv.row;
blockmv.as_mv.col += best_mv.as_mv.col;
@@ -366,7 +785,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
break;
}
- mbmi->need_to_clamp_mvs = vp8_check_mv_bounds(&blockmv,
+ mbmi->need_to_clamp_mvs |= vp8_check_mv_bounds(&blockmv,
mb_to_left_edge,
mb_to_right_edge,
mb_to_top_edge,
@@ -414,6 +833,11 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
goto propagate_mv;
case NEWMV:
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ read_mv_hp(bc, &mv->as_mv, (const MV_CONTEXT_HP *) mvc_hp);
+ else
+#endif
read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc);
mv->as_mv.row += best_mv.as_mv.row;
mv->as_mv.col += best_mv.as_mv.col;
@@ -430,27 +854,57 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
mb_to_bottom_edge);
propagate_mv: /* same MV throughout */
-#if CONFIG_ERROR_CONCEALMENT
- if(pbi->ec_enabled)
+
+ if ( cm->comp_pred_mode == COMP_PREDICTION_ONLY ||
+ (cm->comp_pred_mode == HYBRID_PREDICTION &&
+ vp8_read(bc, get_pred_prob( cm, xd, PRED_COMP ))) )
{
- mi->bmi[ 0].mv.as_int =
- mi->bmi[ 1].mv.as_int =
- mi->bmi[ 2].mv.as_int =
- mi->bmi[ 3].mv.as_int =
- mi->bmi[ 4].mv.as_int =
- mi->bmi[ 5].mv.as_int =
- mi->bmi[ 6].mv.as_int =
- mi->bmi[ 7].mv.as_int =
- mi->bmi[ 8].mv.as_int =
- mi->bmi[ 9].mv.as_int =
- mi->bmi[10].mv.as_int =
- mi->bmi[11].mv.as_int =
- mi->bmi[12].mv.as_int =
- mi->bmi[13].mv.as_int =
- mi->bmi[14].mv.as_int =
- mi->bmi[15].mv.as_int = mv->as_int;
+ mbmi->second_ref_frame = mbmi->ref_frame + 1;
+ if (mbmi->second_ref_frame == 4)
+ mbmi->second_ref_frame = 1;
}
+ if (mbmi->second_ref_frame)
+ {
+ vp8_find_near_mvs(xd, mi,
+ prev_mi,
+ &nearest, &nearby, &best_mv, rct,
+ (int)mbmi->second_ref_frame,
+ pbi->common.ref_frame_sign_bias);
+ switch (mbmi->mode) {
+ case ZEROMV:
+ mbmi->second_mv.as_int = 0;
+ break;
+ case NEARMV:
+ mbmi->second_mv.as_int = nearby.as_int;
+ vp8_clamp_mv(&mbmi->second_mv, mb_to_left_edge, mb_to_right_edge,
+ mb_to_top_edge, mb_to_bottom_edge);
+ break;
+ case NEARESTMV:
+ mbmi->second_mv.as_int = nearest.as_int;
+ vp8_clamp_mv(&mbmi->second_mv, mb_to_left_edge, mb_to_right_edge,
+ mb_to_top_edge, mb_to_bottom_edge);
+ break;
+ case NEWMV:
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ read_mv_hp(bc, &mbmi->second_mv.as_mv,
+ (const MV_CONTEXT_HP *) mvc_hp);
+ else
#endif
+ read_mv(bc, &mbmi->second_mv.as_mv, (const MV_CONTEXT *) mvc);
+ mbmi->second_mv.as_mv.row += best_mv.as_mv.row;
+ mbmi->second_mv.as_mv.col += best_mv.as_mv.col;
+ mbmi->need_to_clamp_mvs |= vp8_check_mv_bounds(&mbmi->second_mv,
+ mb_to_left_edge,
+ mb_to_right_edge,
+ mb_to_top_edge,
+ mb_to_bottom_edge);
+ break;
+ default:
+ break;
+ }
+ }
+
break;
default:;
#if CONFIG_DEBUG
@@ -463,18 +917,73 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
/* required for left and above block mv */
mbmi->mv.as_int = 0;
- /* MB is intra coded */
- if ((mbmi->mode = (MB_PREDICTION_MODE) vp8_read_ymode(bc, pbi->common.fc.ymode_prob)) == B_PRED)
+ if ( segfeature_active( xd, mbmi->segment_id, SEG_LVL_MODE ) )
+ mbmi->mode = (MB_PREDICTION_MODE)
+ get_segdata( xd, mbmi->segment_id, SEG_LVL_MODE );
+ else
+ {
+ mbmi->mode = (MB_PREDICTION_MODE)
+ vp8_read_ymode(bc, pbi->common.fc.ymode_prob);
+ }
+#if CONFIG_COMP_INTRA_PRED
+ mbmi->second_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
+
+ // If MB mode is BPRED read the block modes
+ if (mbmi->mode == B_PRED)
{
int j = 0;
+#if CONFIG_COMP_INTRA_PRED
+ int use_comp_pred = vp8_read(bc, 128);
+#endif
do
{
- mi->bmi[j].as_mode = (B_PREDICTION_MODE)vp8_read_bmode(bc, pbi->common.fc.bmode_prob);
+ mi->bmi[j].as_mode.first = (B_PREDICTION_MODE)vp8_read_bmode(bc, pbi->common.fc.bmode_prob);
+#if CONFIG_COMP_INTRA_PRED
+ if (use_comp_pred)
+ {
+ mi->bmi[j].as_mode.second = (B_PREDICTION_MODE)vp8_read_bmode(bc, pbi->common.fc.bmode_prob);
+ }
+ else
+ {
+ mi->bmi[j].as_mode.second = (B_PREDICTION_MODE) (B_DC_PRED - 1);
+ }
+#endif
}
while (++j < 16);
}
- mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc, pbi->common.fc.uv_mode_prob);
+ if(mbmi->mode == I8X8_PRED)
+ {
+ int i;
+ int mode8x8;
+ for(i=0;i<4;i++)
+ {
+ int ib = vp8_i8x8_block[i];
+ mode8x8 = vp8_read_i8x8_mode(bc, pbi->common.i8x8_mode_prob);
+ mi->bmi[ib+0].as_mode.first= mode8x8;
+ mi->bmi[ib+1].as_mode.first= mode8x8;
+ mi->bmi[ib+4].as_mode.first= mode8x8;
+ mi->bmi[ib+5].as_mode.first= mode8x8;
+#if CONFIG_COMP_INTRA_PRED
+ mi->bmi[ib+0].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+ mi->bmi[ib+1].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+ mi->bmi[ib+4].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+ mi->bmi[ib+5].as_mode.second= (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
+ }
+ }
+ else
+#if CONFIG_UVINTRA
+ mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc,
+ pbi->common.fc.uv_mode_prob[mbmi->mode]);
+#else
+ mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc,
+ pbi->common.fc.uv_mode_prob);
+#endif /*CONFIG_UVINTRA*/
+#if CONFIG_COMP_INTRA_PRED
+ mbmi->second_uv_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
}
}
@@ -482,10 +991,26 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
void vp8_decode_mode_mvs(VP8D_COMP *pbi)
{
MODE_INFO *mi = pbi->common.mi;
+
+ MODE_INFO *prev_mi = pbi->common.prev_mi;
+
int mb_row = -1;
+#if 0
+ FILE *statsfile;
+ statsfile = fopen("decsegmap.stt", "a");
+ fprintf(statsfile, "\n" );
+#endif
+
mb_mode_mv_init(pbi);
+#if CONFIG_QIMODE
+ if(pbi->common.frame_type==KEY_FRAME && !pbi->common.kf_ymode_probs_update)
+ {
+ pbi->common.kf_ymode_probs_index = vp8_read_literal(&pbi->bc, 3);
+ }
+#endif
+
while (++mb_row < pbi->common.mb_rows)
{
int mb_col = -1;
@@ -500,34 +1025,51 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
mb_to_bottom_edge = ((pbi->common.mb_rows - 1 - mb_row) * 16) << 3;
mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
+#if 0
+ fprintf(statsfile, "\n" );
+#endif
+
while (++mb_col < pbi->common.mb_cols)
{
-#if CONFIG_ERROR_CONCEALMENT
- int mb_num = mb_row * pbi->common.mb_cols + mb_col;
-#endif
/*read_mb_modes_mv(pbi, xd->mode_info_context, &xd->mode_info_context->mbmi, mb_row, mb_col);*/
if(pbi->common.frame_type == KEY_FRAME)
vp8_kfread_modes(pbi, mi, mb_row, mb_col);
else
- read_mb_modes_mv(pbi, mi, &mi->mbmi, mb_row, mb_col);
+ read_mb_modes_mv(pbi, mi, &mi->mbmi,
+ prev_mi,
+ mb_row, mb_col);
+
+ //printf("%3d", mi->mbmi.mode);
+
+ /*
+ if(pbi->common.current_video_frame==7)
+ {
+ FILE *fmode=fopen("kfmode.txt", "a");
+ fprintf(fmode, "%3d:%3d:%d\n",mb_row, mb_col, mi->mbmi.mode);
+ fclose(fmode);
-#if CONFIG_ERROR_CONCEALMENT
- /* look for corruption. set mvs_corrupt_from_mb to the current
- * mb_num if the frame is corrupt from this macroblock. */
- if (vp8dx_bool_error(&pbi->bc) && mb_num < pbi->mvs_corrupt_from_mb)
+ }*/
+ /*
+ if(mi->mbmi.mode==I8X8_PRED)
{
- pbi->mvs_corrupt_from_mb = mb_num;
- /* no need to continue since the partition is corrupt from
- * here on.
- */
- return;
+ printf("F%3d:%d:%d\n", pbi->common.current_video_frame, mb_row, mb_col);
}
+ */
+#if 0
+ fprintf(statsfile, "%2d%2d%2d ",
+ mi->mbmi.segment_id, mi->mbmi.ref_frame, mi->mbmi.mode );
#endif
-
+ prev_mi++;
mi++; /* next macroblock */
}
-
+ // printf("\n");
+ prev_mi++;
mi++; /* skip left predictor each row */
}
-}
+#if 0
+ fclose(statsfile);
+#endif
+
+
+}
diff --git a/vp8/decoder/decoderthreading.h b/vp8/decoder/decoderthreading.h
deleted file mode 100644
index 60c39d1e1..000000000
--- a/vp8/decoder/decoderthreading.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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 _DECODER_THREADING_H
-#define _DECODER_THREADING_H
-
-#if CONFIG_MULTITHREAD
-extern void vp8mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd);
-extern void vp8_decoder_remove_threads(VP8D_COMP *pbi);
-extern void vp8_decoder_create_threads(VP8D_COMP *pbi);
-extern void vp8mt_alloc_temp_buffers(VP8D_COMP *pbi, int width, int prev_mb_rows);
-extern void vp8mt_de_alloc_temp_buffers(VP8D_COMP *pbi, int mb_rows);
-#endif
-
-#endif
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
index 6bbc71f79..29b9e9b85 100644
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -27,19 +27,22 @@
#include "decodemv.h"
#include "vp8/common/extend.h"
-#if CONFIG_ERROR_CONCEALMENT
-#include "error_concealment.h"
-#endif
+#include "vp8/common/modecont.h"
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/idct.h"
#include "dequantize.h"
-#include "vp8/common/threading.h"
-#include "decoderthreading.h"
#include "dboolhuff.h"
+#include "vp8/common/seg_common.h"
+
#include <assert.h>
#include <stdio.h>
+
+#ifdef DEC_DEBUG
+int dec_debug = 0;
+#endif
+
void vp8cx_init_de_quantizer(VP8D_COMP *pbi)
{
int i;
@@ -68,20 +71,21 @@ void mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd)
{
int i;
int QIndex;
- MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
VP8_COMMON *const pc = & pbi->common;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
- /* Decide whether to use the default or alternate baseline Q value. */
- if (xd->segmentation_enabled)
+ // Set the Q baseline allowing for any segment level adjustment
+ if ( segfeature_active( xd, segment_id, SEG_LVL_ALT_Q ) )
{
/* Abs Value */
- if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
- QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+ if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA)
+ QIndex = get_segdata( xd, segment_id, SEG_LVL_ALT_Q );
/* Delta Value */
else
{
- QIndex = pc->base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+ QIndex = pc->base_qindex +
+ get_segdata( xd, segment_id, SEG_LVL_ALT_Q );
QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0; /* Clamp to valid range */
}
}
@@ -125,32 +129,85 @@ static void skip_recon_mb(VP8D_COMP *pbi, MACROBLOCKD *xd)
vp8_build_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
xd->dst.u_buffer, xd->dst.v_buffer,
xd->dst.y_stride, xd->dst.uv_stride);
+
+ if (xd->mode_info_context->mbmi.second_ref_frame)
+ {
+ vp8_build_2nd_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
+ xd->dst.u_buffer, xd->dst.v_buffer,
+ xd->dst.y_stride, xd->dst.uv_stride);
+ }
}
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int i, j;
+ printf("Generating predictors\n");
+ for (i=0;i<16;i++) {
+ for (j=0;j<16;j++) printf("%3d ", xd->dst.y_buffer[i*xd->dst.y_stride+j]);
+ printf("\n");
+ }
+ }
+#endif
+
}
+extern const int vp8_i8x8_block[4];
static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
unsigned int mb_idx)
{
int eobtotal = 0;
- int throw_residual = 0;
MB_PREDICTION_MODE mode;
int i;
+ int tx_type;
+ if( pbi->common.txfm_mode==ONLY_4X4 )
+ {
+ xd->mode_info_context->mbmi.txfm_size = TX_4X4;
+ }
+ else if( pbi->common.txfm_mode == ALLOW_8X8 )
+ {
+ if( xd->mode_info_context->mbmi.mode ==B_PRED
+ ||xd->mode_info_context->mbmi.mode ==I8X8_PRED
+ ||xd->mode_info_context->mbmi.mode ==SPLITMV)
+ xd->mode_info_context->mbmi.txfm_size = TX_4X4;
+ else
+ xd->mode_info_context->mbmi.txfm_size = TX_8X8;
+ }
+
+ tx_type = xd->mode_info_context->mbmi.txfm_size;
+
if (xd->mode_info_context->mbmi.mb_skip_coeff)
{
vp8_reset_mb_tokens_context(xd);
}
else if (!vp8dx_bool_error(xd->current_bc))
{
- eobtotal = vp8_decode_mb_tokens(pbi, xd);
+ for(i = 0; i < 25; i++)
+ {
+ xd->block[i].eob = 0;
+ xd->eobs[i] = 0;
+ }
+ if ( tx_type == TX_8X8 )
+ eobtotal = vp8_decode_mb_tokens_8x8(pbi, xd);
+ else
+ eobtotal = vp8_decode_mb_tokens(pbi, xd);
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ printf("\nTokens (%d)\n", eobtotal);
+ for (i =0; i<400; i++) {
+ printf("%3d ", xd->qcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("\n");
+ }
+#endif
}
-
-
mode = xd->mode_info_context->mbmi.mode;
- if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV &&
- !vp8dx_bool_error(xd->current_bc))
+ if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV
+ && mode != I8X8_PRED
+ &&!vp8dx_bool_error(xd->current_bc)
+ )
{
/* Special case: Force the loopfilter to skip when eobtotal and
* mb_skip_coeff are zero.
@@ -161,57 +218,114 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
return;
}
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int i, j;
+ printf("Generating predictors\n");
+ for (i=0;i<16;i++) {
+ for (j=0;j<16;j++) printf("%3d ", xd->dst.y_buffer[i*xd->dst.y_stride+j]);
+ printf("\n");
+ }
+ }
+#endif
+
+
+
if (xd->segmentation_enabled)
mb_init_dequantizer(pbi, xd);
/* do prediction */
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
{
- RECON_INVOKE(&pbi->common.rtcd.recon, build_intra_predictors_mbuv)(xd);
-
- if (mode != B_PRED)
+ if(mode != I8X8_PRED)
{
- RECON_INVOKE(&pbi->common.rtcd.recon,
- build_intra_predictors_mby)(xd);
- } else {
- vp8_intra_prediction_down_copy(xd);
+ RECON_INVOKE(&pbi->common.rtcd.recon, build_intra_predictors_mbuv)(xd);
+ if (mode != B_PRED)
+ {
+ RECON_INVOKE(&pbi->common.rtcd.recon,
+ build_intra_predictors_mby)(xd);
+ }
+ else
+ {
+ vp8_intra_prediction_down_copy(xd);
+ }
}
}
else
{
vp8_build_inter_predictors_mb(xd);
}
- /* When we have independent partitions we can apply residual even
- * though other partitions within the frame are corrupt.
- */
- throw_residual = (!pbi->independent_partitions &&
- pbi->frame_corrupt_residual);
- throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
-#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_active &&
- (mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
+ /* dequantization and idct */
+ if (mode == I8X8_PRED)
{
- /* MB with corrupt residuals or corrupt mode/motion vectors.
- * Better to use the predictor as reconstruction.
- */
- pbi->frame_corrupt_residual = 1;
- vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
- vp8_conceal_corrupt_mb(xd);
- return;
- }
-#endif
+ for (i = 0; i < 4; i++)
+ {
+ int ib = vp8_i8x8_block[i];
+ const int iblock[4]={0,1,4,5};
+ int j;
+ int i8x8mode;
+ BLOCKD *b;
+
+ b = &xd->block[ib];
+ i8x8mode= b->bmi.as_mode.first;
+ RECON_INVOKE(RTCD_VTABLE(recon), intra8x8_predict)
+ (b, i8x8mode, b->predictor);
+
+ for(j = 0; j < 4; j++)
+ {
+ b = &xd->block[ib+iblock[j]];
+ if (xd->eobs[ib+iblock[j]] > 1)
+ {
+ DEQUANT_INVOKE(&pbi->dequant, idct_add)
+ (b->qcoeff, b->dequant, b->predictor,
+ *(b->base_dst) + b->dst, 16, b->dst_stride);
+ }
+ else
+ {
+ IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar_add)
+ (b->qcoeff[0] * b->dequant[0], b->predictor,
+ *(b->base_dst) + b->dst, 16, b->dst_stride);
+ ((int *)b->qcoeff)[0] = 0;
+ }
+ }
- /* dequantization and idct */
- if (mode == B_PRED)
+ b = &xd->block[16+i];
+ RECON_INVOKE(RTCD_VTABLE(recon), intra_uv4x4_predict)
+ (b, i8x8mode, b->predictor);
+ DEQUANT_INVOKE(&pbi->dequant, idct_add)
+ (b->qcoeff, b->dequant, b->predictor,
+ *(b->base_dst) + b->dst, 8, b->dst_stride);
+ b = &xd->block[20+i];
+ RECON_INVOKE(RTCD_VTABLE(recon), intra_uv4x4_predict)
+ (b, i8x8mode, b->predictor);
+ DEQUANT_INVOKE(&pbi->dequant, idct_add)
+ (b->qcoeff, b->dequant, b->predictor,
+ *(b->base_dst) + b->dst, 8, b->dst_stride);
+ }
+ }
+ else if (mode == B_PRED)
{
for (i = 0; i < 16; i++)
{
BLOCKD *b = &xd->block[i];
- int b_mode = xd->mode_info_context->bmi[i].as_mode;
+ int b_mode = xd->mode_info_context->bmi[i].as_mode.first;
+#if CONFIG_COMP_INTRA_PRED
+ int b_mode2 = xd->mode_info_context->bmi[i].as_mode.second;
+ if (b_mode2 == (B_PREDICTION_MODE) (B_DC_PRED - 1))
+ {
+#endif
RECON_INVOKE(RTCD_VTABLE(recon), intra4x4_predict)
(b, b_mode, b->predictor);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ RECON_INVOKE(RTCD_VTABLE(recon), comp_intra4x4_predict)
+ (b, b_mode, b_mode2, b->predictor);
+ }
+#endif
if (xd->eobs[i] > 1)
{
@@ -227,26 +341,35 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
((int *)b->qcoeff)[0] = 0;
}
}
-
}
else if (mode == SPLITMV)
{
DEQUANT_INVOKE (&pbi->dequant, idct_add_y_block)
- (xd->qcoeff, xd->block[0].dequant,
- xd->predictor, xd->dst.y_buffer,
- xd->dst.y_stride, xd->eobs);
+ (xd->qcoeff, xd->block[0].dequant,
+ xd->predictor, xd->dst.y_buffer,
+ xd->dst.y_stride, xd->eobs);
}
else
{
BLOCKD *b = &xd->block[24];
- DEQUANT_INVOKE(&pbi->dequant, block)(b);
- /* do 2nd order transform on the dc block */
- if (xd->eobs[24] > 1)
+ if( tx_type == TX_8X8 )
{
- IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh16)(&b->dqcoeff[0], b->diff);
- ((int *)b->qcoeff)[0] = 0;
+ DEQUANT_INVOKE(&pbi->dequant, block_2x2)(b);
+#ifdef DEC_DEBUG
+ if (dec_debug)
+ {
+ int j;
+ printf("DQcoeff Haar\n");
+ for (j=0;j<16;j++) {
+ printf("%d ", b->dqcoeff[j]);
+ }
+ printf("\n");
+ }
+#endif
+ IDCT_INVOKE(RTCD_VTABLE(idct), ihaar2)(&b->dqcoeff[0], b->diff, 8);
+ ((int *)b->qcoeff)[0] = 0;//2nd order block are set to 0 after inverse transform
((int *)b->qcoeff)[1] = 0;
((int *)b->qcoeff)[2] = 0;
((int *)b->qcoeff)[3] = 0;
@@ -254,23 +377,50 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
((int *)b->qcoeff)[5] = 0;
((int *)b->qcoeff)[6] = 0;
((int *)b->qcoeff)[7] = 0;
+ DEQUANT_INVOKE (&pbi->dequant, dc_idct_add_y_block_8x8)
+ (xd->qcoeff, xd->block[0].dequant,
+ xd->predictor, xd->dst.y_buffer,
+ xd->dst.y_stride, xd->eobs, xd->block[24].diff, xd);
}
else
{
- IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh1)(&b->dqcoeff[0], b->diff);
- ((int *)b->qcoeff)[0] = 0;
- }
+ DEQUANT_INVOKE(&pbi->dequant, block)(b);
+ if (xd->eobs[24] > 1)
+ {
+ IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh16)(&b->dqcoeff[0], b->diff);
+ ((int *)b->qcoeff)[0] = 0;
+ ((int *)b->qcoeff)[1] = 0;
+ ((int *)b->qcoeff)[2] = 0;
+ ((int *)b->qcoeff)[3] = 0;
+ ((int *)b->qcoeff)[4] = 0;
+ ((int *)b->qcoeff)[5] = 0;
+ ((int *)b->qcoeff)[6] = 0;
+ ((int *)b->qcoeff)[7] = 0;
+ }
+ else
+ {
+ IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh1)(&b->dqcoeff[0], b->diff);
+ ((int *)b->qcoeff)[0] = 0;
+ }
- DEQUANT_INVOKE (&pbi->dequant, dc_idct_add_y_block)
- (xd->qcoeff, xd->block[0].dequant,
- xd->predictor, xd->dst.y_buffer,
- xd->dst.y_stride, xd->eobs, xd->block[24].diff);
+ DEQUANT_INVOKE (&pbi->dequant, dc_idct_add_y_block)
+ (xd->qcoeff, xd->block[0].dequant,
+ xd->predictor, xd->dst.y_buffer,
+ xd->dst.y_stride, xd->eobs, xd->block[24].diff);
+ }
}
- DEQUANT_INVOKE (&pbi->dequant, idct_add_uv_block)
- (xd->qcoeff+16*16, xd->block[16].dequant,
- xd->predictor+16*16, xd->dst.u_buffer, xd->dst.v_buffer,
- xd->dst.uv_stride, xd->eobs+16);
+ if( tx_type == TX_8X8 )
+ DEQUANT_INVOKE (&pbi->dequant, idct_add_uv_block_8x8)//
+ (xd->qcoeff+16*16, xd->block[16].dequant,
+ xd->predictor+16*16, xd->dst.u_buffer, xd->dst.v_buffer,
+ xd->dst.uv_stride, xd->eobs+16, xd);//
+ else if(xd->mode_info_context->mbmi.mode!=I8X8_PRED)
+ DEQUANT_INVOKE (&pbi->dequant, idct_add_uv_block)
+ (xd->qcoeff+16*16, xd->block[16].dequant,
+ xd->predictor+16*16, xd->dst.u_buffer, xd->dst.v_buffer,
+ xd->dst.uv_stride, xd->eobs+16);
+
}
@@ -298,8 +448,6 @@ static int get_delta_q(vp8_reader *bc, int prev, int *q_update)
FILE *vpxlog = 0;
#endif
-
-
static void
decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
{
@@ -330,31 +478,7 @@ decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
-#if CONFIG_ERROR_CONCEALMENT
- {
- int corrupt_residual = (!pbi->independent_partitions &&
- pbi->frame_corrupt_residual) ||
- vp8dx_bool_error(xd->current_bc);
- if (pbi->ec_active &&
- xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
- corrupt_residual)
- {
- /* We have an intra block with corrupt coefficients, better to
- * conceal with an inter block. Interpolate MVs from neighboring
- * MBs.
- *
- * Note that for the first mb with corrupt residual in a frame,
- * we might not discover that before decoding the residual. That
- * happens after this check, and therefore no inter concealment
- * will be done.
- */
- vp8_interpolate_motion(xd,
- mb_row, mb_col,
- pc->mb_rows, pc->mb_cols,
- pc->mode_info_stride);
- }
- }
-#endif
+ update_blockd_bmi(xd);
xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
@@ -374,17 +498,36 @@ decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
+ if (xd->mode_info_context->mbmi.second_ref_frame)
+ {
+ int second_ref_fb_idx;
+
+ /* Select the appropriate reference frame for this MB */
+ if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME)
+ second_ref_fb_idx = pc->lst_fb_idx;
+ else if (xd->mode_info_context->mbmi.second_ref_frame == GOLDEN_FRAME)
+ second_ref_fb_idx = pc->gld_fb_idx;
+ else
+ second_ref_fb_idx = pc->alt_fb_idx;
+
+ xd->second_pre.y_buffer = pc->yv12_fb[second_ref_fb_idx].y_buffer + recon_yoffset;
+ xd->second_pre.u_buffer = pc->yv12_fb[second_ref_fb_idx].u_buffer + recon_uvoffset;
+ xd->second_pre.v_buffer = pc->yv12_fb[second_ref_fb_idx].v_buffer + recon_uvoffset;
+ }
+
if (xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME)
{
/* propagate errors from reference frames */
xd->corrupted |= pc->yv12_fb[ref_fb_idx].corrupted;
}
+#ifdef DEC_DEBUG
+ dec_debug = (pc->current_video_frame==1 && mb_row==4 && mb_col==0);
+#endif
decode_macroblock(pbi, xd, mb_row * pc->mb_cols + mb_col);
/* check if the boolean decoder has suffered an error */
xd->corrupted |= vp8dx_bool_error(xd->current_bc);
-
recon_yoffset += 16;
recon_uvoffset += 8;
@@ -403,7 +546,6 @@ decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
++xd->mode_info_context; /* skip prediction column */
}
-
static unsigned int read_partition_size(const unsigned char *cx_size)
{
const unsigned int size =
@@ -411,49 +553,6 @@ static unsigned int read_partition_size(const unsigned char *cx_size)
return size;
}
-static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
-{
- vp8_reader *bool_decoder = &pbi->bc2;
- int part_idx = 1;
- int num_token_partitions;
-
- TOKEN_PARTITION multi_token_partition =
- (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
- if (!vp8dx_bool_error(&pbi->bc))
- pbi->common.multi_token_partition = multi_token_partition;
- num_token_partitions = 1 << pbi->common.multi_token_partition;
- if (num_token_partitions + 1 > pbi->num_partitions)
- vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
- "Partitions missing");
- assert(vp8dx_bool_error(&pbi->bc) ||
- multi_token_partition == pbi->common.multi_token_partition);
- if (pbi->num_partitions > 2)
- {
- CHECK_MEM_ERROR(pbi->mbc, vpx_malloc((pbi->num_partitions - 1) *
- sizeof(vp8_reader)));
- bool_decoder = pbi->mbc;
- }
-
- for (; part_idx < pbi->num_partitions; ++part_idx)
- {
- if (vp8dx_start_decode(bool_decoder,
- pbi->partitions[part_idx],
- pbi->partition_sizes[part_idx]))
- vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
- "Failed to allocate bool decoder %d",
- part_idx);
-
- bool_decoder++;
- }
-
-#if CONFIG_MULTITHREAD
- /* Clamp number of decoder threads */
- if (pbi->decoding_thread_count > pbi->num_partitions - 1)
- pbi->decoding_thread_count = pbi->num_partitions - 1;
-#endif
-}
-
-
static int read_is_valid(const unsigned char *start,
size_t len,
const unsigned char *end)
@@ -465,99 +564,37 @@ static int read_is_valid(const unsigned char *start,
static void setup_token_decoder(VP8D_COMP *pbi,
const unsigned char *cx_data)
{
- int num_part;
- int i;
VP8_COMMON *pc = &pbi->common;
const unsigned char *user_data_end = pbi->Source + pbi->source_sz;
vp8_reader *bool_decoder;
const unsigned char *partition;
- /* Parse number of token partitions to use */
- const TOKEN_PARTITION multi_token_partition =
- (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
- /* Only update the multi_token_partition field if we are sure the value
- * is correct. */
- if (!pbi->ec_active || !vp8dx_bool_error(&pbi->bc))
- pc->multi_token_partition = multi_token_partition;
+ ptrdiff_t partition_size;
+ ptrdiff_t bytes_left;
- num_part = 1 << pc->multi_token_partition;
+ // Dummy read for now
+ vp8_read_literal(&pbi->bc, 2);
- /* Set up pointers to the first partition */
+ // Set up pointers to token partition
partition = cx_data;
bool_decoder = &pbi->bc2;
+ bytes_left = user_data_end - partition;
+ partition_size = bytes_left;
- if (num_part > 1)
+ /* Validate the calculated partition length. If the buffer
+ * described by the partition can't be fully read, then restrict
+ * it to the portion that can be (for EC mode) or throw an error.
+ */
+ if (!read_is_valid(partition, partition_size, user_data_end))
{
- CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_part * sizeof(vp8_reader)));
- bool_decoder = pbi->mbc;
- partition += 3 * (num_part - 1);
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet or corrupt partition "
+ "%d length", 1);
}
- for (i = 0; i < num_part; i++)
- {
- const unsigned char *partition_size_ptr = cx_data + i * 3;
- ptrdiff_t partition_size, bytes_left;
-
- bytes_left = user_data_end - partition;
-
- /* Calculate the length of this partition. The last partition
- * size is implicit. If the partition size can't be read, then
- * either use the remaining data in the buffer (for EC mode)
- * or throw an error.
- */
- if (i < num_part - 1)
- {
- if (read_is_valid(partition_size_ptr, 3, user_data_end))
- partition_size = read_partition_size(partition_size_ptr);
- else if (pbi->ec_active)
- partition_size = bytes_left;
- else
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated partition size data");
- }
- else
- partition_size = bytes_left;
-
- /* Validate the calculated partition length. If the buffer
- * described by the partition can't be fully read, then restrict
- * it to the portion that can be (for EC mode) or throw an error.
- */
- if (!read_is_valid(partition, partition_size, user_data_end))
- {
- if (pbi->ec_active)
- partition_size = bytes_left;
- else
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated packet or corrupt partition "
- "%d length", i + 1);
- }
-
- if (vp8dx_start_decode(bool_decoder, partition, partition_size))
- vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
- "Failed to allocate bool decoder %d", i + 1);
-
- /* Advance to the next partition */
- partition += partition_size;
- bool_decoder++;
- }
-
-#if CONFIG_MULTITHREAD
- /* Clamp number of decoder threads */
- if (pbi->decoding_thread_count > num_part - 1)
- pbi->decoding_thread_count = num_part - 1;
-#endif
-}
-
-
-static void stop_token_decoder(VP8D_COMP *pbi)
-{
- VP8_COMMON *pc = &pbi->common;
-
- if (pc->multi_token_partition != ONE_PARTITION)
- {
- vpx_free(pbi->mbc);
- pbi->mbc = NULL;
- }
+ if (vp8dx_start_decode(bool_decoder, partition, partition_size))
+ vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate bool decoder %d", 1);
}
static void init_frame(VP8D_COMP *pbi)
@@ -569,15 +606,21 @@ static void init_frame(VP8D_COMP *pbi)
{
/* Various keyframe initializations */
vpx_memcpy(pc->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+#if CONFIG_HIGH_PRECISION_MV
+ vpx_memcpy(pc->fc.mvc_hp, vp8_default_mv_context_hp,
+ sizeof(vp8_default_mv_context_hp));
+#endif
vp8_init_mbmode_probs(pc);
vp8_default_coef_probs(pc);
vp8_kf_default_bmode_probs(pc->kf_bmode_prob);
- /* reset the segment feature data to 0 with delta coding (Default state). */
- vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
- xd->mb_segement_abs_delta = SEGMENT_DELTADATA;
+ // Reset the segment feature data to the default stats:
+ // Features disabled, 0, with delta coding (Default state).
+ clearall_segfeatures( xd );
+
+ xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
/* reset the mode ref deltasa for loop filter */
vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
@@ -594,9 +637,18 @@ static void init_frame(VP8D_COMP *pbi)
*/
pc->ref_frame_sign_bias[GOLDEN_FRAME] = 0;
pc->ref_frame_sign_bias[ALTREF_FRAME] = 0;
+
+ vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
+ vpx_memcpy(&pc->lfc_a, &pc->fc, sizeof(pc->fc));
+
+ vp8_init_mode_contexts(&pbi->common);
+ vpx_memcpy( pbi->common.vp8_mode_contexts,
+ pbi->common.mode_context,
+ sizeof(pbi->common.mode_context));
}
else
{
+
if (!pc->use_bilinear_mc_filter)
pc->mcomp_filter_type = SIXTAP;
else
@@ -609,6 +661,8 @@ static void init_frame(VP8D_COMP *pbi)
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16);
+ xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8);
+ xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16);
}
else
{
@@ -616,10 +670,9 @@ static void init_frame(VP8D_COMP *pbi)
xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4);
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
+ xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8);
+ xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16);
}
-
- if (pbi->decoded_key_frame && pbi->ec_enabled && !pbi->ec_active)
- pbi->ec_active = 1;
}
xd->left_context = &pc->left_context;
@@ -646,15 +699,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
int mb_row;
int i, j, k, l;
- const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
int corrupt_tokens = 0;
- int prev_independent_partitions = pbi->independent_partitions;
-
- if (pbi->input_partition)
- {
- data = pbi->partitions[0];
- data_end = data + pbi->partition_sizes[0];
- }
/* start with no corruption of current frame */
xd->corrupted = 0;
@@ -662,21 +707,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
if (data_end - data < 3)
{
- if (pbi->ec_active)
- {
- /* Declare the missing frame as an inter frame since it will
- be handled as an inter frame when we have estimated its
- motion vectors. */
- pc->frame_type = INTER_FRAME;
- pc->version = 0;
- pc->show_frame = 1;
- first_partition_length_in_bytes = 0;
- }
- else
- {
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated packet");
- }
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet");
}
else
{
@@ -686,7 +718,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
first_partition_length_in_bytes =
(data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
- if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
+ if ((data + first_partition_length_in_bytes > data_end
|| data + first_partition_length_in_bytes < data))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition 0 length");
@@ -704,7 +736,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
/* When error concealment is enabled we should only check the sync
* code if we have enough bits available
*/
- if (!pbi->ec_active || data + 3 < data_end)
+ if (data + 3 < data_end)
{
if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
@@ -715,7 +747,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
* if we have enough data. Otherwise we will end up with the wrong
* size.
*/
- if (!pbi->ec_active || data + 6 < data_end)
+ if (data + 6 < data_end)
{
pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
pc->horiz_scale = data[4] >> 6;
@@ -745,22 +777,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffers");
-
-#if CONFIG_ERROR_CONCEALMENT
- pbi->overlaps = NULL;
- if (pbi->ec_enabled)
- {
- if (vp8_alloc_overlap_lists(pbi))
- vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
- "Failed to allocate overlap lists "
- "for error concealment");
- }
-#endif
-
-#if CONFIG_MULTITHREAD
- if (pbi->b_multithreaded_rd)
- vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows);
-#endif
}
}
}
@@ -786,51 +802,147 @@ int vp8_decode_frame(VP8D_COMP *pbi)
if (xd->segmentation_enabled)
{
- /* Signal whether or not the segmentation map is being explicitly updated this frame. */
+ // Read whether or not the segmentation map is being explicitly
+ // updated this frame.
xd->update_mb_segmentation_map = (unsigned char)vp8_read_bit(bc);
+
+ // If so what method will be used.
+ if ( xd->update_mb_segmentation_map )
+ pc->temporal_update = (unsigned char)vp8_read_bit(bc);
+
+ // Is the segment data being updated
xd->update_mb_segmentation_data = (unsigned char)vp8_read_bit(bc);
if (xd->update_mb_segmentation_data)
{
- xd->mb_segement_abs_delta = (unsigned char)vp8_read_bit(bc);
+ int data;
- vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
+ xd->mb_segment_abs_delta = (unsigned char)vp8_read_bit(bc);
- /* For each segmentation feature (Quant and loop filter level) */
- for (i = 0; i < MB_LVL_MAX; i++)
+ clearall_segfeatures( xd );
+
+ // For each segmentation...
+ for (i = 0; i < MAX_MB_SEGMENTS; i++)
{
- for (j = 0; j < MAX_MB_SEGMENTS; j++)
+ // For each of the segments features...
+ for (j = 0; j < SEG_LVL_MAX; j++)
{
- /* Frame level data */
+
+#if CONFIG_FEATUREUPDATES
+ // feature updated?
+ if (vp8_read_bit(bc))
+ {
+ int active=1;
+
+ if ( segfeature_active( xd, i, j ))
+ active=vp8_read_bit(bc);
+
+ // Is the feature enabled
+ if (active)
+ {
+ // Update the feature data and mask
+ enable_segfeature(xd, i, j);
+
+ data = (signed char)vp8_read_literal(
+ bc, seg_feature_data_bits(j));
+
+ // Is the segment data signed..
+ if ( is_segfeature_signed(j) )
+ {
+ if (vp8_read_bit(bc))
+ data = - data;
+ }
+ }
+ else
+ data = 0;
+
+ set_segdata(xd, i, j, data);
+ }
+
+#else
+ // Is the feature enabled
if (vp8_read_bit(bc))
{
- xd->segment_feature_data[i][j] = (signed char)vp8_read_literal(bc, mb_feature_data_bits[i]);
+ // Update the feature data and mask
+ enable_segfeature(xd, i, j);
- if (vp8_read_bit(bc))
- xd->segment_feature_data[i][j] = -xd->segment_feature_data[i][j];
+ data = (signed char)vp8_read_literal(
+ bc, seg_feature_data_bits(j));
+
+ // Is the segment data signed..
+ if ( is_segfeature_signed(j) )
+ {
+ if (vp8_read_bit(bc))
+ data = - data;
+ }
}
else
- xd->segment_feature_data[i][j] = 0;
+ data = 0;
+
+ set_segdata(xd, i, j, data);
+#endif
}
}
}
if (xd->update_mb_segmentation_map)
{
- /* Which macro block level features are enabled */
- vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
-
- /* Read the probs used to decode the segment id for each macro block. */
+ // Which macro block level features are enabled
+ vpx_memset(xd->mb_segment_tree_probs, 255,
+ sizeof(xd->mb_segment_tree_probs));
+ vpx_memset(pc->segment_pred_probs, 255,
+ sizeof(pc->segment_pred_probs));
+
+ // Read the probs used to decode the segment id for each macro
+ // block.
for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
{
- /* If not explicitly set value is defaulted to 255 by memset above */
+ // If not explicitly set value is defaulted to 255 by
+ //memset above
if (vp8_read_bit(bc))
- xd->mb_segment_tree_probs[i] = (vp8_prob)vp8_read_literal(bc, 8);
+ xd->mb_segment_tree_probs[i] =
+ (vp8_prob)vp8_read_literal(bc, 8);
+ }
+
+ // If predictive coding of segment map is enabled read the
+ // prediction probabilities.
+ if ( pc->temporal_update )
+ {
+ // Read the prediction probs needed to decode the segment id
+ // when predictive coding enabled
+ for (i = 0; i < PREDICTION_PROBS; i++)
+ {
+ // If not explicitly set value is defaulted to 255 by
+ // memset above
+ if (vp8_read_bit(bc))
+ pc->segment_pred_probs[i] =
+ (vp8_prob)vp8_read_literal(bc, 8);
+ }
}
}
}
+ // Read common prediction model status flag probability updates for the
+ // reference frame
+ if ( pc->frame_type == KEY_FRAME )
+ {
+ // Set the prediction probabilities to defaults
+ pc->ref_pred_probs[0] = 120;
+ pc->ref_pred_probs[1] = 80;
+ pc->ref_pred_probs[2] = 40;
+ }
+ else
+ {
+ for (i = 0; i < PREDICTION_PROBS; i++)
+ {
+ if ( vp8_read_bit(bc) )
+ pc->ref_pred_probs[i] = (vp8_prob)vp8_read_literal(bc, 8);
+ }
+ }
+
/* Read the loop filter level and type */
+ pc->txfm_mode = (TXFM_MODE) vp8_read_bit(bc);
+
pc->filter_type = (LOOPFILTERTYPE) vp8_read_bit(bc);
pc->filter_level = vp8_read_literal(bc, 6);
pc->sharpness_level = vp8_read_literal(bc, 3);
@@ -874,21 +986,15 @@ int vp8_decode_frame(VP8D_COMP *pbi)
}
}
- if (pbi->input_partition)
- {
- setup_token_decoder_partition_input(pbi);
- }
- else
- {
- setup_token_decoder(pbi, data + first_partition_length_in_bytes);
- }
+ setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+
xd->current_bc = &pbi->bc2;
/* Read the default quantizers. */
{
int Q, q_update;
- Q = vp8_read_literal(bc, 7); /* AC 1st order Q = default */
+ Q = vp8_read_literal(bc, QINDEX_BITS); /* AC 1st order Q = default */
pc->base_qindex = Q;
q_update = 0;
pc->y1dc_delta_q = get_delta_q(bc, pc->y1dc_delta_q, &q_update);
@@ -912,20 +1018,22 @@ int vp8_decode_frame(VP8D_COMP *pbi)
{
/* Should the GF or ARF be updated from the current frame */
pc->refresh_golden_frame = vp8_read_bit(bc);
-#if CONFIG_ERROR_CONCEALMENT
- /* Assume we shouldn't refresh golden if the bit is missing */
- xd->corrupted |= vp8dx_bool_error(bc);
- if (pbi->ec_active && xd->corrupted)
- pc->refresh_golden_frame = 0;
-#endif
-
pc->refresh_alt_ref_frame = vp8_read_bit(bc);
-#if CONFIG_ERROR_CONCEALMENT
- /* Assume we shouldn't refresh altref if the bit is missing */
- xd->corrupted |= vp8dx_bool_error(bc);
- if (pbi->ec_active && xd->corrupted)
- pc->refresh_alt_ref_frame = 0;
-#endif
+
+ if(pc->refresh_alt_ref_frame)
+ {
+ vpx_memcpy(&pc->fc, &pc->lfc_a, sizeof(pc->fc));
+ vpx_memcpy( pc->vp8_mode_contexts,
+ pc->mode_context_a,
+ sizeof(pc->vp8_mode_contexts));
+ }
+ else
+ {
+ vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
+ vpx_memcpy( pc->vp8_mode_contexts,
+ pc->mode_context,
+ sizeof(pc->vp8_mode_contexts));
+ }
/* Buffer to buffer copy flags. */
pc->copy_buffer_to_gf = 0;
@@ -940,6 +1048,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp8_read_bit(bc);
pc->ref_frame_sign_bias[ALTREF_FRAME] = vp8_read_bit(bc);
+
+#if CONFIG_HIGH_PRECISION_MV
+ /* Is high precision mv allowed */
+ xd->allow_high_precision_mv = (unsigned char)vp8_read_bit(bc);
+#endif
}
pc->refresh_entropy_probs = vp8_read_bit(bc);
@@ -950,13 +1063,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
pc->refresh_last_frame = pc->frame_type == KEY_FRAME || vp8_read_bit(bc);
-#if CONFIG_ERROR_CONCEALMENT
- /* Assume we should refresh the last frame if the bit is missing */
- xd->corrupted |= vp8dx_bool_error(bc);
- if (pbi->ec_active && xd->corrupted)
- pc->refresh_last_frame = 1;
-#endif
-
if (0)
{
FILE *z = fopen("decodestats.stt", "a");
@@ -971,15 +1077,14 @@ int vp8_decode_frame(VP8D_COMP *pbi)
}
{
- pbi->independent_partitions = 1;
-
+ if(vp8_read_bit(bc))
+ {
/* read coef probability tree */
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
for (l = 0; l < ENTROPY_NODES; l++)
{
-
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
if (vp8_read(bc, vp8_coef_update_probs [i][j][k][l]))
@@ -987,20 +1092,40 @@ int vp8_decode_frame(VP8D_COMP *pbi)
*p = (vp8_prob)vp8_read_literal(bc, 8);
}
- if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
- pbi->independent_partitions = 0;
+ }
+ }
+ }
+
+ if(pbi->common.txfm_mode == ALLOW_8X8 && vp8_read_bit(bc))
+ {
+ // read coef probability tree
+ for (i = 0; i < BLOCK_TYPES; i++)
+ for (j = 0; j < COEF_BANDS; j++)
+ for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+ for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+ {
+
+ vp8_prob *const p = pc->fc.coef_probs_8x8 [i][j][k] + l;
+
+ if (vp8_read(bc, vp8_coef_update_probs_8x8 [i][j][k][l]))
+ {
+ *p = (vp8_prob)vp8_read_literal(bc, 8);
+ }
}
}
+
vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG));
vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx], sizeof(YV12_BUFFER_CONFIG));
+ // Create the segmentation map structure and set to 0
+ if (!pc->last_frame_seg_map)
+ CHECK_MEM_ERROR(pc->last_frame_seg_map,
+ vpx_calloc((pc->mb_rows * pc->mb_cols), 1));
+
/* set up frame new frame for intra coded blocks */
-#if CONFIG_MULTITHREAD
- if (!(pbi->b_multithreaded_rd) || pc->multi_token_partition == ONE_PARTITION || !(pc->filter_level))
-#endif
- vp8_setup_intra_recon(&pc->yv12_fb[pc->new_fb_idx]);
+ vp8_setup_intra_recon(&pc->yv12_fb[pc->new_fb_idx]);
vp8_setup_block_dptrs(xd);
@@ -1012,57 +1137,23 @@ int vp8_decode_frame(VP8D_COMP *pbi)
/* Read the mb_no_coeff_skip flag */
pc->mb_no_coeff_skip = (int)vp8_read_bit(bc);
-
vp8_decode_mode_mvs(pbi);
-
-#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_active &&
- pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
+ if(pbi->common.frame_type != KEY_FRAME)
{
- /* Motion vectors are missing in this frame. We will try to estimate
- * them and then continue decoding the frame as usual */
- vp8_estimate_missing_mvs(pbi);
+ vp8_update_mode_context(&pbi->common);
}
-#endif
vpx_memset(pc->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * pc->mb_cols);
-#if CONFIG_MULTITHREAD
- if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
- {
- int i;
- pbi->frame_corrupt_residual = 0;
- vp8mt_decode_mb_rows(pbi, xd);
- vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]); /*cm->frame_to_show);*/
- for (i = 0; i < pbi->decoding_thread_count; ++i)
- corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
- }
- else
-#endif
- {
- int ibc = 0;
- int num_part = 1 << pc->multi_token_partition;
- pbi->frame_corrupt_residual = 0;
-
- /* Decode the individual macro block */
- for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
- {
-
- if (num_part > 1)
- {
- xd->current_bc = & pbi->mbc[ibc];
- ibc++;
-
- if (ibc == num_part)
- ibc = 0;
- }
+ // Resset the macroblock mode info context to the start of the list
+ xd->mode_info_context = pc->mi;
- decode_mb_row(pbi, pc, mb_row, xd);
- }
- corrupt_tokens |= xd->corrupted;
+ /* Decode a row of macro blocks */
+ for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
+ {
+ decode_mb_row(pbi, pc, mb_row, xd);
}
-
- stop_token_decoder(pbi);
+ corrupt_tokens |= xd->corrupted;
/* Collect information about decoder corruption. */
/* 1. Check first boolean decoder for errors. */
@@ -1088,11 +1179,12 @@ int vp8_decode_frame(VP8D_COMP *pbi)
{
pc->last_kf_gf_q = pc->base_qindex;
}
-
- if (pc->refresh_entropy_probs == 0)
+ if(pc->refresh_entropy_probs)
{
- vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
- pbi->independent_partitions = prev_independent_partitions;
+ if(pc->refresh_alt_ref_frame)
+ vpx_memcpy(&pc->lfc_a, &pc->fc, sizeof(pc->fc));
+ else
+ vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
}
#ifdef PACKET_TESTING
@@ -1104,6 +1196,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
fclose(f);
}
#endif
+ //printf("Frame %d Done\n", frame_count++);
return 0;
}
diff --git a/vp8/decoder/dequantize.c b/vp8/decoder/dequantize.c
index a60442fe8..f83032766 100644
--- a/vp8/decoder/dequantize.c
+++ b/vp8/decoder/dequantize.c
@@ -9,17 +9,24 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "dequantize.h"
#include "vp8/common/idct.h"
#include "vpx_mem/vpx_mem.h"
+#include "onyxd_int.h"
extern void vp8_short_idct4x4llm_c(short *input, short *output, int pitch) ;
extern void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch);
+extern void vp8_short_idct8x8_c(short *input, short *output, int pitch);
+extern void vp8_short_idct8x8_1_c(short *input, short *output, int pitch);
+#ifdef DEC_DEBUG
+extern int dec_debug;
+#endif
void vp8_dequantize_b_c(BLOCKD *d)
{
+
int i;
short *DQ = d->dqcoeff;
short *Q = d->qcoeff;
@@ -111,3 +118,212 @@ void vp8_dequant_dc_idct_add_c(short *input, short *dq, unsigned char *pred,
pred += pitch;
}
}
+
+void vp8_dequantize_b_2x2_c(BLOCKD *d)
+{
+ int i;
+ short *DQ = d->dqcoeff;
+ short *Q = d->qcoeff;
+ short *DQC = d->dequant;
+
+ for (i = 0; i < 16; i++)
+ {
+ DQ[i] = (short)((Q[i] * DQC[i]));
+ }
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Dequantize 2x2\n");
+ for (j=0;j<16;j++) printf("%d ", Q[j]); printf("\n");
+ for (j=0;j<16;j++) printf("%d ", DQ[j]); printf("\n");
+ }
+#endif
+}
+
+void vp8_dequant_idct_add_8x8_c(short *input, short *dq, unsigned char *pred,
+ unsigned char *dest, int pitch, int stride)//, MACROBLOCKD *xd, short blk_idx
+{
+ short output[64];
+ short *diff_ptr = output;
+ int r, c, b;
+ int i;
+ unsigned char *origdest = dest;
+ unsigned char *origpred = pred;
+
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Input 8x8\n");
+ for (j=0;j<64;j++) {
+ printf("%d ", input[j]);
+ if (j%8 == 7) printf("\n");
+ }
+ }
+#endif
+
+ input[0]= input[0] * dq[0];
+
+ // recover quantizer for 4 4x4 blocks
+ for (i = 1; i < 64; i++)
+ {
+ input[i]=input[i] * dq[1];
+ }
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Input DQ 8x8\n");
+ for (j=0;j<64;j++) {
+ printf("%d ", input[j]);
+ if (j%8 == 7) printf("\n");
+ }
+ }
+#endif
+
+ // the idct halves ( >> 1) the pitch
+ vp8_short_idct8x8_c(input, output, 16);
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Output 8x8\n");
+ for (j=0;j<64;j++) {
+ printf("%d ", output[j]);
+ if (j%8 == 7) printf("\n");
+ }
+ }
+#endif
+
+ vpx_memset(input, 0, 128);// test what should i put here
+
+ for (b = 0; b < 4; b++)
+ {
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ int a = diff_ptr[c] + pred[c];
+
+ if (a < 0)
+ a = 0;
+
+ if (a > 255)
+ a = 255;
+
+ dest[c] = (unsigned char) a;
+ }
+
+ dest += stride;
+ diff_ptr += 8;
+ pred += pitch;
+ }
+ diff_ptr = output + (b+1) / 2 * 4 * 8 + (b+1) % 2 * 4;
+ dest = origdest + (b+1) / 2 * 4 * stride + (b+1) % 2 * 4;
+ pred = origpred + (b+1) / 2 * 4 * pitch + (b+1) % 2 * 4;
+ }
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int k,j;
+ printf("Final 8x8\n");
+ for (j=0;j<8;j++) {
+ for (k=0;k<8;k++) {
+ printf("%d ", origdest[k]);
+ }
+ printf("\n");
+ origdest+=stride;
+ }
+ }
+#endif
+}
+
+void vp8_dequant_dc_idct_add_8x8_c(short *input, short *dq, unsigned char *pred,
+ unsigned char *dest, int pitch, int stride,
+ int Dc)// Dc for 1st order T in some rear case
+{
+ short output[64];
+ short *diff_ptr = output;
+ int r, c, b;
+ int i;
+ unsigned char *origdest = dest;
+ unsigned char *origpred = pred;
+
+ input[0] = (short)Dc;//Dc is the reconstructed value, do not need dequantization
+ //dc value is recovered after dequantization, since dc need not quantization
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Input 8x8\n");
+ for (j=0;j<64;j++) {
+ printf("%d ", input[j]);
+ if (j%8 == 7) printf("\n");
+ }
+ }
+#endif
+ for (i = 1; i < 64; i++)
+ {
+ input[i]=input[i] * dq[1];
+ }
+
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Input DQ 8x8\n");
+ for (j=0;j<64;j++) {
+ printf("%d ", input[j]);
+ if (j%8 == 7) printf("\n");
+ }
+ }
+#endif
+
+ // the idct halves ( >> 1) the pitch
+ vp8_short_idct8x8_c(input, output,16);
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int j;
+ printf("Output 8x8\n");
+ for (j=0;j<64;j++) {
+ printf("%d ", output[j]);
+ if (j%8 == 7) printf("\n");
+ }
+ }
+#endif
+ vpx_memset(input, 0, 128);
+
+ for (b = 0; b < 4; b++)
+ {
+ for (r = 0; r < 4; r++)
+ {
+ for (c = 0; c < 4; c++)
+ {
+ int a = diff_ptr[c] + pred[c];
+
+ if (a < 0)
+ a = 0;
+
+ if (a > 255)
+ a = 255;
+
+ dest[c] = (unsigned char) a;
+ }
+
+ dest += stride;
+ diff_ptr += 8;
+ pred += pitch;
+ }
+ diff_ptr = output + (b+1) / 2 * 4 * 8 + (b+1) % 2 * 4;
+ dest = origdest + (b+1) / 2 * 4 * stride + (b+1) % 2 * 4;
+ pred = origpred + (b+1) / 2 * 4 * pitch + (b+1) % 2 * 4;
+ }
+#ifdef DEC_DEBUG
+ if (dec_debug) {
+ int k,j;
+ printf("Final 8x8\n");
+ for (j=0;j<8;j++) {
+ for (k=0;k<8;k++) {
+ printf("%d ", origdest[k]);
+ }
+ printf("\n");
+ origdest+=stride;
+ }
+ }
+#endif
+}
+
diff --git a/vp8/decoder/dequantize.h b/vp8/decoder/dequantize.h
index 2e662a593..d0f162b48 100644
--- a/vp8/decoder/dequantize.h
+++ b/vp8/decoder/dequantize.h
@@ -42,6 +42,22 @@
unsigned char *pre, unsigned char *dst_u, \
unsigned char *dst_v, int stride, char *eobs)
+#define prototype_dequant_dc_idct_add_y_block_8x8(sym) \
+ void sym(short *q, short *dq, \
+ unsigned char *pre, unsigned char *dst, \
+ int stride, char *eobs, short *dc, MACROBLOCKD *xd)
+
+#define prototype_dequant_idct_add_y_block_8x8(sym) \
+ void sym(short *q, short *dq, \
+ unsigned char *pre, unsigned char *dst, \
+ int stride, char *eobs, MACROBLOCKD *xd)
+
+#define prototype_dequant_idct_add_uv_block_8x8(sym) \
+ void sym(short *q, short *dq, \
+ unsigned char *pre, unsigned char *dst_u, \
+ unsigned char *dst_v, int stride, char *eobs, \
+ MACROBLOCKD *xd)
+
#if ARCH_X86 || ARCH_X86_64
#include "x86/dequantize_x86.h"
#endif
@@ -81,6 +97,38 @@ extern prototype_dequant_idct_add_y_block(vp8_dequant_idct_add_y_block);
extern prototype_dequant_idct_add_uv_block(vp8_dequant_idct_add_uv_block);
+#ifndef vp8_dequant_block_2x2
+#define vp8_dequant_block_2x2 vp8_dequantize_b_2x2_c
+#endif
+extern prototype_dequant_block(vp8_dequant_block_2x2);
+
+#ifndef vp8_dequant_idct_add_8x8
+#define vp8_dequant_idct_add_8x8 vp8_dequant_idct_add_8x8_c
+#endif
+extern prototype_dequant_idct_add(vp8_dequant_idct_add_8x8);
+
+#ifndef vp8_dequant_dc_idct_add_8x8
+#define vp8_dequant_dc_idct_add_8x8 vp8_dequant_dc_idct_add_8x8_c
+#endif
+extern prototype_dequant_dc_idct_add(vp8_dequant_dc_idct_add_8x8);
+
+#ifndef vp8_dequant_dc_idct_add_y_block_8x8
+#define vp8_dequant_dc_idct_add_y_block_8x8 vp8_dequant_dc_idct_add_y_block_8x8_c
+#endif
+extern prototype_dequant_dc_idct_add_y_block_8x8(vp8_dequant_dc_idct_add_y_block_8x8);
+
+#ifndef vp8_dequant_idct_add_y_block_8x8
+#define vp8_dequant_idct_add_y_block_8x8 vp8_dequant_idct_add_y_block_8x8_c
+#endif
+extern prototype_dequant_idct_add_y_block_8x8(vp8_dequant_idct_add_y_block_8x8);
+
+#ifndef vp8_dequant_idct_add_uv_block_8x8
+#define vp8_dequant_idct_add_uv_block_8x8 vp8_dequant_idct_add_uv_block_8x8_c
+#endif
+extern prototype_dequant_idct_add_uv_block_8x8(vp8_dequant_idct_add_uv_block_8x8);
+
+
+
typedef prototype_dequant_block((*vp8_dequant_block_fn_t));
typedef prototype_dequant_idct_add((*vp8_dequant_idct_add_fn_t));
@@ -93,6 +141,12 @@ typedef prototype_dequant_idct_add_y_block((*vp8_dequant_idct_add_y_block_fn_t))
typedef prototype_dequant_idct_add_uv_block((*vp8_dequant_idct_add_uv_block_fn_t));
+typedef prototype_dequant_dc_idct_add_y_block_8x8((*vp8_dequant_dc_idct_add_y_block_fn_t_8x8));
+
+typedef prototype_dequant_idct_add_y_block_8x8((*vp8_dequant_idct_add_y_block_fn_t_8x8));
+
+typedef prototype_dequant_idct_add_uv_block_8x8((*vp8_dequant_idct_add_uv_block_fn_t_8x8));
+
typedef struct
{
vp8_dequant_block_fn_t block;
@@ -101,6 +155,12 @@ typedef struct
vp8_dequant_dc_idct_add_y_block_fn_t dc_idct_add_y_block;
vp8_dequant_idct_add_y_block_fn_t idct_add_y_block;
vp8_dequant_idct_add_uv_block_fn_t idct_add_uv_block;
+ vp8_dequant_block_fn_t block_2x2;
+ vp8_dequant_idct_add_fn_t idct_add_8x8;
+ vp8_dequant_dc_idct_add_fn_t dc_idct_add_8x8;
+ vp8_dequant_dc_idct_add_y_block_fn_t_8x8 dc_idct_add_y_block_8x8;
+ vp8_dequant_idct_add_y_block_fn_t_8x8 idct_add_y_block_8x8;
+ vp8_dequant_idct_add_uv_block_fn_t_8x8 idct_add_uv_block_8x8;
} vp8_dequant_rtcd_vtable_t;
#if CONFIG_RUNTIME_CPU_DETECT
diff --git a/vp8/decoder/detokenize.c b/vp8/decoder/detokenize.c
index 98be68558..ae105b139 100644
--- a/vp8/decoder/detokenize.c
+++ b/vp8/decoder/detokenize.c
@@ -16,6 +16,8 @@
#include "vpx_ports/mem.h"
#include "detokenize.h"
+#include "vp8/common/seg_common.h"
+
#define BOOL_DATA UINT8
#define OCB_X PREV_COEF_CONTEXTS * ENTROPY_NODES
@@ -26,6 +28,17 @@ DECLARE_ALIGNED(16, static const unsigned char, coef_bands_x[16]) =
6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X,
6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 7 * OCB_X
};
+DECLARE_ALIGNED(64, static const unsigned char, coef_bands_x_8x8[64]) = {
+ 0 * OCB_X, 1 * OCB_X, 2 * OCB_X, 3 * OCB_X, 5 * OCB_X, 4 * OCB_X, 4 * OCB_X, 5 * OCB_X,
+ 5 * OCB_X, 3 * OCB_X, 6 * OCB_X, 3 * OCB_X, 5 * OCB_X, 4 * OCB_X, 6 * OCB_X, 6 * OCB_X,
+ 6 * OCB_X, 5 * OCB_X, 5 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X,
+ 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X,
+ 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X,
+ 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X,
+ 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X,
+ 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X, 7 * OCB_X,
+};
+
#define EOB_CONTEXT_NODE 0
#define ZERO_CONTEXT_NODE 1
#define ONE_CONTEXT_NODE 2
@@ -44,7 +57,6 @@ DECLARE_ALIGNED(16, static const unsigned char, coef_bands_x[16]) =
#define CAT4_MIN_VAL 19
#define CAT5_MIN_VAL 35
#define CAT6_MIN_VAL 67
-
#define CAT1_PROB0 159
#define CAT2_PROB0 145
#define CAT2_PROB1 165
@@ -64,18 +76,14 @@ DECLARE_ALIGNED(16, static const unsigned char, coef_bands_x[16]) =
#define CAT5_PROB3 157
#define CAT5_PROB4 180
-#if CONFIG_EXTEND_QRANGE
static const unsigned char cat6_prob[14] =
{ 129, 130, 133, 140, 153, 177, 196, 230, 243, 249, 252, 254, 254, 0 };
-#else
-static const unsigned char cat6_prob[12] =
-{ 129, 130, 133, 140, 153, 177, 196, 230, 243, 254, 254, 0 };
-#endif
void vp8_reset_mb_tokens_context(MACROBLOCKD *x)
{
/* Clear entropy contexts for Y2 blocks */
if (x->mode_info_context->mbmi.mode != B_PRED &&
+ x->mode_info_context->mbmi.mode != I8X8_PRED &&
x->mode_info_context->mbmi.mode != SPLITMV)
{
vpx_memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
@@ -158,6 +166,47 @@ DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
NORMALIZE \
}
+#define DECODE_AND_LOOP_IF_ZERO_8x8_2(probability,branch) \
+ { \
+ split = 1 + ((( probability*(range-1) ) ) >> 8); \
+ bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); \
+ FILL \
+ if ( value < bigsplit ) \
+ { \
+ range = split; \
+ NORMALIZE \
+ Prob = coef_probs; \
+ if(c<3) {\
+ ++c; \
+ Prob += coef_bands_x[c]; \
+ goto branch; \
+ } goto BLOCK_FINISHED_8x8; /*for malformed input */\
+ } \
+ value -= bigsplit; \
+ range = range - split; \
+ NORMALIZE \
+ }
+#define DECODE_AND_LOOP_IF_ZERO_8X8(probability,branch) \
+ { \
+ split = 1 + ((( probability*(range-1) ) ) >> 8); \
+ bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); \
+ FILL \
+ if ( value < bigsplit ) \
+ { \
+ range = split; \
+ NORMALIZE \
+ Prob = coef_probs; \
+ if(c<63) {\
+ ++c; \
+ Prob += coef_bands_x_8x8[c]; \
+ goto branch; \
+ } goto BLOCK_FINISHED_8x8; /*for malformed input */\
+ } \
+ value -= bigsplit; \
+ range = range - split; \
+ NORMALIZE \
+ }
+
#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \
DECODE_AND_APPLYSIGN(val) \
Prob = coef_probs + (ENTROPY_NODES*2); \
@@ -169,6 +218,26 @@ DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
goto BLOCK_FINISHED;
+#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val) \
+ DECODE_AND_APPLYSIGN(val) \
+ Prob = coef_probs + (ENTROPY_NODES*2); \
+ if(c < 3){\
+ qcoeff_ptr [ scan[c] ] = (INT16) v; \
+ ++c; \
+ goto DO_WHILE_8x8; }\
+ qcoeff_ptr [ scan[3] ] = (INT16) v; \
+ goto BLOCK_FINISHED_8x8;
+#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val) \
+ DECODE_AND_APPLYSIGN(val) \
+ Prob = coef_probs + (ENTROPY_NODES*2); \
+ if(c < 63){\
+ qcoeff_ptr [ scan[c] ] = (INT16) v; \
+ ++c; \
+ goto DO_WHILE_8x8; }\
+ qcoeff_ptr [ scan[63] ] = (INT16) v; \
+ goto BLOCK_FINISHED_8x8;
+
+
#define DECODE_EXTRABIT_AND_ADJUST_VAL(prob, bits_count)\
split = 1 + (((range-1) * prob) >> 8); \
bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8); \
@@ -185,11 +254,12 @@ DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
}\
NORMALIZE
-int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
+
+int vp8_decode_mb_tokens_8x8(VP8D_COMP *dx, MACROBLOCKD *x)
{
ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)x->above_context;
ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)x->left_context;
- const FRAME_CONTEXT * const fc = &dx->common.fc;
+ const VP8_COMMON *const oc = & dx->common;
BOOL_DECODER *bc = x->current_bc;
@@ -207,6 +277,331 @@ int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
const BOOL_DATA *bufend;
register unsigned int range;
VP8_BD_VALUE value;
+ const int *scan;//
+ register unsigned int shift;
+ UINT32 split;
+ VP8_BD_VALUE bigsplit;
+ INT16 *qcoeff_ptr;
+
+ const vp8_prob *coef_probs;//
+ int type;
+ int stop;
+ INT16 val, bits_count;
+ INT16 c;
+ INT16 v;
+ const vp8_prob *Prob;//
+
+ int seg_eob;
+ int segment_id = x->mode_info_context->mbmi.segment_id;
+
+ type = 3;
+ i = 0;
+ stop = 16;
+
+ scan = vp8_default_zig_zag1d_8x8;
+ qcoeff_ptr = &x->qcoeff[0];
+
+ if (x->mode_info_context->mbmi.mode != B_PRED && x->mode_info_context->mbmi.mode != SPLITMV)
+ {
+ i = 24;
+ stop = 24;
+ type = 1;
+ qcoeff_ptr += 24*16;
+ eobtotal -= 4;
+ scan = vp8_default_zig_zag1d;
+ }
+
+ bufend = bc->user_buffer_end;
+ bufptr = bc->user_buffer;
+ value = bc->value;
+ count = bc->count;
+ range = bc->range;
+
+ coef_probs = oc->fc.coef_probs_8x8 [type] [ 0 ] [0];
+
+BLOCK_LOOP_8x8:
+ a = A + vp8_block2above_8x8[i];
+ l = L + vp8_block2left_8x8[i];
+
+ c = (INT16)(!type);
+
+// Dest = ((A)!=0) + ((B)!=0);
+ if(i==24)
+ {
+ VP8_COMBINEENTROPYCONTEXTS(v, *a, *l);
+ if ( segfeature_active( x, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( x, segment_id, SEG_LVL_EOB );
+ }
+ else
+ seg_eob = 4;
+ }
+ else
+ {
+ VP8_COMBINEENTROPYCONTEXTS(v, *a, *l);
+ if ( segfeature_active( x, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( x, segment_id, SEG_LVL_EOB );
+ }
+ else
+ seg_eob = 64;
+ }
+
+ Prob = coef_probs;
+ Prob += v * ENTROPY_NODES;
+
+DO_WHILE_8x8:
+ if ( c == seg_eob )
+ goto BLOCK_FINISHED_8x8;
+
+ if(i==24)
+ Prob += coef_bands_x[c];
+ else
+ Prob += coef_bands_x_8x8[c];
+ DECODE_AND_BRANCH_IF_ZERO(Prob[EOB_CONTEXT_NODE], BLOCK_FINISHED_8x8);
+
+CHECK_0_8x8_:
+ if (i==24)
+ {
+ DECODE_AND_LOOP_IF_ZERO_8x8_2(Prob[ZERO_CONTEXT_NODE], CHECK_0_8x8_);
+ }
+ else
+ {
+ DECODE_AND_LOOP_IF_ZERO_8X8(Prob[ZERO_CONTEXT_NODE], CHECK_0_8x8_);
+ }
+ DECODE_AND_BRANCH_IF_ZERO(Prob[ONE_CONTEXT_NODE], ONE_CONTEXT_NODE_0_8x8_);
+ DECODE_AND_BRANCH_IF_ZERO(Prob[LOW_VAL_CONTEXT_NODE],
+ LOW_VAL_CONTEXT_NODE_0_8x8_);
+ DECODE_AND_BRANCH_IF_ZERO(Prob[HIGH_LOW_CONTEXT_NODE],
+ HIGH_LOW_CONTEXT_NODE_0_8x8_);
+ DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_THREEFOUR_CONTEXT_NODE],
+ CAT_THREEFOUR_CONTEXT_NODE_0_8x8_);
+ DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_FIVE_CONTEXT_NODE],
+ CAT_FIVE_CONTEXT_NODE_0_8x8_);
+ val = CAT6_MIN_VAL;
+ bits_count = 12;
+ do
+ {
+ DECODE_EXTRABIT_AND_ADJUST_VAL(cat6_prob[bits_count], bits_count);
+ bits_count -- ;
+ }
+ while (bits_count >= 0);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val);
+ }
+
+CAT_FIVE_CONTEXT_NODE_0_8x8_:
+ val = CAT5_MIN_VAL;
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT5_PROB4, 4);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT5_PROB3, 3);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT5_PROB2, 2);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT5_PROB1, 1);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT5_PROB0, 0);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val);
+ }
+
+CAT_THREEFOUR_CONTEXT_NODE_0_8x8_:
+ DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_THREE_CONTEXT_NODE],
+ CAT_THREE_CONTEXT_NODE_0_8x8_);
+ val = CAT4_MIN_VAL;
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT4_PROB3, 3);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT4_PROB2, 2);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT4_PROB1, 1);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT4_PROB0, 0);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val);
+ }
+
+CAT_THREE_CONTEXT_NODE_0_8x8_:
+ val = CAT3_MIN_VAL;
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT3_PROB2, 2);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT3_PROB1, 1);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT3_PROB0, 0);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val);
+ }
+
+HIGH_LOW_CONTEXT_NODE_0_8x8_:
+ DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_ONE_CONTEXT_NODE],
+ CAT_ONE_CONTEXT_NODE_0_8x8_);
+ val = CAT2_MIN_VAL;
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT2_PROB1, 1);
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT2_PROB0, 0);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val);
+ }
+
+CAT_ONE_CONTEXT_NODE_0_8x8_:
+ val = CAT1_MIN_VAL;
+ DECODE_EXTRABIT_AND_ADJUST_VAL(CAT1_PROB0, 0);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(val);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(val);
+ }
+
+LOW_VAL_CONTEXT_NODE_0_8x8_:
+ DECODE_AND_BRANCH_IF_ZERO(Prob[TWO_CONTEXT_NODE],
+ TWO_CONTEXT_NODE_0_8x8_);
+ DECODE_AND_BRANCH_IF_ZERO(Prob[THREE_CONTEXT_NODE],
+ THREE_CONTEXT_NODE_0_8x8_);
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(4);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(4);
+ }
+
+
+THREE_CONTEXT_NODE_0_8x8_:
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(3);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(3);
+ }
+
+
+TWO_CONTEXT_NODE_0_8x8_:
+ if(i==24)
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8_2(2);
+ }
+ else
+ {
+ DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT_8x8(2);
+ }
+
+
+ONE_CONTEXT_NODE_0_8x8_:
+ DECODE_AND_APPLYSIGN(1);
+ Prob = coef_probs + ENTROPY_NODES;
+
+ if (i==24)
+ {
+ if (c < 3)//15
+ {
+ qcoeff_ptr [ scan[c] ] = (INT16) v;
+ ++c;
+ goto DO_WHILE_8x8;
+ }
+ }
+ else
+ {
+ if (c < 63)
+ {
+ qcoeff_ptr [ scan[c] ] = (INT16) v;
+ ++c;
+ goto DO_WHILE_8x8;
+ }
+ }
+
+ if(i==24)
+ qcoeff_ptr [ scan[3] ] = (INT16) v;//15
+ else
+ qcoeff_ptr [ scan[63] ] = (INT16) v;
+
+
+BLOCK_FINISHED_8x8:
+ *a = *l = ((eobs[i] = c) != !type); // any nonzero data?
+ if (i!=24)
+ {
+ *(a + 1) = *a;
+ *(l + 1) = *l;
+ }
+
+ eobtotal += c;
+ qcoeff_ptr += (i==24 ? 16 : 64);
+
+ i+=4;
+
+ if (i < stop)
+ goto BLOCK_LOOP_8x8;
+
+ if (i > 24)
+ {
+ type = 0;
+ i = 0;
+ stop = 16;
+ coef_probs = oc->fc.coef_probs_8x8 [type] [ 0 ] [0];
+ qcoeff_ptr -= (24*16 + 16);
+ scan = vp8_default_zig_zag1d_8x8;
+ goto BLOCK_LOOP_8x8;
+ }
+
+ if (i == 16)
+ {
+ type = 2;
+ coef_probs = oc->fc.coef_probs_8x8 [type] [ 0 ] [0];
+ stop = 24;
+ goto BLOCK_LOOP_8x8;
+ }
+
+ FILL
+ bc->user_buffer = bufptr;
+ bc->value = value;
+ bc->count = count;
+ bc->range = range;
+
+ return eobtotal;
+
+}
+
+int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *xd)
+{
+ ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)xd->above_context;
+ ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)xd->left_context;
+ const FRAME_CONTEXT * const fc = &dx->common.fc;
+
+ BOOL_DECODER *bc = xd->current_bc;
+
+ char *eobs = xd->eobs;
+
+ ENTROPY_CONTEXT *a;
+ ENTROPY_CONTEXT *l;
+ int i;
+
+ int eobtotal = 0;
+
+ register int count;
+
+ const BOOL_DATA *bufptr;
+ const BOOL_DATA *bufend;
+ register unsigned int range;
+ VP8_BD_VALUE value;
const int *scan;
register unsigned int shift;
UINT32 split;
@@ -221,15 +616,23 @@ int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
INT16 v;
const vp8_prob *Prob;
+ int seg_eob = 16;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
+
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+
type = 3;
i = 0;
stop = 16;
scan = vp8_default_zig_zag1d;
- qcoeff_ptr = &x->qcoeff[0];
-
- if (x->mode_info_context->mbmi.mode != B_PRED &&
- x->mode_info_context->mbmi.mode != SPLITMV)
+ qcoeff_ptr = &xd->qcoeff[0];
+ if (xd->mode_info_context->mbmi.mode != B_PRED &&
+ xd->mode_info_context->mbmi.mode != I8X8_PRED &&
+ xd->mode_info_context->mbmi.mode != SPLITMV)
{
i = 24;
stop = 24;
@@ -259,6 +662,9 @@ BLOCK_LOOP:
Prob += v * ENTROPY_NODES;
DO_WHILE:
+ if ( c == seg_eob )
+ goto BLOCK_FINISHED;
+
Prob += coef_bands_x[c];
DECODE_AND_BRANCH_IF_ZERO(Prob[EOB_CONTEXT_NODE], BLOCK_FINISHED);
@@ -275,7 +681,7 @@ CHECK_0_:
CAT_FIVE_CONTEXT_NODE_0_);
val = CAT6_MIN_VAL;
- bits_count = CONFIG_EXTEND_QRANGE?12:10;
+ bits_count = 12;
do
{
@@ -382,6 +788,7 @@ BLOCK_FINISHED:
bc->value = value;
bc->count = count;
bc->range = range;
+
return eobtotal;
}
diff --git a/vp8/decoder/detokenize.h b/vp8/decoder/detokenize.h
index 8640bda4c..caedf2f37 100644
--- a/vp8/decoder/detokenize.h
+++ b/vp8/decoder/detokenize.h
@@ -16,5 +16,6 @@
void vp8_reset_mb_tokens_context(MACROBLOCKD *x);
int vp8_decode_mb_tokens(VP8D_COMP *, MACROBLOCKD *);
+int vp8_decode_mb_tokens_8x8(VP8D_COMP *, MACROBLOCKD *);
#endif /* DETOKENIZE_H */
diff --git a/vp8/decoder/error_concealment.c b/vp8/decoder/error_concealment.c
deleted file mode 100644
index 48f97b565..000000000
--- a/vp8/decoder/error_concealment.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * 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 "error_concealment.h"
-#include "onyxd_int.h"
-#include "decodemv.h"
-#include "vpx_mem/vpx_mem.h"
-#include "vp8/common/recon.h"
-#include "vp8/common/findnearmv.h"
-
-#include <assert.h>
-
-#define MIN(x,y) (((x)<(y))?(x):(y))
-#define MAX(x,y) (((x)>(y))?(x):(y))
-
-#define FLOOR(x,q) ((x) & -(1 << (q)))
-
-#define NUM_NEIGHBORS 20
-
-typedef struct ec_position
-{
- int row;
- int col;
-} EC_POS;
-
-/*
- * Regenerate the table in Matlab with:
- * x = meshgrid((1:4), (1:4));
- * y = meshgrid((1:4), (1:4))';
- * W = round((1./(sqrt(x.^2 + y.^2))*2^7));
- * W(1,1) = 0;
- */
-static const int weights_q7[5][5] = {
- { 0, 128, 64, 43, 32 },
- {128, 91, 57, 40, 31 },
- { 64, 57, 45, 36, 29 },
- { 43, 40, 36, 30, 26 },
- { 32, 31, 29, 26, 23 }
-};
-
-int vp8_alloc_overlap_lists(VP8D_COMP *pbi)
-{
- if (pbi->overlaps != NULL)
- {
- vpx_free(pbi->overlaps);
- pbi->overlaps = NULL;
- }
- pbi->overlaps = vpx_calloc(pbi->common.mb_rows * pbi->common.mb_cols,
- sizeof(MB_OVERLAP));
- if (pbi->overlaps == NULL)
- return -1;
- vpx_memset(pbi->overlaps, 0,
- sizeof(MB_OVERLAP) * pbi->common.mb_rows * pbi->common.mb_cols);
- return 0;
-}
-
-void vp8_de_alloc_overlap_lists(VP8D_COMP *pbi)
-{
- vpx_free(pbi->overlaps);
- pbi->overlaps = NULL;
-}
-
-/* Inserts a new overlap area value to the list of overlaps of a block */
-static void assign_overlap(OVERLAP_NODE* overlaps,
- union b_mode_info *bmi,
- int overlap)
-{
- int i;
- if (overlap <= 0)
- return;
- /* Find and assign to the next empty overlap node in the list of overlaps.
- * Empty is defined as bmi == NULL */
- for (i = 0; i < MAX_OVERLAPS; i++)
- {
- if (overlaps[i].bmi == NULL)
- {
- overlaps[i].bmi = bmi;
- overlaps[i].overlap = overlap;
- break;
- }
- }
-}
-
-/* Calculates the overlap area between two 4x4 squares, where the first
- * square has its upper-left corner at (b1_row, b1_col) and the second
- * square has its upper-left corner at (b2_row, b2_col). Doesn't
- * properly handle squares which do not overlap.
- */
-static int block_overlap(int b1_row, int b1_col, int b2_row, int b2_col)
-{
- const int int_top = MAX(b1_row, b2_row); // top
- const int int_left = MAX(b1_col, b2_col); // left
- /* Since each block is 4x4 pixels, adding 4 (Q3) to the left/top edge
- * gives us the right/bottom edge.
- */
- const int int_right = MIN(b1_col + (4<<3), b2_col + (4<<3)); // right
- const int int_bottom = MIN(b1_row + (4<<3), b2_row + (4<<3)); // bottom
- return (int_bottom - int_top) * (int_right - int_left);
-}
-
-/* Calculates the overlap area for all blocks in a macroblock at position
- * (mb_row, mb_col) in macroblocks, which are being overlapped by a given
- * overlapping block at position (new_row, new_col) (in pixels, Q3). The
- * first block being overlapped in the macroblock has position (first_blk_row,
- * first_blk_col) in blocks relative the upper-left corner of the image.
- */
-static void calculate_overlaps_mb(B_OVERLAP *b_overlaps, union b_mode_info *bmi,
- int new_row, int new_col,
- int mb_row, int mb_col,
- int first_blk_row, int first_blk_col)
-{
- /* Find the blocks within this MB (defined by mb_row, mb_col) which are
- * overlapped by bmi and calculate and assign overlap for each of those
- * blocks. */
-
- /* Block coordinates relative the upper-left block */
- const int rel_ol_blk_row = first_blk_row - mb_row * 4;
- const int rel_ol_blk_col = first_blk_col - mb_col * 4;
- /* If the block partly overlaps any previous MB, these coordinates
- * can be < 0. We don't want to access blocks in previous MBs.
- */
- const int blk_idx = MAX(rel_ol_blk_row,0) * 4 + MAX(rel_ol_blk_col,0);
- /* Upper left overlapping block */
- B_OVERLAP *b_ol_ul = &(b_overlaps[blk_idx]);
-
- /* Calculate and assign overlaps for all blocks in this MB
- * which the motion compensated block overlaps
- */
- /* Avoid calculating overlaps for blocks in later MBs */
- int end_row = MIN(4 + mb_row * 4 - first_blk_row, 2);
- int end_col = MIN(4 + mb_col * 4 - first_blk_col, 2);
- int row, col;
-
- /* Check if new_row and new_col are evenly divisible by 4 (Q3),
- * and if so we shouldn't check neighboring blocks
- */
- if (new_row >= 0 && (new_row & 0x1F) == 0)
- end_row = 1;
- if (new_col >= 0 && (new_col & 0x1F) == 0)
- end_col = 1;
-
- /* Check if the overlapping block partly overlaps a previous MB
- * and if so, we're overlapping fewer blocks in this MB.
- */
- if (new_row < (mb_row*16)<<3)
- end_row = 1;
- if (new_col < (mb_col*16)<<3)
- end_col = 1;
-
- for (row = 0; row < end_row; ++row)
- {
- for (col = 0; col < end_col; ++col)
- {
- /* input in Q3, result in Q6 */
- const int overlap = block_overlap(new_row, new_col,
- (((first_blk_row + row) *
- 4) << 3),
- (((first_blk_col + col) *
- 4) << 3));
- assign_overlap(b_ol_ul[row * 4 + col].overlaps, bmi, overlap);
- }
- }
-}
-
-void vp8_calculate_overlaps(MB_OVERLAP *overlap_ul,
- int mb_rows, int mb_cols,
- union b_mode_info *bmi,
- int b_row, int b_col)
-{
- MB_OVERLAP *mb_overlap;
- int row, col, rel_row, rel_col;
- int new_row, new_col;
- int end_row, end_col;
- int overlap_b_row, overlap_b_col;
- int overlap_mb_row, overlap_mb_col;
-
- /* mb subpixel position */
- row = (4 * b_row) << 3; /* Q3 */
- col = (4 * b_col) << 3; /* Q3 */
-
- /* reverse compensate for motion */
- new_row = row - bmi->mv.as_mv.row;
- new_col = col - bmi->mv.as_mv.col;
-
- if (new_row >= ((16*mb_rows) << 3) || new_col >= ((16*mb_cols) << 3))
- {
- /* the new block ended up outside the frame */
- return;
- }
-
- if (new_row <= (-4 << 3) || new_col <= (-4 << 3))
- {
- /* outside the frame */
- return;
- }
- /* overlapping block's position in blocks */
- overlap_b_row = FLOOR(new_row / 4, 3) >> 3;
- overlap_b_col = FLOOR(new_col / 4, 3) >> 3;
-
- /* overlapping block's MB position in MBs
- * operations are done in Q3
- */
- overlap_mb_row = FLOOR((overlap_b_row << 3) / 4, 3) >> 3;
- overlap_mb_col = FLOOR((overlap_b_col << 3) / 4, 3) >> 3;
-
- end_row = MIN(mb_rows - overlap_mb_row, 2);
- end_col = MIN(mb_cols - overlap_mb_col, 2);
-
- /* Don't calculate overlap for MBs we don't overlap */
- /* Check if the new block row starts at the last block row of the MB */
- if (abs(new_row - ((16*overlap_mb_row) << 3)) < ((3*4) << 3))
- end_row = 1;
- /* Check if the new block col starts at the last block col of the MB */
- if (abs(new_col - ((16*overlap_mb_col) << 3)) < ((3*4) << 3))
- end_col = 1;
-
- /* find the MB(s) this block is overlapping */
- for (rel_row = 0; rel_row < end_row; ++rel_row)
- {
- for (rel_col = 0; rel_col < end_col; ++rel_col)
- {
- if (overlap_mb_row + rel_row < 0 ||
- overlap_mb_col + rel_col < 0)
- continue;
- mb_overlap = overlap_ul + (overlap_mb_row + rel_row) * mb_cols +
- overlap_mb_col + rel_col;
-
- calculate_overlaps_mb(mb_overlap->overlaps, bmi,
- new_row, new_col,
- overlap_mb_row + rel_row,
- overlap_mb_col + rel_col,
- overlap_b_row + rel_row,
- overlap_b_col + rel_col);
- }
- }
-}
-
-/* Estimates a motion vector given the overlapping blocks' motion vectors.
- * Filters out all overlapping blocks which do not refer to the correct
- * reference frame type.
- */
-static void estimate_mv(const OVERLAP_NODE *overlaps, union b_mode_info *bmi)
-{
- int i;
- int overlap_sum = 0;
- int row_acc = 0;
- int col_acc = 0;
-
- bmi->mv.as_int = 0;
- for (i=0; i < MAX_OVERLAPS; ++i)
- {
- if (overlaps[i].bmi == NULL)
- break;
- col_acc += overlaps[i].overlap * overlaps[i].bmi->mv.as_mv.col;
- row_acc += overlaps[i].overlap * overlaps[i].bmi->mv.as_mv.row;
- overlap_sum += overlaps[i].overlap;
- }
- if (overlap_sum > 0)
- {
- /* Q9 / Q6 = Q3 */
- bmi->mv.as_mv.col = col_acc / overlap_sum;
- bmi->mv.as_mv.row = row_acc / overlap_sum;
- }
- else
- {
- bmi->mv.as_mv.col = 0;
- bmi->mv.as_mv.row = 0;
- }
-}
-
-/* Estimates all motion vectors for a macroblock given the lists of
- * overlaps for each block. Decides whether or not the MVs must be clamped.
- */
-static void estimate_mb_mvs(const B_OVERLAP *block_overlaps,
- MODE_INFO *mi,
- int mb_to_left_edge,
- int mb_to_right_edge,
- int mb_to_top_edge,
- int mb_to_bottom_edge)
-{
- int row, col;
- int non_zero_count = 0;
- MV * const filtered_mv = &(mi->mbmi.mv.as_mv);
- union b_mode_info * const bmi = mi->bmi;
- filtered_mv->col = 0;
- filtered_mv->row = 0;
- mi->mbmi.need_to_clamp_mvs = 0;
- for (row = 0; row < 4; ++row)
- {
- int this_b_to_top_edge = mb_to_top_edge + ((row*4)<<3);
- int this_b_to_bottom_edge = mb_to_bottom_edge - ((row*4)<<3);
- for (col = 0; col < 4; ++col)
- {
- int i = row * 4 + col;
- int this_b_to_left_edge = mb_to_left_edge + ((col*4)<<3);
- int this_b_to_right_edge = mb_to_right_edge - ((col*4)<<3);
- /* Estimate vectors for all blocks which are overlapped by this */
- /* type. Interpolate/extrapolate the rest of the block's MVs */
- estimate_mv(block_overlaps[i].overlaps, &(bmi[i]));
- mi->mbmi.need_to_clamp_mvs |= vp8_check_mv_bounds(
- &bmi[i].mv,
- this_b_to_left_edge,
- this_b_to_right_edge,
- this_b_to_top_edge,
- this_b_to_bottom_edge);
- if (bmi[i].mv.as_int != 0)
- {
- ++non_zero_count;
- filtered_mv->col += bmi[i].mv.as_mv.col;
- filtered_mv->row += bmi[i].mv.as_mv.row;
- }
- }
- }
- if (non_zero_count > 0)
- {
- filtered_mv->col /= non_zero_count;
- filtered_mv->row /= non_zero_count;
- }
-}
-
-static void calc_prev_mb_overlaps(MB_OVERLAP *overlaps, MODE_INFO *prev_mi,
- int mb_row, int mb_col,
- int mb_rows, int mb_cols)
-{
- int sub_row;
- int sub_col;
- for (sub_row = 0; sub_row < 4; ++sub_row)
- {
- for (sub_col = 0; sub_col < 4; ++sub_col)
- {
- vp8_calculate_overlaps(
- overlaps, mb_rows, mb_cols,
- &(prev_mi->bmi[sub_row * 4 + sub_col]),
- 4 * mb_row + sub_row,
- 4 * mb_col + sub_col);
- }
- }
-}
-
-/* Estimate all missing motion vectors. This function does the same as the one
- * above, but has different input arguments. */
-static void estimate_missing_mvs(MB_OVERLAP *overlaps,
- MODE_INFO *mi, MODE_INFO *prev_mi,
- int mb_rows, int mb_cols,
- unsigned int first_corrupt)
-{
- int mb_row, mb_col;
- vpx_memset(overlaps, 0, sizeof(MB_OVERLAP) * mb_rows * mb_cols);
- /* First calculate the overlaps for all blocks */
- for (mb_row = 0; mb_row < mb_rows; ++mb_row)
- {
- for (mb_col = 0; mb_col < mb_cols; ++mb_col)
- {
- /* We're only able to use blocks referring to the last frame
- * when extrapolating new vectors.
- */
- if (prev_mi->mbmi.ref_frame == LAST_FRAME)
- {
- calc_prev_mb_overlaps(overlaps, prev_mi,
- mb_row, mb_col,
- mb_rows, mb_cols);
- }
- ++prev_mi;
- }
- ++prev_mi;
- }
-
- mb_row = first_corrupt / mb_cols;
- mb_col = first_corrupt - mb_row * mb_cols;
- mi += mb_row*(mb_cols + 1) + mb_col;
- /* Go through all macroblocks in the current image with missing MVs
- * and calculate new MVs using the overlaps.
- */
- for (; mb_row < mb_rows; ++mb_row)
- {
- int mb_to_top_edge = -((mb_row * 16)) << 3;
- int mb_to_bottom_edge = ((mb_rows - 1 - mb_row) * 16) << 3;
- for (; mb_col < mb_cols; ++mb_col)
- {
- int mb_to_left_edge = -((mb_col * 16) << 3);
- int mb_to_right_edge = ((mb_cols - 1 - mb_col) * 16) << 3;
- const B_OVERLAP *block_overlaps =
- overlaps[mb_row*mb_cols + mb_col].overlaps;
- mi->mbmi.ref_frame = LAST_FRAME;
- mi->mbmi.mode = SPLITMV;
- mi->mbmi.uv_mode = DC_PRED;
- mi->mbmi.partitioning = 3;
- mi->mbmi.segment_id = 0;
- estimate_mb_mvs(block_overlaps,
- mi,
- mb_to_left_edge,
- mb_to_right_edge,
- mb_to_top_edge,
- mb_to_bottom_edge);
- ++mi;
- }
- mb_col = 0;
- ++mi;
- }
-}
-
-void vp8_estimate_missing_mvs(VP8D_COMP *pbi)
-{
- VP8_COMMON * const pc = &pbi->common;
- estimate_missing_mvs(pbi->overlaps,
- pc->mi, pc->prev_mi,
- pc->mb_rows, pc->mb_cols,
- pbi->mvs_corrupt_from_mb);
-}
-
-static void assign_neighbor(EC_BLOCK *neighbor, MODE_INFO *mi, int block_idx)
-{
- assert(mi->mbmi.ref_frame < MAX_REF_FRAMES);
- neighbor->ref_frame = mi->mbmi.ref_frame;
- neighbor->mv = mi->bmi[block_idx].mv.as_mv;
-}
-
-/* Finds the neighboring blocks of a macroblocks. In the general case
- * 20 blocks are found. If a fewer number of blocks are found due to
- * image boundaries, those positions in the EC_BLOCK array are left "empty".
- * The neighbors are enumerated with the upper-left neighbor as the first
- * element, the second element refers to the neighbor to right of the previous
- * neighbor, and so on. The last element refers to the neighbor below the first
- * neighbor.
- */
-static void find_neighboring_blocks(MODE_INFO *mi,
- EC_BLOCK *neighbors,
- int mb_row, int mb_col,
- int mb_rows, int mb_cols,
- int mi_stride)
-{
- int i = 0;
- int j;
- if (mb_row > 0)
- {
- /* upper left */
- if (mb_col > 0)
- assign_neighbor(&neighbors[i], mi - mi_stride - 1, 15);
- ++i;
- /* above */
- for (j = 12; j < 16; ++j, ++i)
- assign_neighbor(&neighbors[i], mi - mi_stride, j);
- }
- else
- i += 5;
- if (mb_col < mb_cols - 1)
- {
- /* upper right */
- if (mb_row > 0)
- assign_neighbor(&neighbors[i], mi - mi_stride + 1, 12);
- ++i;
- /* right */
- for (j = 0; j <= 12; j += 4, ++i)
- assign_neighbor(&neighbors[i], mi + 1, j);
- }
- else
- i += 5;
- if (mb_row < mb_rows - 1)
- {
- /* lower right */
- if (mb_col < mb_cols - 1)
- assign_neighbor(&neighbors[i], mi + mi_stride + 1, 0);
- ++i;
- /* below */
- for (j = 0; j < 4; ++j, ++i)
- assign_neighbor(&neighbors[i], mi + mi_stride, j);
- }
- else
- i += 5;
- if (mb_col > 0)
- {
- /* lower left */
- if (mb_row < mb_rows - 1)
- assign_neighbor(&neighbors[i], mi + mi_stride - 1, 4);
- ++i;
- /* left */
- for (j = 3; j < 16; j += 4, ++i)
- {
- assign_neighbor(&neighbors[i], mi - 1, j);
- }
- }
- else
- i += 5;
- assert(i == 20);
-}
-
-/* Calculates which reference frame type is dominating among the neighbors */
-static MV_REFERENCE_FRAME dominant_ref_frame(EC_BLOCK *neighbors)
-{
- /* Default to referring to "skip" */
- MV_REFERENCE_FRAME dom_ref_frame = LAST_FRAME;
- int max_ref_frame_cnt = 0;
- int ref_frame_cnt[MAX_REF_FRAMES] = {0};
- int i;
- /* Count neighboring reference frames */
- for (i = 0; i < NUM_NEIGHBORS; ++i)
- {
- if (neighbors[i].ref_frame < MAX_REF_FRAMES &&
- neighbors[i].ref_frame != INTRA_FRAME)
- ++ref_frame_cnt[neighbors[i].ref_frame];
- }
- /* Find maximum */
- for (i = 0; i < MAX_REF_FRAMES; ++i)
- {
- if (ref_frame_cnt[i] > max_ref_frame_cnt)
- {
- dom_ref_frame = i;
- max_ref_frame_cnt = ref_frame_cnt[i];
- }
- }
- return dom_ref_frame;
-}
-
-/* Interpolates all motion vectors for a macroblock from the neighboring blocks'
- * motion vectors.
- */
-static void interpolate_mvs(MACROBLOCKD *mb,
- EC_BLOCK *neighbors,
- MV_REFERENCE_FRAME dom_ref_frame)
-{
- int row, col, i;
- MODE_INFO * const mi = mb->mode_info_context;
- /* Table with the position of the neighboring blocks relative the position
- * of the upper left block of the current MB. Starting with the upper left
- * neighbor and going to the right.
- */
- const EC_POS neigh_pos[NUM_NEIGHBORS] = {
- {-1,-1}, {-1,0}, {-1,1}, {-1,2}, {-1,3},
- {-1,4}, {0,4}, {1,4}, {2,4}, {3,4},
- {4,4}, {4,3}, {4,2}, {4,1}, {4,0},
- {4,-1}, {3,-1}, {2,-1}, {1,-1}, {0,-1}
- };
- mi->mbmi.need_to_clamp_mvs = 0;
- for (row = 0; row < 4; ++row)
- {
- int mb_to_top_edge = mb->mb_to_top_edge + ((row*4)<<3);
- int mb_to_bottom_edge = mb->mb_to_bottom_edge - ((row*4)<<3);
- for (col = 0; col < 4; ++col)
- {
- int mb_to_left_edge = mb->mb_to_left_edge + ((col*4)<<3);
- int mb_to_right_edge = mb->mb_to_right_edge - ((col*4)<<3);
- int w_sum = 0;
- int mv_row_sum = 0;
- int mv_col_sum = 0;
- int_mv * const mv = &(mi->bmi[row*4 + col].mv);
- mv->as_int = 0;
- for (i = 0; i < NUM_NEIGHBORS; ++i)
- {
- /* Calculate the weighted sum of neighboring MVs referring
- * to the dominant frame type.
- */
- const int w = weights_q7[abs(row - neigh_pos[i].row)]
- [abs(col - neigh_pos[i].col)];
- if (neighbors[i].ref_frame != dom_ref_frame)
- continue;
- w_sum += w;
- /* Q7 * Q3 = Q10 */
- mv_row_sum += w*neighbors[i].mv.row;
- mv_col_sum += w*neighbors[i].mv.col;
- }
- if (w_sum > 0)
- {
- /* Avoid division by zero.
- * Normalize with the sum of the coefficients
- * Q3 = Q10 / Q7
- */
- mv->as_mv.row = mv_row_sum / w_sum;
- mv->as_mv.col = mv_col_sum / w_sum;
- mi->mbmi.need_to_clamp_mvs |= vp8_check_mv_bounds(
- mv,
- mb_to_left_edge,
- mb_to_right_edge,
- mb_to_top_edge,
- mb_to_bottom_edge);
- }
- }
- }
-}
-
-void vp8_interpolate_motion(MACROBLOCKD *mb,
- int mb_row, int mb_col,
- int mb_rows, int mb_cols,
- int mi_stride)
-{
- /* Find relevant neighboring blocks */
- EC_BLOCK neighbors[NUM_NEIGHBORS];
- MV_REFERENCE_FRAME dom_ref_frame;
- int i;
- /* Initialize the array. MAX_REF_FRAMES is interpreted as "doesn't exist" */
- for (i = 0; i < NUM_NEIGHBORS; ++i)
- {
- neighbors[i].ref_frame = MAX_REF_FRAMES;
- neighbors[i].mv.row = neighbors[i].mv.col = 0;
- }
- find_neighboring_blocks(mb->mode_info_context,
- neighbors,
- mb_row, mb_col,
- mb_rows, mb_cols,
- mb->mode_info_stride);
- /* Determine the dominant block type */
- dom_ref_frame = dominant_ref_frame(neighbors);
- /* Interpolate MVs for the missing blocks
- * from the dominating MVs */
- interpolate_mvs(mb, neighbors, dom_ref_frame);
-
- mb->mode_info_context->mbmi.ref_frame = dom_ref_frame;
- mb->mode_info_context->mbmi.mode = SPLITMV;
- mb->mode_info_context->mbmi.uv_mode = DC_PRED;
- mb->mode_info_context->mbmi.partitioning = 3;
- mb->mode_info_context->mbmi.segment_id = 0;
-}
-
-void vp8_conceal_corrupt_mb(MACROBLOCKD *xd)
-{
- /* This macroblock has corrupt residual, use the motion compensated
- image (predictor) for concealment */
- vp8_recon_copy16x16(xd->predictor, 16, xd->dst.y_buffer, xd->dst.y_stride);
- vp8_recon_copy8x8(xd->predictor + 256, 8,
- xd->dst.u_buffer, xd->dst.uv_stride);
- vp8_recon_copy8x8(xd->predictor + 320, 8,
- xd->dst.v_buffer, xd->dst.uv_stride);
-}
diff --git a/vp8/decoder/error_concealment.h b/vp8/decoder/error_concealment.h
deleted file mode 100644
index 65ae9d9be..000000000
--- a/vp8/decoder/error_concealment.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 ERROR_CONCEALMENT_H
-#define ERROR_CONCEALMENT_H
-
-#include "onyxd_int.h"
-#include "ec_types.h"
-
-/* Allocate memory for the overlap lists */
-int vp8_alloc_overlap_lists(VP8D_COMP *pbi);
-
-/* Deallocate the overlap lists */
-void vp8_de_alloc_overlap_lists(VP8D_COMP *pbi);
-
-/* Estimate all missing motion vectors. */
-void vp8_estimate_missing_mvs(VP8D_COMP *pbi);
-
-/* Functions for spatial MV interpolation */
-
-/* Interpolates all motion vectors for a macroblock mb at position
- * (mb_row, mb_col). */
-void vp8_interpolate_motion(MACROBLOCKD *mb,
- int mb_row, int mb_col,
- int mb_rows, int mb_cols,
- int mi_stride);
-
-/* Conceal a macroblock with corrupt residual.
- * Copies the prediction signal to the reconstructed image.
- */
-void vp8_conceal_corrupt_mb(MACROBLOCKD *xd);
-
-#endif
diff --git a/vp8/decoder/generic/dsystemdependent.c b/vp8/decoder/generic/dsystemdependent.c
index 0325fdf1c..fbba1b50a 100644
--- a/vp8/decoder/generic/dsystemdependent.c
+++ b/vp8/decoder/generic/dsystemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/decoder/dequantize.h"
#include "vp8/decoder/onyxd_int.h"
@@ -21,6 +21,12 @@ void vp8_dmachine_specific_config(VP8D_COMP *pbi)
/* Pure C: */
#if CONFIG_RUNTIME_CPU_DETECT
pbi->mb.rtcd = &pbi->common.rtcd;
+ pbi->dequant.block_2x2 = vp8_dequantize_b_2x2_c;
+ pbi->dequant.idct_add_8x8 = vp8_dequant_idct_add_8x8_c;
+ pbi->dequant.dc_idct_add_8x8 = vp8_dequant_dc_idct_add_8x8_c;
+ pbi->dequant.dc_idct_add_y_block_8x8 = vp8_dequant_dc_idct_add_y_block_8x8_c;
+ pbi->dequant.idct_add_y_block_8x8 = vp8_dequant_idct_add_y_block_8x8_c;
+ pbi->dequant.idct_add_uv_block_8x8 = vp8_dequant_idct_add_uv_block_8x8_c;
pbi->dequant.block = vp8_dequantize_b_c;
pbi->dequant.idct_add = vp8_dequant_idct_add_c;
pbi->dequant.dc_idct_add = vp8_dequant_dc_idct_add_c;
@@ -38,11 +44,9 @@ void vp8_dmachine_specific_config(VP8D_COMP *pbi)
vp8_arch_arm_decode_init(pbi);
#endif
-#if CONFIG_EXTEND_QRANGE
pbi->dequant.idct_add = vp8_dequant_idct_add_c;
pbi->dequant.dc_idct_add = vp8_dequant_dc_idct_add_c;
pbi->dequant.dc_idct_add_y_block = vp8_dequant_dc_idct_add_y_block_c;
pbi->dequant.idct_add_y_block = vp8_dequant_idct_add_y_block_c;
pbi->dequant.idct_add_uv_block = vp8_dequant_idct_add_uv_block_c;
-#endif
}
diff --git a/vp8/decoder/idct_blk.c b/vp8/decoder/idct_blk.c
index 04bce665e..16ac46c48 100644
--- a/vp8/decoder/idct_blk.c
+++ b/vp8/decoder/idct_blk.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "dequantize.h"
@@ -122,3 +122,45 @@ void vp8_dequant_idct_add_uv_block_c
dstv += 4*stride - 8;
}
}
+
+
+void vp8_dequant_dc_idct_add_y_block_8x8_c
+ (short *q, short *dq, unsigned char *pre,
+ unsigned char *dst, int stride, char *eobs, short *dc, MACROBLOCKD *xd)
+{
+
+ vp8_dequant_dc_idct_add_8x8_c (q, dq, pre, dst, 16, stride, dc[0]);
+ vp8_dequant_dc_idct_add_8x8_c (&q[64], dq, pre+8, dst+8, 16, stride, dc[1]);
+ vp8_dequant_dc_idct_add_8x8_c (&q[128], dq, pre+8*16, dst+8*stride, 16, stride, dc[4]);
+ vp8_dequant_dc_idct_add_8x8_c (&q[192], dq, pre+8*16+8, dst+8*stride+8, 16, stride, dc[8]);
+
+}
+
+void vp8_dequant_idct_add_y_block_8x8_c
+ (short *q, short *dq, unsigned char *pre,
+ unsigned char *dst, int stride, char *eobs, MACROBLOCKD *xd)
+{
+
+
+ unsigned char *origdest = dst;
+ unsigned char *origpred = pre;
+
+ vp8_dequant_idct_add_8x8_c (q, dq, pre, dst, 16, stride);
+ vp8_dequant_idct_add_8x8_c (&q[64], dq, origpred+8, origdest+8, 16, stride);
+ vp8_dequant_idct_add_8x8_c (&q[128], dq, origpred+8*16, origdest+8*stride, 16, stride);
+ vp8_dequant_idct_add_8x8_c (&q[192], dq, origpred+8*16+8, origdest+8*stride+8, 16, stride);
+
+}
+
+void vp8_dequant_idct_add_uv_block_8x8_c
+ (short *q, short *dq, unsigned char *pre,
+ unsigned char *dstu, unsigned char *dstv, int stride, char *eobs, MACROBLOCKD *xd)
+{
+ vp8_dequant_idct_add_8x8_c (q, dq, pre, dstu, 8, stride);
+
+ q += 64;
+ pre += 64;
+
+ vp8_dequant_idct_add_8x8_c (q, dq, pre, dstv, 8, stride);
+}
+
diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c
index 357684ab9..96649b9e6 100644
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -21,8 +21,6 @@
#include "vp8/common/loopfilter.h"
#include "vp8/common/swapyv12buffer.h"
#include "vp8/common/g_common.h"
-#include "vp8/common/threading.h"
-#include "decoderthreading.h"
#include <stdio.h>
#include <assert.h>
@@ -31,9 +29,6 @@
#include "vp8/common/systemdependent.h"
#include "vpx_ports/vpx_timer.h"
#include "detokenize.h"
-#if CONFIG_ERROR_CONCEALMENT
-#include "error_concealment.h"
-#endif
#if ARCH_ARM
#include "vpx_ports/arm.h"
#endif
@@ -43,6 +38,79 @@ extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
static int get_free_fb (VP8_COMMON *cm);
static void ref_cnt_fb (int *buf, int *idx, int new_idx);
+#if CONFIG_DEBUG
+void vp8_recon_write_yuv_frame(char *name, YV12_BUFFER_CONFIG *s)
+{
+ FILE *yuv_file = fopen((char *)name, "ab");
+ unsigned char *src = s->y_buffer;
+ int h = s->y_height;
+
+ do
+ {
+ fwrite(src, s->y_width, 1, yuv_file);
+ src += s->y_stride;
+ }
+ while (--h);
+
+ src = s->u_buffer;
+ h = s->uv_height;
+
+ do
+ {
+ fwrite(src, s->uv_width, 1, yuv_file);
+ src += s->uv_stride;
+ }
+ while (--h);
+
+ src = s->v_buffer;
+ h = s->uv_height;
+
+ do
+ {
+ fwrite(src, s->uv_width, 1, yuv_file);
+ src += s->uv_stride;
+ }
+ while (--h);
+
+ fclose(yuv_file);
+}
+#endif
+//#define WRITE_RECON_BUFFER 1
+#if WRITE_RECON_BUFFER
+void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
+{
+
+ // write the frame
+ FILE *yframe;
+ int i;
+ char filename[255];
+
+ sprintf(filename, "dx\\y%04d.raw", this_frame);
+ yframe = fopen(filename, "wb");
+
+ for (i = 0; i < frame->y_height; i++)
+ fwrite(frame->y_buffer + i * frame->y_stride,
+ frame->y_width, 1, yframe);
+
+ fclose(yframe);
+ sprintf(filename, "dx\\u%04d.raw", this_frame);
+ yframe = fopen(filename, "wb");
+
+ for (i = 0; i < frame->uv_height; i++)
+ fwrite(frame->u_buffer + i * frame->uv_stride,
+ frame->uv_width, 1, yframe);
+
+ fclose(yframe);
+ sprintf(filename, "dx\\v%04d.raw", this_frame);
+ yframe = fopen(filename, "wb");
+
+ for (i = 0; i < frame->uv_height; i++)
+ fwrite(frame->v_buffer + i * frame->uv_stride,
+ frame->uv_width, 1, yframe);
+
+ fclose(yframe);
+}
+#endif
void vp8dx_initialize()
{
@@ -51,12 +119,12 @@ void vp8dx_initialize()
if (!init_done)
{
vp8_initialize_common();
+ vp8_init_quant_tables();
vp8_scale_machine_specific_config();
init_done = 1;
}
}
-
VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
{
VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP));
@@ -82,11 +150,6 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
pbi->common.current_video_frame = 0;
pbi->ready_for_new_data = 1;
-#if CONFIG_MULTITHREAD
- pbi->max_threads = oxcf->max_threads;
- vp8_decoder_create_threads(pbi);
-#endif
-
/* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
* unnecessary calling of vp8cx_init_de_quantizer() for every frame.
*/
@@ -96,30 +159,11 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
pbi->common.error.setjmp = 0;
-#if CONFIG_ERROR_CONCEALMENT
- pbi->ec_enabled = oxcf->error_concealment;
-#else
- pbi->ec_enabled = 0;
-#endif
- /* Error concealment is activated after a key frame has been
- * decoded without errors when error concealment is enabled.
- */
- pbi->ec_active = 0;
-
pbi->decoded_key_frame = 0;
- pbi->input_partition = oxcf->input_partition;
-
- /* Independent partitions is activated when a frame updates the
- * token probability table to have equal probabilities over the
- * PREV_COEF context.
- */
- pbi->independent_partitions = 0;
-
return (VP8D_PTR) pbi;
}
-
void vp8dx_remove_decompressor(VP8D_PTR ptr)
{
VP8D_COMP *pbi = (VP8D_COMP *) ptr;
@@ -127,14 +171,10 @@ void vp8dx_remove_decompressor(VP8D_PTR ptr)
if (!pbi)
return;
-#if CONFIG_MULTITHREAD
- if (pbi->b_multithreaded_rd)
- vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
- vp8_decoder_remove_threads(pbi);
-#endif
-#if CONFIG_ERROR_CONCEALMENT
- vp8_de_alloc_overlap_lists(pbi);
-#endif
+ // Delete sementation map
+ if (pbi->common.last_frame_seg_map != 0)
+ vpx_free(pbi->common.last_frame_seg_map);
+
vp8_remove_common(&pbi->common);
vpx_free(pbi->mbc);
vpx_free(pbi);
@@ -300,6 +340,22 @@ static int swap_frame_buffers (VP8_COMMON *cm)
return err;
}
+/*
+static void vp8_print_yuv_rec_mb(VP8_COMMON *cm, int mb_row, int mb_col)
+{
+ YV12_BUFFER_CONFIG *s = cm->frame_to_show;
+ unsigned char *src = s->y_buffer;
+ int i, j;
+
+ printf("After loop filter\n");
+ for (i=0;i<16;i++) {
+ for (j=0;j<16;j++)
+ printf("%3d ", src[(mb_row*16+i)*s->y_stride + mb_col*16+j]);
+ printf("\n");
+ }
+}
+*/
+
int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, int64_t time_stamp)
{
#if HAVE_ARMV7
@@ -319,115 +375,55 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
pbi->common.error.error_code = VPX_CODEC_OK;
- if (pbi->input_partition && !(source == NULL && size == 0))
+ pbi->Source = source;
+ pbi->source_sz = size;
+
+ if (pbi->source_sz == 0)
{
- /* Store a pointer to this partition and return. We haven't
- * received the complete frame yet, so we will wait with decoding.
- */
- assert(pbi->num_partitions < MAX_PARTITIONS);
- pbi->partitions[pbi->num_partitions] = source;
- pbi->partition_sizes[pbi->num_partitions] = size;
- pbi->source_sz += size;
- pbi->num_partitions++;
- if (pbi->num_partitions > (1 << EIGHT_PARTITION) + 1)
- {
- pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
- pbi->common.error.setjmp = 0;
- pbi->num_partitions = 0;
- return -1;
- }
- return 0;
+ /* This is used to signal that we are missing frames.
+ * We do not know if the missing frame(s) was supposed to update
+ * any of the reference buffers, but we act conservative and
+ * mark only the last buffer as corrupted.
+ */
+ cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
}
- else
- {
- if (!pbi->input_partition)
- {
- pbi->Source = source;
- pbi->source_sz = size;
- }
- else
- {
- assert(pbi->common.multi_token_partition <= EIGHT_PARTITION);
- if (pbi->num_partitions == 0)
- {
- pbi->num_partitions = 1;
- pbi->partitions[0] = NULL;
- pbi->partition_sizes[0] = 0;
- }
- while (pbi->num_partitions < (1 << pbi->common.multi_token_partition) + 1)
- {
- // Reset all missing partitions
- pbi->partitions[pbi->num_partitions] =
- pbi->partitions[pbi->num_partitions - 1] +
- pbi->partition_sizes[pbi->num_partitions - 1];
- pbi->partition_sizes[pbi->num_partitions] = 0;
- pbi->num_partitions++;
- }
- }
-
- if (pbi->source_sz == 0)
- {
- /* This is used to signal that we are missing frames.
- * We do not know if the missing frame(s) was supposed to update
- * any of the reference buffers, but we act conservative and
- * mark only the last buffer as corrupted.
- */
- cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
-
- /* If error concealment is disabled we won't signal missing frames to
- * the decoder.
- */
- if (!pbi->ec_active)
- {
- /* Signal that we have no frame to show. */
- cm->show_frame = 0;
-
- pbi->num_partitions = 0;
-
- /* Nothing more to do. */
- return 0;
- }
- }
#if HAVE_ARMV7
#if CONFIG_RUNTIME_CPU_DETECT
- if (cm->rtcd.flags & HAS_NEON)
+ if (cm->rtcd.flags & HAS_NEON)
#endif
- {
- vp8_push_neon(dx_store_reg);
- }
+ {
+ vp8_push_neon(dx_store_reg);
+ }
#endif
- cm->new_fb_idx = get_free_fb (cm);
+ cm->new_fb_idx = get_free_fb (cm);
- if (setjmp(pbi->common.error.jmp))
- {
+ if (setjmp(pbi->common.error.jmp))
+ {
#if HAVE_ARMV7
#if CONFIG_RUNTIME_CPU_DETECT
- if (cm->rtcd.flags & HAS_NEON)
+ if (cm->rtcd.flags & HAS_NEON)
#endif
- {
- vp8_pop_neon(dx_store_reg);
- }
+ {
+ vp8_pop_neon(dx_store_reg);
+ }
#endif
- pbi->common.error.setjmp = 0;
-
- pbi->num_partitions = 0;
+ pbi->common.error.setjmp = 0;
- /* We do not know if the missing frame(s) was supposed to update
- * any of the reference buffers, but we act conservative and
- * mark only the last buffer as corrupted.
- */
- cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
+ /* We do not know if the missing frame(s) was supposed to update
+ * any of the reference buffers, but we act conservative and
+ * mark only the last buffer as corrupted.
+ */
+ cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
- if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
- cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
- return -1;
- }
-
- pbi->common.error.setjmp = 1;
+ if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
+ cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+ return -1;
}
+ pbi->common.error.setjmp = 1;
+
retcode = vp8_decode_frame(pbi);
if (retcode < 0)
@@ -442,14 +438,11 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif
pbi->common.error.error_code = VPX_CODEC_ERROR;
pbi->common.error.setjmp = 0;
- pbi->num_partitions = 0;
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
return retcode;
}
-#if CONFIG_MULTITHREAD
- if (pbi->b_multithreaded_rd && cm->multi_token_partition != ONE_PARTITION)
{
if (swap_frame_buffers (cm))
{
@@ -463,27 +456,17 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif
pbi->common.error.error_code = VPX_CODEC_ERROR;
pbi->common.error.setjmp = 0;
- pbi->num_partitions = 0;
return -1;
}
- } else
-#endif
- {
- if (swap_frame_buffers (cm))
- {
-#if HAVE_ARMV7
-#if CONFIG_RUNTIME_CPU_DETECT
- if (cm->rtcd.flags & HAS_NEON)
-#endif
- {
- vp8_pop_neon(dx_store_reg);
- }
+
+#if WRITE_RECON_BUFFER
+ if(cm->show_frame)
+ write_dx_frame_to_file(cm->frame_to_show,
+ cm->current_video_frame);
+ else
+ write_dx_frame_to_file(cm->frame_to_show,
+ cm->current_video_frame+1000);
#endif
- pbi->common.error.error_code = VPX_CODEC_ERROR;
- pbi->common.error.setjmp = 0;
- pbi->num_partitions = 0;
- return -1;
- }
if(cm->filter_level)
{
@@ -493,30 +476,22 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
}
+#if CONFIG_DEBUG
+ vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);
+#endif
vp8_clear_system_state();
-#if CONFIG_ERROR_CONCEALMENT
- /* swap the mode infos to storage for future error concealment */
- if (pbi->ec_enabled && pbi->common.prev_mi)
+ if(cm->show_frame)
{
- const MODE_INFO* tmp = pbi->common.prev_mi;
- int row, col;
- pbi->common.prev_mi = pbi->common.mi;
- pbi->common.mi = tmp;
-
- /* Propagate the segment_ids to the next frame */
- for (row = 0; row < pbi->common.mb_rows; ++row)
- {
- for (col = 0; col < pbi->common.mb_cols; ++col)
- {
- const int i = row*pbi->common.mode_info_stride + col;
- pbi->common.mi[i].mbmi.segment_id =
- pbi->common.prev_mi[i].mbmi.segment_id;
- }
- }
+ vpx_memcpy(cm->prev_mip, cm->mip,
+ (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
+ }
+ else
+ {
+ vpx_memset(cm->prev_mip, 0,
+ (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
}
-#endif
/*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
@@ -525,7 +500,6 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
pbi->ready_for_new_data = 0;
pbi->last_time_stamp = time_stamp;
- pbi->num_partitions = 0;
pbi->source_sz = 0;
#if 0
diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h
index a84f16914..289808e28 100644
--- a/vp8/decoder/onyxd_int.h
+++ b/vp8/decoder/onyxd_int.h
@@ -11,15 +11,13 @@
#ifndef __INC_VP8D_INT_H
#define __INC_VP8D_INT_H
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/onyxd.h"
#include "treereader.h"
#include "vp8/common/onyxc_int.h"
-#include "vp8/common/threading.h"
#include "dequantize.h"
-#if CONFIG_ERROR_CONCEALMENT
-#include "ec_types.h"
-#endif
+
+//#define DEC_DEBUG
typedef struct
{
@@ -45,10 +43,12 @@ typedef struct
typedef struct
{
int const *scan;
+ int const *scan_8x8;
UINT8 const *ptr_block2leftabove;
vp8_tree_index const *vp8_coef_tree_ptr;
unsigned char *norm_ptr;
UINT8 *ptr_coef_bands_x;
+ UINT8 *ptr_coef_bands_x_8x8;
ENTROPY_CONTEXT_PLANES *A;
ENTROPY_CONTEXT_PLANES *L;
@@ -57,6 +57,7 @@ typedef struct
BOOL_DECODER *current_bc;
vp8_prob const *coef_probs[4];
+ vp8_prob const *coef_probs_8x8[4];
UINT8 eob[25];
@@ -75,38 +76,6 @@ typedef struct VP8Decompressor
const unsigned char *Source;
unsigned int source_sz;
- const unsigned char *partitions[MAX_PARTITIONS];
- unsigned int partition_sizes[MAX_PARTITIONS];
- unsigned int num_partitions;
-
-#if CONFIG_MULTITHREAD
- /* variable for threading */
-
- volatile int b_multithreaded_rd;
- int max_threads;
- int current_mb_col_main;
- int decoding_thread_count;
- int allocated_decoding_thread_count;
-
- int mt_baseline_filter_level[MAX_MB_SEGMENTS];
- int sync_range;
- int *mt_current_mb_col; /* Each row remembers its already decoded column. */
-
- unsigned char **mt_yabove_row; /* mb_rows x width */
- unsigned char **mt_uabove_row;
- unsigned char **mt_vabove_row;
- unsigned char **mt_yleft_col; /* mb_rows x 16 */
- unsigned char **mt_uleft_col; /* mb_rows x 8 */
- unsigned char **mt_vleft_col; /* mb_rows x 8 */
-
- MB_ROW_DEC *mb_row_di;
- DECODETHREAD_DATA *de_thread_data;
-
- pthread_t *h_decoding_thread;
- sem_t *h_event_start_decoding;
- sem_t h_event_end_decoding;
- /* end of threading data */
-#endif
vp8_reader *mbc;
int64_t last_time_stamp;
@@ -120,23 +89,9 @@ typedef struct VP8Decompressor
vp8_dequant_rtcd_vtable_t dequant;
#endif
-
- vp8_prob prob_intra;
- vp8_prob prob_last;
- vp8_prob prob_gf;
vp8_prob prob_skip_false;
-#if CONFIG_ERROR_CONCEALMENT
- MB_OVERLAP *overlaps;
- /* the mb num from which modes and mvs (first partition) are corrupt */
- unsigned int mvs_corrupt_from_mb;
-#endif
- int ec_enabled;
- int ec_active;
- int input_partition;
int decoded_key_frame;
- int independent_partitions;
- int frame_corrupt_residual;
} VP8D_COMP;
diff --git a/vp8/decoder/reconintra_mt.c b/vp8/decoder/reconintra_mt.c
index 9bba5b75f..b9d2b3703 100644
--- a/vp8/decoder/reconintra_mt.c
+++ b/vp8/decoder/reconintra_mt.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/recon.h"
#include "vp8/common/reconintra.h"
#include "vpx_mem/vpx_mem.h"
diff --git a/vp8/decoder/reconintra_mt.h b/vp8/decoder/reconintra_mt.h
index d401295b2..b04537956 100644
--- a/vp8/decoder/reconintra_mt.h
+++ b/vp8/decoder/reconintra_mt.h
@@ -12,15 +12,4 @@
#ifndef __INC_RECONINTRA_MT_H
#define __INC_RECONINTRA_MT_H
-/* reconintra functions used in multi-threaded decoder */
-#if CONFIG_MULTITHREAD
-extern void vp8mt_build_intra_predictors_mby(VP8D_COMP *pbi, MACROBLOCKD *x, int mb_row, int mb_col);
-extern void vp8mt_build_intra_predictors_mby_s(VP8D_COMP *pbi, MACROBLOCKD *x, int mb_row, int mb_col);
-extern void vp8mt_build_intra_predictors_mbuv(VP8D_COMP *pbi, MACROBLOCKD *x, int mb_row, int mb_col);
-extern void vp8mt_build_intra_predictors_mbuv_s(VP8D_COMP *pbi, MACROBLOCKD *x, int mb_row, int mb_col);
-
-extern void vp8mt_predict_intra4x4(VP8D_COMP *pbi, MACROBLOCKD *x, int b_mode, unsigned char *predictor, int mb_row, int mb_col, int num);
-extern void vp8mt_intra_prediction_down_copy(VP8D_COMP *pbi, MACROBLOCKD *x, int mb_row, int mb_col);
-#endif
-
#endif
diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c
deleted file mode 100644
index bfe09735c..000000000
--- a/vp8/decoder/threading.c
+++ /dev/null
@@ -1,1003 +0,0 @@
-/*
- * 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.
- */
-
-
-#if !defined(WIN32) && CONFIG_OS_SUPPORT == 1
-# include <unistd.h>
-#endif
-#include "onyxd_int.h"
-#include "vpx_mem/vpx_mem.h"
-#include "vp8/common/threading.h"
-
-#include "vp8/common/loopfilter.h"
-#include "vp8/common/extend.h"
-#include "vpx_ports/vpx_timer.h"
-#include "detokenize.h"
-#include "vp8/common/reconinter.h"
-#include "reconintra_mt.h"
-#if CONFIG_ERROR_CONCEALMENT
-#include "error_concealment.h"
-#endif
-
-extern void mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd);
-
-#if CONFIG_RUNTIME_CPU_DETECT
-#define RTCD_VTABLE(x) (&(pbi)->common.rtcd.x)
-#else
-#define RTCD_VTABLE(x) NULL
-#endif
-
-static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC *mbrd, int count)
-{
- VP8_COMMON *const pc = & pbi->common;
- int i, j;
-
- for (i = 0; i < count; i++)
- {
- MACROBLOCKD *mbd = &mbrd[i].mbd;
-#if CONFIG_RUNTIME_CPU_DETECT
- mbd->rtcd = xd->rtcd;
-#endif
- mbd->subpixel_predict = xd->subpixel_predict;
- mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;
- mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;
- mbd->subpixel_predict16x16 = xd->subpixel_predict16x16;
-
- mbd->mode_info_context = pc->mi + pc->mode_info_stride * (i + 1);
- mbd->mode_info_stride = pc->mode_info_stride;
-
- mbd->frame_type = pc->frame_type;
- mbd->frames_since_golden = pc->frames_since_golden;
- mbd->frames_till_alt_ref_frame = pc->frames_till_alt_ref_frame;
-
- mbd->pre = pc->yv12_fb[pc->lst_fb_idx];
- mbd->dst = pc->yv12_fb[pc->new_fb_idx];
-
- vp8_setup_block_dptrs(mbd);
- vp8_build_block_doffsets(mbd);
- mbd->segmentation_enabled = xd->segmentation_enabled;
- mbd->mb_segement_abs_delta = xd->mb_segement_abs_delta;
- vpx_memcpy(mbd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data));
-
- /*signed char ref_lf_deltas[MAX_REF_LF_DELTAS];*/
- vpx_memcpy(mbd->ref_lf_deltas, xd->ref_lf_deltas, sizeof(xd->ref_lf_deltas));
- /*signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];*/
- vpx_memcpy(mbd->mode_lf_deltas, xd->mode_lf_deltas, sizeof(xd->mode_lf_deltas));
- /*unsigned char mode_ref_lf_delta_enabled;
- unsigned char mode_ref_lf_delta_update;*/
- mbd->mode_ref_lf_delta_enabled = xd->mode_ref_lf_delta_enabled;
- mbd->mode_ref_lf_delta_update = xd->mode_ref_lf_delta_update;
-
- mbd->current_bc = &pbi->bc2;
-
- for (j = 0; j < 25; j++)
- {
- mbd->block[j].dequant = xd->block[j].dequant;
- }
-
- mbd->fullpixel_mask = 0xffffffff;
- if(pc->full_pixel)
- mbd->fullpixel_mask = 0xfffffff8;
-
- }
-
- for (i=0; i< pc->mb_rows; i++)
- pbi->mt_current_mb_col[i]=-1;
-}
-
-
-static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col)
-{
- int eobtotal = 0;
- int throw_residual = 0;
- int i;
-
- if (xd->mode_info_context->mbmi.mb_skip_coeff)
- {
- vp8_reset_mb_tokens_context(xd);
- }
- else if (!vp8dx_bool_error(xd->current_bc))
- {
- eobtotal = vp8_decode_mb_tokens(pbi, xd);
- }
-
- eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
- xd->mode_info_context->mbmi.mode == SPLITMV);
- if (!eobtotal && !vp8dx_bool_error(xd->current_bc))
- {
- /* Special case: Force the loopfilter to skip when eobtotal and
- * mb_skip_coeff are zero.
- * */
- xd->mode_info_context->mbmi.mb_skip_coeff = 1;
-
- /*mt_skip_recon_mb(pbi, xd, mb_row, mb_col);*/
- if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
- {
- vp8mt_build_intra_predictors_mbuv_s(pbi, xd, mb_row, mb_col);
- vp8mt_build_intra_predictors_mby_s(pbi, xd, mb_row, mb_col);
- }
- else
- {
- vp8_build_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
- xd->dst.u_buffer, xd->dst.v_buffer,
- xd->dst.y_stride, xd->dst.uv_stride);
- }
- return;
- }
-
- if (xd->segmentation_enabled)
- mb_init_dequantizer(pbi, xd);
-
- /* do prediction */
- if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
- {
- vp8mt_build_intra_predictors_mbuv(pbi, xd, mb_row, mb_col);
-
- if (xd->mode_info_context->mbmi.mode != B_PRED)
- {
- vp8mt_build_intra_predictors_mby(pbi, xd, mb_row, mb_col);
- } else {
- vp8mt_intra_prediction_down_copy(pbi, xd, mb_row, mb_col);
- }
- }
- else
- {
- vp8_build_inter_predictors_mb(xd);
- }
-
- /* When we have independent partitions we can apply residual even
- * though other partitions within the frame are corrupt.
- */
- throw_residual = (!pbi->independent_partitions &&
- pbi->frame_corrupt_residual);
- throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
-
-#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_active &&
- (mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
- throw_residual))
- {
- /* MB with corrupt residuals or corrupt mode/motion vectors.
- * Better to use the predictor as reconstruction.
- */
- pbi->frame_corrupt_residual = 1;
- vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
- vp8_conceal_corrupt_mb(xd);
- return;
- }
-#endif
-
- /* dequantization and idct */
- if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV)
- {
- BLOCKD *b = &xd->block[24];
- DEQUANT_INVOKE(&pbi->dequant, block)(b);
-
- /* do 2nd order transform on the dc block */
- if (xd->eobs[24] > 1)
- {
- IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh16)(&b->dqcoeff[0], b->diff);
- ((int *)b->qcoeff)[0] = 0;
- ((int *)b->qcoeff)[1] = 0;
- ((int *)b->qcoeff)[2] = 0;
- ((int *)b->qcoeff)[3] = 0;
- ((int *)b->qcoeff)[4] = 0;
- ((int *)b->qcoeff)[5] = 0;
- ((int *)b->qcoeff)[6] = 0;
- ((int *)b->qcoeff)[7] = 0;
- }
- else
- {
- IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh1)(&b->dqcoeff[0], b->diff);
- ((int *)b->qcoeff)[0] = 0;
- }
-
- DEQUANT_INVOKE (&pbi->dequant, dc_idct_add_y_block)
- (xd->qcoeff, xd->block[0].dequant,
- xd->predictor, xd->dst.y_buffer,
- xd->dst.y_stride, xd->eobs, xd->block[24].diff);
- }
- else if (xd->mode_info_context->mbmi.mode == B_PRED)
- {
- for (i = 0; i < 16; i++)
- {
- BLOCKD *b = &xd->block[i];
- int b_mode = xd->mode_info_context->bmi[i].as_mode;
-
- vp8mt_predict_intra4x4(pbi, xd, b_mode, b->predictor, mb_row, mb_col, i);
-
- if (xd->eobs[i] > 1)
- {
- DEQUANT_INVOKE(&pbi->dequant, idct_add)
- (b->qcoeff, b->dequant, b->predictor,
- *(b->base_dst) + b->dst, 16, b->dst_stride);
- }
- else
- {
- IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar_add)
- (b->qcoeff[0] * b->dequant[0], b->predictor,
- *(b->base_dst) + b->dst, 16, b->dst_stride);
- ((int *)b->qcoeff)[0] = 0;
- }
- }
- }
- else
- {
- DEQUANT_INVOKE (&pbi->dequant, idct_add_y_block)
- (xd->qcoeff, xd->block[0].dequant,
- xd->predictor, xd->dst.y_buffer,
- xd->dst.y_stride, xd->eobs);
- }
-
- DEQUANT_INVOKE (&pbi->dequant, idct_add_uv_block)
- (xd->qcoeff+16*16, xd->block[16].dequant,
- xd->predictor+16*16, xd->dst.u_buffer, xd->dst.v_buffer,
- xd->dst.uv_stride, xd->eobs+16);
-}
-
-
-static THREAD_FUNCTION thread_decoding_proc(void *p_data)
-{
- int ithread = ((DECODETHREAD_DATA *)p_data)->ithread;
- VP8D_COMP *pbi = (VP8D_COMP *)(((DECODETHREAD_DATA *)p_data)->ptr1);
- MB_ROW_DEC *mbrd = (MB_ROW_DEC *)(((DECODETHREAD_DATA *)p_data)->ptr2);
- ENTROPY_CONTEXT_PLANES mb_row_left_context;
-
- while (1)
- {
- if (pbi->b_multithreaded_rd == 0)
- break;
-
- /*if(WaitForSingleObject(pbi->h_event_start_decoding[ithread], INFINITE) == WAIT_OBJECT_0)*/
- if (sem_wait(&pbi->h_event_start_decoding[ithread]) == 0)
- {
- if (pbi->b_multithreaded_rd == 0)
- break;
- else
- {
- VP8_COMMON *pc = &pbi->common;
- MACROBLOCKD *xd = &mbrd->mbd;
-
- int mb_row;
- int num_part = 1 << pbi->common.multi_token_partition;
- volatile int *last_row_current_mb_col;
- int nsync = pbi->sync_range;
-
- for (mb_row = ithread+1; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
- {
- int i;
- int recon_yoffset, recon_uvoffset;
- int mb_col;
- int ref_fb_idx = pc->lst_fb_idx;
- int dst_fb_idx = pc->new_fb_idx;
- int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
- int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
-
- int filter_level;
- loop_filter_info_n *lfi_n = &pc->lf_info;
-
- pbi->mb_row_di[ithread].mb_row = mb_row;
- pbi->mb_row_di[ithread].mbd.current_bc = &pbi->mbc[mb_row%num_part];
-
- last_row_current_mb_col = &pbi->mt_current_mb_col[mb_row -1];
-
- recon_yoffset = mb_row * recon_y_stride * 16;
- recon_uvoffset = mb_row * recon_uv_stride * 8;
- /* reset above block coeffs */
-
- xd->above_context = pc->above_context;
- xd->left_context = &mb_row_left_context;
- vpx_memset(&mb_row_left_context, 0, sizeof(mb_row_left_context));
- xd->up_available = (mb_row != 0);
-
- xd->mb_to_top_edge = -((mb_row * 16)) << 3;
- xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
-
- for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
- {
- if ((mb_col & (nsync-1)) == 0)
- {
- while (mb_col > (*last_row_current_mb_col - nsync) && *last_row_current_mb_col != pc->mb_cols - 1)
- {
- x86_pause_hint();
- thread_sleep(0);
- }
- }
-
- /* Distance of MB to the various image edges.
- * These are specified to 8th pel as they are always
- * compared to values that are in 1/8th pel units.
- */
- xd->mb_to_left_edge = -((mb_col * 16) << 3);
- xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
-
-#if CONFIG_ERROR_CONCEALMENT
- {
- int corrupt_residual =
- (!pbi->independent_partitions &&
- pbi->frame_corrupt_residual) ||
- vp8dx_bool_error(xd->current_bc);
- if (pbi->ec_active &&
- (xd->mode_info_context->mbmi.ref_frame ==
- INTRA_FRAME) &&
- corrupt_residual)
- {
- /* We have an intra block with corrupt
- * coefficients, better to conceal with an inter
- * block.
- * Interpolate MVs from neighboring MBs
- *
- * Note that for the first mb with corrupt
- * residual in a frame, we might not discover
- * that before decoding the residual. That
- * happens after this check, and therefore no
- * inter concealment will be done.
- */
- vp8_interpolate_motion(xd,
- mb_row, mb_col,
- pc->mb_rows, pc->mb_cols,
- pc->mode_info_stride);
- }
- }
-#endif
-
-
- xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
- xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
- xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
-
- xd->left_available = (mb_col != 0);
-
- /* Select the appropriate reference frame for this MB */
- if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
- ref_fb_idx = pc->lst_fb_idx;
- else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME)
- ref_fb_idx = pc->gld_fb_idx;
- else
- ref_fb_idx = pc->alt_fb_idx;
-
- xd->pre.y_buffer = pc->yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
- xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
- xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
-
- if (xd->mode_info_context->mbmi.ref_frame !=
- INTRA_FRAME)
- {
- /* propagate errors from reference frames */
- xd->corrupted |= pc->yv12_fb[ref_fb_idx].corrupted;
- }
-
- decode_macroblock(pbi, xd, mb_row, mb_col);
-
- /* check if the boolean decoder has suffered an error */
- xd->corrupted |= vp8dx_bool_error(xd->current_bc);
-
- if (pbi->common.filter_level)
- {
- int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
- xd->mode_info_context->mbmi.mode != SPLITMV &&
- xd->mode_info_context->mbmi.mb_skip_coeff);
-
- const int mode_index = lfi_n->mode_lf_lut[xd->mode_info_context->mbmi.mode];
- const int seg = xd->mode_info_context->mbmi.segment_id;
- const int ref_frame = xd->mode_info_context->mbmi.ref_frame;
-
- filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
-
- if( mb_row != pc->mb_rows-1 )
- {
- /* Save decoded MB last row data for next-row decoding */
- vpx_memcpy((pbi->mt_yabove_row[mb_row + 1] + 32 + mb_col*16), (xd->dst.y_buffer + 15 * recon_y_stride), 16);
- vpx_memcpy((pbi->mt_uabove_row[mb_row + 1] + 16 + mb_col*8), (xd->dst.u_buffer + 7 * recon_uv_stride), 8);
- vpx_memcpy((pbi->mt_vabove_row[mb_row + 1] + 16 + mb_col*8), (xd->dst.v_buffer + 7 * recon_uv_stride), 8);
- }
-
- /* save left_col for next MB decoding */
- if(mb_col != pc->mb_cols-1)
- {
- MODE_INFO *next = xd->mode_info_context +1;
-
- if (next->mbmi.ref_frame == INTRA_FRAME)
- {
- for (i = 0; i < 16; i++)
- pbi->mt_yleft_col[mb_row][i] = xd->dst.y_buffer [i* recon_y_stride + 15];
- for (i = 0; i < 8; i++)
- {
- pbi->mt_uleft_col[mb_row][i] = xd->dst.u_buffer [i* recon_uv_stride + 7];
- pbi->mt_vleft_col[mb_row][i] = xd->dst.v_buffer [i* recon_uv_stride + 7];
- }
- }
- }
-
- /* loopfilter on this macroblock. */
- if (filter_level)
- {
- if(pc->filter_type == NORMAL_LOOPFILTER)
- {
- loop_filter_info lfi;
- FRAME_TYPE frame_type = pc->frame_type;
- const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
- lfi.mblim = lfi_n->mblim[filter_level];
- lfi.blim = lfi_n->blim[filter_level];
- lfi.lim = lfi_n->lim[filter_level];
- lfi.hev_thr = lfi_n->hev_thr[hev_index];
-
- if (mb_col > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_mb_v)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_b_v)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
-
- /* don't apply across umv border */
- if (mb_row > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_mb_h)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_b_h)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
- }
- else
- {
- if (mb_col > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_mb_v)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->mblim[filter_level]);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_b_v)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->blim[filter_level]);
-
- /* don't apply across umv border */
- if (mb_row > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_mb_h)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->mblim[filter_level]);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_b_h)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->blim[filter_level]);
- }
- }
-
- }
-
- recon_yoffset += 16;
- recon_uvoffset += 8;
-
- ++xd->mode_info_context; /* next mb */
-
- xd->above_context++;
-
- /*pbi->mb_row_di[ithread].current_mb_col = mb_col;*/
- pbi->mt_current_mb_col[mb_row] = mb_col;
- }
-
- /* adjust to the next row of mbs */
- if (pbi->common.filter_level)
- {
- if(mb_row != pc->mb_rows-1)
- {
- int lasty = pc->yv12_fb[ref_fb_idx].y_width + VP8BORDERINPIXELS;
- int lastuv = (pc->yv12_fb[ref_fb_idx].y_width>>1) + (VP8BORDERINPIXELS>>1);
-
- for (i = 0; i < 4; i++)
- {
- pbi->mt_yabove_row[mb_row +1][lasty + i] = pbi->mt_yabove_row[mb_row +1][lasty -1];
- pbi->mt_uabove_row[mb_row +1][lastuv + i] = pbi->mt_uabove_row[mb_row +1][lastuv -1];
- pbi->mt_vabove_row[mb_row +1][lastuv + i] = pbi->mt_vabove_row[mb_row +1][lastuv -1];
- }
- }
- } else
- vp8_extend_mb_row(&pc->yv12_fb[dst_fb_idx], xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
-
- ++xd->mode_info_context; /* skip prediction column */
-
- /* since we have multithread */
- xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
- }
- }
- }
- /* add this to each frame */
- if ((mbrd->mb_row == pbi->common.mb_rows-1) || ((mbrd->mb_row == pbi->common.mb_rows-2) && (pbi->common.mb_rows % (pbi->decoding_thread_count+1))==1))
- {
- /*SetEvent(pbi->h_event_end_decoding);*/
- sem_post(&pbi->h_event_end_decoding);
- }
- }
-
- return 0 ;
-}
-
-
-void vp8_decoder_create_threads(VP8D_COMP *pbi)
-{
- int core_count = 0;
- int ithread;
-
- pbi->b_multithreaded_rd = 0;
- pbi->allocated_decoding_thread_count = 0;
-
- /* limit decoding threads to the max number of token partitions */
- core_count = (pbi->max_threads > 8) ? 8 : pbi->max_threads;
-
- /* limit decoding threads to the available cores */
- if (core_count > pbi->common.processor_core_count)
- core_count = pbi->common.processor_core_count;
-
- if (core_count > 1)
- {
- pbi->b_multithreaded_rd = 1;
- pbi->decoding_thread_count = core_count - 1;
-
- CHECK_MEM_ERROR(pbi->h_decoding_thread, vpx_malloc(sizeof(pthread_t) * pbi->decoding_thread_count));
- CHECK_MEM_ERROR(pbi->h_event_start_decoding, vpx_malloc(sizeof(sem_t) * pbi->decoding_thread_count));
- CHECK_MEM_ERROR(pbi->mb_row_di, vpx_memalign(32, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count));
- vpx_memset(pbi->mb_row_di, 0, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count);
- CHECK_MEM_ERROR(pbi->de_thread_data, vpx_malloc(sizeof(DECODETHREAD_DATA) * pbi->decoding_thread_count));
-
- for (ithread = 0; ithread < pbi->decoding_thread_count; ithread++)
- {
- sem_init(&pbi->h_event_start_decoding[ithread], 0, 0);
-
- pbi->de_thread_data[ithread].ithread = ithread;
- pbi->de_thread_data[ithread].ptr1 = (void *)pbi;
- pbi->de_thread_data[ithread].ptr2 = (void *) &pbi->mb_row_di[ithread];
-
- pthread_create(&pbi->h_decoding_thread[ithread], 0, thread_decoding_proc, (&pbi->de_thread_data[ithread]));
- }
-
- sem_init(&pbi->h_event_end_decoding, 0, 0);
-
- pbi->allocated_decoding_thread_count = pbi->decoding_thread_count;
- }
-}
-
-
-void vp8mt_de_alloc_temp_buffers(VP8D_COMP *pbi, int mb_rows)
-{
- int i;
-
- if (pbi->b_multithreaded_rd)
- {
- vpx_free(pbi->mt_current_mb_col);
- pbi->mt_current_mb_col = NULL ;
-
- /* Free above_row buffers. */
- if (pbi->mt_yabove_row)
- {
- for (i=0; i< mb_rows; i++)
- {
- vpx_free(pbi->mt_yabove_row[i]);
- pbi->mt_yabove_row[i] = NULL ;
- }
- vpx_free(pbi->mt_yabove_row);
- pbi->mt_yabove_row = NULL ;
- }
-
- if (pbi->mt_uabove_row)
- {
- for (i=0; i< mb_rows; i++)
- {
- vpx_free(pbi->mt_uabove_row[i]);
- pbi->mt_uabove_row[i] = NULL ;
- }
- vpx_free(pbi->mt_uabove_row);
- pbi->mt_uabove_row = NULL ;
- }
-
- if (pbi->mt_vabove_row)
- {
- for (i=0; i< mb_rows; i++)
- {
- vpx_free(pbi->mt_vabove_row[i]);
- pbi->mt_vabove_row[i] = NULL ;
- }
- vpx_free(pbi->mt_vabove_row);
- pbi->mt_vabove_row = NULL ;
- }
-
- /* Free left_col buffers. */
- if (pbi->mt_yleft_col)
- {
- for (i=0; i< mb_rows; i++)
- {
- vpx_free(pbi->mt_yleft_col[i]);
- pbi->mt_yleft_col[i] = NULL ;
- }
- vpx_free(pbi->mt_yleft_col);
- pbi->mt_yleft_col = NULL ;
- }
-
- if (pbi->mt_uleft_col)
- {
- for (i=0; i< mb_rows; i++)
- {
- vpx_free(pbi->mt_uleft_col[i]);
- pbi->mt_uleft_col[i] = NULL ;
- }
- vpx_free(pbi->mt_uleft_col);
- pbi->mt_uleft_col = NULL ;
- }
-
- if (pbi->mt_vleft_col)
- {
- for (i=0; i< mb_rows; i++)
- {
- vpx_free(pbi->mt_vleft_col[i]);
- pbi->mt_vleft_col[i] = NULL ;
- }
- vpx_free(pbi->mt_vleft_col);
- pbi->mt_vleft_col = NULL ;
- }
- }
-}
-
-
-void vp8mt_alloc_temp_buffers(VP8D_COMP *pbi, int width, int prev_mb_rows)
-{
- VP8_COMMON *const pc = & pbi->common;
- int i;
- int uv_width;
-
- if (pbi->b_multithreaded_rd)
- {
- vp8mt_de_alloc_temp_buffers(pbi, prev_mb_rows);
-
- /* our internal buffers are always multiples of 16 */
- if ((width & 0xf) != 0)
- width += 16 - (width & 0xf);
-
- if (width < 640) pbi->sync_range = 1;
- else if (width <= 1280) pbi->sync_range = 8;
- else if (width <= 2560) pbi->sync_range =16;
- else pbi->sync_range = 32;
-
- uv_width = width >>1;
-
- /* Allocate an int for each mb row. */
- CHECK_MEM_ERROR(pbi->mt_current_mb_col, vpx_malloc(sizeof(int) * pc->mb_rows));
-
- /* Allocate memory for above_row buffers. */
- CHECK_MEM_ERROR(pbi->mt_yabove_row, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
- for (i=0; i< pc->mb_rows; i++)
- CHECK_MEM_ERROR(pbi->mt_yabove_row[i], vpx_calloc(sizeof(unsigned char) * (width + (VP8BORDERINPIXELS<<1)), 1));
-
- CHECK_MEM_ERROR(pbi->mt_uabove_row, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
- for (i=0; i< pc->mb_rows; i++)
- CHECK_MEM_ERROR(pbi->mt_uabove_row[i], vpx_calloc(sizeof(unsigned char) * (uv_width + VP8BORDERINPIXELS), 1));
-
- CHECK_MEM_ERROR(pbi->mt_vabove_row, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
- for (i=0; i< pc->mb_rows; i++)
- CHECK_MEM_ERROR(pbi->mt_vabove_row[i], vpx_calloc(sizeof(unsigned char) * (uv_width + VP8BORDERINPIXELS), 1));
-
- /* Allocate memory for left_col buffers. */
- CHECK_MEM_ERROR(pbi->mt_yleft_col, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
- for (i=0; i< pc->mb_rows; i++)
- CHECK_MEM_ERROR(pbi->mt_yleft_col[i], vpx_calloc(sizeof(unsigned char) * 16, 1));
-
- CHECK_MEM_ERROR(pbi->mt_uleft_col, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
- for (i=0; i< pc->mb_rows; i++)
- CHECK_MEM_ERROR(pbi->mt_uleft_col[i], vpx_calloc(sizeof(unsigned char) * 8, 1));
-
- CHECK_MEM_ERROR(pbi->mt_vleft_col, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
- for (i=0; i< pc->mb_rows; i++)
- CHECK_MEM_ERROR(pbi->mt_vleft_col[i], vpx_calloc(sizeof(unsigned char) * 8, 1));
- }
-}
-
-
-void vp8_decoder_remove_threads(VP8D_COMP *pbi)
-{
- /* shutdown MB Decoding thread; */
- if (pbi->b_multithreaded_rd)
- {
- int i;
-
- pbi->b_multithreaded_rd = 0;
-
- /* allow all threads to exit */
- for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
- {
- sem_post(&pbi->h_event_start_decoding[i]);
- pthread_join(pbi->h_decoding_thread[i], NULL);
- }
-
- for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
- {
- sem_destroy(&pbi->h_event_start_decoding[i]);
- }
-
- sem_destroy(&pbi->h_event_end_decoding);
-
- vpx_free(pbi->h_decoding_thread);
- pbi->h_decoding_thread = NULL;
-
- vpx_free(pbi->h_event_start_decoding);
- pbi->h_event_start_decoding = NULL;
-
- vpx_free(pbi->mb_row_di);
- pbi->mb_row_di = NULL ;
-
- vpx_free(pbi->de_thread_data);
- pbi->de_thread_data = NULL;
- }
-}
-
-void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
-{
- int mb_row;
- VP8_COMMON *pc = &pbi->common;
-
- int num_part = 1 << pbi->common.multi_token_partition;
- int i;
- volatile int *last_row_current_mb_col = NULL;
- int nsync = pbi->sync_range;
-
- int filter_level = pc->filter_level;
- loop_filter_info_n *lfi_n = &pc->lf_info;
-
- if (filter_level)
- {
- /* Set above_row buffer to 127 for decoding first MB row */
- vpx_memset(pbi->mt_yabove_row[0] + VP8BORDERINPIXELS-1, 127, pc->yv12_fb[pc->lst_fb_idx].y_width + 5);
- vpx_memset(pbi->mt_uabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (pc->yv12_fb[pc->lst_fb_idx].y_width>>1) +5);
- vpx_memset(pbi->mt_vabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (pc->yv12_fb[pc->lst_fb_idx].y_width>>1) +5);
-
- for (i=1; i<pc->mb_rows; i++)
- {
- vpx_memset(pbi->mt_yabove_row[i] + VP8BORDERINPIXELS-1, (unsigned char)129, 1);
- vpx_memset(pbi->mt_uabove_row[i] + (VP8BORDERINPIXELS>>1)-1, (unsigned char)129, 1);
- vpx_memset(pbi->mt_vabove_row[i] + (VP8BORDERINPIXELS>>1)-1, (unsigned char)129, 1);
- }
-
- /* Set left_col to 129 initially */
- for (i=0; i<pc->mb_rows; i++)
- {
- vpx_memset(pbi->mt_yleft_col[i], (unsigned char)129, 16);
- vpx_memset(pbi->mt_uleft_col[i], (unsigned char)129, 8);
- vpx_memset(pbi->mt_vleft_col[i], (unsigned char)129, 8);
- }
-
- /* Initialize the loop filter for this frame. */
- vp8_loop_filter_frame_init(pc, &pbi->mb, filter_level);
- }
-
- setup_decoding_thread_data(pbi, xd, pbi->mb_row_di, pbi->decoding_thread_count);
-
- for (i = 0; i < pbi->decoding_thread_count; i++)
- sem_post(&pbi->h_event_start_decoding[i]);
-
- for (mb_row = 0; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
- {
- xd->current_bc = &pbi->mbc[mb_row%num_part];
-
- /* vp8_decode_mb_row(pbi, pc, mb_row, xd); */
- {
- int i;
- int recon_yoffset, recon_uvoffset;
- int mb_col;
- int ref_fb_idx = pc->lst_fb_idx;
- int dst_fb_idx = pc->new_fb_idx;
- int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
- int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
-
- /* volatile int *last_row_current_mb_col = NULL; */
- if (mb_row > 0)
- last_row_current_mb_col = &pbi->mt_current_mb_col[mb_row -1];
-
- vpx_memset(&pc->left_context, 0, sizeof(pc->left_context));
- recon_yoffset = mb_row * recon_y_stride * 16;
- recon_uvoffset = mb_row * recon_uv_stride * 8;
- /* reset above block coeffs */
-
- xd->above_context = pc->above_context;
- xd->up_available = (mb_row != 0);
-
- xd->mb_to_top_edge = -((mb_row * 16)) << 3;
- xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
-
- for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
- {
- if ( mb_row > 0 && (mb_col & (nsync-1)) == 0){
- while (mb_col > (*last_row_current_mb_col - nsync) && *last_row_current_mb_col != pc->mb_cols - 1)
- {
- x86_pause_hint();
- thread_sleep(0);
- }
- }
-
- /* Distance of MB to the various image edges.
- * These are specified to 8th pel as they are always compared to
- * values that are in 1/8th pel units.
- */
- xd->mb_to_left_edge = -((mb_col * 16) << 3);
- xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
-
-#if CONFIG_ERROR_CONCEALMENT
- {
- int corrupt_residual = (!pbi->independent_partitions &&
- pbi->frame_corrupt_residual) ||
- vp8dx_bool_error(xd->current_bc);
- if (pbi->ec_active &&
- (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
- corrupt_residual)
- {
- /* We have an intra block with corrupt coefficients,
- * better to conceal with an inter block. Interpolate
- * MVs from neighboring MBs
- *
- * Note that for the first mb with corrupt residual in a
- * frame, we might not discover that before decoding the
- * residual. That happens after this check, and
- * therefore no inter concealment will be done.
- */
- vp8_interpolate_motion(xd,
- mb_row, mb_col,
- pc->mb_rows, pc->mb_cols,
- pc->mode_info_stride);
- }
- }
-#endif
-
-
- xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
- xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
- xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
-
- xd->left_available = (mb_col != 0);
-
- /* Select the appropriate reference frame for this MB */
- if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
- ref_fb_idx = pc->lst_fb_idx;
- else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME)
- ref_fb_idx = pc->gld_fb_idx;
- else
- ref_fb_idx = pc->alt_fb_idx;
-
- xd->pre.y_buffer = pc->yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
- xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
- xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
-
- if (xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME)
- {
- /* propagate errors from reference frames */
- xd->corrupted |= pc->yv12_fb[ref_fb_idx].corrupted;
- }
-
- decode_macroblock(pbi, xd, mb_row, mb_col);
-
- /* check if the boolean decoder has suffered an error */
- xd->corrupted |= vp8dx_bool_error(xd->current_bc);
-
- if (pbi->common.filter_level)
- {
- int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
- xd->mode_info_context->mbmi.mode != SPLITMV &&
- xd->mode_info_context->mbmi.mb_skip_coeff);
-
- const int mode_index = lfi_n->mode_lf_lut[xd->mode_info_context->mbmi.mode];
- const int seg = xd->mode_info_context->mbmi.segment_id;
- const int ref_frame = xd->mode_info_context->mbmi.ref_frame;
-
- filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
-
- /* Save decoded MB last row data for next-row decoding */
- if(mb_row != pc->mb_rows-1)
- {
- vpx_memcpy((pbi->mt_yabove_row[mb_row +1] + 32 + mb_col*16), (xd->dst.y_buffer + 15 * recon_y_stride), 16);
- vpx_memcpy((pbi->mt_uabove_row[mb_row +1] + 16 + mb_col*8), (xd->dst.u_buffer + 7 * recon_uv_stride), 8);
- vpx_memcpy((pbi->mt_vabove_row[mb_row +1] + 16 + mb_col*8), (xd->dst.v_buffer + 7 * recon_uv_stride), 8);
- }
-
- /* save left_col for next MB decoding */
- if(mb_col != pc->mb_cols-1)
- {
- MODE_INFO *next = xd->mode_info_context +1;
-
- if (next->mbmi.ref_frame == INTRA_FRAME)
- {
- for (i = 0; i < 16; i++)
- pbi->mt_yleft_col[mb_row][i] = xd->dst.y_buffer [i* recon_y_stride + 15];
- for (i = 0; i < 8; i++)
- {
- pbi->mt_uleft_col[mb_row][i] = xd->dst.u_buffer [i* recon_uv_stride + 7];
- pbi->mt_vleft_col[mb_row][i] = xd->dst.v_buffer [i* recon_uv_stride + 7];
- }
- }
- }
-
- /* loopfilter on this macroblock. */
- if (filter_level)
- {
- if(pc->filter_type == NORMAL_LOOPFILTER)
- {
- loop_filter_info lfi;
- FRAME_TYPE frame_type = pc->frame_type;
- const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
- lfi.mblim = lfi_n->mblim[filter_level];
- lfi.blim = lfi_n->blim[filter_level];
- lfi.lim = lfi_n->lim[filter_level];
- lfi.hev_thr = lfi_n->hev_thr[hev_index];
-
- if (mb_col > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_mb_v)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_b_v)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
-
- /* don't apply across umv border */
- if (mb_row > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_mb_h)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, normal_b_h)
- (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
- }
- else
- {
- if (mb_col > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_mb_v)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->mblim[filter_level]);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_b_v)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->blim[filter_level]);
-
- /* don't apply across umv border */
- if (mb_row > 0)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_mb_h)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->mblim[filter_level]);
-
- if (!skip_lf)
- LF_INVOKE(&pc->rtcd.loopfilter, simple_b_h)
- (xd->dst.y_buffer, recon_y_stride, lfi_n->blim[filter_level]);
- }
- }
-
- }
- recon_yoffset += 16;
- recon_uvoffset += 8;
-
- ++xd->mode_info_context; /* next mb */
-
- xd->above_context++;
-
- pbi->mt_current_mb_col[mb_row] = mb_col;
- }
-
- /* adjust to the next row of mbs */
- if (pbi->common.filter_level)
- {
- if(mb_row != pc->mb_rows-1)
- {
- int lasty = pc->yv12_fb[ref_fb_idx].y_width + VP8BORDERINPIXELS;
- int lastuv = (pc->yv12_fb[ref_fb_idx].y_width>>1) + (VP8BORDERINPIXELS>>1);
-
- for (i = 0; i < 4; i++)
- {
- pbi->mt_yabove_row[mb_row +1][lasty + i] = pbi->mt_yabove_row[mb_row +1][lasty -1];
- pbi->mt_uabove_row[mb_row +1][lastuv + i] = pbi->mt_uabove_row[mb_row +1][lastuv -1];
- pbi->mt_vabove_row[mb_row +1][lastuv + i] = pbi->mt_vabove_row[mb_row +1][lastuv -1];
- }
- }
- }else
- vp8_extend_mb_row(&pc->yv12_fb[dst_fb_idx], xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
-
- ++xd->mode_info_context; /* skip prediction column */
- }
- xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
- }
-
- sem_wait(&pbi->h_event_end_decoding); /* add back for each frame */
-}
diff --git a/vp8/decoder/x86/idct_blk_mmx.c b/vp8/decoder/x86/idct_blk_mmx.c
index 558dbaf7e..8f1a363cd 100644
--- a/vp8/decoder/x86/idct_blk_mmx.c
+++ b/vp8/decoder/x86/idct_blk_mmx.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "vp8/decoder/dequantize.h"
diff --git a/vp8/decoder/x86/idct_blk_sse2.c b/vp8/decoder/x86/idct_blk_sse2.c
index a6a720639..3a4806862 100644
--- a/vp8/decoder/x86/idct_blk_sse2.c
+++ b/vp8/decoder/x86/idct_blk_sse2.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "vp8/decoder/dequantize.h"
diff --git a/vp8/decoder/x86/x86_dsystemdependent.c b/vp8/decoder/x86/x86_dsystemdependent.c
index 443150483..a244a3a98 100644
--- a/vp8/decoder/x86/x86_dsystemdependent.c
+++ b/vp8/decoder/x86/x86_dsystemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/x86.h"
#include "vp8/decoder/onyxd_int.h"
diff --git a/vp8/encoder/arm/arm_csystemdependent.c b/vp8/encoder/arm/arm_csystemdependent.c
index 210a5a5c5..e66835ae0 100644
--- a/vp8/encoder/arm/arm_csystemdependent.c
+++ b/vp8/encoder/arm/arm_csystemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/arm.h"
#include "vp8/encoder/variance.h"
#include "vp8/encoder/onyx_int.h"
@@ -56,8 +56,6 @@ void vp8_arch_arm_encoder_init(VP8_COMP *cpi)
cpi->rtcd.variance.mse16x16 = vp8_mse16x16_armv6;
/*cpi->rtcd.variance.getmbss = vp8_get_mb_ss_c;*/
- /*cpi->rtcd.variance.get4x4sse_cs = vp8_get4x4sse_cs_c;*/
-
cpi->rtcd.fdct.short4x4 = vp8_short_fdct4x4_armv6;
cpi->rtcd.fdct.short8x4 = vp8_short_fdct8x4_armv6;
cpi->rtcd.fdct.fast4x4 = vp8_short_fdct4x4_armv6;
@@ -103,8 +101,6 @@ void vp8_arch_arm_encoder_init(VP8_COMP *cpi)
cpi->rtcd.variance.mse16x16 = vp8_mse16x16_neon;
/*cpi->rtcd.variance.getmbss = vp8_get_mb_ss_c;*/
- cpi->rtcd.variance.get4x4sse_cs = vp8_get4x4sse_cs_neon;
-
cpi->rtcd.fdct.short4x4 = vp8_short_fdct4x4_neon;
cpi->rtcd.fdct.short8x4 = vp8_short_fdct8x4_neon;
cpi->rtcd.fdct.fast4x4 = vp8_short_fdct4x4_neon;
diff --git a/vp8/encoder/arm/variance_arm.c b/vp8/encoder/arm/variance_arm.c
index e77be9f73..6e83c6e7b 100644
--- a/vp8/encoder/arm/variance_arm.c
+++ b/vp8/encoder/arm/variance_arm.c
@@ -13,6 +13,12 @@
#include "vp8/common/filter.h"
#include "vp8/common/arm/bilinearfilter_arm.h"
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define HALFNDX 8
+#else
+#define HALFNDX 4
+#endif
+
#if HAVE_ARMV6
unsigned int vp8_sub_pixel_variance8x8_armv6
@@ -59,17 +65,17 @@ unsigned int vp8_sub_pixel_variance16x16_armv6
const short *HFilter, *VFilter;
unsigned int var;
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
var = vp8_variance_halfpixvar16x16_h_armv6(src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, sse);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
var = vp8_variance_halfpixvar16x16_v_armv6(src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, sse);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
var = vp8_variance_halfpixvar16x16_hv_armv6(src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, sse);
@@ -107,11 +113,11 @@ unsigned int vp8_sub_pixel_variance16x16_neon
unsigned int *sse
)
{
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
return vp8_variance_halfpixvar16x16_h_neon(src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
return vp8_variance_halfpixvar16x16_v_neon(src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
return vp8_variance_halfpixvar16x16_hv_neon(src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
else
return vp8_sub_pixel_variance16x16_neon_func(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
diff --git a/vp8/encoder/arm/variance_arm.h b/vp8/encoder/arm/variance_arm.h
index f2f761f9e..fdb7289b1 100644
--- a/vp8/encoder/arm/variance_arm.h
+++ b/vp8/encoder/arm/variance_arm.h
@@ -83,7 +83,6 @@ extern prototype_variance(vp8_variance_halfpixvar16x16_hv_neon);
//extern prototype_getmbss(vp8_get_mb_ss_c);
extern prototype_variance(vp8_mse16x16_neon);
-extern prototype_get16x16prederror(vp8_get4x4sse_cs_neon);
#if !CONFIG_RUNTIME_CPU_DETECT
#undef vp8_variance_sad4x4
@@ -146,8 +145,6 @@ extern prototype_get16x16prederror(vp8_get4x4sse_cs_neon);
#undef vp8_variance_mse16x16
#define vp8_variance_mse16x16 vp8_mse16x16_neon
-#undef vp8_variance_get4x4sse_cs
-#define vp8_variance_get4x4sse_cs vp8_get4x4sse_cs_neon
#endif
#endif
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
index cea8e1232..8906f93fd 100644
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -23,27 +23,10 @@
#include "vpx_mem/vpx_mem.h"
#include "bitstream.h"
-#include "defaultcoefcounts.h"
+#include "vp8/common/defaultcoefcounts.h"
-const int vp8cx_base_skip_false_prob[128] =
-{
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 251, 248, 244, 240, 236, 232, 229, 225,
- 221, 217, 213, 208, 204, 199, 194, 190,
- 187, 183, 179, 175, 172, 168, 164, 160,
- 157, 153, 149, 145, 142, 138, 134, 130,
- 127, 124, 120, 117, 114, 110, 107, 104,
- 101, 98, 95, 92, 89, 86, 83, 80,
- 77, 74, 71, 68, 65, 62, 59, 56,
- 53, 50, 47, 44, 41, 38, 35, 32,
- 30, 28, 26, 24, 22, 20, 18, 16,
-};
+#include "vp8/common/seg_common.h"
+#include "vp8/common/pred_common.h"
#if defined(SECTIONBITS_OUTPUT)
unsigned __int64 Sectionbits[500];
@@ -52,6 +35,8 @@ unsigned __int64 Sectionbits[500];
#ifdef ENTROPY_STATS
int intra_mode_stats[10][10][10];
static unsigned int tree_update_hist [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] [2];
+static unsigned int tree_update_hist_8x8 [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] [2];
+
extern unsigned int active_section;
#endif
@@ -59,7 +44,6 @@ extern unsigned int active_section;
int count_mb_seg[4] = { 0, 0, 0, 0 };
#endif
-
static void update_mode(
vp8_writer *const w,
int n,
@@ -121,13 +105,16 @@ static void update_mbintra_mode_probs(VP8_COMP *cpi)
);
}
{
+#if CONFIG_UVINTRA
+ //vp8_write_bit(w, 0);
+#else
vp8_prob Pnew [VP8_UV_MODES-1];
unsigned int bct [VP8_UV_MODES-1] [2];
-
update_mode(
w, VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
Pnew, x->fc.uv_mode_prob, bct, (unsigned int *)cpi->uv_mode_count
);
+#endif
}
}
@@ -141,6 +128,11 @@ static void kfwrite_ymode(vp8_writer *bc, int m, const vp8_prob *p)
vp8_write_token(bc, vp8_kf_ymode_tree, p, vp8_kf_ymode_encodings + m);
}
+static void write_i8x8_mode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+ vp8_write_token(bc,vp8_i8x8_mode_tree, p, vp8_i8x8_mode_encodings + m);
+}
+
static void write_uv_mode(vp8_writer *bc, int m, const vp8_prob *p)
{
vp8_write_token(bc, vp8_uv_mode_tree, p, vp8_uv_mode_encodings + m);
@@ -358,415 +350,6 @@ static void write_partition_size(unsigned char *cx_data, int size)
}
-static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data, int num_part, int *size)
-{
-
- int i;
- unsigned char *ptr = cx_data;
- unsigned int shift;
- vp8_writer *w = &cpi->bc2;
- *size = 3 * (num_part - 1);
- cpi->partition_sz[0] += *size;
- ptr = cx_data + (*size);
-
- for (i = 0; i < num_part; i++)
- {
- vp8_start_encode(w, ptr);
- {
- unsigned int split;
- int count = w->count;
- unsigned int range = w->range;
- unsigned int lowvalue = w->lowvalue;
- int mb_row;
-
- for (mb_row = i; mb_row < cpi->common.mb_rows; mb_row += num_part)
- {
- TOKENEXTRA *p = cpi->tplist[mb_row].start;
- TOKENEXTRA *stop = cpi->tplist[mb_row].stop;
-
- while (p < stop)
- {
- const int t = p->Token;
- vp8_token *const a = vp8_coef_encodings + t;
- const vp8_extra_bit_struct *const b = vp8_extra_bits + t;
- int i = 0;
- const unsigned char *pp = p->context_tree;
- int v = a->value;
- int n = a->Len;
-
- if (p->skip_eob_node)
- {
- n--;
- i = 2;
- }
-
- do
- {
- const int bb = (v >> --n) & 1;
- split = 1 + (((range - 1) * pp[i>>1]) >> 8);
- i = vp8_coef_tree[i+bb];
-
- if (bb)
- {
- lowvalue += split;
- range = range - split;
- }
- else
- {
- range = split;
- }
-
- shift = vp8_norm[range];
- range <<= shift;
- count += shift;
-
- if (count >= 0)
- {
- int offset = shift - count;
-
- if ((lowvalue << (offset - 1)) & 0x80000000)
- {
- int x = w->pos - 1;
-
- while (x >= 0 && w->buffer[x] == 0xff)
- {
- w->buffer[x] = (unsigned char)0;
- x--;
- }
-
- w->buffer[x] += 1;
- }
-
- w->buffer[w->pos++] = (lowvalue >> (24 - offset));
- lowvalue <<= offset;
- shift = count;
- lowvalue &= 0xffffff;
- count -= 8 ;
- }
-
- lowvalue <<= shift;
- }
- while (n);
-
-
- if (b->base_val)
- {
- const int e = p->Extra, L = b->Len;
-
- if (L)
- {
- const unsigned char *pp = b->prob;
- int v = e >> 1;
- int n = L; /* number of bits in v, assumed nonzero */
- int i = 0;
-
- do
- {
- const int bb = (v >> --n) & 1;
- split = 1 + (((range - 1) * pp[i>>1]) >> 8);
- i = b->tree[i+bb];
-
- if (bb)
- {
- lowvalue += split;
- range = range - split;
- }
- else
- {
- range = split;
- }
-
- shift = vp8_norm[range];
- range <<= shift;
- count += shift;
-
- if (count >= 0)
- {
- int offset = shift - count;
-
- if ((lowvalue << (offset - 1)) & 0x80000000)
- {
- int x = w->pos - 1;
-
- while (x >= 0 && w->buffer[x] == 0xff)
- {
- w->buffer[x] = (unsigned char)0;
- x--;
- }
-
- w->buffer[x] += 1;
- }
-
- w->buffer[w->pos++] = (lowvalue >> (24 - offset));
- lowvalue <<= offset;
- shift = count;
- lowvalue &= 0xffffff;
- count -= 8 ;
- }
-
- lowvalue <<= shift;
- }
- while (n);
- }
-
- {
- split = (range + 1) >> 1;
-
- if (e & 1)
- {
- lowvalue += split;
- range = range - split;
- }
- else
- {
- range = split;
- }
-
- range <<= 1;
-
- if ((lowvalue & 0x80000000))
- {
- int x = w->pos - 1;
-
- while (x >= 0 && w->buffer[x] == 0xff)
- {
- w->buffer[x] = (unsigned char)0;
- x--;
- }
-
- w->buffer[x] += 1;
-
- }
-
- lowvalue <<= 1;
-
- if (!++count)
- {
- count = -8;
- w->buffer[w->pos++] = (lowvalue >> 24);
- lowvalue &= 0xffffff;
- }
- }
-
- }
-
- ++p;
- }
- }
-
- w->count = count;
- w->lowvalue = lowvalue;
- w->range = range;
-
- }
-
- vp8_stop_encode(w);
- *size += w->pos;
-
- /* The first partition size is set earlier */
- cpi->partition_sz[i + 1] = w->pos;
-
- if (i < (num_part - 1))
- {
- write_partition_size(cx_data, w->pos);
- cx_data += 3;
- ptr += w->pos;
- }
- }
-}
-
-
-static void pack_mb_row_tokens_c(VP8_COMP *cpi, vp8_writer *w)
-{
-
- unsigned int split;
- int count = w->count;
- unsigned int range = w->range;
- unsigned int lowvalue = w->lowvalue;
- unsigned int shift;
- int mb_row;
-
- for (mb_row = 0; mb_row < cpi->common.mb_rows; mb_row++)
- {
- TOKENEXTRA *p = cpi->tplist[mb_row].start;
- TOKENEXTRA *stop = cpi->tplist[mb_row].stop;
-
- while (p < stop)
- {
- const int t = p->Token;
- vp8_token *const a = vp8_coef_encodings + t;
- const vp8_extra_bit_struct *const b = vp8_extra_bits + t;
- int i = 0;
- const unsigned char *pp = p->context_tree;
- int v = a->value;
- int n = a->Len;
-
- if (p->skip_eob_node)
- {
- n--;
- i = 2;
- }
-
- do
- {
- const int bb = (v >> --n) & 1;
- split = 1 + (((range - 1) * pp[i>>1]) >> 8);
- i = vp8_coef_tree[i+bb];
-
- if (bb)
- {
- lowvalue += split;
- range = range - split;
- }
- else
- {
- range = split;
- }
-
- shift = vp8_norm[range];
- range <<= shift;
- count += shift;
-
- if (count >= 0)
- {
- int offset = shift - count;
-
- if ((lowvalue << (offset - 1)) & 0x80000000)
- {
- int x = w->pos - 1;
-
- while (x >= 0 && w->buffer[x] == 0xff)
- {
- w->buffer[x] = (unsigned char)0;
- x--;
- }
-
- w->buffer[x] += 1;
- }
-
- w->buffer[w->pos++] = (lowvalue >> (24 - offset));
- lowvalue <<= offset;
- shift = count;
- lowvalue &= 0xffffff;
- count -= 8 ;
- }
-
- lowvalue <<= shift;
- }
- while (n);
-
-
- if (b->base_val)
- {
- const int e = p->Extra, L = b->Len;
-
- if (L)
- {
- const unsigned char *pp = b->prob;
- int v = e >> 1;
- int n = L; /* number of bits in v, assumed nonzero */
- int i = 0;
-
- do
- {
- const int bb = (v >> --n) & 1;
- split = 1 + (((range - 1) * pp[i>>1]) >> 8);
- i = b->tree[i+bb];
-
- if (bb)
- {
- lowvalue += split;
- range = range - split;
- }
- else
- {
- range = split;
- }
-
- shift = vp8_norm[range];
- range <<= shift;
- count += shift;
-
- if (count >= 0)
- {
- int offset = shift - count;
-
- if ((lowvalue << (offset - 1)) & 0x80000000)
- {
- int x = w->pos - 1;
-
- while (x >= 0 && w->buffer[x] == 0xff)
- {
- w->buffer[x] = (unsigned char)0;
- x--;
- }
-
- w->buffer[x] += 1;
- }
-
- w->buffer[w->pos++] = (lowvalue >> (24 - offset));
- lowvalue <<= offset;
- shift = count;
- lowvalue &= 0xffffff;
- count -= 8 ;
- }
-
- lowvalue <<= shift;
- }
- while (n);
- }
-
- {
- split = (range + 1) >> 1;
-
- if (e & 1)
- {
- lowvalue += split;
- range = range - split;
- }
- else
- {
- range = split;
- }
-
- range <<= 1;
-
- if ((lowvalue & 0x80000000))
- {
- int x = w->pos - 1;
-
- while (x >= 0 && w->buffer[x] == 0xff)
- {
- w->buffer[x] = (unsigned char)0;
- x--;
- }
-
- w->buffer[x] += 1;
-
- }
-
- lowvalue <<= 1;
-
- if (!++count)
- {
- count = -8;
- w->buffer[w->pos++] = (lowvalue >> 24);
- lowvalue &= 0xffffff;
- }
- }
-
- }
-
- ++p;
- }
- }
-
- w->count = count;
- w->lowvalue = lowvalue;
- w->range = range;
-
-}
-
static void write_mv_ref
(
vp8_writer *w, MB_PREDICTION_MODE m, const vp8_prob *p
@@ -803,7 +386,24 @@ static void write_mv
vp8_encode_motion_vector(w, &e, mvc);
}
-static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACROBLOCKD *x)
+#if CONFIG_HIGH_PRECISION_MV
+static void write_mv_hp
+(
+ vp8_writer *w, const MV *mv, const int_mv *ref, const MV_CONTEXT_HP *mvc
+)
+{
+ MV e;
+ e.row = mv->row - ref->as_mv.row;
+ e.col = mv->col - ref->as_mv.col;
+
+ vp8_encode_motion_vector_hp(w, &e, mvc);
+}
+#endif
+
+// This function writes the current macro block's segnment id to the bitstream
+// It should only be called if a segment map update is indicated.
+static void write_mb_segid(vp8_writer *w,
+ const MB_MODE_INFO *mi, const MACROBLOCKD *x)
{
// Encode the MB segment id.
if (x->segmentation_enabled && x->update_mb_segmentation_map)
@@ -836,43 +436,161 @@ static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACRO
}
}
+// This function encodes the reference frame
+static void encode_ref_frame( vp8_writer *const w,
+ VP8_COMMON *const cm,
+ MACROBLOCKD *xd,
+ int segment_id,
+ MV_REFERENCE_FRAME rf )
+{
+ int seg_ref_active;
+ int seg_ref_count = 0;
+ seg_ref_active = segfeature_active( xd,
+ segment_id,
+ SEG_LVL_REF_FRAME );
+
+ if ( seg_ref_active )
+ {
+ seg_ref_count = check_segref( xd, segment_id, INTRA_FRAME ) +
+ check_segref( xd, segment_id, LAST_FRAME ) +
+ check_segref( xd, segment_id, GOLDEN_FRAME ) +
+ check_segref( xd, segment_id, ALTREF_FRAME );
+ }
+
+ // If segment level coding of this signal is disabled...
+ // or the segment allows multiple reference frame options
+ if ( !seg_ref_active || (seg_ref_count > 1) )
+ {
+ // Values used in prediction model coding
+ unsigned char prediction_flag;
+ vp8_prob pred_prob;
+ MV_REFERENCE_FRAME pred_rf;
+
+ // Get the context probability the prediction flag
+ pred_prob = get_pred_prob( cm, xd, PRED_REF );
+
+ // Get the predicted value.
+ pred_rf = get_pred_ref( cm, xd );
+
+ // Did the chosen reference frame match its predicted value.
+ prediction_flag =
+ ( xd->mode_info_context->mbmi.ref_frame == pred_rf );
+
+ set_pred_flag( xd, PRED_REF, prediction_flag );
+ vp8_write( w, prediction_flag, pred_prob );
+
+ // If not predicted correctly then code value explicitly
+ if ( !prediction_flag )
+ {
+ vp8_prob mod_refprobs[PREDICTION_PROBS];
+
+ vpx_memcpy( mod_refprobs,
+ cm->mod_refprobs[pred_rf], sizeof(mod_refprobs) );
+
+ // If segment coding enabled blank out options that cant occur by
+ // setting the branch probability to 0.
+ if ( seg_ref_active )
+ {
+ mod_refprobs[INTRA_FRAME] *=
+ check_segref( xd, segment_id, INTRA_FRAME );
+ mod_refprobs[LAST_FRAME] *=
+ check_segref( xd, segment_id, LAST_FRAME );
+ mod_refprobs[GOLDEN_FRAME] *=
+ ( check_segref( xd, segment_id, GOLDEN_FRAME ) *
+ check_segref( xd, segment_id, ALTREF_FRAME ) );
+ }
+
+ if ( mod_refprobs[0] )
+ {
+ vp8_write(w, (rf != INTRA_FRAME), mod_refprobs[0] );
+ }
+
+ // Inter coded
+ if (rf != INTRA_FRAME)
+ {
+ if ( mod_refprobs[1] )
+ {
+ vp8_write(w, (rf != LAST_FRAME), mod_refprobs[1] );
+ }
+
+ if (rf != LAST_FRAME)
+ {
+ if ( mod_refprobs[2] )
+ {
+ vp8_write(w, (rf != GOLDEN_FRAME), mod_refprobs[2] );
+ }
+ }
+ }
+ }
+ }
+
+ // if using the prediction mdoel we have nothing further to do because
+ // the reference frame is fully coded by the segment
+}
+
+// Update the probabilities used to encode reference frame data
+static void update_ref_probs( VP8_COMP *const cpi )
+{
+ VP8_COMMON *const cm = & cpi->common;
+
+ const int *const rfct = cpi->count_mb_ref_frame_usage;
+ const int rf_intra = rfct[INTRA_FRAME];
+ const int rf_inter = rfct[LAST_FRAME] +
+ rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+ cm->prob_intra_coded = (rf_intra + rf_inter)
+ ? rf_intra * 255 / (rf_intra + rf_inter) : 1;
+
+ if (!cm->prob_intra_coded)
+ cm->prob_intra_coded = 1;
+
+ cm->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+ if (!cm->prob_last_coded)
+ cm->prob_last_coded = 1;
+
+ cm->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+ ? (rfct[GOLDEN_FRAME] * 255) /
+ (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+ if (!cm->prob_gf_coded)
+ cm->prob_gf_coded = 1;
+
+ // Compute a modified set of probabilities to use when prediction of the
+ // reference frame fails
+ compute_mod_refprobs( cm );
+}
static void pack_inter_mode_mvs(VP8_COMP *const cpi)
{
VP8_COMMON *const pc = & cpi->common;
vp8_writer *const w = & cpi->bc;
const MV_CONTEXT *mvc = pc->fc.mvc;
+#if CONFIG_HIGH_PRECISION_MV
+ const MV_CONTEXT_HP *mvc_hp = pc->fc.mvc_hp;
+#endif
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
- const int *const rfct = cpi->count_mb_ref_frame_usage;
- const int rf_intra = rfct[INTRA_FRAME];
- const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+ int i;
+ int pred_context;
+
+
+ MODE_INFO *m = pc->mi;
+ MODE_INFO *prev_m = pc->prev_mi;
- MODE_INFO *m = pc->mi, *ms;
const int mis = pc->mode_info_stride;
int mb_row = -1;
- int prob_last_coded;
- int prob_gf_coded;
int prob_skip_false = 0;
- ms = pc->mi - 1;
-
- cpi->mb.partition_info = cpi->mb.pi;
-
- // Calculate the probabilities to be used to code the reference frame based on actual useage this frame
- if (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter)))
- cpi->prob_intra_coded = 1;
-
- prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
- if (!prob_last_coded)
- prob_last_coded = 1;
+ // Values used in prediction model coding
+ vp8_prob pred_prob;
+ unsigned char prediction_flag;
- prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
- ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
-
- if (!prob_gf_coded)
- prob_gf_coded = 1;
+ cpi->mb.partition_info = cpi->mb.pi;
+ // Update the probabilities used to encode reference frame data
+ update_ref_probs( cpi );
#ifdef ENTROPY_STATS
active_section = 1;
@@ -880,24 +598,66 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
if (pc->mb_no_coeff_skip)
{
- prob_skip_false = cpi->skip_false_count * 256 / (cpi->skip_false_count + cpi->skip_true_count);
+ // Divide by 0 check. 0 case possible with segment features
+ if ( (cpi->skip_false_count + cpi->skip_true_count) )
+ {
+ prob_skip_false = cpi->skip_false_count * 256 /
+ (cpi->skip_false_count + cpi->skip_true_count);
- if (prob_skip_false <= 1)
- prob_skip_false = 1;
+ if (prob_skip_false <= 1)
+ prob_skip_false = 1;
- if (prob_skip_false > 255)
+ if (prob_skip_false > 255)
+ prob_skip_false = 255;
+ }
+ else
prob_skip_false = 255;
cpi->prob_skip_false = prob_skip_false;
vp8_write_literal(w, prob_skip_false, 8);
}
- vp8_write_literal(w, cpi->prob_intra_coded, 8);
- vp8_write_literal(w, prob_last_coded, 8);
- vp8_write_literal(w, prob_gf_coded, 8);
+ vp8_write_literal(w, pc->prob_intra_coded, 8);
+ vp8_write_literal(w, pc->prob_last_coded, 8);
+ vp8_write_literal(w, pc->prob_gf_coded, 8);
+
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
+ {
+ vp8_write(w, 1, 128);
+ vp8_write(w, 1, 128);
+ for (i = 0; i < COMP_PRED_CONTEXTS; i++)
+ {
+ if (cpi->single_pred_count[i] + cpi->comp_pred_count[i])
+ {
+ pc->prob_comppred[i] = cpi->single_pred_count[i] * 255 /
+ (cpi->single_pred_count[i] + cpi->comp_pred_count[i]);
+ if (pc->prob_comppred[i] < 1)
+ pc->prob_comppred[i] = 1;
+ }
+ else
+ {
+ pc->prob_comppred[i] = 128;
+ }
+ vp8_write_literal(w, pc->prob_comppred[i], 8);
+ }
+ }
+ else if (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY)
+ {
+ vp8_write(w, 0, 128);
+ }
+ else /* compound prediction only */
+ {
+ vp8_write(w, 1, 128);
+ vp8_write(w, 0, 128);
+ }
update_mbintra_mode_probs(cpi);
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ vp8_write_mvprobs_hp(cpi);
+ else
+#endif
vp8_write_mvprobs(cpi);
while (++mb_row < pc->mb_rows)
@@ -909,8 +669,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
const MB_MODE_INFO *const mi = & m->mbmi;
const MV_REFERENCE_FRAME rf = mi->ref_frame;
const MB_PREDICTION_MODE mode = mi->mode;
-
- MACROBLOCKD *xd = &cpi->mb.e_mbd;
+ const int segment_id = mi->segment_id;
// Distance of Mb to the various image edges.
// These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
@@ -919,164 +678,284 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
xd->mb_to_top_edge = -((mb_row * 16)) << 3;
xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+ // Make sure the MacroBlockD mode info pointer is set correctly
+ xd->mode_info_context = m;
+
+ xd->prev_mode_info_context = prev_m;
+
#ifdef ENTROPY_STATS
active_section = 9;
#endif
if (cpi->mb.e_mbd.update_mb_segmentation_map)
- write_mb_features(w, mi, &cpi->mb.e_mbd);
+ {
+ // Is temporal coding of the segment map enabled
+ if (pc->temporal_update)
+ {
+ prediction_flag =
+ get_pred_flag( xd, PRED_SEG_ID );
+ pred_prob =
+ get_pred_prob( pc, xd, PRED_SEG_ID);
+
+ // Code the segment id prediction flag for this mb
+ vp8_write( w, prediction_flag, pred_prob );
+
+ // If the mbs segment id was not predicted code explicitly
+ if (!prediction_flag)
+ write_mb_segid(w, mi, &cpi->mb.e_mbd);
+ }
+ else
+ {
+ // Normal undpredicted coding
+ write_mb_segid(w, mi, &cpi->mb.e_mbd);
+ }
+ }
+
+ if ( pc->mb_no_coeff_skip &&
+ ( !segfeature_active( xd, segment_id, SEG_LVL_EOB ) ||
+ ( get_segdata( xd, segment_id, SEG_LVL_EOB ) != 0 ) ) )
+ {
+ vp8_encode_bool(w, mi->mb_skip_coeff, prob_skip_false);
+ }
- if (pc->mb_no_coeff_skip)
- vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false);
+ // Encode the reference frame.
+ encode_ref_frame( w, pc, xd,
+ segment_id, rf );
if (rf == INTRA_FRAME)
{
- vp8_write(w, 0, cpi->prob_intra_coded);
#ifdef ENTROPY_STATS
active_section = 6;
#endif
- write_ymode(w, mode, pc->fc.ymode_prob);
+
+ if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) )
+ write_ymode(w, mode, pc->fc.ymode_prob);
if (mode == B_PRED)
{
int j = 0;
-
- do
- write_bmode(w, m->bmi[j].as_mode, pc->fc.bmode_prob);
- while (++j < 16);
+#if CONFIG_COMP_INTRA_PRED
+ int uses_second = m->bmi[0].as_mode.second != (B_PREDICTION_MODE) (B_DC_PRED - 1);
+ vp8_write(w, uses_second, 128);
+#endif
+ do {
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE mode2 = m->bmi[j].as_mode.second;
+#endif
+ write_bmode(w, m->bmi[j].as_mode.first, pc->fc.bmode_prob);
+#if CONFIG_COMP_INTRA_PRED
+ if (uses_second)
+ {
+ write_bmode(w, mode2, pc->fc.bmode_prob);
+ }
+#endif
+ } while (++j < 16);
}
+ if(mode == I8X8_PRED)
+ {
+ write_i8x8_mode(w, m->bmi[0].as_mode.first, pc->i8x8_mode_prob);
+ write_i8x8_mode(w, m->bmi[2].as_mode.first, pc->i8x8_mode_prob);
+ write_i8x8_mode(w, m->bmi[8].as_mode.first, pc->i8x8_mode_prob);
+ write_i8x8_mode(w, m->bmi[10].as_mode.first, pc->i8x8_mode_prob);
+ }
+ else
+ {
+#if CONFIG_UVINTRA
+ write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob[mode]);
+#ifdef MODE_STATS
+ if(mode!=B_PRED)
+ ++cpi->y_uv_mode_count[mode][mi->uv_mode];
+#endif
- write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
+#else
+ write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
+#endif /*CONFIG_UVINTRA*/
+
+ }
}
- else /* inter coded */
+ else
{
int_mv best_mv;
- vp8_prob mv_ref_p [VP8_MVREFS-1];
-
- vp8_write(w, 1, cpi->prob_intra_coded);
+ int ct[4];
- if (rf == LAST_FRAME)
- vp8_write(w, 0, prob_last_coded);
- else
- {
- vp8_write(w, 1, prob_last_coded);
- vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, prob_gf_coded);
- }
+ vp8_prob mv_ref_p [VP8_MVREFS-1];
{
int_mv n1, n2;
- int ct[4];
- vp8_find_near_mvs(xd, m, &n1, &n2, &best_mv, ct, rf, cpi->common.ref_frame_sign_bias);
- vp8_mv_ref_probs(mv_ref_p, ct);
+ vp8_find_near_mvs(xd, m,
+ prev_m,
+ &n1, &n2, &best_mv, ct, rf, cpi->common.ref_frame_sign_bias);
+ vp8_mv_ref_probs(&cpi->common, mv_ref_p, ct);
+
#ifdef ENTROPY_STATS
accum_mv_refs(mode, ct);
#endif
-
}
#ifdef ENTROPY_STATS
active_section = 3;
#endif
- write_mv_ref(w, mode, mv_ref_p);
-
- switch (mode) /* new, split require MVs */
+ // Is the segment coding of mode enabled
+ if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) )
{
- case NEWMV:
+ write_mv_ref(w, mode, mv_ref_p);
+ vp8_accum_mv_refs(&cpi->common, mode, ct);
+ }
+ {
+ switch (mode) /* new, split require MVs */
+ {
+ case NEWMV:
#ifdef ENTROPY_STATS
- active_section = 5;
+ active_section = 5;
#endif
- write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
- break;
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ write_mv_hp(w, &mi->mv.as_mv, &best_mv, mvc_hp);
+ else
+#endif
+ write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
- case SPLITMV:
- {
- int j = 0;
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
+ {
+ vp8_write(w, mi->second_ref_frame != INTRA_FRAME,
+ get_pred_prob( pc, xd, PRED_COMP ) );
+ }
+ if (mi->second_ref_frame)
+ {
+ const int second_rf = mi->second_ref_frame;
+ int_mv n1, n2;
+ int ct[4];
+ vp8_find_near_mvs(xd, m,
+ prev_m,
+ &n1, &n2, &best_mv,
+ ct, second_rf,
+ cpi->common.ref_frame_sign_bias);
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ write_mv_hp(w, &mi->second_mv.as_mv, &best_mv, mvc_hp);
+ else
+#endif
+ write_mv(w, &mi->second_mv.as_mv, &best_mv, mvc);
+ }
+ break;
+ case SPLITMV:
+ {
+ int j = 0;
#ifdef MODE_STATS
- ++count_mb_seg [mi->partitioning];
+ ++count_mb_seg [mi->partitioning];
#endif
- write_split(w, mi->partitioning);
+ write_split(w, mi->partitioning);
- do
- {
- B_PREDICTION_MODE blockmode;
- int_mv blockmv;
- const int *const L = vp8_mbsplits [mi->partitioning];
- int k = -1; /* first block in subset j */
- int mv_contz;
- int_mv leftmv, abovemv;
-
- blockmode = cpi->mb.partition_info->bmi[j].mode;
- blockmv = cpi->mb.partition_info->bmi[j].mv;
+ do
+ {
+ B_PREDICTION_MODE blockmode;
+ int_mv blockmv;
+ const int *const L = vp8_mbsplits [mi->partitioning];
+ int k = -1; /* first block in subset j */
+ int mv_contz;
+ int_mv leftmv, abovemv;
+
+ blockmode = cpi->mb.partition_info->bmi[j].mode;
+ blockmv = cpi->mb.partition_info->bmi[j].mv;
#if CONFIG_DEBUG
- while (j != L[++k])
- if (k >= 16)
- assert(0);
+ while (j != L[++k])
+ if (k >= 16)
+ assert(0);
#else
- while (j != L[++k]);
+ while (j != L[++k]);
#endif
- leftmv.as_int = left_block_mv(m, k);
- abovemv.as_int = above_block_mv(m, k, mis);
- mv_contz = vp8_mv_cont(&leftmv, &abovemv);
+ leftmv.as_int = left_block_mv(m, k);
+ abovemv.as_int = above_block_mv(m, k, mis);
+ mv_contz = vp8_mv_cont(&leftmv, &abovemv);
- write_sub_mv_ref(w, blockmode, vp8_sub_mv_ref_prob2 [mv_contz]);
+ write_sub_mv_ref(w, blockmode, vp8_sub_mv_ref_prob2 [mv_contz]);
- if (blockmode == NEW4X4)
- {
+ if (blockmode == NEW4X4)
+ {
#ifdef ENTROPY_STATS
- active_section = 11;
+ active_section = 11;
#endif
- write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc);
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ write_mv_hp(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT_HP *) mvc_hp);
+ else
+#endif
+ write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc);
+ }
}
+ while (++j < cpi->mb.partition_info->count);
}
- while (++j < cpi->mb.partition_info->count);
- }
- break;
- default:
break;
+ default:
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
+ {
+ vp8_write(w, mi->second_ref_frame != INTRA_FRAME,
+ get_pred_prob( pc, xd, PRED_COMP ) );
+ }
+ break;
+ }
}
}
++m;
+ ++prev_m;
+ assert((prev_m-cpi->common.prev_mip)==(m-cpi->common.mip));
+ assert((prev_m-cpi->common.prev_mi)==(m-cpi->common.mi));
cpi->mb.partition_info++;
}
++m; /* skip L prediction border */
+ ++prev_m;
cpi->mb.partition_info++;
}
}
-
static void write_kfmodes(VP8_COMP *cpi)
{
vp8_writer *const bc = & cpi->bc;
const VP8_COMMON *const c = & cpi->common;
/* const */
MODE_INFO *m = c->mi;
-
int mb_row = -1;
int prob_skip_false = 0;
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
+
if (c->mb_no_coeff_skip)
{
- prob_skip_false = cpi->skip_false_count * 256 / (cpi->skip_false_count + cpi->skip_true_count);
+ // Divide by 0 check. 0 case possible with segment features
+ if ( (cpi->skip_false_count + cpi->skip_true_count) )
+ {
+ prob_skip_false = cpi->skip_false_count * 256 /
+ (cpi->skip_false_count + cpi->skip_true_count);
- if (prob_skip_false <= 1)
- prob_skip_false = 1;
+ if (prob_skip_false <= 1)
+ prob_skip_false = 1;
- if (prob_skip_false >= 255)
+ if (prob_skip_false > 255)
+ prob_skip_false = 255;
+ }
+ else
prob_skip_false = 255;
cpi->prob_skip_false = prob_skip_false;
vp8_write_literal(bc, prob_skip_false, 8);
}
+#if CONFIG_QIMODE
+ if(!c->kf_ymode_probs_update)
+ {
+ vp8_write_literal(bc, c->kf_ymode_probs_index, 3);
+ }
+#endif
+
while (++mb_row < c->mb_rows)
{
int mb_col = -1;
@@ -1084,42 +963,76 @@ static void write_kfmodes(VP8_COMP *cpi)
while (++mb_col < c->mb_cols)
{
const int ym = m->mbmi.mode;
+ int segment_id = m->mbmi.segment_id;
if (cpi->mb.e_mbd.update_mb_segmentation_map)
- write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd);
+ {
+ write_mb_segid(bc, &m->mbmi, &cpi->mb.e_mbd);
+ }
- if (c->mb_no_coeff_skip)
+ if ( c->mb_no_coeff_skip &&
+ ( !segfeature_active( xd, segment_id, SEG_LVL_EOB ) ||
+ (get_segdata( xd, segment_id, SEG_LVL_EOB ) != 0) ) )
+ {
vp8_encode_bool(bc, m->mbmi.mb_skip_coeff, prob_skip_false);
-
+ }
+#if CONFIG_QIMODE
+ kfwrite_ymode(bc, ym, c->kf_ymode_prob[c->kf_ymode_probs_index]);
+#else
kfwrite_ymode(bc, ym, c->kf_ymode_prob);
-
+#endif
if (ym == B_PRED)
{
const int mis = c->mode_info_stride;
int i = 0;
-
+#if CONFIG_COMP_INTRA_PRED
+ int uses_second = m->bmi[0].as_mode.second != (B_PREDICTION_MODE) (B_DC_PRED - 1);
+ vp8_write(bc, uses_second, 128);
+#endif
do
{
const B_PREDICTION_MODE A = above_block_mode(m, i, mis);
const B_PREDICTION_MODE L = left_block_mode(m, i);
- const int bm = m->bmi[i].as_mode;
+ const int bm = m->bmi[i].as_mode.first;
+#if CONFIG_COMP_INTRA_PRED
+ const int bm2 = m->bmi[i].as_mode.second;
+#endif
#ifdef ENTROPY_STATS
++intra_mode_stats [A] [L] [bm];
#endif
write_bmode(bc, bm, c->kf_bmode_prob [A] [L]);
+#if CONFIG_COMP_INTRA_PRED
+ if (uses_second)
+ {
+ write_bmode(bc, bm2, c->kf_bmode_prob [A] [L]);
+ }
+#endif
}
while (++i < 16);
}
-
- write_uv_mode(bc, (m++)->mbmi.uv_mode, c->kf_uv_mode_prob);
+ if(ym == I8X8_PRED)
+ {
+ write_i8x8_mode(bc, m->bmi[0].as_mode.first, c->i8x8_mode_prob);
+ write_i8x8_mode(bc, m->bmi[2].as_mode.first, c->i8x8_mode_prob);
+ write_i8x8_mode(bc, m->bmi[8].as_mode.first, c->i8x8_mode_prob);
+ write_i8x8_mode(bc, m->bmi[10].as_mode.first, c->i8x8_mode_prob);
+ m++;
+ }
+ else
+#if CONFIG_UVINTRA
+ write_uv_mode(bc, (m++)->mbmi.uv_mode, c->kf_uv_mode_prob[ym]);
+#else
+ write_uv_mode(bc, (m++)->mbmi.uv_mode, c->kf_uv_mode_prob);
+#endif
}
-
+ //printf("\n");
m++; // skip L prediction border
}
}
+
/* This function is used for debugging probability trees. */
static void print_prob_tree(vp8_prob
coef_probs[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES])
@@ -1182,84 +1095,6 @@ static int prob_update_savings(const unsigned int *ct,
return old_b - new_b - update_b;
}
-static int independent_coef_context_savings(VP8_COMP *cpi)
-{
- int savings = 0;
- int i = 0;
- do
- {
- int j = 0;
- do
- {
- int k = 0;
- unsigned int prev_coef_count_sum[MAX_ENTROPY_TOKENS] = {0};
- int prev_coef_savings[MAX_ENTROPY_TOKENS] = {0};
- /* Calculate new probabilities given the constraint that
- * they must be equal over the prev coef contexts
- */
- if (cpi->common.frame_type == KEY_FRAME)
- {
- /* Reset to default probabilities at key frames */
- sum_probs_over_prev_coef_context(default_coef_counts[i][j],
- prev_coef_count_sum);
- }
- else
- {
- sum_probs_over_prev_coef_context(cpi->coef_counts[i][j],
- prev_coef_count_sum);
- }
- do
- {
- /* at every context */
-
- /* calc probs and branch cts for this frame only */
- //vp8_prob new_p [ENTROPY_NODES];
- //unsigned int branch_ct [ENTROPY_NODES] [2];
-
- int t = 0; /* token/prob index */
-
- vp8_tree_probs_from_distribution(
- MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
- cpi->frame_coef_probs[i][j][k],
- cpi->frame_branch_ct [i][j][k],
- prev_coef_count_sum,
- 256, 1);
-
- do
- {
- const unsigned int *ct = cpi->frame_branch_ct [i][j][k][t];
- const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
- const vp8_prob oldp = cpi->common.fc.coef_probs [i][j][k][t];
- const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
- const int s = prob_update_savings(ct, oldp, newp, upd);
-
- if (cpi->common.frame_type != KEY_FRAME ||
- (cpi->common.frame_type == KEY_FRAME && newp != oldp))
- prev_coef_savings[t] += s;
- }
- while (++t < ENTROPY_NODES);
- }
- while (++k < PREV_COEF_CONTEXTS);
- k = 0;
- do
- {
- /* We only update probabilities if we can save bits, except
- * for key frames where we have to update all probabilities
- * to get the equal probabilities across the prev coef
- * contexts.
- */
- if (prev_coef_savings[k] > 0 ||
- cpi->common.frame_type == KEY_FRAME)
- savings += prev_coef_savings[k];
- }
- while (++k < ENTROPY_NODES);
- }
- while (++j < COEF_BANDS);
- }
- while (++i < BLOCK_TYPES);
- return savings;
-}
-
static int default_coef_context_savings(VP8_COMP *cpi)
{
int savings = 0;
@@ -1315,24 +1150,32 @@ static int default_coef_context_savings(VP8_COMP *cpi)
int vp8_estimate_entropy_savings(VP8_COMP *cpi)
{
int savings = 0;
-
+ int i=0;
+ VP8_COMMON *const cm = & cpi->common;
const int *const rfct = cpi->count_mb_ref_frame_usage;
const int rf_intra = rfct[INTRA_FRAME];
const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
- int new_intra, new_last, gf_last, oldtotal, newtotal;
+ int new_intra, new_last, new_gf_alt, oldtotal, newtotal;
int ref_frame_cost[MAX_REF_FRAMES];
vp8_clear_system_state(); //__asm emms;
+ // Estimate reference frame cost savings.
+ // For now this is just based on projected overall frequency of
+ // each reference frame coded using an unpredicted coding tree.
if (cpi->common.frame_type != KEY_FRAME)
{
- if (!(new_intra = rf_intra * 255 / (rf_intra + rf_inter)))
- new_intra = 1;
+ new_intra = (rf_intra + rf_inter)
+ ? rf_intra * 255 / (rf_intra + rf_inter) : 1;
+ new_intra += !new_intra;
new_last = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+ new_last += !new_last;
- gf_last = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
- ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+ new_gf_alt = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+ ? (rfct[GOLDEN_FRAME] * 255) /
+ (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+ new_gf_alt += !new_gf_alt;
// new costs
ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(new_intra);
@@ -1340,10 +1183,10 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
+ vp8_cost_zero(new_last);
ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(new_intra)
+ vp8_cost_one(new_last)
- + vp8_cost_zero(gf_last);
+ + vp8_cost_zero(new_gf_alt);
ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(new_intra)
+ vp8_cost_one(new_last)
- + vp8_cost_one(gf_last);
+ + vp8_cost_one(new_gf_alt);
newtotal =
rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
@@ -1351,17 +1194,16 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
-
// old costs
- ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cpi->prob_intra_coded);
- ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_zero(cpi->prob_last_coded);
- ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_one(cpi->prob_last_coded)
- + vp8_cost_zero(cpi->prob_gf_coded);
- ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_one(cpi->prob_last_coded)
- + vp8_cost_one(cpi->prob_gf_coded);
+ ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cm->prob_intra_coded);
+ ref_frame_cost[LAST_FRAME] = vp8_cost_one(cm->prob_intra_coded)
+ + vp8_cost_zero(cm->prob_last_coded);
+ ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cm->prob_intra_coded)
+ + vp8_cost_one(cm->prob_last_coded)
+ + vp8_cost_zero(cm->prob_gf_coded);
+ ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cm->prob_intra_coded)
+ + vp8_cost_one(cm->prob_last_coded)
+ + vp8_cost_one(cm->prob_gf_coded);
oldtotal =
rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
@@ -1370,14 +1212,77 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
savings += (oldtotal - newtotal) / 256;
+
+ // Update the reference frame probability numbers to reflect
+ // the observed counts in this frame. Doing this here insures
+ // that if there are multiple recode iterations the baseline
+ // probabilities used are updated in each iteration.
+ cm->prob_intra_coded = new_intra;
+ cm->prob_last_coded = new_last;
+ cm->prob_gf_coded = new_gf_alt;
}
+ savings += default_coef_context_savings(cpi);
- if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
- savings += independent_coef_context_savings(cpi);
- else
- savings += default_coef_context_savings(cpi);
+ /* do not do this if not evena allowed */
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ {
+ int savings8x8 = 0;
+ do
+ {
+ int j = 0;
+ do
+ {
+ int k = 0;
+ do
+ {
+ /* at every context */
+ /* calc probs and branch cts for this frame only */
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
+ int t = 0; /* token/prob index */
+ vp8_tree_probs_from_distribution(
+ MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ cpi->frame_coef_probs_8x8 [i][j][k],
+ cpi->frame_branch_ct_8x8 [i][j][k],
+ cpi->coef_counts_8x8 [i][j][k],
+ 256, 1
+ );
+
+ do
+ {
+ const unsigned int *ct = cpi->frame_branch_ct_8x8 [i][j][k][t];
+ const vp8_prob newp = cpi->frame_coef_probs_8x8 [i][j][k][t];
+
+ const vp8_prob old = cpi->common.fc.coef_probs_8x8 [i][j][k][t];
+ const vp8_prob upd = vp8_coef_update_probs_8x8 [i][j][k][t];
+
+ const int old_b = vp8_cost_branch(ct, old);
+ const int new_b = vp8_cost_branch(ct, newp);
+
+ const int update_b = 8 +
+ ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+
+ const int s = old_b - new_b - update_b;
+
+ if (s > 0)
+ savings8x8 += s;
+
+
+ }
+ while (++t < MAX_ENTROPY_TOKENS - 1);
+
+
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
+
+ savings += savings8x8 >> 8;
+ }
return savings;
}
@@ -1386,125 +1291,265 @@ static void update_coef_probs(VP8_COMP *cpi)
{
int i = 0;
vp8_writer *const w = & cpi->bc;
- int savings = 0;
+ int update = 0;
vp8_clear_system_state(); //__asm emms;
-
+ /* dry run to see if there is any udpate at all needed */
do
{
int j = 0;
-
do
{
int k = 0;
int prev_coef_savings[ENTROPY_NODES] = {0};
- if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
- {
- for (k = 0; k < PREV_COEF_CONTEXTS; ++k)
- {
- int t; /* token/prob index */
- for (t = 0; t < ENTROPY_NODES; ++t)
- {
- const unsigned int *ct = cpi->frame_branch_ct [i][j]
- [k][t];
- const vp8_prob newp = cpi->frame_coef_probs[i][j][k][t];
- const vp8_prob oldp = cpi->common.fc.coef_probs[i][j]
- [k][t];
- const vp8_prob upd = vp8_coef_update_probs[i][j][k][t];
-
- prev_coef_savings[t] +=
- prob_update_savings(ct, oldp, newp, upd);
- }
- }
- k = 0;
- }
do
{
//note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
/* at every context */
-
/* calc probs and branch cts for this frame only */
//vp8_prob new_p [ENTROPY_NODES];
//unsigned int branch_ct [ENTROPY_NODES] [2];
-
int t = 0; /* token/prob index */
-
//vp8_tree_probs_from_distribution(
// MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
// new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
// 256, 1
// );
-
do
{
const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
-
vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
-
int s = prev_coef_savings[t];
int u = 0;
- if (!(cpi->oxcf.error_resilient_mode &
- VPX_ERROR_RESILIENT_PARTITIONS))
- {
- s = prob_update_savings(
- cpi->frame_branch_ct [i][j][k][t],
- *Pold, newp, upd);
- }
+ s = prob_update_savings(
+ cpi->frame_branch_ct [i][j][k][t],
+ *Pold, newp, upd);
if (s > 0)
u = 1;
- /* Force updates on key frames if the new is different,
- * so that we can be sure we end up with equal probabilities
- * over the prev coef contexts.
- */
- if ((cpi->oxcf.error_resilient_mode &
- VPX_ERROR_RESILIENT_PARTITIONS) &&
- cpi->common.frame_type == KEY_FRAME && newp != *Pold)
- u = 1;
+ update += u;
+ }
+ while (++t < ENTROPY_NODES);
+ /* Accum token counts for generation of default statistics */
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
+ /* Is coef updated at all */
+ if(update==0)
+ {
+ vp8_write_bit(w, 0);
+ }
+ else
+ {
+ vp8_write_bit(w, 1);
+ i=0;
+ do
+ {
+ int j = 0;
+ do
+ {
+ int k = 0;
+ int prev_coef_savings[ENTROPY_NODES] = {0};
- vp8_write(w, u, upd);
+ do
+ {
+ //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+ /* at every context */
+
+ /* calc probs and branch cts for this frame only */
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
+ int t = 0; /* token/prob index */
+ //vp8_tree_probs_from_distribution(
+ // MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ // new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+ // 256, 1
+ // );
+ do
+ {
+ const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+ vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
+ const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+ int s = prev_coef_savings[t];
+ int u = 0;
+ s = prob_update_savings(
+ cpi->frame_branch_ct [i][j][k][t],
+ *Pold, newp, upd);
+
+ if (s > 0)
+ u = 1;
+ vp8_write(w, u, upd);
+#ifdef ENTROPY_STATS
+ ++ tree_update_hist [i][j][k][t] [u];
+#endif
+ if (u)
+ {
+ /* send/use new probability */
+ *Pold = newp;
+ vp8_write_literal(w, newp, 8);
+ }
+ }
+ while (++t < ENTROPY_NODES);
+ /* Accum token counts for generation of default statistics */
#ifdef ENTROPY_STATS
- ++ tree_update_hist [i][j][k][t] [u];
+ t = 0;
+ do
+ {
+ context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
+ }
+ while (++t < MAX_ENTROPY_TOKENS);
#endif
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
+ }
- if (u)
+
+ /* do not do this if not evena allowed */
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ {
+ /* dry run to see if update is necessary */
+ update = 0;
+ i = 0;
+ do
+ {
+ int j = 0;
+ do
+ {
+ int k = 0;
+ do
+ {
+ //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+ /* at every context */
+ /* calc probs and branch cts for this frame only */
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
+ int t = 0; /* token/prob index */
+ //vp8_tree_probs_from_distribution(
+ // MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ // new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+ // 256, 1
+ // );
+ do
{
- /* send/use new probability */
+ const unsigned int *ct = cpi->frame_branch_ct_8x8 [i][j][k][t];
+ const vp8_prob newp = cpi->frame_coef_probs_8x8 [i][j][k][t];
+ vp8_prob *Pold = cpi->common.fc.coef_probs_8x8 [i][j][k] + t;
+ const vp8_prob old = *Pold;
+ const vp8_prob upd = vp8_coef_update_probs_8x8 [i][j][k][t];
+ const int old_b = vp8_cost_branch(ct, old);
+ const int new_b = vp8_cost_branch(ct, newp);
+ const int update_b = 8 +
+ ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+ const int s = old_b - new_b - update_b;
+ const int u = s > 0 ? 1 : 0;
- *Pold = newp;
- vp8_write_literal(w, newp, 8);
+#ifdef ENTROPY_STATS
+ ++ tree_update_hist_8x8 [i][j][k][t] [u];
+#endif
+ update += u;
+ }
+ while (++t < MAX_ENTROPY_TOKENS - 1);
- savings += s;
+ /* Accum token counts for generation of default statistics */
+#ifdef ENTROPY_STATS
+ t = 0;
+ do
+ {
+ context_counters_8x8 [i][j][k][t] += cpi->coef_counts_8x8 [i][j][k][t];
}
+ while (++t < MAX_ENTROPY_TOKENS);
+#endif
}
- while (++t < ENTROPY_NODES);
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
- /* Accum token counts for generation of default statistics */
-#ifdef ENTROPY_STATS
- t = 0;
+ if(update == 0)
+ {
+ vp8_write_bit(w, 0);
+ }
+ else
+ {
+ vp8_write_bit(w, 1);
+ i = 0;
+ do
+ {
+ int j = 0;
do
{
- context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
- }
- while (++t < MAX_ENTROPY_TOKENS);
-
+ int k = 0;
+ do
+ {
+ //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+ /* at every context */
+ /* calc probs and branch cts for this frame only */
+ //vp8_prob new_p [ENTROPY_NODES];
+ //unsigned int branch_ct [ENTROPY_NODES] [2];
+ int t = 0; /* token/prob index */
+ //vp8_tree_probs_from_distribution(
+ // MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+ // new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+ // 256, 1
+ // );
+ do
+ {
+ const unsigned int *ct = cpi->frame_branch_ct_8x8 [i][j][k][t];
+ const vp8_prob newp = cpi->frame_coef_probs_8x8 [i][j][k][t];
+ vp8_prob *Pold = cpi->common.fc.coef_probs_8x8 [i][j][k] + t;
+ const vp8_prob old = *Pold;
+ const vp8_prob upd = vp8_coef_update_probs_8x8 [i][j][k][t];
+ const int old_b = vp8_cost_branch(ct, old);
+ const int new_b = vp8_cost_branch(ct, newp);
+ const int update_b = 8 +
+ ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+ const int s = old_b - new_b - update_b;
+ const int u = s > 0 ? 1 : 0;
+ vp8_write(w, u, upd);
+#ifdef ENTROPY_STATS
+ ++ tree_update_hist_8x8 [i][j][k][t] [u];
#endif
-
+ if (u)
+ {
+ /* send/use new probability */
+ *Pold = newp;
+ vp8_write_literal(w, newp, 8);
+ }
+ }
+ while (++t < MAX_ENTROPY_TOKENS - 1);
+ /* Accum token counts for generation of default statistics */
+#ifdef ENTROPY_STATS
+ t = 0;
+ do
+ {
+ context_counters_8x8 [i][j][k][t] += cpi->coef_counts_8x8 [i][j][k][t];
+ }
+ while (++t < MAX_ENTROPY_TOKENS);
+#endif
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
}
- while (++k < PREV_COEF_CONTEXTS);
+ while (++i < BLOCK_TYPES);
}
- while (++j < COEF_BANDS);
}
- while (++i < BLOCK_TYPES);
-
}
#ifdef PACKET_TESTING
FILE *vpxlogc = 0;
@@ -1525,7 +1570,60 @@ static void put_delta_q(vp8_writer *bc, int delta_q)
else
vp8_write_bit(bc, 0);
}
+#if CONFIG_QIMODE
+extern const unsigned int kf_y_mode_cts[8][VP8_YMODES];
+static void decide_kf_ymode_entropy(VP8_COMP *cpi)
+{
+
+ int mode_cost[MB_MODE_COUNT];
+ int cost;
+ int bestcost = INT_MAX;
+ int bestindex = 0;
+ int i, j;
+
+ for(i=0; i<8; i++)
+ {
+ vp8_cost_tokens(mode_cost, cpi->common.kf_ymode_prob[i], vp8_kf_ymode_tree);
+ cost = 0;
+ for(j=0;j<VP8_YMODES;j++)
+ {
+ cost += mode_cost[j] * cpi->ymode_count[j];
+ }
+ if(cost < bestcost)
+ {
+ bestindex = i;
+ bestcost = cost;
+ }
+ }
+ cpi->common.kf_ymode_probs_index = bestindex;
+
+}
+#endif
+static segment_reference_frames(VP8_COMP *cpi)
+{
+ VP8_COMMON *oci = &cpi->common;
+ MODE_INFO *mi = oci->mi;
+ int ref[MAX_MB_SEGMENTS]={0};
+ int i,j;
+ int mb_index=0;
+ MACROBLOCKD *const xd = & cpi->mb.e_mbd;
+
+ for (i = 0; i < oci->mb_rows; i++)
+ {
+ for (j = 0; j < oci->mb_cols; j++, mb_index++)
+ {
+ ref[mi[mb_index].mbmi.segment_id]|=(1<<mi[mb_index].mbmi.ref_frame);
+ }
+ mb_index++;
+ }
+ for (i = 0; i < MAX_MB_SEGMENTS; i++)
+ {
+ enable_segfeature(xd,i,SEG_LVL_REF_FRAME);
+ set_segdata( xd,i, SEG_LVL_REF_FRAME, ref[i]);
+ }
+
+}
void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
{
int i, j;
@@ -1536,14 +1634,12 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
int extra_bytes_packed = 0;
unsigned char *cx_data = dest;
- const int *mb_feature_data_bits;
oh.show_frame = (int) pc->show_frame;
oh.type = (int)pc->frame_type;
oh.version = pc->version;
oh.first_partition_length_in_bytes = 0;
- mb_feature_data_bits = vp8_mb_feature_data_bits;
cx_data += 3;
#if defined(SECTIONBITS_OUTPUT)
@@ -1586,57 +1682,133 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
else
vp8_start_encode(bc, cx_data);
-
// Signal whether or not Segmentation is enabled
vp8_write_bit(bc, (xd->segmentation_enabled) ? 1 : 0);
// Indicate which features are enabled
- if (xd->segmentation_enabled)
+ if ( xd->segmentation_enabled )
{
- // Signal whether or not the segmentation map is being updated.
+ // Indicate whether or not the segmentation map is being updated.
vp8_write_bit(bc, (xd->update_mb_segmentation_map) ? 1 : 0);
+
+ // If it is, then indicate the method that will be used.
+ if ( xd->update_mb_segmentation_map )
+ vp8_write_bit(bc, (pc->temporal_update) ? 1:0);
+
vp8_write_bit(bc, (xd->update_mb_segmentation_data) ? 1 : 0);
+ //segment_reference_frames(cpi);
+
if (xd->update_mb_segmentation_data)
{
signed char Data;
- vp8_write_bit(bc, (xd->mb_segement_abs_delta) ? 1 : 0);
+ vp8_write_bit(bc, (xd->mb_segment_abs_delta) ? 1 : 0);
- // For each segmentation feature (Quant and loop filter level)
- for (i = 0; i < MB_LVL_MAX; i++)
+ // For each segments id...
+ for (i = 0; i < MAX_MB_SEGMENTS; i++)
{
- // For each of the segments
- for (j = 0; j < MAX_MB_SEGMENTS; j++)
+ // For each segmentation codable feature...
+ for (j = 0; j < SEG_LVL_MAX; j++)
{
- Data = xd->segment_feature_data[i][j];
+ Data = get_segdata( xd, i, j );
+
+
+#if CONFIG_FEATUREUPDATES
- // Frame level data
- if (Data)
+ // check if there's an update
+ if(segfeature_changed( xd,i,j) )
{
vp8_write_bit(bc, 1);
- if (Data < 0)
+ if ( segfeature_active( xd, i, j ) )
+ {
+ // this bit is to say we are still
+ // active/ if we were inactive
+ // this is unnecessary
+ if ( old_segfeature_active( xd, i, j ))
+ {
+ vp8_write_bit(bc, 1);
+ }
+ // Is the segment data signed..
+ if ( is_segfeature_signed(j) )
+ {
+ // Encode the relevant feature data
+ if (Data < 0)
+ {
+ Data = - Data;
+ vp8_write_literal(bc, Data,
+ seg_feature_data_bits(j));
+ vp8_write_bit(bc, 1);
+ }
+ else
+ {
+ vp8_write_literal(bc, Data,
+ seg_feature_data_bits(j));
+ vp8_write_bit(bc, 0);
+ }
+ }
+ // Unsigned data element so no sign bit needed
+ else
+ vp8_write_literal(bc, Data,
+ seg_feature_data_bits(j));
+ }
+ // feature is inactive now
+ else if ( old_segfeature_active( xd, i, j ))
{
- Data = - Data;
- vp8_write_literal(bc, Data, mb_feature_data_bits[i]);
- vp8_write_bit(bc, 1);
+ vp8_write_bit(bc, 0);
}
- else
+ }
+ else
+ {
+ vp8_write_bit(bc,0);
+ }
+#else
+
+ // If the feature is enabled...
+ if ( segfeature_active( xd, i, j ) )
+ {
+ vp8_write_bit(bc, 1);
+
+ // Is the segment data signed..
+ if ( is_segfeature_signed(j) )
{
- vp8_write_literal(bc, Data, mb_feature_data_bits[i]);
- vp8_write_bit(bc, 0);
+ // Encode the relevant feature data
+ if (Data < 0)
+ {
+ Data = - Data;
+ vp8_write_literal(bc, Data,
+ seg_feature_data_bits(j));
+ vp8_write_bit(bc, 1);
+ }
+ else
+ {
+ vp8_write_literal(bc, Data,
+ seg_feature_data_bits(j));
+ vp8_write_bit(bc, 0);
+ }
}
+ // Unsigned data element so no sign bit needed
+ else
+ vp8_write_literal(bc, Data,
+ seg_feature_data_bits(j));
}
else
vp8_write_bit(bc, 0);
+#endif
}
}
}
+#if CONFIG_FEATUREUPDATES
+ // save the segment info for updates next frame
+ save_segment_info ( xd );
+#endif
+
if (xd->update_mb_segmentation_map)
{
- // Write the probs used to decode the segment id for each macro block.
+ // Send the tree probabilities used to decode unpredicted
+ // macro-block segments
for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
{
int Data = xd->mb_segment_tree_probs[i];
@@ -1649,10 +1821,46 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
else
vp8_write_bit(bc, 0);
}
+
+ // If predictive coding of segment map is enabled send the
+ // prediction probabilities.
+ if ( pc->temporal_update )
+ {
+ for (i = 0; i < PREDICTION_PROBS; i++)
+ {
+ int Data = pc->segment_pred_probs[i];
+
+ if (Data != 255)
+ {
+ vp8_write_bit(bc, 1);
+ vp8_write_literal(bc, Data, 8);
+ }
+ else
+ vp8_write_bit(bc, 0);
+ }
+ }
+ }
+ }
+
+ // Encode the common prediction model status flag probability updates for
+ // the reference frame
+ if ( pc->frame_type != KEY_FRAME )
+ {
+ for (i = 0; i < PREDICTION_PROBS; i++)
+ {
+ if ( cpi->ref_pred_probs_update[i] )
+ {
+ vp8_write_bit(bc, 1);
+ vp8_write_literal(bc, pc->ref_pred_probs[i], 8);
+ }
+ else
+ vp8_write_bit(bc, 0);
}
}
- // Code to determine whether or not to update the scan order.
+ vp8_write_bit(bc, pc->txfm_mode);
+
+ // Encode the loop filter level and type
vp8_write_bit(bc, pc->filter_type);
vp8_write_literal(bc, pc->filter_level, 6);
vp8_write_literal(bc, pc->sharpness_level, 3);
@@ -1663,8 +1871,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
if (xd->mode_ref_lf_delta_enabled)
{
// Do the deltas need to be updated
- int send_update = xd->mode_ref_lf_delta_update
- || cpi->oxcf.error_resilient_mode;
+ int send_update = xd->mode_ref_lf_delta_update;
vp8_write_bit(bc, send_update);
if (send_update)
@@ -1677,8 +1884,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
Data = xd->ref_lf_deltas[i];
// Frame level data
- if (xd->ref_lf_deltas[i] != xd->last_ref_lf_deltas[i]
- || cpi->oxcf.error_resilient_mode)
+ if (xd->ref_lf_deltas[i] != xd->last_ref_lf_deltas[i])
{
xd->last_ref_lf_deltas[i] = xd->ref_lf_deltas[i];
vp8_write_bit(bc, 1);
@@ -1704,8 +1910,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
{
Data = xd->mode_lf_deltas[i];
- if (xd->mode_lf_deltas[i] != xd->last_mode_lf_deltas[i]
- || cpi->oxcf.error_resilient_mode)
+ if (xd->mode_lf_deltas[i] != xd->last_mode_lf_deltas[i])
{
xd->last_mode_lf_deltas[i] = xd->mode_lf_deltas[i];
vp8_write_bit(bc, 1);
@@ -1729,10 +1934,11 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
}
//signal here is multi token partition is enabled
- vp8_write_literal(bc, pc->multi_token_partition, 2);
+ //vp8_write_literal(bc, pc->multi_token_partition, 2);
+ vp8_write_literal(bc, 0, 2);
- // Frame Qbaseline quantizer index
- vp8_write_literal(bc, pc->base_qindex, 7);
+ // Frame Q baseline quantizer index
+ vp8_write_literal(bc, pc->base_qindex, QINDEX_BITS);
// Transmit Dc, Second order and Uv quantizer delta information
put_delta_q(bc, pc->y1dc_delta_q);
@@ -1758,14 +1964,11 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
// Indicate reference frame sign bias for Golden and ARF frames (always 0 for last frame buffer)
vp8_write_bit(bc, pc->ref_frame_sign_bias[GOLDEN_FRAME]);
vp8_write_bit(bc, pc->ref_frame_sign_bias[ALTREF_FRAME]);
- }
- if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
- {
- if (pc->frame_type == KEY_FRAME)
- pc->refresh_entropy_probs = 1;
- else
- pc->refresh_entropy_probs = 0;
+#if CONFIG_HIGH_PRECISION_MV
+ // Signal whether to allow high MV precision
+ vp8_write_bit(bc, (xd->allow_high_precision_mv) ? 1 : 0);
+#endif
}
vp8_write_bit(bc, pc->refresh_entropy_probs);
@@ -1784,12 +1987,6 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
vp8_clear_system_state(); //__asm emms;
- //************************************************
- // save a copy for later refresh
- {
- vpx_memcpy(&cpi->common.lfc, &cpi->common.fc, sizeof(cpi->common.fc));
- }
-
update_coef_probs(cpi);
#ifdef ENTROPY_STATS
@@ -1801,6 +1998,9 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
if (pc->frame_type == KEY_FRAME)
{
+#if CONFIG_QIMODE
+ decide_kf_ymode_entropy(cpi);
+#endif
write_kfmodes(cpi);
#ifdef ENTROPY_STATS
@@ -1811,6 +2011,8 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
{
pack_inter_mode_mvs(cpi);
+ vp8_update_mode_context(&cpi->common);
+
#ifdef ENTROPY_STATS
active_section = 1;
#endif
@@ -1833,34 +2035,14 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
}
*size = VP8_HEADER_SIZE + extra_bytes_packed + cpi->bc.pos;
- cpi->partition_sz[0] = *size;
- if (pc->multi_token_partition != ONE_PARTITION)
- {
- int num_part;
- int asize;
- num_part = 1 << pc->multi_token_partition;
+ vp8_start_encode(&cpi->bc2, cx_data + bc->pos);
- pack_tokens_into_partitions(cpi, cx_data + bc->pos, num_part, &asize);
+ pack_tokens(&cpi->bc2, cpi->tok, cpi->tok_count);
- *size += asize;
- }
- else
- {
- vp8_start_encode(&cpi->bc2, cx_data + bc->pos);
+ vp8_stop_encode(&cpi->bc2);
-#if CONFIG_MULTITHREAD
- if (cpi->b_multi_threaded)
- pack_mb_row_tokens(cpi, &cpi->bc2);
- else
-#endif
- pack_tokens(&cpi->bc2, cpi->tok, cpi->tok_count);
-
- vp8_stop_encode(&cpi->bc2);
-
- *size += cpi->bc2.pos;
- cpi->partition_sz[1] = cpi->bc2.pos;
- }
+ *size += cpi->bc2.pos;
}
#ifdef ENTROPY_STATS
@@ -1909,6 +2091,44 @@ void print_tree_update_probs()
}
fprintf(f, "};\n");
+
+ fprintf(f, "const vp8_prob tree_update_probs_8x8[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] = {\n");
+
+ for (i = 0; i < BLOCK_TYPES; i++)
+ {
+ fprintf(f, " { \n");
+
+ for (j = 0; j < COEF_BANDS; j++)
+ {
+ fprintf(f, " {\n");
+
+ for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+ {
+ fprintf(f, " {");
+
+ for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+ {
+ Sum = tree_update_hist_8x8[i][j][k][l][0] + tree_update_hist_8x8[i][j][k][l][1];
+
+ if (Sum > 0)
+ {
+ if (((tree_update_hist_8x8[i][j][k][l][0] * 255) / Sum) > 0)
+ fprintf(f, "%3ld, ", (tree_update_hist_8x8[i][j][k][l][0] * 255) / Sum);
+ else
+ fprintf(f, "%3ld, ", 1);
+ }
+ else
+ fprintf(f, "%3ld, ", 128);
+ }
+
+ fprintf(f, "},\n");
+ }
+
+ fprintf(f, " },\n");
+ }
+
+ fprintf(f, " },\n");
+ }
fclose(f);
}
#endif
diff --git a/vp8/encoder/bitstream.h b/vp8/encoder/bitstream.h
index f5d148ea4..39fa642a5 100644
--- a/vp8/encoder/bitstream.h
+++ b/vp8/encoder/bitstream.h
@@ -17,23 +17,9 @@ void vp8cx_pack_tokens_armv5(vp8_writer *w, const TOKENEXTRA *p, int xcount,
vp8_token *,
vp8_extra_bit_struct *,
const vp8_tree_index *);
-void vp8cx_pack_tokens_into_partitions_armv5(VP8_COMP *, unsigned char *, int , int *,
- vp8_token *,
- vp8_extra_bit_struct *,
- const vp8_tree_index *);
-void vp8cx_pack_mb_row_tokens_armv5(VP8_COMP *cpi, vp8_writer *w,
- vp8_token *,
- vp8_extra_bit_struct *,
- const vp8_tree_index *);
# define pack_tokens(a,b,c) \
vp8cx_pack_tokens_armv5(a,b,c,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
-# define pack_tokens_into_partitions(a,b,c,d) \
- vp8cx_pack_tokens_into_partitions_armv5(a,b,c,d,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
-# define pack_mb_row_tokens(a,b) \
- vp8cx_pack_mb_row_tokens_armv5(a,b,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
#else
# define pack_tokens(a,b,c) pack_tokens_c(a,b,c)
-# define pack_tokens_into_partitions(a,b,c,d) pack_tokens_into_partitions_c(a,b,c,d)
-# define pack_mb_row_tokens(a,b) pack_mb_row_tokens_c(a,b)
#endif
#endif
diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h
index 0d14b545c..25d2398ce 100644
--- a/vp8/encoder/block.h
+++ b/vp8/encoder/block.h
@@ -46,8 +46,8 @@ typedef struct
int src;
int src_stride;
-// MV enc_mv;
- int force_empty;
+ int eob_max_offset;
+ int eob_max_offset_8x8;
} BLOCK;
@@ -95,9 +95,16 @@ typedef struct
int *mvcost[2];
int mvsadcosts[2][MVfpvals+1];
int *mvsadcost[2];
+#if CONFIG_HIGH_PRECISION_MV
+ int mvcosts_hp[2][MVvals_hp+1];
+ int *mvcost_hp[2];
+ int mvsadcosts_hp[2][MVfpvals_hp+1];
+ int *mvsadcost_hp[2];
+#endif
int mbmode_cost[2][MB_MODE_COUNT];
int intra_uv_mode_cost[2][MB_MODE_COUNT];
unsigned int bmode_costs[10][10][10];
+ unsigned int i8x8_mode_costs[MB_MODE_COUNT];
unsigned int inter_bmode_costs[B_MODE_COUNT];
// These define limits to motion vector components to prevent them from extending outside the UMV borders
@@ -116,8 +123,15 @@ typedef struct
unsigned char *active_ptr;
MV_CONTEXT *mvc;
+#if CONFIG_HIGH_PRECISION_MV
+ MV_CONTEXT_HP *mvc_hp;
+#endif
+
+ unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS]
+ [PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS];
+ unsigned int token_costs_8x8[BLOCK_TYPES] [COEF_BANDS]
+ [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
- unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
int optimize;
int q_index;
@@ -126,6 +140,10 @@ typedef struct
void (*short_walsh4x4)(short *input, short *output, int pitch);
void (*quantize_b)(BLOCK *b, BLOCKD *d);
void (*quantize_b_pair)(BLOCK *b1, BLOCK *b2, BLOCKD *d0, BLOCKD *d1);
+ void (*vp8_short_fdct8x8)(short *input, short *output, int pitch);
+ void (*short_fhaar2x2)(short *input, short *output, int pitch);
+ void (*quantize_b_8x8)(BLOCK *b, BLOCKD *d);
+ void (*quantize_b_2x2)(BLOCK *b, BLOCKD *d);
} MACROBLOCK;
diff --git a/vp8/encoder/dct.c b/vp8/encoder/dct.c
index c15437f3e..c2f2d1117 100644
--- a/vp8/encoder/dct.c
+++ b/vp8/encoder/dct.c
@@ -10,7 +10,123 @@
#include <math.h>
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
+
+
+
+
+
+
+void vp8_short_fdct8x8_c(short *block, short *coefs, int pitch)
+{
+ int j1, i, j, k;
+ float b[8];
+ float b1[8];
+ float d[8][8];
+ float f0 = (float) .7071068;
+ float f1 = (float) .4903926;
+ float f2 = (float) .4619398;
+ float f3 = (float) .4157348;
+ float f4 = (float) .3535534;
+ float f5 = (float) .2777851;
+ float f6 = (float) .1913417;
+ float f7 = (float) .0975452;
+ pitch = pitch / 2;
+ for (i = 0, k = 0; i < 8; i++, k += pitch)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ b[j] = (float)( block[k + j]<<3);
+ }
+ /* Horizontal transform */
+ for (j = 0; j < 4; j++)
+ {
+ j1 = 7 - j;
+ b1[j] = b[j] + b[j1];
+ b1[j1] = b[j] - b[j1];
+ }
+ b[0] = b1[0] + b1[3];
+ b[1] = b1[1] + b1[2];
+ b[2] = b1[1] - b1[2];
+ b[3] = b1[0] - b1[3];
+ b[4] = b1[4];
+ b[5] = (b1[6] - b1[5]) * f0;
+ b[6] = (b1[6] + b1[5]) * f0;
+ b[7] = b1[7];
+ d[i][0] = (b[0] + b[1]) * f4;
+ d[i][4] = (b[0] - b[1]) * f4;
+ d[i][2] = b[2] * f6 + b[3] * f2;
+ d[i][6] = b[3] * f6 - b[2] * f2;
+ b1[4] = b[4] + b[5];
+ b1[7] = b[7] + b[6];
+ b1[5] = b[4] - b[5];
+ b1[6] = b[7] - b[6];
+ d[i][1] = b1[4] * f7 + b1[7] * f1;
+ d[i][5] = b1[5] * f3 + b1[6] * f5;
+ d[i][7] = b1[7] * f7 - b1[4] * f1;
+ d[i][3] = b1[6] * f3 - b1[5] * f5;
+ }
+ /* Vertical transform */
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ j1 = 7 - j;
+ b1[j] = d[j][i] + d[j1][i];
+ b1[j1] = d[j][i] - d[j1][i];
+ }
+ b[0] = b1[0] + b1[3];
+ b[1] = b1[1] + b1[2];
+ b[2] = b1[1] - b1[2];
+ b[3] = b1[0] - b1[3];
+ b[4] = b1[4];
+ b[5] = (b1[6] - b1[5]) * f0;
+ b[6] = (b1[6] + b1[5]) * f0;
+ b[7] = b1[7];
+ d[0][i] = (b[0] + b[1]) * f4;
+ d[4][i] = (b[0] - b[1]) * f4;
+ d[2][i] = b[2] * f6 + b[3] * f2;
+ d[6][i] = b[3] * f6 - b[2] * f2;
+ b1[4] = b[4] + b[5];
+ b1[7] = b[7] + b[6];
+ b1[5] = b[4] - b[5];
+ b1[6] = b[7] - b[6];
+ d[1][i] = b1[4] * f7 + b1[7] * f1;
+ d[5][i] = b1[5] * f3 + b1[6] * f5;
+ d[7][i] = b1[7] * f7 - b1[4] * f1;
+ d[3][i] = b1[6] * f3 - b1[5] * f5;
+ }
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ *(coefs + j + i * 8) = (short) floor(d[i][j] +0.5);
+ }
+ }
+ return;
+}
+
+
+
+void vp8_short_fhaar2x2_c(short *input, short *output, int pitch) //pitch = 8
+{
+ /* [1 1 ; 1 -1] orthogonal transform */
+ /* use position: 0,1, 4, 8 */
+ int i;
+ short *ip1 = input;
+ short *op1 = output;
+ for (i = 0; i < 16; i++)
+ {
+ op1[i] = 0;
+ }
+
+ op1[0]=(ip1[0] + ip1[1] + ip1[4] + ip1[8] + 1)>>1;
+ op1[1]=(ip1[0] - ip1[1] + ip1[4] - ip1[8])>>1;
+ op1[4]=(ip1[0] + ip1[1] - ip1[4] - ip1[8])>>1;
+ op1[8]=(ip1[0] - ip1[1] - ip1[4] + ip1[8])>>1;
+
+}
+
void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
{
int i;
@@ -20,17 +136,11 @@ void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
for (i = 0; i < 4; i++)
{
-#if CONFIG_EXTEND_QRANGE
a1 = ((ip[0] + ip[3])<<5);
b1 = ((ip[1] + ip[2])<<5);
c1 = ((ip[1] - ip[2])<<5);
d1 = ((ip[0] - ip[3])<<5);
-#else
- a1 = ((ip[0] + ip[3])<<3);
- b1 = ((ip[1] + ip[2])<<3);
- c1 = ((ip[1] - ip[2])<<3);
- d1 = ((ip[0] - ip[3])<<3);
-#endif
+
op[0] = a1 + b1;
op[2] = a1 - b1;
@@ -78,22 +188,12 @@ void vp8_short_walsh4x4_c(short *input, short *output, int pitch)
for (i = 0; i < 4; i++)
{
-#if !CONFIG_EXTEND_QRANGE
- a1 = ((ip[0] + ip[2])<<2);
- d1 = ((ip[1] + ip[3])<<2);
- c1 = ((ip[1] - ip[3])<<2);
- b1 = ((ip[0] - ip[2])<<2);
-
- op[0] = a1 + d1 + (a1!=0);
-#else
a1 = ((ip[0] + ip[2]));
d1 = ((ip[1] + ip[3]));
c1 = ((ip[1] - ip[3]));
b1 = ((ip[0] - ip[2]));
-
op[0] = a1 + d1;
-#endif
op[1] = b1 + c1;
op[2] = b1 - c1;
op[3] = a1 - d1;
@@ -121,17 +221,11 @@ void vp8_short_walsh4x4_c(short *input, short *output, int pitch)
c2 += c2<0;
d2 += d2<0;
-#if !CONFIG_EXTEND_QRANGE
- op[0] = (a2+3) >> 3;
- op[4] = (b2+3) >> 3;
- op[8] = (c2+3) >> 3;
- op[12]= (d2+3) >> 3;
-#else
op[0] = (a2+1) >> 2;
op[4] = (b2+1) >> 2;
op[8] = (c2+1) >> 2;
op[12]= (d2+1) >> 2;
-#endif
+
ip++;
op++;
}
diff --git a/vp8/encoder/dct.h b/vp8/encoder/dct.h
index fec3b4c37..7ab525c0b 100644
--- a/vp8/encoder/dct.h
+++ b/vp8/encoder/dct.h
@@ -22,6 +22,19 @@
#include "arm/dct_arm.h"
#endif
+
+
+#ifndef vp8_fdct_short8x8
+#define vp8_fdct_short8x8 vp8_short_fdct8x8_c
+#endif
+extern prototype_fdct(vp8_fdct_short8x8);
+
+#ifndef vp8_fhaar_short2x2
+#define vp8_fhaar_short2x2 vp8_short_fhaar2x2_c
+#endif
+extern prototype_fdct(vp8_fhaar_short2x2);
+
+
#ifndef vp8_fdct_short4x4
#define vp8_fdct_short4x4 vp8_short_fdct4x4_c
#endif
@@ -49,6 +62,8 @@ extern prototype_fdct(vp8_fdct_walsh_short4x4);
typedef prototype_fdct(*vp8_fdct_fn_t);
typedef struct
{
+ vp8_fdct_fn_t short8x8;
+ vp8_fdct_fn_t haar_short2x2;
vp8_fdct_fn_t short4x4;
vp8_fdct_fn_t short8x4;
vp8_fdct_fn_t fast4x4;
diff --git a/vp8/encoder/defaultcoefcounts.h b/vp8/encoder/defaultcoefcounts.h
deleted file mode 100644
index 2c0f3ddf3..000000000
--- a/vp8/encoder/defaultcoefcounts.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * 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.
- */
-
-/* Generated file, included by entropy.c */
-
-static const unsigned int default_coef_counts[BLOCK_TYPES]
- [COEF_BANDS]
- [PREV_COEF_CONTEXTS]
- [MAX_ENTROPY_TOKENS] =
-{
-
- {
- /* Block Type ( 0 ) */
- {
- /* Coeff Band ( 0 ) */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- },
- {
- /* Coeff Band ( 1 ) */
- {30190, 26544, 225, 24, 4, 0, 0, 0, 0, 0, 0, 4171593,},
- {26846, 25157, 1241, 130, 26, 6, 1, 0, 0, 0, 0, 149987,},
- {10484, 9538, 1006, 160, 36, 18, 0, 0, 0, 0, 0, 15104,},
- },
- {
- /* Coeff Band ( 2 ) */
- {25842, 40456, 1126, 83, 11, 2, 0, 0, 0, 0, 0, 0,},
- {9338, 8010, 512, 73, 7, 3, 2, 0, 0, 0, 0, 43294,},
- {1047, 751, 149, 31, 13, 6, 1, 0, 0, 0, 0, 879,},
- },
- {
- /* Coeff Band ( 3 ) */
- {26136, 9826, 252, 13, 0, 0, 0, 0, 0, 0, 0, 0,},
- {8134, 5574, 191, 14, 2, 0, 0, 0, 0, 0, 0, 35302,},
- { 605, 677, 116, 9, 1, 0, 0, 0, 0, 0, 0, 611,},
- },
- {
- /* Coeff Band ( 4 ) */
- {10263, 15463, 283, 17, 0, 0, 0, 0, 0, 0, 0, 0,},
- {2773, 2191, 128, 9, 2, 2, 0, 0, 0, 0, 0, 10073,},
- { 134, 125, 32, 4, 0, 2, 0, 0, 0, 0, 0, 50,},
- },
- {
- /* Coeff Band ( 5 ) */
- {10483, 2663, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0,},
- {2137, 1251, 27, 1, 1, 0, 0, 0, 0, 0, 0, 14362,},
- { 116, 156, 14, 2, 1, 0, 0, 0, 0, 0, 0, 190,},
- },
- {
- /* Coeff Band ( 6 ) */
- {40977, 27614, 412, 28, 0, 0, 0, 0, 0, 0, 0, 0,},
- {6113, 5213, 261, 22, 3, 0, 0, 0, 0, 0, 0, 26164,},
- { 382, 312, 50, 14, 2, 0, 0, 0, 0, 0, 0, 345,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,},
- },
- },
- {
- /* Block Type ( 1 ) */
- {
- /* Coeff Band ( 0 ) */
- {3268, 19382, 1043, 250, 93, 82, 49, 26, 17, 8, 25, 82289,},
- {8758, 32110, 5436, 1832, 827, 668, 420, 153, 24, 0, 3, 52914,},
- {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399, 59, 0, 0, 18620,},
- },
- {
- /* Coeff Band ( 1 ) */
- {12419, 8420, 452, 62, 9, 1, 0, 0, 0, 0, 0, 0,},
- {11715, 8705, 693, 92, 15, 7, 2, 0, 0, 0, 0, 53988,},
- {7603, 8585, 2306, 778, 270, 145, 39, 5, 0, 0, 0, 9136,},
- },
- {
- /* Coeff Band ( 2 ) */
- {15938, 14335, 1207, 184, 55, 13, 4, 1, 0, 0, 0, 0,},
- {7415, 6829, 1138, 244, 71, 26, 7, 0, 0, 0, 0, 9980,},
- {1580, 1824, 655, 241, 89, 46, 10, 2, 0, 0, 0, 429,},
- },
- {
- /* Coeff Band ( 3 ) */
- {19453, 5260, 201, 19, 0, 0, 0, 0, 0, 0, 0, 0,},
- {9173, 3758, 213, 22, 1, 1, 0, 0, 0, 0, 0, 9820,},
- {1689, 1277, 276, 51, 17, 4, 0, 0, 0, 0, 0, 679,},
- },
- {
- /* Coeff Band ( 4 ) */
- {12076, 10667, 620, 85, 19, 9, 5, 0, 0, 0, 0, 0,},
- {4665, 3625, 423, 55, 19, 9, 0, 0, 0, 0, 0, 5127,},
- { 415, 440, 143, 34, 20, 7, 2, 0, 0, 0, 0, 101,},
- },
- {
- /* Coeff Band ( 5 ) */
- {12183, 4846, 115, 11, 1, 0, 0, 0, 0, 0, 0, 0,},
- {4226, 3149, 177, 21, 2, 0, 0, 0, 0, 0, 0, 7157,},
- { 375, 621, 189, 51, 11, 4, 1, 0, 0, 0, 0, 198,},
- },
- {
- /* Coeff Band ( 6 ) */
- {61658, 37743, 1203, 94, 10, 3, 0, 0, 0, 0, 0, 0,},
- {15514, 11563, 903, 111, 14, 5, 0, 0, 0, 0, 0, 25195,},
- { 929, 1077, 291, 78, 14, 7, 1, 0, 0, 0, 0, 507,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 990, 15, 3, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 412, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1641,},
- { 0, 18, 7, 1, 0, 0, 0, 0, 0, 0, 0, 30,},
- },
- },
- {
- /* Block Type ( 2 ) */
- {
- /* Coeff Band ( 0 ) */
- { 953, 24519, 628, 120, 28, 12, 4, 0, 0, 0, 0, 2248798,},
- {1525, 25654, 2647, 617, 239, 143, 42, 5, 0, 0, 0, 66837,},
- {1180, 11011, 3001, 1237, 532, 448, 239, 54, 5, 0, 0, 7122,},
- },
- {
- /* Coeff Band ( 1 ) */
- {1356, 2220, 67, 10, 4, 1, 0, 0, 0, 0, 0, 0,},
- {1450, 2544, 102, 18, 4, 3, 0, 0, 0, 0, 0, 57063,},
- {1182, 2110, 470, 130, 41, 21, 0, 0, 0, 0, 0, 6047,},
- },
- {
- /* Coeff Band ( 2 ) */
- { 370, 3378, 200, 30, 5, 4, 1, 0, 0, 0, 0, 0,},
- { 293, 1006, 131, 29, 11, 0, 0, 0, 0, 0, 0, 5404,},
- { 114, 387, 98, 23, 4, 8, 1, 0, 0, 0, 0, 236,},
- },
- {
- /* Coeff Band ( 3 ) */
- { 579, 194, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 395, 213, 5, 1, 0, 0, 0, 0, 0, 0, 0, 4157,},
- { 119, 122, 4, 0, 0, 0, 0, 0, 0, 0, 0, 300,},
- },
- {
- /* Coeff Band ( 4 ) */
- { 38, 557, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 21, 114, 12, 1, 0, 0, 0, 0, 0, 0, 0, 427,},
- { 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,},
- },
- {
- /* Coeff Band ( 5 ) */
- { 52, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 18, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 652,},
- { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,},
- },
- {
- /* Coeff Band ( 6 ) */
- { 640, 569, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 25, 77, 2, 0, 0, 0, 0, 0, 0, 0, 0, 517,},
- { 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- },
- },
- {
- /* Block Type ( 3 ) */
- {
- /* Coeff Band ( 0 ) */
- {2506, 20161, 2707, 767, 261, 178, 107, 30, 14, 3, 0, 100694,},
- {8806, 36478, 8817, 3268, 1280, 850, 401, 114, 42, 0, 0, 58572,},
- {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175, 32, 0, 0, 19284,},
- },
- {
- /* Coeff Band ( 1 ) */
- {9738, 11313, 959, 205, 70, 18, 11, 1, 0, 0, 0, 0,},
- {12628, 15085, 1507, 273, 52, 19, 9, 0, 0, 0, 0, 54280,},
- {10701, 15846, 5561, 1926, 813, 570, 249, 36, 0, 0, 0, 6460,},
- },
- {
- /* Coeff Band ( 2 ) */
- {6781, 22539, 2784, 634, 182, 123, 20, 4, 0, 0, 0, 0,},
- {6263, 11544, 2649, 790, 259, 168, 27, 5, 0, 0, 0, 20539,},
- {3109, 4075, 2031, 896, 457, 386, 158, 29, 0, 0, 0, 1138,},
- },
- {
- /* Coeff Band ( 3 ) */
- {11515, 4079, 465, 73, 5, 14, 2, 0, 0, 0, 0, 0,},
- {9361, 5834, 650, 96, 24, 8, 4, 0, 0, 0, 0, 22181,},
- {4343, 3974, 1360, 415, 132, 96, 14, 1, 0, 0, 0, 1267,},
- },
- {
- /* Coeff Band ( 4 ) */
- {4787, 9297, 823, 168, 44, 12, 4, 0, 0, 0, 0, 0,},
- {3619, 4472, 719, 198, 60, 31, 3, 0, 0, 0, 0, 8401,},
- {1157, 1175, 483, 182, 88, 31, 8, 0, 0, 0, 0, 268,},
- },
- {
- /* Coeff Band ( 5 ) */
- {8299, 1226, 32, 5, 1, 0, 0, 0, 0, 0, 0, 0,},
- {3502, 1568, 57, 4, 1, 1, 0, 0, 0, 0, 0, 9811,},
- {1055, 1070, 166, 29, 6, 1, 0, 0, 0, 0, 0, 527,},
- },
- {
- /* Coeff Band ( 6 ) */
- {27414, 27927, 1989, 347, 69, 26, 0, 0, 0, 0, 0, 0,},
- {5876, 10074, 1574, 341, 91, 24, 4, 0, 0, 0, 0, 21954,},
- {1571, 2171, 778, 324, 124, 65, 16, 0, 0, 0, 0, 979,},
- },
- {
- /* Coeff Band ( 7 ) */
- { 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
- { 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 459,},
- { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,},
- },
- },
-};
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
index 46e6c7645..a59dd6324 100644
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "encodemb.h"
#include "encodemv.h"
#include "vp8/common/common.h"
@@ -22,13 +22,17 @@
#include "encodeintra.h"
#include "vp8/common/reconinter.h"
#include "rdopt.h"
-#include "pickinter.h"
#include "vp8/common/findnearmv.h"
#include "vp8/common/reconintra.h"
+#include "vp8/common/seg_common.h"
#include <stdio.h>
+#include <math.h>
#include <limits.h>
#include "vp8/common/subpixel.h"
#include "vpx_ports/vpx_timer.h"
+#include "vp8/common/pred_common.h"
+
+//#define DBG_PRNT_SEGMAP 1
#if CONFIG_RUNTIME_CPU_DETECT
#define RTCD(x) &cpi->common.rtcd.x
@@ -37,6 +41,12 @@
#define RTCD(x) NULL
#define IF_RTCD(x) NULL
#endif
+
+#ifdef ENC_DEBUG
+int enc_debug=0;
+int mb_row_debug, mb_col_debug;
+#endif
+
extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
@@ -52,13 +62,25 @@ int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);
static void adjust_act_zbin( VP8_COMP *cpi, MACROBLOCK *x );
+
+
#ifdef MODE_STATS
-unsigned int inter_y_modes[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-unsigned int inter_uv_modes[4] = {0, 0, 0, 0};
-unsigned int inter_b_modes[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-unsigned int y_modes[5] = {0, 0, 0, 0, 0};
-unsigned int uv_modes[4] = {0, 0, 0, 0};
-unsigned int b_modes[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int inter_y_modes[MB_MODE_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int inter_uv_modes[VP8_UV_MODES] = {0, 0, 0, 0};
+unsigned int inter_b_modes[B_MODE_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int y_modes[VP8_YMODES] = {0, 0, 0, 0, 0, 0};
+unsigned int i8x8_modes[VP8_I8X8_MODES]={0 };
+unsigned int uv_modes[VP8_UV_MODES] = {0, 0, 0, 0};
+unsigned int uv_modes_y[VP8_YMODES][VP8_UV_MODES]=
+{
+{0, 0, 0, 0},
+{0, 0, 0, 0},
+{0, 0, 0, 0},
+{0, 0, 0, 0},
+{0, 0, 0, 0},
+{0, 0, 0, 0}
+};
+unsigned int b_modes[B_MODE_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
#endif
@@ -365,7 +387,6 @@ void encode_mb_row(VP8_COMP *cpi,
MACROBLOCK *x,
MACROBLOCKD *xd,
TOKENEXTRA **tp,
- int *segment_counts,
int *totalrate)
{
int recon_yoffset, recon_uvoffset;
@@ -376,16 +397,8 @@ void encode_mb_row(VP8_COMP *cpi,
int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
int map_index = (mb_row * cpi->common.mb_cols);
-#if CONFIG_MULTITHREAD
- const int nsync = cpi->mt_sync_range;
- const int rightmost_col = cm->mb_cols - 1;
- volatile const int *last_row_current_mb_col;
-
- if ((cpi->b_multi_threaded != 0) && (mb_row != 0))
- last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1];
- else
- last_row_current_mb_col = &rightmost_col;
-#endif
+ // Reset the left context
+ vp8_zero(cm->left_context)
// reset above block coeffs
xd->above_context = cm->above_context;
@@ -414,6 +427,11 @@ void encode_mb_row(VP8_COMP *cpi,
// for each macroblock col in image
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
{
+#ifdef ENC_DEBUG
+ enc_debug = (cpi->common.current_video_frame ==1 && mb_row==4 && mb_col==0);
+ mb_col_debug=mb_col;
+ mb_row_debug=mb_row;
+#endif
// Distance of Mb to the left & right edges, specified in
// 1/8th pel units as they are always compared to values
// that are in 1/8th pel units
@@ -437,29 +455,13 @@ void encode_mb_row(VP8_COMP *cpi,
//Copy current mb to a buffer
RECON_INVOKE(&xd->rtcd->recon, copy16x16)(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
-#if CONFIG_MULTITHREAD
- if ((cpi->b_multi_threaded != 0) && (mb_row != 0))
- {
- if ((mb_col & (nsync - 1)) == 0)
- {
- while (mb_col > (*last_row_current_mb_col - nsync)
- && (*last_row_current_mb_col) != (cm->mb_cols - 1))
- {
- x86_pause_hint();
- thread_sleep(0);
- }
- }
- }
-#endif
-
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
vp8_activity_masking(cpi, x);
// Is segmentation enabled
- // MB level adjutment to quantizer
if (xd->segmentation_enabled)
{
- // Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
+ // Code to set segment id in xd->mbmi.segment_id
if (cpi->segmentation_map[map_index+mb_col] <= 3)
xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[map_index+mb_col];
else
@@ -468,66 +470,51 @@ void encode_mb_row(VP8_COMP *cpi,
vp8cx_mb_init_quantizer(cpi, x);
}
else
- xd->mode_info_context->mbmi.segment_id = 0; // Set to Segment 0 by default
+ // Set to Segment 0 by default
+ xd->mode_info_context->mbmi.segment_id = 0;
x->active_ptr = cpi->active_map + map_index + mb_col;
+ /* force 4x4 transform for mode selection */
+ xd->mode_info_context->mbmi.txfm_size = TX_4X4;
+
if (cm->frame_type == KEY_FRAME)
{
*totalrate += vp8cx_encode_intra_macro_block(cpi, x, tp);
+ //Note the encoder may have changed the segment_id
+
#ifdef MODE_STATS
- y_modes[xd->mbmi.mode] ++;
+ y_modes[xd->mode_info_context->mbmi.mode] ++;
#endif
}
else
{
*totalrate += vp8cx_encode_inter_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset);
+ //Note the encoder may have changed the segment_id
#ifdef MODE_STATS
- inter_y_modes[xd->mbmi.mode] ++;
+ inter_y_modes[xd->mode_info_context->mbmi.mode] ++;
- if (xd->mbmi.mode == SPLITMV)
+ if (xd->mode_info_context->mbmi.mode == SPLITMV)
{
int b;
- for (b = 0; b < xd->mbmi.partition_count; b++)
+ for (b = 0; b < x->partition_info->count; b++)
{
- inter_b_modes[x->partition->bmi[b].mode] ++;
+ inter_b_modes[x->partition_info->bmi[b].mode] ++;
}
}
#endif
- // Count of last ref frame 0,0 useage
+ // Count of last ref frame 0,0 usage
if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
cpi->inter_zz_count ++;
-
- // Special case code for cyclic refresh
- // If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
- // during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
- if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
- {
- cpi->segmentation_map[map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
-
- // If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
- // Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
- // else mark it as dirty (1).
- if (xd->mode_info_context->mbmi.segment_id)
- cpi->cyclic_refresh_map[map_index+mb_col] = -1;
- else if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
- {
- if (cpi->cyclic_refresh_map[map_index+mb_col] == 1)
- cpi->cyclic_refresh_map[map_index+mb_col] = 0;
- }
- else
- cpi->cyclic_refresh_map[map_index+mb_col] = 1;
-
- }
}
cpi->tplist[mb_row].stop = *tp;
- // Increment pointer into gf useage flags structure.
+ // Increment pointer into gf usage flags structure.
x->gf_active_ptr++;
// Increment the activity mask pointers.
@@ -541,20 +528,15 @@ void encode_mb_row(VP8_COMP *cpi,
recon_yoffset += 16;
recon_uvoffset += 8;
- // Keep track of segment useage
- segment_counts[xd->mode_info_context->mbmi.segment_id] ++;
-
// skip to next mb
xd->mode_info_context++;
+
+ xd->prev_mode_info_context++;
+ assert((xd->prev_mode_info_context - cpi->common.prev_mip)
+ ==(xd->mode_info_context - cpi->common.mip));
x->partition_info++;
xd->above_context++;
-#if CONFIG_MULTITHREAD
- if (cpi->b_multi_threaded != 0)
- {
- cpi->mt_current_mb_col[mb_row] = mb_col;
- }
-#endif
}
//extend the recon for intra prediction
@@ -565,13 +547,17 @@ void encode_mb_row(VP8_COMP *cpi,
xd->dst.v_buffer + 8);
// this is to account for the border
+ xd->prev_mode_info_context++;
xd->mode_info_context++;
x->partition_info++;
-#if CONFIG_MULTITHREAD
- if ((cpi->b_multi_threaded != 0) && (mb_row == cm->mb_rows - 1))
+// debug output
+#if DBG_PRNT_SEGMAP
{
- sem_post(&cpi->h_event_end_encoding); /* signal frame encoding end */
+ FILE *statsfile;
+ statsfile = fopen("segmap2.stt", "a");
+ fprintf(statsfile, "\n" );
+ fclose(statsfile);
}
#endif
}
@@ -596,6 +582,7 @@ void init_encode_frame_mb_context(VP8_COMP *cpi)
xd->mode_info_context = cm->mi;
xd->mode_info_stride = cm->mode_info_stride;
+ xd->prev_mode_info_context = cm->prev_mi;
xd->frame_type = cm->frame_type;
@@ -630,42 +617,19 @@ void init_encode_frame_mb_context(VP8_COMP *cpi)
vp8_zero(cpi->uv_mode_count)
x->mvc = cm->fc.mvc;
+#if CONFIG_HIGH_PRECISION_MV
+ x->mvc_hp = cm->fc.mvc_hp;
+#endif
vpx_memset(cm->above_context, 0,
sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols);
- xd->ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cpi->prob_intra_coded);
-
- // Special case treatment when GF and ARF are not sensible options for reference
- if (cpi->ref_frame_flags == VP8_LAST_FLAG)
- {
- xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_zero(255);
- xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_one(255)
- + vp8_cost_zero(128);
- xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_one(255)
- + vp8_cost_one(128);
- }
- else
- {
- xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_zero(cpi->prob_last_coded);
- xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_one(cpi->prob_last_coded)
- + vp8_cost_zero(cpi->prob_gf_coded);
- xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
- + vp8_cost_one(cpi->prob_last_coded)
- + vp8_cost_one(cpi->prob_gf_coded);
- }
-
xd->fullpixel_mask = 0xffffffff;
if(cm->full_pixel)
xd->fullpixel_mask = 0xfffffff8;
}
-void vp8_encode_frame(VP8_COMP *cpi)
+static void encode_frame_internal(VP8_COMP *cpi)
{
int mb_row;
MACROBLOCK *const x = & cpi->mb;
@@ -673,19 +637,24 @@ void vp8_encode_frame(VP8_COMP *cpi)
MACROBLOCKD *const xd = & x->e_mbd;
TOKENEXTRA *tp = cpi->tok;
- int segment_counts[MAX_MB_SEGMENTS];
int totalrate;
- vpx_memset(segment_counts, 0, sizeof(segment_counts));
- totalrate = 0;
+ // Compute a modified set of reference frame probabilities to use when
+ // prediction fails. These are based on the current genreal estimates for
+ // this frame which may be updated with each itteration of the recode loop.
+ compute_mod_refprobs( cm );
- if (cpi->compressor_speed == 2)
+// debug output
+#if DBG_PRNT_SEGMAP
{
- if (cpi->oxcf.cpu_used < 0)
- cpi->Speed = -(cpi->oxcf.cpu_used);
- else
- vp8_auto_select_speed(cpi);
+ FILE *statsfile;
+ statsfile = fopen("segmap2.stt", "a");
+ fprintf(statsfile, "\n" );
+ fclose(statsfile);
}
+#endif
+
+ totalrate = 0;
// Functions setup for all frame types so we can use MC in AltRef
if (cm->mcomp_filter_type == SIXTAP)
@@ -698,6 +667,10 @@ void vp8_encode_frame(VP8_COMP *cpi)
&cpi->common.rtcd.subpix, sixtap8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, sixtap16x16);
+ xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
+ &cpi->common.rtcd.subpix, sixtap_avg8x8);
+ xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
+ &cpi->common.rtcd.subpix, sixtap_avg16x16);
}
else
{
@@ -709,13 +682,15 @@ void vp8_encode_frame(VP8_COMP *cpi)
&cpi->common.rtcd.subpix, bilinear8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(
&cpi->common.rtcd.subpix, bilinear16x16);
+ xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
+ &cpi->common.rtcd.subpix, bilinear_avg8x8);
+ xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
+ &cpi->common.rtcd.subpix, bilinear_avg16x16);
}
- // Reset frame count of inter 0,0 motion vector useage.
+ // Reset frame count of inter 0,0 motion vector usage.
cpi->inter_zz_count = 0;
- vpx_memset(segment_counts, 0, sizeof(segment_counts));
-
cpi->prediction_error = 0;
cpi->intra_error = 0;
cpi->skip_true_count = 0;
@@ -729,7 +704,12 @@ void vp8_encode_frame(VP8_COMP *cpi)
xd->mode_info_context = cm->mi;
+ xd->prev_mode_info_context = cm->prev_mi;
+
vp8_zero(cpi->MVcount);
+#if CONFIG_HIGH_PRECISION_MV
+ vp8_zero(cpi->MVcount_hp);
+#endif
vp8_zero(cpi->coef_counts);
vp8cx_frame_init_quantizer(cpi);
@@ -749,86 +729,21 @@ void vp8_encode_frame(VP8_COMP *cpi)
// re-initencode frame context.
init_encode_frame_mb_context(cpi);
+ cpi->rd_single_diff = cpi->rd_comp_diff = cpi->rd_hybrid_diff = 0;
+ vpx_memset(cpi->single_pred_count, 0, sizeof(cpi->single_pred_count));
+ vpx_memset(cpi->comp_pred_count, 0, sizeof(cpi->comp_pred_count));
+
{
struct vpx_usec_timer emr_timer;
vpx_usec_timer_start(&emr_timer);
-#if CONFIG_MULTITHREAD
- if (cpi->b_multi_threaded)
{
- int i;
-
- vp8cx_init_mbrthread_data(cpi, x, cpi->mb_row_ei, 1, cpi->encoding_thread_count);
-
- for (i = 0; i < cm->mb_rows; i++)
- cpi->mt_current_mb_col[i] = -1;
-
- for (i = 0; i < cpi->encoding_thread_count; i++)
- {
- sem_post(&cpi->h_event_start_encoding[i]);
- }
-
- for (mb_row = 0; mb_row < cm->mb_rows; mb_row += (cpi->encoding_thread_count + 1))
- {
- vp8_zero(cm->left_context)
-
- tp = cpi->tok + mb_row * (cm->mb_cols * 16 * 24);
-
- encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
-
- // adjust to the next row of mbs
- x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
- x->src.u_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
- x->src.v_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
-
- xd->mode_info_context += xd->mode_info_stride * cpi->encoding_thread_count;
- x->partition_info += xd->mode_info_stride * cpi->encoding_thread_count;
- x->gf_active_ptr += cm->mb_cols * cpi->encoding_thread_count;
-
- }
-
- sem_wait(&cpi->h_event_end_encoding); /* wait for other threads to finish */
-
- cpi->tok_count = 0;
-
- for (mb_row = 0; mb_row < cm->mb_rows; mb_row ++)
- {
- cpi->tok_count += cpi->tplist[mb_row].stop - cpi->tplist[mb_row].start;
- }
-
- if (xd->segmentation_enabled)
- {
- int i, j;
-
- if (xd->segmentation_enabled)
- {
-
- for (i = 0; i < cpi->encoding_thread_count; i++)
- {
- for (j = 0; j < 4; j++)
- segment_counts[j] += cpi->mb_row_ei[i].segment_counts[j];
- }
- }
- }
-
- for (i = 0; i < cpi->encoding_thread_count; i++)
- {
- totalrate += cpi->mb_row_ei[i].totalrate;
- }
-
- }
- else
-#endif
- {
- // for each macroblock row in image
+ // for each macroblock row in the image
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
{
+ encode_mb_row(cpi, cm, mb_row, x, xd, &tp, &totalrate);
- vp8_zero(cm->left_context)
-
- encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
-
- // adjust to the next row of mbs
+ // adjust to the next row of MBs
x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
x->src.u_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
x->src.v_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
@@ -843,43 +758,6 @@ void vp8_encode_frame(VP8_COMP *cpi)
}
-
- // Work out the segment probabilites if segmentation is enabled
- if (xd->segmentation_enabled)
- {
- int tot_count;
- int i;
-
- // Set to defaults
- vpx_memset(xd->mb_segment_tree_probs, 255 , sizeof(xd->mb_segment_tree_probs));
-
- tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3];
-
- if (tot_count)
- {
- xd->mb_segment_tree_probs[0] = ((segment_counts[0] + segment_counts[1]) * 255) / tot_count;
-
- tot_count = segment_counts[0] + segment_counts[1];
-
- if (tot_count > 0)
- {
- xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) / tot_count;
- }
-
- tot_count = segment_counts[2] + segment_counts[3];
-
- if (tot_count > 0)
- xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) / tot_count;
-
- // Zero probabilities not allowed
- for (i = 0; i < MB_FEATURE_TREE_PROBS; i ++)
- {
- if (xd->mb_segment_tree_probs[i] == 0)
- xd->mb_segment_tree_probs[i] = 1;
- }
- }
- }
-
// 256 rate units to the bit
cpi->projected_frame_size = totalrate >> 8; // projected_frame_size in units of BYTES
@@ -932,44 +810,95 @@ void vp8_encode_frame(VP8_COMP *cpi)
}
#endif
- // Adjust the projected reference frame useage probability numbers to reflect
- // what we have just seen. This may be usefull when we make multiple itterations
- // of the recode loop rather than continuing to use values from the previous frame.
- if ((cm->frame_type != KEY_FRAME) && !cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)
- {
- const int *const rfct = cpi->count_mb_ref_frame_usage;
- const int rf_intra = rfct[INTRA_FRAME];
- const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+#if 0
+ // Keep record of the total distortion this time around for future use
+ cpi->last_frame_distortion = cpi->frame_distortion;
+#endif
- if ((rf_intra + rf_inter) > 0)
- {
- cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
+}
- if (cpi->prob_intra_coded < 1)
- cpi->prob_intra_coded = 1;
+void vp8_encode_frame(VP8_COMP *cpi)
+{
+ if (cpi->sf.RD)
+ {
+ int frame_type, pred_type;
+ int redo = 0;
+ int single_diff, comp_diff, hybrid_diff;
+
+ /*
+ * This code does a single RD pass over the whole frame assuming
+ * either compound, single or hybrid prediction as per whatever has
+ * worked best for that type of frame in the past.
+ * It also predicts whether another coding mode would have worked
+ * better that this coding mode. If that is the case, it remembers
+ * that for subsequent frames. If the difference is above a certain
+ * threshold, it will actually re-encode the current frame using
+ * that different coding mode.
+ */
+ if (cpi->common.frame_type == KEY_FRAME)
+ frame_type = 0;
+ else if (cpi->is_src_frame_alt_ref && cpi->common.refresh_golden_frame)
+ frame_type = 3;
+ else if (cpi->common.refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
+ frame_type = 1;
+ else
+ frame_type = 2;
+
+ if (cpi->rd_prediction_type_threshes[frame_type][1] >
+ cpi->rd_prediction_type_threshes[frame_type][0] &&
+ cpi->rd_prediction_type_threshes[frame_type][1] >
+ cpi->rd_prediction_type_threshes[frame_type][2])
+ pred_type = COMP_PREDICTION_ONLY;
+ else if (cpi->rd_prediction_type_threshes[frame_type][0] >
+ cpi->rd_prediction_type_threshes[frame_type][1] &&
+ cpi->rd_prediction_type_threshes[frame_type][0] >
+ cpi->rd_prediction_type_threshes[frame_type][2])
+ pred_type = SINGLE_PREDICTION_ONLY;
+ else
+ pred_type = HYBRID_PREDICTION;
+
+ cpi->common.comp_pred_mode = pred_type;
+ encode_frame_internal(cpi);
+
+ single_diff = cpi->rd_single_diff / cpi->common.MBs;
+ cpi->rd_prediction_type_threshes[frame_type][0] += single_diff;
+ cpi->rd_prediction_type_threshes[frame_type][0] >>= 1;
+ comp_diff = cpi->rd_comp_diff / cpi->common.MBs;
+ cpi->rd_prediction_type_threshes[frame_type][1] += comp_diff;
+ cpi->rd_prediction_type_threshes[frame_type][1] >>= 1;
+ hybrid_diff = cpi->rd_hybrid_diff / cpi->common.MBs;
+ cpi->rd_prediction_type_threshes[frame_type][2] += hybrid_diff;
+ cpi->rd_prediction_type_threshes[frame_type][2] >>= 1;
+
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
+ {
+ int single_count_zero = 0;
+ int comp_count_zero = 0;
+ int i;
- if ((cm->frames_since_golden > 0) || cpi->source_alt_ref_active)
+ for ( i = 0; i < COMP_PRED_CONTEXTS; i++ )
{
- cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
-
- if (cpi->prob_last_coded < 1)
- cpi->prob_last_coded = 1;
-
- cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
- ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+ single_count_zero += cpi->single_pred_count[i];
+ comp_count_zero += cpi->comp_pred_count[i];
+ }
- if (cpi->prob_gf_coded < 1)
- cpi->prob_gf_coded = 1;
+ if (comp_count_zero == 0)
+ {
+ cpi->common.comp_pred_mode = SINGLE_PREDICTION_ONLY;
+ }
+ else if (single_count_zero == 0)
+ {
+ cpi->common.comp_pred_mode = COMP_PREDICTION_ONLY;
}
}
}
-
-#if 0
- // Keep record of the total distortion this time around for future use
- cpi->last_frame_distortion = cpi->frame_distortion;
-#endif
+ else
+ {
+ encode_frame_internal(cpi);
+ }
}
+
void vp8_setup_block_ptrs(MACROBLOCK *x)
{
int r, c;
@@ -1070,6 +999,7 @@ static void sum_intra_stats(VP8_COMP *cpi, MACROBLOCK *x)
const int is_key = cpi->common.frame_type == KEY_FRAME;
++ (is_key ? uv_modes : inter_uv_modes)[uvm];
+ ++ uv_modes_y[m][uvm];
if (m == B_PRED)
{
@@ -1079,11 +1009,18 @@ static void sum_intra_stats(VP8_COMP *cpi, MACROBLOCK *x)
do
{
- ++ bct[xd->block[b].bmi.mode];
+ ++ bct[xd->block[b].bmi.as_mode.first];
}
while (++b < 16);
}
+ if(m==I8X8_PRED)
+ {
+ i8x8_modes[xd->block[0].bmi.as_mode.first]++;
+ i8x8_modes[xd->block[2].bmi.as_mode.first]++;
+ i8x8_modes[xd->block[8].bmi.as_mode.first]++;
+ i8x8_modes[xd->block[10].bmi.as_mode.first]++;
+ }
#endif
++cpi->ymode_count[m];
@@ -1117,10 +1054,11 @@ int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
{
int rate;
- if (cpi->sf.RD && cpi->compressor_speed != 2)
- vp8_rd_pick_intra_mode(cpi, x, &rate);
- else
- vp8_pick_intra_mode(cpi, x, &rate);
+ // Non rd path deprecated in test code base
+ //if (cpi->sf.RD && cpi->compressor_speed != 2)
+ vp8_rd_pick_intra_mode(cpi, x, &rate);
+ //else
+ // vp8_pick_intra_mode(cpi, x, &rate);
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
{
@@ -1128,12 +1066,32 @@ int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
vp8_update_zbin_extra(cpi, x);
}
- if (x->e_mbd.mode_info_context->mbmi.mode == B_PRED)
+ /* test code: set transform size based on mode selection */
+ if(cpi->common.txfm_mode == ALLOW_8X8
+ && x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != B_PRED)
+ {
+ x->e_mbd.mode_info_context->mbmi.txfm_size = TX_8X8;
+ cpi->t8x8_count++;
+ }
+ else
+ {
+ x->e_mbd.mode_info_context->mbmi.txfm_size = TX_4X4;
+ cpi->t4x4_count ++;
+ }
+
+ if(x->e_mbd.mode_info_context->mbmi.mode == I8X8_PRED)
+ {
+ vp8_encode_intra8x8mby(IF_RTCD(&cpi->rtcd), x);
+ vp8_encode_intra8x8mbuv(IF_RTCD(&cpi->rtcd), x);
+ }
+ else if (x->e_mbd.mode_info_context->mbmi.mode == B_PRED)
vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
else
vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
- vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
+ if(x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED)
+ vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
sum_intra_stats(cpi, x);
vp8_tokenize_mb(cpi, &x->e_mbd, t);
@@ -1151,21 +1109,27 @@ int vp8cx_encode_inter_macroblock
int recon_yoffset, int recon_uvoffset
)
{
+ VP8_COMMON *cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
int intra_error = 0;
int rate;
int distortion;
+ unsigned char *segment_id = &xd->mode_info_context->mbmi.segment_id;
+ int seg_ref_active;
+ unsigned char ref_pred_flag;
x->skip = 0;
if (xd->segmentation_enabled)
- x->encode_breakout = cpi->segment_encode_breakout[xd->mode_info_context->mbmi.segment_id];
+ x->encode_breakout = cpi->segment_encode_breakout[*segment_id];
else
x->encode_breakout = cpi->oxcf.encode_breakout;
- if (cpi->sf.RD)
+ //if (cpi->sf.RD)
+ // For now this codebase is limited to a single rd encode path
{
int zbin_mode_boost_enabled = cpi->zbin_mode_boost_enabled;
+ int single, compound, hybrid;
/* Are we using the fast quantizer for the mode selection? */
if(cpi->sf.use_fastquant_for_pick)
@@ -1180,7 +1144,39 @@ int vp8cx_encode_inter_macroblock
cpi->zbin_mode_boost_enabled = 0;
}
vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
- &distortion, &intra_error);
+ &distortion, &intra_error, &single, &compound, &hybrid);
+
+ cpi->rd_single_diff += single;
+ cpi->rd_comp_diff += compound;
+ cpi->rd_hybrid_diff += hybrid;
+ if (x->e_mbd.mode_info_context->mbmi.ref_frame &&
+ x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+ {
+ unsigned char pred_context;
+
+ pred_context = get_pred_context( cm, xd, PRED_COMP );
+
+ if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME)
+ cpi->single_pred_count[pred_context]++;
+ else
+ cpi->comp_pred_count[pred_context]++;
+ }
+
+
+ /* test code: set transform size based on mode selection */
+ if( cpi->common.txfm_mode == ALLOW_8X8
+ && x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+ {
+ x->e_mbd.mode_info_context->mbmi.txfm_size = TX_8X8;
+ cpi->t8x8_count ++;
+ }
+ else
+ {
+ x->e_mbd.mode_info_context->mbmi.txfm_size = TX_4X4;
+ cpi->t4x4_count++;
+ }
/* switch back to the regular quantizer for the encode */
if (cpi->sf.improved_quant)
@@ -1190,14 +1186,14 @@ int vp8cx_encode_inter_macroblock
cpi->mb.quantize_b_pair = QUANTIZE_INVOKE(&cpi->rtcd.quantize,
quantb_pair);
}
-
/* restore cpi->zbin_mode_boost_enabled */
cpi->zbin_mode_boost_enabled = zbin_mode_boost_enabled;
}
- else
- vp8_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
- &distortion, &intra_error);
+ //else
+ // The non rd encode path has been deleted from this code base
+ // to simplify development
+ // vp8_pick_inter_mode
cpi->prediction_error += distortion;
cpi->intra_error += intra_error;
@@ -1208,30 +1204,6 @@ int vp8cx_encode_inter_macroblock
adjust_act_zbin( cpi, x );
}
-#if 0
- // Experimental RD code
- cpi->frame_distortion += distortion;
- cpi->last_mb_distortion = distortion;
-#endif
-
- // MB level adjutment to quantizer setup
- if (xd->segmentation_enabled)
- {
- // If cyclic update enabled
- if (cpi->cyclic_refresh_mode_enabled)
- {
- // Clear segment_id back to 0 if not coded (last frame 0,0)
- if ((xd->mode_info_context->mbmi.segment_id == 1) &&
- ((xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) || (xd->mode_info_context->mbmi.mode != ZEROMV)))
- {
- xd->mode_info_context->mbmi.segment_id = 0;
-
- /* segment_id changed, so update */
- vp8cx_mb_init_quantizer(cpi, x);
- }
- }
- }
-
{
// Experimental code. Special case for gf and arf zeromv modes.
// Increase zbin size to supress noise
@@ -1260,21 +1232,56 @@ int vp8cx_encode_inter_macroblock
vp8_update_zbin_extra(cpi, x);
}
- cpi->count_mb_ref_frame_usage[xd->mode_info_context->mbmi.ref_frame] ++;
+ seg_ref_active = segfeature_active( xd, *segment_id, SEG_LVL_REF_FRAME );
+
+ // SET VARIOUS PREDICTION FLAGS
+
+ // Did the chosen reference frame match its predicted value.
+ ref_pred_flag = ( (xd->mode_info_context->mbmi.ref_frame ==
+ get_pred_ref( cm, xd )) );
+ set_pred_flag( xd, PRED_REF, ref_pred_flag );
+
+ // If we have just a single reference frame coded for a segment then
+ // exclude from the reference frame counts used to work out
+ // probabilities. NOTE: At the moment we dont support custom trees
+ // for the reference frame coding for each segment but this is a
+ // possible future action.
+ if ( !seg_ref_active ||
+ ( ( check_segref( xd, *segment_id, INTRA_FRAME ) +
+ check_segref( xd, *segment_id, LAST_FRAME ) +
+ check_segref( xd, *segment_id, GOLDEN_FRAME ) +
+ check_segref( xd, *segment_id, ALTREF_FRAME ) ) > 1 ) )
+ {
+// TODO this may not be a good idea as it makes sample size small and means
+// the predictor functions cannot use data about most likely value only most
+// likely unpredicted value.
+//#if CONFIG_COMPRED
+// // Only update count for incorrectly predicted cases
+// if ( !ref_pred_flag )
+//#endif
+ {
+ cpi->count_mb_ref_frame_usage
+ [xd->mode_info_context->mbmi.ref_frame]++;
+ }
+ }
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
{
- vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
-
if (xd->mode_info_context->mbmi.mode == B_PRED)
{
+ vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
}
+ else if(xd->mode_info_context->mbmi.mode == I8X8_PRED)
+ {
+ vp8_encode_intra8x8mby(IF_RTCD(&cpi->rtcd), x);
+ vp8_encode_intra8x8mbuv(IF_RTCD(&cpi->rtcd), x);
+ }
else
{
+ vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
}
-
sum_intra_stats(cpi, x);
}
else
@@ -1292,6 +1299,24 @@ int vp8cx_encode_inter_macroblock
xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
+ if (xd->mode_info_context->mbmi.second_ref_frame) {
+ int second_ref_fb_idx;
+
+ if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME)
+ second_ref_fb_idx = cpi->common.lst_fb_idx;
+ else if (xd->mode_info_context->mbmi.second_ref_frame == GOLDEN_FRAME)
+ second_ref_fb_idx = cpi->common.gld_fb_idx;
+ else
+ second_ref_fb_idx = cpi->common.alt_fb_idx;
+
+ xd->second_pre.y_buffer = cpi->common.yv12_fb[second_ref_fb_idx].y_buffer +
+ recon_yoffset;
+ xd->second_pre.u_buffer = cpi->common.yv12_fb[second_ref_fb_idx].u_buffer +
+ recon_uvoffset;
+ xd->second_pre.v_buffer = cpi->common.yv12_fb[second_ref_fb_idx].v_buffer +
+ recon_uvoffset;
+ }
+
if (!x->skip)
{
vp8_encode_inter16x16(IF_RTCD(&cpi->rtcd), x);
@@ -1302,14 +1327,40 @@ int vp8cx_encode_inter_macroblock
}
else
+ {
vp8_build_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
xd->dst.u_buffer, xd->dst.v_buffer,
xd->dst.y_stride, xd->dst.uv_stride);
-
+ }
}
if (!x->skip)
+ {
+#ifdef ENC_DEBUG
+ if (enc_debug)
+ {
+ int i;
+ printf("Segment=%d [%d, %d]: %d %d:\n", x->e_mbd.mode_info_context->mbmi.segment_id, mb_col_debug, mb_row_debug, xd->mb_to_left_edge, xd->mb_to_top_edge);
+ for (i =0; i<400; i++) {
+ printf("%3d ", xd->qcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("\n");
+ printf("eobs = ");
+ for (i=0;i<25;i++)
+ printf("%d:%d ", i, xd->block[i].eob);
+ printf("\n");
+ fflush(stdout);
+ }
+#endif
vp8_tokenize_mb(cpi, xd, t);
+#ifdef ENC_DEBUG
+ if (enc_debug) {
+ printf("Tokenized\n");
+ fflush(stdout);
+ }
+#endif
+ }
else
{
if (cpi->common.mb_no_coeff_skip)
@@ -1325,6 +1376,5 @@ int vp8cx_encode_inter_macroblock
cpi->skip_false_count ++;
}
}
-
return rate;
}
diff --git a/vp8/encoder/encodeintra.c b/vp8/encoder/encodeintra.c
index 4a77c1ff3..f34de6f75 100644
--- a/vp8/encoder/encodeintra.c
+++ b/vp8/encoder/encodeintra.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "quantize.h"
#include "vp8/common/reconintra.h"
@@ -22,22 +22,29 @@
#include "encodeintra.h"
+#ifdef ENC_DEBUG
+extern int enc_debug;
+#endif
+
#if CONFIG_RUNTIME_CPU_DETECT
#define IF_RTCD(x) (x)
#else
#define IF_RTCD(x) NULL
#endif
-int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred)
+int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_16x16_pred)
{
int i;
int intra_pred_var = 0;
(void) cpi;
- if (use_dc_pred)
+ if (use_16x16_pred)
{
x->e_mbd.mode_info_context->mbmi.mode = DC_PRED;
+#if CONFIG_COMP_INTRA_PRED
+ x->e_mbd.mode_info_context->mbmi.second_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
@@ -47,7 +54,7 @@ int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred)
{
for (i = 0; i < 16; i++)
{
- x->e_mbd.block[i].bmi.as_mode = B_DC_PRED;
+ x->e_mbd.block[i].bmi.as_mode.first = B_DC_PRED;
vp8_encode_intra4x4block(IF_RTCD(&cpi->rtcd), x, i);
}
}
@@ -63,8 +70,20 @@ void vp8_encode_intra4x4block(const VP8_ENCODER_RTCD *rtcd,
BLOCKD *b = &x->e_mbd.block[ib];
BLOCK *be = &x->block[ib];
+#if CONFIG_COMP_INTRA_PRED
+ if (b->bmi.as_mode.second == (B_PREDICTION_MODE) (B_DC_PRED - 1))
+ {
+#endif
RECON_INVOKE(&rtcd->common->recon, intra4x4_predict)
- (b, b->bmi.as_mode, b->predictor);
+ (b, b->bmi.as_mode.first, b->predictor);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ RECON_INVOKE(&rtcd->common->recon, comp_intra4x4_predict)
+ (b, b->bmi.as_mode.first, b->bmi.as_mode.second, b->predictor);
+ }
+#endif
ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 16);
@@ -93,18 +112,72 @@ void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
{
BLOCK *b = &x->block[0];
+ int tx_type = x->e_mbd.mode_info_context->mbmi.txfm_size;
+
+#if CONFIG_COMP_INTRA_PRED
+ if (x->e_mbd.mode_info_context->mbmi.second_mode == (MB_PREDICTION_MODE) (DC_PRED - 1))
+#endif
RECON_INVOKE(&rtcd->common->recon, build_intra_predictors_mby)(&x->e_mbd);
+#if CONFIG_COMP_INTRA_PRED
+ else
+ RECON_INVOKE(&rtcd->common->recon, build_comp_intra_predictors_mby)(&x->e_mbd);
+#endif
ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, *(b->base_src), x->e_mbd.predictor, b->src_stride);
- vp8_transform_intra_mby(x);
+ if( tx_type == TX_8X8 )
+ vp8_transform_intra_mby_8x8(x);
+ else
+ vp8_transform_intra_mby(x);
- vp8_quantize_mby(x);
+ if(tx_type == TX_8X8)
+ vp8_quantize_mby_8x8(x);
+ else
+ vp8_quantize_mby(x);
if (x->optimize)
+ {
+ if( tx_type == TX_8X8 )
+ vp8_optimize_mby_8x8(x, rtcd);
+ else
vp8_optimize_mby(x, rtcd);
+ }
- vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ if(tx_type == TX_8X8)
+ vp8_inverse_transform_mby_8x8(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ else
+ vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+#ifdef ENC_DEBUG
+ if (enc_debug) {
+ int i;
+ printf("Intra qcoeff:\n");
+ printf("%d %d:\n", x->e_mbd.mb_to_left_edge, x->e_mbd.mb_to_top_edge);
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.qcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("Intra dqcoeff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.dqcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("Intra diff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.diff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("Intra predictor:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.predictor[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("eobs:\n");
+ for (i=0;i<25;i++)
+ printf("%d ", x->e_mbd.block[i].eob);
+ printf("\n");
+ }
+#endif
RECON_INVOKE(&rtcd->common->recon, recon_mby)
(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
@@ -113,18 +186,181 @@ void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
void vp8_encode_intra16x16mbuv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
{
+ int tx_type = x->e_mbd.mode_info_context->mbmi.txfm_size;
+#if CONFIG_COMP_INTRA_PRED
+ if (x->e_mbd.mode_info_context->mbmi.second_uv_mode == (MB_PREDICTION_MODE) (DC_PRED - 1))
+ {
+#endif
RECON_INVOKE(&rtcd->common->recon, build_intra_predictors_mbuv)(&x->e_mbd);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ RECON_INVOKE(&rtcd->common->recon, build_comp_intra_predictors_mbuv)(&x->e_mbd);
+ }
+#endif
ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+ if(tx_type == TX_8X8)
+ vp8_transform_mbuv_8x8(x);
+ else
+ vp8_transform_mbuv(x);
- vp8_transform_mbuv(x);
-
- vp8_quantize_mbuv(x);
-
+ if(tx_type == TX_8X8)
+ vp8_quantize_mbuv_8x8(x);
+ else
+ vp8_quantize_mbuv(x);
+
+#ifdef ENC_DEBUG
+ if (enc_debug) {
+ int i;
+ printf("vp8_encode_intra16x16mbuv\n");
+ printf("%d %d:\n", x->e_mbd.mb_to_left_edge, x->e_mbd.mb_to_top_edge);
+ printf("qcoeff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.qcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("dqcoeff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.dqcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("diff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.diff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("predictor:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.predictor[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("eobs:\n");
+ for (i=0;i<25;i++)
+ printf("%d ", x->e_mbd.block[i].eob);
+ printf("\n");
+ }
+#endif
if (x->optimize)
+ {
+ if(tx_type == TX_8X8)
+ vp8_optimize_mbuv_8x8(x, rtcd);
+ else
vp8_optimize_mbuv(x, rtcd);
+ }
- vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ if(tx_type == TX_8X8)
+ vp8_inverse_transform_mbuv_8x8(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ else
+ vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
vp8_recon_intra_mbuv(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
}
+
+void vp8_encode_intra8x8(const VP8_ENCODER_RTCD *rtcd,
+ MACROBLOCK *x, int ib)
+{
+ BLOCKD *b = &x->e_mbd.block[ib];
+ BLOCK *be = &x->block[ib];
+ const int iblock[4]={0,1,4,5};
+ int i;
+
+#if CONFIG_COMP_INTRA_PRED
+ if (b->bmi.as_mode.second == (MB_PREDICTION_MODE) (DC_PRED - 1))
+ {
+#endif
+ RECON_INVOKE(&rtcd->common->recon, intra8x8_predict)
+ (b, b->bmi.as_mode.first, b->predictor);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ RECON_INVOKE(&rtcd->common->recon, comp_intra8x8_predict)
+ (b, b->bmi.as_mode.first, b->bmi.as_mode.second, b->predictor);
+ }
+#endif
+
+ for(i=0;i<4;i++)
+ {
+ b = &x->e_mbd.block[ib + iblock[i]];
+ be = &x->block[ib + iblock[i]];
+ ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 16);
+ x->vp8_short_fdct4x4(be->src_diff, be->coeff, 32);
+ x->quantize_b(be, b);
+ vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 32);
+ RECON_INVOKE(&rtcd->common->recon, recon)(b->predictor,
+ b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+ }
+
+}
+
+extern const int vp8_i8x8_block[4];
+void vp8_encode_intra8x8mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+ int i, ib;
+
+ for(i=0;i<4;i++)
+ {
+ ib = vp8_i8x8_block[i];
+ vp8_encode_intra8x8(rtcd, x, ib);
+ }
+
+}
+
+void vp8_encode_intra_uv4x4(const VP8_ENCODER_RTCD *rtcd,
+ MACROBLOCK *x, int ib,
+ int mode, int second)
+{
+ BLOCKD *b = &x->e_mbd.block[ib];
+ BLOCK *be = &x->block[ib];
+
+#if CONFIG_COMP_INTRA_PRED
+ if (second == -1)
+ {
+#endif
+ RECON_INVOKE(&rtcd->common->recon, intra_uv4x4_predict)
+ (b, mode, b->predictor);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ RECON_INVOKE(&rtcd->common->recon, comp_intra_uv4x4_predict)
+ (b, mode, second, b->predictor);
+ }
+#endif
+
+ ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 8);
+
+ x->vp8_short_fdct4x4(be->src_diff, be->coeff, 16);
+
+ x->quantize_b(be, b);
+
+ vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 16);
+
+ RECON_INVOKE(&rtcd->common->recon, recon_uv)(b->predictor,
+ b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+}
+
+
+
+void vp8_encode_intra8x8mbuv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+ int i, ib, mode, second;
+ BLOCKD *b;
+ for(i=0;i<4;i++)
+ {
+ ib = vp8_i8x8_block[i];
+ b = &x->e_mbd.block[ib];
+ mode = b->bmi.as_mode.first;
+#if CONFIG_COMP_INTRA_PRED
+ second = b->bmi.as_mode.second;
+#else
+ second = -1;
+#endif
+ /*u */
+ vp8_encode_intra_uv4x4(rtcd, x, i+16, mode, second);
+ /*v */
+ vp8_encode_intra_uv4x4(rtcd, x, i+20, mode, second);
+ }
+}
diff --git a/vp8/encoder/encodeintra.h b/vp8/encoder/encodeintra.h
index 9c1fa5684..ae822d3d9 100644
--- a/vp8/encoder/encodeintra.h
+++ b/vp8/encoder/encodeintra.h
@@ -13,10 +13,15 @@
#define _ENCODEINTRA_H_
#include "onyx_int.h"
-int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred);
+int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_16x16_pred);
void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *, MACROBLOCK *x);
void vp8_encode_intra16x16mbuv(const VP8_ENCODER_RTCD *, MACROBLOCK *x);
void vp8_encode_intra4x4mby(const VP8_ENCODER_RTCD *, MACROBLOCK *mb);
void vp8_encode_intra4x4block(const VP8_ENCODER_RTCD *rtcd,
MACROBLOCK *x, int ib);
+void vp8_encode_intra8x8mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+void vp8_encode_intra8x8mbuv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+void vp8_encode_intra8x8(const VP8_ENCODER_RTCD *rtcd,
+ MACROBLOCK *x, int ib);
+
#endif
diff --git a/vp8/encoder/encodemb.c b/vp8/encoder/encodemb.c
index 68005ad60..ab0f1c13e 100644
--- a/vp8/encoder/encodemb.c
+++ b/vp8/encoder/encodemb.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "encodemb.h"
#include "vp8/common/reconinter.h"
#include "quantize.h"
@@ -20,12 +20,18 @@
#include "dct.h"
#include "vpx_mem/vpx_mem.h"
#include "rdopt.h"
+#include "vp8/common/systemdependent.h"
#if CONFIG_RUNTIME_CPU_DETECT
#define IF_RTCD(x) (x)
#else
#define IF_RTCD(x) NULL
#endif
+
+#ifdef ENC_DEBUG
+extern int enc_debug;
+#endif
+
void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch)
{
unsigned char *src_ptr = (*(be->base_src) + be->src);
@@ -48,6 +54,25 @@ void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch)
}
}
+void vp8_subtract_4b_c(BLOCK *be, BLOCKD *bd, int pitch)
+{
+ unsigned char *src_ptr = (*(be->base_src) + be->src);
+ short *diff_ptr = be->src_diff;
+ unsigned char *pred_ptr = bd->predictor;
+ int src_stride = be->src_stride;
+ int r, c;
+ for (r = 0; r < 8; r++)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ diff_ptr[c] = src_ptr[c] - pred_ptr[c];
+ }
+ diff_ptr += pitch;
+ pred_ptr += pitch;
+ src_ptr += src_stride;
+ }
+}
+
void vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride)
{
short *udiff = diff + 256;
@@ -117,6 +142,19 @@ static void build_dcblock(MACROBLOCK *x)
src_diff_ptr[i] = x->coeff[i * 16];
}
}
+void vp8_build_dcblock_8x8(MACROBLOCK *x)
+{
+ short *src_diff_ptr = &x->src_diff[384];
+ int i;
+ for (i = 0; i < 16; i++)
+ {
+ src_diff_ptr[i] = 0;
+ }
+ src_diff_ptr[0] = x->coeff[0 * 16];
+ src_diff_ptr[1] = x->coeff[4 * 16];
+ src_diff_ptr[4] = x->coeff[8 * 16];
+ src_diff_ptr[8] = x->coeff[12 * 16];
+}
void vp8_transform_mbuv(MACROBLOCK *x)
{
@@ -197,10 +235,109 @@ static void transform_mby(MACROBLOCK *x)
}
}
+void vp8_transform_mbuv_8x8(MACROBLOCK *x)
+{
+ int i;
+ vp8_clear_system_state();
-#define RDTRUNC(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
+ for (i = 16; i < 24; i += 4)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i].coeff[0], 16);
+ }
+}
+
+
+void vp8_transform_intra_mby_8x8(MACROBLOCK *x)//changed
+{
+ int i;
+ vp8_clear_system_state();
+
+ for (i = 0; i < 9; i += 8)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i].coeff[0], 32);
+ }
+ for (i = 2; i < 11; i += 8)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i+2].coeff[0], 32);
+ }
+ // build dc block from 16 y dc values
+ vp8_build_dcblock_8x8(x);
+ //vp8_build_dcblock(x);
+
+ // do 2nd order transform on the dc block
+ x->short_fhaar2x2(&x->block[24].src_diff[0],
+ &x->block[24].coeff[0], 8);
+
+}
+
+
+void vp8_transform_mb_8x8(MACROBLOCK *x)
+{
+ int i;
+
+ vp8_clear_system_state();
+
+ for (i = 0; i < 9; i += 8)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i].coeff[0], 32);
+ }
+ for (i = 2; i < 11; i += 8)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i+2].coeff[0], 32);
+ }
+ // build dc block from 16 y dc values
+ if (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+ vp8_build_dcblock_8x8(x);
+ //vp8_build_dcblock(x);
+
+ for (i = 16; i < 24; i += 4)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i].coeff[0], 16);
+ }
+
+ // do 2nd order transform on the dc block
+ if (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+ x->short_fhaar2x2(&x->block[24].src_diff[0],
+ &x->block[24].coeff[0], 8);
+}
+
+void vp8_transform_mby_8x8(MACROBLOCK *x)
+{
+ int i;
+
+ vp8_clear_system_state();
+
+ for (i = 0; i < 9; i += 8)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i].coeff[0], 32);
+ }
+ for (i = 2; i < 11; i += 8)
+ {
+ x->vp8_short_fdct8x8(&x->block[i].src_diff[0],
+ &x->block[i+2].coeff[0], 32);
+ }
+ // build dc block from 16 y dc values
+ if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+ {
+ //vp8_build_dcblock(x);
+ vp8_build_dcblock_8x8(x);
+ x->short_fhaar2x2(&x->block[24].src_diff[0],
+ &x->block[24].coeff[0], 8);
+ }
+}
+
+
+#define RDTRUNC(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
+#define RDTRUNC_8x8(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
typedef struct vp8_token_state vp8_token_state;
struct vp8_token_state{
@@ -214,11 +351,7 @@ struct vp8_token_state{
// TODO: experiments to find optimal multiple numbers
#define Y1_RD_MULT 4
#define UV_RD_MULT 2
-#if !CONFIG_EXTEND_QRANGE
-#define Y2_RD_MULT 16
-#else
#define Y2_RD_MULT 4
-#endif
static const int plane_rd_mult[4]=
{
@@ -474,6 +607,80 @@ static void optimize_b(MACROBLOCK *mb, int ib, int type,
*a = *l = (d->eob != !type);
}
+ /**************************************************************************
+ our inverse hadamard transform effectively is weighted sum of all 16 inputs
+ with weight either 1 or -1. It has a last stage scaling of (sum+1)>>2. And
+ dc only idct is (dc+16)>>5. So if all the sums are between -65 and 63 the
+ output after inverse wht and idct will be all zero. A sum of absolute value
+ smaller than 65 guarantees all 16 different (+1/-1) weighted sums in wht
+ fall between -65 and +65.
+ **************************************************************************/
+#define SUM_2ND_COEFF_THRESH 65
+
+static void check_reset_2nd_coeffs(MACROBLOCKD *x, int type,
+ ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+ int sum=0;
+ int i;
+ BLOCKD *bd = &x->block[24];
+ if(bd->dequant[0]>=SUM_2ND_COEFF_THRESH
+ && bd->dequant[1]>=SUM_2ND_COEFF_THRESH)
+ return;
+
+ for(i=0;i<bd->eob;i++)
+ {
+ int coef = bd->dqcoeff[vp8_default_zig_zag1d[i]];
+ sum+= (coef>=0)?coef:-coef;
+ if(sum>=SUM_2ND_COEFF_THRESH)
+ return;
+ }
+
+ if(sum < SUM_2ND_COEFF_THRESH)
+ {
+ for(i=0;i<bd->eob;i++)
+ {
+ int rc = vp8_default_zig_zag1d[i];
+ bd->qcoeff[rc]=0;
+ bd->dqcoeff[rc]=0;
+ }
+ bd->eob = 0;
+ *a = *l = (bd->eob != !type);
+ }
+}
+#define SUM_2ND_COEFF_THRESH_8X8 32
+static void check_reset_8x8_2nd_coeffs(MACROBLOCKD *x, int type,
+ ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+ int sum=0;
+ BLOCKD *bd = &x->block[24];
+ int coef;
+
+ coef = bd->dqcoeff[0];
+ sum+= (coef>=0)?coef:-coef;
+ coef = bd->dqcoeff[1];
+ sum+= (coef>=0)?coef:-coef;
+ coef = bd->dqcoeff[4];
+ sum+= (coef>=0)?coef:-coef;
+ coef = bd->dqcoeff[8];
+ sum+= (coef>=0)?coef:-coef;
+
+ if(sum < SUM_2ND_COEFF_THRESH_8X8)
+ {
+ bd->qcoeff[0] = 0;
+ bd->dqcoeff[0] = 0;
+ bd->qcoeff[1] = 0;
+ bd->dqcoeff[1] = 0;
+ bd->qcoeff[4] = 0;
+ bd->dqcoeff[4] = 0;
+ bd->qcoeff[8] = 0;
+ bd->dqcoeff[8] = 0;
+ bd->eob = 0;
+ *a = *l = (bd->eob != !type);
+ }
+}
+
+
+
static void optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
{
int b;
@@ -490,6 +697,7 @@ static void optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
tl = (ENTROPY_CONTEXT *)&t_left;
has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ &&x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED
&& x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
@@ -510,6 +718,8 @@ static void optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
b=24;
optimize_b(x, b, PLANE_TYPE_Y2,
ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
+ check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
+ ta + vp8_block2above[b], tl + vp8_block2left[b]);
}
}
@@ -537,6 +747,7 @@ void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
tl = (ENTROPY_CONTEXT *)&t_left;
has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ &&x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED
&& x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
@@ -552,6 +763,8 @@ void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
b=24;
optimize_b(x, b, PLANE_TYPE_Y2,
ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
+ check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
+ ta + vp8_block2above[b], tl + vp8_block2left[b]);
}
}
@@ -581,40 +794,463 @@ void vp8_optimize_mbuv(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
}
}
+void optimize_b_8x8(MACROBLOCK *mb, int i, int type,
+ ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
+ const VP8_ENCODER_RTCD *rtcd)
+{
+ BLOCK *b;
+ BLOCKD *d;
+ vp8_token_state tokens[65][2];
+ unsigned best_mask[2];
+ const short *dequant_ptr;
+ const short *coeff_ptr;
+ short *qcoeff_ptr;
+ short *dqcoeff_ptr;
+ int eob;
+ int i0;
+ int rc;
+ int x;
+ int sz = 0;
+ int next;
+ int rdmult;
+ int rddiv;
+ int final_eob;
+ int rd_cost0;
+ int rd_cost1;
+ int rate0;
+ int rate1;
+ int error0;
+ int error1;
+ int t0;
+ int t1;
+ int best;
+ int band;
+ int pt;
+ int err_mult = plane_rd_mult[type];
+
+ b = &mb->block[i];
+ d = &mb->e_mbd.block[i];
+
+ /* Enable this to test the effect of RDO as a replacement for the dynamic
+ * zero bin instead of an augmentation of it.
+ */
+#if 0
+ vp8_strict_quantize_b(b, d);
+#endif
+
+ dequant_ptr = d->dequant;
+ coeff_ptr = b->coeff;
+ qcoeff_ptr = d->qcoeff;
+ dqcoeff_ptr = d->dqcoeff;
+ i0 = !type;
+ eob = d->eob;
+
+ /* Now set up a Viterbi trellis to evaluate alternative roundings. */
+ rdmult = mb->rdmult * err_mult;
+ if(mb->e_mbd.mode_info_context->mbmi.ref_frame==INTRA_FRAME)
+ rdmult = (rdmult * 9)>>4;
+ rddiv = mb->rddiv;
+ best_mask[0] = best_mask[1] = 0;
+ /* Initialize the sentinel node of the trellis. */
+ tokens[eob][0].rate = 0;
+ tokens[eob][0].error = 0;
+ tokens[eob][0].next = 64;
+ tokens[eob][0].token = DCT_EOB_TOKEN;
+ tokens[eob][0].qc = 0;
+ *(tokens[eob] + 1) = *(tokens[eob] + 0);
+ next = eob;
+ for (i = eob; i-- > i0;)
+ {
+ int base_bits;
+ int d2;
+ int dx;
+
+ rc = vp8_default_zig_zag1d_8x8[i];
+ x = qcoeff_ptr[rc];
+ /* Only add a trellis state for non-zero coefficients. */
+ if (x)
+ {
+ int shortcut=0;
+ error0 = tokens[next][0].error;
+ error1 = tokens[next][1].error;
+ /* Evaluate the first possibility for this state. */
+ rate0 = tokens[next][0].rate;
+ rate1 = tokens[next][1].rate;
+ t0 = (vp8_dct_value_tokens_ptr + x)->Token;
+ /* Consider both possible successor states. */
+ if (next < 64)
+ {
+ band = vp8_coef_bands_8x8[i + 1];
+ pt = vp8_prev_token_class[t0];
+ rate0 +=
+ mb->token_costs_8x8[type][band][pt][tokens[next][0].token];
+ rate1 +=
+ mb->token_costs_8x8[type][band][pt][tokens[next][1].token];
+ }
+ rd_cost0 = RDCOST_8x8(rdmult, rddiv, rate0, error0);
+ rd_cost1 = RDCOST_8x8(rdmult, rddiv, rate1, error1);
+ if (rd_cost0 == rd_cost1)
+ {
+ rd_cost0 = RDTRUNC_8x8(rdmult, rddiv, rate0, error0);
+ rd_cost1 = RDTRUNC_8x8(rdmult, rddiv, rate1, error1);
+ }
+ /* And pick the best. */
+ best = rd_cost1 < rd_cost0;
+ base_bits = *(vp8_dct_value_cost_ptr + x);
+ dx = dqcoeff_ptr[rc] - coeff_ptr[rc];
+ d2 = dx*dx;
+ tokens[i][0].rate = base_bits + (best ? rate1 : rate0);
+ tokens[i][0].error = d2 + (best ? error1 : error0);
+ tokens[i][0].next = next;
+ tokens[i][0].token = t0;
+ tokens[i][0].qc = x;
+ best_mask[0] |= best << i;
+ /* Evaluate the second possibility for this state. */
+ rate0 = tokens[next][0].rate;
+ rate1 = tokens[next][1].rate;
+
+ if((abs(x)*dequant_ptr[rc!=0]>abs(coeff_ptr[rc])) &&
+ (abs(x)*dequant_ptr[rc!=0]<abs(coeff_ptr[rc])+dequant_ptr[rc!=0]))
+ shortcut = 1;
+ else
+ shortcut = 0;
+
+ if(shortcut)
+ {
+ sz = -(x < 0);
+ x -= 2*sz + 1;
+ }
+
+ /* Consider both possible successor states. */
+ if (!x)
+ {
+ /* If we reduced this coefficient to zero, check to see if
+ * we need to move the EOB back here.
+ */
+ t0 = tokens[next][0].token == DCT_EOB_TOKEN ?
+ DCT_EOB_TOKEN : ZERO_TOKEN;
+ t1 = tokens[next][1].token == DCT_EOB_TOKEN ?
+ DCT_EOB_TOKEN : ZERO_TOKEN;
+ }
+ else
+ {
+ t0=t1 = (vp8_dct_value_tokens_ptr + x)->Token;
+ }
+ if (next < 64)
+ {
+ band = vp8_coef_bands_8x8[i + 1];
+ if(t0!=DCT_EOB_TOKEN)
+ {
+ pt = vp8_prev_token_class[t0];
+ rate0 += mb->token_costs_8x8[type][band][pt][
+ tokens[next][0].token];
+ }
+ if(t1!=DCT_EOB_TOKEN)
+ {
+ pt = vp8_prev_token_class[t1];
+ rate1 += mb->token_costs_8x8[type][band][pt][
+ tokens[next][1].token];
+ }
+ }
+
+ rd_cost0 = RDCOST_8x8(rdmult, rddiv, rate0, error0);
+ rd_cost1 = RDCOST_8x8(rdmult, rddiv, rate1, error1);
+ if (rd_cost0 == rd_cost1)
+ {
+ rd_cost0 = RDTRUNC_8x8(rdmult, rddiv, rate0, error0);
+ rd_cost1 = RDTRUNC_8x8(rdmult, rddiv, rate1, error1);
+ }
+ /* And pick the best. */
+ best = rd_cost1 < rd_cost0;
+ base_bits = *(vp8_dct_value_cost_ptr + x);
+
+ if(shortcut)
+ {
+ dx -= (dequant_ptr[rc!=0] + sz) ^ sz;
+ d2 = dx*dx;
+ }
+ tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
+ tokens[i][1].error = d2 + (best ? error1 : error0);
+ tokens[i][1].next = next;
+ tokens[i][1].token =best?t1:t0;
+ tokens[i][1].qc = x;
+ best_mask[1] |= best << i;
+ /* Finally, make this the new head of the trellis. */
+ next = i;
+ }
+ /* There's no choice to make for a zero coefficient, so we don't
+ * add a new trellis node, but we do need to update the costs.
+ */
+ else
+ {
+ band = vp8_coef_bands_8x8[i + 1];
+ t0 = tokens[next][0].token;
+ t1 = tokens[next][1].token;
+ /* Update the cost of each path if we're past the EOB token. */
+ if (t0 != DCT_EOB_TOKEN)
+ {
+ tokens[next][0].rate += mb->token_costs_8x8[type][band][0][t0];
+ tokens[next][0].token = ZERO_TOKEN;
+ }
+ if (t1 != DCT_EOB_TOKEN)
+ {
+ tokens[next][1].rate += mb->token_costs_8x8[type][band][0][t1];
+ tokens[next][1].token = ZERO_TOKEN;
+ }
+ /* Don't update next, because we didn't add a new node. */
+ }
+ }
+
+ /* Now pick the best path through the whole trellis. */
+ band = vp8_coef_bands_8x8[i + 1];
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+ rate0 = tokens[next][0].rate;
+ rate1 = tokens[next][1].rate;
+ error0 = tokens[next][0].error;
+ error1 = tokens[next][1].error;
+ t0 = tokens[next][0].token;
+ t1 = tokens[next][1].token;
+ rate0 += mb->token_costs_8x8[type][band][pt][t0];
+ rate1 += mb->token_costs_8x8[type][band][pt][t1];
+ rd_cost0 = RDCOST_8x8(rdmult, rddiv, rate0, error0);
+ rd_cost1 = RDCOST_8x8(rdmult, rddiv, rate1, error1);
+ if (rd_cost0 == rd_cost1)
+ {
+ rd_cost0 = RDTRUNC_8x8(rdmult, rddiv, rate0, error0);
+ rd_cost1 = RDTRUNC_8x8(rdmult, rddiv, rate1, error1);
+ }
+ best = rd_cost1 < rd_cost0;
+ final_eob = i0 - 1;
+ for (i = next; i < eob; i = next)
+ {
+ x = tokens[i][best].qc;
+ if (x)
+ final_eob = i;
+ rc = vp8_default_zig_zag1d_8x8[i];
+ qcoeff_ptr[rc] = x;
+ dqcoeff_ptr[rc] = (x * dequant_ptr[rc!=0]);
+
+ next = tokens[i][best].next;
+ best = (best_mask[best] >> i) & 1;
+ }
+ final_eob++;
+
+ d->eob = final_eob;
+ *a = *l = (d->eob != !type);
+
+}
+
+void optimize_mb_8x8(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+ int b;
+ int type;
+ ENTROPY_CONTEXT_PLANES t_above, t_left;
+ ENTROPY_CONTEXT *ta;
+ ENTROPY_CONTEXT *tl;
+
+ vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+
+ type = 0;
+ for (b = 0; b < 16; b+=4)
+ {
+ optimize_b_8x8(x, b, type,
+ ta + vp8_block2above_8x8[b], tl + vp8_block2left_8x8[b],
+ rtcd);
+ *(ta + vp8_block2above_8x8[b] + 1) = *(ta + vp8_block2above_8x8[b]);
+ *(tl + vp8_block2left_8x8[b] + 1) = *(tl + vp8_block2left_8x8[b] );
+ }
+
+ for (b = 16; b < 24; b+=4)
+ {
+ optimize_b_8x8(x, b, PLANE_TYPE_UV,
+ ta + vp8_block2above_8x8[b], tl + vp8_block2left_8x8[b],
+ rtcd);
+ *(ta + vp8_block2above_8x8[b]+1) = *(ta + vp8_block2above_8x8[b]);
+ *(tl + vp8_block2left_8x8[b]+1 ) = *(tl + vp8_block2left_8x8[b]);
+ }
+
+ //8x8 always have 2nd roder haar block
+ check_reset_8x8_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
+ ta + vp8_block2above_8x8[24], tl + vp8_block2left_8x8[24]);
+
+}
+
+void vp8_optimize_mby_8x8(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+ int b;
+ int type;
+ int has_2nd_order;
+
+ ENTROPY_CONTEXT_PLANES t_above, t_left;
+ ENTROPY_CONTEXT *ta;
+ ENTROPY_CONTEXT *tl;
+
+
+ if (!x->e_mbd.above_context)
+ return;
+
+ if (!x->e_mbd.left_context)
+ return;
+
+ vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+ type = 0;
+ for (b = 0; b < 16; b+=4)
+ {
+ optimize_b_8x8(x, b, type,
+ ta + vp8_block2above[b], tl + vp8_block2left[b],
+ rtcd);
+ *(ta + vp8_block2above_8x8[b] + 1) = *(ta + vp8_block2above_8x8[b]);
+ *(tl + vp8_block2left_8x8[b] + 1) = *(tl + vp8_block2left_8x8[b] );
+ }
+ //8x8 always have 2nd roder haar block
+ check_reset_8x8_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
+ ta + vp8_block2above_8x8[24], tl + vp8_block2left_8x8[24]);
+
+}
+
+void vp8_optimize_mbuv_8x8(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+ int b;
+ ENTROPY_CONTEXT_PLANES t_above, t_left;
+ ENTROPY_CONTEXT *ta;
+ ENTROPY_CONTEXT *tl;
+
+ if (!x->e_mbd.above_context)
+ return;
+
+ if (!x->e_mbd.left_context)
+ return;
+
+ vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+
+ for (b = 16; b < 24; b+=4)
+ {
+ optimize_b_8x8(x, b, PLANE_TYPE_UV,
+ ta + vp8_block2above_8x8[b], tl + vp8_block2left_8x8[b],
+ rtcd);
+ *(ta + vp8_block2above_8x8[b]+1) = *(ta + vp8_block2above_8x8[b]);
+ *(tl + vp8_block2left_8x8[b]+1 ) = *(tl + vp8_block2left_8x8[b]);
+ }
+
+}
+
void vp8_encode_inter16x16(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
{
+ int tx_type = x->e_mbd.mode_info_context->mbmi.txfm_size;
vp8_build_inter_predictors_mb(&x->e_mbd);
vp8_subtract_mb(rtcd, x);
- transform_mb(x);
+ if( tx_type == TX_8X8 )
+ vp8_transform_mb_8x8(x);
+ else
+ transform_mb(x);
- vp8_quantize_mb(x);
+ if( tx_type == TX_8X8 )
+ vp8_quantize_mb_8x8(x);
+ else
+ vp8_quantize_mb(x);
if (x->optimize)
+ {
+ if( tx_type == TX_8X8 )
+ optimize_mb_8x8(x, rtcd);
+ else
optimize_mb(x, rtcd);
+ }
+
+ if( tx_type == TX_8X8 )
+ vp8_inverse_transform_mb_8x8(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ else
+ vp8_inverse_transform_mb(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
- vp8_inverse_transform_mb(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ if( tx_type == TX_8X8 )
+ {
+#ifdef ENC_DEBUG
+ if (enc_debug)
+ {
+ int i;
+ printf("qcoeff:\n");
+ printf("%d %d:\n", x->e_mbd.mb_to_left_edge, x->e_mbd.mb_to_top_edge);
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.qcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("dqcoeff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.dqcoeff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("diff:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.diff[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("predictor:\n");
+ for (i =0; i<400; i++) {
+ printf("%3d ", x->e_mbd.predictor[i]);
+ if (i%16 == 15) printf("\n");
+ }
+ printf("\n");
+ }
+#endif
+ }
RECON_INVOKE(&rtcd->common->recon, recon_mb)
(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+#ifdef ENC_DEBUG
+ if (enc_debug) {
+ int i, j, k;
+ printf("Final Reconstruction\n");
+ for (i =0; i<16; i+=4) {
+ BLOCKD *b = &x->e_mbd.block[i];
+ unsigned char *d = *(b->base_dst) + b->dst;
+ for (k=0; k<4; k++) {
+ for (j=0; j<16; j++)
+ printf("%3d ", d[j]);
+ printf("\n");
+ d+=b->dst_stride;
+ }
+ }
+ }
+#endif
}
-/* this funciton is used by first pass only */
+/* this function is used by first pass only */
void vp8_encode_inter16x16y(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
{
+ int tx_type = x->e_mbd.mode_info_context->mbmi.txfm_size;
+
BLOCK *b = &x->block[0];
vp8_build_inter16x16_predictors_mby(&x->e_mbd);
ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, *(b->base_src), x->e_mbd.predictor, b->src_stride);
- transform_mby(x);
+ if( tx_type == TX_8X8 )
+ vp8_transform_mby_8x8(x);
+ else
+ transform_mby(x);
vp8_quantize_mby(x);
- vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ if( tx_type == TX_8X8 )
+ vp8_inverse_transform_mby_8x8(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+ else
+ vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
RECON_INVOKE(&rtcd->common->recon, recon_mby)
(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
diff --git a/vp8/encoder/encodemb.h b/vp8/encoder/encodemb.h
index 8fa457aa8..e211eea65 100644
--- a/vp8/encoder/encodemb.h
+++ b/vp8/encoder/encodemb.h
@@ -12,7 +12,7 @@
#ifndef __INC_ENCODEMB_H
#define __INC_ENCODEMB_H
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "block.h"
#define prototype_mberr(sym) \
@@ -103,4 +103,15 @@ void vp8_transform_intra_mby(MACROBLOCK *x);
void vp8_optimize_mby(MACROBLOCK *x, const struct VP8_ENCODER_RTCD *rtcd);
void vp8_optimize_mbuv(MACROBLOCK *x, const struct VP8_ENCODER_RTCD *rtcd);
void vp8_encode_inter16x16y(const struct VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+
+void vp8_transform_mb_8x8(MACROBLOCK *mb);
+void vp8_transform_mby_8x8(MACROBLOCK *x);
+void vp8_transform_mbuv_8x8(MACROBLOCK *x);
+void vp8_transform_intra_mby_8x8(MACROBLOCK *x);
+void vp8_build_dcblock_8x8(MACROBLOCK *b);
+void vp8_optimize_mby_8x8(MACROBLOCK *x, const struct VP8_ENCODER_RTCD *rtcd);
+void vp8_optimize_mbuv_8x8(MACROBLOCK *x, const struct VP8_ENCODER_RTCD *rtcd);
+
+void vp8_subtract_4b_c(BLOCK *be, BLOCKD *bd, int pitch);
+
#endif
diff --git a/vp8/encoder/encodemv.c b/vp8/encoder/encodemv.c
index a4849c654..0ba8848a0 100644
--- a/vp8/encoder/encodemv.c
+++ b/vp8/encoder/encodemv.c
@@ -20,6 +20,11 @@
extern unsigned int active_section;
#endif
+//#define DEBUG_ENC_MV
+#ifdef DEBUG_ENC_MV
+int enc_mvcount = 0;
+#endif
+
static void encode_mvcomponent(
vp8_writer *const w,
const int v,
@@ -32,8 +37,7 @@ static void encode_mvcomponent(
if (x < mvnum_short) // Small
{
vp8_write(w, 0, p [mvpis_short]);
- vp8_treed_write(w, vp8_small_mvtree, p + MVPshort, x, 3);
-
+ vp8_treed_write(w, vp8_small_mvtree, p + MVPshort, x, mvnum_short_bits);
if (!x)
return; // no sign bit
}
@@ -46,17 +50,17 @@ static void encode_mvcomponent(
do
vp8_write(w, (x >> i) & 1, p [MVPbits + i]);
- while (++i < 3);
+ while (++i < mvnum_short_bits);
i = mvlong_width - 1; /* Skip bit 3, which is sometimes implicit */
do
vp8_write(w, (x >> i) & 1, p [MVPbits + i]);
- while (--i > 3);
+ while (--i > mvnum_short_bits);
- if (x & 0xFFF0)
- vp8_write(w, (x >> 3) & 1, p [MVPbits + 3]);
+ if (x & ~((2<<mvnum_short_bits)-1))
+ vp8_write(w, (x >> mvnum_short_bits) & 1, p [MVPbits + mvnum_short_bits]);
}
vp8_write(w, v < 0, p [MVPsign]);
@@ -91,9 +95,20 @@ void vp8_encode_motion_vector(vp8_writer *w, const MV *mv, const MV_CONTEXT *mvc
}
}
#endif
-
encode_mvcomponent(w, mv->row >> 1, &mvc[0]);
encode_mvcomponent(w, mv->col >> 1, &mvc[1]);
+#ifdef DEBUG_ENC_MV
+ {
+ int i;
+ printf("%d (np): %d %d\n", enc_mvcount++,
+ (mv->row >> 1)<<1, (mv->col >> 1)<<1);
+ //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[0])->prob[i]);
+ //printf("\n");
+ //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[1])->prob[i]);
+ //printf("\n");
+ fflush(stdout);
+ }
+#endif
}
@@ -106,7 +121,7 @@ static unsigned int cost_mvcomponent(const int v, const struct mv_context *mvc)
if (x < mvnum_short)
{
cost = vp8_cost_zero(p [mvpis_short])
- + vp8_treed_cost(vp8_small_mvtree, p + MVPshort, x, 3);
+ + vp8_treed_cost(vp8_small_mvtree, p + MVPshort, x, mvnum_short_bits);
if (!x)
return cost;
@@ -119,17 +134,17 @@ static unsigned int cost_mvcomponent(const int v, const struct mv_context *mvc)
do
cost += vp8_cost_bit(p [MVPbits + i], (x >> i) & 1);
- while (++i < 3);
+ while (++i < mvnum_short_bits);
i = mvlong_width - 1; /* Skip bit 3, which is sometimes implicit */
do
cost += vp8_cost_bit(p [MVPbits + i], (x >> i) & 1);
- while (--i > 3);
+ while (--i > mvnum_short_bits);
- if (x & 0xFFF0)
- cost += vp8_cost_bit(p [MVPbits + 3], (x >> 3) & 1);
+ if (x & ~((2<<mvnum_short_bits)-1))
+ cost += vp8_cost_bit(p [MVPbits + mvnum_short_bits], (x >> mvnum_short_bits) & 1);
}
return cost; // + vp8_cost_bit( p [MVPsign], v < 0);
@@ -258,7 +273,7 @@ static void write_component_probs(
{
const int c = events [mv_max];
- is_short_ct [0] += c; // Short vector
+ is_short_ct [0] += c; // Short vector
short_ct [0] += c; // Magnitude distribution
}
@@ -342,7 +357,7 @@ static void write_component_probs(
int j = 0;
vp8_tree_probs_from_distribution(
- 8, vp8_small_mvencodings, vp8_small_mvtree,
+ mvnum_short, vp8_small_mvencodings, vp8_small_mvtree,
p, short_bct, short_ct,
256, 1
);
@@ -415,3 +430,345 @@ void vp8_write_mvprobs(VP8_COMP *cpi)
active_section = 5;
#endif
}
+
+#if CONFIG_HIGH_PRECISION_MV
+
+static void encode_mvcomponent_hp(
+ vp8_writer *const w,
+ const int v,
+ const struct mv_context_hp *mvc
+)
+{
+ const vp8_prob *p = mvc->prob;
+ const int x = v < 0 ? -v : v;
+
+ if (x < mvnum_short_hp) // Small
+ {
+ vp8_write(w, 0, p [mvpis_short_hp]);
+ vp8_treed_write(w, vp8_small_mvtree_hp, p + MVPshort_hp, x,
+ mvnum_short_bits_hp);
+ if (!x)
+ return; // no sign bit
+ }
+ else // Large
+ {
+ int i = 0;
+
+ vp8_write(w, 1, p [mvpis_short_hp]);
+
+ do
+ vp8_write(w, (x >> i) & 1, p [MVPbits_hp + i]);
+
+ while (++i < mvnum_short_bits_hp);
+
+ i = mvlong_width_hp - 1; /* Skip bit 3, which is sometimes implicit */
+
+ do
+ vp8_write(w, (x >> i) & 1, p [MVPbits_hp + i]);
+
+ while (--i > mvnum_short_bits_hp);
+
+ if (x & ~((2<<mvnum_short_bits_hp)-1))
+ vp8_write(w, (x >> mvnum_short_bits_hp) & 1,
+ p [MVPbits_hp + mvnum_short_bits_hp]);
+ }
+
+ vp8_write(w, v < 0, p [MVPsign_hp]);
+}
+#if 0
+static int max_mv_r = 0;
+static int max_mv_c = 0;
+#endif
+void vp8_encode_motion_vector_hp(vp8_writer *w, const MV *mv,
+ const MV_CONTEXT_HP *mvc)
+{
+
+#if 0
+ {
+ if (abs(mv->row >> 1) > max_mv_r)
+ {
+ FILE *f = fopen("maxmv.stt", "a");
+ max_mv_r = abs(mv->row >> 1);
+ fprintf(f, "New Mv Row Max %6d\n", (mv->row >> 1));
+
+ if ((abs(mv->row) / 2) != max_mv_r)
+ fprintf(f, "MV Row conversion error %6d\n", abs(mv->row) / 2);
+
+ fclose(f);
+ }
+
+ if (abs(mv->col >> 1) > max_mv_c)
+ {
+ FILE *f = fopen("maxmv.stt", "a");
+ fprintf(f, "New Mv Col Max %6d\n", (mv->col >> 1));
+ max_mv_c = abs(mv->col >> 1);
+ fclose(f);
+ }
+ }
+#endif
+ encode_mvcomponent_hp(w, mv->row, &mvc[0]);
+ encode_mvcomponent_hp(w, mv->col, &mvc[1]);
+#ifdef DEBUG_ENC_MV
+ {
+ int i;
+ printf("%d (hp): %d %d\n", enc_mvcount++, mv->row, mv->col);
+ //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[0])->prob[i]);
+ //printf("\n");
+ //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[1])->prob[i]);
+ //printf("\n");
+ fflush(stdout);
+ }
+#endif
+}
+
+
+static unsigned int cost_mvcomponent_hp(const int v,
+ const struct mv_context_hp *mvc)
+{
+ const vp8_prob *p = mvc->prob;
+ const int x = v; //v<0? -v:v;
+ unsigned int cost;
+
+ if (x < mvnum_short_hp)
+ {
+ cost = vp8_cost_zero(p [mvpis_short_hp])
+ + vp8_treed_cost(vp8_small_mvtree_hp, p + MVPshort_hp, x,
+ mvnum_short_bits_hp);
+
+ if (!x)
+ return cost;
+ }
+ else
+ {
+ int i = 0;
+ cost = vp8_cost_one(p [mvpis_short_hp]);
+
+ do
+ cost += vp8_cost_bit(p [MVPbits_hp + i], (x >> i) & 1);
+
+ while (++i < mvnum_short_bits_hp);
+
+ i = mvlong_width_hp - 1; /* Skip bit 3, which is sometimes implicit */
+
+ do
+ cost += vp8_cost_bit(p [MVPbits_hp + i], (x >> i) & 1);
+
+ while (--i > mvnum_short_bits_hp);
+
+ if (x & ~((2<<mvnum_short_bits_hp)-1))
+ cost += vp8_cost_bit(p [MVPbits_hp + mvnum_short_bits_hp],
+ (x >> mvnum_short_bits_hp) & 1);
+ }
+
+ return cost; // + vp8_cost_bit( p [MVPsign], v < 0);
+}
+
+void vp8_build_component_cost_table_hp(int *mvcost[2],
+ const MV_CONTEXT_HP *mvc,
+ int mvc_flag[2])
+{
+ int i = 1; //-mv_max;
+ unsigned int cost0 = 0;
+ unsigned int cost1 = 0;
+
+ vp8_clear_system_state();
+
+ i = 1;
+
+ if (mvc_flag[0])
+ {
+ mvcost [0] [0] = cost_mvcomponent_hp(0, &mvc[0]);
+
+ do
+ {
+ //mvcost [0] [i] = cost_mvcomponent( i, &mvc[0]);
+ cost0 = cost_mvcomponent_hp(i, &mvc[0]);
+
+ mvcost [0] [i] = cost0 + vp8_cost_zero(mvc[0].prob[MVPsign_hp]);
+ mvcost [0] [-i] = cost0 + vp8_cost_one(mvc[0].prob[MVPsign_hp]);
+ }
+ while (++i <= mv_max_hp);
+ }
+
+ i = 1;
+
+ if (mvc_flag[1])
+ {
+ mvcost [1] [0] = cost_mvcomponent_hp(0, &mvc[1]);
+
+ do
+ {
+ //mvcost [1] [i] = cost_mvcomponent( i, mvc[1]);
+ cost1 = cost_mvcomponent_hp(i, &mvc[1]);
+
+ mvcost [1] [i] = cost1 + vp8_cost_zero(mvc[1].prob[MVPsign_hp]);
+ mvcost [1] [-i] = cost1 + vp8_cost_one(mvc[1].prob[MVPsign_hp]);
+ }
+ while (++i <= mv_max_hp);
+ }
+}
+
+
+static void write_component_probs_hp(
+ vp8_writer *const w,
+ struct mv_context_hp *cur_mvc,
+ const struct mv_context_hp *default_mvc_,
+ const struct mv_context_hp *update_mvc,
+ const unsigned int events [MVvals_hp],
+ unsigned int rc,
+ int *updated
+)
+{
+ vp8_prob *Pcur = cur_mvc->prob;
+ const vp8_prob *default_mvc = default_mvc_->prob;
+ const vp8_prob *Pupdate = update_mvc->prob;
+ unsigned int is_short_ct[2], sign_ct[2];
+
+ unsigned int bit_ct [mvlong_width_hp] [2];
+
+ unsigned int short_ct [mvnum_short_hp];
+ unsigned int short_bct [mvnum_short_hp-1] [2];
+
+ vp8_prob Pnew [MVPcount_hp];
+
+ (void) rc;
+ vp8_copy_array(Pnew, default_mvc, MVPcount_hp);
+
+ vp8_zero(is_short_ct)
+ vp8_zero(sign_ct)
+ vp8_zero(bit_ct)
+ vp8_zero(short_ct)
+ vp8_zero(short_bct)
+
+
+ //j=0
+ {
+ const int c = events [mv_max_hp];
+
+ is_short_ct [0] += c; // Short vector
+ short_ct [0] += c; // Magnitude distribution
+ }
+
+ //j: 1 ~ mv_max (1023)
+ {
+ int j = 1;
+
+ do
+ {
+ const int c1 = events [mv_max_hp + j]; //positive
+ const int c2 = events [mv_max_hp - j]; //negative
+ const int c = c1 + c2;
+ int a = j;
+
+ sign_ct [0] += c1;
+ sign_ct [1] += c2;
+
+ if (a < mvnum_short_hp)
+ {
+ is_short_ct [0] += c; // Short vector
+ short_ct [a] += c; // Magnitude distribution
+ }
+ else
+ {
+ int k = mvlong_width_hp - 1;
+ is_short_ct [1] += c; // Long vector
+
+ /* bit 3 not always encoded. */
+ do
+ bit_ct [k] [(a >> k) & 1] += c;
+
+ while (--k >= 0);
+ }
+ }
+ while (++j <= mv_max_hp);
+ }
+
+ calc_prob(Pnew + mvpis_short_hp, is_short_ct);
+
+ calc_prob(Pnew + MVPsign_hp, sign_ct);
+
+ {
+ vp8_prob p [mvnum_short_hp - 1]; /* actually only need branch ct */
+ int j = 0;
+
+ vp8_tree_probs_from_distribution(
+ mvnum_short_hp, vp8_small_mvencodings_hp, vp8_small_mvtree_hp,
+ p, short_bct, short_ct,
+ 256, 1
+ );
+
+ do
+ calc_prob(Pnew + MVPshort_hp + j, short_bct[j]);
+
+ while (++j < mvnum_short_hp - 1);
+ }
+
+ {
+ int j = 0;
+
+ do
+ calc_prob(Pnew + MVPbits_hp + j, bit_ct[j]);
+
+ while (++j < mvlong_width_hp);
+ }
+
+ update(w, is_short_ct, Pcur + mvpis_short_hp, Pnew[mvpis_short_hp],
+ *Pupdate++, updated);
+
+ update(w, sign_ct, Pcur + MVPsign_hp, Pnew[MVPsign_hp], *Pupdate++,
+ updated);
+
+ {
+ const vp8_prob *const new_p = Pnew + MVPshort_hp;
+ vp8_prob *const cur_p = Pcur + MVPshort_hp;
+
+ int j = 0;
+
+ do
+
+ update(w, short_bct[j], cur_p + j, new_p[j], *Pupdate++, updated);
+
+ while (++j < mvnum_short_hp - 1);
+ }
+
+ {
+ const vp8_prob *const new_p = Pnew + MVPbits_hp;
+ vp8_prob *const cur_p = Pcur + MVPbits_hp;
+
+ int j = 0;
+
+ do
+
+ update(w, bit_ct[j], cur_p + j, new_p[j], *Pupdate++, updated);
+
+ while (++j < mvlong_width_hp);
+ }
+}
+
+void vp8_write_mvprobs_hp(VP8_COMP *cpi)
+{
+ vp8_writer *const w = & cpi->bc;
+ MV_CONTEXT_HP *mvc = cpi->common.fc.mvc_hp;
+ int flags[2] = {0, 0};
+#ifdef ENTROPY_STATS
+ active_section = 4;
+#endif
+ write_component_probs_hp(
+ w, &mvc[0], &vp8_default_mv_context_hp[0], &vp8_mv_update_probs_hp[0],
+ cpi->MVcount_hp[0], 0, &flags[0]
+ );
+ write_component_probs_hp(
+ w, &mvc[1], &vp8_default_mv_context_hp[1], &vp8_mv_update_probs_hp[1],
+ cpi->MVcount_hp[1], 1, &flags[1]
+ );
+
+ if (flags[0] || flags[1])
+ vp8_build_component_cost_table_hp(cpi->mb.mvcost_hp,
+ (const MV_CONTEXT_HP *)
+ cpi->common.fc.mvc_hp, flags);
+
+#ifdef ENTROPY_STATS
+ active_section = 5;
+#endif
+}
+#endif /* CONFIG_HIGH_PRECISION_MV */
diff --git a/vp8/encoder/encodemv.h b/vp8/encoder/encodemv.h
index a6116c133..09b0935cb 100644
--- a/vp8/encoder/encodemv.h
+++ b/vp8/encoder/encodemv.h
@@ -17,5 +17,10 @@
void vp8_write_mvprobs(VP8_COMP *);
void vp8_encode_motion_vector(vp8_writer *, const MV *, const MV_CONTEXT *);
void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc, int mvc_flag[2]);
+#if CONFIG_HIGH_PRECISION_MV
+void vp8_write_mvprobs_hp(VP8_COMP *);
+void vp8_encode_motion_vector_hp(vp8_writer *, const MV *, const MV_CONTEXT_HP *);
+void vp8_build_component_cost_table_hp(int *mvcost[2], const MV_CONTEXT_HP *mvc, int mvc_flag[2]);
+#endif /* CONFIG_HIGH_PRECISION_MV */
#endif
diff --git a/vp8/encoder/ethreading.c b/vp8/encoder/ethreading.c
deleted file mode 100644
index c4e12ff02..000000000
--- a/vp8/encoder/ethreading.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * 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 "onyx_int.h"
-#include "vp8/common/threading.h"
-#include "vp8/common/common.h"
-#include "vp8/common/extend.h"
-
-#if CONFIG_MULTITHREAD
-
-extern int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
- TOKENEXTRA **t, int recon_yoffset,
- int recon_uvoffset);
-extern int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x,
- TOKENEXTRA **t);
-extern void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x);
-extern void vp8_build_block_offsets(MACROBLOCK *x);
-extern void vp8_setup_block_ptrs(MACROBLOCK *x);
-
-extern void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm);
-
-static THREAD_FUNCTION loopfilter_thread(void *p_data)
-{
- VP8_COMP *cpi = (VP8_COMP *)(((LPFTHREAD_DATA *)p_data)->ptr1);
- VP8_COMMON *cm = &cpi->common;
-
- while (1)
- {
- if (cpi->b_multi_threaded == 0)
- break;
-
- if (sem_wait(&cpi->h_event_start_lpf) == 0)
- {
- if (cpi->b_multi_threaded == FALSE) // we're shutting down
- break;
-
- loopfilter_frame(cpi, cm);
-
- sem_post(&cpi->h_event_end_lpf);
- }
- }
-
- return 0;
-}
-
-static
-THREAD_FUNCTION thread_encoding_proc(void *p_data)
-{
- int ithread = ((ENCODETHREAD_DATA *)p_data)->ithread;
- VP8_COMP *cpi = (VP8_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr1);
- MB_ROW_COMP *mbri = (MB_ROW_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr2);
- ENTROPY_CONTEXT_PLANES mb_row_left_context;
-
- const int nsync = cpi->mt_sync_range;
- //printf("Started thread %d\n", ithread);
-
- while (1)
- {
- if (cpi->b_multi_threaded == 0)
- break;
-
- //if(WaitForSingleObject(cpi->h_event_mbrencoding[ithread], INFINITE) == WAIT_OBJECT_0)
- if (sem_wait(&cpi->h_event_start_encoding[ithread]) == 0)
- {
- VP8_COMMON *cm = &cpi->common;
- int mb_row;
- MACROBLOCK *x = &mbri->mb;
- MACROBLOCKD *xd = &x->e_mbd;
- TOKENEXTRA *tp ;
-
- int *segment_counts = mbri->segment_counts;
- int *totalrate = &mbri->totalrate;
-
- if (cpi->b_multi_threaded == FALSE) // we're shutting down
- break;
-
- for (mb_row = ithread + 1; mb_row < cm->mb_rows; mb_row += (cpi->encoding_thread_count + 1))
- {
-
- int i;
- int recon_yoffset, recon_uvoffset;
- int mb_col;
- int ref_fb_idx = cm->lst_fb_idx;
- int dst_fb_idx = cm->new_fb_idx;
- int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
- int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
- int map_index = (mb_row * cm->mb_cols);
- volatile int *last_row_current_mb_col;
-
- tp = cpi->tok + (mb_row * (cm->mb_cols * 16 * 24));
-
- last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1];
-
- // reset above block coeffs
- xd->above_context = cm->above_context;
- xd->left_context = &mb_row_left_context;
-
- vp8_zero(mb_row_left_context);
-
- xd->up_available = (mb_row != 0);
- recon_yoffset = (mb_row * recon_y_stride * 16);
- recon_uvoffset = (mb_row * recon_uv_stride * 8);
-
- cpi->tplist[mb_row].start = tp;
-
- //printf("Thread mb_row = %d\n", mb_row);
-
- // Set the mb activity pointer to the start of the row.
- x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
-
- // for each macroblock col in image
- for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
- {
- if ((mb_col & (nsync - 1)) == 0)
- {
- while (mb_col > (*last_row_current_mb_col - nsync) && *last_row_current_mb_col != cm->mb_cols - 1)
- {
- x86_pause_hint();
- thread_sleep(0);
- }
- }
-
- // Distance of Mb to the various image edges.
- // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
- xd->mb_to_left_edge = -((mb_col * 16) << 3);
- xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
- xd->mb_to_top_edge = -((mb_row * 16) << 3);
- xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
-
- // Set up limit values for motion vectors used to prevent them extending outside the UMV borders
- x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
- x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
- x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
- x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
-
- xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
- xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
- xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
- xd->left_available = (mb_col != 0);
-
- x->rddiv = cpi->RDDIV;
- x->rdmult = cpi->RDMULT;
-
- //Copy current mb to a buffer
- RECON_INVOKE(&xd->rtcd->recon, copy16x16)(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
-
- if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
- vp8_activity_masking(cpi, x);
-
- // Is segmentation enabled
- // MB level adjutment to quantizer
- if (xd->segmentation_enabled)
- {
- // Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
- if (cpi->segmentation_map[map_index + mb_col] <= 3)
- xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[map_index + mb_col];
- else
- xd->mode_info_context->mbmi.segment_id = 0;
-
- vp8cx_mb_init_quantizer(cpi, x);
- }
- else
- xd->mode_info_context->mbmi.segment_id = 0; // Set to Segment 0 by default
-
- x->active_ptr = cpi->active_map + map_index + mb_col;
-
- if (cm->frame_type == KEY_FRAME)
- {
- *totalrate += vp8cx_encode_intra_macro_block(cpi, x, &tp);
-#ifdef MODE_STATS
- y_modes[xd->mbmi.mode] ++;
-#endif
- }
- else
- {
- *totalrate += vp8cx_encode_inter_macroblock(cpi, x, &tp, recon_yoffset, recon_uvoffset);
-
-#ifdef MODE_STATS
- inter_y_modes[xd->mbmi.mode] ++;
-
- if (xd->mbmi.mode == SPLITMV)
- {
- int b;
-
- for (b = 0; b < xd->mbmi.partition_count; b++)
- {
- inter_b_modes[x->partition->bmi[b].mode] ++;
- }
- }
-
-#endif
-
- // Count of last ref frame 0,0 useage
- if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
- cpi->inter_zz_count++;
-
- // Special case code for cyclic refresh
- // If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
- // during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
- if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
- {
- const MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
- cpi->segmentation_map[map_index + mb_col] = mbmi->segment_id;
-
- // If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
- // Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
- // else mark it as dirty (1).
- if (mbmi->segment_id)
- cpi->cyclic_refresh_map[map_index + mb_col] = -1;
- else if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME))
- {
- if (cpi->cyclic_refresh_map[map_index + mb_col] == 1)
- cpi->cyclic_refresh_map[map_index + mb_col] = 0;
- }
- else
- cpi->cyclic_refresh_map[map_index + mb_col] = 1;
-
- }
- }
- cpi->tplist[mb_row].stop = tp;
-
- // Increment pointer into gf useage flags structure.
- x->gf_active_ptr++;
-
- // Increment the activity mask pointers.
- x->mb_activity_ptr++;
-
- // adjust to the next column of macroblocks
- x->src.y_buffer += 16;
- x->src.u_buffer += 8;
- x->src.v_buffer += 8;
-
- recon_yoffset += 16;
- recon_uvoffset += 8;
-
- // Keep track of segment useage
- segment_counts[xd->mode_info_context->mbmi.segment_id]++;
-
- // skip to next mb
- xd->mode_info_context++;
- x->partition_info++;
- xd->above_context++;
-
- cpi->mt_current_mb_col[mb_row] = mb_col;
- }
-
- //extend the recon for intra prediction
- vp8_extend_mb_row(
- &cm->yv12_fb[dst_fb_idx],
- xd->dst.y_buffer + 16,
- xd->dst.u_buffer + 8,
- xd->dst.v_buffer + 8);
-
- // this is to account for the border
- xd->mode_info_context++;
- x->partition_info++;
-
- x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
- x->src.u_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
- x->src.v_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
-
- xd->mode_info_context += xd->mode_info_stride * cpi->encoding_thread_count;
- x->partition_info += xd->mode_info_stride * cpi->encoding_thread_count;
- x->gf_active_ptr += cm->mb_cols * cpi->encoding_thread_count;
-
- if (mb_row == cm->mb_rows - 1)
- {
- //SetEvent(cpi->h_event_main);
- sem_post(&cpi->h_event_end_encoding); /* signal frame encoding end */
- }
- }
- }
- }
-
- //printf("exit thread %d\n", ithread);
- return 0;
-}
-
-static void setup_mbby_copy(MACROBLOCK *mbdst, MACROBLOCK *mbsrc)
-{
-
- MACROBLOCK *x = mbsrc;
- MACROBLOCK *z = mbdst;
- int i;
-
- z->ss = x->ss;
- z->ss_count = x->ss_count;
- z->searches_per_step = x->searches_per_step;
- z->errorperbit = x->errorperbit;
-
- z->sadperbit16 = x->sadperbit16;
- z->sadperbit4 = x->sadperbit4;
-
- /*
- z->mv_col_min = x->mv_col_min;
- z->mv_col_max = x->mv_col_max;
- z->mv_row_min = x->mv_row_min;
- z->mv_row_max = x->mv_row_max;
- z->vector_range = x->vector_range ;
- */
-
- z->vp8_short_fdct4x4 = x->vp8_short_fdct4x4;
- z->vp8_short_fdct8x4 = x->vp8_short_fdct8x4;
- z->short_walsh4x4 = x->short_walsh4x4;
- z->quantize_b = x->quantize_b;
- z->quantize_b_pair = x->quantize_b_pair;
- z->optimize = x->optimize;
-
- /*
- z->mvc = x->mvc;
- z->src.y_buffer = x->src.y_buffer;
- z->src.u_buffer = x->src.u_buffer;
- z->src.v_buffer = x->src.v_buffer;
- */
-
-
- vpx_memcpy(z->mvcosts, x->mvcosts, sizeof(x->mvcosts));
- z->mvcost[0] = &z->mvcosts[0][mv_max+1];
- z->mvcost[1] = &z->mvcosts[1][mv_max+1];
- z->mvsadcost[0] = &z->mvsadcosts[0][mvfp_max+1];
- z->mvsadcost[1] = &z->mvsadcosts[1][mvfp_max+1];
-
-
- vpx_memcpy(z->token_costs, x->token_costs, sizeof(x->token_costs));
- vpx_memcpy(z->inter_bmode_costs, x->inter_bmode_costs, sizeof(x->inter_bmode_costs));
- //memcpy(z->mvcosts, x->mvcosts, sizeof(x->mvcosts));
- //memcpy(z->mvcost, x->mvcost, sizeof(x->mvcost));
- vpx_memcpy(z->mbmode_cost, x->mbmode_cost, sizeof(x->mbmode_cost));
- vpx_memcpy(z->intra_uv_mode_cost, x->intra_uv_mode_cost, sizeof(x->intra_uv_mode_cost));
- vpx_memcpy(z->bmode_costs, x->bmode_costs, sizeof(x->bmode_costs));
-
- for (i = 0; i < 25; i++)
- {
- z->block[i].quant = x->block[i].quant;
- z->block[i].quant_fast = x->block[i].quant_fast;
- z->block[i].quant_shift = x->block[i].quant_shift;
- z->block[i].zbin = x->block[i].zbin;
- z->block[i].zrun_zbin_boost = x->block[i].zrun_zbin_boost;
- z->block[i].round = x->block[i].round;
- /*
- z->block[i].src = x->block[i].src;
- */
- z->block[i].src_stride = x->block[i].src_stride;
- z->block[i].force_empty = x->block[i].force_empty;
-
- }
-
- {
- MACROBLOCKD *xd = &x->e_mbd;
- MACROBLOCKD *zd = &z->e_mbd;
-
- /*
- zd->mode_info_context = xd->mode_info_context;
- zd->mode_info = xd->mode_info;
-
- zd->mode_info_stride = xd->mode_info_stride;
- zd->frame_type = xd->frame_type;
- zd->up_available = xd->up_available ;
- zd->left_available = xd->left_available;
- zd->left_context = xd->left_context;
- zd->last_frame_dc = xd->last_frame_dc;
- zd->last_frame_dccons = xd->last_frame_dccons;
- zd->gold_frame_dc = xd->gold_frame_dc;
- zd->gold_frame_dccons = xd->gold_frame_dccons;
- zd->mb_to_left_edge = xd->mb_to_left_edge;
- zd->mb_to_right_edge = xd->mb_to_right_edge;
- zd->mb_to_top_edge = xd->mb_to_top_edge ;
- zd->mb_to_bottom_edge = xd->mb_to_bottom_edge;
- zd->gf_active_ptr = xd->gf_active_ptr;
- zd->frames_since_golden = xd->frames_since_golden;
- zd->frames_till_alt_ref_frame = xd->frames_till_alt_ref_frame;
- */
- zd->subpixel_predict = xd->subpixel_predict;
- zd->subpixel_predict8x4 = xd->subpixel_predict8x4;
- zd->subpixel_predict8x8 = xd->subpixel_predict8x8;
- zd->subpixel_predict16x16 = xd->subpixel_predict16x16;
- zd->segmentation_enabled = xd->segmentation_enabled;
- zd->mb_segement_abs_delta = xd->mb_segement_abs_delta;
- vpx_memcpy(zd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data));
-
- for (i = 0; i < 25; i++)
- {
- zd->block[i].dequant = xd->block[i].dequant;
- }
- }
-}
-
-void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
- MACROBLOCK *x,
- MB_ROW_COMP *mbr_ei,
- int mb_row,
- int count
- )
-{
-
- VP8_COMMON *const cm = & cpi->common;
- MACROBLOCKD *const xd = & x->e_mbd;
- int i;
- (void) mb_row;
-
- for (i = 0; i < count; i++)
- {
- MACROBLOCK *mb = & mbr_ei[i].mb;
- MACROBLOCKD *mbd = &mb->e_mbd;
-
- mbd->subpixel_predict = xd->subpixel_predict;
- mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;
- mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;
- mbd->subpixel_predict16x16 = xd->subpixel_predict16x16;
-#if CONFIG_RUNTIME_CPU_DETECT
- mbd->rtcd = xd->rtcd;
-#endif
- mb->gf_active_ptr = x->gf_active_ptr;
-
- mb->vector_range = 32;
-
- vpx_memset(mbr_ei[i].segment_counts, 0, sizeof(mbr_ei[i].segment_counts));
- mbr_ei[i].totalrate = 0;
-
- mb->partition_info = x->pi + x->e_mbd.mode_info_stride * (i + 1);
-
- mbd->mode_info_context = cm->mi + x->e_mbd.mode_info_stride * (i + 1);
- mbd->mode_info_stride = cm->mode_info_stride;
-
- mbd->frame_type = cm->frame_type;
-
- mbd->frames_since_golden = cm->frames_since_golden;
- mbd->frames_till_alt_ref_frame = cm->frames_till_alt_ref_frame;
-
- mb->src = * cpi->Source;
- mbd->pre = cm->yv12_fb[cm->lst_fb_idx];
- mbd->dst = cm->yv12_fb[cm->new_fb_idx];
-
- mb->src.y_buffer += 16 * x->src.y_stride * (i + 1);
- mb->src.u_buffer += 8 * x->src.uv_stride * (i + 1);
- mb->src.v_buffer += 8 * x->src.uv_stride * (i + 1);
-
- vp8_build_block_offsets(mb);
-
- vp8_setup_block_dptrs(mbd);
-
- vp8_setup_block_ptrs(mb);
-
- mbd->left_context = &cm->left_context;
- mb->mvc = cm->fc.mvc;
-
- setup_mbby_copy(&mbr_ei[i].mb, x);
-
- mbd->fullpixel_mask = 0xffffffff;
- if(cm->full_pixel)
- mbd->fullpixel_mask = 0xfffffff8;
- }
-}
-
-void vp8cx_create_encoder_threads(VP8_COMP *cpi)
-{
- const VP8_COMMON * cm = &cpi->common;
-
- cpi->b_multi_threaded = 0;
- cpi->encoding_thread_count = 0;
-
- if (cm->processor_core_count > 1 && cpi->oxcf.multi_threaded > 1)
- {
- int ithread;
- int th_count = cpi->oxcf.multi_threaded - 1;
-
- /* don't allocate more threads than cores available */
- if (cpi->oxcf.multi_threaded > cm->processor_core_count)
- th_count = cm->processor_core_count - 1;
-
- /* we have th_count + 1 (main) threads processing one row each */
- /* no point to have more threads than the sync range allows */
- if(th_count > ((cm->mb_cols / cpi->mt_sync_range) - 1))
- {
- th_count = (cm->mb_cols / cpi->mt_sync_range) - 1;
- }
-
- if(th_count == 0)
- return;
-
- CHECK_MEM_ERROR(cpi->h_encoding_thread, vpx_malloc(sizeof(pthread_t) * th_count));
- CHECK_MEM_ERROR(cpi->h_event_start_encoding, vpx_malloc(sizeof(sem_t) * th_count));
- CHECK_MEM_ERROR(cpi->mb_row_ei, vpx_memalign(32, sizeof(MB_ROW_COMP) * th_count));
- vpx_memset(cpi->mb_row_ei, 0, sizeof(MB_ROW_COMP) * th_count);
- CHECK_MEM_ERROR(cpi->en_thread_data,
- vpx_malloc(sizeof(ENCODETHREAD_DATA) * th_count));
- CHECK_MEM_ERROR(cpi->mt_current_mb_col,
- vpx_malloc(sizeof(*cpi->mt_current_mb_col) * cm->mb_rows));
-
- sem_init(&cpi->h_event_end_encoding, 0, 0);
-
- cpi->b_multi_threaded = 1;
- cpi->encoding_thread_count = th_count;
-
- /*
- printf("[VP8:] multi_threaded encoding is enabled with %d threads\n\n",
- (cpi->encoding_thread_count +1));
- */
-
- for (ithread = 0; ithread < th_count; ithread++)
- {
- ENCODETHREAD_DATA * ethd = &cpi->en_thread_data[ithread];
-
- sem_init(&cpi->h_event_start_encoding[ithread], 0, 0);
- ethd->ithread = ithread;
- ethd->ptr1 = (void *)cpi;
- ethd->ptr2 = (void *)&cpi->mb_row_ei[ithread];
-
- pthread_create(&cpi->h_encoding_thread[ithread], 0, thread_encoding_proc, ethd);
- }
-
- {
- LPFTHREAD_DATA * lpfthd = &cpi->lpf_thread_data;
-
- sem_init(&cpi->h_event_start_lpf, 0, 0);
- sem_init(&cpi->h_event_end_lpf, 0, 0);
-
- lpfthd->ptr1 = (void *)cpi;
- pthread_create(&cpi->h_filter_thread, 0, loopfilter_thread, lpfthd);
- }
- }
-
-}
-
-void vp8cx_remove_encoder_threads(VP8_COMP *cpi)
-{
- if (cpi->b_multi_threaded)
- {
- //shutdown other threads
- cpi->b_multi_threaded = 0;
- {
- int i;
-
- for (i = 0; i < cpi->encoding_thread_count; i++)
- {
- //SetEvent(cpi->h_event_mbrencoding[i]);
- sem_post(&cpi->h_event_start_encoding[i]);
- pthread_join(cpi->h_encoding_thread[i], 0);
-
- sem_destroy(&cpi->h_event_start_encoding[i]);
- }
-
- sem_post(&cpi->h_event_start_lpf);
- pthread_join(cpi->h_filter_thread, 0);
- }
-
- sem_destroy(&cpi->h_event_end_encoding);
- sem_destroy(&cpi->h_event_end_lpf);
- sem_destroy(&cpi->h_event_start_lpf);
-
- //free thread related resources
- vpx_free(cpi->h_event_start_encoding);
- vpx_free(cpi->h_encoding_thread);
- vpx_free(cpi->mb_row_ei);
- vpx_free(cpi->en_thread_data);
- vpx_free(cpi->mt_current_mb_col);
- }
-}
-#endif
diff --git a/vp8/encoder/find_rotation.c b/vp8/encoder/find_rotation.c
new file mode 100644
index 000000000..742c0ba81
--- /dev/null
+++ b/vp8/encoder/find_rotation.c
@@ -0,0 +1,58 @@
+/*
+ * 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 "block.h"
+#include "variance.h"
+
+#if CONFIG_ROTATION
+
+int vp8_find_best_rotation(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *bestmv,
+ int_mv *ref_mv, int *bri, int error_per_bit,
+ const vp8_variance_fn_ptr_t *vfp, int *mvcost[2],
+ int *distortion, unsigned int *sse1)
+{
+ unsigned char *z = (*(b->base_src) + b->src);
+
+ int ri;
+
+ int y_stride;
+
+ unsigned int besterr;
+ int br = bestmv->as_mv.row;
+ int bc = bestmv->as_mv.col;
+ unsigned char *y = *(d->base_pre) + d->pre + br * d->pre_stride + bc;
+ y_stride = d->pre_stride;
+
+ // calculate central point error
+ besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);
+ *distortion = besterr;
+
+ // find the best matching rotation
+ *bri = 5;
+ for (ri = 0; ri < ROTATIONS; ri++)
+ {
+ unsigned int this_err;
+ unsigned char pb[256];
+ predict_rotated_16x16(ri, y, y_stride, pb, 16);
+ this_err = vfp->vf(pb, 16, z, b->src_stride, sse1);
+
+ if (this_err < besterr)
+ {
+ *bri = ri;
+ besterr = this_err;
+ }
+ }
+ *sse1 = besterr;
+ *distortion = besterr;
+
+ return 0;
+}
+
+#endif
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index f2a1cd2d6..d63a1f923 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -26,6 +26,7 @@
#include "vp8/common/swapyv12buffer.h"
#include <stdio.h>
#include "rdopt.h"
+#include "ratectrl.h"
#include "vp8/common/quant_common.h"
#include "encodemv.h"
@@ -37,19 +38,18 @@
#define IF_RTCD(x) NULL
#endif
+#if CONFIG_HIGH_PRECISION_MV
+#define XMVCOST (x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost)
+#else
+#define XMVCOST (x->mvcost)
+#endif
+
extern void vp8_build_block_offsets(MACROBLOCK *x);
extern void vp8_setup_block_ptrs(MACROBLOCK *x);
extern void vp8cx_frame_init_quantizer(VP8_COMP *cpi);
extern void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv);
extern void vp8_alloc_compressor_data(VP8_COMP *cpi);
-//#define GFQ_ADJUSTMENT (40 + ((15*Q)/10))
-//#define GFQ_ADJUSTMENT (80 + ((15*Q)/10))
-#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
-extern int vp8_kf_boost_qadjustment[QINDEX_RANGE];
-
-extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE];
-
#define IIFACTOR 1.5
#define IIKFACTOR1 1.40
#define IIKFACTOR2 1.5
@@ -69,20 +69,27 @@ extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE];
static int vscale_lookup[7] = {0, 1, 1, 2, 2, 3, 3};
static int hscale_lookup[7] = {0, 0, 1, 1, 2, 2, 3};
+static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame);
-static const int cq_level[QINDEX_RANGE] =
+static int select_cq_level( int qindex )
{
- 0,0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,
- 9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,20,
- 20,21,22,22,23,24,24,25,26,27,27,28,29,30,30,31,
- 32,33,33,34,35,36,36,37,38,39,39,40,41,42,42,43,
- 44,45,46,46,47,48,49,50,50,51,52,53,54,55,55,56,
- 57,58,59,60,60,61,62,63,64,65,66,67,67,68,69,70,
- 71,72,73,74,75,75,76,77,78,79,80,81,82,83,84,85,
- 86,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
-};
+ int ret_val = QINDEX_RANGE - 1;
+ int i;
+
+ double target_q = ( vp8_convert_qindex_to_q( qindex ) * 0.5847 ) + 1.0;
+
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ if ( target_q <= vp8_convert_qindex_to_q( i ) )
+ {
+ ret_val = i;
+ break;
+ }
+ }
+
+ return ret_val;
+}
-static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame);
// Resets the first pass file to the given position using a relative seek from the current position
static void reset_fpf_position(VP8_COMP *cpi, FIRSTPASS_STATS *Position)
@@ -152,7 +159,7 @@ static void output_stats(const VP8_COMP *cpi,
fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f"
" %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f"
- " %12.0f %12.4f\n",
+ " %12.0f %12.0f %12.4f\n",
stats->frame,
stats->intra_error,
stats->coded_error,
@@ -168,6 +175,7 @@ static void output_stats(const VP8_COMP *cpi,
stats->MVrv,
stats->MVcv,
stats->mv_in_out_count,
+ stats->new_mv_count,
stats->count,
stats->duration);
fclose(fpfile);
@@ -192,6 +200,7 @@ static void zero_stats(FIRSTPASS_STATS *section)
section->MVrv = 0.0;
section->MVcv = 0.0;
section->mv_in_out_count = 0.0;
+ section->new_mv_count = 0.0;
section->count = 0.0;
section->duration = 1.0;
}
@@ -213,10 +222,33 @@ static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
section->MVrv += frame->MVrv;
section->MVcv += frame->MVcv;
section->mv_in_out_count += frame->mv_in_out_count;
+ section->new_mv_count += frame->new_mv_count;
section->count += frame->count;
section->duration += frame->duration;
}
+static void subtract_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
+{
+ section->frame -= frame->frame;
+ section->intra_error -= frame->intra_error;
+ section->coded_error -= frame->coded_error;
+ section->ssim_weighted_pred_err -= frame->ssim_weighted_pred_err;
+ section->pcnt_inter -= frame->pcnt_inter;
+ section->pcnt_motion -= frame->pcnt_motion;
+ section->pcnt_second_ref -= frame->pcnt_second_ref;
+ section->pcnt_neutral -= frame->pcnt_neutral;
+ section->MVr -= frame->MVr;
+ section->mvr_abs -= frame->mvr_abs;
+ section->MVc -= frame->MVc;
+ section->mvc_abs -= frame->mvc_abs;
+ section->MVrv -= frame->MVrv;
+ section->MVcv -= frame->MVcv;
+ section->mv_in_out_count -= frame->mv_in_out_count;
+ section->new_mv_count -= frame->new_mv_count;
+ section->count -= frame->count;
+ section->duration -= frame->duration;
+}
+
static void avg_stats(FIRSTPASS_STATS *section)
{
if (section->count < 1.0)
@@ -242,49 +274,16 @@ static void avg_stats(FIRSTPASS_STATS *section)
// Calculate a modified Error used in distributing bits between easier and harder frames
static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
{
- double av_err = cpi->twopass.total_stats->ssim_weighted_pred_err;
+ double av_err = ( cpi->twopass.total_stats->ssim_weighted_pred_err /
+ cpi->twopass.total_stats->count );
double this_err = this_frame->ssim_weighted_pred_err;
double modified_err;
- //double relative_next_iiratio;
- //double next_iiratio;
- //double sum_iiratio;
- //int i;
-
- //FIRSTPASS_STATS next_frame;
- //FIRSTPASS_STATS *start_pos;
-
- /*start_pos = cpi->twopass.stats_in;
- sum_iiratio = 0.0;
- i = 0;
- while ( (i < 1) && input_stats(cpi,&next_frame) != EOF )
- {
-
- next_iiratio = next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error);
- next_iiratio = ( next_iiratio < 1.0 ) ? 1.0 : (next_iiratio > 20.0) ? 20.0 : next_iiratio;
- sum_iiratio += next_iiratio;
- i++;
- }
- if ( i > 0 )
- {
- relative_next_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK(cpi->twopass.avg_iiratio * (double)i);
- }
- else
- {
- relative_next_iiratio = 1.0;
- }
- reset_fpf_position(cpi, start_pos);*/
-
if (this_err > av_err)
modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW1);
else
modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW2);
- /*
- relative_next_iiratio = pow(relative_next_iiratio,0.25);
- modified_err = modified_err * relative_next_iiratio;
- */
-
return modified_err;
}
@@ -356,33 +355,8 @@ static int frame_max_bits(VP8_COMP *cpi)
// Max allocation for a single frame based on the max section guidelines passed in and how many bits are left
int max_bits;
- // For CBR we need to also consider buffer fullness.
- // If we are running below the optimal level then we need to gradually tighten up on max_bits.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- double buffer_fullness_ratio = (double)cpi->buffer_level / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.optimal_buffer_level);
-
- // For CBR base this on the target average bits per frame plus the maximum sedction rate passed in by the user
- max_bits = (int)(cpi->av_per_frame_bandwidth * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
-
- // If our buffer is below the optimum level
- if (buffer_fullness_ratio < 1.0)
- {
- // The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4.
- int min_max_bits = ((cpi->av_per_frame_bandwidth >> 2) < (max_bits >> 2)) ? cpi->av_per_frame_bandwidth >> 2 : max_bits >> 2;
-
- max_bits = (int)(max_bits * buffer_fullness_ratio);
-
- if (max_bits < min_max_bits)
- max_bits = min_max_bits; // Lowest value we will set ... which should allow the buffer to refil.
- }
- }
- // VBR
- else
- {
- // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
- max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
- }
+ // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
+ max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
// Trap case where we are out of bits
if (max_bits < 0)
@@ -452,7 +426,7 @@ static void first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x,
ref_mv_full.as_mv.row = ref_mv->as_mv.row>>3;
tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv, step_param,
x->sadperbit16, &num00, &v_fn_ptr,
- x->mvcost, ref_mv);
+ XMVCOST, ref_mv);
if ( tmp_err < INT_MAX-new_mv_mode_penalty )
tmp_err += new_mv_mode_penalty;
@@ -477,8 +451,8 @@ static void first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x,
{
tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv,
step_param + n, x->sadperbit16,
- &num00, &v_fn_ptr, x->mvcost,
- ref_mv);
+ &num00, &v_fn_ptr,
+ XMVCOST, ref_mv);
if ( tmp_err < INT_MAX-new_mv_mode_penalty )
tmp_err += new_mv_mode_penalty;
@@ -516,8 +490,9 @@ void vp8_first_pass(VP8_COMP *cpi)
int second_ref_count = 0;
int intrapenalty = 256;
int neutral_count = 0;
-
+ int new_mv_count = 0;
int sum_in_vectors = 0;
+ uint32_t lastmv_as_int = 0;
int_mv zero_ref_mv;
@@ -548,9 +523,13 @@ void vp8_first_pass(VP8_COMP *cpi)
//if ( 0 )
{
int flag[2] = {1, 1};
- vp8_initialize_rd_consts(cpi, cm->base_qindex+cm->y1dc_delta_q);
+ vp8_initialize_rd_consts(cpi, cm->base_qindex + cm->y1dc_delta_q);
vpx_memcpy(cm->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cm->fc.mvc, flag);
+#if CONFIG_HIGH_PRECISION_MV
+ vpx_memcpy(cm->fc.mvc_hp, vp8_default_mv_context_hp, sizeof(vp8_default_mv_context_hp));
+ vp8_build_component_cost_table_hp(cpi->mb.mvcost_hp, (const MV_CONTEXT_HP *) cm->fc.mvc_hp, flag);
+#endif
}
// for each macroblock row in image
@@ -697,6 +676,11 @@ void vp8_first_pass(VP8_COMP *cpi)
{
mvcount++;
+ // Was it different from the last non zero vector
+ if ( d->bmi.mv.as_int != lastmv_as_int )
+ new_mv_count++;
+ lastmv_as_int = d->bmi.mv.as_int;
+
// Does the Row vector point inwards or outwards
if (mb_row < cm->mb_rows / 2)
{
@@ -794,6 +778,7 @@ void vp8_first_pass(VP8_COMP *cpi)
fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / (double)mvcount)) / (double)mvcount;
fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / (double)mvcount)) / (double)mvcount;
fps.mv_in_out_count = (double)sum_in_vectors / (double)(mvcount * 2);
+ fps.new_mv_count = new_mv_count;
fps.pcnt_motion = 1.0 * (double)mvcount / cpi->common.MBs;
}
@@ -849,44 +834,150 @@ void vp8_first_pass(VP8_COMP *cpi)
cm->current_video_frame++;
}
-extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
-#define BASE_ERRPERMB 150
-static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh)
+// Estimate a cost per mb attributable to overheads such as the coding of
+// modes and motion vectors.
+// Currently simplistic in its assumptions for testing.
+//
+
+
+double bitcost( double prob )
+{
+ return -(log( prob ) / log( 2.0 ));
+}
+static long long estimate_modemvcost(VP8_COMP *cpi,
+ FIRSTPASS_STATS * fpstats)
+{
+ int mv_cost;
+ int mode_cost;
+
+ double av_pct_inter = fpstats->pcnt_inter / fpstats->count;
+ double av_pct_motion = fpstats->pcnt_motion / fpstats->count;
+ double av_intra = (1.0 - av_pct_inter);
+
+ double zz_cost;
+ double motion_cost;
+ double intra_cost;
+
+ zz_cost = bitcost(av_pct_inter - av_pct_motion);
+ motion_cost = bitcost(av_pct_motion);
+ intra_cost = bitcost(av_intra);
+
+ // Estimate of extra bits per mv overhead for mbs
+ // << 9 is the normalization to the (bits * 512) used in vp8_bits_per_mb
+ mv_cost = ((int)(fpstats->new_mv_count / fpstats->count) * 8) << 9;
+
+ // Crude estimate of overhead cost from modes
+ // << 9 is the normalization to (bits * 512) used in vp8_bits_per_mb
+ mode_cost =
+ (int)( ( ((av_pct_inter - av_pct_motion) * zz_cost) +
+ (av_pct_motion * motion_cost) +
+ (av_intra * intra_cost) ) * cpi->common.MBs ) << 9;
+
+ //return mv_cost + mode_cost;
+ // TODO PGW Fix overhead costs for extended Q range
+ return 0;
+}
+
+static double calc_correction_factor( double err_per_mb,
+ double err_divisor,
+ double pt_low,
+ double pt_high,
+ int Q )
+{
+ double power_term;
+ double error_term = err_per_mb / err_divisor;
+ double correction_factor;
+
+ // Adjustment based on actual quantizer to power term.
+ power_term = (vp8_convert_qindex_to_q(Q) * 0.01) + pt_low;
+ power_term = (power_term > pt_high) ? pt_high : power_term;
+
+ // Adjustments to error term
+ // TBD
+
+ // Calculate correction factor
+ correction_factor = pow(error_term, power_term);
+
+ // Clip range
+ correction_factor =
+ (correction_factor < 0.05)
+ ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor;
+
+ return correction_factor;
+}
+
+// Given a current maxQ value sets a range for future values.
+// PGW TODO..
+// This code removes direct dependency on QIndex to determin the range
+// (now uses the actual quantizer) but has not been tuned.
+static double adjust_maxq_qrange(VP8_COMP *cpi)
+{
+ int i;
+ double q;
+
+ // Set the max corresponding to cpi->avg_q * 2.0
+ q = cpi->avg_q * 2.0;
+ cpi->twopass.maxq_max_limit = cpi->worst_quality;
+ for ( i = cpi->best_quality; i <= cpi->worst_quality; i++ )
+ {
+ cpi->twopass.maxq_max_limit = i;
+ if ( vp8_convert_qindex_to_q(i) >= q )
+ break;
+ }
+
+ // Set the min corresponding to cpi->avg_q * 0.5
+ q = cpi->avg_q * 0.5;
+ cpi->twopass.maxq_min_limit = cpi->best_quality;
+ for ( i = cpi->worst_quality; i >= cpi->best_quality; i-- )
+ {
+ cpi->twopass.maxq_min_limit = i;
+ if ( vp8_convert_qindex_to_q(i) <= q )
+ break;
+ }
+}
+#define ERR_DIVISOR 150.0
+static int estimate_max_q(VP8_COMP *cpi,
+ FIRSTPASS_STATS * fpstats,
+ int section_target_bandwitdh,
+ int overhead_bits )
{
int Q;
int num_mbs = cpi->common.MBs;
int target_norm_bits_per_mb;
+ double section_err = (fpstats->coded_error / fpstats->count);
double err_per_mb = section_err / num_mbs;
- double correction_factor;
+ double err_correction_factor;
double corr_high;
double speed_correction = 1.0;
- double pow_highq = 0.90;
- double pow_lowq = 0.40;
+ double inter_pct = (fpstats->pcnt_inter / fpstats->count);
+ double intra_pct = 1.0 - inter_pct;
+ int overhead_bits_per_mb;
if (section_target_bandwitdh <= 0)
return cpi->twopass.maxq_max_limit; // Highest value allowed
- target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
+ target_norm_bits_per_mb =
+ (section_target_bandwitdh < (1 << 20))
+ ? (512 * section_target_bandwitdh) / num_mbs
+ : 512 * (section_target_bandwitdh / num_mbs);
- // Calculate a corrective factor based on a rolling ratio of bits spent vs target bits
- if ((cpi->rolling_target_bits > 0) && (cpi->active_worst_quality < cpi->worst_quality))
+ // Calculate a corrective factor based on a rolling ratio of bits spent
+ // vs target bits
+ if ((cpi->rolling_target_bits > 0) &&
+ (cpi->active_worst_quality < cpi->worst_quality))
{
double rolling_ratio;
- rolling_ratio = (double)cpi->rolling_actual_bits / (double)cpi->rolling_target_bits;
+ rolling_ratio = (double)cpi->rolling_actual_bits /
+ (double)cpi->rolling_target_bits;
- //if ( cpi->twopass.est_max_qcorrection_factor > rolling_ratio )
if (rolling_ratio < 0.95)
- //cpi->twopass.est_max_qcorrection_factor *= adjustment_rate;
cpi->twopass.est_max_qcorrection_factor -= 0.005;
- //else if ( cpi->twopass.est_max_qcorrection_factor < rolling_ratio )
else if (rolling_ratio > 1.05)
cpi->twopass.est_max_qcorrection_factor += 0.005;
- //cpi->twopass.est_max_qcorrection_factor /= adjustment_rate;
-
cpi->twopass.est_max_qcorrection_factor =
(cpi->twopass.est_max_qcorrection_factor < 0.1)
? 0.1
@@ -894,8 +985,9 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_
? 10.0 : cpi->twopass.est_max_qcorrection_factor;
}
- // Corrections for higher compression speed settings (reduced compression expected)
- if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+ // Corrections for higher compression speed settings
+ // (reduced compression expected)
+ if (cpi->compressor_speed == 1)
{
if (cpi->oxcf.cpu_used <= 5)
speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
@@ -903,10 +995,12 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_
speed_correction = 1.25;
}
- // Correction factor used for Q values >= 20
- corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
- corr_high = (corr_high < 0.05)
- ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
+ // Estimate of overhead bits per mb
+ // Correction to overhead bits for min allowed Q.
+ // PGW TODO.. This code is broken for the extended Q range
+ // for now overhead set to 0.
+ overhead_bits_per_mb = overhead_bits / num_mbs;
+ overhead_bits_per_mb *= pow( 0.98, (double)cpi->twopass.maxq_min_limit );
// Try and pick a max Q that will be high enough to encode the
// content at the given rate.
@@ -914,18 +1008,24 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_
{
int bits_per_mb_at_this_q;
- if (Q < 50)
- {
- correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
- correction_factor = (correction_factor < 0.05) ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor;
- }
- else
- correction_factor = corr_high;
+ // Error per MB based correction factor
+ err_correction_factor =
+ calc_correction_factor(err_per_mb, ERR_DIVISOR, 0.36, 0.90, Q);
+
+ bits_per_mb_at_this_q =
+ vp8_bits_per_mb(INTER_FRAME, Q) + overhead_bits_per_mb;
- bits_per_mb_at_this_q = (int)(.5 + correction_factor
+ bits_per_mb_at_this_q = (int)(.5 + err_correction_factor
* speed_correction * cpi->twopass.est_max_qcorrection_factor
* cpi->twopass.section_max_qfactor
- * (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
+ * (double)bits_per_mb_at_this_q);
+
+ // Mode and motion overhead
+ // As Q rises in real encode loop rd code will force overhead down
+ // We make a crude adjustment for this here as *.98 per Q step.
+ // PGW TODO.. This code is broken for the extended Q range
+ // for now overhead set to 0.
+ overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98);
if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
break;
@@ -934,27 +1034,116 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_
// Restriction on active max q for constrained quality mode.
if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
(Q < cpi->cq_target_quality) )
- //(Q < cpi->oxcf.cq_level;) )
{
Q = cpi->cq_target_quality;
- //Q = cpi->oxcf.cq_level;
}
// Adjust maxq_min_limit and maxq_max_limit limits based on
- // averaga q observed in clip for non kf/gf.arf frames
+ // averaga q observed in clip for non kf/gf/arf frames
// Give average a chance to settle though.
+ // PGW TODO.. This code is broken for the extended Q range
if ( (cpi->ni_frames >
((unsigned int)cpi->twopass.total_stats->count >> 8)) &&
(cpi->ni_frames > 150) )
{
- cpi->twopass.maxq_max_limit = ((cpi->ni_av_qi + 32) < cpi->worst_quality)
- ? (cpi->ni_av_qi + 32) : cpi->worst_quality;
- cpi->twopass.maxq_min_limit = ((cpi->ni_av_qi - 32) > cpi->best_quality)
- ? (cpi->ni_av_qi - 32) : cpi->best_quality;
+ adjust_maxq_qrange( cpi );
}
return Q;
}
+
+// For cq mode estimate a cq level that matches the observed
+// complexity and data rate.
+static int estimate_cq( VP8_COMP *cpi,
+ FIRSTPASS_STATS * fpstats,
+ int section_target_bandwitdh,
+ int overhead_bits )
+{
+ int Q;
+ int num_mbs = cpi->common.MBs;
+ int target_norm_bits_per_mb;
+
+ double section_err = (fpstats->coded_error / fpstats->count);
+ double err_per_mb = section_err / num_mbs;
+ double err_correction_factor;
+ double corr_high;
+ double speed_correction = 1.0;
+ double clip_iiratio;
+ double clip_iifactor;
+ double inter_pct = (fpstats->pcnt_inter / fpstats->count);
+ double intra_pct = 1.0 - inter_pct;
+ int overhead_bits_per_mb;
+
+ if (0)
+ {
+ FILE *f = fopen("epmp.stt", "a");
+ fprintf(f, "%10.2f\n", err_per_mb );
+ fclose(f);
+ }
+
+ target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20))
+ ? (512 * section_target_bandwitdh) / num_mbs
+ : 512 * (section_target_bandwitdh / num_mbs);
+
+ // Estimate of overhead bits per mb
+ overhead_bits_per_mb = overhead_bits / num_mbs;
+
+ // Corrections for higher compression speed settings
+ // (reduced compression expected)
+ if (cpi->compressor_speed == 1)
+ {
+ if (cpi->oxcf.cpu_used <= 5)
+ speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+ else
+ speed_correction = 1.25;
+ }
+
+ // II ratio correction factor for clip as a whole
+ clip_iiratio = cpi->twopass.total_stats->intra_error /
+ DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats->coded_error);
+ clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025);
+ if (clip_iifactor < 0.80)
+ clip_iifactor = 0.80;
+
+ // Try and pick a Q that can encode the content at the given rate.
+ for (Q = 0; Q < MAXQ; Q++)
+ {
+ int bits_per_mb_at_this_q;
+
+ // Error per MB based correction factor
+ err_correction_factor =
+ calc_correction_factor(err_per_mb, 100.0, 0.36, 0.90, Q);
+
+ bits_per_mb_at_this_q =
+ vp8_bits_per_mb(INTER_FRAME, Q) + overhead_bits_per_mb;
+
+ bits_per_mb_at_this_q =
+ (int)( .5 + err_correction_factor *
+ speed_correction *
+ clip_iifactor *
+ (double)bits_per_mb_at_this_q);
+
+ // Mode and motion overhead
+ // As Q rises in real encode loop rd code will force overhead down
+ // We make a crude adjustment for this here as *.98 per Q step.
+ // PGW TODO.. This code is broken for the extended Q range
+ // for now overhead set to 0.
+ overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98);
+
+ if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+ break;
+ }
+
+ // Clip value to range "best allowed to (worst allowed - 1)"
+ Q = select_cq_level( Q );
+ if ( Q >= cpi->worst_quality )
+ Q = cpi->worst_quality - 1;
+ if ( Q < cpi->best_quality )
+ Q = cpi->best_quality;
+
+ return Q;
+}
+
static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh)
{
int Q;
@@ -962,16 +1151,14 @@ static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_band
int target_norm_bits_per_mb;
double err_per_mb = section_err / num_mbs;
- double correction_factor;
+ double err_correction_factor;
double corr_high;
double speed_correction = 1.0;
- double pow_highq = 0.90;
- double pow_lowq = 0.40;
target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
// Corrections for higher compression speed settings (reduced compression expected)
- if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+ if (cpi->compressor_speed == 1)
{
if (cpi->oxcf.cpu_used <= 5)
speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
@@ -979,24 +1166,20 @@ static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_band
speed_correction = 1.25;
}
- // Correction factor used for Q values >= 20
- corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
- corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
-
// Try and pick a Q that can encode the content at the given rate.
for (Q = 0; Q < MAXQ; Q++)
{
int bits_per_mb_at_this_q;
- if (Q < 50)
- {
- correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
- correction_factor = (correction_factor < 0.05) ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor;
- }
- else
- correction_factor = corr_high;
+ // Error per MB based correction factor
+ err_correction_factor =
+ calc_correction_factor(err_per_mb, ERR_DIVISOR, 0.36, 0.90, Q);
- bits_per_mb_at_this_q = (int)(.5 + correction_factor * speed_correction * cpi->twopass.est_max_qcorrection_factor * (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
+ bits_per_mb_at_this_q =
+ (int)( .5 + ( err_correction_factor *
+ speed_correction *
+ cpi->twopass.est_max_qcorrection_factor *
+ (double)vp8_bits_per_mb(INTER_FRAME, Q) / 1.0 ) );
if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
break;
@@ -1048,7 +1231,7 @@ static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_ta
iiratio_correction_factor = 0.5;
// Corrections for higher compression speed settings (reduced compression expected)
- if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+ if (cpi->compressor_speed == 1)
{
if (cpi->oxcf.cpu_used <= 5)
speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
@@ -1059,23 +1242,17 @@ static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_ta
// Combine the various factors calculated above
combined_correction_factor = speed_correction * iiratio_correction_factor * current_spend_ratio;
- // Correction factor used for Q values >= 20
- corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
- corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
-
// Try and pick a Q that should be high enough to encode the content at the given rate.
for (Q = 0; Q < MAXQ; Q++)
{
- // Q values < 20 treated as a special case
- if (Q < 20)
- {
- err_correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
- err_correction_factor = (err_correction_factor < 0.05) ? 0.05 : (err_correction_factor > 5.0) ? 5.0 : err_correction_factor;
- }
- else
- err_correction_factor = corr_high;
+ // Error per MB based correction factor
+ err_correction_factor =
+ calc_correction_factor(err_per_mb, ERR_DIVISOR, pow_lowq, pow_highq, Q);
- bits_per_mb_at_this_q = (int)(.5 + err_correction_factor * combined_correction_factor * (double)vp8_bits_per_mb[INTER_FRAME][Q]);
+ bits_per_mb_at_this_q =
+ (int)(.5 + ( err_correction_factor *
+ combined_correction_factor *
+ (double)vp8_bits_per_mb(INTER_FRAME, Q)) );
if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
break;
@@ -1102,77 +1279,6 @@ static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_ta
return Q;
}
-// For cq mode estimate a cq level that matches the observed
-// complexity and data rate.
-static int estimate_cq(VP8_COMP *cpi, double section_err, int section_target_bandwitdh)
-{
- int Q;
- int num_mbs = cpi->common.MBs;
- int target_norm_bits_per_mb;
-
- double err_per_mb = section_err / num_mbs;
- double correction_factor;
- double corr_high;
- double speed_correction = 1.0;
- double pow_highq = 0.90;
- double pow_lowq = 0.40;
- double clip_iiratio;
- double clip_iifactor;
-
- target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20))
- ? (512 * section_target_bandwitdh) / num_mbs
- : 512 * (section_target_bandwitdh / num_mbs);
-
- // Corrections for higher compression speed settings
- // (reduced compression expected)
- if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
- {
- if (cpi->oxcf.cpu_used <= 5)
- speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
- else
- speed_correction = 1.25;
- }
- // II ratio correction factor for clip as a whole
- clip_iiratio = cpi->twopass.total_stats->intra_error /
- DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats->coded_error);
- clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025);
- if (clip_iifactor < 0.80)
- clip_iifactor = 0.80;
-
- // Correction factor used for Q values >= 20
- corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
- corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
-
- // Try and pick a Q that can encode the content at the given rate.
- for (Q = 0; Q < MAXQ; Q++)
- {
- int bits_per_mb_at_this_q;
-
- if (Q < 50)
- {
- correction_factor =
- pow( err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
-
- correction_factor = (correction_factor < 0.05) ? 0.05
- : (correction_factor > 5.0) ? 5.0
- : correction_factor;
- }
- else
- correction_factor = corr_high;
-
- bits_per_mb_at_this_q =
- (int)( .5 + correction_factor *
- speed_correction *
- clip_iifactor *
- (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
-
- if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
- break;
- }
-
- return cq_level[Q];
-}
-
extern void vp8_new_frame_rate(VP8_COMP *cpi, double framerate);
void vp8_init_second_pass(VP8_COMP *cpi)
@@ -1180,22 +1286,21 @@ void vp8_init_second_pass(VP8_COMP *cpi)
FIRSTPASS_STATS this_frame;
FIRSTPASS_STATS *start_pos;
- double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+ double lower_bounds_min_rate = FRAME_OVERHEAD_BITS*cpi->oxcf.frame_rate;
+ double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
+ * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+ if (two_pass_min_rate < lower_bounds_min_rate)
+ two_pass_min_rate = lower_bounds_min_rate;
zero_stats(cpi->twopass.total_stats);
+ zero_stats(cpi->twopass.total_left_stats);
if (!cpi->twopass.stats_in_end)
return;
*cpi->twopass.total_stats = *cpi->twopass.stats_in_end;
-
- cpi->twopass.total_error_left = cpi->twopass.total_stats->ssim_weighted_pred_err;
- cpi->twopass.total_intra_error_left = cpi->twopass.total_stats->intra_error;
- cpi->twopass.total_coded_error_left = cpi->twopass.total_stats->coded_error;
- cpi->twopass.start_tot_err_left = cpi->twopass.total_error_left;
-
- //cpi->twopass.bits_left = (int64_t)(cpi->twopass.total_stats->count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate));
- //cpi->twopass.bits_left -= (int64_t)(cpi->twopass.total_stats->count * two_pass_min_rate / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate));
+ *cpi->twopass.total_left_stats = *cpi->twopass.total_stats;
// each frame can have a different duration, as the frame rate in the source
// isn't guaranteed to be constant. The frame rate prior to the first frame
@@ -1207,7 +1312,6 @@ void vp8_init_second_pass(VP8_COMP *cpi)
cpi->output_frame_rate = cpi->oxcf.frame_rate;
cpi->twopass.bits_left = (int64_t)(cpi->twopass.total_stats->duration * cpi->oxcf.target_bandwidth / 10000000.0) ;
cpi->twopass.bits_left -= (int64_t)(cpi->twopass.total_stats->duration * two_pass_min_rate / 10000000.0);
- cpi->twopass.clip_bits_total = cpi->twopass.bits_left;
// Calculate a minimum intra value to be used in determining the IIratio
// scores used in the second pass. We have this minimum to make sure
@@ -1216,8 +1320,6 @@ void vp8_init_second_pass(VP8_COMP *cpi)
cpi->twopass.kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
cpi->twopass.gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
- avg_stats(cpi->twopass.total_stats);
-
// Scan the first pass file and calculate an average Intra / Inter error score ratio for the sequence
{
double sum_iiratio = 0.0;
@@ -1716,35 +1818,6 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
cpi->twopass.gf_decay_rate =
(i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
- // When using CBR apply additional buffer related upper limits
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- double max_boost;
-
- // For cbr apply buffer related limits
- if (cpi->drop_frames_allowed)
- {
- int df_buffer_level = cpi->oxcf.drop_frames_water_mark *
- (cpi->oxcf.optimal_buffer_level / 100);
-
- if (cpi->buffer_level > df_buffer_level)
- max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
- else
- max_boost = 0.0;
- }
- else if (cpi->buffer_level > 0)
- {
- max_boost = ((double)(cpi->buffer_level * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
- }
- else
- {
- max_boost = 0.0;
- }
-
- if (boost_score > max_boost)
- boost_score = max_boost;
- }
-
// Dont allow conventional gf too near the next kf
if ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL)
{
@@ -1815,9 +1888,9 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// Boost for arf frame
#if NEW_BOOST
- Boost = (alt_boost * GFQ_ADJUSTMENT) / 100;
+ Boost = (alt_boost * vp8_gfboost_qadjust(Q)) / 100;
#else
- Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+ Boost = (cpi->gfu_boost * 3 * vp8_gfboost_qadjust(Q)) / (2 * 100);
#endif
Boost += (i * 50);
@@ -1982,9 +2055,9 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
if (cpi->source_alt_ref_pending && i == 0)
{
#if NEW_BOOST
- Boost = (alt_boost * GFQ_ADJUSTMENT) / 100;
+ Boost = (alt_boost * vp8_gfboost_qadjust(Q)) / 100;
#else
- Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+ Boost = (cpi->gfu_boost * 3 * vp8_gfboost_qadjust(Q)) / (2 * 100);
#endif
Boost += (cpi->baseline_gf_interval * 50);
@@ -2001,7 +2074,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
else
{
// boost based on inter / intra ratio of subsequent frames
- Boost = (cpi->gfu_boost * GFQ_ADJUSTMENT) / 100;
+ Boost = (cpi->gfu_boost * vp8_gfboost_qadjust(Q)) / 100;
// Set max and minimum boost and hence minimum allocation
if (Boost > (cpi->baseline_gf_interval * 150))
@@ -2063,13 +2136,6 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
}
}
- // Apply an additional limit for CBR
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- if (cpi->twopass.gf_bits > (cpi->buffer_level >> 1))
- cpi->twopass.gf_bits = cpi->buffer_level >> 1;
- }
-
// Dont allow a negative value for gf_bits
if (gf_bits < 0)
gf_bits = 0;
@@ -2224,6 +2290,46 @@ static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
cpi->per_frame_bandwidth = target_frame_size; // Per frame bit target for this frame
}
+// Make a damped adjustment to the active max q.
+int adjust_active_maxq( int old_maxqi, int new_maxqi )
+{
+ int i;
+ int ret_val = new_maxqi;
+ double old_q;
+ double new_q;
+ double target_q;
+
+ old_q = vp8_convert_qindex_to_q( old_maxqi );
+ new_q = vp8_convert_qindex_to_q( new_maxqi );
+
+ target_q = ((old_q * 7.0) + new_q) / 8.0;
+
+ if ( target_q > old_q )
+ {
+ for ( i = old_maxqi; i <= new_maxqi; i++ )
+ {
+ if ( vp8_convert_qindex_to_q( i ) >= target_q )
+ {
+ ret_val = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for ( i = old_maxqi; i >= new_maxqi; i-- )
+ {
+ if ( vp8_convert_qindex_to_q( i ) <= target_q )
+ {
+ ret_val = i;
+ break;
+ }
+ }
+ }
+
+ return ret_val;
+}
+
void vp8_second_pass(VP8_COMP *cpi)
{
int tmp_q;
@@ -2238,6 +2344,8 @@ void vp8_second_pass(VP8_COMP *cpi)
FIRSTPASS_STATS *start_pos;
+ int overhead_bits;
+
if (!cpi->twopass.stats_in)
{
return ;
@@ -2260,19 +2368,6 @@ void vp8_second_pass(VP8_COMP *cpi)
// Define next KF group and assign bits to it
vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
find_next_key_frame(cpi, &this_frame_copy);
-
- // Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
- // outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
- // This is temporary code till we decide what should really happen in this case.
- if (cpi->oxcf.error_resilient_mode)
- {
- cpi->twopass.gf_group_bits = cpi->twopass.kf_group_bits;
- cpi->twopass.gf_group_error_left = cpi->twopass.kf_group_error_left;
- cpi->baseline_gf_interval = cpi->twopass.frames_to_key;
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
- cpi->source_alt_ref_pending = FALSE;
- }
-
}
// Is this a GF / ARF (Note that a KF is always also a GF)
@@ -2298,26 +2393,9 @@ void vp8_second_pass(VP8_COMP *cpi)
// Otherwise this is an ordinary frame
else
{
- // Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
- // outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
- // This is temporary code till we decide what should really happen in this case.
- if (cpi->oxcf.error_resilient_mode)
- {
- cpi->frames_till_gf_update_due = cpi->twopass.frames_to_key;
-
- if (cpi->common.frame_type != KEY_FRAME)
- {
- // Assign bits from those allocated to the GF group
- vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
- assign_std_frame_bits(cpi, &this_frame_copy);
- }
- }
- else
- {
- // Assign bits from those allocated to the GF group
- vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
- assign_std_frame_bits(cpi, &this_frame_copy);
- }
+ // Assign bits from those allocated to the GF group
+ vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+ assign_std_frame_bits(cpi, &this_frame_copy);
}
// Keep a globally available copy of this and the next frame's iiratio.
@@ -2337,20 +2415,26 @@ void vp8_second_pass(VP8_COMP *cpi)
if (cpi->target_bandwidth < 0)
cpi->target_bandwidth = 0;
+
+ // Account for mv, mode and other overheads.
+ overhead_bits = estimate_modemvcost(
+ cpi, cpi->twopass.total_left_stats );
+
+ // Special case code for first frame.
if (cpi->common.current_video_frame == 0)
{
cpi->twopass.est_max_qcorrection_factor = 1.0;
- // Experimental code to try and set a cq_level in constrained
- // quality mode.
+ // Set a cq_level in constrained quality mode.
if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY )
{
int est_cq;
est_cq =
estimate_cq( cpi,
- (cpi->twopass.total_coded_error_left / frames_left),
- (int)(cpi->twopass.bits_left / frames_left));
+ cpi->twopass.total_left_stats,
+ (int)(cpi->twopass.bits_left / frames_left),
+ overhead_bits );
cpi->cq_target_quality = cpi->oxcf.cq_level;
if ( est_cq > cpi->cq_target_quality )
@@ -2360,22 +2444,23 @@ void vp8_second_pass(VP8_COMP *cpi)
// guess at maxq needed in 2nd pass
cpi->twopass.maxq_max_limit = cpi->worst_quality;
cpi->twopass.maxq_min_limit = cpi->best_quality;
- tmp_q = estimate_max_q( cpi,
- (cpi->twopass.total_coded_error_left / frames_left),
- (int)(cpi->twopass.bits_left / frames_left));
+
+ tmp_q = estimate_max_q(
+ cpi,
+ cpi->twopass.total_left_stats,
+ (int)(cpi->twopass.bits_left / frames_left),
+ overhead_bits );
+
+ cpi->active_worst_quality = tmp_q;
+ cpi->ni_av_qi = tmp_q;
+ cpi->avg_q = vp8_convert_qindex_to_q( tmp_q );
// Limit the maxq value returned subsequently.
// This increases the risk of overspend or underspend if the initial
// estimate for the clip is bad, but helps prevent excessive
// variation in Q, especially near the end of a clip
// where for example a small overspend may cause Q to crash
- cpi->twopass.maxq_max_limit = ((tmp_q + 32) < cpi->worst_quality)
- ? (tmp_q + 32) : cpi->worst_quality;
- cpi->twopass.maxq_min_limit = ((tmp_q - 32) > cpi->best_quality)
- ? (tmp_q - 32) : cpi->best_quality;
-
- cpi->active_worst_quality = tmp_q;
- cpi->ni_av_qi = tmp_q;
+ adjust_maxq_qrange(cpi);
}
// The last few frames of a clip almost always have to few or too many
@@ -2383,28 +2468,28 @@ void vp8_second_pass(VP8_COMP *cpi)
// radical adjustments to the allowed quantizer range just to use up a
// few surplus bits or get beneath the target rate.
else if ( (cpi->common.current_video_frame <
- (((unsigned int)cpi->twopass.total_stats->count * 255)>>8)) &&
+ (((unsigned int)cpi->twopass.total_stats->count * 255)>>8)) &&
((cpi->common.current_video_frame + cpi->baseline_gf_interval) <
- (unsigned int)cpi->twopass.total_stats->count) )
+ (unsigned int)cpi->twopass.total_stats->count) )
{
if (frames_left < 1)
frames_left = 1;
- tmp_q = estimate_max_q(cpi, (cpi->twopass.total_coded_error_left / frames_left), (int)(cpi->twopass.bits_left / frames_left));
-
- // Move active_worst_quality but in a damped way
- if (tmp_q > cpi->active_worst_quality)
- cpi->active_worst_quality ++;
- else if (tmp_q < cpi->active_worst_quality)
- cpi->active_worst_quality --;
+ tmp_q = estimate_max_q(
+ cpi,
+ cpi->twopass.total_left_stats,
+ (int)(cpi->twopass.bits_left / frames_left),
+ overhead_bits );
- cpi->active_worst_quality = ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4;
+ // Make a damped adjustment to active max Q
+ cpi->active_worst_quality =
+ adjust_active_maxq( cpi->active_worst_quality, tmp_q );
}
cpi->twopass.frames_to_key --;
- cpi->twopass.total_error_left -= this_frame_error;
- cpi->twopass.total_intra_error_left -= this_frame_intra_error;
- cpi->twopass.total_coded_error_left -= this_frame_coded_error;
+
+ // Update the total stats remaining sturcture
+ subtract_stats(cpi->twopass.total_left_stats, &this_frame );
}
@@ -2678,51 +2763,6 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
max_grp_bits = (int64_t)max_bits * (int64_t)cpi->twopass.frames_to_key;
if (cpi->twopass.kf_group_bits > max_grp_bits)
cpi->twopass.kf_group_bits = max_grp_bits;
-
- // Additional special case for CBR if buffer is getting full.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- int opt_buffer_lvl = cpi->oxcf.optimal_buffer_level;
- int buffer_lvl = cpi->buffer_level;
-
- // If the buffer is near or above the optimal and this kf group is
- // not being allocated much then increase the allocation a bit.
- if (buffer_lvl >= opt_buffer_lvl)
- {
- int high_water_mark = (opt_buffer_lvl +
- cpi->oxcf.maximum_buffer_size) >> 1;
-
- int64_t av_group_bits;
-
- // Av bits per frame * number of frames
- av_group_bits = (int64_t)cpi->av_per_frame_bandwidth *
- (int64_t)cpi->twopass.frames_to_key;
-
- // We are at or above the maximum.
- if (cpi->buffer_level >= high_water_mark)
- {
- int64_t min_group_bits;
-
- min_group_bits = av_group_bits +
- (int64_t)(buffer_lvl -
- high_water_mark);
-
- if (cpi->twopass.kf_group_bits < min_group_bits)
- cpi->twopass.kf_group_bits = min_group_bits;
- }
- // We are above optimal but below the maximum
- else if (cpi->twopass.kf_group_bits < av_group_bits)
- {
- int64_t bits_below_av = av_group_bits -
- cpi->twopass.kf_group_bits;
-
- cpi->twopass.kf_group_bits +=
- (int64_t)((double)bits_below_av *
- (double)(buffer_lvl - opt_buffer_lvl) /
- (double)(high_water_mark - opt_buffer_lvl));
- }
- }
- }
}
else
cpi->twopass.kf_group_bits = 0;
@@ -2802,33 +2842,6 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// cpi->twopass.section_max_qfactor = 1.0;
}
- // When using CBR apply additional buffer fullness related upper limits
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- double max_boost;
-
- if (cpi->drop_frames_allowed)
- {
- int df_buffer_level = cpi->oxcf.drop_frames_water_mark * (cpi->oxcf.optimal_buffer_level / 100);
-
- if (cpi->buffer_level > df_buffer_level)
- max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
- else
- max_boost = 0.0;
- }
- else if (cpi->buffer_level > 0)
- {
- max_boost = ((double)(cpi->buffer_level * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
- }
- else
- {
- max_boost = 0.0;
- }
-
- if (boost_score > max_boost)
- boost_score = max_boost;
- }
-
// Reset the first pass file position
reset_fpf_position(cpi, start_position);
@@ -2866,18 +2879,31 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
kf_boost = (int)((double)kf_boost * 100.0) >> 4; // Scale 16 to 100
- // Adjustment to boost based on recent average q
- //kf_boost = kf_boost * vp8_kf_boost_qadjustment[cpi->ni_av_qi] / 100;
-
if (kf_boost < 250) // Min KF boost
kf_boost = 250;
// We do three calculations for kf size.
// The first is based on the error score for the whole kf group.
- // The second (optionaly) on the key frames own error if this is smaller than the average for the group.
- // The final one insures that the frame receives at least the allocation it would have received based on its own error score vs the error score remaining
-
- allocation_chunks = ((cpi->twopass.frames_to_key - 1) * 100) + kf_boost; // cpi->twopass.frames_to_key-1 because key frame itself is taken care of by kf_boost
+ // The second (optionaly) on the key frames own error if this is
+ // smaller than the average for the group.
+ // The final one insures that the frame receives at least the
+ // allocation it would have received based on its own error score vs
+ // the error score remaining
+ // Special case if the sequence appears almost totaly static
+ // as measured by the decay accumulator. In this case we want to
+ // spend almost all of the bits on the key frame.
+ // cpi->twopass.frames_to_key-1 because key frame itself is taken
+ // care of by kf_boost.
+ if ( decay_accumulator >= 0.99 )
+ {
+ allocation_chunks =
+ ((cpi->twopass.frames_to_key - 1) * 10) + kf_boost;
+ }
+ else
+ {
+ allocation_chunks =
+ ((cpi->twopass.frames_to_key - 1) * 100) + kf_boost;
+ }
// Normalize Altboost and allocations chunck down to prevent overflow
while (kf_boost > 1000)
@@ -2891,13 +2917,6 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// Calculate the number of bits to be spent on the key frame
cpi->twopass.kf_bits = (int)((double)kf_boost * ((double)cpi->twopass.kf_group_bits / (double)allocation_chunks));
- // Apply an additional limit for CBR
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- if (cpi->twopass.kf_bits > ((3 * cpi->buffer_level) >> 2))
- cpi->twopass.kf_bits = (3 * cpi->buffer_level) >> 2;
- }
-
// If the key frame is actually easier than the average for the
// kf group (which does sometimes happen... eg a blank intro frame)
// Then use an alternate calculation based on the kf error score
@@ -2946,147 +2965,4 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// Adjust the count of total modified error left.
// The count of bits left is adjusted elsewhere based on real coded frame sizes
cpi->twopass.modified_error_left -= kf_group_err;
-
- if (cpi->oxcf.allow_spatial_resampling)
- {
- int resample_trigger = FALSE;
- int last_kf_resampled = FALSE;
- int kf_q;
- int scale_val = 0;
- int hr, hs, vr, vs;
- int new_width = cpi->oxcf.Width;
- int new_height = cpi->oxcf.Height;
-
- int projected_buffer_level = cpi->buffer_level;
- int tmp_q;
-
- double projected_bits_perframe;
- double group_iiratio = (kf_group_intra_err - first_frame.intra_error) / (kf_group_coded_err - first_frame.coded_error);
- double err_per_frame = kf_group_err / cpi->twopass.frames_to_key;
- double bits_per_frame;
- double av_bits_per_frame;
- double effective_size_ratio;
-
- if ((cpi->common.Width != cpi->oxcf.Width) || (cpi->common.Height != cpi->oxcf.Height))
- last_kf_resampled = TRUE;
-
- // Set back to unscaled by defaults
- cpi->common.horiz_scale = NORMAL;
- cpi->common.vert_scale = NORMAL;
-
- // Calculate Average bits per frame.
- //av_bits_per_frame = cpi->twopass.bits_left/(double)(cpi->twopass.total_stats->count - cpi->common.current_video_frame);
- av_bits_per_frame = cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate);
- //if ( av_bits_per_frame < 0.0 )
- // av_bits_per_frame = 0.0
-
- // CBR... Use the clip average as the target for deciding resample
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- bits_per_frame = av_bits_per_frame;
- }
-
- // In VBR we want to avoid downsampling in easy section unless we are under extreme pressure
- // So use the larger of target bitrate for this sectoion or average bitrate for sequence
- else
- {
- bits_per_frame = cpi->twopass.kf_group_bits / cpi->twopass.frames_to_key; // This accounts for how hard the section is...
-
- if (bits_per_frame < av_bits_per_frame) // Dont turn to resampling in easy sections just because they have been assigned a small number of bits
- bits_per_frame = av_bits_per_frame;
- }
-
- // bits_per_frame should comply with our minimum
- if (bits_per_frame < (cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100))
- bits_per_frame = (cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
-
- // Work out if spatial resampling is necessary
- kf_q = estimate_kf_group_q(cpi, err_per_frame, bits_per_frame, group_iiratio);
-
- // If we project a required Q higher than the maximum allowed Q then make a guess at the actual size of frames in this section
- projected_bits_perframe = bits_per_frame;
- tmp_q = kf_q;
-
- while (tmp_q > cpi->worst_quality)
- {
- projected_bits_perframe *= 1.04;
- tmp_q--;
- }
-
- // Guess at buffer level at the end of the section
- projected_buffer_level = cpi->buffer_level - (int)((projected_bits_perframe - av_bits_per_frame) * cpi->twopass.frames_to_key);
-
- if (0)
- {
- FILE *f = fopen("Subsamle.stt", "a");
- fprintf(f, " %8d %8d %8d %8d %12.0f %8d %8d %8d\n", cpi->common.current_video_frame, kf_q, cpi->common.horiz_scale, cpi->common.vert_scale, kf_group_err / cpi->twopass.frames_to_key, (int)(cpi->twopass.kf_group_bits / cpi->twopass.frames_to_key), new_height, new_width);
- fclose(f);
- }
-
- // The trigger for spatial resampling depends on the various parameters such as whether we are streaming (CBR) or VBR.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- // Trigger resample if we are projected to fall below down sample level or
- // resampled last time and are projected to remain below the up sample level
- if ((projected_buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100)) ||
- (last_kf_resampled && (projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))))
- //( ((cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))) &&
- // ((projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))) ))
- resample_trigger = TRUE;
- else
- resample_trigger = FALSE;
- }
- else
- {
- int64_t clip_bits = (int64_t)(cpi->twopass.total_stats->count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate));
- int64_t over_spend = cpi->oxcf.starting_buffer_level - cpi->buffer_level;
-
- if ((last_kf_resampled && (kf_q > cpi->worst_quality)) || // If triggered last time the threshold for triggering again is reduced
- ((kf_q > cpi->worst_quality) && // Projected Q higher than allowed and ...
- (over_spend > clip_bits / 20))) // ... Overspend > 5% of total bits
- resample_trigger = TRUE;
- else
- resample_trigger = FALSE;
-
- }
-
- if (resample_trigger)
- {
- while ((kf_q >= cpi->worst_quality) && (scale_val < 6))
- {
- scale_val ++;
-
- cpi->common.vert_scale = vscale_lookup[scale_val];
- cpi->common.horiz_scale = hscale_lookup[scale_val];
-
- Scale2Ratio(cpi->common.horiz_scale, &hr, &hs);
- Scale2Ratio(cpi->common.vert_scale, &vr, &vs);
-
- new_width = ((hs - 1) + (cpi->oxcf.Width * hr)) / hs;
- new_height = ((vs - 1) + (cpi->oxcf.Height * vr)) / vs;
-
- // Reducing the area to 1/4 does not reduce the complexity (err_per_frame) to 1/4...
- // effective_sizeratio attempts to provide a crude correction for this
- effective_size_ratio = (double)(new_width * new_height) / (double)(cpi->oxcf.Width * cpi->oxcf.Height);
- effective_size_ratio = (1.0 + (3.0 * effective_size_ratio)) / 4.0;
-
- // Now try again and see what Q we get with the smaller image size
- kf_q = estimate_kf_group_q(cpi, err_per_frame * effective_size_ratio, bits_per_frame, group_iiratio);
-
- if (0)
- {
- FILE *f = fopen("Subsamle.stt", "a");
- fprintf(f, "******** %8d %8d %8d %12.0f %8d %8d %8d\n", kf_q, cpi->common.horiz_scale, cpi->common.vert_scale, kf_group_err / cpi->twopass.frames_to_key, (int)(cpi->twopass.kf_group_bits / cpi->twopass.frames_to_key), new_height, new_width);
- fclose(f);
- }
- }
- }
-
- if ((cpi->common.Width != new_width) || (cpi->common.Height != new_height))
- {
- cpi->common.Width = new_width;
- cpi->common.Height = new_height;
- vp8_alloc_compressor_data(cpi);
- }
- }
}
diff --git a/vp8/encoder/generic/csystemdependent.c b/vp8/encoder/generic/csystemdependent.c
index b85827926..ebb16e3f0 100644
--- a/vp8/encoder/generic/csystemdependent.c
+++ b/vp8/encoder/generic/csystemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/encoder/variance.h"
#include "vp8/encoder/onyx_int.h"
@@ -69,8 +69,8 @@ void vp8_cmachine_specific_config(VP8_COMP *cpi)
cpi->rtcd.variance.mse16x16 = vp8_mse16x16_c;
cpi->rtcd.variance.getmbss = vp8_get_mb_ss_c;
- cpi->rtcd.variance.get4x4sse_cs = vp8_get4x4sse_cs_c;
-
+ cpi->rtcd.fdct.short8x8 = vp8_short_fdct8x8_c;
+ cpi->rtcd.fdct.haar_short2x2 = vp8_short_fhaar2x2_c;
cpi->rtcd.fdct.short4x4 = vp8_short_fdct4x4_c;
cpi->rtcd.fdct.short8x4 = vp8_short_fdct8x4_c;
cpi->rtcd.fdct.fast4x4 = vp8_short_fdct4x4_c;
@@ -88,19 +88,21 @@ void vp8_cmachine_specific_config(VP8_COMP *cpi)
cpi->rtcd.quantize.quantb_pair = vp8_regular_quantize_b_pair;
cpi->rtcd.quantize.fastquantb = vp8_fast_quantize_b_c;
cpi->rtcd.quantize.fastquantb_pair = vp8_fast_quantize_b_pair_c;
+ cpi->rtcd.quantize.quantb_8x8 = vp8_regular_quantize_b_8x8;
+ cpi->rtcd.quantize.fastquantb_8x8 = vp8_fast_quantize_b_8x8_c;
+ cpi->rtcd.quantize.quantb_2x2 = vp8_regular_quantize_b_2x2;
+ cpi->rtcd.quantize.fastquantb_2x2 = vp8_fast_quantize_b_2x2_c;
cpi->rtcd.search.full_search = vp8_full_search_sad;
cpi->rtcd.search.refining_search = vp8_refining_search_sad;
cpi->rtcd.search.diamond_search = vp8_diamond_search_sad;
-#if !(CONFIG_REALTIME_ONLY)
cpi->rtcd.temporal.apply = vp8_temporal_filter_apply_c;
-#endif
#if CONFIG_INTERNAL_STATS
cpi->rtcd.variance.ssimpf_8x8 = vp8_ssim_parms_8x8_c;
cpi->rtcd.variance.ssimpf_16x16 = vp8_ssim_parms_16x16_c;
#endif
#endif
- // Pure C:
+ cpi->rtcd.variance.satd16x16 = vp8_satd16x16_c;
vp8_yv12_copy_partial_frame_ptr = vp8_yv12_copy_partial_frame;
#if ARCH_X86 || ARCH_X86_64
@@ -111,12 +113,10 @@ void vp8_cmachine_specific_config(VP8_COMP *cpi)
vp8_arch_arm_encoder_init(cpi);
#endif
-#if CONFIG_EXTEND_QRANGE
cpi->rtcd.fdct.short4x4 = vp8_short_fdct4x4_c;
cpi->rtcd.fdct.short8x4 = vp8_short_fdct8x4_c;
cpi->rtcd.fdct.fast4x4 = vp8_short_fdct4x4_c;
cpi->rtcd.fdct.fast8x4 = vp8_short_fdct8x4_c;
cpi->rtcd.fdct.walsh_short4x4 = vp8_short_walsh4x4_c;
-#endif
}
diff --git a/vp8/encoder/lookahead.c b/vp8/encoder/lookahead.c
index b92e82bdf..b800d0136 100644
--- a/vp8/encoder/lookahead.c
+++ b/vp8/encoder/lookahead.c
@@ -13,7 +13,7 @@
#include "lookahead.h"
#include "vp8/common/extend.h"
-#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
+#define MAX_LAG_BUFFERS 25
struct lookahead_ctx
{
diff --git a/vp8/encoder/mbgraph.c b/vp8/encoder/mbgraph.c
new file mode 100644
index 000000000..869562662
--- /dev/null
+++ b/vp8/encoder/mbgraph.c
@@ -0,0 +1,564 @@
+/*
+ * 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 <limits.h>
+#include <vp8/encoder/encodeintra.h>
+#include <vp8/encoder/rdopt.h>
+#include <vp8/common/setupintrarecon.h>
+#include <vp8/common/blockd.h>
+#include <vp8/common/reconinter.h>
+#include <vp8/common/systemdependent.h>
+#include <vpx_mem/vpx_mem.h>
+#include <vp8/encoder/segmentation.h>
+
+static unsigned int do_16x16_motion_iteration
+(
+ VP8_COMP *cpi,
+ int_mv *ref_mv,
+ int_mv *dst_mv
+)
+{
+ MACROBLOCK * const x = &cpi->mb;
+ MACROBLOCKD * const xd = &x->e_mbd;
+ BLOCK *b = &x->block[0];
+ BLOCKD *d = &xd->block[0];
+ vp8_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[BLOCK_16X16];
+ unsigned int best_err;
+ int step_param, further_steps;
+ static int dummy_cost[2*mv_max+1];
+ int *mvcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] };
+ int *mvsadcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] };
+#if CONFIG_HIGH_PRECISION_MV
+ static int dummy_cost_hp[2*mv_max_hp+1];
+ int *mvcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost_hp[mv_max_hp+1] };
+ int *mvsadcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost_hp[mv_max_hp+1] };
+#endif
+ int col_min = (ref_mv->as_mv.col>>3) - MAX_FULL_PEL_VAL + ((ref_mv->as_mv.col & 7)?1:0);
+ int row_min = (ref_mv->as_mv.row>>3) - MAX_FULL_PEL_VAL + ((ref_mv->as_mv.row & 7)?1:0);
+ int col_max = (ref_mv->as_mv.col>>3) + MAX_FULL_PEL_VAL;
+ int row_max = (ref_mv->as_mv.row>>3) + MAX_FULL_PEL_VAL;
+ int tmp_col_min = x->mv_col_min;
+ int tmp_col_max = x->mv_col_max;
+ int tmp_row_min = x->mv_row_min;
+ int tmp_row_max = x->mv_row_max;
+ int_mv ref_full;
+
+ // Further step/diamond searches as necessary
+ if (cpi->Speed < 8)
+ {
+ step_param = cpi->sf.first_step + ((cpi->Speed > 5) ? 1 : 0);
+ further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+ }
+ else
+ {
+ step_param = cpi->sf.first_step + 2;
+ further_steps = 0;
+ }
+
+ /* Get intersection of UMV window and valid MV window to reduce # of checks in diamond search. */
+ if (x->mv_col_min < col_min )
+ x->mv_col_min = col_min;
+ if (x->mv_col_max > col_max )
+ x->mv_col_max = col_max;
+ if (x->mv_row_min < row_min )
+ x->mv_row_min = row_min;
+ if (x->mv_row_max > row_max )
+ x->mv_row_max = row_max;
+
+ ref_full.as_mv.col = ref_mv->as_mv.col >> 3;
+ ref_full.as_mv.row = ref_mv->as_mv.row >> 3;
+
+ /*cpi->sf.search_method == HEX*/
+ best_err = vp8_hex_search(x, b, d,
+ &ref_full, dst_mv,
+ step_param,
+ x->errorperbit,
+ &v_fn_ptr,
+#if CONFIG_HIGH_PRECISION_MV
+ xd->allow_high_precision_mv?mvsadcost_hp:mvsadcost, xd->allow_high_precision_mv?mvcost_hp:mvcost,
+#else
+ mvsadcost, mvcost,
+#endif
+ ref_mv);
+
+ // Try sub-pixel MC
+ //if (bestsme > error_thresh && bestsme < INT_MAX)
+ {
+ int distortion;
+ unsigned int sse;
+ best_err = cpi->find_fractional_mv_step(x, b, d,
+ dst_mv, ref_mv,
+ x->errorperbit, &v_fn_ptr,
+#if CONFIG_HIGH_PRECISION_MV
+ xd->allow_high_precision_mv?mvcost_hp:mvcost,
+#else
+ mvcost,
+#endif
+ &distortion, &sse);
+ }
+
+ vp8_set_mbmode_and_mvs(x, NEWMV, dst_mv);
+ vp8_build_inter16x16_predictors_mby(xd);
+ //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+ best_err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
+ (xd->dst.y_buffer, xd->dst.y_stride,
+ xd->predictor, 16, &best_err);
+
+ /* restore UMV window */
+ x->mv_col_min = tmp_col_min;
+ x->mv_col_max = tmp_col_max;
+ x->mv_row_min = tmp_row_min;
+ x->mv_row_max = tmp_row_max;
+
+ return best_err;
+}
+
+static int do_16x16_motion_search
+(
+ VP8_COMP *cpi,
+ int_mv *ref_mv,
+ int_mv *dst_mv,
+ YV12_BUFFER_CONFIG *buf,
+ int buf_mb_y_offset,
+ YV12_BUFFER_CONFIG *ref,
+ int mb_y_offset
+)
+{
+ MACROBLOCK * const x = &cpi->mb;
+ MACROBLOCKD * const xd = &x->e_mbd;
+ unsigned int err, tmp_err;
+ int_mv tmp_mv;
+ int n;
+
+ for (n = 0; n < 16; n++) {
+ BLOCKD *d = &xd->block[n];
+ BLOCK *b = &x->block[n];
+
+ b->base_src = &buf->y_buffer;
+ b->src_stride = buf->y_stride;
+ b->src = buf->y_stride * (n & 12) + (n & 3) * 4 + buf_mb_y_offset;
+
+ d->base_pre = &ref->y_buffer;
+ d->pre_stride = ref->y_stride;
+ d->pre = ref->y_stride * (n & 12) + (n & 3) * 4 + mb_y_offset;
+ }
+
+ // Try zero MV first
+ // FIXME should really use something like near/nearest MV and/or MV prediction
+ xd->pre.y_buffer = ref->y_buffer + mb_y_offset;
+ xd->pre.y_stride = ref->y_stride;
+ //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+ err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
+ (ref->y_buffer + mb_y_offset,
+ ref->y_stride, xd->dst.y_buffer,
+ xd->dst.y_stride, &err);
+ dst_mv->as_int = 0;
+
+ // Test last reference frame using the previous best mv as the
+ // starting point (best reference) for the search
+ tmp_err = do_16x16_motion_iteration(cpi, ref_mv, &tmp_mv);
+ if (tmp_err < err)
+ {
+ err = tmp_err;
+ dst_mv->as_int = tmp_mv.as_int;
+ }
+
+ // If the current best reference mv is not centred on 0,0 then do a 0,0 based search as well
+ if (ref_mv->as_int)
+ {
+ int tmp_err;
+ int_mv zero_ref_mv, tmp_mv;
+
+ zero_ref_mv.as_int = 0;
+ tmp_err = do_16x16_motion_iteration(cpi, &zero_ref_mv, &tmp_mv);
+ if (tmp_err < err)
+ {
+ dst_mv->as_int = tmp_mv.as_int;
+ err = tmp_err;
+ }
+ }
+
+ return err;
+}
+
+static int do_16x16_zerozero_search
+(
+ VP8_COMP *cpi,
+ int_mv *dst_mv,
+ YV12_BUFFER_CONFIG *buf,
+ int buf_mb_y_offset,
+ YV12_BUFFER_CONFIG *ref,
+ int mb_y_offset
+)
+{
+ MACROBLOCK * const x = &cpi->mb;
+ MACROBLOCKD * const xd = &x->e_mbd;
+ unsigned int err;
+ int n;
+
+ for (n = 0; n < 16; n++) {
+ BLOCKD *d = &xd->block[n];
+ BLOCK *b = &x->block[n];
+
+ b->base_src = &buf->y_buffer;
+ b->src_stride = buf->y_stride;
+ b->src = buf->y_stride * (n & 12) + (n & 3) * 4 + buf_mb_y_offset;
+
+ d->base_pre = &ref->y_buffer;
+ d->pre_stride = ref->y_stride;
+ d->pre = ref->y_stride * (n & 12) + (n & 3) * 4 + mb_y_offset;
+ }
+
+ // Try zero MV first
+ // FIXME should really use something like near/nearest MV and/or MV prediction
+ xd->pre.y_buffer = ref->y_buffer + mb_y_offset;
+ xd->pre.y_stride = ref->y_stride;
+ //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+ err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
+ (ref->y_buffer + mb_y_offset,
+ ref->y_stride, xd->dst.y_buffer,
+ xd->dst.y_stride, &err);
+
+ dst_mv->as_int = 0;
+
+ return err;
+}
+static int find_best_16x16_intra
+(
+ VP8_COMP *cpi,
+ YV12_BUFFER_CONFIG *buf,
+ int mb_y_offset,
+ MB_PREDICTION_MODE *pbest_mode
+)
+{
+ MACROBLOCK * const x = &cpi->mb;
+ MACROBLOCKD * const xd = &x->e_mbd;
+ MB_PREDICTION_MODE best_mode = -1, mode;
+ int best_err = INT_MAX;
+
+ // calculate SATD for each intra prediction mode;
+ // we're intentionally not doing 4x4, we just want a rough estimate
+ for (mode = DC_PRED; mode <= TM_PRED; mode++)
+ {
+ unsigned int err;
+
+ xd->mode_info_context->mbmi.mode = mode;
+ RECON_INVOKE(&cpi->rtcd.common->recon, build_intra_predictors_mby)(xd);
+ //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+ err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
+ (xd->predictor, 16,
+ buf->y_buffer + mb_y_offset,
+ buf->y_stride, &err);
+ // find best
+ if (err < best_err)
+ {
+ best_err = err;
+ best_mode = mode;
+ }
+ }
+
+ if (pbest_mode)
+ *pbest_mode = best_mode;
+
+ return best_err;
+}
+
+static void update_mbgraph_mb_stats
+(
+ VP8_COMP *cpi,
+ MBGRAPH_MB_STATS *stats,
+ YV12_BUFFER_CONFIG *buf,
+ int mb_y_offset,
+ YV12_BUFFER_CONFIG *golden_ref,
+ int_mv *prev_golden_ref_mv,
+ int gld_y_offset,
+ YV12_BUFFER_CONFIG *alt_ref,
+ int_mv *prev_alt_ref_mv,
+ int arf_y_offset
+)
+{
+ MACROBLOCK * const x = &cpi->mb;
+ MACROBLOCKD * const xd = &x->e_mbd;
+ int intra_error;
+
+ // FIXME in practice we're completely ignoring chroma here
+ xd->dst.y_buffer = buf->y_buffer + mb_y_offset;
+
+ // do intra 16x16 prediction
+ intra_error = find_best_16x16_intra(cpi, buf, mb_y_offset, &stats->ref[INTRA_FRAME].m.mode);
+ if (intra_error <= 0)
+ intra_error = 1;
+ stats->ref[INTRA_FRAME].err = intra_error;
+
+ // Golden frame MV search, if it exists and is different than last frame
+ if (golden_ref)
+ {
+ int g_motion_error = do_16x16_motion_search(cpi, prev_golden_ref_mv,
+ &stats->ref[GOLDEN_FRAME].m.mv,
+ buf, mb_y_offset,
+ golden_ref, gld_y_offset);
+ stats->ref[GOLDEN_FRAME].err = g_motion_error;
+ }
+ else
+ {
+ stats->ref[GOLDEN_FRAME].err = INT_MAX;
+ stats->ref[GOLDEN_FRAME].m.mv.as_int = 0;
+ }
+
+ // Alt-ref frame MV search, if it exists and is different than last/golden frame
+ if (alt_ref)
+ {
+ //int a_motion_error = do_16x16_motion_search(cpi, prev_alt_ref_mv,
+ // &stats->ref[ALTREF_FRAME].m.mv,
+ // buf, mb_y_offset,
+ // alt_ref, arf_y_offset);
+
+ int a_motion_error =
+ do_16x16_zerozero_search( cpi,
+ &stats->ref[ALTREF_FRAME].m.mv,
+ buf, mb_y_offset,
+ alt_ref, arf_y_offset);
+
+ stats->ref[ALTREF_FRAME].err = a_motion_error;
+ }
+ else
+ {
+ stats->ref[ALTREF_FRAME].err = INT_MAX;
+ stats->ref[ALTREF_FRAME].m.mv.as_int = 0;
+ }
+}
+
+static void update_mbgraph_frame_stats
+(
+ VP8_COMP *cpi,
+ MBGRAPH_FRAME_STATS *stats,
+ YV12_BUFFER_CONFIG *buf,
+ YV12_BUFFER_CONFIG *golden_ref,
+ YV12_BUFFER_CONFIG *alt_ref
+)
+{
+ MACROBLOCK * const x = &cpi->mb;
+ VP8_COMMON * const cm = &cpi->common;
+ MACROBLOCKD * const xd = &x->e_mbd;
+ int mb_col, mb_row, offset = 0;
+ int mb_y_offset = 0, arf_y_offset = 0, gld_y_offset = 0;
+ int_mv arf_top_mv, gld_top_mv;
+ MODE_INFO mi_local;
+
+ // Set up limit values for motion vectors to prevent them extending outside the UMV borders
+ arf_top_mv.as_int = 0;
+ gld_top_mv.as_int = 0;
+ x->mv_row_min = -(VP8BORDERINPIXELS - 16 - INTERP_EXTEND);
+ x->mv_row_max = (cm->mb_rows - 1) * 16 + VP8BORDERINPIXELS - 16 - INTERP_EXTEND;
+ xd->up_available = 0;
+ xd->dst.y_stride = buf->y_stride;
+ xd->pre.y_stride = buf->y_stride;
+ xd->dst.uv_stride = buf->uv_stride;
+ xd->mode_info_context = &mi_local;
+
+ for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+ {
+ int_mv arf_left_mv, gld_left_mv;
+ int mb_y_in_offset = mb_y_offset;
+ int arf_y_in_offset = arf_y_offset;
+ int gld_y_in_offset = gld_y_offset;
+
+ // Set up limit values for motion vectors to prevent them extending outside the UMV borders
+ arf_left_mv.as_int = arf_top_mv.as_int;
+ gld_left_mv.as_int = gld_top_mv.as_int;
+ x->mv_col_min = -(VP8BORDERINPIXELS - 16 - INTERP_EXTEND);
+ x->mv_col_max = (cm->mb_cols - 1) * 16 + VP8BORDERINPIXELS - 16 - INTERP_EXTEND;
+ xd->left_available = 0;
+
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+ {
+ MBGRAPH_MB_STATS *mb_stats = &stats->mb_stats[offset + mb_col];
+
+ update_mbgraph_mb_stats(cpi, mb_stats, buf, mb_y_in_offset,
+ golden_ref, &gld_left_mv, gld_y_in_offset,
+ alt_ref, &arf_left_mv, arf_y_in_offset);
+ arf_left_mv.as_int = mb_stats->ref[ALTREF_FRAME].m.mv.as_int;
+ gld_left_mv.as_int = mb_stats->ref[GOLDEN_FRAME].m.mv.as_int;
+ if (mb_col == 0)
+ {
+ arf_top_mv.as_int = arf_left_mv.as_int;
+ gld_top_mv.as_int = gld_left_mv.as_int;
+ }
+ xd->left_available = 1;
+ mb_y_in_offset += 16;
+ gld_y_in_offset += 16;
+ arf_y_in_offset += 16;
+ x->mv_col_min -= 16;
+ x->mv_col_max -= 16;
+ }
+ xd->up_available = 1;
+ mb_y_offset += buf->y_stride * 16;
+ gld_y_offset += golden_ref->y_stride * 16;
+ if (alt_ref)
+ arf_y_offset += alt_ref->y_stride * 16;
+ x->mv_row_min -= 16;
+ x->mv_row_max -= 16;
+ offset += cm->mb_cols;
+ }
+}
+
+// Test for small magnitude (<= 1 pel mvs)
+int small_mv( MV mv )
+{
+ if ( (abs( (int)mv.col ) > 2) || (abs( (int)mv.row ) > 2) )
+ return FALSE;
+ else
+ return TRUE;
+}
+
+//void separate_arf_mbs_byzz
+void separate_arf_mbs
+(
+ VP8_COMP *cpi
+)
+{
+ VP8_COMMON * const cm = &cpi->common;
+ int mb_col, mb_row, offset, i;
+ int ncnt[4];
+ int n_frames = cpi->mbgraph_n_frames;
+
+ int * arf_not_zz;
+
+ CHECK_MEM_ERROR(arf_not_zz,
+ vpx_calloc(cm->mb_rows * cm->mb_cols * sizeof(*arf_not_zz), 1));
+
+ vpx_memset(arf_not_zz, 0, sizeof(arf_not_zz));
+
+ // We are not interested in results beyond the alt ref itself.
+ if ( n_frames > cpi->frames_till_gf_update_due )
+ n_frames = cpi->frames_till_gf_update_due;
+
+ // defer cost to reference frames
+ for (i = n_frames - 1; i >= 0; i--)
+ {
+ MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
+
+ for (offset = 0, mb_row = 0; mb_row < cm->mb_rows;
+ offset += cm->mb_cols, mb_row++)
+ {
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+ {
+ MBGRAPH_MB_STATS *mb_stats =
+ &frame_stats->mb_stats[offset + mb_col];
+
+ int altref_err = mb_stats->ref[ALTREF_FRAME].err;
+
+ int intra_err =
+ mb_stats->ref[INTRA_FRAME ].err + 250;
+
+ int golden_err =
+ mb_stats->ref[GOLDEN_FRAME].err + 250;
+
+ // Test for altref vs intra and gf and that its mv was 0,0.
+ if ( (altref_err > 1000) ||
+ (altref_err > intra_err) ||
+ (altref_err > golden_err) )
+ {
+ arf_not_zz[offset + mb_col]++;
+ }
+ }
+ }
+ }
+
+ vpx_memset(ncnt, 0, sizeof(ncnt));
+ for (offset = 0, mb_row = 0; mb_row < cm->mb_rows;
+ offset += cm->mb_cols, mb_row++)
+ {
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+ {
+ // If any of the blocks in the sequence failed then the MB
+ // goes in segment 0
+ if ( arf_not_zz[offset + mb_col] )
+ {
+ ncnt[0]++;
+ cpi->segmentation_map[offset + mb_col] = 0;
+ }
+ else
+ {
+ ncnt[1]++;
+ cpi->segmentation_map[offset + mb_col] = 1;
+ }
+ }
+ }
+
+ // Only bother with segmentation if over 10% of the MBs in static segment
+ //if ( ncnt[1] && (ncnt[0] / ncnt[1] < 10) )
+ if ( 1 )
+ {
+ // Note % of blocks that are marked as static
+ if ( cm->MBs )
+ cpi->static_mb_pct = (ncnt[1] * 100) / cm->MBs;
+
+ // This error case should not be reachable as this function should
+ // never be called with the common data structure unititialized.
+ else
+ cpi->static_mb_pct = 0;
+
+ vp8_enable_segmentation((VP8_PTR) cpi);
+ }
+ else
+ {
+ cpi->static_mb_pct = 0;
+ vp8_disable_segmentation((VP8_PTR) cpi);
+ }
+
+ // Free localy allocated storage
+ vpx_free(arf_not_zz);
+}
+
+void vp8_update_mbgraph_stats
+(
+ VP8_COMP *cpi
+)
+{
+ VP8_COMMON * const cm = &cpi->common;
+ int i, n_frames = vp8_lookahead_depth(cpi->lookahead);
+ YV12_BUFFER_CONFIG *golden_ref = &cm->yv12_fb[cm->gld_fb_idx];
+
+ // we need to look ahead beyond where the ARF transitions into
+ // being a GF - so exit if we don't look ahead beyond that
+ if (n_frames <= cpi->frames_till_gf_update_due)
+ return;
+ if (n_frames > MAX_LAG_BUFFERS)
+ n_frames = MAX_LAG_BUFFERS;
+
+ cpi->mbgraph_n_frames = n_frames;
+ for (i = 0; i < n_frames; i++)
+ {
+ MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
+ vpx_memset(frame_stats->mb_stats, 0,
+ cm->mb_rows * cm->mb_cols * sizeof(*cpi->mbgraph_stats[i].mb_stats));
+ }
+
+ // do motion search to find contribution of each reference to data
+ // later on in this GF group
+ // FIXME really, the GF/last MC search should be done forward, and
+ // the ARF MC search backwards, to get optimal results for MV caching
+ for (i = 0; i < n_frames; i++)
+ {
+ MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i];
+ struct lookahead_entry *q_cur =
+ vp8_lookahead_peek(cpi->lookahead, i);
+
+ assert(q_cur != NULL);
+
+ update_mbgraph_frame_stats(cpi, frame_stats, &q_cur->img,
+ golden_ref, cpi->Source);
+ }
+
+ vp8_clear_system_state(); //__asm emms;
+
+ separate_arf_mbs(cpi);
+}
diff --git a/vp8/encoder/pickinter.h b/vp8/encoder/mbgraph.h
index 1c5d6a6e6..11ff3e2f0 100644
--- a/vp8/encoder/pickinter.h
+++ b/vp8/encoder/mbgraph.h
@@ -8,12 +8,9 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#ifndef __INC_MBGRAPH_H__
+#define __INC_MBGRAPH_H__ 1
-#ifndef __INC_PICKINTER_H
-#define __INC_PICKINTER_H
-#include "vpx_config.h"
-#include "vp8/common/onyxc_int.h"
+extern void vp8_update_mbgraph_stats(VP8_COMP *cpi);
-extern void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra);
-extern void vp8_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate);
-#endif
+#endif /* __INC_MBGRAPH_H__ */
diff --git a/vp8/encoder/mcomp.c b/vp8/encoder/mcomp.c
index c1a0ea7bf..f07d18b49 100644
--- a/vp8/encoder/mcomp.c
+++ b/vp8/encoder/mcomp.c
@@ -11,7 +11,7 @@
#include "mcomp.h"
#include "vpx_mem/vpx_mem.h"
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include <stdio.h>
#include <limits.h>
#include <math.h>
@@ -22,6 +22,16 @@ static int mv_ref_ct [31] [4] [2];
static int mv_mode_cts [4] [2];
#endif
+#if CONFIG_HIGH_PRECISION_MV
+int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight, int ishp)
+{
+ // MV costing is based on the distribution of vectors in the previous frame and as such will tend to
+ // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the
+ // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks.
+ // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors.
+ return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> (ishp==0)] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> (ishp==0)]) * Weight) >> 7;
+}
+#else
int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight)
{
// MV costing is based on the distribution of vectors in the previous frame and as such will tend to
@@ -30,13 +40,24 @@ int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight)
// The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors.
return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1]) * Weight) >> 7;
}
+#endif
+#if CONFIG_HIGH_PRECISION_MV
+static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit, int ishp)
+{
+ return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> (ishp==0)] +
+ mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> (ishp==0)])
+ * error_per_bit + 128) >> 8;
+}
+#else
static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit)
{
return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] +
mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1])
* error_per_bit + 128) >> 8;
}
+#endif
+
static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_per_bit)
{
@@ -46,6 +67,7 @@ static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_
* error_per_bit + 128) >> 8;
}
+
void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride)
{
int Len;
@@ -175,13 +197,32 @@ void vp8_init3smotion_compensation(MACROBLOCK *x, int stride)
* 32 cols area that is enough for 16x16 macroblock. Later, for SPLITMV, we
* could reduce the area.
*/
-#define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+
#define PRE(r,c) (y + (((r)>>2) * y_stride + ((c)>>2) -(offset))) // pointer to predictor base of a motionvector
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define SP(x) (((x)&3)<<2) // convert motion vector component to offset for svf calc
+#else
#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
+#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
+#define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c)-rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
#define DIST(r,c) vfp->svf( PRE(r,c), y_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
-#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
+#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
+
+#if CONFIG_HIGH_PRECISION_MV
+#define PREHP(r,c) (y + (((r)>>3) * y_stride + ((c)>>3) -(offset))) // pointer to predictor base of a motionvector
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define SPHP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
+#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
+#define SPHP(x) ((x)&7) // convert motion vector component to offset for svf calc
+#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
+#define DISTHP(r,c) vfp->svf( PREHP(r,c), y_stride, SPHP(c),SPHP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
+#define ERRHP(r,c) (MVC(r,c)+DISTHP(r,c)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = ((xd->allow_high_precision_mv)?DISTHP(r,c):DIST(r,c)); if((v = (MVC(r,c)+thismse)) < besterr) { besterr = v; br=r; bc=c; *distortion = thismse; *sse1 = sse; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best
+#else
#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = DIST(r,c); if((v = (MVC(r,c)+thismse)) < besterr) { besterr = v; br=r; bc=c; *distortion = thismse; *sse1 = sse; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best
+#endif /* CONFIG_HIGH_PRECISION_MV */
+
#define MIN(x,y) (((x)<(y))?(x):(y))
#define MAX(x,y) (((x)>(y))?(x):(y))
@@ -193,37 +234,34 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
unsigned int *sse1)
{
unsigned char *z = (*(b->base_src) + b->src);
+ MACROBLOCKD *xd = &x->e_mbd;
- int rr = ref_mv->as_mv.row >> 1, rc = ref_mv->as_mv.col >> 1;
- int br = bestmv->as_mv.row << 2, bc = bestmv->as_mv.col << 2;
- int tr = br, tc = bc;
+ int rr, rc, br, bc, hstep;
+ int tr, tc;
unsigned int besterr = INT_MAX;
unsigned int left, right, up, down, diag;
unsigned int sse;
unsigned int whichdir;
unsigned int halfiters = 4;
unsigned int quarteriters = 4;
+#if CONFIG_HIGH_PRECISION_MV
+ unsigned int eighthiters = 4;
+#endif
int thismse;
-
- int minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));
- int maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));
- int minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));
- int maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));
-
+ int maxc, minc, maxr, minr;
int y_stride;
int offset;
#if ARCH_X86 || ARCH_X86_64
- MACROBLOCKD *xd = &x->e_mbd;
unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
unsigned char *y;
int buf_r1, buf_r2, buf_c1, buf_c2;
// Clamping to avoid out-of-range data access
- buf_r1 = ((bestmv->as_mv.row - 3) < x->mv_row_min)?(bestmv->as_mv.row - x->mv_row_min):3;
- buf_r2 = ((bestmv->as_mv.row + 3) > x->mv_row_max)?(x->mv_row_max - bestmv->as_mv.row):3;
- buf_c1 = ((bestmv->as_mv.col - 3) < x->mv_col_min)?(bestmv->as_mv.col - x->mv_col_min):3;
- buf_c2 = ((bestmv->as_mv.col + 3) > x->mv_col_max)?(x->mv_col_max - bestmv->as_mv.col):3;
+ buf_r1 = ((bestmv->as_mv.row - INTERP_EXTEND) < x->mv_row_min)?(bestmv->as_mv.row - x->mv_row_min):INTERP_EXTEND;
+ buf_r2 = ((bestmv->as_mv.row + INTERP_EXTEND) > x->mv_row_max)?(x->mv_row_max - bestmv->as_mv.row):INTERP_EXTEND;
+ buf_c1 = ((bestmv->as_mv.col - INTERP_EXTEND) < x->mv_col_min)?(bestmv->as_mv.col - x->mv_col_min):INTERP_EXTEND;
+ buf_c2 = ((bestmv->as_mv.col + INTERP_EXTEND) > x->mv_col_max)?(x->mv_col_max - bestmv->as_mv.col):INTERP_EXTEND;
y_stride = 32;
/* Copy to intermediate buffer before searching. */
@@ -234,6 +272,34 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
y_stride = d->pre_stride;
#endif
+
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ rr = ref_mv->as_mv.row; rc = ref_mv->as_mv.col;
+ br = bestmv->as_mv.row << 3; bc = bestmv->as_mv.col << 3;
+ hstep = 4;
+ minc = MAX(x->mv_col_min << 3, (ref_mv->as_mv.col) - ((1 << mvlong_width_hp) - 1));
+ maxc = MIN(x->mv_col_max << 3, (ref_mv->as_mv.col) + ((1 << mvlong_width_hp) - 1));
+ minr = MAX(x->mv_row_min << 3, (ref_mv->as_mv.row) - ((1 << mvlong_width_hp) - 1));
+ maxr = MIN(x->mv_row_max << 3, (ref_mv->as_mv.row) + ((1 << mvlong_width_hp) - 1));
+ }
+ else
+#endif
+ {
+ rr = ref_mv->as_mv.row >> 1; rc = ref_mv->as_mv.col >> 1;
+ br = bestmv->as_mv.row << 2; bc = bestmv->as_mv.col << 2;
+ hstep = 2;
+ minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));
+ maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));
+ minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));
+ maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));
+ }
+
+ tr = br;
+ tc = bc;
+
+
offset = (bestmv->as_mv.row) * y_stride + bestmv->as_mv.col;
// central mv
@@ -243,32 +309,36 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
// calculate central point error
besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);
*distortion = besterr;
+#if CONFIG_HIGH_PRECISION_MV
+ besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+#endif
// TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
while (--halfiters)
{
// 1/2 pel
- CHECK_BETTER(left, tr, tc - 2);
- CHECK_BETTER(right, tr, tc + 2);
- CHECK_BETTER(up, tr - 2, tc);
- CHECK_BETTER(down, tr + 2, tc);
+ CHECK_BETTER(left, tr, tc - hstep);
+ CHECK_BETTER(right, tr, tc + hstep);
+ CHECK_BETTER(up, tr - hstep, tc);
+ CHECK_BETTER(down, tr + hstep, tc);
whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
switch (whichdir)
{
case 0:
- CHECK_BETTER(diag, tr - 2, tc - 2);
+ CHECK_BETTER(diag, tr - hstep, tc - hstep);
break;
case 1:
- CHECK_BETTER(diag, tr - 2, tc + 2);
+ CHECK_BETTER(diag, tr - hstep, tc + hstep);
break;
case 2:
- CHECK_BETTER(diag, tr + 2, tc - 2);
+ CHECK_BETTER(diag, tr + hstep, tc - hstep);
break;
case 3:
- CHECK_BETTER(diag, tr + 2, tc + 2);
+ CHECK_BETTER(diag, tr + hstep, tc + hstep);
break;
}
@@ -282,28 +352,29 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
// TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
// 1/4 pel
+ hstep >>= 1;
while (--quarteriters)
{
- CHECK_BETTER(left, tr, tc - 1);
- CHECK_BETTER(right, tr, tc + 1);
- CHECK_BETTER(up, tr - 1, tc);
- CHECK_BETTER(down, tr + 1, tc);
+ CHECK_BETTER(left, tr, tc - hstep);
+ CHECK_BETTER(right, tr, tc + hstep);
+ CHECK_BETTER(up, tr - hstep, tc);
+ CHECK_BETTER(down, tr + hstep, tc);
whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
switch (whichdir)
{
case 0:
- CHECK_BETTER(diag, tr - 1, tc - 1);
+ CHECK_BETTER(diag, tr - hstep, tc - hstep);
break;
case 1:
- CHECK_BETTER(diag, tr - 1, tc + 1);
+ CHECK_BETTER(diag, tr - hstep, tc + hstep);
break;
case 2:
- CHECK_BETTER(diag, tr + 1, tc - 1);
+ CHECK_BETTER(diag, tr + hstep, tc - hstep);
break;
case 3:
- CHECK_BETTER(diag, tr + 1, tc + 1);
+ CHECK_BETTER(diag, tr + hstep, tc + hstep);
break;
}
@@ -315,8 +386,56 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
tc = bc;
}
- bestmv->as_mv.row = br << 1;
- bestmv->as_mv.col = bc << 1;
+#if CONFIG_HIGH_PRECISION_MV
+ if (x->e_mbd.allow_high_precision_mv)
+ {
+ hstep >>= 1;
+ while (--eighthiters)
+ {
+ CHECK_BETTER(left, tr, tc - hstep);
+ CHECK_BETTER(right, tr, tc + hstep);
+ CHECK_BETTER(up, tr - hstep, tc);
+ CHECK_BETTER(down, tr + hstep, tc);
+
+ whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+ switch (whichdir)
+ {
+ case 0:
+ CHECK_BETTER(diag, tr - hstep, tc - hstep);
+ break;
+ case 1:
+ CHECK_BETTER(diag, tr - hstep, tc + hstep);
+ break;
+ case 2:
+ CHECK_BETTER(diag, tr + hstep, tc - hstep);
+ break;
+ case 3:
+ CHECK_BETTER(diag, tr + hstep, tc + hstep);
+ break;
+ }
+
+ // no reason to check the same one again.
+ if (tr == br && tc == bc)
+ break;
+
+ tr = br;
+ tc = bc;
+ }
+ }
+#endif
+#if CONFIG_HIGH_PRECISION_MV
+ if (x->e_mbd.allow_high_precision_mv)
+ {
+ bestmv->as_mv.row = br;
+ bestmv->as_mv.col = bc;
+ }
+ else
+#endif /* CONFIG_HIGH_PRECISION_MV */
+ {
+ bestmv->as_mv.row = br << 1;
+ bestmv->as_mv.col = bc << 1;
+ }
if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > (MAX_FULL_PEL_VAL<<3)) ||
(abs(bestmv->as_mv.row - ref_mv->as_mv.row) > (MAX_FULL_PEL_VAL<<3)))
@@ -333,6 +452,19 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
#undef CHECK_BETTER
#undef MIN
#undef MAX
+
+#if CONFIG_HIGH_PRECISION_MV
+#undef PREHP
+#undef DPHP
+#undef DISTHP
+#undef ERRHP
+#endif
+
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define SP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc
+#else
+#define SP(x) ((x)&7) // convert motion vector component to offset for svf calc
+#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int_mv *bestmv, int_mv *ref_mv,
int error_per_bit,
@@ -343,15 +475,19 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int bestmse = INT_MAX;
int_mv startmv;
int_mv this_mv;
+#if CONFIG_HIGH_PRECISION_MV
+ int_mv orig_mv;
+ int yrow_movedback=0, ycol_movedback=0;
+#endif
unsigned char *z = (*(b->base_src) + b->src);
int left, right, up, down, diag;
unsigned int sse;
int whichdir ;
int thismse;
int y_stride;
+ MACROBLOCKD *xd = &x->e_mbd;
#if ARCH_X86 || ARCH_X86_64
- MACROBLOCKD *xd = &x->e_mbd;
unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
unsigned char *y;
@@ -368,17 +504,28 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
bestmv->as_mv.row <<= 3;
bestmv->as_mv.col <<= 3;
startmv = *bestmv;
+#if CONFIG_HIGH_PRECISION_MV
+ orig_mv = *bestmv;
+#endif
// calculate central point error
bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
*distortion = bestmse;
+#if CONFIG_HIGH_PRECISION_MV
+ bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+#endif
// go left then right and check error
this_mv.as_mv.row = startmv.as_mv.row;
this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (left < bestmse)
{
@@ -390,7 +537,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
this_mv.as_mv.col += 8;
thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (right < bestmse)
{
@@ -404,7 +555,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
this_mv.as_mv.col = startmv.as_mv.col;
this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
thismse = vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (up < bestmse)
{
@@ -416,7 +571,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
this_mv.as_mv.row += 8;
thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (down < bestmse)
{
@@ -458,7 +617,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
break;
}
+#if CONFIG_HIGH_PRECISION_MV
+ diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (diag < bestmse)
{
@@ -473,10 +636,20 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
// time to check quarter pels.
if (bestmv->as_mv.row < startmv.as_mv.row)
+ {
y -= y_stride;
+#if CONFIG_HIGH_PRECISION_MV
+ yrow_movedback = 1;
+#endif
+ }
if (bestmv->as_mv.col < startmv.as_mv.col)
+ {
y--;
+#if CONFIG_HIGH_PRECISION_MV
+ ycol_movedback = 1;
+#endif
+ }
startmv = *bestmv;
@@ -488,15 +661,19 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (startmv.as_mv.col & 7)
{
this_mv.as_mv.col = startmv.as_mv.col - 2;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
else
{
this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
- thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
+#if CONFIG_HIGH_PRECISION_MV
+ left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (left < bestmse)
{
@@ -507,8 +684,12 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
}
this_mv.as_mv.col += 4;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (right < bestmse)
{
@@ -524,15 +705,19 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (startmv.as_mv.row & 7)
{
this_mv.as_mv.row = startmv.as_mv.row - 2;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
else
{
this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
- thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
+ thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
}
+#if CONFIG_HIGH_PRECISION_MV
+ up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (up < bestmse)
{
@@ -543,8 +728,12 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
}
this_mv.as_mv.row += 4;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (down < bestmse)
{
@@ -573,12 +762,12 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (startmv.as_mv.col & 7)
{
this_mv.as_mv.col -= 2;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
else
{
this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
- thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);;
+ thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse);;
}
}
else
@@ -588,12 +777,12 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (startmv.as_mv.col & 7)
{
this_mv.as_mv.col -= 2;
- thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
+ thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
}
else
{
this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
- thismse = vfp->svf(y - y_stride - 1, y_stride, 6, 6, z, b->src_stride, &sse);
+ thismse = vfp->svf(y - y_stride - 1, y_stride, SP(6), SP(6), z, b->src_stride, &sse);
}
}
@@ -604,12 +793,12 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (startmv.as_mv.row & 7)
{
this_mv.as_mv.row -= 2;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
else
{
this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
- thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
+ thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse);
}
break;
@@ -619,23 +808,27 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (startmv.as_mv.col & 7)
{
this_mv.as_mv.col -= 2;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
else
{
this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
- thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
}
break;
case 3:
this_mv.as_mv.col += 2;
this_mv.as_mv.row += 2;
- thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
break;
}
+#if CONFIG_HIGH_PRECISION_MV
+ diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (diag < bestmse)
{
@@ -645,9 +838,195 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
*sse1 = sse;
}
+#if CONFIG_HIGH_PRECISION_MV
+ if (!x->e_mbd.allow_high_precision_mv)
+ return bestmse;
+
+ /* Now do 1/8th pixel */
+ if (bestmv->as_mv.row < orig_mv.as_mv.row && !yrow_movedback)
+ {
+ y -= y_stride;
+ yrow_movedback = 1;
+ }
+
+ if (bestmv->as_mv.col < orig_mv.as_mv.col && !ycol_movedback)
+ {
+ y--;
+ ycol_movedback = 1;
+ }
+
+ startmv = *bestmv;
+
+ // go left then right and check error
+ this_mv.as_mv.row = startmv.as_mv.row;
+
+ if (startmv.as_mv.col & 7)
+ {
+ this_mv.as_mv.col = startmv.as_mv.col - 1;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+ else
+ {
+ this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
+ thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+
+ left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+
+ if (left < bestmse)
+ {
+ *bestmv = this_mv;
+ bestmse = left;
+ *distortion = thismse;
+ *sse1 = sse;
+ }
+
+ this_mv.as_mv.col += 2;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+
+ if (right < bestmse)
+ {
+ *bestmv = this_mv;
+ bestmse = right;
+ *distortion = thismse;
+ *sse1 = sse;
+ }
+
+ // go up then down and check error
+ this_mv.as_mv.col = startmv.as_mv.col;
+
+ if (startmv.as_mv.row & 7)
+ {
+ this_mv.as_mv.row = startmv.as_mv.row - 1;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+ else
+ {
+ this_mv.as_mv.row = (startmv.as_mv.row - 8) | 7;
+ thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse);
+ }
+
+ up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+
+ if (up < bestmse)
+ {
+ *bestmv = this_mv;
+ bestmse = up;
+ *distortion = thismse;
+ *sse1 = sse;
+ }
+
+ this_mv.as_mv.row += 2;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+
+ if (down < bestmse)
+ {
+ *bestmv = this_mv;
+ bestmse = down;
+ *distortion = thismse;
+ *sse1 = sse;
+ }
+
+
+ // now check 1 more diagonal
+ whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+// for(whichdir=0;whichdir<4;whichdir++)
+// {
+ this_mv = startmv;
+
+ switch (whichdir)
+ {
+ case 0:
+
+ if (startmv.as_mv.row & 7)
+ {
+ this_mv.as_mv.row -= 1;
+
+ if (startmv.as_mv.col & 7)
+ {
+ this_mv.as_mv.col -= 1;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+ else
+ {
+ this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
+ thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse);;
+ }
+ }
+ else
+ {
+ this_mv.as_mv.row = (startmv.as_mv.row - 8) | 7;
+
+ if (startmv.as_mv.col & 7)
+ {
+ this_mv.as_mv.col -= 1;
+ thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse);
+ }
+ else
+ {
+ this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
+ thismse = vfp->svf(y - y_stride - 1, y_stride, SP(7), SP(7), z, b->src_stride, &sse);
+ }
+ }
+
+ break;
+ case 1:
+ this_mv.as_mv.col += 1;
+
+ if (startmv.as_mv.row & 7)
+ {
+ this_mv.as_mv.row -= 1;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+ else
+ {
+ this_mv.as_mv.row = (startmv.as_mv.row - 8) | 7;
+ thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse);
+ }
+
+ break;
+ case 2:
+ this_mv.as_mv.row += 1;
+
+ if (startmv.as_mv.col & 7)
+ {
+ this_mv.as_mv.col -= 1;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+ else
+ {
+ this_mv.as_mv.col = (startmv.as_mv.col - 8) | 7;
+ thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ }
+
+ break;
+ case 3:
+ this_mv.as_mv.col += 1;
+ this_mv.as_mv.row += 1;
+ thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse);
+ break;
+ }
+
+ diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+
+ if (diag < bestmse)
+ {
+ *bestmv = this_mv;
+ bestmse = diag;
+ *distortion = thismse;
+ *sse1 = sse;
+ }
+
+#endif /* CONFIG_HIGH_PRECISION_MV */
+
return bestmse;
}
+#undef SP
+
int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int_mv *bestmv, int_mv *ref_mv,
int error_per_bit,
@@ -664,9 +1043,9 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int whichdir ;
int thismse;
int y_stride;
+ MACROBLOCKD *xd = &x->e_mbd;
#if ARCH_X86 || ARCH_X86_64
- MACROBLOCKD *xd = &x->e_mbd;
unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
unsigned char *y;
@@ -687,13 +1066,21 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
// calculate central point error
bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
*distortion = bestmse;
+#if CONFIG_HIGH_PRECISION_MV
+ bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+#endif
// go left then right and check error
this_mv.as_mv.row = startmv.as_mv.row;
this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (left < bestmse)
{
@@ -705,7 +1092,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
this_mv.as_mv.col += 8;
thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (right < bestmse)
{
@@ -719,7 +1110,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
this_mv.as_mv.col = startmv.as_mv.col;
this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
thismse = vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (up < bestmse)
{
@@ -731,7 +1126,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
this_mv.as_mv.row += 8;
thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (down < bestmse)
{
@@ -770,7 +1169,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
break;
}
+#if CONFIG_HIGH_PRECISION_MV
+ diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv);
+#else
diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+#endif
if (diag < bestmse)
{
@@ -854,6 +1257,7 @@ int vp8_hex_search
int k = -1;
int all_in;
int best_site = -1;
+ MACROBLOCKD *xd = &x->e_mbd;
int_mv fcenter_mv;
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
@@ -1035,9 +1439,18 @@ int vp8_diamond_search_sad
unsigned char *check_here;
int thissad;
+ MACROBLOCKD *xd = &x->e_mbd;
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1115,7 +1528,11 @@ int vp8_diamond_search_sad
return INT_MAX;
return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
}
int vp8_diamond_search_sadx4
@@ -1156,9 +1573,18 @@ int vp8_diamond_search_sadx4
unsigned char *check_here;
unsigned int thissad;
+ MACROBLOCKD *xd = &x->e_mbd;
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1277,7 +1703,11 @@ int vp8_diamond_search_sadx4
return INT_MAX;
return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
}
int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
@@ -1298,6 +1728,7 @@ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
unsigned char *check_here;
int thissad;
+ MACROBLOCKD *xd = &x->e_mbd;
int ref_row = ref_mv->as_mv.row;
int ref_col = ref_mv->as_mv.col;
@@ -1309,6 +1740,14 @@ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1367,7 +1806,11 @@ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
if (bestsad < INT_MAX)
return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
else
return INT_MAX;
}
@@ -1390,6 +1833,7 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
unsigned char *check_here;
unsigned int thissad;
+ MACROBLOCKD *xd = &x->e_mbd;
int ref_row = ref_mv->as_mv.row;
int ref_col = ref_mv->as_mv.col;
@@ -1403,6 +1847,14 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1497,7 +1949,11 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
if (bestsad < INT_MAX)
return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
else
return INT_MAX;
}
@@ -1520,6 +1976,7 @@ int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
unsigned char *check_here;
unsigned int thissad;
+ MACROBLOCKD *xd = &x->e_mbd;
int ref_row = ref_mv->as_mv.row;
int ref_col = ref_mv->as_mv.col;
@@ -1534,6 +1991,14 @@ int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1657,7 +2122,11 @@ int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
if (bestsad < INT_MAX)
return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
else
return INT_MAX;
}
@@ -1680,10 +2149,19 @@ int vp8_refining_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
unsigned int thissad;
int_mv this_mv;
unsigned int bestsad = INT_MAX;
+ MACROBLOCKD *xd = &x->e_mbd;
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
+
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1734,7 +2212,11 @@ int vp8_refining_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
if (bestsad < INT_MAX)
return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
else
return INT_MAX;
}
@@ -1757,10 +2239,19 @@ int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
unsigned int thissad;
int_mv this_mv;
unsigned int bestsad = INT_MAX;
+ MACROBLOCKD *xd = &x->e_mbd;
int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
int_mv fcenter_mv;
+#if CONFIG_HIGH_PRECISION_MV
+ if (xd->allow_high_precision_mv)
+ {
+ mvsadcost[0] = x->mvsadcost_hp[0];
+ mvsadcost[1] = x->mvsadcost_hp[1];
+ }
+#endif
+
fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
@@ -1847,46 +2338,37 @@ int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
if (bestsad < INT_MAX)
return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+#if CONFIG_HIGH_PRECISION_MV
+ + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv);
+#else
+ mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+#endif
else
return INT_MAX;
}
+
+
#ifdef ENTROPY_STATS
void print_mode_context(void)
{
- FILE *f = fopen("modecont.c", "w");
+ FILE *f = fopen("modecont.c", "a");
int i, j;
fprintf(f, "#include \"entropy.h\"\n");
- fprintf(f, "const int vp8_mode_contexts[6][4] =\n");
+ fprintf(f, "const int vp8_mode_contexts[6][4] =");
fprintf(f, "{\n");
-
for (j = 0; j < 6; j++)
{
- fprintf(f, " { // %d \n", j);
+ fprintf(f, " {/* %d */ ", j);
fprintf(f, " ");
-
for (i = 0; i < 4; i++)
{
- int overal_prob;
int this_prob;
- int count; // = mv_ref_ct[j][i][0]+mv_ref_ct[j][i][1];
-
- // Overall probs
- count = mv_mode_cts[i][0] + mv_mode_cts[i][1];
-
- if (count)
- overal_prob = 256 * mv_mode_cts[i][0] / count;
- else
- overal_prob = 128;
-
- if (overal_prob == 0)
- overal_prob = 1;
+ int count;
// context probs
count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
-
if (count)
this_prob = 256 * mv_ref_ct[j][i][0] / count;
else
@@ -1894,12 +2376,8 @@ void print_mode_context(void)
if (this_prob == 0)
this_prob = 1;
-
fprintf(f, "%5d, ", this_prob);
- //fprintf(f,"%5d, %5d, %8d,", this_prob, overal_prob, (this_prob << 10)/overal_prob);
- //fprintf(f,"%8d, ", (this_prob << 10)/overal_prob);
}
-
fprintf(f, " },\n");
}
@@ -1908,7 +2386,6 @@ void print_mode_context(void)
}
/* MV ref count ENTROPY_STATS stats code */
-#ifdef ENTROPY_STATS
void init_mv_ref_counts()
{
vpx_memset(mv_ref_ct, 0, sizeof(mv_ref_ct));
@@ -1963,5 +2440,3 @@ void accum_mv_refs(MB_PREDICTION_MODE m, const int ct[4])
}
#endif/* END MV ref count ENTROPY_STATS stats code */
-
-#endif
diff --git a/vp8/encoder/mcomp.h b/vp8/encoder/mcomp.h
index 416c4d5eb..f1314533f 100644
--- a/vp8/encoder/mcomp.h
+++ b/vp8/encoder/mcomp.h
@@ -25,8 +25,11 @@ extern void accum_mv_refs(MB_PREDICTION_MODE, const int near_mv_ref_cts[4]);
#define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS)) - 1) // Max full pel mv specified in 1 pel units
#define MAX_FIRST_STEP (1 << (MAX_MVSEARCH_STEPS-1)) // Maximum size of the first step in full pel units
-extern void print_mode_context(void);
+#if CONFIG_HIGH_PRECISION_MV
+extern int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight, int ishp);
+#else
extern int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight);
+#endif
extern void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride);
extern void vp8_init3smotion_compensation(MACROBLOCK *x, int stride);
diff --git a/vp8/encoder/modecosts.c b/vp8/encoder/modecosts.c
index c636c482b..b6f77e1a1 100644
--- a/vp8/encoder/modecosts.c
+++ b/vp8/encoder/modecosts.c
@@ -37,11 +37,30 @@ void vp8_init_mode_costs(VP8_COMP *c)
vp8_cost_tokens((int *)c->mb.inter_bmode_costs, x->fc.bmode_prob, T);
}
- vp8_cost_tokens((int *)c->mb.inter_bmode_costs, x->fc.sub_mv_ref_prob, vp8_sub_mv_ref_tree);
+ vp8_cost_tokens((int *)c->mb.inter_bmode_costs,
+ x->fc.sub_mv_ref_prob, vp8_sub_mv_ref_tree);
vp8_cost_tokens(c->mb.mbmode_cost[1], x->fc.ymode_prob, vp8_ymode_tree);
- vp8_cost_tokens(c->mb.mbmode_cost[0], x->kf_ymode_prob, vp8_kf_ymode_tree);
+#if CONFIG_QIMODE
+ vp8_cost_tokens(c->mb.mbmode_cost[0],
+ x->kf_ymode_prob[c->common.kf_ymode_probs_index],
+ vp8_kf_ymode_tree);
+#else
+ vp8_cost_tokens(c->mb.mbmode_cost[0],
+ x->kf_ymode_prob, vp8_kf_ymode_tree);
+#endif
+#if CONFIG_UVINTRA
+ vp8_cost_tokens(c->mb.intra_uv_mode_cost[1],
+ x->fc.uv_mode_prob[VP8_YMODES-1], vp8_uv_mode_tree);
+ vp8_cost_tokens(c->mb.intra_uv_mode_cost[0],
+ x->kf_uv_mode_prob[VP8_YMODES-1], vp8_uv_mode_tree);
+#else
+ vp8_cost_tokens(c->mb.intra_uv_mode_cost[1],
+ x->fc.uv_mode_prob, vp8_uv_mode_tree);
+ vp8_cost_tokens(c->mb.intra_uv_mode_cost[0],
+ x->kf_uv_mode_prob, vp8_uv_mode_tree);
+#endif
+ vp8_cost_tokens(c->mb.i8x8_mode_costs,
+ x->i8x8_mode_prob,vp8_i8x8_mode_tree);
- vp8_cost_tokens(c->mb.intra_uv_mode_cost[1], x->fc.uv_mode_prob, vp8_uv_mode_tree);
- vp8_cost_tokens(c->mb.intra_uv_mode_cost[0], x->kf_uv_mode_prob, vp8_uv_mode_tree);
}
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index bf155e250..0d126067e 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -30,9 +30,13 @@
#endif
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/swapyv12buffer.h"
-#include "vp8/common/threading.h"
#include "vpx_ports/vpx_timer.h"
#include "temporal_filter.h"
+
+#include "vp8/common/seg_common.h"
+#include "mbgraph.h"
+#include "vp8/common/pred_common.h"
+
#if ARCH_ARM
#include "vpx_ports/arm.h"
#endif
@@ -75,6 +79,14 @@ static void set_default_lf_deltas(VP8_COMP *cpi);
extern const int vp8_gf_interval_table[101];
+#if CONFIG_HIGH_PRECISION_MV
+#define ALTREF_HIGH_PRECISION_MV 1 /* whether to use high precision mv for altref computation */
+#define HIGH_PRECISION_MV_QTHRESH 200 /* Q threshold for use of high precision mv */
+ /* Choose a very high value for now so
+ * that HIGH_PRECISION is always chosen
+ */
+#endif
+
#if CONFIG_INTERNAL_STATS
#include "math.h"
@@ -101,10 +113,14 @@ extern double vp8_calc_ssimg
#endif
+//#define OUTPUT_YUV_REC
#ifdef OUTPUT_YUV_SRC
FILE *yuv_file;
#endif
+#ifdef OUTPUT_YUV_REC
+FILE *yuv_rec_file;
+#endif
#if 0
FILE *framepsnr;
@@ -130,164 +146,131 @@ unsigned int tot_ef = 0;
unsigned int cnt_ef = 0;
#endif
+#if defined(SECTIONBITS_OUTPUT)
+extern unsigned __int64 Sectionbits[500];
+#endif
#ifdef MODE_STATS
-extern unsigned __int64 Sectionbits[50];
-extern int y_modes[5] ;
-extern int uv_modes[4] ;
-extern int b_modes[10] ;
-
-extern int inter_y_modes[10] ;
-extern int inter_uv_modes[4] ;
-extern unsigned int inter_b_modes[15];
+extern INT64 Sectionbits[500];
+extern int y_modes[VP8_YMODES] ;
+extern int i8x8_modes[VP8_I8X8_MODES];
+extern int uv_modes[VP8_UV_MODES] ;
+extern int uv_modes_y[VP8_YMODES][VP8_UV_MODES];
+extern int b_modes[B_MODE_COUNT];
+extern int inter_y_modes[MB_MODE_COUNT] ;
+extern int inter_uv_modes[VP8_UV_MODES] ;
+extern unsigned int inter_b_modes[B_MODE_COUNT];
#endif
extern void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
extern void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
-extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
-
-extern const int qrounding_factors[129];
-extern const int qzbin_factors[129];
extern void vp8cx_init_quantizer(VP8_COMP *cpi);
-extern const int vp8cx_base_skip_false_prob[128];
-#if !CONFIG_EXTEND_QRANGE
+
+int vp8cx_base_skip_false_prob[QINDEX_RANGE];
+
// Tables relating active max Q to active min Q
-static const int kf_low_motion_minq[QINDEX_RANGE] =
-{
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,
- 3,3,3,3,3,3,4,4,4,5,5,5,5,5,6,6,
- 6,6,7,7,8,8,8,8,9,9,10,10,10,10,11,11,
- 11,11,12,12,13,13,13,13,14,14,15,15,15,15,16,16,
- 16,16,17,17,18,18,18,18,19,20,20,21,21,22,23,23
-};
-static const int kf_high_motion_minq[QINDEX_RANGE] =
-{
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 1,1,1,1,1,1,1,1,2,2,2,2,3,3,3,3,
- 3,3,3,3,4,4,4,4,5,5,5,5,5,5,6,6,
- 6,6,7,7,8,8,8,8,9,9,10,10,10,10,11,11,
- 11,11,12,12,13,13,13,13,14,14,15,15,15,15,16,16,
- 16,16,17,17,18,18,18,18,19,19,20,20,20,20,21,21,
- 21,21,22,22,23,23,24,25,25,26,26,27,28,28,29,30
-};
-static const int gf_low_motion_minq[QINDEX_RANGE] =
-{
- 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,
- 3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,
- 7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,
- 11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,
- 19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,
- 27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,
- 35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,
- 43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58
-};
-static const int gf_mid_motion_minq[QINDEX_RANGE] =
+static int kf_low_motion_minq[QINDEX_RANGE];
+static int kf_high_motion_minq[QINDEX_RANGE];
+static int gf_low_motion_minq[QINDEX_RANGE];
+static int gf_mid_motion_minq[QINDEX_RANGE];
+static int gf_high_motion_minq[QINDEX_RANGE];
+static int inter_minq[QINDEX_RANGE];
+
+// Functions to compute the active minq lookup table entries based on a
+// formulaic approach to facilitate easier adjustment of the Q tables.
+// The formulae were derived from computing a 3rd order polynomial best
+// fit to the original data (after plotting real maxq vs minq (not q index))
+int calculate_minq_index( double maxq,
+ double x3, double x2, double x, double c )
{
- 0,0,0,0,1,1,1,1,1,1,2,2,3,3,3,4,
- 4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,
- 9,10,10,10,10,11,11,11,12,12,12,12,13,13,13,14,
- 14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,
- 22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,
- 30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,
- 38,39,39,40,40,41,41,42,42,43,43,44,45,46,47,48,
- 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
-};
-static const int gf_high_motion_minq[QINDEX_RANGE] =
-{
- 0,0,0,0,1,1,1,1,1,2,2,2,3,3,3,4,
- 4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,
- 9,10,10,10,11,11,12,12,13,13,14,14,15,15,16,16,
- 17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,
- 25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,
- 33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,
- 41,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,
- 55,56,57,58,59,60,62,64,66,68,70,72,74,76,78,80
-};
-static const int inter_minq[QINDEX_RANGE] =
-{
- 0,0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,
- 9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,20,
- 20,21,22,22,23,24,24,25,26,27,27,28,29,30,30,31,
- 32,33,33,34,35,36,36,37,38,39,39,40,41,42,42,43,
- 44,45,46,46,47,48,49,50,50,51,52,53,54,55,55,56,
- 57,58,59,60,60,61,62,63,64,65,66,67,67,68,69,70,
- 71,72,73,74,75,75,76,77,78,79,80,81,82,83,84,85,
- 86,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
-};
-#else
-static const int kf_low_motion_minq[QINDEX_RANGE] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8,
- 9, 9, 9, 10,10,11,11,12,12,13,13,14,14,15,15,16,
- 16,17,17,18,18,19,19,20,20,21,21,22,23,23,24,24,
- 25,25,26,27,28,29,30,30,31,32,33,34,35,35,36,36,
- 38,38,39,40,40,41,42,42,43,44,44,45,46,46,47,48,
- 49,49,50,50,51,52,52,53,54,55,56,57,58,59,60,61,
-};
-static const int kf_high_motion_minq[QINDEX_RANGE] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2,
- 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6,
- 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9,10,10,
- 11,11,12,13,14,15,16,17,18,19,20,21,22,23,24,24,
- 25,26,27,28,28,29,29,30,30,31,31,32,33,33,34,34,
- 35,36,37,38,39,39,40,41,41,42,43,44,45,45,46,46,
- 47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,
- 55,55,56,56,57,58,59,60,61,62,63,64,65,67,69,70,
-};
+ int i;
+ double minqtarget;
+ double thisq;
-static const int gf_low_motion_minq[QINDEX_RANGE] =
-{
- 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4,
- 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9,
- 10,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,
- 17,18,18,19,19,20,21,22,23,24,25,26,27,29,29,30,
- 31,32,33,34,35,36,37,38,39,40,41,41,42,42,43,43,
- 44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,
- 52,52,53,53,54,54,55,55,56,56,57,57,58,59,60,61,
- 62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
-};
-static const int gf_mid_motion_minq[QINDEX_RANGE] =
-{
- 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4,
- 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9,10,
- 10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,
- 18,19,19,20,20,21,22,23,24,25,26,27,28,29,30,31,
- 32,33,34,35,35,36,36,37,37,38,38,39,39,40,40,41,
- 41,42,42,43,43,44,44,45,45,46,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,
-};
-static const int gf_high_motion_minq[QINDEX_RANGE] =
+ minqtarget = ( (x3 * maxq * maxq * maxq) +
+ (x2 * maxq * maxq) +
+ (x * maxq) +
+ c );
+
+ if ( minqtarget > maxq )
+ minqtarget = maxq;
+
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ thisq = vp8_convert_qindex_to_q(i);
+ if ( minqtarget <= vp8_convert_qindex_to_q(i) )
+ return i;
+ }
+ if ( i == QINDEX_RANGE )
+ return QINDEX_RANGE-1;
+}
+void init_minq_luts()
{
- 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4,
- 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9,10,10,
- 11,11,12,12,13,14,15,16,17,18,18,19,19,20,20,21,
- 22,23,24,25,26,26,27,28,29,30,31,32,33,34,35,36,
- 37,38,39,39,40,40,40,41,41,41,42,42,43,43,44,44,
- 44,45,45,45,46,46,47,47,47,48,48,48,49,49,49,50,
- 50,50,51,51,52,53,54,54,55,56,57,57,58,59,60,61,
- 62,63,64,66,68,69,72,74,77,80,82,85,87,89,91,93,
-};
+ int i;
+ double maxq;
+
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ maxq = vp8_convert_qindex_to_q(i);
+
+
+ kf_low_motion_minq[i] = calculate_minq_index( maxq,
+ 0.0000003,
+ -0.000015,
+ 0.074,
+ 0.0 );
+
+ kf_high_motion_minq[i] = calculate_minq_index( maxq,
+ 0.00000034,
+ -0.000125,
+ 0.13,
+ 0.0 );
+ gf_low_motion_minq[i] = calculate_minq_index( maxq,
+ 0.0000016,
+ -0.00078,
+ 0.315,
+ 0.0 );
+ gf_mid_motion_minq[i] = calculate_minq_index( maxq,
+ 0.00000415,
+ -0.0017,
+ 0.425,
+ 0.0 );
+ gf_high_motion_minq[i] = calculate_minq_index( maxq,
+ 0.00000725,
+ -0.00235,
+ 0.47,
+ 0.0 );
+ inter_minq[i] = calculate_minq_index( maxq,
+ 0.00000271,
+ -0.00113,
+ 0.697,
+ 0.0 );
+
+ }
+}
-static const int inter_minq[QINDEX_RANGE] =
+void init_base_skip_probs()
{
- 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
- 8, 9,10,11,12,13,14,15,16,17,18,18,19,19,20,21,
- 21,22,23,23,24,25,26,26,27,28,29,30,31,32,32,33,
- 34,35,36,36,37,38,39,40,40,41,41,42,43,44,44,45,
- 46,46,47,47,48,49,49,50,50,51,52,52,53,54,54,55,
- 55,56,57,57,58,59,60,60,61,62,63,63,64,65,66,67,
- 68,68,69,70,71,72,72,73,74,75,76,77,78,79,80,81,
- 81,82,83,84,85,86,87,88,89,90,90,91,92,93,94,95,
-};
-#endif
+ int i;
+ double q;
+ int skip_prob;
+
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ q = vp8_convert_qindex_to_q(i);
+
+ // Exponential decay caluclation of baseline skip prob with clamping
+ // Based on crude best fit of old table.
+ skip_prob = (int)( 564.25 * pow( 2.71828, (-0.012*q) ) );
+ if ( skip_prob < 1 )
+ skip_prob = 1;
+ else if ( skip_prob > 255 )
+ skip_prob = 255;
+
+ vp8cx_base_skip_false_prob[i] = skip_prob;
+ }
+}
+
void vp8_initialize()
{
static int init_done = 0;
@@ -298,7 +281,10 @@ void vp8_initialize()
vp8_initialize_common();
//vp8_dmachine_specific_config();
vp8_tokenize_initialize();
-
+ vp8_init_quant_tables();
+ vp8_init_me_luts();
+ init_minq_luts();
+ init_base_skip_probs();
init_done = 1;
}
}
@@ -308,19 +294,24 @@ extern FILE *vpxlogc;
static void setup_features(VP8_COMP *cpi)
{
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
+
// Set up default state for MB feature flags
- cpi->mb.e_mbd.segmentation_enabled = 0;
- cpi->mb.e_mbd.update_mb_segmentation_map = 0;
- cpi->mb.e_mbd.update_mb_segmentation_data = 0;
- vpx_memset(cpi->mb.e_mbd.mb_segment_tree_probs, 255, sizeof(cpi->mb.e_mbd.mb_segment_tree_probs));
- vpx_memset(cpi->mb.e_mbd.segment_feature_data, 0, sizeof(cpi->mb.e_mbd.segment_feature_data));
-
- cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 0;
- cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
- vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
- vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
- vpx_memset(cpi->mb.e_mbd.last_ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
- vpx_memset(cpi->mb.e_mbd.last_mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+
+ xd->segmentation_enabled = 0; // Default segmentation disabled
+
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 0;
+ vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
+
+ clearall_segfeatures( xd );
+
+ xd->mode_ref_lf_delta_enabled = 0;
+ xd->mode_ref_lf_delta_update = 0;
+ vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
+ vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
+ vpx_memset(xd->last_ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
+ vpx_memset(xd->last_mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
set_default_lf_deltas(cpi);
@@ -345,6 +336,8 @@ static void dealloc_compressor_data(VP8_COMP *cpi)
// Delete sementation map
vpx_free(cpi->segmentation_map);
cpi->segmentation_map = 0;
+ vpx_free(cpi->common.last_frame_seg_map);
+ cpi->common.last_frame_seg_map = 0;
vpx_free(cpi->active_map);
cpi->active_map = 0;
@@ -374,212 +367,239 @@ static void dealloc_compressor_data(VP8_COMP *cpi)
vpx_free(cpi->mb.pip);
cpi->mb.pip = 0;
-#if !(CONFIG_REALTIME_ONLY)
vpx_free(cpi->twopass.total_stats);
cpi->twopass.total_stats = 0;
+ vpx_free(cpi->twopass.total_left_stats);
+ cpi->twopass.total_left_stats = 0;
+
vpx_free(cpi->twopass.this_frame_stats);
cpi->twopass.this_frame_stats = 0;
-#endif
-}
-
-static void enable_segmentation(VP8_PTR ptr)
-{
- VP8_COMP *cpi = (VP8_COMP *)(ptr);
-
- // Set the appropriate feature bit
- cpi->mb.e_mbd.segmentation_enabled = 1;
- cpi->mb.e_mbd.update_mb_segmentation_map = 1;
- cpi->mb.e_mbd.update_mb_segmentation_data = 1;
-}
-static void disable_segmentation(VP8_PTR ptr)
-{
- VP8_COMP *cpi = (VP8_COMP *)(ptr);
-
- // Clear the appropriate feature bit
- cpi->mb.e_mbd.segmentation_enabled = 0;
}
-// Valid values for a segment are 0 to 3
-// Segmentation map is arrange as [Rows][Columns]
-static void set_segmentation_map(VP8_PTR ptr, unsigned char *segmentation_map)
+// Computes a q delta (in "q index" terms) to get from a starting q value
+// to a target value
+// target q value
+static int compute_qdelta( VP8_COMP *cpi, double qstart, double qtarget )
{
- VP8_COMP *cpi = (VP8_COMP *)(ptr);
-
- // Copy in the new segmentation map
- vpx_memcpy(cpi->segmentation_map, segmentation_map, (cpi->common.mb_rows * cpi->common.mb_cols));
+ int i;
+ int start_index = cpi->worst_quality;
+ int target_index = cpi->worst_quality;
+ int retval = 0;
- // Signal that the map should be updated.
- cpi->mb.e_mbd.update_mb_segmentation_map = 1;
- cpi->mb.e_mbd.update_mb_segmentation_data = 1;
-}
+ // Convert the average q value to an index.
+ for ( i = cpi->best_quality; i < cpi->worst_quality; i++ )
+ {
+ start_index = i;
+ if ( vp8_convert_qindex_to_q(i) >= qstart )
+ break;
+ }
-// The values given for each segment can be either deltas (from the default value chosen for the frame) or absolute values.
-//
-// Valid range for abs values is (0-127 for MB_LVL_ALT_Q) , (0-63 for SEGMENT_ALT_LF)
-// Valid range for delta values are (+/-127 for MB_LVL_ALT_Q) , (+/-63 for SEGMENT_ALT_LF)
-//
-// abs_delta = SEGMENT_DELTADATA (deltas) abs_delta = SEGMENT_ABSDATA (use the absolute values given).
-//
-//
-static void set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned char abs_delta)
-{
- VP8_COMP *cpi = (VP8_COMP *)(ptr);
+ // Convert the q target to an index
+ for ( i = cpi->best_quality; i < cpi->worst_quality; i++ )
+ {
+ target_index = i;
+ if ( vp8_convert_qindex_to_q(i) >= qtarget )
+ break;
+ }
- cpi->mb.e_mbd.mb_segement_abs_delta = abs_delta;
- vpx_memcpy(cpi->segment_feature_data, feature_data, sizeof(cpi->segment_feature_data));
+ return target_index - start_index;
}
-
-static void segmentation_test_function(VP8_PTR ptr)
+static void init_seg_features(VP8_COMP *cpi)
{
- VP8_COMP *cpi = (VP8_COMP *)(ptr);
-
- unsigned char *seg_map;
- signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+ VP8_COMMON *cm = &cpi->common;
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
- // Create a temporary map for segmentation data.
- CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+ int high_q = (int)(cpi->avg_q > 48.0);
+ int qi_delta;
- // MB loop to set local segmentation map
- /*for ( i = 0; i < cpi->common.mb_rows; i++ )
+ // Disable and clear down for KF
+ if ( cm->frame_type == KEY_FRAME )
{
- for ( j = 0; j < cpi->common.mb_cols; j++ )
- {
- //seg_map[(i*cpi->common.mb_cols) + j] = (j % 2) + ((i%2)* 2);
- //if ( j < cpi->common.mb_cols/2 )
-
- // Segment 1 around the edge else 0
- if ( (i == 0) || (j == 0) || (i == (cpi->common.mb_rows-1)) || (j == (cpi->common.mb_cols-1)) )
- seg_map[(i*cpi->common.mb_cols) + j] = 1;
- //else if ( (i < 2) || (j < 2) || (i > (cpi->common.mb_rows-3)) || (j > (cpi->common.mb_cols-3)) )
- // seg_map[(i*cpi->common.mb_cols) + j] = 2;
- //else if ( (i < 5) || (j < 5) || (i > (cpi->common.mb_rows-6)) || (j > (cpi->common.mb_cols-6)) )
- // seg_map[(i*cpi->common.mb_cols) + j] = 3;
- else
- seg_map[(i*cpi->common.mb_cols) + j] = 0;
- }
- }*/
-
- // Set the segmentation Map
- set_segmentation_map(ptr, seg_map);
+ // Clear down the global segmentation map
+ vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 0;
+ cpi->static_mb_pct = 0;
- // Activate segmentation.
- enable_segmentation(ptr);
+ // Disable segmentation
+ vp8_disable_segmentation((VP8_PTR)cpi);
- // Set up the quant segment data
- feature_data[MB_LVL_ALT_Q][0] = 0;
- feature_data[MB_LVL_ALT_Q][1] = 4;
- feature_data[MB_LVL_ALT_Q][2] = 0;
- feature_data[MB_LVL_ALT_Q][3] = 0;
- // Set up the loop segment data
- feature_data[MB_LVL_ALT_LF][0] = 0;
- feature_data[MB_LVL_ALT_LF][1] = 0;
- feature_data[MB_LVL_ALT_LF][2] = 0;
- feature_data[MB_LVL_ALT_LF][3] = 0;
+ // Clear down the segment features.
+ clearall_segfeatures(xd);
+ }
- // Initialise the feature data structure
- // SEGMENT_DELTADATA 0, SEGMENT_ABSDATA 1
- set_segment_data(ptr, &feature_data[0][0], SEGMENT_DELTADATA);
+ // If this is an alt ref frame
+ else if ( cm->refresh_alt_ref_frame )
+ {
+ // Clear down the global segmentation map
+ vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 0;
+ cpi->static_mb_pct = 0;
- // Delete sementation map
- vpx_free(seg_map);
+ // Disable segmentation and individual segment features by default
+ vp8_disable_segmentation((VP8_PTR)cpi);
+ clearall_segfeatures(xd);
- seg_map = 0;
+ // Scan frames from current to arf frame.
+ // This function re-enables segmentation if appropriate.
+ vp8_update_mbgraph_stats(cpi);
-}
+ // If segmentation was enabled set those features needed for the
+ // arf itself.
+ if ( xd->segmentation_enabled )
+ {
+ xd->update_mb_segmentation_map = 1;
+ xd->update_mb_segmentation_data = 1;
-// A simple function to cyclically refresh the background at a lower Q
-static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment)
-{
- unsigned char *seg_map;
- signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
- int i;
- int block_count = cpi->cyclic_refresh_mode_max_mbs_perframe;
- int mbs_in_frame = cpi->common.mb_rows * cpi->common.mb_cols;
+ qi_delta = compute_qdelta( cpi, cpi->avg_q, (cpi->avg_q * 0.875) );
+ set_segdata( xd, 1, SEG_LVL_ALT_Q, (qi_delta - 2) );
+ set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
- // Create a temporary map for segmentation data.
- CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+ enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
+ enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
- cpi->cyclic_refresh_q = Q;
+ // Where relevant assume segment data is delta data
+ xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
- for (i = Q; i > 0; i--)
- {
- if (vp8_bits_per_mb[cpi->common.frame_type][i] >= ((vp8_bits_per_mb[cpi->common.frame_type][Q]*(Q + 128)) / 64))
- //if ( vp8_bits_per_mb[cpi->common.frame_type][i] >= ((vp8_bits_per_mb[cpi->common.frame_type][Q]*((2*Q)+96))/64) )
- {
- break;
}
}
-
- cpi->cyclic_refresh_q = i;
-
- // Only update for inter frames
- if (cpi->common.frame_type != KEY_FRAME)
+ // All other frames if segmentation has been enabled
+ else if ( xd->segmentation_enabled )
{
- // Cycle through the macro_block rows
- // MB loop to set local segmentation map
- for (i = cpi->cyclic_refresh_mode_index; i < mbs_in_frame; i++)
+/*
+ int i;
+
+ // clears prior frame seg lev refs
+ for (i = 0; i < MAX_MB_SEGMENTS; i++)
{
- // If the MB is as a candidate for clean up then mark it for possible boost/refresh (segment 1)
- // The segment id may get reset to 0 later if the MB gets coded anything other than last frame 0,0
- // as only (last frame 0,0) MBs are eligable for refresh : that is to say Mbs likely to be background blocks.
- if (cpi->cyclic_refresh_map[i] == 0)
+ // only do it if the force drop the background stuff is off
+ if(!segfeature_active(xd, i, SEG_LVL_MODE))
{
- seg_map[i] = 1;
+ disable_segfeature(xd,i,SEG_LVL_REF_FRAME);
+ set_segdata( xd,i, SEG_LVL_REF_FRAME, 0xffffff);
}
- else
+ }
+*/
+
+ // First normal frame in a valid gf or alt ref group
+ if ( cpi->common.frames_since_golden == 0 )
+ {
+ // Set up segment features for normal frames in an af group
+ if ( cpi->source_alt_ref_active )
{
- seg_map[i] = 0;
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 1;
+ xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
- // Skip blocks that have been refreshed recently anyway.
- if (cpi->cyclic_refresh_map[i] < 0)
- //cpi->cyclic_refresh_map[i] = cpi->cyclic_refresh_map[i] / 16;
- cpi->cyclic_refresh_map[i]++;
- }
+ qi_delta = compute_qdelta( cpi, cpi->avg_q,
+ (cpi->avg_q * 1.125) );
+ set_segdata( xd, 1, SEG_LVL_ALT_Q, (qi_delta + 2) );
+ set_segdata( xd, 1, SEG_LVL_ALT_Q, 0 );
+ enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
+ set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
+ enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
- if (block_count > 0)
- block_count--;
- else
- break;
+ // Segment coding disabled for compred testing
+ if ( high_q || (cpi->static_mb_pct == 100) )
+ {
+ //set_segref(xd, 1, LAST_FRAME);
+ set_segref(xd, 1, ALTREF_FRAME);
+ enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
- }
+ set_segdata( xd, 1, SEG_LVL_MODE, ZEROMV );
+ enable_segfeature(xd, 1, SEG_LVL_MODE);
- // If we have gone through the frame reset to the start
- cpi->cyclic_refresh_mode_index = i;
+ // EOB segment coding not fixed for 8x8 yet
+ set_segdata( xd, 1, SEG_LVL_EOB, 0 );
+ enable_segfeature(xd, 1, SEG_LVL_EOB);
+ }
+ }
+ // Disable segmentation and clear down features if alt ref
+ // is not active for this group
+ else
+ {
+ vp8_disable_segmentation((VP8_PTR)cpi);
- if (cpi->cyclic_refresh_mode_index >= mbs_in_frame)
- cpi->cyclic_refresh_mode_index = 0;
- }
+ vpx_memset( cpi->segmentation_map, 0,
+ (cm->mb_rows * cm->mb_cols));
- // Set the segmentation Map
- set_segmentation_map((VP8_PTR)cpi, seg_map);
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 0;
- // Activate segmentation.
- enable_segmentation((VP8_PTR)cpi);
+ clearall_segfeatures(xd);
+ }
+ }
- // Set up the quant segment data
- feature_data[MB_LVL_ALT_Q][0] = 0;
- feature_data[MB_LVL_ALT_Q][1] = (cpi->cyclic_refresh_q - Q);
- feature_data[MB_LVL_ALT_Q][2] = 0;
- feature_data[MB_LVL_ALT_Q][3] = 0;
+ // Special case where we are coding over the top of a previous
+ // alt ref frame
+ // Segment coding disabled for compred testing
+ else if ( cpi->is_src_frame_alt_ref )
+ {
+ // Enable mode and ref frame features for segment 0 as well
+ enable_segfeature(xd, 0, SEG_LVL_REF_FRAME);
+ enable_segfeature(xd, 0, SEG_LVL_MODE);
+ enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
+ enable_segfeature(xd, 1, SEG_LVL_MODE);
+
+ // All mbs should use ALTREF_FRAME, ZEROMV exclusively
+ clear_segref(xd, 0);
+ set_segref(xd, 0, ALTREF_FRAME);
+ clear_segref(xd, 1);
+ set_segref(xd, 1, ALTREF_FRAME);
+ set_segdata( xd, 0, SEG_LVL_MODE, ZEROMV );
+ set_segdata( xd, 1, SEG_LVL_MODE, ZEROMV );
+
+ // Skip all MBs if high Q
+ if ( high_q )
+ {
+ enable_segfeature(xd, 0, SEG_LVL_EOB);
+ set_segdata( xd, 0, SEG_LVL_EOB, 0 );
+ enable_segfeature(xd, 1, SEG_LVL_EOB);
+ set_segdata( xd, 1, SEG_LVL_EOB, 0 );
+ }
+ // Enable data udpate
+ xd->update_mb_segmentation_data = 1;
+ }
+ // All other frames.
+ else
+ {
+ // No updeates.. leave things as they are.
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 0;
+ }
+ }
+}
- // Set up the loop segment data
- feature_data[MB_LVL_ALT_LF][0] = 0;
- feature_data[MB_LVL_ALT_LF][1] = lf_adjustment;
- feature_data[MB_LVL_ALT_LF][2] = 0;
- feature_data[MB_LVL_ALT_LF][3] = 0;
+// DEBUG: Print out the segment id of each MB in the current frame.
+static void print_seg_map(VP8_COMP *cpi)
+{
+ VP8_COMMON *cm = & cpi->common;
+ int row,col;
+ int map_index = 0;
+ FILE *statsfile;
- // Initialise the feature data structure
- // SEGMENT_DELTADATA 0, SEGMENT_ABSDATA 1
- set_segment_data((VP8_PTR)cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+ statsfile = fopen("segmap.stt", "a");
- // Delete sementation map
- vpx_free(seg_map);
+ fprintf(statsfile, "%10d\n",
+ cm->current_video_frame );
- seg_map = 0;
+ for ( row = 0; row < cpi->common.mb_rows; row++ )
+ {
+ for ( col = 0; col < cpi->common.mb_cols; col++ )
+ {
+ fprintf(statsfile, "%10d",
+ cpi->segmentation_map[map_index]);
+ map_index++;
+ }
+ fprintf(statsfile, "\n");
+ }
+ fprintf(statsfile, "\n");
+ fclose(statsfile);
}
static void set_default_lf_deltas(VP8_COMP *cpi)
@@ -611,6 +631,10 @@ void vp8_set_speed_features(VP8_COMP *cpi)
VP8_COMMON *cm = &cpi->common;
int last_improved_quant = sf->improved_quant;
+ // Only modes 0 and 1 supported for now in experimental code basae
+ if ( Mode > 1 )
+ Mode = 1;
+
// Initialise default mode frequency sampling variables
for (i = 0; i < MAX_MODES; i ++)
{
@@ -645,7 +669,6 @@ void vp8_set_speed_features(VP8_COMP *cpi)
switch (Mode)
{
-#if !(CONFIG_REALTIME_ONLY)
case 0: // best quality mode
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROG ] = 0;
@@ -662,6 +685,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_V_PRED ] = 1000;
sf->thresh_mult[THR_H_PRED ] = 1000;
sf->thresh_mult[THR_B_PRED ] = 2000;
+ sf->thresh_mult[THR_I8X8_PRED] = 2000;
sf->thresh_mult[THR_TM ] = 1000;
sf->thresh_mult[THR_NEWMV ] = 1000;
@@ -672,12 +696,24 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_SPLITG ] = 5000;
sf->thresh_mult[THR_SPLITA ] = 5000;
+ sf->thresh_mult[THR_COMP_ZEROLG ] = 0;
+ sf->thresh_mult[THR_COMP_NEARESTLG] = 0;
+ sf->thresh_mult[THR_COMP_NEARLG ] = 0;
+ sf->thresh_mult[THR_COMP_ZEROLA ] = 0;
+ sf->thresh_mult[THR_COMP_NEARESTLA] = 0;
+ sf->thresh_mult[THR_COMP_NEARLA ] = 0;
+ sf->thresh_mult[THR_COMP_ZEROGA ] = 0;
+ sf->thresh_mult[THR_COMP_NEARESTGA] = 0;
+ sf->thresh_mult[THR_COMP_NEARGA ] = 0;
+
+ sf->thresh_mult[THR_COMP_NEWLG ] = 1000;
+ sf->thresh_mult[THR_COMP_NEWLA ] = 1000;
+ sf->thresh_mult[THR_COMP_NEWGA ] = 1000;
sf->first_step = 0;
sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
break;
case 1:
- case 3:
sf->thresh_mult[THR_NEARESTMV] = 0;
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_DC ] = 0;
@@ -685,6 +721,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_V_PRED ] = 1000;
sf->thresh_mult[THR_H_PRED ] = 1000;
sf->thresh_mult[THR_B_PRED ] = 2500;
+ sf->thresh_mult[THR_I8X8_PRED] = 2500;
sf->thresh_mult[THR_TM ] = 1000;
sf->thresh_mult[THR_NEARESTG ] = 1000;
@@ -695,7 +732,6 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_NEARG ] = 1000;
sf->thresh_mult[THR_NEARA ] = 1000;
-#if 1
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROG ] = 0;
sf->thresh_mult[THR_ZEROA ] = 0;
@@ -706,13 +742,6 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_NEARG ] = 0;
sf->thresh_mult[THR_NEARA ] = 0;
-// sf->thresh_mult[THR_DC ] = 0;
-
-// sf->thresh_mult[THR_V_PRED ] = 1000;
-// sf->thresh_mult[THR_H_PRED ] = 1000;
-// sf->thresh_mult[THR_B_PRED ] = 2000;
-// sf->thresh_mult[THR_TM ] = 1000;
-
sf->thresh_mult[THR_NEWMV ] = 1000;
sf->thresh_mult[THR_NEWG ] = 1000;
sf->thresh_mult[THR_NEWA ] = 1000;
@@ -720,15 +749,20 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_SPLITMV ] = 1700;
sf->thresh_mult[THR_SPLITG ] = 4500;
sf->thresh_mult[THR_SPLITA ] = 4500;
-#else
- sf->thresh_mult[THR_NEWMV ] = 1500;
- sf->thresh_mult[THR_NEWG ] = 1500;
- sf->thresh_mult[THR_NEWA ] = 1500;
- sf->thresh_mult[THR_SPLITMV ] = 5000;
- sf->thresh_mult[THR_SPLITG ] = 10000;
- sf->thresh_mult[THR_SPLITA ] = 10000;
-#endif
+ sf->thresh_mult[THR_COMP_ZEROLG ] = 0;
+ sf->thresh_mult[THR_COMP_NEARESTLG] = 0;
+ sf->thresh_mult[THR_COMP_NEARLG ] = 0;
+ sf->thresh_mult[THR_COMP_ZEROLA ] = 0;
+ sf->thresh_mult[THR_COMP_NEARESTLA] = 0;
+ sf->thresh_mult[THR_COMP_NEARLA ] = 0;
+ sf->thresh_mult[THR_COMP_ZEROGA ] = 0;
+ sf->thresh_mult[THR_COMP_NEARESTGA] = 0;
+ sf->thresh_mult[THR_COMP_NEARGA ] = 0;
+
+ sf->thresh_mult[THR_COMP_NEWLG ] = 1000;
+ sf->thresh_mult[THR_COMP_NEWLA ] = 1000;
+ sf->thresh_mult[THR_COMP_NEWGA ] = 1000;
if (Speed > 0)
{
@@ -754,6 +788,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_V_PRED ] = 1500;
sf->thresh_mult[THR_H_PRED ] = 1500;
sf->thresh_mult[THR_B_PRED ] = 5000;
+ sf->thresh_mult[THR_I8X8_PRED] = 5000;
if (cpi->ref_frame_flags & VP8_LAST_FLAG)
{
@@ -778,6 +813,20 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_NEWA ] = 2000;
sf->thresh_mult[THR_SPLITA ] = 20000;
}
+
+ sf->thresh_mult[THR_COMP_ZEROLG ] = 1500;
+ sf->thresh_mult[THR_COMP_NEARESTLG] = 1500;
+ sf->thresh_mult[THR_COMP_NEARLG ] = 1500;
+ sf->thresh_mult[THR_COMP_ZEROLA ] = 1500;
+ sf->thresh_mult[THR_COMP_NEARESTLA] = 1500;
+ sf->thresh_mult[THR_COMP_NEARLA ] = 1500;
+ sf->thresh_mult[THR_COMP_ZEROGA ] = 1500;
+ sf->thresh_mult[THR_COMP_NEARESTGA] = 1500;
+ sf->thresh_mult[THR_COMP_NEARGA ] = 1500;
+
+ sf->thresh_mult[THR_COMP_NEWLG ] = 2000;
+ sf->thresh_mult[THR_COMP_NEWLA ] = 2000;
+ sf->thresh_mult[THR_COMP_NEWGA ] = 2000;
}
if (Speed > 2)
@@ -790,6 +839,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_V_PRED ] = 2000;
sf->thresh_mult[THR_H_PRED ] = 2000;
sf->thresh_mult[THR_B_PRED ] = 7500;
+ sf->thresh_mult[THR_I8X8_PRED] = 7500;
if (cpi->ref_frame_flags & VP8_LAST_FLAG)
{
@@ -815,6 +865,20 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_SPLITA ] = 50000;
}
+ sf->thresh_mult[THR_COMP_ZEROLG ] = 2000;
+ sf->thresh_mult[THR_COMP_NEARESTLG] = 2000;
+ sf->thresh_mult[THR_COMP_NEARLG ] = 2000;
+ sf->thresh_mult[THR_COMP_ZEROLA ] = 2000;
+ sf->thresh_mult[THR_COMP_NEARESTLA] = 2000;
+ sf->thresh_mult[THR_COMP_NEARLA ] = 2000;
+ sf->thresh_mult[THR_COMP_ZEROGA ] = 2000;
+ sf->thresh_mult[THR_COMP_NEARESTGA] = 2000;
+ sf->thresh_mult[THR_COMP_NEARGA ] = 2000;
+
+ sf->thresh_mult[THR_COMP_NEWLG ] = 2500;
+ sf->thresh_mult[THR_COMP_NEWLA ] = 2500;
+ sf->thresh_mult[THR_COMP_NEWGA ] = 2500;
+
sf->improved_quant = 0;
sf->improved_dct = 0;
@@ -824,368 +888,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
}
- if (Speed > 3)
- {
- sf->thresh_mult[THR_SPLITA ] = INT_MAX;
- sf->thresh_mult[THR_SPLITG ] = INT_MAX;
- sf->thresh_mult[THR_SPLITMV ] = INT_MAX;
-
- cpi->mode_check_freq[THR_V_PRED] = 0;
- cpi->mode_check_freq[THR_H_PRED] = 0;
- cpi->mode_check_freq[THR_B_PRED] = 0;
- cpi->mode_check_freq[THR_NEARG] = 0;
- cpi->mode_check_freq[THR_NEWG] = 0;
- cpi->mode_check_freq[THR_NEARA] = 0;
- cpi->mode_check_freq[THR_NEWA] = 0;
-
- sf->auto_filter = 1;
- sf->recode_loop = 0; // recode loop off
- sf->RD = 0; // Turn rd off
-
- }
-
- if (Speed > 4)
- {
- sf->auto_filter = 0; // Faster selection of loop filter
-
- cpi->mode_check_freq[THR_V_PRED] = 2;
- cpi->mode_check_freq[THR_H_PRED] = 2;
- cpi->mode_check_freq[THR_B_PRED] = 2;
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- cpi->mode_check_freq[THR_NEARG] = 2;
- cpi->mode_check_freq[THR_NEWG] = 4;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- cpi->mode_check_freq[THR_NEARA] = 2;
- cpi->mode_check_freq[THR_NEWA] = 4;
- }
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- sf->thresh_mult[THR_NEARESTG ] = 2000;
- sf->thresh_mult[THR_ZEROG ] = 2000;
- sf->thresh_mult[THR_NEARG ] = 2000;
- sf->thresh_mult[THR_NEWG ] = 4000;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- sf->thresh_mult[THR_NEARESTA ] = 2000;
- sf->thresh_mult[THR_ZEROA ] = 2000;
- sf->thresh_mult[THR_NEARA ] = 2000;
- sf->thresh_mult[THR_NEWA ] = 4000;
- }
- }
-
break;
-#endif
- case 2:
- sf->optimize_coefficients = 0;
- sf->recode_loop = 0;
- sf->auto_filter = 1;
- sf->iterative_sub_pixel = 1;
- sf->thresh_mult[THR_NEARESTMV] = 0;
- sf->thresh_mult[THR_ZEROMV ] = 0;
- sf->thresh_mult[THR_DC ] = 0;
- sf->thresh_mult[THR_TM ] = 0;
- sf->thresh_mult[THR_NEARMV ] = 0;
- sf->thresh_mult[THR_V_PRED ] = 1000;
- sf->thresh_mult[THR_H_PRED ] = 1000;
- sf->thresh_mult[THR_B_PRED ] = 2500;
- sf->thresh_mult[THR_NEARESTG ] = 1000;
- sf->thresh_mult[THR_ZEROG ] = 1000;
- sf->thresh_mult[THR_NEARG ] = 1000;
- sf->thresh_mult[THR_NEARESTA ] = 1000;
- sf->thresh_mult[THR_ZEROA ] = 1000;
- sf->thresh_mult[THR_NEARA ] = 1000;
- sf->thresh_mult[THR_NEWMV ] = 2000;
- sf->thresh_mult[THR_NEWG ] = 2000;
- sf->thresh_mult[THR_NEWA ] = 2000;
- sf->thresh_mult[THR_SPLITMV ] = 5000;
- sf->thresh_mult[THR_SPLITG ] = 10000;
- sf->thresh_mult[THR_SPLITA ] = 10000;
- sf->search_method = NSTEP;
-
- if (Speed > 0)
- {
- cpi->mode_check_freq[THR_SPLITG] = 4;
- cpi->mode_check_freq[THR_SPLITA] = 4;
- cpi->mode_check_freq[THR_SPLITMV] = 2;
-
- sf->thresh_mult[THR_DC ] = 0;
- sf->thresh_mult[THR_TM ] = 1000;
- sf->thresh_mult[THR_V_PRED ] = 2000;
- sf->thresh_mult[THR_H_PRED ] = 2000;
- sf->thresh_mult[THR_B_PRED ] = 5000;
-
- if (cpi->ref_frame_flags & VP8_LAST_FLAG)
- {
- sf->thresh_mult[THR_NEARESTMV] = 0;
- sf->thresh_mult[THR_ZEROMV ] = 0;
- sf->thresh_mult[THR_NEARMV ] = 0;
- sf->thresh_mult[THR_NEWMV ] = 2000;
- sf->thresh_mult[THR_SPLITMV ] = 10000;
- }
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- sf->thresh_mult[THR_NEARESTG ] = 1000;
- sf->thresh_mult[THR_ZEROG ] = 1000;
- sf->thresh_mult[THR_NEARG ] = 1000;
- sf->thresh_mult[THR_NEWG ] = 2000;
- sf->thresh_mult[THR_SPLITG ] = 20000;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- sf->thresh_mult[THR_NEARESTA ] = 1000;
- sf->thresh_mult[THR_ZEROA ] = 1000;
- sf->thresh_mult[THR_NEARA ] = 1000;
- sf->thresh_mult[THR_NEWA ] = 2000;
- sf->thresh_mult[THR_SPLITA ] = 20000;
- }
-
- sf->improved_quant = 0;
- sf->improved_dct = 0;
-
- sf->use_fastquant_for_pick = 1;
- sf->no_skip_block4x4_search = 0;
- sf->first_step = 1;
- }
-
- if (Speed > 1)
- {
- cpi->mode_check_freq[THR_SPLITMV] = 7;
- cpi->mode_check_freq[THR_SPLITG] = 15;
- cpi->mode_check_freq[THR_SPLITA] = 15;
-
- sf->thresh_mult[THR_TM ] = 2000;
- sf->thresh_mult[THR_V_PRED ] = 2000;
- sf->thresh_mult[THR_H_PRED ] = 2000;
- sf->thresh_mult[THR_B_PRED ] = 5000;
-
- if (cpi->ref_frame_flags & VP8_LAST_FLAG)
- {
- sf->thresh_mult[THR_NEWMV ] = 2000;
- sf->thresh_mult[THR_SPLITMV ] = 25000;
- }
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- sf->thresh_mult[THR_NEARESTG ] = 2000;
- sf->thresh_mult[THR_ZEROG ] = 2000;
- sf->thresh_mult[THR_NEARG ] = 2000;
- sf->thresh_mult[THR_NEWG ] = 2500;
- sf->thresh_mult[THR_SPLITG ] = 50000;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- sf->thresh_mult[THR_NEARESTA ] = 2000;
- sf->thresh_mult[THR_ZEROA ] = 2000;
- sf->thresh_mult[THR_NEARA ] = 2000;
- sf->thresh_mult[THR_NEWA ] = 2500;
- sf->thresh_mult[THR_SPLITA ] = 50000;
- }
-
- }
-
- if (Speed > 2)
- {
- sf->auto_filter = 0; // Faster selection of loop filter
-
- cpi->mode_check_freq[THR_V_PRED] = 2;
- cpi->mode_check_freq[THR_H_PRED] = 2;
- cpi->mode_check_freq[THR_B_PRED] = 2;
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- cpi->mode_check_freq[THR_NEARG] = 2;
- cpi->mode_check_freq[THR_NEWG] = 4;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- cpi->mode_check_freq[THR_NEARA] = 2;
- cpi->mode_check_freq[THR_NEWA] = 4;
- }
-
- sf->thresh_mult[THR_SPLITMV ] = INT_MAX;
- sf->thresh_mult[THR_SPLITG ] = INT_MAX;
- sf->thresh_mult[THR_SPLITA ] = INT_MAX;
-
- }
-
- if (Speed > 3)
- {
- sf->RD = 0;
-
- sf->auto_filter = 1;
- }
-
- if (Speed > 4)
- {
- sf->auto_filter = 0; // Faster selection of loop filter
-
- sf->search_method = HEX;
- //sf->search_method = DIAMOND;
-
- sf->iterative_sub_pixel = 0;
-
- cpi->mode_check_freq[THR_V_PRED] = 4;
- cpi->mode_check_freq[THR_H_PRED] = 4;
- cpi->mode_check_freq[THR_B_PRED] = 4;
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- cpi->mode_check_freq[THR_NEARG] = 2;
- cpi->mode_check_freq[THR_NEWG] = 4;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- cpi->mode_check_freq[THR_NEARA] = 2;
- cpi->mode_check_freq[THR_NEWA] = 4;
- }
-
- sf->thresh_mult[THR_TM ] = 2000;
- sf->thresh_mult[THR_B_PRED ] = 5000;
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- sf->thresh_mult[THR_NEARESTG ] = 2000;
- sf->thresh_mult[THR_ZEROG ] = 2000;
- sf->thresh_mult[THR_NEARG ] = 2000;
- sf->thresh_mult[THR_NEWG ] = 4000;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- sf->thresh_mult[THR_NEARESTA ] = 2000;
- sf->thresh_mult[THR_ZEROA ] = 2000;
- sf->thresh_mult[THR_NEARA ] = 2000;
- sf->thresh_mult[THR_NEWA ] = 4000;
- }
- }
-
- if (Speed > 5)
- {
- // Disable split MB intra prediction mode
- sf->thresh_mult[THR_B_PRED] = INT_MAX;
- }
-
- if (Speed > 6)
- {
- unsigned int i, sum = 0;
- unsigned int total_mbs = cm->MBs;
- int thresh;
- int total_skip;
-
- int min = 2000;
-
- if (cpi->oxcf.encode_breakout > 2000)
- min = cpi->oxcf.encode_breakout;
-
- min >>= 7;
-
- for (i = 0; i < min; i++)
- {
- sum += cpi->error_bins[i];
- }
-
- total_skip = sum;
- sum = 0;
-
- // i starts from 2 to make sure thresh started from 2048
- for (; i < 1024; i++)
- {
- sum += cpi->error_bins[i];
-
- if (10 * sum >= (unsigned int)(cpi->Speed - 6)*(total_mbs - total_skip))
- break;
- }
-
- i--;
- thresh = (i << 7);
-
- if (thresh < 2000)
- thresh = 2000;
-
- if (cpi->ref_frame_flags & VP8_LAST_FLAG)
- {
- sf->thresh_mult[THR_NEWMV] = thresh;
- sf->thresh_mult[THR_NEARESTMV ] = thresh >> 1;
- sf->thresh_mult[THR_NEARMV ] = thresh >> 1;
- }
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- sf->thresh_mult[THR_NEWG] = thresh << 1;
- sf->thresh_mult[THR_NEARESTG ] = thresh;
- sf->thresh_mult[THR_NEARG ] = thresh;
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- sf->thresh_mult[THR_NEWA] = thresh << 1;
- sf->thresh_mult[THR_NEARESTA ] = thresh;
- sf->thresh_mult[THR_NEARA ] = thresh;
- }
-
- // Disable other intra prediction modes
- sf->thresh_mult[THR_TM] = INT_MAX;
- sf->thresh_mult[THR_V_PRED] = INT_MAX;
- sf->thresh_mult[THR_H_PRED] = INT_MAX;
-
- sf->improved_mv_pred = 0;
- }
-
- if (Speed > 8)
- {
- sf->quarter_pixel_search = 0;
- }
-
- if (Speed > 9)
- {
- int Tmp = cpi->Speed - 8;
-
- if (Tmp > 4)
- Tmp = 4;
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- cpi->mode_check_freq[THR_ZEROG] = 1 << (Tmp - 1);
- cpi->mode_check_freq[THR_NEARESTG] = 1 << (Tmp - 1);
- cpi->mode_check_freq[THR_NEARG] = 1 << Tmp;
- cpi->mode_check_freq[THR_NEWG] = 1 << (Tmp + 1);
- }
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG)
- {
- cpi->mode_check_freq[THR_ZEROA] = 1 << (Tmp - 1);
- cpi->mode_check_freq[THR_NEARESTA] = 1 << (Tmp - 1);
- cpi->mode_check_freq[THR_NEARA] = 1 << Tmp;
- cpi->mode_check_freq[THR_NEWA] = 1 << (Tmp + 1);
- }
-
- cpi->mode_check_freq[THR_NEWMV] = 1 << (Tmp - 1);
- }
-
- cm->filter_type = NORMAL_LOOPFILTER;
-
- if (Speed >= 14)
- cm->filter_type = SIMPLE_LOOPFILTER;
-
- if (Speed >= 15)
- {
- sf->half_pixel_search = 0; // This has a big hit on quality. Last resort
- }
-
- vpx_memset(cpi->error_bins, 0, sizeof(cpi->error_bins));
}; /* switch */
@@ -1217,6 +920,29 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_SPLITA ] = INT_MAX;
}
+ if ((cpi->ref_frame_flags & (VP8_LAST_FLAG | VP8_GOLD_FLAG)) != (VP8_LAST_FLAG | VP8_GOLD_FLAG))
+ {
+ sf->thresh_mult[THR_COMP_ZEROLG ] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEARESTLG] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEARLG ] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEWLG ] = INT_MAX;
+ }
+
+ if ((cpi->ref_frame_flags & (VP8_LAST_FLAG | VP8_ALT_FLAG)) != (VP8_LAST_FLAG | VP8_ALT_FLAG))
+ {
+ sf->thresh_mult[THR_COMP_ZEROLA ] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEARESTLA] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEARLA ] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEWLA ] = INT_MAX;
+ }
+
+ if ((cpi->ref_frame_flags & (VP8_GOLD_FLAG | VP8_ALT_FLAG)) != (VP8_GOLD_FLAG | VP8_ALT_FLAG))
+ {
+ sf->thresh_mult[THR_COMP_ZEROGA ] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEARESTGA] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEARGA ] = INT_MAX;
+ sf->thresh_mult[THR_COMP_NEWGA ] = INT_MAX;
+ }
// Slow quant, dct and trellis not worthwhile for first pass
// so make sure they are always turned off.
@@ -1238,16 +964,19 @@ void vp8_set_speed_features(VP8_COMP *cpi)
if (cpi->sf.improved_dct)
{
+ cpi->mb.vp8_short_fdct8x8 = FDCT_INVOKE(&cpi->rtcd.fdct, short8x8);
cpi->mb.vp8_short_fdct8x4 = FDCT_INVOKE(&cpi->rtcd.fdct, short8x4);
cpi->mb.vp8_short_fdct4x4 = FDCT_INVOKE(&cpi->rtcd.fdct, short4x4);
}
else
{
+ cpi->mb.vp8_short_fdct8x8 = FDCT_INVOKE(&cpi->rtcd.fdct, short8x8);
cpi->mb.vp8_short_fdct8x4 = FDCT_INVOKE(&cpi->rtcd.fdct, fast8x4);
cpi->mb.vp8_short_fdct4x4 = FDCT_INVOKE(&cpi->rtcd.fdct, fast4x4);
}
cpi->mb.short_walsh4x4 = FDCT_INVOKE(&cpi->rtcd.fdct, walsh_short4x4);
+ cpi->mb.short_fhaar2x2 = FDCT_INVOKE(&cpi->rtcd.fdct, haar_short2x2);
if (cpi->sf.improved_quant)
{
@@ -1255,6 +984,8 @@ void vp8_set_speed_features(VP8_COMP *cpi)
quantb);
cpi->mb.quantize_b_pair = QUANTIZE_INVOKE(&cpi->rtcd.quantize,
quantb_pair);
+ cpi->mb.quantize_b_8x8 = QUANTIZE_INVOKE(&cpi->rtcd.quantize, quantb_8x8);
+ cpi->mb.quantize_b_2x2 = QUANTIZE_INVOKE(&cpi->rtcd.quantize, quantb_2x2);
}
else
{
@@ -1262,6 +993,8 @@ void vp8_set_speed_features(VP8_COMP *cpi)
fastquantb);
cpi->mb.quantize_b_pair = QUANTIZE_INVOKE(&cpi->rtcd.quantize,
fastquantb_pair);
+ cpi->mb.quantize_b_8x8 = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb_8x8);
+ cpi->mb.quantize_b_2x2 = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb_2x2);
}
if (cpi->sf.improved_quant != last_improved_quant)
vp8cx_init_quantizer(cpi);
@@ -1282,19 +1015,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
{
cpi->find_fractional_mv_step = vp8_find_best_half_pixel_step;
}
- else
- {
- cpi->find_fractional_mv_step = vp8_skip_fractional_mv_step;
- }
if (cpi->sf.optimize_coefficients == 1 && cpi->pass!=1)
cpi->mb.optimize = 1;
else
cpi->mb.optimize = 0;
- if (cpi->common.full_pixel)
- cpi->find_fractional_mv_step = vp8_skip_fractional_mv_step;
-
#ifdef SPEEDSTATS
frames_at_speed[cpi->Speed]++;
#endif
@@ -1399,30 +1125,22 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi)
vpx_calloc(sizeof(unsigned int),
cm->mb_rows * cm->mb_cols));
-#if !(CONFIG_REALTIME_ONLY)
vpx_free(cpi->twopass.total_stats);
cpi->twopass.total_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
+ vpx_free(cpi->twopass.total_left_stats);
+ cpi->twopass.total_left_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
+
vpx_free(cpi->twopass.this_frame_stats);
cpi->twopass.this_frame_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
- if(!cpi->twopass.total_stats || !cpi->twopass.this_frame_stats)
+ if( !cpi->twopass.total_stats ||
+ !cpi->twopass.total_left_stats ||
+ !cpi->twopass.this_frame_stats)
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate firstpass stats");
-#endif
-
-#if CONFIG_MULTITHREAD
- if (width < 640)
- cpi->mt_sync_range = 1;
- else if (width <= 1280)
- cpi->mt_sync_range = 4;
- else if (width <= 2560)
- cpi->mt_sync_range = 8;
- else
- cpi->mt_sync_range = 16;
-#endif
vpx_free(cpi->tplist);
@@ -1430,17 +1148,22 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi)
}
-// Quant MOD
+// TODO perhaps change number of steps expose to outside world when setting
+// max and min limits. Also this will likely want refining for the extended Q
+// range.
+//
+// Table that converts 0-63 Q range values passed in outside to the Qindex
+// range used internally.
static const int q_trans[] =
{
- 0, 1, 2, 3, 4, 5, 7, 8,
- 9, 10, 12, 13, 15, 17, 18, 19,
- 20, 21, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 33, 35, 37, 39, 41,
- 43, 45, 47, 49, 51, 53, 55, 57,
- 59, 61, 64, 67, 70, 73, 76, 79,
- 82, 85, 88, 91, 94, 97, 100, 103,
- 106, 109, 112, 115, 118, 121, 124, 127,
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 44, 48, 52, 56, 60,
+ 64, 68, 72, 76, 80, 84, 88, 92,
+ 96, 100, 104, 108, 112, 116, 120, 124,
+ 128, 132, 136, 140, 144, 148, 152, 156,
+ 160, 164, 168, 172, 176, 180, 184, 188,
+ 192, 196, 200, 204, 208, 212, 216, 220,
+ 224, 228, 232, 236, 240, 244, 249, 255,
};
int vp8_reverse_trans(int x)
@@ -1464,6 +1187,9 @@ void vp8_new_frame_rate(VP8_COMP *cpi, double framerate)
cpi->av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate);
cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+ if (cpi->min_frame_bandwidth < FRAME_OVERHEAD_BITS )
+ cpi->min_frame_bandwidth = FRAME_OVERHEAD_BITS;
+
// Set Maximum gf/arf interval
cpi->max_gf_interval = ((int)(cpi->output_frame_rate / 2.0) + 2);
@@ -1506,8 +1232,6 @@ static void init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->oxcf = *oxcf;
- cpi->auto_gold = 1;
- cpi->auto_adjust_gold_quantizer = 1;
cpi->goldfreq = 7;
cm->version = oxcf->Version;
@@ -1533,6 +1257,8 @@ static void init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
+ cpi->static_mb_pct = 0;
+
#if VP8_TEMPORAL_ALT_REF
{
int i;
@@ -1567,44 +1293,12 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
switch (cpi->oxcf.Mode)
{
-
- case MODE_REALTIME:
- cpi->pass = 0;
- cpi->compressor_speed = 2;
-
- if (cpi->oxcf.cpu_used < -16)
- {
- cpi->oxcf.cpu_used = -16;
- }
-
- if (cpi->oxcf.cpu_used > 16)
- cpi->oxcf.cpu_used = 16;
-
- break;
-
- case MODE_GOODQUALITY:
- cpi->pass = 0;
- cpi->compressor_speed = 1;
-
- if (cpi->oxcf.cpu_used < -5)
- {
- cpi->oxcf.cpu_used = -5;
- }
-
- if (cpi->oxcf.cpu_used > 5)
- cpi->oxcf.cpu_used = 5;
-
- break;
-
- case MODE_BESTQUALITY:
- cpi->pass = 0;
- cpi->compressor_speed = 0;
- break;
-
+ // Real time and one pass deprecated in test code base
case MODE_FIRSTPASS:
cpi->pass = 1;
cpi->compressor_speed = 1;
break;
+
case MODE_SECONDPASS:
cpi->pass = 2;
cpi->compressor_speed = 1;
@@ -1618,45 +1312,18 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->oxcf.cpu_used = 5;
break;
+
case MODE_SECONDPASS_BEST:
cpi->pass = 2;
cpi->compressor_speed = 0;
break;
}
- if (cpi->pass == 0)
- cpi->auto_worst_q = 1;
-
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
cpi->oxcf.best_allowed_q = q_trans[oxcf->best_allowed_q];
cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level];
- if (oxcf->fixed_q >= 0)
- {
- if (oxcf->worst_allowed_q < 0)
- cpi->oxcf.fixed_q = q_trans[0];
- else
- cpi->oxcf.fixed_q = q_trans[oxcf->worst_allowed_q];
-
- if (oxcf->alt_q < 0)
- cpi->oxcf.alt_q = q_trans[0];
- else
- cpi->oxcf.alt_q = q_trans[oxcf->alt_q];
-
- if (oxcf->key_q < 0)
- cpi->oxcf.key_q = q_trans[0];
- else
- cpi->oxcf.key_q = q_trans[oxcf->key_q];
-
- if (oxcf->gold_q < 0)
- cpi->oxcf.gold_q = q_trans[0];
- else
- cpi->oxcf.gold_q = q_trans[oxcf->gold_q];
-
- }
-
- cpi->baseline_gf_interval =
- cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL;
+ cpi->baseline_gf_interval = DEFAULT_GF_INTERVAL;
cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
@@ -1666,11 +1333,10 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cm->refresh_last_frame = 1;
cm->refresh_entropy_probs = 1;
- if (cpi->oxcf.token_partitions >= 0 && cpi->oxcf.token_partitions <= 3)
- cm->multi_token_partition =
- (TOKEN_PARTITION) cpi->oxcf.token_partitions;
-
setup_features(cpi);
+#if CONFIG_HIGH_PRECISION_MV
+ cpi->mb.e_mbd.allow_high_precision_mv = 0; // Default mv precision adaptation
+#endif
{
int i;
@@ -1744,9 +1410,6 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->cq_target_quality = cpi->oxcf.cq_level;
- // Only allow dropped frames in buffered mode
- cpi->drop_frames_allowed = cpi->oxcf.allow_df && cpi->buffered_mode;
-
if (!cm->use_bilinear_mc_filter)
cm->mcomp_filter_type = SIXTAP;
else
@@ -1793,6 +1456,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
{
cpi->last_q[0] = cpi->oxcf.fixed_q;
cpi->last_q[1] = cpi->oxcf.fixed_q;
+ cpi->last_boosted_qindex = cpi->oxcf.fixed_q;
}
cpi->Speed = cpi->oxcf.cpu_used;
@@ -1810,7 +1474,6 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->alt_ref_source = NULL;
cpi->is_src_frame_alt_ref = 0;
-
#if 0
// Experimental RD Code
cpi->frame_distortion = 0;
@@ -1839,6 +1502,26 @@ static void cal_mvsadcosts(int *mvsadcost[2])
while (++i <= mvfp_max);
}
+#if CONFIG_HIGH_PRECISION_MV
+static void cal_mvsadcosts_hp(int *mvsadcost[2])
+{
+ int i = 1;
+
+ mvsadcost [0] [0] = 300;
+ mvsadcost [1] [0] = 300;
+
+ do
+ {
+ double z = 256 * (2 * (log2f(8 * i) + .6));
+ mvsadcost [0][i] = (int) z;
+ mvsadcost [1][i] = (int) z;
+ mvsadcost [0][-i] = (int) z;
+ mvsadcost [1][-i] = (int) z;
+ }
+ while (++i <= mvfp_max_hp);
+}
+#endif
+
VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
{
int i;
@@ -1885,9 +1568,11 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
cpi->frames_till_gf_update_due = 0;
cpi->gf_overspend_bits = 0;
cpi->non_gf_bitrate_adjustment = 0;
- cpi->prob_last_coded = 128;
- cpi->prob_gf_coded = 128;
- cpi->prob_intra_coded = 63;
+ cm->prob_last_coded = 128;
+ cm->prob_gf_coded = 128;
+ cm->prob_intra_coded = 63;
+ for ( i = 0; i < COMP_PRED_CONTEXTS; i++ )
+ cm->prob_comppred[i] = 128;
// Prime the recent reference frame useage counters.
// Hereafter they will be maintained as a sort of moving average
@@ -1912,50 +1597,24 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
CHECK_MEM_ERROR(cpi->lf_ref_frame, vpx_calloc((cpi->common.mb_rows+2) * (cpi->common.mb_cols+2), sizeof(int)));
// Create the encoder segmentation map and set all entries to 0
- CHECK_MEM_ERROR(cpi->segmentation_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+ CHECK_MEM_ERROR(cpi->segmentation_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1));
+
+ // And a copy in common for temporal coding
+ CHECK_MEM_ERROR(cm->last_frame_seg_map,
+ vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1));
+
CHECK_MEM_ERROR(cpi->active_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
vpx_memset(cpi->active_map , 1, (cpi->common.mb_rows * cpi->common.mb_cols));
cpi->active_map_enabled = 0;
-#if 0
- // Experimental code for lagged and one pass
- // Initialise one_pass GF frames stats
- // Update stats used for GF selection
- if (cpi->pass == 0)
- {
- cpi->one_pass_frame_index = 0;
-
- for (i = 0; i < MAX_LAG_BUFFERS; i++)
- {
- cpi->one_pass_frame_stats[i].frames_so_far = 0;
- cpi->one_pass_frame_stats[i].frame_intra_error = 0.0;
- cpi->one_pass_frame_stats[i].frame_coded_error = 0.0;
- cpi->one_pass_frame_stats[i].frame_pcnt_inter = 0.0;
- cpi->one_pass_frame_stats[i].frame_pcnt_motion = 0.0;
- cpi->one_pass_frame_stats[i].frame_mvr = 0.0;
- cpi->one_pass_frame_stats[i].frame_mvr_abs = 0.0;
- cpi->one_pass_frame_stats[i].frame_mvc = 0.0;
- cpi->one_pass_frame_stats[i].frame_mvc_abs = 0.0;
- }
- }
-#endif
-
- // Should we use the cyclic refresh method.
- // Currently this is tied to error resilliant mode
- cpi->cyclic_refresh_mode_enabled = cpi->oxcf.error_resilient_mode;
- cpi->cyclic_refresh_mode_max_mbs_perframe = (cpi->common.mb_rows * cpi->common.mb_cols) / 40;
- cpi->cyclic_refresh_mode_index = 0;
- cpi->cyclic_refresh_q = 32;
-
- if (cpi->cyclic_refresh_mode_enabled)
+ for (i = 0; i < ( sizeof(cpi->mbgraph_stats) /
+ sizeof(cpi->mbgraph_stats[0]) ); i++)
{
- CHECK_MEM_ERROR(cpi->cyclic_refresh_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1));
+ CHECK_MEM_ERROR(cpi->mbgraph_stats[i].mb_stats,
+ vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols *
+ sizeof(*cpi->mbgraph_stats[i].mb_stats),
+ 1));
}
- else
- cpi->cyclic_refresh_map = (signed char *) NULL;
-
- // Test function for segmentation
- //segmentation_test_function((VP8_PTR) cpi);
#ifdef ENTROPY_STATS
init_context_counters();
@@ -2018,13 +1677,10 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
cpi->ni_av_qi = cpi->oxcf.worst_allowed_q;
cpi->ni_tot_qi = 0;
cpi->ni_frames = 0;
+ cpi->tot_q = 0.0;
+ cpi->avg_q = vp8_convert_qindex_to_q( cpi->oxcf.worst_allowed_q );
cpi->total_byte_count = 0;
- cpi->drop_frame = 0;
- cpi->drop_count = 0;
- cpi->max_drop_count = 0;
- cpi->max_consec_dropped_frames = 4;
-
cpi->rate_correction_factor = 1.0;
cpi->key_frame_rate_correction_factor = 1.0;
cpi->gf_rate_correction_factor = 1.0;
@@ -2037,6 +1693,15 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
cal_mvsadcosts(cpi->mb.mvsadcost);
+#if CONFIG_HIGH_PRECISION_MV
+ cpi->mb.mvcost_hp[0] = &cpi->mb.mvcosts_hp[0][mv_max_hp+1];
+ cpi->mb.mvcost_hp[1] = &cpi->mb.mvcosts_hp[1][mv_max_hp+1];
+ cpi->mb.mvsadcost_hp[0] = &cpi->mb.mvsadcosts_hp[0][mvfp_max_hp+1];
+ cpi->mb.mvsadcost_hp[1] = &cpi->mb.mvsadcosts_hp[1][mvfp_max_hp+1];
+
+ cal_mvsadcosts_hp(cpi->mb.mvsadcost_hp);
+#endif
+
for (i = 0; i < KEY_FRAME_CONTEXT; i++)
{
cpi->prior_key_frame_distance[i] = (int)cpi->output_frame_rate;
@@ -2045,6 +1710,9 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
#ifdef OUTPUT_YUV_SRC
yuv_file = fopen("bd.yuv", "ab");
#endif
+#ifdef OUTPUT_YUV_REC
+ yuv_rec_file = fopen("rec.yuv", "wb");
+#endif
#if 0
framepsnr = fopen("framepsnr.stt", "a");
@@ -2053,8 +1721,6 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
cpi->output_pkt_list = oxcf->output_pkt_list;
-#if !(CONFIG_REALTIME_ONLY)
-
if (cpi->pass == 1)
{
vp8_init_first_pass(cpi);
@@ -2071,15 +1737,6 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
vp8_init_second_pass(cpi);
}
-#endif
-
- if (cpi->compressor_speed == 2)
- {
- cpi->cpu_freq = 0; //vp8_get_processor_freq();
- cpi->avg_encode_time = 0;
- cpi->avg_pick_mode_time = 0;
- }
-
vp8_set_speed_features(cpi);
// Set starting values of RD threshold multipliers (128 = *1)
@@ -2092,10 +1749,6 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
init_mv_ref_counts();
#endif
-#if CONFIG_MULTITHREAD
- vp8cx_create_encoder_threads(cpi);
-#endif
-
cpi->fn_ptr[BLOCK_16X16].sdf = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16);
cpi->fn_ptr[BLOCK_16X16].vf = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x16);
cpi->fn_ptr[BLOCK_16X16].svf = VARIANCE_INVOKE(&cpi->rtcd.variance, subpixvar16x16);
@@ -2168,6 +1821,12 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
vp8_loop_filter_init(cm);
cpi->common.error.setjmp = 0;
+
+#if CONFIG_UVINTRA
+ vp8_zero(cpi->y_uv_mode_count)
+#endif
+
+
return (VP8_PTR) cpi;
}
@@ -2176,21 +1835,18 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
void vp8_remove_compressor(VP8_PTR *ptr)
{
VP8_COMP *cpi = (VP8_COMP *)(*ptr);
+ int i;
if (!cpi)
return;
if (cpi && (cpi->common.current_video_frame > 0))
{
-#if !(CONFIG_REALTIME_ONLY)
-
if (cpi->pass == 2)
{
vp8_end_second_pass(cpi);
}
-#endif
-
#ifdef ENTROPY_STATS
print_context_counters();
print_tree_update_probs();
@@ -2199,6 +1855,9 @@ void vp8_remove_compressor(VP8_PTR *ptr)
#if CONFIG_INTERNAL_STATS
+ vp8_clear_system_state();
+
+ printf("\n8x8-4x4:%d-%d\n", cpi->t8x8_count, cpi->t4x4_count);
if (cpi->pass != 1)
{
FILE *f = fopen("opsnr.stt", "a");
@@ -2206,7 +1865,9 @@ void vp8_remove_compressor(VP8_PTR *ptr)
- cpi->first_time_stamp_ever) / 10000000.000;
double total_encode_time = (cpi->time_receive_data + cpi->time_compress_data) / 1000.000;
double dr = (double)cpi->bytes * (double) 8 / (double)1000 / time_encoded;
-
+#if defined(MODE_STATS)
+ print_mode_contexts(&cpi->common);
+#endif
if (cpi->b_calculate_psnr)
{
YV12_BUFFER_CONFIG *lst_yv12 = &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
@@ -2219,6 +1880,9 @@ void vp8_remove_compressor(VP8_PTR *ptr)
fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f\n",
dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
total_encode_time);
+// fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f %10ld\n",
+// dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
+// total_encode_time, cpi->tot_recode_hits);
}
if (cpi->b_calculate_ssimg)
@@ -2227,34 +1891,12 @@ void vp8_remove_compressor(VP8_PTR *ptr)
fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count,
cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time);
+// fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f %10ld\n", dr,
+// cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count,
+// cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time, cpi->tot_recode_hits);
}
fclose(f);
-#if 0
- f = fopen("qskip.stt", "a");
- fprintf(f, "minq:%d -maxq:%d skipture:skipfalse = %d:%d\n", cpi->oxcf.best_allowed_q, cpi->oxcf.worst_allowed_q, skiptruecount, skipfalsecount);
- fclose(f);
-#endif
-
- }
-
-#endif
-
-
-#ifdef SPEEDSTATS
-
- if (cpi->compressor_speed == 2)
- {
- int i;
- FILE *f = fopen("cxspeed.stt", "a");
- cnt_pm /= cpi->common.MBs;
-
- for (i = 0; i < 16; i++)
- fprintf(f, "%5d", frames_at_speed[i]);
-
- fprintf(f, "\n");
- //fprintf(f, "%10d PM %10d %10d %10d EF %10d %10d %10d\n", cpi->Speed, cpi->avg_pick_mode_time, (tot_pm/cnt_pm), cnt_pm, cpi->avg_encode_time, 0, 0);
- fclose(f);
}
#endif
@@ -2263,11 +1905,35 @@ void vp8_remove_compressor(VP8_PTR *ptr)
#ifdef MODE_STATS
{
extern int count_mb_seg[4];
- FILE *f = fopen("modes.stt", "a");
- double dr = (double)cpi->oxcf.frame_rate * (double)bytes * (double)8 / (double)count / (double)1000 ;
+ char modes_stats_file[250];
+ FILE *f;
+ double dr = (double)cpi->oxcf.frame_rate * (double)cpi->bytes * (double)8 / (double)cpi->count / (double)1000 ;
+ sprintf(modes_stats_file, "modes_q%03d.stt",cpi->common.base_qindex);
+ f = fopen(modes_stats_file, "w");
fprintf(f, "intra_mode in Intra Frames:\n");
- fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d\n", y_modes[0], y_modes[1], y_modes[2], y_modes[3], y_modes[4]);
+ fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d, %8d\n", y_modes[0], y_modes[1], y_modes[2], y_modes[3], y_modes[4], y_modes[5]);
+ fprintf(f, "I8:%8d, %8d, %8d, %8d\n", i8x8_modes[0], i8x8_modes[1], i8x8_modes[2], i8x8_modes[3]);
fprintf(f, "UV:%8d, %8d, %8d, %8d\n", uv_modes[0], uv_modes[1], uv_modes[2], uv_modes[3]);
+ fprintf(f, "KeyFrame Y-UV:\n");
+ {
+ int i;
+ for(i=0;i<VP8_YMODES;i++)
+ {
+ fprintf(f, "%2d:%8d, %8d, %8d, %8d\n",i,uv_modes_y[i][0],
+ uv_modes_y[i][1], uv_modes_y[i][2], uv_modes_y[i][3]);
+ }
+ }
+#if CONFIG_UVINTRA
+ fprintf(f, "Inter Y-UV:\n");
+ {
+ int i;
+ for(i=0;i<VP8_YMODES;i++)
+ {
+ fprintf(f, "%2d:%8d, %8d, %8d, %8d\n",i,cpi->y_uv_mode_count[i][0],
+ cpi->y_uv_mode_count[i][1], cpi->y_uv_mode_count[i][2], cpi->y_uv_mode_count[i][3]);
+ }
+ }
+#endif
fprintf(f, "B: ");
{
int i;
@@ -2280,10 +1946,14 @@ void vp8_remove_compressor(VP8_PTR *ptr)
}
fprintf(f, "Modes in Inter Frames:\n");
- fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d\n",
- inter_y_modes[0], inter_y_modes[1], inter_y_modes[2], inter_y_modes[3], inter_y_modes[4],
- inter_y_modes[5], inter_y_modes[6], inter_y_modes[7], inter_y_modes[8], inter_y_modes[9]);
- fprintf(f, "UV:%8d, %8d, %8d, %8d\n", inter_uv_modes[0], inter_uv_modes[1], inter_uv_modes[2], inter_uv_modes[3]);
+ fprintf(f,
+ "Y: %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d\n",
+ inter_y_modes[0], inter_y_modes[1], inter_y_modes[2],
+ inter_y_modes[3], inter_y_modes[4], inter_y_modes[5],
+ inter_y_modes[6], inter_y_modes[7], inter_y_modes[8],
+ inter_y_modes[9], inter_y_modes[10]);
+ fprintf(f, "UV:%8d, %8d, %8d, %8d\n", inter_uv_modes[0],
+ inter_uv_modes[1], inter_uv_modes[2], inter_uv_modes[3]);
fprintf(f, "B: ");
{
int i;
@@ -2296,9 +1966,6 @@ void vp8_remove_compressor(VP8_PTR *ptr)
}
fprintf(f, "P:%8d, %8d, %8d, %8d\n", count_mb_seg[0], count_mb_seg[1], count_mb_seg[2], count_mb_seg[3]);
fprintf(f, "PB:%8d, %8d, %8d, %8d\n", inter_b_modes[LEFT4X4], inter_b_modes[ABOVE4X4], inter_b_modes[ZERO4X4], inter_b_modes[NEW4X4]);
-
-
-
fclose(f);
}
#endif
@@ -2370,14 +2037,14 @@ void vp8_remove_compressor(VP8_PTR *ptr)
}
-#if CONFIG_MULTITHREAD
- vp8cx_remove_encoder_threads(cpi);
-#endif
-
dealloc_compressor_data(cpi);
vpx_free(cpi->mb.ss);
vpx_free(cpi->tok);
- vpx_free(cpi->cyclic_refresh_map);
+
+ for (i = 0; i < sizeof(cpi->mbgraph_stats) / sizeof(cpi->mbgraph_stats[0]); i++)
+ {
+ vpx_free(cpi->mbgraph_stats[i].mb_stats);
+ }
vp8_remove_common(&cpi->common);
vpx_free(cpi);
@@ -2386,6 +2053,9 @@ void vp8_remove_compressor(VP8_PTR *ptr)
#ifdef OUTPUT_YUV_SRC
fclose(yuv_file);
#endif
+#ifdef OUTPUT_YUV_REC
+ fclose(yuv_rec_file);
+#endif
#if 0
@@ -2596,10 +2266,9 @@ int vp8_update_entropy(VP8_PTR comp, int update)
}
-#if OUTPUT_YUV_SRC
-void vp8_write_yuv_frame(const char *name, YV12_BUFFER_CONFIG *s)
+#ifdef OUTPUT_YUV_SRC
+void vp8_write_yuv_frame(YV12_BUFFER_CONFIG *s)
{
- FILE *yuv_file = fopen(name, "ab");
unsigned char *src = s->y_buffer;
int h = s->y_height;
@@ -2629,113 +2298,49 @@ void vp8_write_yuv_frame(const char *name, YV12_BUFFER_CONFIG *s)
src += s->uv_stride;
}
while (--h);
-
- fclose(yuv_file);
}
#endif
-
-static void scale_and_extend_source(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+#ifdef OUTPUT_YUV_REC
+void vp8_write_yuv_rec_frame(VP8_COMMON *cm)
{
- VP8_COMMON *cm = &cpi->common;
+ YV12_BUFFER_CONFIG *s = cm->frame_to_show;
+ unsigned char *src = s->y_buffer;
+ int h = cm->Height;
- // are we resizing the image
- if (cm->horiz_scale != 0 || cm->vert_scale != 0)
+ do
{
-#if CONFIG_SPATIAL_RESAMPLING
- int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
- int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
- int tmp_height;
-
- if (cm->vert_scale == 3)
- tmp_height = 9;
- else
- tmp_height = 11;
-
- Scale2Ratio(cm->horiz_scale, &hr, &hs);
- Scale2Ratio(cm->vert_scale, &vr, &vs);
-
- vp8_scale_frame(sd, &cpi->scaled_source, cm->temp_scale_frame.y_buffer,
- tmp_height, hs, hr, vs, vr, 0);
-
- vp8_yv12_extend_frame_borders(&cpi->scaled_source);
- cpi->Source = &cpi->scaled_source;
-#endif
+ fwrite(src, s->y_width, 1, yuv_rec_file);
+ src += s->y_stride;
}
- else
- cpi->Source = sd;
-}
-
+ while (--h);
-static void resize_key_frame(VP8_COMP *cpi)
-{
-#if CONFIG_SPATIAL_RESAMPLING
- VP8_COMMON *cm = &cpi->common;
+ src = s->u_buffer;
+ h = (cm->Height+1)/2;
- // Do we need to apply resampling for one pass cbr.
- // In one pass this is more limited than in two pass cbr
- // The test and any change is only made one per key frame sequence
- if (cpi->oxcf.allow_spatial_resampling && (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER))
+ do
{
- int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
- int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
- int new_width, new_height;
-
- // If we are below the resample DOWN watermark then scale down a notch.
- if (cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))
- {
- cm->horiz_scale = (cm->horiz_scale < ONETWO) ? cm->horiz_scale + 1 : ONETWO;
- cm->vert_scale = (cm->vert_scale < ONETWO) ? cm->vert_scale + 1 : ONETWO;
- }
- // Should we now start scaling back up
- else if (cpi->buffer_level > (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))
- {
- cm->horiz_scale = (cm->horiz_scale > NORMAL) ? cm->horiz_scale - 1 : NORMAL;
- cm->vert_scale = (cm->vert_scale > NORMAL) ? cm->vert_scale - 1 : NORMAL;
- }
+ fwrite(src, s->uv_width, 1, yuv_rec_file);
+ src += s->uv_stride;
+ }
+ while (--h);
- // Get the new hieght and width
- Scale2Ratio(cm->horiz_scale, &hr, &hs);
- Scale2Ratio(cm->vert_scale, &vr, &vs);
- new_width = ((hs - 1) + (cpi->oxcf.Width * hr)) / hs;
- new_height = ((vs - 1) + (cpi->oxcf.Height * vr)) / vs;
+ src = s->v_buffer;
+ h = (cm->Height+1)/2;
- // If the image size has changed we need to reallocate the buffers
- // and resample the source image
- if ((cm->Width != new_width) || (cm->Height != new_height))
- {
- cm->Width = new_width;
- cm->Height = new_height;
- vp8_alloc_compressor_data(cpi);
- scale_and_extend_source(cpi->un_scaled_source, cpi);
- }
+ do
+ {
+ fwrite(src, s->uv_width, 1, yuv_rec_file);
+ src += s->uv_stride;
}
-
-#endif
+ while (--h);
}
-
+#endif
static void update_alt_ref_frame_stats(VP8_COMP *cpi)
{
VP8_COMMON *cm = &cpi->common;
- // Select an interval before next GF or altref
- if (!cpi->auto_gold)
- cpi->frames_till_gf_update_due = cpi->goldfreq;
-
- if ((cpi->pass != 2) && cpi->frames_till_gf_update_due)
- {
- cpi->current_gf_interval = cpi->frames_till_gf_update_due;
-
- // Set the bits per frame that we should try and recover in subsequent inter frames
- // to account for the extra GF spend... note that his does not apply for GF updates
- // that occur coincident with a key frame as the extra cost of key frames is dealt
- // with elsewhere.
-
- cpi->gf_overspend_bits += cpi->projected_frame_size;
- cpi->non_gf_bitrate_adjustment = cpi->gf_overspend_bits / cpi->frames_till_gf_update_due;
- }
-
// Update data structure that monitors level of reference to last GF
vpx_memset(cpi->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
@@ -2758,29 +2363,6 @@ static void update_golden_frame_stats(VP8_COMP *cpi)
// Update the Golden frame usage counts.
if (cm->refresh_golden_frame)
{
- // Select an interval before next GF
- if (!cpi->auto_gold)
- cpi->frames_till_gf_update_due = cpi->goldfreq;
-
- if ((cpi->pass != 2) && (cpi->frames_till_gf_update_due > 0))
- {
- cpi->current_gf_interval = cpi->frames_till_gf_update_due;
-
- // Set the bits per frame that we should try and recover in subsequent inter frames
- // to account for the extra GF spend... note that his does not apply for GF updates
- // that occur coincident with a key frame as the extra cost of key frames is dealt
- // with elsewhere.
- if ((cm->frame_type != KEY_FRAME) && !cpi->source_alt_ref_active)
- {
- // Calcluate GF bits to be recovered
- // Projected size - av frame bits available for inter frames for clip as a whole
- cpi->gf_overspend_bits += (cpi->projected_frame_size - cpi->inter_frame_target);
- }
-
- cpi->non_gf_bitrate_adjustment = cpi->gf_overspend_bits / cpi->frames_till_gf_update_due;
-
- }
-
// Update data structure that monitors level of reference to last GF
vpx_memset(cpi->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
@@ -2843,120 +2425,6 @@ static void update_golden_frame_stats(VP8_COMP *cpi)
}
}
-// This function updates the reference frame probability estimates that
-// will be used during mode selection
-static void update_rd_ref_frame_probs(VP8_COMP *cpi)
-{
- VP8_COMMON *cm = &cpi->common;
-
-#if 0
- const int *const rfct = cpi->recent_ref_frame_usage;
- const int rf_intra = rfct[INTRA_FRAME];
- const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
-
- if (cm->frame_type == KEY_FRAME)
- {
- cpi->prob_intra_coded = 255;
- cpi->prob_last_coded = 128;
- cpi->prob_gf_coded = 128;
- }
- else if (!(rf_intra + rf_inter))
- {
- // This is a trap in case this function is called with cpi->recent_ref_frame_usage[] blank.
- cpi->prob_intra_coded = 63;
- cpi->prob_last_coded = 128;
- cpi->prob_gf_coded = 128;
- }
- else
- {
- cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
-
- if (cpi->prob_intra_coded < 1)
- cpi->prob_intra_coded = 1;
-
- if ((cm->frames_since_golden > 0) || cpi->source_alt_ref_active)
- {
- cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
-
- if (cpi->prob_last_coded < 1)
- cpi->prob_last_coded = 1;
-
- cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
- ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
-
- if (cpi->prob_gf_coded < 1)
- cpi->prob_gf_coded = 1;
- }
- }
-
-#else
- const int *const rfct = cpi->count_mb_ref_frame_usage;
- const int rf_intra = rfct[INTRA_FRAME];
- const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
-
- if (cm->frame_type == KEY_FRAME)
- {
- cpi->prob_intra_coded = 255;
- cpi->prob_last_coded = 128;
- cpi->prob_gf_coded = 128;
- }
- else if (!(rf_intra + rf_inter))
- {
- // This is a trap in case this function is called with cpi->recent_ref_frame_usage[] blank.
- cpi->prob_intra_coded = 63;
- cpi->prob_last_coded = 128;
- cpi->prob_gf_coded = 128;
- }
- else
- {
- cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
-
- if (cpi->prob_intra_coded < 1)
- cpi->prob_intra_coded = 1;
-
- cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
-
- if (cpi->prob_last_coded < 1)
- cpi->prob_last_coded = 1;
-
- cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
- ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
-
- if (cpi->prob_gf_coded < 1)
- cpi->prob_gf_coded = 1;
- }
-
- // update reference frame costs since we can do better than what we got last frame.
-
- if (cpi->common.refresh_alt_ref_frame)
- {
- cpi->prob_intra_coded += 40;
- cpi->prob_last_coded = 200;
- cpi->prob_gf_coded = 1;
- }
- else if (cpi->common.frames_since_golden == 0)
- {
- cpi->prob_last_coded = 214;
- cpi->prob_gf_coded = 1;
- }
- else if (cpi->common.frames_since_golden == 1)
- {
- cpi->prob_last_coded = 192;
- cpi->prob_gf_coded = 220;
- }
- else if (cpi->source_alt_ref_active)
- {
- //int dist = cpi->common.frames_till_alt_ref_frame + cpi->common.frames_since_golden;
- cpi->prob_gf_coded -= 20;
-
- if (cpi->prob_gf_coded < 10)
- cpi->prob_gf_coded = 10;
- }
-
-#endif
-}
-
-
// 1 = key, 0 = inter
static int decide_key_frame(VP8_COMP *cpi)
{
@@ -2972,50 +2440,6 @@ static int decide_key_frame(VP8_COMP *cpi)
// Clear down mmx registers
vp8_clear_system_state(); //__asm emms;
- if ((cpi->compressor_speed == 2) && (cpi->Speed >= 5) && (cpi->sf.RD == 0))
- {
- double change = 1.0 * abs((int)(cpi->intra_error - cpi->last_intra_error)) / (1 + cpi->last_intra_error);
- double change2 = 1.0 * abs((int)(cpi->prediction_error - cpi->last_prediction_error)) / (1 + cpi->last_prediction_error);
- double minerror = cm->MBs * 256;
-
-#if 0
-
- if (10 * cpi->intra_error / (1 + cpi->prediction_error) < 15
- && cpi->prediction_error > minerror
- && (change > .25 || change2 > .25))
- {
- FILE *f = fopen("intra_inter.stt", "a");
-
- if (cpi->prediction_error <= 0)
- cpi->prediction_error = 1;
-
- fprintf(f, "%d %d %d %d %14.4f\n",
- cm->current_video_frame,
- (int) cpi->prediction_error,
- (int) cpi->intra_error,
- (int)((10 * cpi->intra_error) / cpi->prediction_error),
- change);
-
- fclose(f);
- }
-
-#endif
-
- cpi->last_intra_error = cpi->intra_error;
- cpi->last_prediction_error = cpi->prediction_error;
-
- if (10 * cpi->intra_error / (1 + cpi->prediction_error) < 15
- && cpi->prediction_error > minerror
- && (change > .25 || change2 > .25))
- {
- /*(change > 1.4 || change < .75)&& cpi->this_frame_percent_intra > cpi->last_frame_percent_intra + 3*/
- return TRUE;
- }
-
- return FALSE;
-
- }
-
// If the following are true we might as well code a key frame
if (((cpi->this_frame_percent_intra == 100) &&
(cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra + 2))) ||
@@ -3041,27 +2465,37 @@ static int decide_key_frame(VP8_COMP *cpi)
return code_key_frame;
}
-#if !CONFIG_EXTEND_QRANGE
-#define FIRSTPASS_QINDEX 26
-#else
-#define FIRSTPASS_QINDEX 49
-#endif
+int find_fp_qindex()
+{
+ int i;
+
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ if ( vp8_convert_qindex_to_q(i) >= 30.0 )
+ {
+ break;
+ }
+ }
+
+ if ( i == QINDEX_RANGE )
+ i--;
+
+ return i;
+}
-#if !(CONFIG_REALTIME_ONLY)
static void Pass1Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
{
(void) size;
(void) dest;
(void) frame_flags;
- vp8_set_quantizer(cpi, 26);
- scale_and_extend_source(cpi->un_scaled_source, cpi);
+
+ vp8_set_quantizer(cpi, find_fp_qindex());
vp8_first_pass(cpi);
}
-#endif
-
-#if 0
+//#define WRITE_RECON_BUFFER 1
+#if WRITE_RECON_BUFFER
void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
{
@@ -3074,26 +2508,28 @@ void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
yframe = fopen(filename, "wb");
for (i = 0; i < frame->y_height; i++)
- fwrite(frame->y_buffer + i * frame->y_stride, frame->y_width, 1, yframe);
+ fwrite(frame->y_buffer + i * frame->y_stride,
+ frame->y_width, 1, yframe);
fclose(yframe);
sprintf(filename, "cx\\u%04d.raw", this_frame);
yframe = fopen(filename, "wb");
for (i = 0; i < frame->uv_height; i++)
- fwrite(frame->u_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
+ fwrite(frame->u_buffer + i * frame->uv_stride,
+ frame->uv_width, 1, yframe);
fclose(yframe);
sprintf(filename, "cx\\v%04d.raw", this_frame);
yframe = fopen(filename, "wb");
for (i = 0; i < frame->uv_height; i++)
- fwrite(frame->v_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
+ fwrite(frame->v_buffer + i * frame->uv_stride,
+ frame->uv_width, 1, yframe);
fclose(yframe);
}
#endif
-// return of 0 means drop frame
// Function to test for conditions that indeicate we should loop
// back and recode a frame.
@@ -3257,11 +2693,6 @@ void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
}
-#if CONFIG_MULTITHREAD
- if (cpi->b_multi_threaded)
- sem_post(&cpi->h_event_end_lpf); /* signal that we have set filter_level */
-#endif
-
if (cm->filter_level > 0)
{
vp8cx_set_alt_lf_level(cpi, cm->filter_level);
@@ -3272,6 +2703,106 @@ void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
}
+// This function updates the reference frame prediction stats
+static void update_refpred_stats( VP8_COMP *cpi )
+{
+ VP8_COMMON *const cm = & cpi->common;
+ MACROBLOCKD *const xd = & cpi->mb.e_mbd;
+
+ int mb_row, mb_col;
+ int i;
+ int tot_count;
+ int ref_pred_count[PREDICTION_PROBS][2];
+ vp8_prob new_pred_probs[PREDICTION_PROBS];
+ unsigned char pred_context;
+ unsigned char pred_flag;
+
+ int old_cost, new_cost;
+
+ // Clear the prediction hit counters
+ vpx_memset(ref_pred_count, 0, sizeof(ref_pred_count));
+
+ // Set the prediction probability structures to defaults
+ if ( cm->frame_type == KEY_FRAME )
+ {
+ // Set the prediction probabilities to defaults
+ cm->ref_pred_probs[0] = 120;
+ cm->ref_pred_probs[1] = 80;
+ cm->ref_pred_probs[2] = 40;
+
+ vpx_memset(cpi->ref_pred_probs_update, 0,
+ sizeof(cpi->ref_pred_probs_update) );
+ }
+ else
+ {
+ // For non-key frames.......
+
+ // Scan through the macroblocks and collate prediction counts.
+ xd->mode_info_context = cm->mi;
+ for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+ {
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+ {
+ // Get the prediction context and status
+ pred_flag = get_pred_flag( xd, PRED_REF );
+ pred_context = get_pred_context( cm, xd, PRED_REF );
+
+ // Count prediction success
+ ref_pred_count[pred_context][pred_flag]++;
+
+ // Step on to the next mb
+ xd->mode_info_context++;
+ }
+
+ // this is to account for the border in mode_info_context
+ xd->mode_info_context++;
+ }
+
+ // From the prediction counts set the probabilities for each context
+ for ( i = 0; i < PREDICTION_PROBS; i++ )
+ {
+ // MB reference frame not relevent to key frame encoding
+ if ( cm->frame_type != KEY_FRAME )
+ {
+ // Work out the probabilities for the reference frame predictor
+ tot_count = ref_pred_count[i][0] + ref_pred_count[i][1];
+ if ( tot_count )
+ {
+ new_pred_probs[i] =
+ ( ref_pred_count[i][0] * 255 ) / tot_count;
+
+ // Clamp to minimum allowed value
+ new_pred_probs[i] += !new_pred_probs[i];
+ }
+ else
+ new_pred_probs[i] = 128;
+ }
+ else
+ new_pred_probs[i] = 128;
+
+ // Decide whether or not to update the reference frame probs.
+ // Returned costs are in 1/256 bit units.
+ old_cost =
+ (ref_pred_count[i][0] * vp8_cost_zero(cm->ref_pred_probs[i])) +
+ (ref_pred_count[i][1] * vp8_cost_one(cm->ref_pred_probs[i]));
+
+ new_cost =
+ (ref_pred_count[i][0] * vp8_cost_zero(new_pred_probs[i])) +
+ (ref_pred_count[i][1] * vp8_cost_one(new_pred_probs[i]));
+
+ // Cost saving must be >= 8 bits (2048 in these units)
+ if ( (old_cost - new_cost) >= 2048 )
+ {
+ cpi->ref_pred_probs_update[i] = 1;
+ cm->ref_pred_probs[i] = new_pred_probs[i];
+ }
+ else
+ cpi->ref_pred_probs_update[i] = 0;
+
+ }
+ }
+}
+
static void encode_frame_to_data_rate
(
VP8_COMP *cpi,
@@ -3280,6 +2811,9 @@ static void encode_frame_to_data_rate
unsigned int *frame_flags
)
{
+ VP8_COMMON *cm = &cpi->common;
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
+
int Q;
int frame_over_shoot_limit;
int frame_under_shoot_limit;
@@ -3295,49 +2829,21 @@ static void encode_frame_to_data_rate
int zbin_oq_low = 0;
int top_index;
int bottom_index;
- VP8_COMMON *cm = &cpi->common;
int active_worst_qchanged = FALSE;
int overshoot_seen = FALSE;
int undershoot_seen = FALSE;
- int drop_mark = cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100;
- int drop_mark75 = drop_mark * 2 / 3;
- int drop_mark50 = drop_mark / 4;
- int drop_mark25 = drop_mark / 8;
-
// Clear down mmx registers to allow floating point in what follows
vp8_clear_system_state();
- // Test code for segmentation of gf/arf (0,0)
- //segmentation_test_function((VP8_PTR) cpi);
-
- if (cpi->compressor_speed == 2)
- {
- if(cpi->oxcf.auto_key && cm->frame_type != KEY_FRAME)
- {
- if(cpi->force_next_frame_intra)
- {
- cm->frame_type = KEY_FRAME; /* delayed intra frame */
- }
- }
- cpi->force_next_frame_intra = 0;
- }
-
- // For an alt ref frame in 2 pass we skip the call to the second pass function that sets the target bandwidth
-#if !(CONFIG_REALTIME_ONLY)
-
- if (cpi->pass == 2)
+ // For an alt ref frame in 2 pass we skip the call to the second
+ // pass function that sets the target bandwidth so must set it here
+ if (cpi->common.refresh_alt_ref_frame)
{
- if (cpi->common.refresh_alt_ref_frame)
- {
- cpi->per_frame_bandwidth = cpi->twopass.gf_bits; // Per frame bit target for the alt ref frame
- cpi->target_bandwidth = cpi->twopass.gf_bits * cpi->output_frame_rate; // per second target bitrate
- }
+ cpi->per_frame_bandwidth = cpi->twopass.gf_bits; // Per frame bit target for the alt ref frame
+ cpi->target_bandwidth = cpi->twopass.gf_bits * cpi->output_frame_rate; // per second target bitrate
}
- else
-#endif
- cpi->per_frame_bandwidth = (int)(cpi->target_bandwidth / cpi->output_frame_rate);
// Default turn off buffer to buffer copying
cm->copy_buffer_to_gf = 0;
@@ -3352,12 +2858,9 @@ static void encode_frame_to_data_rate
// is above a threshold
cpi->zbin_mode_boost = 0;
cpi->zbin_mode_boost_enabled = TRUE;
- if (cpi->pass == 2)
+ if ( cpi->gfu_boost <= 400 )
{
- if ( cpi->gfu_boost <= 400 )
- {
- cpi->zbin_mode_boost_enabled = FALSE;
- }
+ cpi->zbin_mode_boost_enabled = FALSE;
}
// Current default encoder behaviour for the altref sign bias
@@ -3376,10 +2879,8 @@ static void encode_frame_to_data_rate
cm->frame_type = KEY_FRAME;
}
- // Set default state for segment and mode based loop filter update flags
- cpi->mb.e_mbd.update_mb_segmentation_map = 0;
- cpi->mb.e_mbd.update_mb_segmentation_data = 0;
- cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+ // Set default state for segment based loop filter update flags
+ xd->mode_ref_lf_delta_update = 0;
// Set various flags etc to special state if it is a key frame
if (cm->frame_type == KEY_FRAME)
@@ -3390,10 +2891,10 @@ static void encode_frame_to_data_rate
setup_features(cpi);
// If segmentation is enabled force a map update for key frames
- if (cpi->mb.e_mbd.segmentation_enabled)
+ if (xd->segmentation_enabled)
{
- cpi->mb.e_mbd.update_mb_segmentation_map = 1;
- cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+ xd->update_mb_segmentation_map = 1;
+ xd->update_mb_segmentation_data = 1;
}
// The alternate reference frame cannot be active for a key frame
@@ -3406,107 +2907,14 @@ static void encode_frame_to_data_rate
}
}
- // Test code for segmentation
- //if ( (cm->frame_type == KEY_FRAME) || ((cm->current_video_frame % 2) == 0))
- //if ( (cm->current_video_frame % 2) == 0 )
- // enable_segmentation((VP8_PTR)cpi);
- //else
- // disable_segmentation((VP8_PTR)cpi);
-
-#if 0
- // Experimental code for lagged compress and one pass
- // Initialise one_pass GF frames stats
- // Update stats used for GF selection
- //if ( cpi->pass == 0 )
- {
- cpi->one_pass_frame_index = cm->current_video_frame % MAX_LAG_BUFFERS;
-
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frames_so_far = 0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_intra_error = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_coded_error = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_pcnt_inter = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_pcnt_motion = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvr = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvr_abs = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvc = 0.0;
- cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvc_abs = 0.0;
- }
-#endif
-
- update_rd_ref_frame_probs(cpi);
+//#if !CONFIG_COMPRED
+ // This function has been deprecated for now but we may want to do
+ // something here at a late date
+ //update_rd_ref_frame_probs(cpi);
+//#endif
- if (cpi->drop_frames_allowed)
- {
- // The reset to decimation 0 is only done here for one pass.
- // Once it is set two pass leaves decimation on till the next kf.
- if ((cpi->buffer_level > drop_mark) && (cpi->decimation_factor > 0))
- cpi->decimation_factor --;
-
- if (cpi->buffer_level > drop_mark75 && cpi->decimation_factor > 0)
- cpi->decimation_factor = 1;
-
- else if (cpi->buffer_level < drop_mark25 && (cpi->decimation_factor == 2 || cpi->decimation_factor == 3))
- {
- cpi->decimation_factor = 3;
- }
- else if (cpi->buffer_level < drop_mark50 && (cpi->decimation_factor == 1 || cpi->decimation_factor == 2))
- {
- cpi->decimation_factor = 2;
- }
- else if (cpi->buffer_level < drop_mark75 && (cpi->decimation_factor == 0 || cpi->decimation_factor == 1))
- {
- cpi->decimation_factor = 1;
- }
-
- //vpx_log("Encoder: Decimation Factor: %d \n",cpi->decimation_factor);
- }
-
- // The following decimates the frame rate according to a regular pattern (i.e. to 1/2 or 2/3 frame rate)
- // This can be used to help prevent buffer under-run in CBR mode. Alternatively it might be desirable in
- // some situations to drop frame rate but throw more bits at each frame.
- //
- // Note that dropping a key frame can be problematic if spatial resampling is also active
- if (cpi->decimation_factor > 0)
- {
- switch (cpi->decimation_factor)
- {
- case 1:
- cpi->per_frame_bandwidth = cpi->per_frame_bandwidth * 3 / 2;
- break;
- case 2:
- cpi->per_frame_bandwidth = cpi->per_frame_bandwidth * 5 / 4;
- break;
- case 3:
- cpi->per_frame_bandwidth = cpi->per_frame_bandwidth * 5 / 4;
- break;
- }
-
- // Note that we should not throw out a key frame (especially when spatial resampling is enabled).
- if ((cm->frame_type == KEY_FRAME)) // && cpi->oxcf.allow_spatial_resampling )
- {
- cpi->decimation_count = cpi->decimation_factor;
- }
- else if (cpi->decimation_count > 0)
- {
- cpi->decimation_count --;
- cpi->bits_off_target += cpi->av_per_frame_bandwidth;
- if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
- cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
-
- cm->current_video_frame++;
- cpi->frames_since_key++;
-
-#if CONFIG_INTERNAL_STATS
- cpi->count ++;
-#endif
-
- cpi->buffer_level = cpi->bits_off_target;
-
- return;
- }
- else
- cpi->decimation_count = cpi->decimation_factor;
- }
+ // Test code for new segment features
+ init_seg_features( cpi );
// Decide how big to make the frame
if (!vp8_pick_frame_size(cpi))
@@ -3516,149 +2924,83 @@ static void encode_frame_to_data_rate
return;
}
- // Reduce active_worst_allowed_q for CBR if our buffer is getting too full.
- // This has a knock on effect on active best quality as well.
- // For CBR if the buffer reaches its maximum level then we can no longer
- // save up bits for later frames so we might as well use them up
- // on the current frame.
- if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
- (cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode)
- {
- int Adjustment = cpi->active_worst_quality / 4; // Max adjustment is 1/4
+ vp8_clear_system_state();
- if (Adjustment)
- {
- int buff_lvl_step;
+ // Set an active best quality and if necessary active worst quality
+ Q = cpi->active_worst_quality;
- if (cpi->buffer_level < cpi->oxcf.maximum_buffer_size)
- {
- buff_lvl_step = (cpi->oxcf.maximum_buffer_size - cpi->oxcf.optimal_buffer_level) / Adjustment;
+ if ( cm->frame_type == KEY_FRAME )
+ {
+ if (cpi->gfu_boost > 600)
+ cpi->active_best_quality = kf_low_motion_minq[Q];
+ else
+ cpi->active_best_quality = kf_high_motion_minq[Q];
- if (buff_lvl_step)
- Adjustment = (cpi->buffer_level - cpi->oxcf.optimal_buffer_level) / buff_lvl_step;
- else
- Adjustment = 0;
- }
+ // Special case for key frames forced because we have reached
+ // the maximum key frame interval. Here force the Q to a range
+ // based on the ambient Q to reduce the risk of popping
+ if ( cpi->this_key_frame_forced )
+ {
+ int delta_qindex;
+ int qindex = cpi->last_boosted_qindex;
- cpi->active_worst_quality -= Adjustment;
+ delta_qindex = compute_qdelta( cpi, qindex,
+ (qindex * 0.75) );
- if(cpi->active_worst_quality < cpi->active_best_quality)
- cpi->active_worst_quality = cpi->active_best_quality;
+ cpi->active_best_quality = qindex + delta_qindex;
+ if (cpi->active_best_quality < cpi->best_quality)
+ cpi->active_best_quality = cpi->best_quality;
}
}
- // Set an active best quality and if necessary active worst quality
- // There is some odd behaviour for one pass here that needs attention.
- if ( (cpi->pass == 2) || (cpi->ni_frames > 150))
+ else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
{
- vp8_clear_system_state();
-
- Q = cpi->active_worst_quality;
-
- if ( cm->frame_type == KEY_FRAME )
+ // Use the lower of cpi->active_worst_quality and recent
+ // average Q as basis for GF/ARF Q limit unless last frame was
+ // a key frame.
+ if ( (cpi->frames_since_key > 1) &&
+ (cpi->avg_frame_qindex < cpi->active_worst_quality) )
{
- if ( cpi->pass == 2 )
- {
- if (cpi->gfu_boost > 600)
- cpi->active_best_quality = kf_low_motion_minq[Q];
- else
- cpi->active_best_quality = kf_high_motion_minq[Q];
-
- // Special case for key frames forced because we have reached
- // the maximum key frame interval. Here force the Q to a range
- // based on the ambient Q to reduce the risk of popping
- if ( cpi->this_key_frame_forced )
- {
- if ( cpi->active_best_quality > cpi->avg_frame_qindex * 7/8)
- cpi->active_best_quality = cpi->avg_frame_qindex * 7/8;
- else if ( cpi->active_best_quality < cpi->avg_frame_qindex >> 2 )
- cpi->active_best_quality = cpi->avg_frame_qindex >> 2;
- }
- }
- // One pass more conservative
- else
- cpi->active_best_quality = kf_high_motion_minq[Q];
+ Q = cpi->avg_frame_qindex;
}
- else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
+ // For constrained quality dont allow Q less than the cq level
+ if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+ (Q < cpi->cq_target_quality) )
{
- // Use the lower of cpi->active_worst_quality and recent
- // average Q as basis for GF/ARF Q limit unless last frame was
- // a key frame.
- if ( (cpi->frames_since_key > 1) &&
- (cpi->avg_frame_qindex < cpi->active_worst_quality) )
- {
- Q = cpi->avg_frame_qindex;
-
- if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
- (Q < cpi->oxcf.cq_level) )
- {
- Q = cpi->oxcf.cq_level;
- }
- }
-
- if ( cpi->pass == 2 )
- {
- if ( cpi->gfu_boost > 1000 )
- cpi->active_best_quality = gf_low_motion_minq[Q];
- else if ( cpi->gfu_boost < 400 )
- cpi->active_best_quality = gf_high_motion_minq[Q];
- else
- cpi->active_best_quality = gf_mid_motion_minq[Q];
- }
- // One pass more conservative
- else
- cpi->active_best_quality = gf_high_motion_minq[Q];
+ Q = cpi->cq_target_quality;
}
- else
- {
- cpi->active_best_quality = inter_minq[Q];
- // For the constant/constrained quality mode we dont want
- // the quality to rise above the cq level.
- if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
- (cpi->active_best_quality < cpi->cq_target_quality) )
- {
- // If we are strongly undershooting the target rate in the last
- // frames then use the user passed in cq value not the auto
- // cq value.
- if ( cpi->rolling_actual_bits < cpi->min_frame_bandwidth )
- cpi->active_best_quality = cpi->oxcf.cq_level;
- else
- cpi->active_best_quality = cpi->cq_target_quality;
- }
- }
+ if ( cpi->gfu_boost > 1000 )
+ cpi->active_best_quality = gf_low_motion_minq[Q];
+ else if ( cpi->gfu_boost < 400 )
+ cpi->active_best_quality = gf_high_motion_minq[Q];
+ else
+ cpi->active_best_quality = gf_mid_motion_minq[Q];
- // If CBR and the buffer is as full then it is reasonable to allow
- // higher quality on the frames to prevent bits just going to waste.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+ // Constrained quality use slightly lower active best.
+ if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY )
{
- // Note that the use of >= here elliminates the risk of a devide
- // by 0 error in the else if clause
- if (cpi->buffer_level >= cpi->oxcf.maximum_buffer_size)
- cpi->active_best_quality = cpi->best_quality;
-
- else if (cpi->buffer_level > cpi->oxcf.optimal_buffer_level)
- {
- int Fraction = ((cpi->buffer_level - cpi->oxcf.optimal_buffer_level) * 128) / (cpi->oxcf.maximum_buffer_size - cpi->oxcf.optimal_buffer_level);
- int min_qadjustment = ((cpi->active_best_quality - cpi->best_quality) * Fraction) / 128;
-
- cpi->active_best_quality -= min_qadjustment;
- }
+ cpi->active_best_quality =
+ cpi->active_best_quality * 15/16;
}
}
- // Make sure constrained quality mode limits are adhered to for the first
- // few frames of one pass encodes
- else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
+ else
{
- if ( (cm->frame_type == KEY_FRAME) ||
- cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame )
- {
- cpi->active_best_quality = cpi->best_quality;
- }
- else if (cpi->active_best_quality < cpi->cq_target_quality)
+ cpi->active_best_quality = inter_minq[Q];
+
+ // For the constant/constrained quality mode we dont want
+ // q to fall below the cq level.
+ if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+ (cpi->active_best_quality < cpi->cq_target_quality) )
{
- cpi->active_best_quality = cpi->cq_target_quality;
+ // If we are strongly undershooting the target rate in the last
+ // frames then use the user passed in cq value not the auto
+ // cq value.
+ if ( cpi->rolling_actual_bits < cpi->min_frame_bandwidth )
+ cpi->active_best_quality = cpi->oxcf.cq_level;
+ else
+ cpi->active_best_quality = cpi->cq_target_quality;
}
}
@@ -3668,11 +3010,23 @@ static void encode_frame_to_data_rate
if (cpi->active_best_quality < cpi->best_quality)
cpi->active_best_quality = cpi->best_quality;
- else if (cpi->active_best_quality > cpi->active_worst_quality)
- cpi->active_best_quality = cpi->active_worst_quality;
- // Determine initial Q to try
- Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+ if (cpi->active_best_quality > cpi->worst_quality)
+ cpi->active_best_quality = cpi->worst_quality;
+
+ if ( cpi->active_worst_quality < cpi->active_best_quality )
+ cpi->active_worst_quality = cpi->active_best_quality;
+
+ // Specuial case code to try and match quality with forced key frames
+ if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
+ {
+ Q = cpi->last_boosted_qindex;
+ }
+ else
+ {
+ // Determine initial Q to try
+ Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+ }
last_zbin_oq = cpi->zbin_over_quant;
// Set highest allowed value for Zbin over quant
@@ -3683,10 +3037,6 @@ static void encode_frame_to_data_rate
else
zbin_oq_high = ZBIN_OQ_MAX;
- // Setup background Q adjustment for error resilliant mode
- if (cpi->cyclic_refresh_mode_enabled)
- cyclic_background_refresh(cpi, Q, 0);
-
vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
// Limit Q range for the adaptive loop.
@@ -3699,9 +3049,15 @@ static void encode_frame_to_data_rate
loop_count = 0;
+#if CONFIG_HIGH_PRECISION_MV
+ /* Decide this based on various factors */
+ if (cm->frame_type != KEY_FRAME)
+ {
+ xd->allow_high_precision_mv = (Q < HIGH_PRECISION_MV_QTHRESH);
+ }
+#endif
- scale_and_extend_source(cpi->un_scaled_source, cpi);
-#if !(CONFIG_REALTIME_ONLY) && CONFIG_POSTPROC
+#if CONFIG_POSTPROC
if (cpi->oxcf.noise_sensitivity > 0)
{
@@ -3758,11 +3114,6 @@ static void encode_frame_to_data_rate
{
vp8_clear_system_state(); //__asm emms;
- /*
- if(cpi->is_src_frame_alt_ref)
- Q = 127;
- */
-
vp8_set_quantizer(cpi, Q);
this_q = Q;
@@ -3810,7 +3161,8 @@ static void encode_frame_to_data_rate
*/
}
- //as this is for cost estimate, let's make sure it does not go extreme eitehr way
+ // as this is for cost estimate, let's make sure it does not
+ // get extreme either way
if (cpi->prob_skip_false < 5)
cpi->prob_skip_false = 5;
@@ -3822,25 +3174,13 @@ static void encode_frame_to_data_rate
}
-
-#if 0
-
- if (cpi->pass != 1)
- {
- FILE *f = fopen("skip.stt", "a");
- fprintf(f, "%d, %d, %4d ", cpi->common.refresh_golden_frame, cpi->common.refresh_alt_ref_frame, cpi->prob_skip_false);
- fclose(f);
- }
-
-#endif
-
}
+ // Set up entropy depending on frame type.
if (cm->frame_type == KEY_FRAME)
- {
- resize_key_frame(cpi);
vp8_setup_key_frame(cpi);
- }
+ else
+ vp8_setup_inter_frame(cpi);
// transform / motion compensation build reconstruction frame
vp8_encode_frame(cpi);
@@ -3850,96 +3190,11 @@ static void encode_frame_to_data_rate
vp8_clear_system_state(); //__asm emms;
-#if 0
- if (cpi->pass != 1)
- {
- FILE *f = fopen("q_used.stt", "a");
- fprintf(f, "%4d, %4d, %8d\n", cpi->common.current_video_frame,
- cpi->common.base_qindex, cpi->projected_frame_size);
- fclose(f);
- }
-#endif
-
-
- // Test to see if the stats generated for this frame indicate that we should have coded a key frame
- // (assuming that we didn't)!
- if (cpi->pass != 2 && cpi->oxcf.auto_key && cm->frame_type != KEY_FRAME)
- {
- int key_frame_decision = decide_key_frame(cpi);
-
- if (cpi->compressor_speed == 2)
- {
- /* we don't do re-encoding in realtime mode
- * if key frame is decided than we force it on next frame */
- cpi->force_next_frame_intra = key_frame_decision;
- }
- else if (key_frame_decision)
- {
- // Reset all our sizing numbers and recode
- cm->frame_type = KEY_FRAME;
-
- vp8_pick_frame_size(cpi);
-
- // Clear the Alt reference frame active flag when we have a key frame
- cpi->source_alt_ref_active = FALSE;
-
- // Reset the loop filter deltas and segmentation map
- setup_features(cpi);
-
- // If segmentation is enabled force a map update for key frames
- if (cpi->mb.e_mbd.segmentation_enabled)
- {
- cpi->mb.e_mbd.update_mb_segmentation_map = 1;
- cpi->mb.e_mbd.update_mb_segmentation_data = 1;
- }
-
- vp8_restore_coding_context(cpi);
-
- Q = vp8_regulate_q(cpi, cpi->this_frame_target);
-
- vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
-
- // Limit Q range for the adaptive loop.
- bottom_index = cpi->active_best_quality;
- top_index = cpi->active_worst_quality;
- q_low = cpi->active_best_quality;
- q_high = cpi->active_worst_quality;
-
- loop_count++;
- Loop = TRUE;
-
- continue;
- }
- }
-
- vp8_clear_system_state();
-
if (frame_over_shoot_limit == 0)
frame_over_shoot_limit = 1;
- // Are we are overshooting and up against the limit of active max Q.
- if (((cpi->pass != 2) || (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)) &&
- (Q == cpi->active_worst_quality) &&
- (cpi->active_worst_quality < cpi->worst_quality) &&
- (cpi->projected_frame_size > frame_over_shoot_limit))
- {
- int over_size_percent = ((cpi->projected_frame_size - frame_over_shoot_limit) * 100) / frame_over_shoot_limit;
-
- // If so is there any scope for relaxing it
- while ((cpi->active_worst_quality < cpi->worst_quality) && (over_size_percent > 0))
- {
- cpi->active_worst_quality++;
- top_index = cpi->active_worst_quality;
- over_size_percent = (int)(over_size_percent * 0.96); // Assume 1 qstep = about 4% on frame size.
- }
-
- // If we have updated the active max Q do not call vp8_update_rate_correction_factors() this loop.
- active_worst_qchanged = TRUE;
- }
- else
- active_worst_qchanged = FALSE;
+ active_worst_qchanged = FALSE;
-#if !(CONFIG_REALTIME_ONLY)
// Special case handling for forced key frames
if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
{
@@ -3948,23 +3203,35 @@ static void encode_frame_to_data_rate
&cm->yv12_fb[cm->new_fb_idx],
IF_RTCD(&cpi->rtcd.variance));
+ int high_err_target = cpi->ambient_err;
+ int low_err_target = ((cpi->ambient_err * 3) >> 2);
+
+ // Prevent possible divide by zero error below for perfect KF
+ kf_err += (!kf_err);
+
// The key frame is not good enough
- if ( kf_err > ((cpi->ambient_err * 7) >> 3) )
+ if ( (kf_err > high_err_target) &&
+ (cpi->projected_frame_size <= frame_over_shoot_limit) )
{
// Lower q_high
q_high = (Q > q_low) ? (Q - 1) : q_low;
// Adjust Q
- Q = (q_high + q_low) >> 1;
+ Q = (Q * high_err_target) / kf_err;
+ if ( Q < ((q_high + q_low) >> 1))
+ Q = (q_high + q_low) >> 1;
}
// The key frame is much better than the previous frame
- else if ( kf_err < (cpi->ambient_err >> 1) )
+ else if ( (kf_err < low_err_target) &&
+ (cpi->projected_frame_size >= frame_under_shoot_limit) )
{
// Raise q_low
q_low = (Q < q_high) ? (Q + 1) : q_high;
// Adjust Q
- Q = (q_high + q_low + 1) >> 1;
+ Q = (Q * low_err_target) / kf_err;
+ if ( Q > ((q_high + q_low + 1) >> 1))
+ Q = (q_high + q_low + 1) >> 1;
}
// Clamp Q to upper and lower limits:
@@ -3990,14 +3257,12 @@ static void encode_frame_to_data_rate
// Frame is too large
if (cpi->projected_frame_size > cpi->this_frame_target)
{
- //if ( cpi->zbin_over_quant == 0 )
q_low = (Q < q_high) ? (Q + 1) : q_high; // Raise Qlow as to at least the current value
if (cpi->zbin_over_quant > 0) // If we are using over quant do the same for zbin_oq_low
zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
- //if ( undershoot_seen || (Q == MAXQ) )
- if (undershoot_seen)
+ if ( undershoot_seen || (loop_count > 1) )
{
// Update rate_correction_factor unless cpi->active_worst_quality has changed.
if (!active_worst_qchanged)
@@ -4040,7 +3305,7 @@ static void encode_frame_to_data_rate
else // else lower zbin_oq_high
zbin_oq_high = (cpi->zbin_over_quant > zbin_oq_low) ? (cpi->zbin_over_quant - 1) : zbin_oq_low;
- if (overshoot_seen)
+ if ( overshoot_seen || (loop_count > 1) )
{
// Update rate_correction_factor unless cpi->active_worst_quality has changed.
if (!active_worst_qchanged)
@@ -4097,7 +3362,6 @@ static void encode_frame_to_data_rate
last_zbin_oq = cpi->zbin_over_quant;
}
else
-#endif
Loop = FALSE;
if (cpi->is_src_frame_alt_ref)
@@ -4190,47 +3454,45 @@ static void encode_frame_to_data_rate
// For inter frames the current default behavior is that when
// cm->refresh_golden_frame is set we copy the old GF over to the ARF buffer
// This is purely an encoder decision at present.
- if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame)
+ if (cm->refresh_golden_frame)
cm->copy_buffer_to_arf = 2;
- else
- cm->copy_buffer_to_arf = 0;
cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
-#if CONFIG_MULTITHREAD
- if (cpi->b_multi_threaded)
- {
- sem_post(&cpi->h_event_start_lpf); /* start loopfilter in separate thread */
- }
+#if WRITE_RECON_BUFFER
+ if(cm->show_frame)
+ write_cx_frame_to_file(cm->frame_to_show,
+ cm->current_video_frame);
else
+ write_cx_frame_to_file(cm->frame_to_show,
+ cm->current_video_frame+1000);
#endif
+
{
loopfilter_frame(cpi, cm);
}
update_reference_frames(cm);
- if (cpi->oxcf.error_resilient_mode)
+ // Work out the segment probabilites if segmentation is enabled and
+ // the map is due to be updated
+ if (xd->segmentation_enabled && xd->update_mb_segmentation_map)
{
- cm->refresh_entropy_probs = 0;
+ // Select the coding strategy for the segment map (temporal or spatial)
+ choose_segmap_coding_method( cpi );
+
+ // Take a copy of the segment map if it changed for future comparison
+ vpx_memcpy( cm->last_frame_seg_map,
+ cpi->segmentation_map, cm->MBs );
}
-#if CONFIG_MULTITHREAD
- /* wait that filter_level is picked so that we can continue with stream packing */
- if (cpi->b_multi_threaded)
- sem_wait(&cpi->h_event_end_lpf);
-#endif
+ // Update the common prediction model probabilities to reflect
+ // the what was seen in the current frame.
+ update_refpred_stats( cpi );
// build the bitstream
vp8_pack_bitstream(cpi, dest, size);
-#if CONFIG_MULTITHREAD
- /* wait for loopfilter thread done */
- if (cpi->b_multi_threaded)
- {
- sem_wait(&cpi->h_event_end_lpf);
- }
-#endif
/* Move storing frame_type out of the above loop since it is also
* needed in motion search besides loopfilter */
@@ -4245,6 +3507,20 @@ static void encode_frame_to_data_rate
cpi->last_q[cm->frame_type] = cm->base_qindex;
+ // Keep record of last boosted (KF/KF/ARF) Q value.
+ // If the current frame is coded at a lower Q then we also update it.
+ // If all mbs in this group are skipped only update if the Q value is
+ // better than that already stored.
+ // This is used to help set quality in forced key frames to reduce popping
+ if ( (cm->base_qindex < cpi->last_boosted_qindex) ||
+ ( (cpi->static_mb_pct < 100) &&
+ ( (cm->frame_type == KEY_FRAME) ||
+ cm->refresh_alt_ref_frame ||
+ (cm->refresh_golden_frame && !cpi->is_src_frame_alt_ref) ) ) )
+ {
+ cpi->last_boosted_qindex = cm->base_qindex;
+ }
+
if (cm->frame_type == KEY_FRAME)
{
vp8_adjust_key_frame_context(cpi);
@@ -4258,63 +3534,13 @@ static void encode_frame_to_data_rate
if ((cm->frame_type != KEY_FRAME) && !cm->refresh_golden_frame && !cm->refresh_alt_ref_frame)
{
cpi->ni_frames++;
+ cpi->tot_q += vp8_convert_qindex_to_q(Q);
+ cpi->avg_q = cpi->tot_q / (double)cpi->ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU
// frames).
- if ( cpi->pass == 2 )
- {
- cpi->ni_tot_qi += Q;
- cpi->ni_av_qi = (cpi->ni_tot_qi / cpi->ni_frames);
- }
- else
- {
- // Damp value for first few frames
- if (cpi->ni_frames > 150 )
- {
- cpi->ni_tot_qi += Q;
- cpi->ni_av_qi = (cpi->ni_tot_qi / cpi->ni_frames);
- }
- // For one pass, early in the clip ... average the current frame Q
- // value with the worstq entered by the user as a dampening measure
- else
- {
- cpi->ni_tot_qi += Q;
- cpi->ni_av_qi = ((cpi->ni_tot_qi / cpi->ni_frames) + cpi->worst_quality + 1) / 2;
- }
-
- // If the average Q is higher than what was used in the last frame
- // (after going through the recode loop to keep the frame size within range)
- // then use the last frame value - 1.
- // The -1 is designed to stop Q and hence the data rate, from progressively
- // falling away during difficult sections, but at the same time reduce the number of
- // itterations around the recode loop.
- if (Q > cpi->ni_av_qi)
- cpi->ni_av_qi = Q - 1;
- }
- }
-
-#if 0
-
- // If the frame was massively oversize and we are below optimal buffer level drop next frame
- if ((cpi->drop_frames_allowed) &&
- (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
- (cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
- (cpi->projected_frame_size > (4 * cpi->this_frame_target)))
- {
- cpi->drop_frame = TRUE;
- }
-
-#endif
-
- // Set the count for maximum consequative dropped frames based upon the ratio of
- // this frame size to the target average per frame bandwidth.
- // (cpi->av_per_frame_bandwidth > 0) is just a sanity check to prevent / 0.
- if (cpi->drop_frames_allowed && (cpi->av_per_frame_bandwidth > 0))
- {
- cpi->max_drop_count = cpi->projected_frame_size / cpi->av_per_frame_bandwidth;
-
- if (cpi->max_drop_count > cpi->max_consec_dropped_frames)
- cpi->max_drop_count = cpi->max_consec_dropped_frames;
+ cpi->ni_tot_qi += Q;
+ cpi->ni_av_qi = (cpi->ni_tot_qi / cpi->ni_frames);
}
// Update the buffer level variable.
@@ -4324,7 +3550,7 @@ static void encode_frame_to_data_rate
else
cpi->bits_off_target += cpi->av_per_frame_bandwidth - cpi->projected_frame_size;
- // Clip the buffer level to the maximum specified buffer size
+ // Clip the buffer level at the maximum buffer size
if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
@@ -4387,45 +3613,64 @@ static void encode_frame_to_data_rate
vp8_clear_system_state(); //__asm emms;
- if (cpi->twopass.total_coded_error_left != 0.0)
- fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6d %6d"
- "%6d %6d %6d %5d %5d %5d %8d %8.2f %10d %10.3f"
+ if (cpi->twopass.total_left_stats->coded_error != 0.0)
+ fprintf(f, "%10d %10d %10d %10d %10d %10d %10d"
+ "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
+ "%6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%10.3f %8d\n",
cpi->common.current_video_frame, cpi->this_frame_target,
cpi->projected_frame_size,
(cpi->projected_frame_size - cpi->this_frame_target),
(int)cpi->total_target_vs_actual,
(cpi->oxcf.starting_buffer_level-cpi->bits_off_target),
- (int)cpi->total_actual_bits, cm->base_qindex,
- cpi->active_best_quality, cpi->active_worst_quality,
- cpi->ni_av_qi, cpi->cq_target_quality, cpi->zbin_over_quant,
+ (int)cpi->total_actual_bits,
+ vp8_convert_qindex_to_q(cm->base_qindex),
+ (double)vp8_dc_quant(cm->base_qindex,0)/4.0,
+ vp8_convert_qindex_to_q(cpi->active_best_quality),
+ vp8_convert_qindex_to_q(cpi->active_worst_quality),
+ cpi->avg_q,
+ vp8_convert_qindex_to_q(cpi->ni_av_qi),
+ vp8_convert_qindex_to_q(cpi->cq_target_quality),
+ cpi->zbin_over_quant,
//cpi->avg_frame_qindex, cpi->zbin_over_quant,
cm->refresh_golden_frame, cm->refresh_alt_ref_frame,
cm->frame_type, cpi->gfu_boost,
- cpi->twopass.est_max_qcorrection_factor, (int)cpi->twopass.bits_left,
- cpi->twopass.total_coded_error_left,
- (double)cpi->twopass.bits_left / cpi->twopass.total_coded_error_left,
+ cpi->twopass.est_max_qcorrection_factor,
+ (int)cpi->twopass.bits_left,
+ cpi->twopass.total_left_stats->coded_error,
+ (double)cpi->twopass.bits_left /
+ cpi->twopass.total_left_stats->coded_error,
cpi->tot_recode_hits);
else
- fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6d %6d"
- "%6d %6d %6d %5d %5d %5d %8d %8.2f %10d %10.3f"
+ fprintf(f, "%10d %10d %10d %10d %10d %10d %10d"
+ "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
+ "%6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%8d\n",
cpi->common.current_video_frame,
cpi->this_frame_target, cpi->projected_frame_size,
(cpi->projected_frame_size - cpi->this_frame_target),
(int)cpi->total_target_vs_actual,
(cpi->oxcf.starting_buffer_level-cpi->bits_off_target),
- (int)cpi->total_actual_bits, cm->base_qindex,
- cpi->active_best_quality, cpi->active_worst_quality,
- cpi->ni_av_qi, cpi->cq_target_quality, cpi->zbin_over_quant,
+ (int)cpi->total_actual_bits,
+ vp8_convert_qindex_to_q(cm->base_qindex),
+ (double)vp8_dc_quant(cm->base_qindex,0)/4.0,
+ vp8_convert_qindex_to_q(cpi->active_best_quality),
+ vp8_convert_qindex_to_q(cpi->active_worst_quality),
+ cpi->avg_q,
+ vp8_convert_qindex_to_q(cpi->ni_av_qi),
+ vp8_convert_qindex_to_q(cpi->cq_target_quality),
+ cpi->zbin_over_quant,
//cpi->avg_frame_qindex, cpi->zbin_over_quant,
cm->refresh_golden_frame, cm->refresh_alt_ref_frame,
cm->frame_type, cpi->gfu_boost,
- cpi->twopass.est_max_qcorrection_factor, (int)cpi->twopass.bits_left,
- cpi->twopass.total_coded_error_left, cpi->tot_recode_hits);
+ cpi->twopass.est_max_qcorrection_factor,
+ (int)cpi->twopass.bits_left,
+ cpi->twopass.total_left_stats->coded_error,
+ cpi->tot_recode_hits);
fclose(f);
+ if ( 0 )
{
FILE *fmodes = fopen("Modes.stt", "a");
int i;
@@ -4446,6 +3691,11 @@ static void encode_frame_to_data_rate
#endif
+#if 0
+ // Debug stats for segment feature experiments.
+ print_seg_map(cpi);
+#endif
+
// If this was a kf or Gf note the Q
if ((cm->frame_type == KEY_FRAME) || cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
cm->last_kf_gf_q = cm->base_qindex;
@@ -4487,16 +3737,12 @@ static void encode_frame_to_data_rate
if (cpi->gold_is_alt)
cpi->ref_frame_flags &= ~VP8_ALT_FLAG;
-
- if (!cpi->oxcf.error_resilient_mode)
- {
- if (cpi->oxcf.play_alternate && cm->refresh_alt_ref_frame && (cm->frame_type != KEY_FRAME))
- // Update the alternate reference frame stats as appropriate.
- update_alt_ref_frame_stats(cpi);
- else
- // Update the Golden frame stats as appropriate.
- update_golden_frame_stats(cpi);
- }
+ if (cpi->oxcf.play_alternate && cm->refresh_alt_ref_frame && (cm->frame_type != KEY_FRAME))
+ // Update the alternate reference frame stats as appropriate.
+ update_alt_ref_frame_stats(cpi);
+ else
+ // Update the Golden frame stats as appropriate.
+ update_golden_frame_stats(cpi);
if (cm->frame_type == KEY_FRAME)
{
@@ -4516,9 +3762,9 @@ static void encode_frame_to_data_rate
}
// Clear the one shot update flags for segmentation map and mode/ref loop filter deltas.
- cpi->mb.e_mbd.update_mb_segmentation_map = 0;
- cpi->mb.e_mbd.update_mb_segmentation_data = 0;
- cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+ xd->update_mb_segmentation_map = 0;
+ xd->update_mb_segmentation_data = 0;
+ xd->mode_ref_lf_delta_update = 0;
// Dont increment frame counters if this was an altref buffer update not a real frame
@@ -4543,16 +3789,20 @@ static void encode_frame_to_data_rate
fclose(recon_file);
}
#endif
-#if 0
- // DEBUG
- if(cm->current_video_frame>173 && cm->current_video_frame<178)
- {
- char filename[512];
- sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame);
- vp8_write_yuv_frame(filename, cm->frame_to_show);
- }
+#ifdef OUTPUT_YUV_REC
+ vp8_write_yuv_rec_frame(cm);
#endif
+ if(cm->show_frame)
+ {
+ vpx_memcpy(cm->prev_mip, cm->mip,
+ (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
+ }
+ else
+ {
+ vpx_memset(cm->prev_mip, 0,
+ (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
+ }
}
@@ -4610,7 +3860,6 @@ static void check_gf_quality(VP8_COMP *cpi)
#endif
}
-#if !(CONFIG_REALTIME_ONLY)
static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
{
@@ -4622,12 +3871,16 @@ static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest,
if (!cpi->common.refresh_alt_ref_frame)
{
+ double lower_bounds_min_rate = FRAME_OVERHEAD_BITS*cpi->oxcf.frame_rate;
double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
*cpi->oxcf.two_pass_vbrmin_section / 100);
+
+ if (two_pass_min_rate < lower_bounds_min_rate)
+ two_pass_min_rate = lower_bounds_min_rate;
+
cpi->twopass.bits_left += (int64_t)(two_pass_min_rate / cpi->oxcf.frame_rate);
}
}
-#endif
//For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.
#if HAVE_ARMV7
@@ -4718,10 +3971,11 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
cpi->source = NULL;
-#if !(CONFIG_REALTIME_ONLY)
+#if CONFIG_HIGH_PRECISION_MV
+ cpi->mb.e_mbd.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV;
+#endif
// Should we code an alternate reference frame
- if (cpi->oxcf.error_resilient_mode == 0 &&
- cpi->oxcf.play_alternate &&
+ if (cpi->oxcf.play_alternate &&
cpi->source_alt_ref_pending)
{
if ((cpi->source = vp8_lookahead_peek(cpi->lookahead,
@@ -4743,7 +3997,6 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
cpi->is_src_frame_alt_ref = 0;
}
}
-#endif
if (!cpi->source)
{
@@ -4770,16 +4023,12 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
else
{
*size = 0;
-#if !(CONFIG_REALTIME_ONLY)
-
if (flush && cpi->pass == 1 && !cpi->twopass.first_pass_done)
{
vp8_end_first_pass(cpi); /* get last stats packet */
cpi->twopass.first_pass_done = 1;
}
-#endif
-
#if HAVE_ARMV7
#if CONFIG_RUNTIME_CPU_DETECT
if (cm->rtcd.flags & HAS_NEON)
@@ -4848,13 +4097,6 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
cpi->last_end_time_stamp_seen = cpi->source->ts_end;
}
- if (cpi->compressor_speed == 2)
- {
- check_gf_quality(cpi);
- vpx_usec_timer_start(&tsctimer);
- vpx_usec_timer_start(&ticktimer);
- }
-
// start with a 0 size frame
*size = 0;
@@ -4893,8 +4135,6 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
assert(i < NUM_YV12_BUFFERS );
}
-#if !(CONFIG_REALTIME_ONLY)
-
if (cpi->pass == 1)
{
Pass1Encode(cpi, size, dest, frame_flags);
@@ -4904,43 +4144,14 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
Pass2Encode(cpi, size, dest, frame_flags);
}
else
-#endif
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
- if (cpi->compressor_speed == 2)
+ if(cm->refresh_entropy_probs)
{
- unsigned int duration, duration2;
- vpx_usec_timer_mark(&tsctimer);
- vpx_usec_timer_mark(&ticktimer);
-
- duration = vpx_usec_timer_elapsed(&ticktimer);
- duration2 = (unsigned int)((double)duration / 2);
-
- if (cm->frame_type != KEY_FRAME)
- {
- if (cpi->avg_encode_time == 0)
- cpi->avg_encode_time = duration;
- else
- cpi->avg_encode_time = (7 * cpi->avg_encode_time + duration) >> 3;
- }
-
- if (duration2)
- {
- //if(*frame_flags!=1)
- {
-
- if (cpi->avg_pick_mode_time == 0)
- cpi->avg_pick_mode_time = duration2;
- else
- cpi->avg_pick_mode_time = (7 * cpi->avg_pick_mode_time + duration2) >> 3;
- }
- }
-
- }
-
- if (cm->refresh_entropy_probs == 0)
- {
- vpx_memcpy(&cm->fc, &cm->lfc, sizeof(cm->fc));
+ if(cm->refresh_alt_ref_frame)
+ vpx_memcpy(&cm->lfc_a, &cm->fc, sizeof(cm->fc));
+ else
+ vpx_memcpy(&cm->lfc, &cm->fc, sizeof(cm->fc));
}
// if its a dropped frame honor the requests on subsequent frames
@@ -5070,29 +4281,6 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
}
}
-#if 0
-
- if (cpi->common.frame_type != 0 && cpi->common.base_qindex == cpi->oxcf.worst_allowed_q)
- {
- skiptruecount += cpi->skip_true_count;
- skipfalsecount += cpi->skip_false_count;
- }
-
-#endif
-#if 0
-
- if (cpi->pass != 1)
- {
- FILE *f = fopen("skip.stt", "a");
- fprintf(f, "frame:%4d flags:%4x Q:%4d P:%4d Size:%5d\n", cpi->common.current_video_frame, *frame_flags, cpi->common.base_qindex, cpi->prob_skip_false, *size);
-
- if (cpi->is_src_frame_alt_ref == 1)
- fprintf(f, "skipcount: %4d framesize: %d\n", cpi->skip_true_count , *size);
-
- fclose(f);
- }
-
-#endif
#endif
#if HAVE_ARMV7
@@ -5142,43 +4330,59 @@ int vp8_get_preview_raw_frame(VP8_PTR comp, YV12_BUFFER_CONFIG *dest, vp8_ppflag
int vp8_set_roimap(VP8_PTR comp, unsigned char *map, unsigned int rows, unsigned int cols, int delta_q[4], int delta_lf[4], unsigned int threshold[4])
{
VP8_COMP *cpi = (VP8_COMP *) comp;
- signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+ signed char feature_data[SEG_LVL_MAX][MAX_MB_SEGMENTS];
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
+ int i;
if (cpi->common.mb_rows != rows || cpi->common.mb_cols != cols)
return -1;
if (!map)
{
- disable_segmentation((VP8_PTR)cpi);
+ vp8_disable_segmentation((VP8_PTR)cpi);
return 0;
}
// Set the segmentation Map
- set_segmentation_map((VP8_PTR)cpi, map);
+ vp8_set_segmentation_map((VP8_PTR)cpi, map);
// Activate segmentation.
- enable_segmentation((VP8_PTR)cpi);
+ vp8_enable_segmentation((VP8_PTR)cpi);
// Set up the quant segment data
- feature_data[MB_LVL_ALT_Q][0] = delta_q[0];
- feature_data[MB_LVL_ALT_Q][1] = delta_q[1];
- feature_data[MB_LVL_ALT_Q][2] = delta_q[2];
- feature_data[MB_LVL_ALT_Q][3] = delta_q[3];
+ feature_data[SEG_LVL_ALT_Q][0] = delta_q[0];
+ feature_data[SEG_LVL_ALT_Q][1] = delta_q[1];
+ feature_data[SEG_LVL_ALT_Q][2] = delta_q[2];
+ feature_data[SEG_LVL_ALT_Q][3] = delta_q[3];
// Set up the loop segment data s
- feature_data[MB_LVL_ALT_LF][0] = delta_lf[0];
- feature_data[MB_LVL_ALT_LF][1] = delta_lf[1];
- feature_data[MB_LVL_ALT_LF][2] = delta_lf[2];
- feature_data[MB_LVL_ALT_LF][3] = delta_lf[3];
+ feature_data[SEG_LVL_ALT_LF][0] = delta_lf[0];
+ feature_data[SEG_LVL_ALT_LF][1] = delta_lf[1];
+ feature_data[SEG_LVL_ALT_LF][2] = delta_lf[2];
+ feature_data[SEG_LVL_ALT_LF][3] = delta_lf[3];
cpi->segment_encode_breakout[0] = threshold[0];
cpi->segment_encode_breakout[1] = threshold[1];
cpi->segment_encode_breakout[2] = threshold[2];
cpi->segment_encode_breakout[3] = threshold[3];
+ // Enable the loop and quant changes in the feature mask
+ for ( i = 0; i < 4; i++ )
+ {
+ if (delta_q[i])
+ enable_segfeature(xd, i, SEG_LVL_ALT_Q);
+ else
+ disable_segfeature(xd, i, SEG_LVL_ALT_Q);
+
+ if (delta_lf[i])
+ enable_segfeature(xd, i, SEG_LVL_ALT_LF);
+ else
+ disable_segfeature(xd, i, SEG_LVL_ALT_LF);
+ }
+
// Initialise the feature data structure
// SEGMENT_DELTADATA 0, SEGMENT_ABSDATA 1
- set_segment_data((VP8_PTR)cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+ vp8_set_segment_data((VP8_PTR)cpi, &feature_data[0][0], SEGMENT_DELTADATA);
return 0;
}
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 968ebf833..9c655b845 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -13,7 +13,7 @@
#define __INC_VP8_INT_H
#include <stdio.h>
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/onyx.h"
#include "treewriter.h"
#include "tokenize.h"
@@ -23,7 +23,6 @@
#include "encodemb.h"
#include "quantize.h"
#include "vp8/common/entropy.h"
-#include "vp8/common/threading.h"
#include "vpx_ports/mem.h"
#include "vpx/internal/vpx_codec_internal.h"
#include "mcomp.h"
@@ -37,12 +36,12 @@
#define KEY_FRAME_CONTEXT 5
-#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
+#define MAX_LAG_BUFFERS 25
#define AF_THRESH 25
#define AF_THRESH2 100
#define ARF_DECAY_THRESH 12
-#define MAX_MODES 20
+#define MAX_MODES 33
#define MIN_THRESHMULT 32
#define MAX_THRESHMULT 512
@@ -52,9 +51,7 @@
#define MV_ZBIN_BOOST 4
#define ZBIN_OQ_MAX 192
-#if !(CONFIG_REALTIME_ONLY)
#define VP8_TEMPORAL_ALT_REF 1
-#endif
typedef struct
{
@@ -67,21 +64,39 @@ typedef struct
MV_CONTEXT mvc[2];
int mvcosts[2][MVvals+1];
+#if CONFIG_HIGH_PRECISION_MV
+ MV_CONTEXT_HP mvc_hp[2];
+ int mvcosts_hp[2][MVvals_hp+1];
+#endif
#ifdef MODE_STATS
// Stats
- int y_modes[5];
- int uv_modes[4];
- int b_modes[10];
- int inter_y_modes[10];
- int inter_uv_modes[4];
- int inter_b_modes[10];
+ int y_modes[VP8_YMODES];
+ int uv_modes[VP8_UV_MODES];
+ int i8x8_modes[VP8_I8X8_MODES];
+ int b_modes[B_MODE_COUNT];
+ int inter_y_modes[MB_MODE_COUNT];
+ int inter_uv_modes[VP8_UV_MODES];
+ int inter_b_modes[B_MODE_COUNT];
+#endif
+ /* interframe intra mode probs */
+ vp8_prob ymode_prob[VP8_YMODES-1];
+ /* keyframe intra mode probs */
+#if CONFIG_QIMODE
+ vp8_prob kf_ymode_prob[8][VP8_YMODES-1];
+#else
+ vp8_prob kf_ymode_prob[VP8_YMODES-1];
#endif
- vp8_prob ymode_prob[4], uv_mode_prob[3]; /* interframe intra mode probs */
- vp8_prob kf_ymode_prob[4], kf_uv_mode_prob[3]; /* keyframe "" */
-
- int ymode_count[5], uv_mode_count[4]; /* intra MB type cts this frame */
+#if CONFIG_UVINTRA
+ vp8_prob kf_uv_mode_prob[VP8_YMODES][VP8_UV_MODES-1];
+ vp8_prob uv_mode_prob[VP8_YMODES][VP8_UV_MODES-1];
+#else
+ vp8_prob kf_uv_mode_prob[VP8_UV_MODES-1];
+ vp8_prob uv_mode_prob[VP8_UV_MODES-1];
+#endif
+ /* intra MB type cts this frame */
+ int ymode_count[VP8_YMODES], uv_mode_count[VP8_UV_MODES];
int count_mb_ref_frame_usage[MAX_REF_FRAMES];
@@ -108,6 +123,7 @@ typedef struct
double MVrv;
double MVcv;
double mv_in_out_count;
+ double new_mv_count;
double duration;
double count;
}
@@ -127,6 +143,21 @@ typedef struct
} ONEPASS_FRAMESTATS;
+typedef struct
+{
+ struct {
+ int err;
+ union {
+ int_mv mv;
+ MB_PREDICTION_MODE mode;
+ } m;
+ } ref[MAX_REF_FRAMES];
+} MBGRAPH_MB_STATS;
+
+typedef struct
+{
+ MBGRAPH_MB_STATS *mb_stats;
+} MBGRAPH_FRAME_STATS;
typedef enum
{
@@ -158,6 +189,23 @@ typedef enum
THR_SPLITA = 18,
THR_B_PRED = 19,
+ THR_I8X8_PRED = 20,
+
+ THR_COMP_ZEROLG = 21,
+ THR_COMP_NEARESTLG = 22,
+ THR_COMP_NEARLG = 23,
+
+ THR_COMP_ZEROLA = 24,
+ THR_COMP_NEARESTLA = 25,
+ THR_COMP_NEARLA = 26,
+
+ THR_COMP_ZEROGA = 27,
+ THR_COMP_NEARESTGA = 28,
+ THR_COMP_NEARGA = 29,
+
+ THR_COMP_NEWLG = 30,
+ THR_COMP_NEWLA = 31,
+ THR_COMP_NEWGA = 32,
}
THR_MODES;
@@ -193,7 +241,6 @@ typedef struct
typedef struct
{
MACROBLOCK mb;
- int segment_counts[MAX_MB_SEGMENTS];
int totalrate;
} MB_ROW_COMP;
@@ -310,6 +357,10 @@ typedef struct VP8_COMP
int rd_thresh_mult[MAX_MODES];
int rd_baseline_thresh[MAX_MODES];
int rd_threshes[MAX_MODES];
+ int64_t rd_single_diff, rd_comp_diff, rd_hybrid_diff;
+ int rd_prediction_type_threshes[4][NB_PREDICTION_TYPES];
+ int comp_pred_count[COMP_PRED_CONTEXTS];
+ int single_pred_count[COMP_PRED_CONTEXTS];
int RDMULT;
int RDDIV ;
@@ -325,6 +376,7 @@ typedef struct VP8_COMP
int this_frame_target;
int projected_frame_size;
int last_q[2]; // Separate values for Intra/Inter
+ int last_boosted_qindex; // Last boosted GF/KF/ARF q
double rate_correction_factor;
double key_frame_rate_correction_factor;
@@ -358,6 +410,8 @@ typedef struct VP8_COMP
int ni_tot_qi;
int ni_frames;
int avg_frame_qindex;
+ double tot_q;
+ double avg_q;
int zbin_over_quant;
int zbin_mode_boost;
@@ -386,23 +440,22 @@ typedef struct VP8_COMP
int cq_target_quality;
- int drop_frames_allowed; // Are we permitted to drop frames?
- int drop_frame; // Drop this frame?
- int drop_count; // How many frames have we dropped?
- int max_drop_count; // How many frames should we drop?
- int max_consec_dropped_frames; // Limit number of consecutive frames that can be dropped.
-
-
int ymode_count [VP8_YMODES]; /* intra MB type cts this frame */
int uv_mode_count[VP8_UV_MODES]; /* intra MB type cts this frame */
unsigned int MVcount [2] [MVvals]; /* (row,col) MV cts this frame */
+#if CONFIG_HIGH_PRECISION_MV
+ unsigned int MVcount_hp [2] [MVvals_hp]; /* (row,col) MV cts this frame */
+#endif
unsigned int coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]; /* for this frame */
//DECLARE_ALIGNED(16, int, coef_counts_backup [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]); //not used any more
//save vp8_tree_probs_from_distribution result for each frame to avoid repeat calculation
vp8_prob frame_coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
unsigned int frame_branch_ct [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES][2];
+ unsigned int coef_counts_8x8 [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]; /* for this frame */
+ vp8_prob frame_coef_probs_8x8 [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+ unsigned int frame_branch_ct_8x8 [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES][2];
int gfu_boost;
int kf_boost;
@@ -416,6 +469,9 @@ typedef struct VP8_COMP
ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
int one_pass_frame_index;
#endif
+ MBGRAPH_FRAME_STATS mbgraph_stats[MAX_LAG_BUFFERS];
+ int mbgraph_n_frames; // number of frames filled in the above
+ int static_mb_pct; // % forced skip mbs by segmentation
int decimation_factor;
int decimation_count;
@@ -428,8 +484,6 @@ typedef struct VP8_COMP
int compressor_speed;
int interquantizer;
- int auto_gold;
- int auto_adjust_gold_quantizer;
int goldfreq;
int auto_worst_q;
int cpu_used;
@@ -437,21 +491,18 @@ typedef struct VP8_COMP
int vert_scale;
int pass;
-
- int prob_intra_coded;
- int prob_last_coded;
- int prob_gf_coded;
int prob_skip_false;
int last_skip_false_probs[3];
int last_skip_probs_q[3];
- int recent_ref_frame_usage[MAX_REF_FRAMES];
+ int recent_ref_frame_usage[MAX_REF_FRAMES];
int count_mb_ref_frame_usage[MAX_REF_FRAMES];
int this_frame_percent_intra;
int last_frame_percent_intra;
-
int ref_frame_flags;
+ unsigned char ref_pred_probs_update[PREDICTION_PROBS];
+
SPEED_FEATURES sf;
int error_bins[1024];
@@ -461,46 +512,22 @@ typedef struct VP8_COMP
int gf_update_recommended;
int skip_true_count;
int skip_false_count;
+ int t4x4_count;
+ int t8x8_count;
+
+#if CONFIG_UVINTRA
+ int y_uv_mode_count[VP8_YMODES][VP8_UV_MODES];
+#endif
unsigned char *segmentation_map;
- signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS]; // Segment data (can be deltas or absolute values)
- int segment_encode_breakout[MAX_MB_SEGMENTS]; // segment threashold for encode breakout
+
+ // segment threashold for encode breakout
+ int segment_encode_breakout[MAX_MB_SEGMENTS];
unsigned char *active_map;
unsigned int active_map_enabled;
- // Video conferencing cyclic refresh mode flags etc
- // This is a mode designed to clean up the background over time in live encoding scenarious. It uses segmentation
- int cyclic_refresh_mode_enabled;
- int cyclic_refresh_mode_max_mbs_perframe;
- int cyclic_refresh_mode_index;
- int cyclic_refresh_q;
- signed char *cyclic_refresh_map;
-
-#if CONFIG_MULTITHREAD
- // multithread data
- int * mt_current_mb_col;
- int mt_sync_range;
- int b_multi_threaded;
- int encoding_thread_count;
-
- pthread_t *h_encoding_thread;
- pthread_t h_filter_thread;
-
- MB_ROW_COMP *mb_row_ei;
- ENCODETHREAD_DATA *en_thread_data;
- LPFTHREAD_DATA lpf_thread_data;
-
- //events
- sem_t *h_event_start_encoding;
- sem_t h_event_end_encoding;
- sem_t h_event_start_lpf;
- sem_t h_event_end_lpf;
-#endif
TOKENLIST *tplist;
- unsigned int partition_sz[MAX_PARTITIONS];
- // end of multithread data
-
fractional_mv_step_fp *find_fractional_mv_step;
vp8_full_search_fn_t full_search_sad;
@@ -512,7 +539,7 @@ typedef struct VP8_COMP
unsigned int time_pick_lpf;
unsigned int time_encode_mb_row;
- int base_skip_false_prob[128];
+ int base_skip_false_prob[QINDEX_RANGE];
struct twopass_rc
{
@@ -523,6 +550,7 @@ typedef struct VP8_COMP
FIRSTPASS_STATS *total_stats;
FIRSTPASS_STATS *this_frame_stats;
FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start;
+ FIRSTPASS_STATS *total_left_stats;
int first_pass_done;
int64_t bits_left;
int64_t clip_bits_total;
@@ -530,10 +558,6 @@ typedef struct VP8_COMP
double modified_error_total;
double modified_error_used;
double modified_error_left;
- double total_error_left;
- double total_intra_error_left;
- double total_coded_error_left;
- double start_tot_err_left;
double kf_intra_err_min;
double gf_intra_err_min;
int frames_to_key;
diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c
deleted file mode 100644
index 34e08cad8..000000000
--- a/vp8/encoder/pickinter.c
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- * 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 <limits.h>
-#include "vpx_config.h"
-#include "onyx_int.h"
-#include "modecosts.h"
-#include "encodeintra.h"
-#include "vp8/common/entropymode.h"
-#include "pickinter.h"
-#include "vp8/common/findnearmv.h"
-#include "encodemb.h"
-#include "vp8/common/reconinter.h"
-#include "vp8/common/reconintra.h"
-#include "vp8/common/reconintra4x4.h"
-#include "vp8/common/g_common.h"
-#include "variance.h"
-#include "mcomp.h"
-#include "rdopt.h"
-#include "vpx_mem/vpx_mem.h"
-
-#if CONFIG_RUNTIME_CPU_DETECT
-#define IF_RTCD(x) (x)
-#else
-#define IF_RTCD(x) NULL
-#endif
-
-extern int VP8_UVSSE(MACROBLOCK *x, const vp8_variance_rtcd_vtable_t *rtcd);
-
-#ifdef SPEEDSTATS
-extern unsigned int cnt_pm;
-#endif
-
-extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES];
-extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
-
-extern unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr, int recon_stride);
-extern int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]);
-
-
-int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,
- int_mv *bestmv, int_mv *ref_mv,
- int error_per_bit,
- const vp8_variance_fn_ptr_t *vfp,
- int *mvcost[2], int *distortion,
- unsigned int *sse)
-{
- (void) b;
- (void) d;
- (void) ref_mv;
- (void) error_per_bit;
- (void) vfp;
- (void) mvcost;
- (void) distortion;
- (void) sse;
- bestmv->as_mv.row <<= 3;
- bestmv->as_mv.col <<= 3;
- return 0;
-}
-
-
-static int get_inter_mbpred_error(MACROBLOCK *mb,
- const vp8_variance_fn_ptr_t *vfp,
- unsigned int *sse,
- int_mv this_mv)
-{
-
- BLOCK *b = &mb->block[0];
- BLOCKD *d = &mb->e_mbd.block[0];
- unsigned char *what = (*(b->base_src) + b->src);
- int what_stride = b->src_stride;
- unsigned char *in_what = *(d->base_pre) + d->pre ;
- int in_what_stride = d->pre_stride;
- int xoffset = this_mv.as_mv.col & 7;
- int yoffset = this_mv.as_mv.row & 7;
-
- in_what += (this_mv.as_mv.row >> 3) * d->pre_stride + (this_mv.as_mv.col >> 3);
-
- if (xoffset | yoffset)
- {
- return vfp->svf(in_what, in_what_stride, xoffset, yoffset, what, what_stride, sse);
- }
- else
- {
- return vfp->vf(what, what_stride, in_what, in_what_stride, sse);
- }
-
-}
-
-
-unsigned int vp8_get4x4sse_cs_c
-(
- const unsigned char *src_ptr,
- int source_stride,
- const unsigned char *ref_ptr,
- int recon_stride
-)
-{
- int distortion = 0;
- int r, c;
-
- for (r = 0; r < 4; r++)
- {
- for (c = 0; c < 4; c++)
- {
- int diff = src_ptr[c] - ref_ptr[c];
- distortion += diff * diff;
- }
-
- src_ptr += source_stride;
- ref_ptr += recon_stride;
- }
-
- return distortion;
-}
-
-static int get_prediction_error(BLOCK *be, BLOCKD *b, const vp8_variance_rtcd_vtable_t *rtcd)
-{
- unsigned char *sptr;
- unsigned char *dptr;
- sptr = (*(be->base_src) + be->src);
- dptr = b->predictor;
-
- return VARIANCE_INVOKE(rtcd, get4x4sse_cs)(sptr, be->src_stride, dptr, 16);
-
-}
-
-static int pick_intra4x4block(
- const VP8_ENCODER_RTCD *rtcd,
- MACROBLOCK *x,
- int ib,
- B_PREDICTION_MODE *best_mode,
- unsigned int *mode_costs,
-
- int *bestrate,
- int *bestdistortion)
-{
-
- BLOCKD *b = &x->e_mbd.block[ib];
- BLOCK *be = &x->block[ib];
- B_PREDICTION_MODE mode;
- int best_rd = INT_MAX; // 1<<30
- int rate;
- int distortion;
-
- for (mode = B_DC_PRED; mode <= B_HE_PRED /*B_HU_PRED*/; mode++)
- {
- int this_rd;
-
- rate = mode_costs[mode];
- RECON_INVOKE(&rtcd->common->recon, intra4x4_predict)
- (b, mode, b->predictor);
- distortion = get_prediction_error(be, b, &rtcd->variance);
- this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
-
- if (this_rd < best_rd)
- {
- *bestrate = rate;
- *bestdistortion = distortion;
- best_rd = this_rd;
- *best_mode = mode;
- }
- }
-
- b->bmi.as_mode = (B_PREDICTION_MODE)(*best_mode);
- vp8_encode_intra4x4block(rtcd, x, ib);
- return best_rd;
-}
-
-
-static int pick_intra4x4mby_modes
-(
- const VP8_ENCODER_RTCD *rtcd,
- MACROBLOCK *mb,
- int *Rate,
- int *best_dist
-)
-{
- MACROBLOCKD *const xd = &mb->e_mbd;
- int i;
- int cost = mb->mbmode_cost [xd->frame_type] [B_PRED];
- int error;
- int distortion = 0;
- unsigned int *bmode_costs;
-
- vp8_intra_prediction_down_copy(xd);
-
- bmode_costs = mb->inter_bmode_costs;
-
- for (i = 0; i < 16; i++)
- {
- MODE_INFO *const mic = xd->mode_info_context;
- const int mis = xd->mode_info_stride;
-
- B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
- int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(d);
-
- if (mb->e_mbd.frame_type == KEY_FRAME)
- {
- const B_PREDICTION_MODE A = above_block_mode(mic, i, mis);
- const B_PREDICTION_MODE L = left_block_mode(mic, i);
-
- bmode_costs = mb->bmode_costs[A][L];
- }
-
-
- pick_intra4x4block(rtcd, mb, i, &best_mode, bmode_costs, &r, &d);
-
- cost += r;
- distortion += d;
- mic->bmi[i].as_mode = best_mode;
-
- // Break out case where we have already exceeded best so far value
- // that was passed in
- if (distortion > *best_dist)
- break;
- }
-
- *Rate = cost;
-
- if (i == 16)
- {
- *best_dist = distortion;
- error = RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
- }
- else
- {
- *best_dist = INT_MAX;
- error = INT_MAX;
- }
-
- return error;
-}
-
-static void pick_intra_mbuv_mode(MACROBLOCK *mb)
-{
-
- MACROBLOCKD *x = &mb->e_mbd;
- unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
- unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
- unsigned char *usrc_ptr = (mb->block[16].src + *mb->block[16].base_src);
- unsigned char *vsrc_ptr = (mb->block[20].src + *mb->block[20].base_src);
- int uvsrc_stride = mb->block[16].src_stride;
- unsigned char uleft_col[8];
- unsigned char vleft_col[8];
- unsigned char utop_left = uabove_row[-1];
- unsigned char vtop_left = vabove_row[-1];
- int i, j;
- int expected_udc;
- int expected_vdc;
- int shift;
- int Uaverage = 0;
- int Vaverage = 0;
- int diff;
- int pred_error[4] = {0, 0, 0, 0}, best_error = INT_MAX;
- MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
-
-
- for (i = 0; i < 8; i++)
- {
- uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1];
- vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
- }
-
- if (!x->up_available && !x->left_available)
- {
- expected_udc = 128;
- expected_vdc = 128;
- }
- else
- {
- shift = 2;
-
- if (x->up_available)
- {
-
- for (i = 0; i < 8; i++)
- {
- Uaverage += uabove_row[i];
- Vaverage += vabove_row[i];
- }
-
- shift ++;
-
- }
-
- if (x->left_available)
- {
- for (i = 0; i < 8; i++)
- {
- Uaverage += uleft_col[i];
- Vaverage += vleft_col[i];
- }
-
- shift ++;
-
- }
-
- expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
- expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
- }
-
-
- for (i = 0; i < 8; i++)
- {
- for (j = 0; j < 8; j++)
- {
-
- int predu = uleft_col[i] + uabove_row[j] - utop_left;
- int predv = vleft_col[i] + vabove_row[j] - vtop_left;
- int u_p, v_p;
-
- u_p = usrc_ptr[j];
- v_p = vsrc_ptr[j];
-
- if (predu < 0)
- predu = 0;
-
- if (predu > 255)
- predu = 255;
-
- if (predv < 0)
- predv = 0;
-
- if (predv > 255)
- predv = 255;
-
-
- diff = u_p - expected_udc;
- pred_error[DC_PRED] += diff * diff;
- diff = v_p - expected_vdc;
- pred_error[DC_PRED] += diff * diff;
-
-
- diff = u_p - uabove_row[j];
- pred_error[V_PRED] += diff * diff;
- diff = v_p - vabove_row[j];
- pred_error[V_PRED] += diff * diff;
-
-
- diff = u_p - uleft_col[i];
- pred_error[H_PRED] += diff * diff;
- diff = v_p - vleft_col[i];
- pred_error[H_PRED] += diff * diff;
-
-
- diff = u_p - predu;
- pred_error[TM_PRED] += diff * diff;
- diff = v_p - predv;
- pred_error[TM_PRED] += diff * diff;
-
-
- }
-
- usrc_ptr += uvsrc_stride;
- vsrc_ptr += uvsrc_stride;
-
- if (i == 3)
- {
- usrc_ptr = (mb->block[18].src + *mb->block[18].base_src);
- vsrc_ptr = (mb->block[22].src + *mb->block[22].base_src);
- }
-
-
-
- }
-
-
- for (i = DC_PRED; i <= TM_PRED; i++)
- {
- if (best_error > pred_error[i])
- {
- best_error = pred_error[i];
- best_mode = (MB_PREDICTION_MODE)i;
- }
- }
-
-
- mb->e_mbd.mode_info_context->mbmi.uv_mode = best_mode;
-
-}
-
-static void update_mvcount(VP8_COMP *cpi, MACROBLOCKD *xd, int_mv *best_ref_mv)
-{
- /* Split MV modes currently not supported when RD is nopt enabled,
- * therefore, only need to modify MVcount in NEWMV mode. */
- if (xd->mode_info_context->mbmi.mode == NEWMV)
- {
- cpi->MVcount[0][mv_max+((xd->mode_info_context->mbmi.mv.as_mv.row -
- best_ref_mv->as_mv.row) >> 1)]++;
- cpi->MVcount[1][mv_max+((xd->mode_info_context->mbmi.mv.as_mv.col -
- best_ref_mv->as_mv.col) >> 1)]++;
- }
-}
-
-void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
- int recon_uvoffset, int *returnrate,
- int *returndistortion, int *returnintra)
-{
- BLOCK *b = &x->block[0];
- BLOCKD *d = &x->e_mbd.block[0];
- MACROBLOCKD *xd = &x->e_mbd;
- MB_MODE_INFO best_mbmode;
-
- int_mv best_ref_mv;
- int_mv mode_mv[MB_MODE_COUNT];
- MB_PREDICTION_MODE this_mode;
- int num00;
- int mdcounts[4];
- int best_rd = INT_MAX; // 1 << 30;
- int best_intra_rd = INT_MAX;
- int mode_index;
- int rate;
- int rate2;
- int distortion2;
- int bestsme;
- //int all_rds[MAX_MODES]; // Experimental debug code.
- int best_mode_index = 0;
- unsigned int sse = INT_MAX, best_sse = INT_MAX;
-
- int_mv mvp;
- int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
- int saddone=0;
- int sr=0; //search range got from mv_pred(). It uses step_param levels. (0-7)
-
- int_mv nearest_mv[4];
- int_mv near_mv[4];
- int_mv frame_best_ref_mv[4];
- int MDCounts[4][4];
- unsigned char *y_buffer[4];
- unsigned char *u_buffer[4];
- unsigned char *v_buffer[4];
-
- int skip_mode[4] = {0, 0, 0, 0};
-
- int have_subp_search = cpi->sf.half_pixel_search; /* In real-time mode, when Speed >= 15, no sub-pixel search. */
-
- vpx_memset(mode_mv, 0, sizeof(mode_mv));
- vpx_memset(nearest_mv, 0, sizeof(nearest_mv));
- vpx_memset(near_mv, 0, sizeof(near_mv));
- vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
-
-
- // set up all the refframe dependent pointers.
- if (cpi->ref_frame_flags & VP8_LAST_FLAG)
- {
- YV12_BUFFER_CONFIG *lst_yv12 = &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
-
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[LAST_FRAME], &near_mv[LAST_FRAME],
- &frame_best_ref_mv[LAST_FRAME], MDCounts[LAST_FRAME], LAST_FRAME, cpi->common.ref_frame_sign_bias);
-
- y_buffer[LAST_FRAME] = lst_yv12->y_buffer + recon_yoffset;
- u_buffer[LAST_FRAME] = lst_yv12->u_buffer + recon_uvoffset;
- v_buffer[LAST_FRAME] = lst_yv12->v_buffer + recon_uvoffset;
- }
- else
- skip_mode[LAST_FRAME] = 1;
-
- if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
- {
- YV12_BUFFER_CONFIG *gld_yv12 = &cpi->common.yv12_fb[cpi->common.gld_fb_idx];
-
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[GOLDEN_FRAME], &near_mv[GOLDEN_FRAME],
- &frame_best_ref_mv[GOLDEN_FRAME], MDCounts[GOLDEN_FRAME], GOLDEN_FRAME, cpi->common.ref_frame_sign_bias);
-
- y_buffer[GOLDEN_FRAME] = gld_yv12->y_buffer + recon_yoffset;
- u_buffer[GOLDEN_FRAME] = gld_yv12->u_buffer + recon_uvoffset;
- v_buffer[GOLDEN_FRAME] = gld_yv12->v_buffer + recon_uvoffset;
- }
- else
- skip_mode[GOLDEN_FRAME] = 1;
-
- if (cpi->ref_frame_flags & VP8_ALT_FLAG && cpi->source_alt_ref_active)
- {
- YV12_BUFFER_CONFIG *alt_yv12 = &cpi->common.yv12_fb[cpi->common.alt_fb_idx];
-
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[ALTREF_FRAME], &near_mv[ALTREF_FRAME],
- &frame_best_ref_mv[ALTREF_FRAME], MDCounts[ALTREF_FRAME], ALTREF_FRAME, cpi->common.ref_frame_sign_bias);
-
- y_buffer[ALTREF_FRAME] = alt_yv12->y_buffer + recon_yoffset;
- u_buffer[ALTREF_FRAME] = alt_yv12->u_buffer + recon_uvoffset;
- v_buffer[ALTREF_FRAME] = alt_yv12->v_buffer + recon_uvoffset;
- }
- else
- skip_mode[ALTREF_FRAME] = 1;
-
- cpi->mbs_tested_so_far++; // Count of the number of MBs tested so far this frame
-
- *returnintra = INT_MAX;
- x->skip = 0;
-
- x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
-
- // if we encode a new mv this is important
- // find the best new motion vector
- for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
- {
- int frame_cost;
- int this_rd = INT_MAX;
-
- if (best_rd <= cpi->rd_threshes[mode_index])
- continue;
-
- x->e_mbd.mode_info_context->mbmi.ref_frame = vp8_ref_frame_order[mode_index];
-
- if (skip_mode[x->e_mbd.mode_info_context->mbmi.ref_frame])
- continue;
-
- // Check to see if the testing frequency for this mode is at its max
- // If so then prevent it from being tested and increase the threshold for its testing
- if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
- {
- //if ( (cpi->mbs_tested_so_far / cpi->mode_test_hit_counts[mode_index]) <= cpi->mode_check_freq[mode_index] )
- if (cpi->mbs_tested_so_far <= (cpi->mode_check_freq[mode_index] * cpi->mode_test_hit_counts[mode_index]))
- {
- // Increase the threshold for coding this mode to make it less likely to be chosen
- cpi->rd_thresh_mult[mode_index] += 4;
-
- if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
- cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
-
- cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
-
- continue;
- }
- }
-
- // We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
- cpi->mode_test_hit_counts[mode_index] ++;
-
- rate2 = 0;
- distortion2 = 0;
-
- this_mode = vp8_mode_order[mode_index];
-
- // Experimental debug code.
- //all_rds[mode_index] = -1;
-
- x->e_mbd.mode_info_context->mbmi.mode = this_mode;
- x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
-
- // Work out the cost assosciated with selecting the reference frame
- frame_cost =
- x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
- rate2 += frame_cost;
-
- // everything but intra
- if (x->e_mbd.mode_info_context->mbmi.ref_frame)
- {
- x->e_mbd.pre.y_buffer = y_buffer[x->e_mbd.mode_info_context->mbmi.ref_frame];
- x->e_mbd.pre.u_buffer = u_buffer[x->e_mbd.mode_info_context->mbmi.ref_frame];
- x->e_mbd.pre.v_buffer = v_buffer[x->e_mbd.mode_info_context->mbmi.ref_frame];
- mode_mv[NEARESTMV] = nearest_mv[x->e_mbd.mode_info_context->mbmi.ref_frame];
- mode_mv[NEARMV] = near_mv[x->e_mbd.mode_info_context->mbmi.ref_frame];
- best_ref_mv = frame_best_ref_mv[x->e_mbd.mode_info_context->mbmi.ref_frame];
- memcpy(mdcounts, MDCounts[x->e_mbd.mode_info_context->mbmi.ref_frame], sizeof(mdcounts));
- }
-
- // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
- // unless ARNR filtering is enabled in which case we want
- // an unfiltered alternative
- if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
- {
- if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
- continue;
- }
-
- switch (this_mode)
- {
- case B_PRED:
- // Pass best so far to pick_intra4x4mby_modes to use as breakout
- distortion2 = best_sse;
- pick_intra4x4mby_modes(IF_RTCD(&cpi->rtcd), x, &rate, &distortion2);
-
- if (distortion2 == INT_MAX)
- {
- this_rd = INT_MAX;
- }
- else
- {
- rate2 += rate;
- distortion2 = VARIANCE_INVOKE
- (&cpi->rtcd.variance, var16x16)(
- *(b->base_src), b->src_stride,
- x->e_mbd.predictor, 16, &sse);
- this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
-
- if (this_rd < best_intra_rd)
- {
- best_intra_rd = this_rd;
- *returnintra = distortion2;
- }
- }
-
- break;
-
- case SPLITMV:
-
- // Split MV modes currently not supported when RD is nopt enabled.
- break;
-
- case DC_PRED:
- case V_PRED:
- case H_PRED:
- case TM_PRED:
- RECON_INVOKE(&cpi->common.rtcd.recon, build_intra_predictors_mby)
- (&x->e_mbd);
- distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x16)
- (*(b->base_src), b->src_stride,
- x->e_mbd.predictor, 16, &sse);
- rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.mode];
- this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
-
- if (this_rd < best_intra_rd)
- {
- best_intra_rd = this_rd;
- *returnintra = distortion2;
- }
- break;
-
- case NEWMV:
- {
- int thissme;
- int step_param;
- int further_steps;
- int n = 0;
- int sadpb = x->sadperbit16;
- int_mv mvp_full;
-
- int col_min = (best_ref_mv.as_mv.col>>3) - MAX_FULL_PEL_VAL + ((best_ref_mv.as_mv.col & 7)?1:0);
- int row_min = (best_ref_mv.as_mv.row>>3) - MAX_FULL_PEL_VAL + ((best_ref_mv.as_mv.row & 7)?1:0);
- int col_max = (best_ref_mv.as_mv.col>>3) + MAX_FULL_PEL_VAL;
- int row_max = (best_ref_mv.as_mv.row>>3) + MAX_FULL_PEL_VAL;
-
- int tmp_col_min = x->mv_col_min;
- int tmp_col_max = x->mv_col_max;
- int tmp_row_min = x->mv_row_min;
- int tmp_row_max = x->mv_row_max;
-
- int speed_adjust = (cpi->Speed > 5) ? ((cpi->Speed >= 8)? 3 : 2) : 1;
-
- // Further step/diamond searches as necessary
- step_param = cpi->sf.first_step + speed_adjust;
-
- if(cpi->sf.improved_mv_pred)
- {
- if(!saddone)
- {
- vp8_cal_sad(cpi,xd,x, recon_yoffset ,&near_sadidx[0] );
- saddone = 1;
- }
-
- vp8_mv_pred(cpi, &x->e_mbd, x->e_mbd.mode_info_context, &mvp,
- x->e_mbd.mode_info_context->mbmi.ref_frame, cpi->common.ref_frame_sign_bias, &sr, &near_sadidx[0]);
-
- sr += speed_adjust;
- //adjust search range according to sr from mv prediction
- if(sr > step_param)
- step_param = sr;
-
- mvp_full.as_mv.col = mvp.as_mv.col>>3;
- mvp_full.as_mv.row = mvp.as_mv.row>>3;
-
- }else
- {
- mvp.as_int = best_ref_mv.as_int;
- mvp_full.as_mv.col = best_ref_mv.as_mv.col>>3;
- mvp_full.as_mv.row = best_ref_mv.as_mv.row>>3;
- }
-
- // Get intersection of UMV window and valid MV window to reduce # of checks in diamond search.
- if (x->mv_col_min < col_min )
- x->mv_col_min = col_min;
- if (x->mv_col_max > col_max )
- x->mv_col_max = col_max;
- if (x->mv_row_min < row_min )
- x->mv_row_min = row_min;
- if (x->mv_row_max > row_max )
- x->mv_row_max = row_max;
-
- further_steps = (cpi->Speed >= 8)? 0: (cpi->sf.max_step_search_steps - 1 - step_param);
-
- if (cpi->sf.search_method == HEX)
- {
- bestsme = vp8_hex_search(x, b, d, &mvp_full, &d->bmi.mv, step_param,
- sadpb, &cpi->fn_ptr[BLOCK_16X16],
- x->mvsadcost, x->mvcost, &best_ref_mv);
- mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
- }
- else
- {
- bestsme = cpi->diamond_search_sad(x, b, d, &mvp_full, &d->bmi.mv,
- step_param, sadpb, &num00,
- &cpi->fn_ptr[BLOCK_16X16],
- x->mvcost, &best_ref_mv);
- mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
-
- // Further step/diamond searches as necessary
- n = 0;
- //further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
-
- n = num00;
- num00 = 0;
-
- while (n < further_steps)
- {
- n++;
-
- if (num00)
- num00--;
- else
- {
- thissme =
- cpi->diamond_search_sad(x, b, d, &mvp_full,
- &d->bmi.mv,
- step_param + n,
- sadpb, &num00,
- &cpi->fn_ptr[BLOCK_16X16],
- x->mvcost, &best_ref_mv);
- if (thissme < bestsme)
- {
- bestsme = thissme;
- mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
- }
- else
- {
- d->bmi.mv.as_int = mode_mv[NEWMV].as_int;
- }
- }
- }
- }
-
- x->mv_col_min = tmp_col_min;
- x->mv_col_max = tmp_col_max;
- x->mv_row_min = tmp_row_min;
- x->mv_row_max = tmp_row_max;
-
- if (bestsme < INT_MAX)
- cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv, &best_ref_mv,
- x->errorperbit,
- &cpi->fn_ptr[BLOCK_16X16],
- cpi->mb.mvcost,
- &distortion2,&sse);
-
- mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
-
- // mv cost;
- rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv, cpi->mb.mvcost, 128);
- }
-
- case NEARESTMV:
- case NEARMV:
-
- if (mode_mv[this_mode].as_int == 0)
- continue;
-
- case ZEROMV:
-
- // Trap vectors that reach beyond the UMV borders
- // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
- // because of the lack of break statements in the previous two cases.
- if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
- ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
- continue;
-
- rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
- x->e_mbd.mode_info_context->mbmi.mv.as_int =
- mode_mv[this_mode].as_int;
-
- /* Exit early and don't compute the distortion if this macroblock is marked inactive. */
- if (cpi->active_map_enabled && x->active_ptr[0] == 0)
- {
- sse = 0;
- distortion2 = 0;
- x->skip = 1;
- break;
- }
-
- if((this_mode != NEWMV) ||
- !(have_subp_search) || cpi->common.full_pixel==1)
- distortion2 = get_inter_mbpred_error(x,
- &cpi->fn_ptr[BLOCK_16X16],
- &sse, mode_mv[this_mode]);
-
- this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
-
- if (sse < x->encode_breakout)
- {
- // Check u and v to make sure skip is ok
- int sse2 = 0;
-
- sse2 = VP8_UVSSE(x, IF_RTCD(&cpi->rtcd.variance));
-
- if (sse2 * 2 < x->encode_breakout)
- x->skip = 1;
- else
- x->skip = 0;
- }
-
- break;
- default:
- break;
- }
-
- // Experimental debug code.
- //all_rds[mode_index] = this_rd;
-
- if (this_rd < best_rd || x->skip)
- {
- // Note index of best mode
- best_mode_index = mode_index;
-
- *returnrate = rate2;
- *returndistortion = distortion2;
- best_sse = sse;
- best_rd = this_rd;
- vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi, sizeof(MB_MODE_INFO));
-
- // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
- cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
- cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
- }
-
- // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
- else
- {
- cpi->rd_thresh_mult[mode_index] += 4;
-
- if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
- cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
-
- cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
- }
-
- if (x->skip)
- break;
- }
-
- // Reduce the activation RD thresholds for the best choice mode
- if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2)))
- {
- int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 3);
-
- cpi->rd_thresh_mult[best_mode_index] = (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ? cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
- cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
- }
-
-
- {
- int this_rdbin = (*returndistortion >> 7);
-
- if (this_rdbin >= 1024)
- {
- this_rdbin = 1023;
- }
-
- cpi->error_bins[this_rdbin] ++;
- }
-
- if (cpi->is_src_frame_alt_ref &&
- (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
- {
- x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
- x->e_mbd.mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
- x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
- x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
- x->e_mbd.mode_info_context->mbmi.mb_skip_coeff =
- (cpi->common.mb_no_coeff_skip) ? 1 : 0;
- x->e_mbd.mode_info_context->mbmi.partitioning = 0;
-
- return;
- }
-
- /* set to the best mb mode */
- vpx_memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
-
- if (best_mbmode.mode <= B_PRED)
- {
- /* set mode_info_context->mbmi.uv_mode */
- pick_intra_mbuv_mode(x);
- }
-
- update_mvcount(cpi, &x->e_mbd, &frame_best_ref_mv[xd->mode_info_context->mbmi.ref_frame]);
-}
-
-
-void vp8_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate_)
-{
- int error4x4, error16x16 = INT_MAX;
- int rate, best_rate = 0, distortion, best_sse;
- MB_PREDICTION_MODE mode, best_mode = DC_PRED;
- int this_rd;
- unsigned int sse;
- BLOCK *b = &x->block[0];
-
- x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
-
- pick_intra_mbuv_mode(x);
-
- for (mode = DC_PRED; mode <= TM_PRED; mode ++)
- {
- x->e_mbd.mode_info_context->mbmi.mode = mode;
- RECON_INVOKE(&cpi->common.rtcd.recon, build_intra_predictors_mby)
- (&x->e_mbd);
- distortion = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x16)
- (*(b->base_src), b->src_stride, x->e_mbd.predictor, 16, &sse);
- rate = x->mbmode_cost[x->e_mbd.frame_type][mode];
- this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
-
- if (error16x16 > this_rd)
- {
- error16x16 = this_rd;
- best_mode = mode;
- best_sse = sse;
- best_rate = rate;
- }
- }
- x->e_mbd.mode_info_context->mbmi.mode = best_mode;
-
- error4x4 = pick_intra4x4mby_modes(IF_RTCD(&cpi->rtcd), x, &rate,
- &best_sse);
- if (error4x4 < error16x16)
- {
- x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
- best_rate = rate;
- }
-
- *rate_ = best_rate;
-}
diff --git a/vp8/encoder/picklpf.c b/vp8/encoder/picklpf.c
index beefe8d8e..171ec3a4d 100644
--- a/vp8/encoder/picklpf.c
+++ b/vp8/encoder/picklpf.c
@@ -36,6 +36,15 @@ extern void
(*vp8_yv12_copy_partial_frame_ptr)(YV12_BUFFER_CONFIG *src_ybc,
YV12_BUFFER_CONFIG *dst_ybc,
int Fraction);
+
+extern void vp8_loop_filter_frame_segment
+(
+ VP8_COMMON *cm,
+ MACROBLOCKD *xd,
+ int default_filt_lvl,
+ int segment
+);
+
void
vp8_yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction)
{
@@ -63,7 +72,6 @@ vp8_yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst
vpx_memcpy(dst_y, src_y, ystride *(linestocopy + 16));
}
-
static int vp8_calc_partial_ssl_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, int Fraction, const vp8_variance_rtcd_vtable_t *rtcd)
{
int i, j;
@@ -107,18 +115,21 @@ static int vp8_calc_partial_ssl_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONF
static int get_min_filter_level(VP8_COMP *cpi, int base_qindex)
{
int min_filter_level;
+ /*int q = (int) vp8_convert_qindex_to_q(base_qindex);
if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame && !cpi->common.refresh_alt_ref_frame)
min_filter_level = 0;
else
{
- if (base_qindex <= 6)
+ if (q <= 10)
min_filter_level = 0;
- else if (base_qindex <= 16)
+ else if (q <= 64)
min_filter_level = 1;
else
- min_filter_level = (base_qindex / 8);
+ min_filter_level = (q >> 6);
}
+ */
+ min_filter_level = 0;
return min_filter_level;
}
@@ -256,17 +267,232 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
// Stub function for now Alt LF not used
void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val)
{
- MACROBLOCKD *mbd = &cpi->mb.e_mbd;
- (void) filt_val;
+}
+#if CONFIG_FEATUREUPDATES
+void vp8cx_pick_filter_level_sg(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi, int segment)
+{
+ VP8_COMMON *cm = &cpi->common;
+
+ int best_err = 0;
+ int filt_err = 0;
+ int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+ int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
+
+ int filter_step;
+ int filt_high = 0;
+ int filt_mid = cm->filter_level; // Start search at previous frame filter level
+ int filt_low = 0;
+ int filt_best;
+ int filt_direction = 0;
+
+ int Bias = 0; // Bias against raising loop filter and in favour of lowering it
+
+ // Make a copy of the unfiltered / processed recon buffer
+#if HAVE_ARMV7
+#if CONFIG_RUNTIME_CPU_DETECT
+ if (cm->rtcd.flags & HAS_NEON)
+#endif
+ {
+ vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(cm->frame_to_show, &cpi->last_frame_uf);
+ }
+#if CONFIG_RUNTIME_CPU_DETECT
+ else
+#endif
+#endif
+#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
+ {
+ vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cpi->last_frame_uf);
+ }
+#endif
+
+ if (cm->frame_type == KEY_FRAME)
+ cm->sharpness_level = 0;
+ else
+ cm->sharpness_level = cpi->oxcf.Sharpness;
+
+ // Start the search at the previous frame filter level unless it is now out of range.
+ filt_mid = cm->filter_level;
+
+ if (filt_mid < min_filter_level)
+ filt_mid = min_filter_level;
+ else if (filt_mid > max_filter_level)
+ filt_mid = max_filter_level;
+
+ // Define the initial step size
+ filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
+
+ // Get baseline error score
+ vp8cx_set_alt_lf_level(cpi, filt_mid);
+ vp8_loop_filter_frame_segment(cm, &cpi->mb.e_mbd, filt_mid,segment);
+
+ best_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+ filt_best = filt_mid;
+
+ // Re-instate the unfiltered frame
+#if HAVE_ARMV7
+#if CONFIG_RUNTIME_CPU_DETECT
+ if (cm->rtcd.flags & HAS_NEON)
+#endif
+ {
+ vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
+ }
+#if CONFIG_RUNTIME_CPU_DETECT
+ else
+#endif
+#endif
+#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
+ {
+ vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+ }
+#endif
+
+ while (filter_step > 0)
+ {
+ Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; //PGW change 12/12/06 for small images
+
+ // jbb chg: 20100118 - in sections with lots of new material coming in don't bias as much to a low filter value
+ if (cpi->twopass.section_intra_rating < 20)
+ Bias = Bias * cpi->twopass.section_intra_rating / 20;
+
+ // yx, bias less for large block size
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ Bias >>= 1;
+
+ filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
+ filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
- mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0];
- mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1];
- mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2];
- mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3];
+ if ((filt_direction <= 0) && (filt_low != filt_mid))
+ {
+ // Get Low filter error score
+ vp8cx_set_alt_lf_level(cpi, filt_low);
+ vp8_loop_filter_frame_segment(cm, &cpi->mb.e_mbd, filt_low, segment);
+
+ filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+
+ // Re-instate the unfiltered frame
+#if HAVE_ARMV7
+#if CONFIG_RUNTIME_CPU_DETECT
+ if (cm->rtcd.flags & HAS_NEON)
+#endif
+ {
+ vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
+ }
+#if CONFIG_RUNTIME_CPU_DETECT
+ else
+#endif
+#endif
+#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
+ {
+ vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+ }
+#endif
+
+ // If value is close to the best so far then bias towards a lower loop filter value.
+ if ((filt_err - Bias) < best_err)
+ {
+ // Was it actually better than the previous best?
+ if (filt_err < best_err)
+ best_err = filt_err;
+
+ filt_best = filt_low;
+ }
+ }
+
+ // Now look at filt_high
+ if ((filt_direction >= 0) && (filt_high != filt_mid))
+ {
+ vp8cx_set_alt_lf_level(cpi, filt_high);
+ vp8_loop_filter_frame_segment(cm, &cpi->mb.e_mbd, filt_high, segment);
+
+ filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+
+ // Re-instate the unfiltered frame
+#if HAVE_ARMV7
+#if CONFIG_RUNTIME_CPU_DETECT
+ if (cm->rtcd.flags & HAS_NEON)
+#endif
+ {
+ vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
+ }
+#if CONFIG_RUNTIME_CPU_DETECT
+ else
+#endif
+#endif
+#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
+ {
+ vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+ }
+#endif
+
+ // Was it better than the previous best?
+ if (filt_err < (best_err - Bias))
+ {
+ best_err = filt_err;
+ filt_best = filt_high;
+ }
+ }
+
+ // Half the step distance if the best filter value was the same as last time
+ if (filt_best == filt_mid)
+ {
+ filter_step = filter_step / 2;
+ filt_direction = 0;
+ }
+ else
+ {
+ filt_direction = (filt_best < filt_mid) ? -1 : 1;
+ filt_mid = filt_best;
+ }
+ }
+
+ cm->filter_level = filt_best;
}
void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
{
+ VP8_COMMON *oci = &cpi->common;
+ MODE_INFO *mi = oci->mi;
+ int filt_lev[2];
+ int i, j;
+ MACROBLOCKD * const xd = &cpi->mb.e_mbd;
+ int max_seg;
+ int mb_index = 0;
+
+ // pick the loop filter for each segment after segment 0
+ for (i = 1; i < MAX_MB_SEGMENTS; i++)
+ {
+ // if the segment loop filter is active
+ if (segfeature_active(xd, i, SEG_LVL_ALT_LF))
+ {
+ set_segdata(xd, i, SEG_LVL_ALT_LF, 0);
+ vp8cx_pick_filter_level_sg(sd, cpi, i);
+ filt_lev[i] = oci->filter_level;
+ }
+ }
+
+ // do the 0 segment ( this filter also picks the filter value for all
+ // the not enabled features )
+
+ // TODO : Fix the code if segment 0 is the one with seg_lvl_alt_lf on
+ // right now assumes segment 0 gets base loop filter and the rest are
+ // deltas off of segment 0.
+ set_segdata(xd, 0, SEG_LVL_ALT_LF, 0);
+ vp8cx_pick_filter_level_sg(sd, cpi, 0);
+ filt_lev[0] = oci->filter_level;
+
+ // convert the best filter level for the mbs of the segment to
+ // a delta from 0
+ for (i = 1; i < MAX_MB_SEGMENTS; i++)
+ if (segfeature_active(xd, i, SEG_LVL_ALT_LF))
+ {
+ set_segdata(xd, i, SEG_LVL_ALT_LF, filt_lev[i] - filt_lev[0]);
+ xd->update_mb_segmentation_data !=
+ segfeature_changed( xd,i,SEG_LVL_ALT_LF);
+ }
+}
+#else
+void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
VP8_COMMON *cm = &cpi->common;
int best_err = 0;
@@ -350,6 +576,10 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
if (cpi->twopass.section_intra_rating < 20)
Bias = Bias * cpi->twopass.section_intra_rating / 20;
+ // yx, bias less for large block size
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ Bias >>= 1;
+
filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
@@ -439,3 +669,5 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
cm->filter_level = filt_best;
}
+#endif
+
diff --git a/vp8/encoder/ppc/csystemdependent.c b/vp8/encoder/ppc/csystemdependent.c
index 63f235784..49b1dd6a9 100644
--- a/vp8/encoder/ppc/csystemdependent.c
+++ b/vp8/encoder/ppc/csystemdependent.c
@@ -48,8 +48,6 @@ void (*vp8_subtract_mby)(short *diff, unsigned char *src, unsigned char *pred, i
void (*vp8_subtract_mbuv)(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
void (*vp8_fast_quantize_b)(BLOCK *b, BLOCKD *d);
-unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr, int recon_stride);
-
// c imports
extern int block_error_c(short *coeff, short *dqcoeff);
extern int vp8_mbblock_error_c(MACROBLOCK *mb, int dc);
@@ -85,7 +83,6 @@ extern sub_pixel_variance_function sub_pixel_variance16x8_c;
extern sub_pixel_variance_function sub_pixel_variance16x16_c;
extern unsigned int vp8_get_mb_ss_c(short *);
-extern unsigned int vp8_get4x4sse_cs_c(unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr, int recon_stride);
// ppc
extern int vp8_block_error_ppc(short *coeff, short *dqcoeff);
@@ -143,7 +140,6 @@ void vp8_cmachine_specific_config(void)
vp8_sub_pixel_variance16x16 = vp8_sub_pixel_variance16x16_ppc;
vp8_get_mb_ss = vp8_get_mb_ss_c;
- vp8_get4x4sse_cs = vp8_get4x4sse_cs_c;
vp8_sad16x16 = vp8_sad16x16_ppc;
vp8_sad16x8 = vp8_sad16x8_ppc;
diff --git a/vp8/encoder/quantize.c b/vp8/encoder/quantize.c
index 503d24123..636ed3a67 100644
--- a/vp8/encoder/quantize.c
+++ b/vp8/encoder/quantize.c
@@ -16,60 +16,16 @@
#include "quantize.h"
#include "vp8/common/quant_common.h"
-#define EXACT_QUANT
-
-#ifdef EXACT_FASTQUANT
-void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
-{
- int i, rc, eob;
- int zbin;
- int x, y, z, sz;
- short *coeff_ptr = b->coeff;
- short *zbin_ptr = b->zbin;
- short *round_ptr = b->round;
- short *quant_ptr = b->quant_fast;
- unsigned char *quant_shift_ptr = b->quant_shift;
- short *qcoeff_ptr = d->qcoeff;
- short *dqcoeff_ptr = d->dqcoeff;
- short *dequant_ptr = d->dequant;
-
- vpx_memset(qcoeff_ptr, 0, 32);
- vpx_memset(dqcoeff_ptr, 0, 32);
-
- eob = -1;
-
- for (i = 0; i < 16; i++)
- {
- rc = vp8_default_zig_zag1d[i];
- z = coeff_ptr[rc];
- zbin = zbin_ptr[rc] ;
-
- sz = (z >> 31); // sign of z
- x = (z ^ sz) - sz; // x = abs(z)
+#include "vp8/common/seg_common.h"
- if (x >= zbin)
- {
- x += round_ptr[rc];
- y = (((x * quant_ptr[rc]) >> 16) + x)
- >> quant_shift_ptr[rc]; // quantize (x)
- x = (y ^ sz) - sz; // get the sign back
- qcoeff_ptr[rc] = x; // write to destination
- dqcoeff_ptr[rc] = x * dequant_ptr[rc]; // dequantized value
-
- if (y)
- {
- eob = i; // last nonzero coeffs
- }
- }
- }
- d->eob = eob + 1;
-}
-
-#else
+#ifdef ENC_DEBUG
+extern int enc_debug;
+#endif
+#define EXACT_QUANT
void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
{
- int i, rc, eob;
+ int i, rc, eob, nonzeros;
int x, y, z, sz;
short *coeff_ptr = b->coeff;
short *round_ptr = b->round;
@@ -78,6 +34,9 @@ void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
short *dqcoeff_ptr = d->dqcoeff;
short *dequant_ptr = d->dequant;
+ vpx_memset(qcoeff_ptr, 0, 32);
+ vpx_memset(dqcoeff_ptr, 0, 32);
+
eob = -1;
for (i = 0; i < 16; i++)
{
@@ -100,7 +59,7 @@ void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
d->eob = eob + 1;
}
-#endif
+
#ifdef EXACT_QUANT
void vp8_regular_quantize_b(BLOCK *b, BLOCKD *d)
@@ -124,7 +83,7 @@ void vp8_regular_quantize_b(BLOCK *b, BLOCKD *d)
eob = -1;
- for (i = 0; i < 16; i++)
+ for (i = 0; i < b->eob_max_offset; i++)
{
rc = vp8_default_zig_zag1d[i];
z = coeff_ptr[rc];
@@ -268,11 +227,14 @@ void vp8_regular_quantize_b(BLOCK *b, BLOCKD *d)
}
#endif
+//EXACT_QUANT
+
void vp8_quantize_mby_c(MACROBLOCK *x)
{
int i;
int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED
&& x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
for (i = 0; i < 16; i++)
@@ -286,6 +248,7 @@ void vp8_quantize_mb_c(MACROBLOCK *x)
{
int i;
int has_2nd_order=(x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != I8X8_PRED
&& x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
for (i = 0; i < 24+has_2nd_order; i++)
@@ -301,6 +264,394 @@ void vp8_quantize_mbuv_c(MACROBLOCK *x)
x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
}
+
+
+
+void vp8_fast_quantize_b_2x2_c(BLOCK *b, BLOCKD *d)
+{
+ int i, rc, eob;
+ int zbin;
+ int x, y, z, sz;
+ short *coeff_ptr = b->coeff;
+ short *zbin_ptr = b->zbin;
+ short *round_ptr = b->round;
+ short *quant_ptr = b->quant;
+ short *qcoeff_ptr = d->qcoeff;
+ short *dqcoeff_ptr = d->dqcoeff;
+ short *dequant_ptr = d->dequant;
+ //double q2nd = 4;
+ vpx_memset(qcoeff_ptr, 0, 32);
+ vpx_memset(dqcoeff_ptr, 0, 32);
+
+ eob = -1;
+
+ for (i = 0; i < 4; i++)
+ {
+ rc = vp8_default_zig_zag1d[i];
+ z = coeff_ptr[rc];
+ //zbin = zbin_ptr[rc]/q2nd;
+ zbin = zbin_ptr[rc];
+
+ sz = (z >> 31); // sign of z
+ x = (z ^ sz) - sz; // x = abs(z)
+
+ if (x >= zbin)
+ {
+ //y = ((int)((x + round_ptr[rc]/q2nd) * quant_ptr[rc] * q2nd)) >> 16; // quantize (x)
+ y = ((int)((x + round_ptr[rc]) * quant_ptr[rc])) >> 16; // quantize (x)
+ x = (y ^ sz) - sz; // get the sign back
+ qcoeff_ptr[rc] = x; // write to destination
+ //dqcoeff_ptr[rc] = x * dequant_ptr[rc] / q2nd; // dequantized value
+ dqcoeff_ptr[rc] = x * dequant_ptr[rc]; // dequantized value
+ dqcoeff_ptr[rc] = (dqcoeff_ptr[rc]+2)>>2;
+
+ if (y)
+ {
+ eob = i; // last nonzero coeffs
+ }
+ }
+ }
+ d->eob = eob + 1;
+ //if (d->eob > 4) printf("Flag Fast 2 (%d)\n", d->eob);
+}
+
+void vp8_fast_quantize_b_8x8_c(BLOCK *b, BLOCKD *d)
+{
+ int i, rc, eob;
+ int zbin;
+ int x, y, z, sz;
+ short *coeff_ptr = b->coeff;
+ short *zbin_ptr = b->zbin;
+ short *round_ptr = b->round;
+ short *quant_ptr = b->quant;
+ short *qcoeff_ptr = d->qcoeff;
+ short *dqcoeff_ptr = d->dqcoeff;
+ short *dequant_ptr = d->dequant;
+ //double q1st = 2;
+ vpx_memset(qcoeff_ptr, 0, 64*sizeof(short));
+ vpx_memset(dqcoeff_ptr, 0, 64*sizeof(short));
+
+ eob = -1;
+
+
+
+ for (i = 0; i < 64; i++)
+ {
+
+ rc = vp8_default_zig_zag1d_8x8[i];
+ z = coeff_ptr[rc];
+ //zbin = zbin_ptr[rc!=0]/q1st ;
+ zbin = zbin_ptr[rc!=0] ;
+
+ sz = (z >> 31); // sign of z
+ x = (z ^ sz) - sz; // x = abs(z)
+
+ if (x >= zbin)
+ {
+ //y = ((int)((x + round_ptr[rc!=0] / q1st) * quant_ptr[rc!=0] * q1st)) >> 16;
+ y = ((int)((x + round_ptr[rc!=0]) * quant_ptr[rc!=0])) >> 16;
+ x = (y ^ sz) - sz; // get the sign back
+ qcoeff_ptr[rc] = x; // write to destination
+ //dqcoeff_ptr[rc] = x * dequant_ptr[rc!=0] / q1st; // dequantized value
+ dqcoeff_ptr[rc] = x * dequant_ptr[rc!=0]; // dequantized value
+ dqcoeff_ptr[rc] = (dqcoeff_ptr[rc]+2)>>2;
+
+ if (y)
+ {
+ eob = i; // last nonzero coeffs
+ }
+ }
+ }
+ d->eob = eob + 1;
+}
+
+
+
+
+void vp8_regular_quantize_b_2x2(BLOCK *b, BLOCKD *d)
+{
+ int i, rc, eob;
+ int zbin;
+ int x, y, z, sz;
+ short *zbin_boost_ptr = b->zrun_zbin_boost;
+ short *coeff_ptr = b->coeff;
+ short *zbin_ptr = b->zbin;
+ short *round_ptr = b->round;
+ short *quant_ptr = b->quant;
+ unsigned char *quant_shift_ptr = b->quant_shift;
+ short *qcoeff_ptr = d->qcoeff;
+ short *dqcoeff_ptr = d->dqcoeff;
+ short *dequant_ptr = d->dequant;
+ short zbin_oq_value = b->zbin_extra;
+ //double q2nd = 4;
+ vpx_memset(qcoeff_ptr, 0, 32);
+ vpx_memset(dqcoeff_ptr, 0, 32);
+
+ eob = -1;
+
+ for (i = 0; i < b->eob_max_offset_8x8; i++)
+ {
+ rc = vp8_default_zig_zag1d[i];
+ z = coeff_ptr[rc];
+
+ //zbin = (zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value)/q2nd;
+ zbin = (zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value);
+
+ zbin_boost_ptr ++;
+ sz = (z >> 31); // sign of z
+ x = (z ^ sz) - sz; // x = abs(z)
+
+ if (x >= zbin)
+ {
+ //x += (round_ptr[rc]/q2nd);
+ x += (round_ptr[rc]);
+ y = ((int)((int)(x * quant_ptr[rc]) >> 16) + x)
+ >> quant_shift_ptr[rc]; // quantize (x)
+ x = (y ^ sz) - sz; // get the sign back
+ qcoeff_ptr[rc] = x; // write to destination
+ //dqcoeff_ptr[rc] = x * dequant_ptr[rc]/q2nd; // dequantized value
+ dqcoeff_ptr[rc] = x * dequant_ptr[rc]; // dequantized value
+
+
+ if (y)
+ {
+ eob = i; // last nonzero coeffs
+ zbin_boost_ptr = &b->zrun_zbin_boost[0]; // reset zero runlength
+ }
+ }
+ }
+
+ d->eob = eob + 1;
+}
+
+void vp8_regular_quantize_b_8x8(BLOCK *b, BLOCKD *d)
+{
+ int i, rc, eob;
+ int zbin;
+ int x, y, z, sz;
+ short *zbin_boost_ptr = b->zrun_zbin_boost;
+ short *coeff_ptr = b->coeff;
+ short *zbin_ptr = b->zbin;
+ short *round_ptr = b->round;
+ short *quant_ptr = b->quant;
+ unsigned char *quant_shift_ptr = b->quant_shift;
+ short *qcoeff_ptr = d->qcoeff;
+ short *dqcoeff_ptr = d->dqcoeff;
+ short *dequant_ptr = d->dequant;
+ short zbin_oq_value = b->zbin_extra;
+ //double q1st = 2;
+
+ vpx_memset(qcoeff_ptr, 0, 64*sizeof(short));
+ vpx_memset(dqcoeff_ptr, 0, 64*sizeof(short));
+
+ eob = -1;
+
+ for (i = 0; i < b->eob_max_offset_8x8; i++)
+ {
+
+ rc = vp8_default_zig_zag1d_8x8[i];
+ z = coeff_ptr[rc];
+
+ //zbin = (zbin_ptr[rc!=0] + *zbin_boost_ptr + zbin_oq_value)/q1st;
+ zbin = (zbin_ptr[rc!=0] + *zbin_boost_ptr + zbin_oq_value);
+ //TODO: 8x8 zbin boost needs be done properly
+ if(zbin_boost_ptr < &b->zrun_zbin_boost[15])
+ zbin_boost_ptr ++;
+
+ sz = (z >> 31); // sign of z
+ x = (z ^ sz) - sz; // x = abs(z)
+
+ if (x >= zbin)
+ {
+ //x += (round_ptr[rc!=0]/q1st);
+ //y = ((int)(((int)(x * quant_ptr[rc!=0] * q1st) >> 16) + x))
+ // >> quant_shift_ptr[rc!=0]; // quantize (x)
+ x += (round_ptr[rc!=0]);
+ y = ((int)(((int)(x * quant_ptr[rc!=0]) >> 16) + x))
+ >> quant_shift_ptr[rc!=0]; // quantize (x)
+ x = (y ^ sz) - sz; // get the sign back
+ qcoeff_ptr[rc] = x; // write to destination
+ //dqcoeff_ptr[rc] = x * dequant_ptr[rc!=0] / q1st; // dequantized value
+ dqcoeff_ptr[rc] = x * dequant_ptr[rc!=0]; // dequantized value
+
+ if (y)
+ {
+ eob = i; // last nonzero coeffs
+ zbin_boost_ptr = &b->zrun_zbin_boost[0]; // reset zero runlength
+ }
+ }
+ }
+
+ d->eob = eob + 1;
+}
+
+void vp8_strict_quantize_b_2x2(BLOCK *b, BLOCKD *d)
+{
+ int i;
+ int rc;
+ int eob;
+ int x;
+ int y;
+ int z;
+ int sz;
+ short *coeff_ptr;
+ short *quant_ptr;
+ unsigned char *quant_shift_ptr;
+ short *qcoeff_ptr;
+ short *dqcoeff_ptr;
+ short *dequant_ptr;
+ //double q2nd = 4;
+ coeff_ptr = b->coeff;
+ quant_ptr = b->quant;
+ quant_shift_ptr = b->quant_shift;
+ qcoeff_ptr = d->qcoeff;
+ dqcoeff_ptr = d->dqcoeff;
+ dequant_ptr = d->dequant;
+ eob = - 1;
+ vpx_memset(qcoeff_ptr, 0, 32);
+ vpx_memset(dqcoeff_ptr, 0, 32);
+ for (i = 0; i < 4; i++)
+ {
+ int dq;
+ int round;
+
+ /*TODO: These arrays should be stored in zig-zag order.*/
+ rc = vp8_default_zig_zag1d[i];
+ z = coeff_ptr[rc];
+ //z = z * q2nd;
+ //dq = dequant_ptr[rc]/q2nd;
+ dq = dequant_ptr[rc];
+ round = dq >> 1;
+ /* Sign of z. */
+ sz = -(z < 0);
+ x = (z + sz) ^ sz;
+ x += round;
+ if (x >= dq)
+ {
+ /* Quantize x */
+ y = (((x * quant_ptr[rc]) >> 16) + x) >> quant_shift_ptr[rc];
+ /* Put the sign back. */
+ x = (y + sz) ^ sz;
+ /* Save * the * coefficient and its dequantized value. */
+ qcoeff_ptr[rc] = x;
+ dqcoeff_ptr[rc] = x * dq;
+ /* Remember the last non-zero coefficient. */
+ if (y)
+ eob = i;
+ }
+ }
+ d->eob = eob + 1;
+}
+
+void vp8_strict_quantize_b_8x8(BLOCK *b, BLOCKD *d)
+{
+ int i;
+ int rc;
+ int eob;
+ int x;
+ int y;
+ int z;
+ int sz;
+ short *coeff_ptr;
+ short *quant_ptr;
+ unsigned char *quant_shift_ptr;
+ short *qcoeff_ptr;
+ short *dqcoeff_ptr;
+ short *dequant_ptr;
+ //double q1st = 2;
+ printf("call strict quantizer\n");
+ coeff_ptr = b->coeff;
+ quant_ptr = b->quant;
+ quant_shift_ptr = b->quant_shift;
+ qcoeff_ptr = d->qcoeff;
+ dqcoeff_ptr = d->dqcoeff;
+ dequant_ptr = d->dequant;
+ eob = - 1;
+ vpx_memset(qcoeff_ptr, 0, 64*sizeof(short));
+ vpx_memset(dqcoeff_ptr, 0, 64*sizeof(short));
+ for (i = 0; i < 64; i++)
+ {
+ int dq;
+ int round;
+
+ /*TODO: These arrays should be stored in zig-zag order.*/
+ rc = vp8_default_zig_zag1d_8x8[i];
+ z = coeff_ptr[rc];
+ //z = z * q1st;
+ //dq = dequant_ptr[rc!=0]/q1st;
+ dq = dequant_ptr[rc!=0];
+ round = dq >> 1;
+ /* Sign of z. */
+ sz = -(z < 0);
+ x = (z + sz) ^ sz;
+ x += round;
+ if (x >= dq)
+ {
+ /* Quantize x. */
+ y = ((int)(((int)((x * quant_ptr[rc!=0])) >> 16) + x)) >> quant_shift_ptr[rc!=0];
+ /* Put the sign back. */
+ x = (y + sz) ^ sz;
+ /* Save the coefficient and its dequantized value. * */
+ qcoeff_ptr[rc] = x;
+ dqcoeff_ptr[rc] = x * dq;
+ /* Remember the last non-zero coefficient. */
+ if (y)
+ eob = i;
+ }
+ }
+ d->eob = eob + 1;
+}
+
+
+
+void vp8_quantize_mby_8x8(MACROBLOCK *x)
+{
+ int i;
+ int has_2nd_order=(x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+ for(i = 0; i < 16; i ++)
+ {
+ x->e_mbd.block[i].eob = 0;
+ }
+ x->e_mbd.block[24].eob = 0;
+ for (i = 0; i < 16; i+=4)
+ x->quantize_b_8x8(&x->block[i], &x->e_mbd.block[i]);
+
+ if (has_2nd_order)
+ x->quantize_b_2x2(&x->block[24], &x->e_mbd.block[24]);
+
+}
+
+void vp8_quantize_mb_8x8(MACROBLOCK *x)
+{
+ int i;
+ int has_2nd_order=(x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+ && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+ for(i = 0; i < 25; i ++)
+ {
+ x->e_mbd.block[i].eob = 0;
+ }
+ for (i = 0; i < 24; i+=4)
+ x->quantize_b_8x8(&x->block[i], &x->e_mbd.block[i]);
+
+ if (has_2nd_order)
+ x->quantize_b_2x2(&x->block[24], &x->e_mbd.block[24]);
+}
+
+void vp8_quantize_mbuv_8x8(MACROBLOCK *x)
+{
+ int i;
+
+ for(i = 16; i < 24; i ++)
+ {
+ x->e_mbd.block[i].eob = 0;
+ }
+ for (i = 16; i < 24; i+=4)
+ x->quantize_b_8x8(&x->block[i], &x->e_mbd.block[i]);
+}
+
+
+
/* quantize_b_pair function pointer in MACROBLOCK structure is set to one of
* these two C functions if corresponding optimized routine is not available.
* NEON optimized version implements currently the fast quantization for pair
@@ -318,94 +669,6 @@ void vp8_fast_quantize_b_pair_c(BLOCK *b1, BLOCK *b2, BLOCKD *d1, BLOCKD *d2)
}
-static const int qrounding_factors[129] =
-{
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48
-};
-
-
-static const int qzbin_factors[129] =
-{
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80
-};
-
-
-static const int qrounding_factors_y2[129] =
-{
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48
-};
-
-
-static const int qzbin_factors_y2[129] =
-{
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80
-};
-
-
#define EXACT_QUANT
#ifdef EXACT_QUANT
static void invert_quant(int improved_quant, short *quant,
@@ -435,18 +698,21 @@ void vp8cx_init_quantizer(VP8_COMP *cpi)
int i;
int quant_val;
int Q;
-
- int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 44, 44};
+ int zbin_boost[16] = { 0, 0, 8, 10, 12, 14, 16, 20,
+ 24, 28, 32, 36, 40, 44, 44, 44};
+ int qrounding_factor = 48;
for (Q = 0; Q < QINDEX_RANGE; Q++)
{
+ int qzbin_factor = (vp8_dc_quant(Q,0) < 148) ? 84 : 80;
+
// dc values
quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
cpi->Y1quant_fast[Q][0] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 0,
cpi->Y1quant_shift[Q] + 0, quant_val);
- cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
- cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+ cpi->Y1zbin[Q][0] = ((qzbin_factor * quant_val) + 64) >> 7;
+ cpi->Y1round[Q][0] = (qrounding_factor * quant_val) >> 7;
cpi->common.Y1dequant[Q][0] = quant_val;
cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
@@ -454,8 +720,8 @@ void vp8cx_init_quantizer(VP8_COMP *cpi)
cpi->Y2quant_fast[Q][0] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 0,
cpi->Y2quant_shift[Q] + 0, quant_val);
- cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
- cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+ cpi->Y2zbin[Q][0] = ((qzbin_factor * quant_val) + 64) >> 7;
+ cpi->Y2round[Q][0] = (qrounding_factor * quant_val) >> 7;
cpi->common.Y2dequant[Q][0] = quant_val;
cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
@@ -463,8 +729,8 @@ void vp8cx_init_quantizer(VP8_COMP *cpi)
cpi->UVquant_fast[Q][0] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 0,
cpi->UVquant_shift[Q] + 0, quant_val);
- cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
- cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+ cpi->UVzbin[Q][0] = ((qzbin_factor * quant_val) + 64) >> 7;;
+ cpi->UVround[Q][0] = (qrounding_factor * quant_val) >> 7;
cpi->common.UVdequant[Q][0] = quant_val;
cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
@@ -477,8 +743,8 @@ void vp8cx_init_quantizer(VP8_COMP *cpi)
cpi->Y1quant_fast[Q][rc] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + rc,
cpi->Y1quant_shift[Q] + rc, quant_val);
- cpi->Y1zbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
- cpi->Y1round[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+ cpi->Y1zbin[Q][rc] = ((qzbin_factor * quant_val) + 64) >> 7;
+ cpi->Y1round[Q][rc] = (qrounding_factor * quant_val) >> 7;
cpi->common.Y1dequant[Q][rc] = quant_val;
cpi->zrun_zbin_boost_y1[Q][i] = (quant_val * zbin_boost[i]) >> 7;
@@ -486,8 +752,8 @@ void vp8cx_init_quantizer(VP8_COMP *cpi)
cpi->Y2quant_fast[Q][rc] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + rc,
cpi->Y2quant_shift[Q] + rc, quant_val);
- cpi->Y2zbin[Q][rc] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
- cpi->Y2round[Q][rc] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+ cpi->Y2zbin[Q][rc] = ((qzbin_factor * quant_val) + 64) >> 7;
+ cpi->Y2round[Q][rc] = (qrounding_factor * quant_val) >> 7;
cpi->common.Y2dequant[Q][rc] = quant_val;
cpi->zrun_zbin_boost_y2[Q][i] = (quant_val * zbin_boost[i]) >> 7;
@@ -495,69 +761,8 @@ void vp8cx_init_quantizer(VP8_COMP *cpi)
cpi->UVquant_fast[Q][rc] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + rc,
cpi->UVquant_shift[Q] + rc, quant_val);
- cpi->UVzbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
- cpi->UVround[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
- cpi->common.UVdequant[Q][rc] = quant_val;
- cpi->zrun_zbin_boost_uv[Q][i] = (quant_val * zbin_boost[i]) >> 7;
- }
- }
-}
-#else
-void vp8cx_init_quantizer(VP8_COMP *cpi)
-{
- int i;
- int quant_val;
- int Q;
-
- int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 44, 44};
-
- for (Q = 0; Q < QINDEX_RANGE; Q++)
- {
- // dc values
- quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
- cpi->Y1quant[Q][0] = (1 << 16) / quant_val;
- cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
- cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
- cpi->common.Y1dequant[Q][0] = quant_val;
- cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
-
- quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
- cpi->Y2quant[Q][0] = (1 << 16) / quant_val;
- cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
- cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
- cpi->common.Y2dequant[Q][0] = quant_val;
- cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
-
- quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
- cpi->UVquant[Q][0] = (1 << 16) / quant_val;
- cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
- cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
- cpi->common.UVdequant[Q][0] = quant_val;
- cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
-
- // all the ac values = ;
- for (i = 1; i < 16; i++)
- {
- int rc = vp8_default_zig_zag1d[i];
-
- quant_val = vp8_ac_yquant(Q);
- cpi->Y1quant[Q][rc] = (1 << 16) / quant_val;
- cpi->Y1zbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
- cpi->Y1round[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
- cpi->common.Y1dequant[Q][rc] = quant_val;
- cpi->zrun_zbin_boost_y1[Q][i] = (quant_val * zbin_boost[i]) >> 7;
-
- quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
- cpi->Y2quant[Q][rc] = (1 << 16) / quant_val;
- cpi->Y2zbin[Q][rc] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
- cpi->Y2round[Q][rc] = (qrounding_factors_y2[Q] * quant_val) >> 7;
- cpi->common.Y2dequant[Q][rc] = quant_val;
- cpi->zrun_zbin_boost_y2[Q][i] = (quant_val * zbin_boost[i]) >> 7;
-
- quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
- cpi->UVquant[Q][rc] = (1 << 16) / quant_val;
- cpi->UVzbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
- cpi->UVround[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+ cpi->UVzbin[Q][rc] = ((qzbin_factor * quant_val) + 64) >> 7;
+ cpi->UVround[Q][rc] = (qrounding_factor * quant_val) >> 7;
cpi->common.UVdequant[Q][rc] = quant_val;
cpi->zrun_zbin_boost_uv[Q][i] = (quant_val * zbin_boost[i]) >> 7;
}
@@ -572,19 +777,23 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
int QIndex;
MACROBLOCKD *xd = &x->e_mbd;
int zbin_extra;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
- // Select the baseline MB Q index.
- if (xd->segmentation_enabled)
+ // Select the baseline MB Q index allowing for any segment level change.
+ if ( segfeature_active( xd, segment_id, SEG_LVL_ALT_Q ) )
{
// Abs Value
- if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+ if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA)
+ QIndex = get_segdata( xd, segment_id, SEG_LVL_ALT_Q );
- QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][xd->mode_info_context->mbmi.segment_id];
// Delta Value
else
{
- QIndex = cpi->common.base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][xd->mode_info_context->mbmi.segment_id];
- QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0; // Clamp to valid range
+ QIndex = cpi->common.base_qindex +
+ get_segdata( xd, segment_id, SEG_LVL_ALT_Q );
+
+ // Clamp to valid range
+ QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;
}
}
else
@@ -606,6 +815,20 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
x->e_mbd.block[i].dequant = cpi->common.Y1dequant[QIndex];
x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[QIndex];
x->block[i].zbin_extra = (short)zbin_extra;
+
+ // Segment max eob offset feature.
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ x->block[i].eob_max_offset =
+ get_segdata( xd, segment_id, SEG_LVL_EOB );
+ x->block[i].eob_max_offset_8x8 =
+ get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+ else
+ {
+ x->block[i].eob_max_offset = 16;
+ x->block[i].eob_max_offset_8x8 = 64;
+ }
}
// UV
@@ -624,6 +847,20 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
x->e_mbd.block[i].dequant = cpi->common.UVdequant[QIndex];
x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[QIndex];
x->block[i].zbin_extra = (short)zbin_extra;
+
+ // Segment max eob offset feature.
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ x->block[i].eob_max_offset =
+ get_segdata( xd, segment_id, SEG_LVL_EOB );
+ x->block[i].eob_max_offset_8x8 =
+ get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+ else
+ {
+ x->block[i].eob_max_offset = 16;
+ x->block[i].eob_max_offset_8x8 = 64;
+ }
}
// Y2
@@ -641,6 +878,21 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
x->block[24].zrun_zbin_boost = cpi->zrun_zbin_boost_y2[QIndex];
x->block[24].zbin_extra = (short)zbin_extra;
+ // TBD perhaps not use for Y2
+ // Segment max eob offset feature.
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ x->block[24].eob_max_offset =
+ get_segdata( xd, segment_id, SEG_LVL_EOB );
+ x->block[24].eob_max_offset_8x8 =
+ get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+ else
+ {
+ x->block[24].eob_max_offset = 16;
+ x->block[24].eob_max_offset_8x8 = 4;
+ }
+
/* save this macroblock QIndex for vp8_update_zbin_extra() */
x->q_index = QIndex;
}
@@ -696,39 +948,19 @@ void vp8cx_frame_init_quantizer(VP8_COMP *cpi)
void vp8_set_quantizer(struct VP8_COMP *cpi, int Q)
{
VP8_COMMON *cm = &cpi->common;
- MACROBLOCKD *mbd = &cpi->mb.e_mbd;
- int update = 0;
- int new_delta_q;
- cm->base_qindex = Q;
- /* if any of the delta_q values are changing update flag has to be set */
- /* currently only y2dc_delta_q may change */
+ cm->base_qindex = Q;
+ // if any of the delta_q values are changing update flag will
+ // have to be set.
cm->y1dc_delta_q = 0;
cm->y2ac_delta_q = 0;
cm->uvdc_delta_q = 0;
cm->uvac_delta_q = 0;
+ cm->y2dc_delta_q = 0;
- if (Q < 4)
- {
- new_delta_q = 4-Q;
- }
- else
- new_delta_q = 0;
-
- update |= cm->y2dc_delta_q != new_delta_q;
- cm->y2dc_delta_q = new_delta_q;
-
-
- // Set Segment specific quatizers
- mbd->segment_feature_data[MB_LVL_ALT_Q][0] = cpi->segment_feature_data[MB_LVL_ALT_Q][0];
- mbd->segment_feature_data[MB_LVL_ALT_Q][1] = cpi->segment_feature_data[MB_LVL_ALT_Q][1];
- mbd->segment_feature_data[MB_LVL_ALT_Q][2] = cpi->segment_feature_data[MB_LVL_ALT_Q][2];
- mbd->segment_feature_data[MB_LVL_ALT_Q][3] = cpi->segment_feature_data[MB_LVL_ALT_Q][3];
-
- /* quantizer has to be reinitialized for any delta_q changes */
- if(update)
- vp8cx_init_quantizer(cpi);
-
+ // quantizer has to be reinitialized if any delta_q changes.
+ // As there are not any here for now this is inactive code.
+ //if(update)
+ // vp8cx_init_quantizer(cpi);
}
-
diff --git a/vp8/encoder/quantize.h b/vp8/encoder/quantize.h
index f1f0156d8..37221839e 100644
--- a/vp8/encoder/quantize.h
+++ b/vp8/encoder/quantize.h
@@ -46,6 +46,27 @@ extern prototype_quantize_block_pair(vp8_quantize_quantb_pair);
#endif
extern prototype_quantize_block(vp8_quantize_fastquantb);
+#ifndef vp8_quantize_quantb_8x8
+#define vp8_quantize_quantb_8x8 vp8_regular_quantize_b_8x8
+#endif
+extern prototype_quantize_block(vp8_quantize_quantb_8x8);
+
+#ifndef vp8_quantize_fastquantb_8x8
+#define vp8_quantize_fastquantb_8x8 vp8_fast_quantize_b_8x8_c
+#endif
+extern prototype_quantize_block(vp8_quantize_fastquantb_8x8);
+
+#ifndef vp8_quantize_quantb_2x2
+#define vp8_quantize_quantb_2x2 vp8_regular_quantize_b_2x2
+#endif
+extern prototype_quantize_block(vp8_quantize_quantb_2x2);
+
+#ifndef vp8_quantize_fastquantb_2x2
+#define vp8_quantize_fastquantb_2x2 vp8_fast_quantize_b_2x2_c
+#endif
+extern prototype_quantize_block(vp8_quantize_fastquantb_2x2);
+
+
#ifndef vp8_quantize_fastquantb_pair
#define vp8_quantize_fastquantb_pair vp8_fast_quantize_b_pair_c
#endif
@@ -56,6 +77,10 @@ typedef struct
prototype_quantize_block(*quantb);
prototype_quantize_block_pair(*quantb_pair);
prototype_quantize_block(*fastquantb);
+ prototype_quantize_block(*quantb_8x8);
+ prototype_quantize_block(*fastquantb_8x8);
+ prototype_quantize_block(*quantb_2x2);
+ prototype_quantize_block(*fastquantb_2x2);
prototype_quantize_block_pair(*fastquantb_pair);
} vp8_quantize_rtcd_vtable_t;
@@ -81,6 +106,10 @@ extern prototype_quantize_mb(vp8_quantize_mby);
#endif
extern void vp8_strict_quantize_b(BLOCK *b,BLOCKD *d);
+extern void vp8_strict_quantize_b_8x8(BLOCK *b,BLOCKD *d);
+extern void vp8_strict_quantize_b_2x2(BLOCK *b,BLOCKD *d);
+extern prototype_quantize_mb(vp8_quantize_mby_8x8);
+extern prototype_quantize_mb(vp8_quantize_mbuv_8x8);
struct VP8_COMP;
extern void vp8_set_quantizer(struct VP8_COMP *cpi, int Q);
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
index a0a3db1c4..bf06f32e1 100644
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -24,7 +24,7 @@
#include "encodemv.h"
-#define MIN_BPB_FACTOR 0.01
+#define MIN_BPB_FACTOR 0.005
#define MAX_BPB_FACTOR 50
extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
@@ -33,192 +33,18 @@ extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES];
#ifdef MODE_STATS
-extern int y_modes[5];
-extern int uv_modes[4];
-extern int b_modes[10];
+extern int y_modes[VP8_YMODES];
+extern int uv_modes[VP8_UV_MODES];
+extern int b_modes[B_MODE_COUNT];
-extern int inter_y_modes[10];
-extern int inter_uv_modes[4];
-extern int inter_b_modes[10];
+extern int inter_y_modes[MB_MODE_COUNT];
+extern int inter_uv_modes[VP8_UV_MODES];
+extern int inter_b_modes[B_MODE_COUNT];
#endif
// Bits Per MB at different Q (Multiplied by 512)
#define BPER_MB_NORMBITS 9
-// Work in progress recalibration of baseline rate tables based on
-// the assumption that bits per mb is inversely proportional to the
-// quantizer value.
-#if !CONFIG_EXTEND_QRANGE
-const int vp8_bits_per_mb[2][QINDEX_RANGE] =
-{
- // Intra case 450000/Qintra
- {
- 1125000,900000, 750000, 642857, 562500, 500000, 450000, 450000,
- 409090, 375000, 346153, 321428, 300000, 281250, 264705, 264705,
- 250000, 236842, 225000, 225000, 214285, 214285, 204545, 204545,
- 195652, 195652, 187500, 180000, 180000, 173076, 166666, 160714,
- 155172, 150000, 145161, 140625, 136363, 132352, 128571, 125000,
- 121621, 121621, 118421, 115384, 112500, 109756, 107142, 104651,
- 102272, 100000, 97826, 97826, 95744, 93750, 91836, 90000,
- 88235, 86538, 84905, 83333, 81818, 80357, 78947, 77586,
- 76271, 75000, 73770, 72580, 71428, 70312, 69230, 68181,
- 67164, 66176, 65217, 64285, 63380, 62500, 61643, 60810,
- 60000, 59210, 59210, 58441, 57692, 56962, 56250, 55555,
- 54878, 54216, 53571, 52941, 52325, 51724, 51136, 50561,
- 49450, 48387, 47368, 46875, 45918, 45000, 44554, 44117,
- 43269, 42452, 41666, 40909, 40178, 39473, 38793, 38135,
- 36885, 36290, 35714, 35156, 34615, 34090, 33582, 33088,
- 32608, 32142, 31468, 31034, 30405, 29801, 29220, 28662,
- },
- // Inter case 285000/Qinter
- {
- 712500, 570000, 475000, 407142, 356250, 316666, 285000, 259090,
- 237500, 219230, 203571, 190000, 178125, 167647, 158333, 150000,
- 142500, 135714, 129545, 123913, 118750, 114000, 109615, 105555,
- 101785, 98275, 95000, 91935, 89062, 86363, 83823, 81428,
- 79166, 77027, 75000, 73076, 71250, 69512, 67857, 66279,
- 64772, 63333, 61956, 60638, 59375, 58163, 57000, 55882,
- 54807, 53773, 52777, 51818, 50892, 50000, 49137, 47500,
- 45967, 44531, 43181, 41911, 40714, 39583, 38513, 37500,
- 36538, 35625, 34756, 33928, 33139, 32386, 31666, 30978,
- 30319, 29687, 29081, 28500, 27941, 27403, 26886, 26388,
- 25909, 25446, 25000, 24568, 23949, 23360, 22800, 22265,
- 21755, 21268, 20802, 20357, 19930, 19520, 19127, 18750,
- 18387, 18037, 17701, 17378, 17065, 16764, 16473, 16101,
- 15745, 15405, 15079, 14766, 14467, 14179, 13902, 13636,
- 13380, 13133, 12895, 12666, 12445, 12179, 11924, 11632,
- 11445, 11220, 11003, 10795, 10594, 10401, 10215, 10035,
- }
-};
-#else
-const int vp8_bits_per_mb[2][QINDEX_RANGE] =
-{
- // (Updated DEC 2010) Baseline estimate of Bits Per MB at each Q:
- // 4500000/Qintra
- {
- 4500000,3600000,3000000,2571428,2250000,2000000,1800000,1636363,
- 1500000,1384615,1285714,1200000,1125000,1058823,1000000, 947368,
- 900000, 818181, 750000, 692307, 642857, 600000, 562500, 529411,
- 500000, 473684, 450000, 428571, 409090, 391304, 375000, 352941,
- 333333, 315789, 300000, 285714, 272727, 260869, 250000, 236842,
- 225000, 214285, 204545, 195652, 187500, 180000, 171428, 163636,
- 156521, 150000, 144000, 138461, 133333, 128571, 123287, 118421,
- 113924, 109756, 105882, 102272, 98901, 95744, 92783, 90000,
- 87378, 84905, 82568, 80357, 77586, 75000, 72580, 70312,
- 68181, 66176, 64285, 62500, 60810, 59210, 57692, 56250,
- 54545, 52941, 51428, 50000, 48648, 47368, 45918, 44554,
- 43269, 42056, 40909, 39647, 38461, 37344, 36290, 35294,
- 34351, 33333, 32374, 31468, 30612, 29801, 28938, 28125,
- 27355, 26627, 25862, 25139, 24456, 23809, 23195, 22613,
- 21951, 21327, 20737, 20179, 19650, 19067, 18518, 18000,
- 17441, 16917, 16423, 15957, 15410, 14900, 14376, 13846,
- },
- //2850000/Qinter
- {
- 2850000,2280000,1900000,1628571,1425000,1266666,1140000,1036363,
- 950000, 876923, 814285, 760000, 712500, 670588, 633333, 600000,
- 570000, 518181, 475000, 438461, 407142, 380000, 356250, 335294,
- 316666, 300000, 285000, 271428, 259090, 247826, 237500, 223529,
- 211111, 200000, 190000, 180952, 172727, 165217, 158333, 150000,
- 142500, 135714, 129545, 123913, 118750, 114000, 108571, 103636,
- 99130, 95000, 91200, 87692, 84444, 81428, 78082, 75000,
- 72151, 69512, 67058, 64772, 62637, 60638, 58762, 57000,
- 55339, 53773, 52293, 50892, 49137, 47500, 45967, 44531,
- 43181, 41911, 40714, 39583, 38513, 37500, 36538, 35625,
- 34545, 33529, 32571, 31666, 30810, 30000, 29081, 28217,
- 27403, 26635, 25909, 25110, 24358, 23651, 22983, 22352,
- 21755, 21111, 20503, 19930, 19387, 18874, 18327, 17812,
- 17325, 16863, 16379, 15921, 15489, 15079, 14690, 14321,
- 13902, 13507, 13133, 12780, 12445, 12076, 11728, 11400,
- 11046, 10714, 10401, 10106, 9760, 9437, 9105, 8769,
- }
- };
- #endif
-
-static const int kf_boost_qadjustment[QINDEX_RANGE] =
- {
- 128, 129, 130, 131, 132, 133, 134, 135,
- 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151,
- 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183,
- 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199,
- 200, 200, 201, 201, 202, 203, 203, 203,
- 204, 204, 205, 205, 206, 206, 207, 207,
- 208, 208, 209, 209, 210, 210, 211, 211,
- 212, 212, 213, 213, 214, 214, 215, 215,
- 216, 216, 217, 217, 218, 218, 219, 219,
- 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220,
-};
-
-//#define GFQ_ADJUSTMENT (Q+100)
-#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
-const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
-{
- 80, 82, 84, 86, 88, 90, 92, 94,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135,
- 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151,
- 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183,
- 184, 184, 185, 185, 186, 186, 187, 187,
- 188, 188, 189, 189, 190, 190, 191, 191,
- 192, 192, 193, 193, 194, 194, 194, 194,
- 195, 195, 196, 196, 197, 197, 198, 198
-};
-
-/*
-const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
-{
- 100,101,102,103,104,105,105,106,
- 106,107,107,108,109,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,
- 136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,
- 152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,
- 168,169,170,170,171,171,172,172,
- 173,173,173,174,174,174,175,175,
- 175,176,176,176,177,177,177,177,
- 178,178,179,179,180,180,181,181,
- 182,182,183,183,184,184,185,185,
- 186,186,187,187,188,188,189,189,
- 190,190,191,191,192,192,193,193,
-};
-*/
-
-static const int kf_gf_boost_qlimits[QINDEX_RANGE] =
-{
- 150, 155, 160, 165, 170, 175, 180, 185,
- 190, 195, 200, 205, 210, 215, 220, 225,
- 230, 235, 240, 245, 250, 255, 260, 265,
- 270, 275, 280, 285, 290, 295, 300, 305,
- 310, 320, 330, 340, 350, 360, 370, 380,
- 390, 400, 410, 420, 430, 440, 450, 460,
- 470, 480, 490, 500, 510, 520, 530, 540,
- 550, 560, 570, 580, 590, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, 600, 600, 600,
-};
-
// % adjustment to target kf size based on seperation from previous frame
static const int kf_boost_seperation_adjustment[16] =
{
@@ -226,7 +52,6 @@ static const int kf_boost_seperation_adjustment[16] =
80, 85, 90, 95, 100, 100, 100, 100,
};
-
static const int gf_adjust_table[101] =
{
100,
@@ -265,6 +90,47 @@ static const int gf_interval_table[101] =
static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] = { 1, 2, 3, 4, 5 };
+// These functions use formulaic calculations to make playing with the
+// quantizer tables easier. If necessary they can be replaced by lookup
+// tables if and when things settle down in the experimental bitstream
+double vp8_convert_qindex_to_q( int qindex )
+{
+ // Convert the index to a real Q value (scaled down to match old Q values)
+ return (double)vp8_ac_yquant( qindex, 0 ) / 4.0;
+}
+
+int vp8_gfboost_qadjust( int qindex )
+{
+ int retval;
+ double q;
+
+ q = vp8_convert_qindex_to_q(qindex);
+ retval = (int)( ( 0.00000828 * q * q * q ) +
+ ( -0.0055 * q * q ) +
+ ( 1.32 * q ) + 79.3 );
+ return retval;
+}
+
+int kfboost_qadjust( int qindex )
+{
+ int retval;
+ double q;
+
+ q = vp8_convert_qindex_to_q(qindex);
+ retval = (int)( ( 0.00000973 * q * q * q ) +
+ ( -0.00613 * q * q ) +
+ ( 1.316 * q ) + 121.2 );
+ return retval;
+}
+
+int vp8_bits_per_mb( FRAME_TYPE frame_type, int qindex )
+{
+ if ( frame_type == KEY_FRAME )
+ return (int)(4500000 / vp8_convert_qindex_to_q(qindex));
+ else
+ return (int)(2850000 / vp8_convert_qindex_to_q(qindex));
+}
+
void vp8_save_coding_context(VP8_COMP *cpi)
{
@@ -282,6 +148,10 @@ void vp8_save_coding_context(VP8_COMP *cpi)
vp8_copy(cc->mvc, cpi->common.fc.mvc);
vp8_copy(cc->mvcosts, cpi->mb.mvcosts);
+#if CONFIG_HIGH_PRECISION_MV
+ vp8_copy(cc->mvc_hp, cpi->common.fc.mvc_hp);
+ vp8_copy(cc->mvcosts_hp, cpi->mb.mvcosts_hp);
+#endif
vp8_copy(cc->kf_ymode_prob, cpi->common.kf_ymode_prob);
vp8_copy(cc->ymode_prob, cpi->common.fc.ymode_prob);
@@ -321,7 +191,11 @@ void vp8_restore_coding_context(VP8_COMP *cpi)
vp8_copy(cpi->common.fc.mvc, cc->mvc);
vp8_copy(cpi->mb.mvcosts, cc->mvcosts);
+#if CONFIG_HIGH_PRECISION_MV
+ vp8_copy(cpi->common.fc.mvc_hp, cc->mvc_hp);
+ vp8_copy(cpi->mb.mvcosts_hp, cc->mvcosts_hp);
+#endif
vp8_copy(cpi->common.kf_ymode_prob, cc->kf_ymode_prob);
vp8_copy(cpi->common.fc.ymode_prob, cc->ymode_prob);
vp8_copy(cpi->common.kf_uv_mode_prob, cc->kf_uv_mode_prob);
@@ -357,28 +231,73 @@ void vp8_setup_key_frame(VP8_COMP *cpi)
int flag[2] = {1, 1};
vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flag);
}
-
vpx_memset(cpi->common.fc.pre_mvc, 0, sizeof(cpi->common.fc.pre_mvc)); //initialize pre_mvc to all zero.
+#if CONFIG_HIGH_PRECISION_MV
+ vpx_memcpy(cpi->common.fc.mvc_hp, vp8_default_mv_context_hp, sizeof(vp8_default_mv_context_hp));
+ {
+ int flag[2] = {1, 1};
+ vp8_build_component_cost_table_hp(cpi->mb.mvcost_hp, (const MV_CONTEXT_HP *) cpi->common.fc.mvc_hp, flag);
+ }
+ vpx_memset(cpi->common.fc.pre_mvc_hp, 0, sizeof(cpi->common.fc.pre_mvc_hp)); //initialize pre_mvc to all zero.
+#endif
+
+
+ cpi->common.txfm_mode = ONLY_4X4;
//cpi->common.filter_level = 0; // Reset every key frame.
cpi->common.filter_level = cpi->common.base_qindex * 3 / 8 ;
- // Provisional interval before next GF
- if (cpi->auto_gold)
- //cpi->frames_till_gf_update_due = DEFAULT_GF_INTERVAL;
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
- else
- cpi->frames_till_gf_update_due = cpi->goldfreq;
+ // interval before next GF
+ cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
cpi->common.refresh_golden_frame = TRUE;
cpi->common.refresh_alt_ref_frame = TRUE;
+
+ vpx_memcpy(&cpi->common.lfc, &cpi->common.fc, sizeof(cpi->common.fc));
+ vpx_memcpy(&cpi->common.lfc_a, &cpi->common.fc, sizeof(cpi->common.fc));
+
+ vp8_init_mode_contexts(&cpi->common);
+ vpx_memcpy( cpi->common.vp8_mode_contexts,
+ cpi->common.mode_context,
+ sizeof(cpi->common.mode_context));
+ vpx_memcpy( cpi->common.vp8_mode_contexts,
+ default_vp8_mode_contexts,
+ sizeof(default_vp8_mode_contexts));
+}
+void vp8_setup_inter_frame(VP8_COMP *cpi)
+{
+
+ if(cpi->common.Width * cpi->common.Height > 640*360)
+ //||cpi->this_frame_target < 7 * cpi->common.MBs)
+ cpi->common.txfm_mode = ALLOW_8X8;
+ else
+ cpi->common.txfm_mode = ONLY_4X4;
+
+ if(cpi->common.refresh_alt_ref_frame)
+ {
+ vpx_memcpy( &cpi->common.fc,
+ &cpi->common.lfc_a,
+ sizeof(cpi->common.fc));
+ vpx_memcpy( cpi->common.vp8_mode_contexts,
+ cpi->common.mode_context_a,
+ sizeof(cpi->common.vp8_mode_contexts));
+ }
+ else
+ {
+ vpx_memcpy( &cpi->common.fc,
+ &cpi->common.lfc,
+ sizeof(cpi->common.fc));
+ vpx_memcpy( cpi->common.vp8_mode_contexts,
+ cpi->common.mode_context,
+ sizeof(cpi->common.vp8_mode_contexts));
+ }
}
static int estimate_bits_at_q(int frame_kind, int Q, int MBs,
double correction_factor)
{
- int Bpm = (int)(.5 + correction_factor * vp8_bits_per_mb[frame_kind][Q]);
+ int Bpm = (int)(.5 + correction_factor * vp8_bits_per_mb(frame_kind, Q));
/* Attempt to retain reasonable accuracy without overflow. The cutoff is
* chosen such that the maximum product of Bpm and MBs fits 31 bits. The
@@ -400,53 +319,8 @@ static void calc_iframe_target_size(VP8_COMP *cpi)
// Clear down mmx registers to allow floating point in what follows
vp8_clear_system_state(); //__asm emms;
- if (cpi->oxcf.fixed_q >= 0)
- {
- int Q = cpi->oxcf.key_q;
-
- target = estimate_bits_at_q(INTRA_FRAME, Q, cpi->common.MBs,
- cpi->key_frame_rate_correction_factor);
- }
- else if (cpi->pass == 2)
- {
- // New Two pass RC
- target = cpi->per_frame_bandwidth;
- }
- // First Frame is a special case
- else if (cpi->common.current_video_frame == 0)
- {
- /* 1 Pass there is no information on which to base size so use
- * bandwidth per second * fraction of the initial buffer
- * level
- */
- target = cpi->oxcf.starting_buffer_level / 2;
-
- if(target > cpi->oxcf.target_bandwidth * 3 / 2)
- target = cpi->oxcf.target_bandwidth * 3 / 2;
- }
- else
- {
- // if this keyframe was forced, use a more recent Q estimate
- int Q = (cpi->common.frame_flags & FRAMEFLAGS_KEY)
- ? cpi->avg_frame_qindex : cpi->ni_av_qi;
-
- // Boost depends somewhat on frame rate
- kf_boost = (int)(2 * cpi->output_frame_rate - 16);
-
- // adjustment up based on q
- kf_boost = kf_boost * kf_boost_qadjustment[Q] / 100;
-
- // frame separation adjustment ( down)
- if (cpi->frames_since_key < cpi->output_frame_rate / 2)
- kf_boost = (int)(kf_boost
- * cpi->frames_since_key / (cpi->output_frame_rate / 2));
-
- if (kf_boost < 16)
- kf_boost = 16;
-
- target = ((16 + kf_boost) * cpi->per_frame_bandwidth) >> 4;
- }
-
+ // New Two pass RC
+ target = cpi->per_frame_bandwidth;
if (cpi->oxcf.rc_max_intra_bitrate_pct)
{
@@ -459,192 +333,18 @@ static void calc_iframe_target_size(VP8_COMP *cpi)
cpi->this_frame_target = target;
- // TODO: if we separate rate targeting from Q targetting, move this.
- // Reset the active worst quality to the baseline value for key frames.
- if (cpi->pass != 2)
- cpi->active_worst_quality = cpi->worst_quality;
-
-#if 0
- {
- FILE *f;
-
- f = fopen("kf_boost.stt", "a");
- //fprintf(f, " %8d %10d %10d %10d %10d %10d %10d\n",
- // cpi->common.current_video_frame, cpi->target_bandwidth, cpi->frames_to_key, kf_boost_qadjustment[cpi->ni_av_qi], cpi->kf_boost, (cpi->this_frame_target *100 / cpi->per_frame_bandwidth), cpi->this_frame_target );
-
- fprintf(f, " %8u %10d %10d %10d\n",
- cpi->common.current_video_frame, cpi->gfu_boost, cpi->baseline_gf_interval, cpi->source_alt_ref_pending);
-
- fclose(f);
- }
-#endif
}
-// Do the best we can to define the parameteres for the next GF based on what information we have available.
+// Do the best we can to define the parameteres for the next GF based
+// on what information we have available.
+//
+// In this experimental code only two pass is supported
+// so we just use the interval determined in the two pass code.
static void calc_gf_params(VP8_COMP *cpi)
{
- int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
- int Boost = 0;
-
- int gf_frame_useage = 0; // Golden frame useage since last GF
- int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME] +
- cpi->recent_ref_frame_usage[LAST_FRAME] +
- cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
- cpi->recent_ref_frame_usage[ALTREF_FRAME];
-
- int pct_gf_active = (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);
-
- // Reset the last boost indicator
- //cpi->last_boost = 100;
-
- if (tot_mbs)
- gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;
-
- if (pct_gf_active > gf_frame_useage)
- gf_frame_useage = pct_gf_active;
-
- // Not two pass
- if (cpi->pass != 2)
- {
- // Single Pass lagged mode: TBD
- if (FALSE)
- {
- }
-
- // Single Pass compression: Has to use current and historical data
- else
- {
-#if 0
- // Experimental code
- int index = cpi->one_pass_frame_index;
- int frames_to_scan = (cpi->max_gf_interval <= MAX_LAG_BUFFERS) ? cpi->max_gf_interval : MAX_LAG_BUFFERS;
-
- /*
- // *************** Experimental code - incomplete
- double decay_val = 1.0;
- double IIAccumulator = 0.0;
- double last_iiaccumulator = 0.0;
- double IIRatio;
-
- cpi->one_pass_frame_index = cpi->common.current_video_frame%MAX_LAG_BUFFERS;
-
- for ( i = 0; i < (frames_to_scan - 1); i++ )
- {
- if ( index < 0 )
- index = MAX_LAG_BUFFERS;
- index --;
-
- if ( cpi->one_pass_frame_stats[index].frame_coded_error > 0.0 )
- {
- IIRatio = cpi->one_pass_frame_stats[index].frame_intra_error / cpi->one_pass_frame_stats[index].frame_coded_error;
-
- if ( IIRatio > 30.0 )
- IIRatio = 30.0;
- }
- else
- IIRatio = 30.0;
-
- IIAccumulator += IIRatio * decay_val;
-
- decay_val = decay_val * cpi->one_pass_frame_stats[index].frame_pcnt_inter;
-
- if ( (i > MIN_GF_INTERVAL) &&
- ((IIAccumulator - last_iiaccumulator) < 2.0) )
- {
- break;
- }
- last_iiaccumulator = IIAccumulator;
- }
-
- Boost = IIAccumulator*100.0/16.0;
- cpi->baseline_gf_interval = i;
-
- */
-#else
-
- /*************************************************************/
- // OLD code
-
- // Adjust boost based upon ambient Q
- Boost = GFQ_ADJUSTMENT;
-
- // Adjust based upon most recently measure intra useage
- Boost = Boost * gf_intra_usage_adjustment[(cpi->this_frame_percent_intra < 15) ? cpi->this_frame_percent_intra : 14] / 100;
-
- // Adjust gf boost based upon GF usage since last GF
- Boost = Boost * gf_adjust_table[gf_frame_useage] / 100;
-#endif
- }
-
- // golden frame boost without recode loop often goes awry. be safe by keeping numbers down.
- if (!cpi->sf.recode_loop)
- {
- if (cpi->compressor_speed == 2)
- Boost = Boost / 2;
- }
-
- // Apply an upper limit based on Q for 1 pass encodes
- if (Boost > kf_gf_boost_qlimits[Q] && (cpi->pass == 0))
- Boost = kf_gf_boost_qlimits[Q];
-
- // Apply lower limits to boost.
- else if (Boost < 110)
- Boost = 110;
-
- // Note the boost used
- cpi->last_boost = Boost;
-
- }
-
- // Estimate next interval
- // This is updated once the real frame size/boost is known.
- if (cpi->oxcf.fixed_q == -1)
- {
- if (cpi->pass == 2) // 2 Pass
- {
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
- }
- else // 1 Pass
- {
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
-
- if (cpi->last_boost > 750)
- cpi->frames_till_gf_update_due++;
-
- if (cpi->last_boost > 1000)
- cpi->frames_till_gf_update_due++;
-
- if (cpi->last_boost > 1250)
- cpi->frames_till_gf_update_due++;
-
- if (cpi->last_boost >= 1500)
- cpi->frames_till_gf_update_due ++;
-
- if (gf_interval_table[gf_frame_useage] > cpi->frames_till_gf_update_due)
- cpi->frames_till_gf_update_due = gf_interval_table[gf_frame_useage];
-
- if (cpi->frames_till_gf_update_due > cpi->max_gf_interval)
- cpi->frames_till_gf_update_due = cpi->max_gf_interval;
- }
- }
- else
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
-
- // ARF on or off
- if (cpi->pass != 2)
- {
- // For now Alt ref is not allowed except in 2 pass modes.
- cpi->source_alt_ref_pending = FALSE;
-
- /*if ( cpi->oxcf.fixed_q == -1)
- {
- if ( cpi->oxcf.play_alternate && (cpi->last_boost > (100 + (AF_THRESH*cpi->frames_till_gf_update_due)) ) )
- cpi->source_alt_ref_pending = TRUE;
- else
- cpi->source_alt_ref_pending = FALSE;
- }*/
- }
+ // Set the gf interval
+ cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
}
@@ -655,155 +355,24 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
min_frame_target = 0;
- if (cpi->pass == 2)
- {
- min_frame_target = cpi->min_frame_bandwidth;
+ min_frame_target = cpi->min_frame_bandwidth;
- if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
- min_frame_target = cpi->av_per_frame_bandwidth >> 5;
- }
- else if (min_frame_target < cpi->per_frame_bandwidth / 4)
- min_frame_target = cpi->per_frame_bandwidth / 4;
+ if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
+ min_frame_target = cpi->av_per_frame_bandwidth >> 5;
// Special alt reference frame case
if (cpi->common.refresh_alt_ref_frame)
{
- if (cpi->pass == 2)
- {
- cpi->per_frame_bandwidth = cpi->twopass.gf_bits; // Per frame bit target for the alt ref frame
- cpi->this_frame_target = cpi->per_frame_bandwidth;
- }
-
- /* One Pass ??? TBD */
- /*else
- {
- int frames_in_section;
- int allocation_chunks;
- int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
- int alt_boost;
- int max_arf_rate;
-
- alt_boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
- alt_boost += (cpi->frames_till_gf_update_due * 50);
-
- // If alt ref is not currently active then we have a pottential double hit with GF and ARF so reduce the boost a bit.
- // A similar thing is done on GFs that preceed a arf update.
- if ( !cpi->source_alt_ref_active )
- alt_boost = alt_boost * 3 / 4;
-
- frames_in_section = cpi->frames_till_gf_update_due+1; // Standard frames + GF
- allocation_chunks = (frames_in_section * 100) + alt_boost;
-
- // Normalize Altboost and allocations chunck down to prevent overflow
- while ( alt_boost > 1000 )
- {
- alt_boost /= 2;
- allocation_chunks /= 2;
- }
-
- else
- {
- int bits_in_section;
-
- if ( cpi->kf_overspend_bits > 0 )
- {
- Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;
-
- if ( Adjustment > (cpi->per_frame_bandwidth - min_frame_target) )
- Adjustment = (cpi->per_frame_bandwidth - min_frame_target);
-
- cpi->kf_overspend_bits -= Adjustment;
-
- // Calculate an inter frame bandwidth target for the next few frames designed to recover
- // any extra bits spent on the key frame.
- cpi->inter_frame_target = cpi->per_frame_bandwidth - Adjustment;
- if ( cpi->inter_frame_target < min_frame_target )
- cpi->inter_frame_target = min_frame_target;
- }
- else
- cpi->inter_frame_target = cpi->per_frame_bandwidth;
-
- bits_in_section = cpi->inter_frame_target * frames_in_section;
-
- // Avoid loss of precision but avoid overflow
- if ( (bits_in_section>>7) > allocation_chunks )
- cpi->this_frame_target = alt_boost * (bits_in_section / allocation_chunks);
- else
- cpi->this_frame_target = (alt_boost * bits_in_section) / allocation_chunks;
- }
- }
- */
+ // Per frame bit target for the alt ref frame
+ cpi->per_frame_bandwidth = cpi->twopass.gf_bits;
+ cpi->this_frame_target = cpi->per_frame_bandwidth;
}
// Normal frames (gf,and inter)
else
{
- // 2 pass
- if (cpi->pass == 2)
- {
- cpi->this_frame_target = cpi->per_frame_bandwidth;
- }
- // 1 pass
- else
- {
- // Make rate adjustment to recover bits spent in key frame
- // Test to see if the key frame inter data rate correction should still be in force
- if (cpi->kf_overspend_bits > 0)
- {
- Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;
-
- if (Adjustment > (cpi->per_frame_bandwidth - min_frame_target))
- Adjustment = (cpi->per_frame_bandwidth - min_frame_target);
-
- cpi->kf_overspend_bits -= Adjustment;
-
- // Calculate an inter frame bandwidth target for the next few frames designed to recover
- // any extra bits spent on the key frame.
- cpi->this_frame_target = cpi->per_frame_bandwidth - Adjustment;
-
- if (cpi->this_frame_target < min_frame_target)
- cpi->this_frame_target = min_frame_target;
- }
- else
- cpi->this_frame_target = cpi->per_frame_bandwidth;
-
- // If appropriate make an adjustment to recover bits spent on a recent GF
- if ((cpi->gf_overspend_bits > 0) && (cpi->this_frame_target > min_frame_target))
- {
- int Adjustment = (cpi->non_gf_bitrate_adjustment <= cpi->gf_overspend_bits) ? cpi->non_gf_bitrate_adjustment : cpi->gf_overspend_bits;
-
- if (Adjustment > (cpi->this_frame_target - min_frame_target))
- Adjustment = (cpi->this_frame_target - min_frame_target);
-
- cpi->gf_overspend_bits -= Adjustment;
- cpi->this_frame_target -= Adjustment;
- }
-
- // Apply small + and - boosts for non gf frames
- if ((cpi->last_boost > 150) && (cpi->frames_till_gf_update_due > 0) &&
- (cpi->current_gf_interval >= (MIN_GF_INTERVAL << 1)))
- {
- // % Adjustment limited to the range 1% to 10%
- Adjustment = (cpi->last_boost - 100) >> 5;
-
- if (Adjustment < 1)
- Adjustment = 1;
- else if (Adjustment > 10)
- Adjustment = 10;
-
- // Convert to bits
- Adjustment = (cpi->this_frame_target * Adjustment) / 100;
-
- if (Adjustment > (cpi->this_frame_target - min_frame_target))
- Adjustment = (cpi->this_frame_target - min_frame_target);
-
- if (cpi->common.frames_since_golden == (cpi->current_gf_interval >> 1))
- cpi->this_frame_target += ((cpi->current_gf_interval - 1) * Adjustment);
- else
- cpi->this_frame_target -= Adjustment;
- }
- }
+ cpi->this_frame_target = cpi->per_frame_bandwidth;
}
// Sanity check that the total sum of adjustments is not above the maximum allowed
@@ -818,346 +387,43 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
// Note the baseline target data rate for this inter frame.
cpi->inter_frame_target = cpi->this_frame_target;
- // One Pass specific code
- if (cpi->pass == 0)
- {
- // Adapt target frame size with respect to any buffering constraints:
- if (cpi->buffered_mode)
- {
- int one_percent_bits = 1 + cpi->oxcf.optimal_buffer_level / 100;
-
- if ((cpi->buffer_level < cpi->oxcf.optimal_buffer_level) ||
- (cpi->bits_off_target < cpi->oxcf.optimal_buffer_level))
- {
- int percent_low = 0;
-
- // Decide whether or not we need to adjust the frame data rate target.
- //
- // If we are are below the optimal buffer fullness level and adherence
- // to buffering contraints is important to the end useage then adjust
- // the per frame target.
- if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
- (cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
- {
- percent_low =
- (cpi->oxcf.optimal_buffer_level - cpi->buffer_level) /
- one_percent_bits;
- }
- // Are we overshooting the long term clip data rate...
- else if (cpi->bits_off_target < 0)
- {
- // Adjust per frame data target downwards to compensate.
- percent_low = (int)(100 * -cpi->bits_off_target /
- (cpi->total_byte_count * 8));
- }
-
- if (percent_low > cpi->oxcf.under_shoot_pct)
- percent_low = cpi->oxcf.under_shoot_pct;
- else if (percent_low < 0)
- percent_low = 0;
-
- // lower the target bandwidth for this frame.
- cpi->this_frame_target -= (cpi->this_frame_target * percent_low)
- / 200;
-
- // Are we using allowing control of active_worst_allowed_q
- // according to buffer level.
- if (cpi->auto_worst_q)
- {
- int critical_buffer_level;
-
- // For streaming applications the most important factor is
- // cpi->buffer_level as this takes into account the
- // specified short term buffering constraints. However,
- // hitting the long term clip data rate target is also
- // important.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- // Take the smaller of cpi->buffer_level and
- // cpi->bits_off_target
- critical_buffer_level =
- (cpi->buffer_level < cpi->bits_off_target)
- ? cpi->buffer_level : cpi->bits_off_target;
- }
- // For local file playback short term buffering contraints
- // are less of an issue
- else
- {
- // Consider only how we are doing for the clip as a
- // whole
- critical_buffer_level = cpi->bits_off_target;
- }
-
- // Set the active worst quality based upon the selected
- // buffer fullness number.
- if (critical_buffer_level < cpi->oxcf.optimal_buffer_level)
- {
- if ( critical_buffer_level >
- (cpi->oxcf.optimal_buffer_level >> 2) )
- {
- int64_t qadjustment_range =
- cpi->worst_quality - cpi->ni_av_qi;
- int64_t above_base =
- (critical_buffer_level -
- (cpi->oxcf.optimal_buffer_level >> 2));
-
- // Step active worst quality down from
- // cpi->ni_av_qi when (critical_buffer_level ==
- // cpi->optimal_buffer_level) to
- // cpi->worst_quality when
- // (critical_buffer_level ==
- // cpi->optimal_buffer_level >> 2)
- cpi->active_worst_quality =
- cpi->worst_quality -
- ((qadjustment_range * above_base) /
- (cpi->oxcf.optimal_buffer_level*3>>2));
- }
- else
- {
- cpi->active_worst_quality = cpi->worst_quality;
- }
- }
- else
- {
- cpi->active_worst_quality = cpi->ni_av_qi;
- }
- }
- else
- {
- cpi->active_worst_quality = cpi->worst_quality;
- }
- }
- else
- {
- int percent_high = 0;
-
- if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- && (cpi->buffer_level > cpi->oxcf.optimal_buffer_level))
- {
- percent_high = (cpi->buffer_level
- - cpi->oxcf.optimal_buffer_level)
- / one_percent_bits;
- }
- else if (cpi->bits_off_target > cpi->oxcf.optimal_buffer_level)
- {
- percent_high = (int)((100 * cpi->bits_off_target)
- / (cpi->total_byte_count * 8));
- }
-
- if (percent_high > cpi->oxcf.over_shoot_pct)
- percent_high = cpi->oxcf.over_shoot_pct;
- else if (percent_high < 0)
- percent_high = 0;
-
- cpi->this_frame_target += (cpi->this_frame_target *
- percent_high) / 200;
-
-
- // Are we allowing control of active_worst_allowed_q according to bufferl level.
- if (cpi->auto_worst_q)
- {
- // When using the relaxed buffer model stick to the user specified value
- cpi->active_worst_quality = cpi->ni_av_qi;
- }
- else
- {
- cpi->active_worst_quality = cpi->worst_quality;
- }
- }
-
- // Set active_best_quality to prevent quality rising too high
- cpi->active_best_quality = cpi->best_quality;
-
- // Worst quality obviously must not be better than best quality
- if (cpi->active_worst_quality <= cpi->active_best_quality)
- cpi->active_worst_quality = cpi->active_best_quality + 1;
-
- }
- // Unbuffered mode (eg. video conferencing)
- else
- {
- // Set the active worst quality
- cpi->active_worst_quality = cpi->worst_quality;
- }
-
- // Special trap for constrained quality mode
- // "active_worst_quality" may never drop below cq level
- // for any frame type.
- if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY &&
- cpi->active_worst_quality < cpi->cq_target_quality)
- {
- cpi->active_worst_quality = cpi->cq_target_quality;
- }
- }
-
- // Test to see if we have to drop a frame
- // The auto-drop frame code is only used in buffered mode.
- // In unbufferd mode (eg vide conferencing) the descision to
- // code or drop a frame is made outside the codec in response to real
- // world comms or buffer considerations.
- if (cpi->drop_frames_allowed && cpi->buffered_mode &&
- (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
- ((cpi->common.frame_type != KEY_FRAME))) //|| !cpi->oxcf.allow_spatial_resampling) )
- {
- // Check for a buffer underun-crisis in which case we have to drop a frame
- if ((cpi->buffer_level < 0))
- {
-#if 0
- FILE *f = fopen("dec.stt", "a");
- fprintf(f, "%10d %10d %10d %10d ***** BUFFER EMPTY\n",
- (int) cpi->common.current_video_frame,
- cpi->decimation_factor, cpi->common.horiz_scale,
- (cpi->buffer_level * 100) / cpi->oxcf.optimal_buffer_level);
- fclose(f);
-#endif
- //vpx_log("Decoder: Drop frame due to bandwidth: %d \n",cpi->buffer_level, cpi->av_per_frame_bandwidth);
-
- cpi->drop_frame = TRUE;
- }
-
-#if 0
- // Check for other drop frame crtieria (Note 2 pass cbr uses decimation on whole KF sections)
- else if ((cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
- (cpi->drop_count < cpi->max_drop_count) && (cpi->pass == 0))
- {
- cpi->drop_frame = TRUE;
- }
-
-#endif
-
- if (cpi->drop_frame)
- {
- // Update the buffer level variable.
- cpi->bits_off_target += cpi->av_per_frame_bandwidth;
- if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
- cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
- cpi->buffer_level = cpi->bits_off_target;
- }
- else
- cpi->drop_count = 0;
- }
-
// Adjust target frame size for Golden Frames:
- if (cpi->oxcf.error_resilient_mode == 0 &&
- (cpi->frames_till_gf_update_due == 0) && !cpi->drop_frame)
+ if ( cpi->frames_till_gf_update_due == 0 )
{
//int Boost = 0;
int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
- int gf_frame_useage = 0; // Golden frame useage since last GF
- int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME] +
- cpi->recent_ref_frame_usage[LAST_FRAME] +
- cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
- cpi->recent_ref_frame_usage[ALTREF_FRAME];
-
- int pct_gf_active = (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);
+ cpi->common.refresh_golden_frame = TRUE;
- // Reset the last boost indicator
- //cpi->last_boost = 100;
+ calc_gf_params(cpi);
- if (tot_mbs)
- gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;
-
- if (pct_gf_active > gf_frame_useage)
- gf_frame_useage = pct_gf_active;
-
- // Is a fixed manual GF frequency being used
- if (cpi->auto_gold)
+ // If we are using alternate ref instead of gf then do not apply the boost
+ // It will instead be applied to the altref update
+ // Jims modified boost
+ if (!cpi->source_alt_ref_active)
{
- // For one pass throw a GF if recent frame intra useage is low or the GF useage is high
- if ((cpi->pass == 0) && (cpi->this_frame_percent_intra < 15 || gf_frame_useage >= 5))
- cpi->common.refresh_golden_frame = TRUE;
-
- // Two pass GF descision
- else if (cpi->pass == 2)
- cpi->common.refresh_golden_frame = TRUE;
- }
-
-#if 0
-
- // Debug stats
- if (0)
- {
- FILE *f;
-
- f = fopen("gf_useaget.stt", "a");
- fprintf(f, " %8ld %10ld %10ld %10ld %10ld\n",
- cpi->common.current_video_frame, cpi->gfu_boost, GFQ_ADJUSTMENT, cpi->gfu_boost, gf_frame_useage);
- fclose(f);
- }
-
-#endif
-
- if (cpi->common.refresh_golden_frame == TRUE)
- {
-#if 0
-
- if (0) // p_gw
- {
- FILE *f;
-
- f = fopen("GFexit.stt", "a");
- fprintf(f, "%8ld GF coded\n", cpi->common.current_video_frame);
- fclose(f);
- }
-
-#endif
-
- if (cpi->auto_adjust_gold_quantizer)
- {
- calc_gf_params(cpi);
- }
-
- // If we are using alternate ref instead of gf then do not apply the boost
- // It will instead be applied to the altref update
- // Jims modified boost
- if (!cpi->source_alt_ref_active)
+ if (cpi->oxcf.fixed_q < 0)
{
- if (cpi->oxcf.fixed_q < 0)
- {
- if (cpi->pass == 2)
- {
- cpi->this_frame_target = cpi->per_frame_bandwidth; // The spend on the GF is defined in the two pass code for two pass encodes
- }
- else
- {
- int Boost = cpi->last_boost;
- int frames_in_section = cpi->frames_till_gf_update_due + 1;
- int allocation_chunks = (frames_in_section * 100) + (Boost - 100);
- int bits_in_section = cpi->inter_frame_target * frames_in_section;
-
- // Normalize Altboost and allocations chunck down to prevent overflow
- while (Boost > 1000)
- {
- Boost /= 2;
- allocation_chunks /= 2;
- }
-
- // Avoid loss of precision but avoid overflow
- if ((bits_in_section >> 7) > allocation_chunks)
- cpi->this_frame_target = Boost * (bits_in_section / allocation_chunks);
- else
- cpi->this_frame_target = (Boost * bits_in_section) / allocation_chunks;
- }
- }
- else
- cpi->this_frame_target =
- (estimate_bits_at_q(1, Q, cpi->common.MBs, 1.0)
- * cpi->last_boost) / 100;
-
+ // The spend on the GF is defined in the two pass code
+ // for two pass encodes
+ cpi->this_frame_target = cpi->per_frame_bandwidth;
}
- // If there is an active ARF at this location use the minimum
- // bits on this frame even if it is a contructed arf.
- // The active maximum quantizer insures that an appropriate
- // number of bits will be spent if needed for contstructed ARFs.
else
- {
- cpi->this_frame_target = 0;
- }
-
- cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+ cpi->this_frame_target =
+ (estimate_bits_at_q(1, Q, cpi->common.MBs, 1.0)
+ * cpi->last_boost) / 100;
}
+ // If there is an active ARF at this location use the minimum
+ // bits on this frame even if it is a contructed arf.
+ // The active maximum quantizer insures that an appropriate
+ // number of bits will be spent if needed for contstructed ARFs.
+ else
+ {
+ cpi->this_frame_target = 0;
+ }
+
+ cpi->current_gf_interval = cpi->frames_till_gf_update_due;
}
}
@@ -1188,8 +454,10 @@ void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var)
// Work out how big we would have expected the frame to be at this Q given the current correction factor.
// Stay in double to avoid int overflow when values are large
- //projected_size_based_on_q = ((int)(.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) >> BPER_MB_NORMBITS;
- projected_size_based_on_q = (int)(((.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) / (1 << BPER_MB_NORMBITS));
+ projected_size_based_on_q =
+ (int)(((.5 + rate_correction_factor *
+ vp8_bits_per_mb(cpi->common.frame_type, Q)) *
+ cpi->common.MBs) / (1 << BPER_MB_NORMBITS));
// Make some allowance for cpi->zbin_over_quant
if (cpi->zbin_over_quant > 0)
@@ -1270,126 +538,93 @@ int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame)
{
int Q = cpi->active_worst_quality;
+ int i;
+ int last_error = INT_MAX;
+ int target_bits_per_mb;
+ int bits_per_mb_at_this_q;
+ double correction_factor;
+
// Reset Zbin OQ value
cpi->zbin_over_quant = 0;
- if (cpi->oxcf.fixed_q >= 0)
- {
- Q = cpi->oxcf.fixed_q;
-
- if (cpi->common.frame_type == KEY_FRAME)
- {
- Q = cpi->oxcf.key_q;
- }
- else if (cpi->common.refresh_alt_ref_frame)
- {
- Q = cpi->oxcf.alt_q;
- }
- else if (cpi->common.refresh_golden_frame)
- {
- Q = cpi->oxcf.gold_q;
- }
-
- }
+ // Select the appropriate correction factor based upon type of frame.
+ if (cpi->common.frame_type == KEY_FRAME)
+ correction_factor = cpi->key_frame_rate_correction_factor;
else
{
- int i;
- int last_error = INT_MAX;
- int target_bits_per_mb;
- int bits_per_mb_at_this_q;
- double correction_factor;
-
- // Select the appropriate correction factor based upon type of frame.
- if (cpi->common.frame_type == KEY_FRAME)
- correction_factor = cpi->key_frame_rate_correction_factor;
- else
- {
- if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
- correction_factor = cpi->gf_rate_correction_factor;
- else
- correction_factor = cpi->rate_correction_factor;
- }
-
- // Calculate required scaling factor based on target frame size and size of frame produced using previous Q
- if (target_bits_per_frame >= (INT_MAX >> BPER_MB_NORMBITS))
- target_bits_per_mb = (target_bits_per_frame / cpi->common.MBs) << BPER_MB_NORMBITS; // Case where we would overflow int
+ if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+ correction_factor = cpi->gf_rate_correction_factor;
else
- target_bits_per_mb = (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
-
- i = cpi->active_best_quality;
+ correction_factor = cpi->rate_correction_factor;
+ }
- do
- {
- bits_per_mb_at_this_q = (int)(.5 + correction_factor * vp8_bits_per_mb[cpi->common.frame_type][i]);
+ // Calculate required scaling factor based on target frame size and size of frame produced using previous Q
+ if (target_bits_per_frame >= (INT_MAX >> BPER_MB_NORMBITS))
+ target_bits_per_mb = (target_bits_per_frame / cpi->common.MBs) << BPER_MB_NORMBITS; // Case where we would overflow int
+ else
+ target_bits_per_mb = (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
- if (bits_per_mb_at_this_q <= target_bits_per_mb)
- {
- if ((target_bits_per_mb - bits_per_mb_at_this_q) <= last_error)
- Q = i;
- else
- Q = i - 1;
-
- break;
- }
- else
- last_error = bits_per_mb_at_this_q - target_bits_per_mb;
- }
- while (++i <= cpi->active_worst_quality);
+ i = cpi->active_best_quality;
+ do
+ {
+ bits_per_mb_at_this_q =
+ (int)(.5 + correction_factor *
+ vp8_bits_per_mb(cpi->common.frame_type, i ));
- // If we are at MAXQ then enable Q over-run which seeks to claw back additional bits through things like
- // the RD multiplier and zero bin size.
- if (Q >= MAXQ)
+ if (bits_per_mb_at_this_q <= target_bits_per_mb)
{
- int zbin_oqmax;
-
- double Factor = 0.99;
- double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;
-
- if (cpi->common.frame_type == KEY_FRAME)
- zbin_oqmax = 0; //ZBIN_OQ_MAX/16
- else if (cpi->common.refresh_alt_ref_frame || (cpi->common.refresh_golden_frame && !cpi->source_alt_ref_active))
- zbin_oqmax = 16;
+ if ((target_bits_per_mb - bits_per_mb_at_this_q) <= last_error)
+ Q = i;
else
- zbin_oqmax = ZBIN_OQ_MAX;
-
- /*{
- double Factor = (double)target_bits_per_mb/(double)bits_per_mb_at_this_q;
- double Oq;
+ Q = i - 1;
- Factor = Factor/1.2683;
+ break;
+ }
+ else
+ last_error = bits_per_mb_at_this_q - target_bits_per_mb;
+ }
+ while (++i <= cpi->active_worst_quality);
- Oq = pow( Factor, (1.0/-0.165) );
- if ( Oq > zbin_oqmax )
- Oq = zbin_oqmax;
+ // If we are at MAXQ then enable Q over-run which seeks to claw back additional bits through things like
+ // the RD multiplier and zero bin size.
+ if (Q >= MAXQ)
+ {
+ int zbin_oqmax;
- cpi->zbin_over_quant = (int)Oq;
- }*/
+ double Factor = 0.99;
+ double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;
- // Each incrment in the zbin is assumed to have a fixed effect on bitrate. This is not of course true.
- // The effect will be highly clip dependent and may well have sudden steps.
- // The idea here is to acheive higher effective quantizers than the normal maximum by expanding the zero
- // bin and hence decreasing the number of low magnitude non zero coefficients.
- while (cpi->zbin_over_quant < zbin_oqmax)
- {
- cpi->zbin_over_quant ++;
+ if (cpi->common.frame_type == KEY_FRAME)
+ zbin_oqmax = 0; //ZBIN_OQ_MAX/16
+ else if (cpi->common.refresh_alt_ref_frame || (cpi->common.refresh_golden_frame && !cpi->source_alt_ref_active))
+ zbin_oqmax = 16;
+ else
+ zbin_oqmax = ZBIN_OQ_MAX;
- if (cpi->zbin_over_quant > zbin_oqmax)
- cpi->zbin_over_quant = zbin_oqmax;
+ // Each incrment in the zbin is assumed to have a fixed effect on bitrate. This is not of course true.
+ // The effect will be highly clip dependent and may well have sudden steps.
+ // The idea here is to acheive higher effective quantizers than the normal maximum by expanding the zero
+ // bin and hence decreasing the number of low magnitude non zero coefficients.
+ while (cpi->zbin_over_quant < zbin_oqmax)
+ {
+ cpi->zbin_over_quant ++;
- // Adjust bits_per_mb_at_this_q estimate
- bits_per_mb_at_this_q = (int)(Factor * bits_per_mb_at_this_q);
- Factor += factor_adjustment;
+ if (cpi->zbin_over_quant > zbin_oqmax)
+ cpi->zbin_over_quant = zbin_oqmax;
- if (Factor >= 0.999)
- Factor = 0.999;
+ // Adjust bits_per_mb_at_this_q estimate
+ bits_per_mb_at_this_q = (int)(Factor * bits_per_mb_at_this_q);
+ Factor += factor_adjustment;
- if (bits_per_mb_at_this_q <= target_bits_per_mb) // Break out if we get down to the target rate
- break;
- }
+ if (Factor >= 0.999)
+ Factor = 0.999;
+ if (bits_per_mb_at_this_q <= target_bits_per_mb) // Break out if we get down to the target rate
+ break;
}
+
}
return Q;
@@ -1454,28 +689,6 @@ void vp8_adjust_key_frame_context(VP8_COMP *cpi)
// Clear down mmx registers to allow floating point in what follows
vp8_clear_system_state();
- // Do we have any key frame overspend to recover?
- // Two-pass overspend handled elsewhere.
- if ((cpi->pass != 2)
- && (cpi->projected_frame_size > cpi->per_frame_bandwidth))
- {
- int overspend;
-
- /* Update the count of key frame overspend to be recovered in
- * subsequent frames. A portion of the KF overspend is treated as gf
- * overspend (and hence recovered more quickly) as the kf is also a
- * gf. Otherwise the few frames following each kf tend to get more
- * bits allocated than those following other gfs.
- */
- overspend = (cpi->projected_frame_size - cpi->per_frame_bandwidth);
- cpi->kf_overspend_bits += overspend * 7 / 8;
- cpi->gf_overspend_bits += overspend * 1 / 8;
-
- /* Work out how much to try and recover per frame. */
- cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits
- / estimate_keyframe_frequency(cpi);
- }
-
cpi->frames_since_key = 0;
cpi->key_frame_count++;
}
@@ -1506,45 +719,27 @@ void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit,
}
else
{
- // For CBR take buffer fullness into account
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+ // Stron overshoot limit for constrained quality
+ if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
{
- if (cpi->buffer_level >= ((cpi->oxcf.optimal_buffer_level + cpi->oxcf.maximum_buffer_size) >> 1))
- {
- // Buffer is too full so relax overshoot and tighten undershoot
- *frame_over_shoot_limit = cpi->this_frame_target * 12 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 6 / 8;
- }
- else if (cpi->buffer_level <= (cpi->oxcf.optimal_buffer_level >> 1))
- {
- // Buffer is too low so relax undershoot and tighten overshoot
- *frame_over_shoot_limit = cpi->this_frame_target * 10 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 4 / 8;
- }
- else
- {
- *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
- }
+ *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
+ *frame_under_shoot_limit = cpi->this_frame_target * 2 / 8;
}
- // VBR and CQ mode
- // Note that tighter restrictions here can help quality but hurt encode speed
else
{
- // Stron overshoot limit for constrained quality
- if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
- {
- *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 2 / 8;
- }
- else
- {
- *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
- }
+ *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
+ *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
}
}
}
+
+ // For very small rate targets where the fractional adjustment
+ // (eg * 7/8) may be tiny make sure there is at least a minimum
+ // range.
+ *frame_over_shoot_limit += 200;
+ *frame_under_shoot_limit -= 200;
+ if ( *frame_under_shoot_limit < 0 )
+ *frame_under_shoot_limit = 0;
}
}
@@ -1557,16 +752,7 @@ int vp8_pick_frame_size(VP8_COMP *cpi)
if (cm->frame_type == KEY_FRAME)
calc_iframe_target_size(cpi);
else
- {
calc_pframe_target_size(cpi);
- // Check if we're dropping the frame:
- if (cpi->drop_frame)
- {
- cpi->drop_frame = FALSE;
- cpi->drop_count++;
- return 0;
- }
- }
return 1;
}
diff --git a/vp8/encoder/ratectrl.h b/vp8/encoder/ratectrl.h
index d4f779677..85d36fd6b 100644
--- a/vp8/encoder/ratectrl.h
+++ b/vp8/encoder/ratectrl.h
@@ -13,6 +13,8 @@
#include "onyx_int.h"
+#define FRAME_OVERHEAD_BITS 200
+
extern void vp8_save_coding_context(VP8_COMP *cpi);
extern void vp8_restore_coding_context(VP8_COMP *cpi);
@@ -25,4 +27,8 @@ extern void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_
// return of 0 means drop frame
extern int vp8_pick_frame_size(VP8_COMP *cpi);
+extern double vp8_convert_qindex_to_q( int qindex );
+extern int vp8_gfboost_qadjust( int qindex );
+extern int vp8_bits_per_mb( FRAME_TYPE frame_type, int qindex );
+
#endif
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
index 73beffb39..1f02f55d9 100644
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -25,6 +25,7 @@
#include "vp8/common/reconintra.h"
#include "vp8/common/reconintra4x4.h"
#include "vp8/common/findnearmv.h"
+#include "vp8/common/quant_common.h"
#include "encodemb.h"
#include "quantize.h"
#include "vp8/common/idct.h"
@@ -32,20 +33,29 @@
#include "variance.h"
#include "mcomp.h"
#include "rdopt.h"
+#include "ratectrl.h"
#include "vpx_mem/vpx_mem.h"
#include "dct.h"
#include "vp8/common/systemdependent.h"
+#include "vp8/common/seg_common.h"
+#include "vp8/common/pred_common.h"
+
#if CONFIG_RUNTIME_CPU_DETECT
#define IF_RTCD(x) (x)
#else
#define IF_RTCD(x) NULL
#endif
-
extern void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x);
extern void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x);
+#if CONFIG_HIGH_PRECISION_MV
+#define XMVCOST (x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost)
+#else
+#define XMVCOST (x->mvcost)
+#endif
+
#define MAXF(a,b) (((a) > (b)) ? (a) : (b))
static const int auto_speed_thresh[17] =
@@ -99,6 +109,24 @@ const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES] =
SPLITMV,
B_PRED,
+ I8X8_PRED,
+
+ /* compound prediction modes */
+ ZEROMV,
+ NEARESTMV,
+ NEARMV,
+
+ ZEROMV,
+ NEARESTMV,
+ NEARMV,
+
+ ZEROMV,
+ NEARESTMV,
+ NEARMV,
+
+ NEWMV,
+ NEWMV,
+ NEWMV,
};
const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES] =
@@ -131,6 +159,48 @@ const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES] =
ALTREF_FRAME,
INTRA_FRAME,
+ INTRA_FRAME,
+
+ /* compound prediction modes */
+ LAST_FRAME,
+ LAST_FRAME,
+ LAST_FRAME,
+
+ ALTREF_FRAME,
+ ALTREF_FRAME,
+ ALTREF_FRAME,
+
+ GOLDEN_FRAME,
+ GOLDEN_FRAME,
+ GOLDEN_FRAME,
+
+ LAST_FRAME,
+ ALTREF_FRAME,
+ GOLDEN_FRAME,
+};
+
+const MV_REFERENCE_FRAME vp8_second_ref_frame_order[MAX_MODES] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+
+ /* compound prediction modes */
+ GOLDEN_FRAME,
+ GOLDEN_FRAME,
+ GOLDEN_FRAME,
+
+ LAST_FRAME,
+ LAST_FRAME,
+ LAST_FRAME,
+
+ ALTREF_FRAME,
+ ALTREF_FRAME,
+ ALTREF_FRAME,
+
+ GOLDEN_FRAME,
+ LAST_FRAME,
+ ALTREF_FRAME,
};
static void fill_token_costs(
@@ -144,8 +214,14 @@ static void fill_token_costs(
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+ {
- vp8_cost_tokens((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree);
+ if(k == 0 && ((j > 0 && i > 0) || (j > 1 && i == 0)))
+ vp8_cost_tokens_skip((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree);
+ else
+
+ vp8_cost_tokens((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree);
+ }
}
@@ -156,87 +232,33 @@ static int rd_iifactor [ 32 ] = { 4, 4, 3, 2, 1, 0, 0, 0,
};
// 3* dc_qlookup[Q]*dc_qlookup[Q];
-#if !CONFIG_EXTEND_QRANGE
-static int rdmult_lut[QINDEX_RANGE]=
-{
- 48,75,108,147,192,243,300,300,
- 363,432,507,588,675,768,867,867,
- 972,1083,1200,1200,1323,1323,1452,1452,
- 1587,1587,1728,1875,1875,2028,2187,2352,
- 2523,2700,2883,3072,3267,3468,3675,3888,
- 4107,4107,4332,4563,4800,5043,5292,5547,
- 5808,6075,6348,6348,6627,6912,7203,7500,
- 7803,8112,8427,8748,9075,9408,9747,10092,
- 10443,10800,11163,11532,11907,12288,12675,13068,
- 13467,13872,14283,14700,15123,15552,15987,16428,
- 16875,17328,17328,17787,18252,18723,19200,19683,
- 20172,20667,21168,21675,22188,22707,23232,23763,
- 24843,25947,27075,27648,28812,30000,30603,31212,
- 32448,33708,34992,36300,37632,38988,40368,41772,
- 44652,46128,47628,49152,50700,52272,53868,55488,
- 57132,58800,61347,63075,65712,68403,71148,73947,
-};
-#else
-static int rdmult_lut[QINDEX_RANGE]=
-{
- 3,5,7,9,12,15,19,23,
- 27,32,37,42,48,54,61,68,
- 75,83,91,99,108,117,127,137,
- 147,169,192,217,243,271,300,331,
- 363,397,450,507,567,631,698,768,
- 842,919,999,1083,1170,1261,1355,1452,
- 1587,1728,1875,2028,2187,2352,2523,2700,
- 2883,3072,3267,3468,3675,3888,4107,4332,
- 4563,4800,5043,5292,5547,5808,6075,6348,
- 6627,6912,7203,7500,7880,8269,8667,9075,
- 9492,9919,10355,10800,11255,11719,12192,12675,
- 13167,13669,14180,14700,15230,15769,16317,16875,
- 18019,19200,20419,21675,22969,24300,25669,27075,
- 28519,30000,31519,33075,34669,36300,37969,39675,
- 41772,43923,46128,48387,50700,53067,55488,57963,
- 61347,64827,69312,73947,78732,83667,89787,97200,
-};
-#endif
/* values are now correlated to quantizer */
-static int sad_per_bit16lut[QINDEX_RANGE] =
+static int sad_per_bit16lut[QINDEX_RANGE];
+static int sad_per_bit4lut[QINDEX_RANGE];
+
+void vp8_init_me_luts()
{
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 10, 10,
- 10, 10, 10, 10, 10, 10, 11, 11,
- 11, 11, 11, 11, 12, 12, 12, 12,
- 12, 12, 13, 13, 13, 13, 14, 14
-};
-static int sad_per_bit4lut[QINDEX_RANGE] =
+ int i;
+
+ // Initialize the sad lut tables using a formulaic calculation for now
+ // This is to make it easier to resolve the impact of experimental changes
+ // to the quantizer tables.
+ for ( i = 0; i < QINDEX_RANGE; i++ )
+ {
+ sad_per_bit16lut[i] =
+ (int)((0.0418*vp8_convert_qindex_to_q(i)) + 2.4107);
+ sad_per_bit4lut[i] = (int)((0.063*vp8_convert_qindex_to_q(i)) + 2.742);
+ }
+}
+
+int compute_rd_mult( int qindex )
{
- 2, 2, 2, 2, 2, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 5, 5,
- 5, 5, 5, 5, 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, 8, 8, 8,
- 8, 8, 9, 9, 9, 9, 9, 9,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 14,
- 14, 14, 14, 14, 15, 15, 15, 15,
- 16, 16, 16, 16, 17, 17, 17, 18,
- 18, 18, 19, 19, 19, 20, 20, 20,
-};
+ int q;
+
+ q = vp8_dc_quant(qindex,0);
+ return (11 * q * q) >> 6;
+}
void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex)
{
@@ -245,15 +267,10 @@ void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex)
}
-
-
-
void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
{
int q;
int i;
- int *thresh;
- int threshmult;
vp8_clear_system_state(); //__asm emms;
@@ -261,14 +278,14 @@ void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
// for key frames, golden frames and arf frames.
// if (cpi->common.refresh_golden_frame ||
// cpi->common.refresh_alt_ref_frame)
- QIndex=(QIndex<0)? 0 : ((QIndex>127)?127 : QIndex);
- cpi->RDMULT = rdmult_lut[QIndex];
+ QIndex=(QIndex<0)? 0 : ((QIndex>MAXQ)?MAXQ : QIndex);
+
+ cpi->RDMULT = compute_rd_mult(QIndex);
// Extend rate multiplier along side quantizer zbin increases
if (cpi->zbin_over_quant > 0)
{
double oq_factor;
- double modq;
// Experimental code using the same basic equation as used for Q above
// The units of cpi->zbin_over_quant are 1/128 of Q bin size
@@ -285,31 +302,21 @@ void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
(cpi->RDMULT * rd_iifactor[cpi->twopass.next_iiratio]) >> 4;
}
-#if !CONFIG_EXTEND_QRANGE
-#else
if (cpi->RDMULT < 7)
cpi->RDMULT = 7;
-#endif
+
cpi->mb.errorperbit = (cpi->RDMULT / 110);
cpi->mb.errorperbit += (cpi->mb.errorperbit==0);
-#if CONFIG_EXTEND_QRANGE
- if(cpi->mb.errorperbit<1)
- cpi->mb.errorperbit=1;
-#endif
vp8_set_speed_features(cpi);
- q = (int)pow(vp8_dc_quant(QIndex,0), 1.25);
+ q = (int)pow(vp8_dc_quant(QIndex,0)>>2, 1.25);
+ q = q << 2;
+ cpi->RDMULT = cpi->RDMULT << 4;
if (q < 8)
q = 8;
-
-
-#if CONFIG_EXTEND_QRANGE
- cpi->RDMULT *= 16;
-#endif
-
if (cpi->RDMULT > 1000)
{
cpi->RDDIV = 1;
@@ -353,6 +360,14 @@ void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
(const vp8_prob( *)[8][3][11]) cpi->common.fc.coef_probs
);
+ fill_token_costs(
+ cpi->mb.token_costs_8x8,
+ (const vp8_prob( *)[8][3][11]) cpi->common.fc.coef_probs_8x8
+ );
+#if CONFIG_QIMODE
+ //rough estimate for costing
+ cpi->common.kf_ymode_probs_index = cpi->common.base_qindex>>4;
+#endif
vp8_init_mode_costs(cpi);
}
@@ -526,10 +541,17 @@ int VP8_UVSSE(MACROBLOCK *x, const vp8_variance_rtcd_vtable_t *rtcd)
if ((mv_row | mv_col) & 7)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ VARIANCE_INVOKE(rtcd, subpixvar8x8)(uptr, pre_stride,
+ (mv_col & 7)<<1, (mv_row & 7)<<1, upred_ptr, uv_stride, &sse2);
+ VARIANCE_INVOKE(rtcd, subpixvar8x8)(vptr, pre_stride,
+ (mv_col & 7)<<1, (mv_row & 7)<<1, vpred_ptr, uv_stride, &sse1);
+#else
VARIANCE_INVOKE(rtcd, subpixvar8x8)(uptr, pre_stride,
mv_col & 7, mv_row & 7, upred_ptr, uv_stride, &sse2);
VARIANCE_INVOKE(rtcd, subpixvar8x8)(vptr, pre_stride,
mv_col & 7, mv_row & 7, vpred_ptr, uv_stride, &sse1);
+#endif
sse2 += sse1;
}
else
@@ -640,18 +662,141 @@ static void macro_block_yrd( MACROBLOCK *mb,
// Distortion
d = ENCODEMB_INVOKE(rtcd, mberr)(mb, 1) << 2;
-#if CONFIG_EXTEND_QRANGE
d += ENCODEMB_INVOKE(rtcd, berr)(mb_y2->coeff, x_y2->dqcoeff)<<2;
-#else
- d += ENCODEMB_INVOKE(rtcd, berr)(mb_y2->coeff, x_y2->dqcoeff);
-#endif
*Distortion = (d >> 4);
-
// rate
*Rate = vp8_rdcost_mby(mb);
}
+
+static int cost_coeffs_2x2(MACROBLOCK *mb,
+ BLOCKD *b, int type,
+ ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+ int c = !type; /* start at coef 0, unless Y with Y2 */
+ int eob = b->eob;
+ int pt ; /* surrounding block/prev coef predictor */
+ int cost = 0;
+ short *qcoeff_ptr = b->qcoeff;
+
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+ assert(eob<=4);
+
+# define QC2X2( I) ( qcoeff_ptr [vp8_default_zig_zag1d[I]] )
+
+ for (; c < eob; c++)
+ {
+ int v = QC2X2(c);
+ int t = vp8_dct_value_tokens_ptr[v].Token;
+ cost += mb->token_costs_8x8[type] [vp8_coef_bands[c]] [pt] [t];
+ cost += vp8_dct_value_cost_ptr[v];
+ pt = vp8_prev_token_class[t];
+ }
+
+# undef QC2X2
+ if (c < 4)
+ cost += mb->token_costs_8x8 [type][vp8_coef_bands[c]]
+ [pt] [DCT_EOB_TOKEN];
+
+ pt = (c != !type); // is eob first coefficient;
+ *a = *l = pt;
+ return cost;
+}
+
+
+static int cost_coeffs_8x8(MACROBLOCK *mb,
+ BLOCKD *b, int type,
+ ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+ int c = !type; /* start at coef 0, unless Y with Y2 */
+ int eob = b->eob;
+ int pt ; /* surrounding block/prev coef predictor */
+ int cost = 0;
+ short *qcoeff_ptr = b->qcoeff;
+
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+# define QC8X8( I) ( qcoeff_ptr [vp8_default_zig_zag1d_8x8[I]] )
+
+ for (; c < eob; c++)
+ {
+ int v = QC8X8(c);
+ int t = vp8_dct_value_tokens_ptr[v].Token;
+ cost += mb->token_costs_8x8[type] [vp8_coef_bands_8x8[c]] [pt] [t];
+ cost += vp8_dct_value_cost_ptr[v];
+ pt = vp8_prev_token_class[t];
+ }
+
+# undef QC8X8
+ if (c < 64)
+ cost += mb->token_costs_8x8 [type][vp8_coef_bands_8x8[c]]
+ [pt] [DCT_EOB_TOKEN];
+
+ pt = (c != !type); // is eob first coefficient;
+ *a = *l = pt;
+ return cost;
+}
+static int vp8_rdcost_mby_8x8(MACROBLOCK *mb)
+{
+ int cost = 0;
+ int b;
+ MACROBLOCKD *x = &mb->e_mbd;
+ ENTROPY_CONTEXT_PLANES t_above, t_left;
+ ENTROPY_CONTEXT *ta;
+ ENTROPY_CONTEXT *tl;
+
+ vpx_memcpy(&t_above, mb->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, mb->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+
+ for (b = 0; b < 16; b+=4)
+ cost += cost_coeffs_8x8(mb, x->block + b, PLANE_TYPE_Y_NO_DC,
+ ta + vp8_block2above_8x8[b], tl + vp8_block2left_8x8[b]);
+
+ cost += cost_coeffs_2x2(mb, x->block + 24, PLANE_TYPE_Y2,
+ ta + vp8_block2above[24], tl + vp8_block2left[24]);
+ return cost;
+}
+
+static void macro_block_yrd_8x8( MACROBLOCK *mb,
+ int *Rate,
+ int *Distortion,
+ const VP8_ENCODER_RTCD *rtcd)
+{
+ MACROBLOCKD *const x = &mb->e_mbd;
+ BLOCK *const mb_y2 = mb->block + 24;
+ BLOCKD *const x_y2 = x->block + 24;
+ short *Y2DCPtr = mb_y2->src_diff;
+ int d;
+
+ ENCODEMB_INVOKE(&rtcd->encodemb, submby)
+ ( mb->src_diff, *(mb->block[0].base_src),
+ mb->e_mbd.predictor, mb->block[0].src_stride );
+
+ vp8_transform_mby_8x8(mb);
+ vp8_quantize_mby_8x8(mb);
+
+ /* remove 1st order dc to properly combine 1st/2nd order distortion */
+ mb->coeff[0] = 0;
+ mb->coeff[64] = 0;
+ mb->coeff[128] = 0;
+ mb->coeff[192] = 0;
+ mb->e_mbd.dqcoeff[0] = 0;
+ mb->e_mbd.dqcoeff[64] = 0;
+ mb->e_mbd.dqcoeff[128] = 0;
+ mb->e_mbd.dqcoeff[192] = 0;
+ d = ENCODEMB_INVOKE(&rtcd->encodemb, mberr)(mb, 0) << 2;
+
+ d += ENCODEMB_INVOKE(&rtcd->encodemb, berr)(mb_y2->coeff, x_y2->dqcoeff)<<2;
+
+ *Distortion = (d >> 4);
+ // rate
+ *Rate = vp8_rdcost_mby_8x8(mb);
+}
+
static void copy_predictor(unsigned char *dst, const unsigned char *predictor)
{
const unsigned int *p = (const unsigned int *)predictor;
@@ -661,21 +806,51 @@ static void copy_predictor(unsigned char *dst, const unsigned char *predictor)
d[8] = p[8];
d[12] = p[12];
}
+
+static void copy_predictor_8x8(unsigned char *dst, const unsigned char *predictor)
+{
+ const unsigned int *p = (const unsigned int *)predictor;
+ unsigned int *d = (unsigned int *)dst;
+ d[0] = p[0];
+ d[1] = p[1];
+ d[4] = p[4];
+ d[5] = p[5];
+ d[8] = p[8];
+ d[9] = p[9];
+ d[12] = p[12];
+ d[13] = p[13];
+ d[16] = p[16];
+ d[17] = p[17];
+ d[20] = p[20];
+ d[21] = p[21];
+ d[24] = p[24];
+ d[25] = p[25];
+ d[28] = p[28];
+ d[29] = p[29];
+}
+
static int rd_pick_intra4x4block(
VP8_COMP *cpi,
MACROBLOCK *x,
BLOCK *be,
BLOCKD *b,
B_PREDICTION_MODE *best_mode,
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE *best_second_mode,
+#endif
unsigned int *bmode_costs,
ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l,
int *bestrate,
int *bestratey,
- int *bestdistortion)
+ int *bestdistortion,
+ int allow_comp)
{
B_PREDICTION_MODE mode;
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE mode2;
+#endif
int best_rd = INT_MAX;
int rate = 0;
int distortion;
@@ -692,13 +867,30 @@ static int rd_pick_intra4x4block(
for (mode = B_DC_PRED; mode <= B_HU_PRED; mode++)
{
+#if CONFIG_COMP_INTRA_PRED
+ for (mode2 = (allow_comp ? 0 : (B_DC_PRED - 1)); mode2 != (allow_comp ? (mode + 1) : 0); mode2++)
+ {
+#endif
int this_rd;
int ratey;
rate = bmode_costs[mode];
+#if CONFIG_COMP_INTRA_PRED
+ if (mode2 == (B_PREDICTION_MODE) (B_DC_PRED - 1))
+ {
+#endif
RECON_INVOKE(&cpi->rtcd.common->recon, intra4x4_predict)
(b, mode, b->predictor);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ RECON_INVOKE(&cpi->rtcd.common->recon, comp_intra4x4_predict)
+ (b, mode, mode2, b->predictor);
+ rate += bmode_costs[mode2];
+ }
+#endif
ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), subb)(be, b, 16);
x->vp8_short_fdct4x4(be->src_diff, be->coeff, 32);
x->quantize_b(be, b);
@@ -719,13 +911,22 @@ static int rd_pick_intra4x4block(
*bestdistortion = distortion;
best_rd = this_rd;
*best_mode = mode;
+#if CONFIG_COMP_INTRA_PRED
+ *best_second_mode = mode2;
+#endif
*a = tempa;
*l = templ;
copy_predictor(best_predictor, b->predictor);
vpx_memcpy(best_dqcoeff, b->dqcoeff, 32);
+#if CONFIG_COMP_INTRA_PRED
+ }
+#endif
}
}
- b->bmi.as_mode = (B_PREDICTION_MODE)(*best_mode);
+ b->bmi.as_mode.first = (B_PREDICTION_MODE)(*best_mode);
+#if CONFIG_COMP_INTRA_PRED
+ b->bmi.as_mode.second = (B_PREDICTION_MODE)(*best_second_mode);
+#endif
IDCT_INVOKE(IF_RTCD(&cpi->rtcd.common->idct), idct16)(best_dqcoeff, b->diff, 32);
RECON_INVOKE(IF_RTCD(&cpi->rtcd.common->recon), recon)(best_predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
@@ -734,7 +935,8 @@ static int rd_pick_intra4x4block(
}
static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
- int *rate_y, int *Distortion, int best_rd)
+ int *rate_y, int *Distortion, int best_rd,
+ int allow_comp)
{
MACROBLOCKD *const xd = &mb->e_mbd;
int i;
@@ -762,6 +964,9 @@ static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
MODE_INFO *const mic = xd->mode_info_context;
const int mis = xd->mode_info_stride;
B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_second_mode);
+#endif
int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(ry), UNINITIALIZED_IS_SAFE(d);
if (mb->e_mbd.frame_type == KEY_FRAME)
@@ -773,15 +978,21 @@ static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
}
total_rd += rd_pick_intra4x4block(
- cpi, mb, mb->block + i, xd->block + i, &best_mode, bmode_costs,
- ta + vp8_block2above[i],
- tl + vp8_block2left[i], &r, &ry, &d);
+ cpi, mb, mb->block + i, xd->block + i, &best_mode,
+#if CONFIG_COMP_INTRA_PRED
+ &best_second_mode,
+#endif
+ bmode_costs, ta + vp8_block2above[i],
+ tl + vp8_block2left[i], &r, &ry, &d, allow_comp);
cost += r;
distortion += d;
tot_rate_y += ry;
- mic->bmi[i].as_mode = best_mode;
+ mic->bmi[i].as_mode.first = best_mode;
+#if CONFIG_COMP_INTRA_PRED
+ mic->bmi[i].as_mode.second = best_second_mode;
+#endif
if(total_rd >= (int64_t)best_rd)
break;
@@ -790,7 +1001,7 @@ static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
if(total_rd >= (int64_t)best_rd)
return INT_MAX;
- *Rate = cost;
+ *Rate = cost + vp8_cost_bit(128, allow_comp);
*rate_y += tot_rate_y;
*Distortion = distortion;
@@ -806,6 +1017,10 @@ static int rd_pick_intra16x16mby_mode(VP8_COMP *cpi,
{
MB_PREDICTION_MODE mode;
MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+#if CONFIG_COMP_INTRA_PRED
+ MB_PREDICTION_MODE mode2;
+ MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode2_selected);
+#endif
int rate, ratey;
int distortion;
int best_rd = INT_MAX;
@@ -815,11 +1030,27 @@ static int rd_pick_intra16x16mby_mode(VP8_COMP *cpi,
for (mode = DC_PRED; mode <= TM_PRED; mode++)
{
x->e_mbd.mode_info_context->mbmi.mode = mode;
-
+#if CONFIG_COMP_INTRA_PRED
+ for (mode2 = DC_PRED - 1; mode2 != TM_PRED + 1; mode2++)
+ {
+ x->e_mbd.mode_info_context->mbmi.second_mode = mode2;
+ if (mode2 == (MB_PREDICTION_MODE) (DC_PRED - 1))
+ {
+#endif
RECON_INVOKE(&cpi->common.rtcd.recon, build_intra_predictors_mby)
(&x->e_mbd);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ continue; // i.e. disable for now
+ RECON_INVOKE(&cpi->common.rtcd.recon, build_comp_intra_predictors_mby)(&x->e_mbd);
+ }
+#endif
macro_block_yrd(x, &ratey, &distortion, IF_RTCD(&cpi->rtcd.encodemb));
+ // FIXME add compoundmode cost
+ // FIXME add rate for mode2
rate = ratey + x->mbmode_cost[x->e_mbd.frame_type]
[x->e_mbd.mode_info_context->mbmi.mode];
@@ -828,17 +1059,215 @@ static int rd_pick_intra16x16mby_mode(VP8_COMP *cpi,
if (this_rd < best_rd)
{
mode_selected = mode;
+#if CONFIG_COMP_INTRA_PRED
+ mode2_selected = mode2;
+#endif
best_rd = this_rd;
*Rate = rate;
*rate_y = ratey;
*Distortion = distortion;
}
+#if CONFIG_COMP_INTRA_PRED
+ }
+#endif
}
x->e_mbd.mode_info_context->mbmi.mode = mode_selected;
+#if CONFIG_COMP_INTRA_PRED
+ x->e_mbd.mode_info_context->mbmi.second_mode = mode2_selected;
+#endif
+ return best_rd;
+}
+static int rd_pick_intra8x8block(
+ VP8_COMP *cpi,
+ MACROBLOCK *x,
+ int ib,
+ B_PREDICTION_MODE *best_mode,
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE *best_second_mode,
+#endif
+ unsigned int *mode_costs,
+ ENTROPY_CONTEXT *a,
+ ENTROPY_CONTEXT *l,
+ int *bestrate,
+ int *bestratey,
+ int *bestdistortion)
+{
+ MB_PREDICTION_MODE mode;
+#if CONFIG_COMP_INTRA_PRED
+ MB_PREDICTION_MODE mode2;
+#endif
+ MACROBLOCKD *xd = &x->e_mbd;
+ int best_rd = INT_MAX;
+ int rate = 0;
+ int distortion;
+ BLOCK *be=x->block + ib;
+ BLOCKD *b=x->e_mbd.block + ib;
+ ENTROPY_CONTEXT ta0, ta1, besta0, besta1;
+ ENTROPY_CONTEXT tl0, tl1, bestl0, bestl1;
+
+
+ /*
+ * The predictor buffer is a 2d buffer with a stride of 16. Create
+ * a temp buffer that meets the stride requirements, but we are only
+ * interested in the left 8x8 block
+ * */
+
+ DECLARE_ALIGNED_ARRAY(16, unsigned char, best_predictor, 16*8);
+ DECLARE_ALIGNED_ARRAY(16, short, best_dqcoeff, 16*4);
+
+ for (mode = DC_PRED; mode <= TM_PRED; mode++)
+ {
+#if CONFIG_COMP_INTRA_PRED
+ for (mode2 = DC_PRED - 1; mode2 != TM_PRED + 1; mode2++)
+ {
+#endif
+ int this_rd;
+ int rate_t;
+
+ // FIXME rate for compound mode and second intrapred mode
+ rate = mode_costs[mode];
+
+#if CONFIG_COMP_INTRA_PRED
+ if (mode2 == (MB_PREDICTION_MODE) (DC_PRED - 1))
+ {
+#endif
+ RECON_INVOKE(&cpi->rtcd.common->recon, intra8x8_predict)
+ (b, mode, b->predictor);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ continue; // i.e. disable for now
+ RECON_INVOKE(&cpi->rtcd.common->recon, comp_intra8x8_predict)
+ (b, mode, mode2, b->predictor);
+ }
+#endif
+
+ vp8_subtract_4b_c(be, b, 16);
+
+ x->vp8_short_fdct8x4(be->src_diff, be->coeff, 32);
+ x->vp8_short_fdct8x4(be->src_diff + 64, be->coeff + 64, 32);
+
+ x->quantize_b_pair(x->block+ib, x->block+ib+1,
+ xd->block+ib, xd->block+ib+1);
+ x->quantize_b_pair(x->block+ib+4, x->block+ib+5,
+ xd->block+ib+4, xd->block+ib+5);
+
+ distortion = ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), berr)
+ ((x->block+ib)->coeff,(xd->block+ib)->dqcoeff)>>2;
+ distortion += ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), berr)
+ ((x->block+ib+1)->coeff,(xd->block+ib+1)->dqcoeff)>>2;
+ distortion += ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), berr)
+ ((x->block+ib+4)->coeff,(xd->block+ib+4)->dqcoeff)>>2;
+ distortion += ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), berr)
+ ((x->block+ib+5)->coeff,(xd->block+ib+5)->dqcoeff)>>2;
+
+ ta0 = *(a + vp8_block2above[ib]);
+ ta1 = *(a + vp8_block2above[ib+1]);
+ tl0 = *(l + vp8_block2above[ib]);
+ tl1 = *(l + vp8_block2above[ib+4]);
+ rate_t = cost_coeffs(x, xd->block+ib, PLANE_TYPE_Y_WITH_DC,
+ &ta0, &tl0);
+ rate_t += cost_coeffs(x, xd->block+ib+1, PLANE_TYPE_Y_WITH_DC,
+ &ta1, &tl0);
+ rate_t += cost_coeffs(x, xd->block+ib+4, PLANE_TYPE_Y_WITH_DC,
+ &ta0, &tl1);
+ rate_t += cost_coeffs(x, xd->block+ib+5, PLANE_TYPE_Y_WITH_DC,
+ &ta1, &tl1);
+ rate += rate_t;
+ this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+ if (this_rd < best_rd)
+ {
+ *bestrate = rate;
+ *bestratey = rate_t;
+ *bestdistortion = distortion;
+ besta0 = ta0;
+ besta1 = ta1;
+ bestl0 = tl0;
+ bestl1 = tl1;
+ best_rd = this_rd;
+ *best_mode = mode;
+#if CONFIG_COMP_INTRA_PRED
+ *best_second_mode = mode2;
+#endif
+ copy_predictor_8x8(best_predictor, b->predictor);
+ vpx_memcpy(best_dqcoeff, b->dqcoeff, 64);
+ vpx_memcpy(best_dqcoeff+32, b->dqcoeff+64, 64);
+#if CONFIG_COMP_INTRA_PRED
+ }
+#endif
+ }
+ }
+ b->bmi.as_mode.first = (*best_mode);
+#if CONFIG_COMP_INTRA_PRED
+ b->bmi.as_mode.second = (*best_second_mode);
+#endif
+ vp8_encode_intra8x8 (IF_RTCD(&cpi->rtcd), x, ib);
+ *(a + vp8_block2above[ib]) = besta0;
+ *(a + vp8_block2above[ib+1]) = besta1;
+ *(l + vp8_block2above[ib]) = bestl0;
+ *(l + vp8_block2above[ib+4]) = bestl1;
return best_rd;
}
+const int vp8_i8x8_block[4]={0, 2, 8, 10};
+int rd_pick_intra8x8mby_modes(VP8_COMP *cpi,
+ MACROBLOCK *mb,
+ int *Rate,
+ int *rate_y,
+ int *Distortion,
+ int best_rd)
+{
+ MACROBLOCKD *const xd = &mb->e_mbd;
+ int i,ib;
+ int cost = mb->mbmode_cost [xd->frame_type] [I8X8_PRED];
+ int distortion = 0;
+ int tot_rate_y = 0;
+ long long total_rd = 0;
+ ENTROPY_CONTEXT_PLANES t_above, t_left;
+ ENTROPY_CONTEXT *ta;
+ ENTROPY_CONTEXT *tl;
+ unsigned int *i8x8mode_costs;
+
+ vpx_memcpy(&t_above, mb->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, mb->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+
+ i8x8mode_costs = mb->i8x8_mode_costs;
+
+ for (i = 0; i < 4; i++)
+ {
+ MODE_INFO *const mic = xd->mode_info_context;
+ B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+#if CONFIG_COMP_INTRA_PRED
+ B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_second_mode);
+#endif
+ int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(ry), UNINITIALIZED_IS_SAFE(d);
+
+ ib = vp8_i8x8_block[i];
+ total_rd += rd_pick_intra8x8block(
+ cpi, mb, ib, &best_mode,
+#if CONFIG_COMP_INTRA_PRED
+ &best_second_mode,
+#endif
+ i8x8mode_costs, ta, tl, &r, &ry, &d);
+ cost += r;
+ distortion += d;
+ tot_rate_y += ry;
+ mic->bmi[ib].as_mode.first = best_mode;
+#if CONFIG_COMP_INTRA_PRED
+ mic->bmi[ib].as_mode.second = best_second_mode;
+#endif
+ }
+ *Rate = cost;
+ *rate_y += tot_rate_y;
+ *Distortion = distortion;
+ return RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
+}
+
static int rd_cost_mbuv(MACROBLOCK *mb)
{
int b;
@@ -865,7 +1294,6 @@ static int rd_cost_mbuv(MACROBLOCK *mb)
static int rd_inter16x16_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
int *distortion, int fullpixel)
{
- vp8_build_inter16x16_predictors_mbuv(&x->e_mbd);
ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), submbuv)(x->src_diff,
x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
@@ -878,6 +1306,47 @@ static int rd_inter16x16_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
}
+static int rd_cost_mbuv_8x8(MACROBLOCK *mb)
+{
+ int b;
+ int cost = 0;
+ MACROBLOCKD *x = &mb->e_mbd;
+ ENTROPY_CONTEXT_PLANES t_above, t_left;
+ ENTROPY_CONTEXT *ta;
+ ENTROPY_CONTEXT *tl;
+
+ vpx_memcpy(&t_above, mb->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, mb->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+
+ for (b = 16; b < 24; b+=4)
+ cost += cost_coeffs_8x8(mb, x->block + b, PLANE_TYPE_UV,
+ ta + vp8_block2above_8x8[b],
+ tl + vp8_block2left_8x8[b]);
+
+ return cost;
+}
+
+
+static int rd_inter16x16_uv_8x8(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
+ int *distortion, int fullpixel)
+{
+ ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), submbuv)(x->src_diff,
+ x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+
+ vp8_transform_mbuv_8x8(x);
+
+ vp8_quantize_mbuv_8x8(x);
+
+ *rate = rd_cost_mbuv_8x8(x);
+ *distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+
+ return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
+}
+
+
static int rd_inter4x4_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
int *distortion, int fullpixel)
{
@@ -894,23 +1363,50 @@ static int rd_inter4x4_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
}
-static void rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *rate_tokenonly, int *distortion)
+static void rd_pick_intra_mbuv_mode(VP8_COMP *cpi,
+ MACROBLOCK *x,
+ int *rate,
+ int *rate_tokenonly,
+ int *distortion)
{
MB_PREDICTION_MODE mode;
MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+#if CONFIG_COMP_INTRA_PRED
+ MB_PREDICTION_MODE mode2;
+ MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode2_selected);
+#endif
int best_rd = INT_MAX;
int UNINITIALIZED_IS_SAFE(d), UNINITIALIZED_IS_SAFE(r);
int rate_to;
for (mode = DC_PRED; mode <= TM_PRED; mode++)
{
+#if CONFIG_COMP_INTRA_PRED
+ for (mode2 = DC_PRED - 1; mode2 != TM_PRED + 1; mode2++)
+ {
+#endif
int rate;
int distortion;
int this_rd;
x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
+#if CONFIG_COMP_INTRA_PRED
+ x->e_mbd.mode_info_context->mbmi.second_uv_mode = mode2;
+ if (mode2 == (MB_PREDICTION_MODE) (DC_PRED - 1))
+ {
+#endif
RECON_INVOKE(&cpi->rtcd.common->recon, build_intra_predictors_mbuv)
(&x->e_mbd);
+#if CONFIG_COMP_INTRA_PRED
+ }
+ else
+ {
+ continue;
+ RECON_INVOKE(&cpi->rtcd.common->recon, build_comp_intra_predictors_mbuv)
+ (&x->e_mbd);
+ }
+#endif
+
ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), submbuv)(x->src_diff,
x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor,
x->src.uv_stride);
@@ -931,6 +1427,10 @@ static void rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int
r = rate;
*rate_tokenonly = rate_to;
mode_selected = mode;
+#if CONFIG_COMP_INTRA_PRED
+ mode2_selected = mode2;
+ }
+#endif
}
}
@@ -938,13 +1438,67 @@ static void rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int
*distortion = d;
x->e_mbd.mode_info_context->mbmi.uv_mode = mode_selected;
+#if CONFIG_COMP_INTRA_PRED
+ x->e_mbd.mode_info_context->mbmi.second_uv_mode = mode2_selected;
+#endif
+}
+
+static void rd_pick_intra_mbuv_mode_8x8(VP8_COMP *cpi,
+ MACROBLOCK *x,
+ int *rate,
+ int *rate_tokenonly,
+ int *distortion)
+{
+ MB_PREDICTION_MODE mode;
+ MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+ int best_rd = INT_MAX;
+ int UNINITIALIZED_IS_SAFE(d), UNINITIALIZED_IS_SAFE(r);
+ int rate_to;
+
+ for (mode = DC_PRED; mode <= TM_PRED; mode++)
+ {
+ int rate;
+ int distortion;
+ int this_rd;
+
+ x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
+ RECON_INVOKE(&cpi->rtcd.common->recon, build_intra_predictors_mbuv)
+ (&x->e_mbd);
+ ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), submbuv)(x->src_diff,
+ x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor,
+ x->src.uv_stride);
+ vp8_transform_mbuv_8x8(x);
+
+ vp8_quantize_mbuv_8x8(x);
+
+ rate_to = rd_cost_mbuv_8x8(x);
+ rate = rate_to + x->intra_uv_mode_cost[x->e_mbd.frame_type]
+ [x->e_mbd.mode_info_context->mbmi.uv_mode];
+
+ distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+ this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+ if (this_rd < best_rd)
+ {
+ best_rd = this_rd;
+ d = distortion;
+ r = rate;
+ *rate_tokenonly = rate_to;
+ mode_selected = mode;
+ }
+ }
+ *rate = r;
+ *distortion = d;
+ x->e_mbd.mode_info_context->mbmi.uv_mode = mode_selected;
}
-int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4])
+int vp8_cost_mv_ref(VP8_COMMON *pc,
+ MB_PREDICTION_MODE m,
+ const int near_mv_ref_ct[4])
{
vp8_prob p [VP8_MVREFS-1];
assert(NEARESTMV <= m && m <= SPLITMV);
- vp8_mv_ref_probs(p, near_mv_ref_ct);
+ vp8_mv_ref_probs(pc, p, near_mv_ref_ct);
return vp8_cost_token(vp8_mv_ref_tree, p,
vp8_mv_ref_encoding_array - NEARESTMV + m);
}
@@ -997,7 +1551,12 @@ static int labels2mode(
switch (m = this_mode)
{
case NEW4X4 :
+#if CONFIG_HIGH_PRECISION_MV
+ thismvcost = vp8_mv_bit_cost(this_mv, best_ref_mv, mvcost,
+ 102, xd->allow_high_precision_mv);
+#else
thismvcost = vp8_mv_bit_cost(this_mv, best_ref_mv, mvcost, 102);
+#endif
break;
case LEFT4X4:
this_mv->as_int = col ? d[-1].bmi.mv.as_int : left_block_mv(mic, i);
@@ -1084,7 +1643,6 @@ static unsigned int vp8_encode_inter_mb_segment(MACROBLOCK *x, int const *labels
}
-
static const unsigned int segmentation_to_sseshift[4] = {3, 3, 2, 0};
@@ -1161,7 +1719,7 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
// Segmentation method overheads
rate = vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + segmentation);
- rate += vp8_cost_mv_ref(SPLITMV, bsi->mdcounts);
+ rate += vp8_cost_mv_ref(&cpi->common, SPLITMV, bsi->mdcounts);
this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
br += rate;
@@ -1245,7 +1803,8 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
bestsme = cpi->diamond_search_sad(x, c, e, &mvp_full,
&mode_mv[NEW4X4], step_param,
sadpb, &num00, v_fn_ptr,
- x->mvcost, bsi->ref_mv);
+ XMVCOST,
+ bsi->ref_mv);
n = num00;
num00 = 0;
@@ -1262,7 +1821,8 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
&mvp_full, &temp_mv,
step_param + n, sadpb,
&num00, v_fn_ptr,
- x->mvcost, bsi->ref_mv);
+ XMVCOST,
+ bsi->ref_mv);
if (thissme < bestsme)
{
@@ -1283,7 +1843,7 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
thissme = cpi->full_search_sad(x, c, e, &mvp_full,
sadpb, 16, v_fn_ptr,
- x->mvcost, bsi->ref_mv);
+ XMVCOST, bsi->ref_mv);
if (thissme < bestsme)
{
@@ -1303,14 +1863,13 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
int distortion;
unsigned int sse;
cpi->find_fractional_mv_step(x, c, e, &mode_mv[NEW4X4],
- bsi->ref_mv, x->errorperbit, v_fn_ptr, x->mvcost,
+ bsi->ref_mv, x->errorperbit, v_fn_ptr, XMVCOST,
&distortion, &sse);
-
}
} /* NEW4X4 */
rate = labels2mode(x, labels, i, this_mode, &mode_mv[this_mode],
- bsi->ref_mv, x->mvcost);
+ bsi->ref_mv, XMVCOST);
// Trap vectors that reach beyond the UMV borders
if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
@@ -1344,15 +1903,17 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
vpx_memcpy(tl, tl_b, sizeof(ENTROPY_CONTEXT_PLANES));
labels2mode(x, labels, i, mode_selected, &mode_mv[mode_selected],
- bsi->ref_mv, x->mvcost);
+ bsi->ref_mv, XMVCOST);
br += sbr;
bd += sbd;
segmentyrate += bestlabelyrate;
this_segment_rd += best_label_rd;
- if (this_segment_rd >= bsi->segment_rd)
+ if (this_segment_rd >= bsi->segment_rd) {
break;
+ }
+
} /* for each label */
@@ -1427,6 +1988,7 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x,
rd_check_segment(cpi, x, &bsi, BLOCK_8X8);
+
if (bsi.segment_rd < best_rd)
{
int col_min = (best_ref_mv->as_mv.col>>3) - MAX_FULL_PEL_VAL + ((best_ref_mv->as_mv.col & 7)?1:0);
@@ -1528,6 +2090,7 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x,
return bsi.segment_rd;
}
+/* Order arr in increasing order, original position stored in idx */
static void insertsortmv(int arr[], int len)
{
int i, j, k;
@@ -1795,24 +2358,138 @@ static void rd_update_mvcount(VP8_COMP *cpi, MACROBLOCK *x, int_mv *best_ref_mv)
{
if (x->partition_info->bmi[i].mode == NEW4X4)
{
- cpi->MVcount[0][mv_max+((x->partition_info->bmi[i].mv.as_mv.row
- - best_ref_mv->as_mv.row) >> 1)]++;
- cpi->MVcount[1][mv_max+((x->partition_info->bmi[i].mv.as_mv.col
- - best_ref_mv->as_mv.col) >> 1)]++;
+#if CONFIG_HIGH_PRECISION_MV
+ if (x->e_mbd.allow_high_precision_mv)
+ {
+ cpi->MVcount_hp[0][mv_max_hp+(x->partition_info->bmi[i].mv.as_mv.row
+ - best_ref_mv->as_mv.row)]++;
+ cpi->MVcount_hp[1][mv_max_hp+(x->partition_info->bmi[i].mv.as_mv.col
+ - best_ref_mv->as_mv.col)]++;
+ }
+ else
+#endif
+ {
+ cpi->MVcount[0][mv_max+((x->partition_info->bmi[i].mv.as_mv.row
+ - best_ref_mv->as_mv.row) >> 1)]++;
+ cpi->MVcount[1][mv_max+((x->partition_info->bmi[i].mv.as_mv.col
+ - best_ref_mv->as_mv.col) >> 1)]++;
+ }
}
}
}
else if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV)
{
- cpi->MVcount[0][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row
- - best_ref_mv->as_mv.row) >> 1)]++;
- cpi->MVcount[1][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col
- - best_ref_mv->as_mv.col) >> 1)]++;
+#if CONFIG_HIGH_PRECISION_MV
+ if (x->e_mbd.allow_high_precision_mv)
+ {
+ cpi->MVcount_hp[0][mv_max_hp+(x->e_mbd.mode_info_context->mbmi.mv.as_mv.row
+ - best_ref_mv->as_mv.row)]++;
+ cpi->MVcount_hp[1][mv_max_hp+(x->e_mbd.mode_info_context->mbmi.mv.as_mv.col
+ - best_ref_mv->as_mv.col)]++;
+ }
+ else
+#endif
+ {
+ cpi->MVcount[0][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row
+ - best_ref_mv->as_mv.row) >> 1)]++;
+ cpi->MVcount[1][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col
+ - best_ref_mv->as_mv.col) >> 1)]++;
+ }
+ }
+}
+
+static void set_i8x8_block_modes(MACROBLOCK *x, int modes[2][4])
+{
+ int i;
+ MACROBLOCKD *xd = &x->e_mbd;
+ for(i=0;i<4;i++)
+ {
+ int ib = vp8_i8x8_block[i];
+ x->e_mbd.mode_info_context->bmi[ib+0].as_mode.first= modes[0][i];
+ x->e_mbd.mode_info_context->bmi[ib+1].as_mode.first= modes[0][i];
+ x->e_mbd.mode_info_context->bmi[ib+4].as_mode.first= modes[0][i];
+ x->e_mbd.mode_info_context->bmi[ib+5].as_mode.first= modes[0][i];
+#if CONFIG_COMP_INTRA_PRED
+ x->e_mbd.mode_info_context->bmi[ib+0].as_mode.second= modes[1][i];
+ x->e_mbd.mode_info_context->bmi[ib+1].as_mode.second= modes[1][i];
+ x->e_mbd.mode_info_context->bmi[ib+4].as_mode.second= modes[1][i];
+ x->e_mbd.mode_info_context->bmi[ib+5].as_mode.second= modes[1][i];
+#endif
+ //printf("%d,%d,%d,%d %d,%d,%d,%d\n",
+ // modes[0][0], modes[0][1], modes[0][2], modes[0][3],
+ // modes[1][0], modes[1][1], modes[1][2], modes[1][3]);
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ xd->block[i].bmi = xd->mode_info_context->bmi[i];
}
}
-void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra)
+void vp8_estimate_ref_frame_costs(VP8_COMP *cpi, unsigned int * ref_costs )
{
+ VP8_COMMON *cm = &cpi->common;
+ MACROBLOCKD *xd = &cpi->mb.e_mbd;
+ vp8_prob * mod_refprobs;
+
+ unsigned int cost;
+ int pred_ref ;
+ int pred_flag;
+ int i;
+
+ vp8_prob pred_prob;
+
+ // Get the predicted reference for this mb
+ pred_ref = get_pred_ref( cm, xd );
+
+ // Get the context probability for the prediction flag
+ pred_prob = get_pred_prob( cm, xd, PRED_REF );
+
+ // Get the set of probailities to use if prediction fails
+ mod_refprobs = cm->mod_refprobs[pred_ref];
+
+ // For each possible selected reference frame work out a cost.
+ // TODO: correct handling of costs if segment indicates only a subset of
+ // reference frames are allowed... though mostly this should come out
+ // in the wash.
+ for ( i = 0; i < MAX_REF_FRAMES; i++ )
+ {
+ pred_flag = (i == pred_ref);
+
+ // Get the prediction for the current mb
+ cost = vp8_cost_bit( pred_prob, pred_flag );
+
+ // for incorectly predicted cases
+ if ( ! pred_flag )
+ {
+ if ( mod_refprobs[0] )
+ cost += vp8_cost_bit( (i != INTRA_FRAME), mod_refprobs[0] );
+
+ // Inter coded
+ if (i != INTRA_FRAME)
+ {
+ if ( mod_refprobs[1] )
+ cost += vp8_cost_bit( (i != LAST_FRAME), mod_refprobs[1] );
+
+ if (i != LAST_FRAME)
+ {
+ if ( mod_refprobs[2] )
+ cost += vp8_cost_bit( (i != GOLDEN_FRAME),
+ mod_refprobs[2] );
+ }
+ }
+ }
+
+ ref_costs[i] = cost;
+ }
+}
+
+void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset,
+ int *returnrate, int *returndistortion, int *returnintra,
+ int *best_single_rd_diff, int *best_comp_rd_diff,
+ int *best_hybrid_rd_diff)
+{
+ VP8_COMMON *cm = &cpi->common;
BLOCK *b = &x->block[0];
BLOCKD *d = &x->e_mbd.block[0];
MACROBLOCKD *xd = &x->e_mbd;
@@ -1824,6 +2501,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
MB_PREDICTION_MODE this_mode;
int num00;
int best_mode_index = 0;
+ int mode8x8[2][4];
+ unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;
int i;
int mode_index;
@@ -1832,8 +2511,14 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int distortion;
int best_rd = INT_MAX;
int best_intra_rd = INT_MAX;
+ int best_comp_rd = INT_MAX;
+ int best_single_rd = INT_MAX;
+ int best_hybrid_rd = INT_MAX;
int rate2, distortion2;
int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
+ int uv_intra_skippable = 0;
+ int uv_intra_rate_8x8, uv_intra_distortion_8x8, uv_intra_rate_tokenonly_8x8;
+ int uv_intra_skippable_8x8=0;
int rate_y, UNINITIALIZED_IS_SAFE(rate_uv);
int distortion_uv;
int best_yrd = INT_MAX;
@@ -1844,6 +2529,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
//int intermodecost[MAX_MODES];
MB_PREDICTION_MODE uv_intra_mode;
+ MB_PREDICTION_MODE uv_intra_mode_8x8;
+
int_mv mvp;
int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
int saddone=0;
@@ -1852,55 +2539,63 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int_mv frame_nearest_mv[4];
int_mv frame_near_mv[4];
int_mv frame_best_ref_mv[4];
+ int_mv mc_search_result[4];
int frame_mdcounts[4][4];
- int frame_lf_or_gf[4];
unsigned char *y_buffer[4];
unsigned char *u_buffer[4];
unsigned char *v_buffer[4];
+ unsigned int ref_costs[MAX_REF_FRAMES];
+
vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
vpx_memset(&best_bmodes, 0, sizeof(best_bmodes));
+ for (i = 0; i < 4; i++)
+ {
+#define INVALID_MV 0x80008000
+ mc_search_result[i].as_int = INVALID_MV;
+ }
+
if (cpi->ref_frame_flags & VP8_LAST_FLAG)
{
YV12_BUFFER_CONFIG *lst_yv12 = &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &frame_nearest_mv[LAST_FRAME], &frame_near_mv[LAST_FRAME],
- &frame_best_ref_mv[LAST_FRAME], frame_mdcounts[LAST_FRAME], LAST_FRAME, cpi->common.ref_frame_sign_bias);
+ vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context,
+ x->e_mbd.prev_mode_info_context,
+ &frame_nearest_mv[LAST_FRAME], &frame_near_mv[LAST_FRAME],
+ &frame_best_ref_mv[LAST_FRAME], frame_mdcounts[LAST_FRAME], LAST_FRAME, cpi->common.ref_frame_sign_bias);
y_buffer[LAST_FRAME] = lst_yv12->y_buffer + recon_yoffset;
u_buffer[LAST_FRAME] = lst_yv12->u_buffer + recon_uvoffset;
v_buffer[LAST_FRAME] = lst_yv12->v_buffer + recon_uvoffset;
-
- frame_lf_or_gf[LAST_FRAME] = 0;
}
if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
{
YV12_BUFFER_CONFIG *gld_yv12 = &cpi->common.yv12_fb[cpi->common.gld_fb_idx];
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &frame_nearest_mv[GOLDEN_FRAME], &frame_near_mv[GOLDEN_FRAME],
- &frame_best_ref_mv[GOLDEN_FRAME], frame_mdcounts[GOLDEN_FRAME], GOLDEN_FRAME, cpi->common.ref_frame_sign_bias);
+ vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context,
+ x->e_mbd.prev_mode_info_context,
+ &frame_nearest_mv[GOLDEN_FRAME], &frame_near_mv[GOLDEN_FRAME],
+ &frame_best_ref_mv[GOLDEN_FRAME], frame_mdcounts[GOLDEN_FRAME], GOLDEN_FRAME, cpi->common.ref_frame_sign_bias);
y_buffer[GOLDEN_FRAME] = gld_yv12->y_buffer + recon_yoffset;
u_buffer[GOLDEN_FRAME] = gld_yv12->u_buffer + recon_uvoffset;
v_buffer[GOLDEN_FRAME] = gld_yv12->v_buffer + recon_uvoffset;
-
- frame_lf_or_gf[GOLDEN_FRAME] = 1;
}
if (cpi->ref_frame_flags & VP8_ALT_FLAG)
{
YV12_BUFFER_CONFIG *alt_yv12 = &cpi->common.yv12_fb[cpi->common.alt_fb_idx];
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &frame_nearest_mv[ALTREF_FRAME], &frame_near_mv[ALTREF_FRAME],
+ vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context,
+ x->e_mbd.prev_mode_info_context,
+ &frame_nearest_mv[ALTREF_FRAME], &frame_near_mv[ALTREF_FRAME],
&frame_best_ref_mv[ALTREF_FRAME], frame_mdcounts[ALTREF_FRAME], ALTREF_FRAME, cpi->common.ref_frame_sign_bias);
y_buffer[ALTREF_FRAME] = alt_yv12->y_buffer + recon_yoffset;
u_buffer[ALTREF_FRAME] = alt_yv12->u_buffer + recon_uvoffset;
v_buffer[ALTREF_FRAME] = alt_yv12->v_buffer + recon_uvoffset;
-
- frame_lf_or_gf[ALTREF_FRAME] = 1;
}
*returnintra = INT_MAX;
@@ -1911,22 +2606,37 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
vpx_memset(mode_mv, 0, sizeof(mode_mv));
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
- rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate, &uv_intra_rate_tokenonly, &uv_intra_distortion);
+
+ /* Initialize zbin mode boost for uv costing */
+ cpi->zbin_mode_boost = 0;
+ vp8_update_zbin_extra(cpi, x);
+
+ rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate,
+ &uv_intra_rate_tokenonly, &uv_intra_distortion);
uv_intra_mode = x->e_mbd.mode_info_context->mbmi.uv_mode;
+ uv_intra_skippable = mbuv_is_skippable(&x->e_mbd);
+
+ /* rough estimate for now */
+ if(cpi->common.txfm_mode==ALLOW_8X8)
+ {
+ rd_pick_intra_mbuv_mode_8x8(cpi, x, &uv_intra_rate_8x8,
+ &uv_intra_rate_tokenonly_8x8,
+ &uv_intra_distortion_8x8);
+ uv_intra_mode_8x8 = x->e_mbd.mode_info_context->mbmi.uv_mode;
+ uv_intra_skippable_8x8 = mbuv_is_skippable_8x8(&x->e_mbd);
+ }
+
+ // Get estimates of reference frame costs for each reference frame
+ // that depend on the current prediction etc.
+ vp8_estimate_ref_frame_costs( cpi, ref_costs );
for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
{
int this_rd = INT_MAX;
- int lf_or_gf = 0; // Lat Frame (01) or gf/arf (1)
int disable_skip = 0;
int other_cost = 0;
-
- // Experimental debug code.
- // Record of rd values recorded for this MB. -1 indicates not measured
- //all_rds[mode_index] = -1;
- //all_rates[mode_index] = -1;
- //all_dist[mode_index] = -1;
- //intermodecost[mode_index] = -1;
+ int compmode_cost = 0;
+ int mode_excluded = 0;
// Test best rd so far against threshold for trying this mode.
if (best_rd <= cpi->rd_threshes[mode_index])
@@ -1939,16 +2649,46 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
this_mode = vp8_mode_order[mode_index];
x->e_mbd.mode_info_context->mbmi.mode = this_mode;
+#if CONFIG_COMP_INTRA_PRED
+ x->e_mbd.mode_info_context->mbmi.second_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+ x->e_mbd.mode_info_context->mbmi.second_uv_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
+#endif
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.ref_frame = vp8_ref_frame_order[mode_index];
+ x->e_mbd.mode_info_context->mbmi.second_ref_frame = vp8_second_ref_frame_order[mode_index];
- // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
- // unless ARNR filtering is enabled in which case we want
- // an unfiltered alternative
- if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
+ // If the segment reference frame feature is enabled....
+ // then do nothing if the current ref frame is not allowed..
+ if ( segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ) &&
+ !check_segref( xd, segment_id,
+ xd->mode_info_context->mbmi.ref_frame ) )
{
- if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
- continue;
+ continue;
+ }
+ // If the segment mode feature is enabled....
+ // then do nothing if the current mode is not allowed..
+ else if ( segfeature_active( xd, segment_id, SEG_LVL_MODE ) &&
+ ( this_mode !=
+ get_segdata( xd, segment_id, SEG_LVL_MODE ) ) )
+ {
+ continue;
+ }
+
+ // Disable this drop out case if either the mode or ref frame
+ // segment level feature is enabled for this segment. This is to
+ // prevent the possibility that the we end up unable to pick any mode.
+ else if ( !segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ) &&
+ !segfeature_active( xd, segment_id, SEG_LVL_MODE ) )
+ {
+ // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
+ // unless ARNR filtering is enabled in which case we want
+ // an unfiltered alternative
+ if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
+ {
+ if (this_mode != ZEROMV ||
+ x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
+ continue;
+ }
}
/* everything but intra */
@@ -1961,31 +2701,10 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
mode_mv[NEARMV] = frame_near_mv[x->e_mbd.mode_info_context->mbmi.ref_frame];
best_ref_mv = frame_best_ref_mv[x->e_mbd.mode_info_context->mbmi.ref_frame];
vpx_memcpy(mdcounts, frame_mdcounts[x->e_mbd.mode_info_context->mbmi.ref_frame], sizeof(mdcounts));
- lf_or_gf = frame_lf_or_gf[x->e_mbd.mode_info_context->mbmi.ref_frame];
- }
-
- // Check to see if the testing frequency for this mode is at its max
- // If so then prevent it from being tested and increase the threshold for its testing
- if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
- {
- if (cpi->mbs_tested_so_far <= cpi->mode_check_freq[mode_index] * cpi->mode_test_hit_counts[mode_index])
- {
- // Increase the threshold for coding this mode to make it less likely to be chosen
- cpi->rd_thresh_mult[mode_index] += 4;
-
- if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
- cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
-
- cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
-
- continue;
- }
}
- // We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
- cpi->mode_test_hit_counts[mode_index] ++;
-
- // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
+ // Experimental code. Special case for gf and arf zeromv modes.
+ // Increase zbin size to suppress noise
if (cpi->zbin_mode_boost_enabled)
{
if ( vp8_ref_frame_order[mode_index] == INTRA_FRAME )
@@ -2008,6 +2727,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
vp8_update_zbin_extra(cpi, x);
}
+
+ if (!x->e_mbd.mode_info_context->mbmi.second_ref_frame)
switch (this_mode)
{
case B_PRED:
@@ -2015,7 +2736,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int tmp_rd;
// Note the rate value returned here includes the cost of coding the BPRED mode : x->mbmode_cost[x->e_mbd.frame_type][BPRED];
- tmp_rd = rd_pick_intra4x4mby_modes(cpi, x, &rate, &rate_y, &distortion, best_yrd);
+ tmp_rd = rd_pick_intra4x4mby_modes(cpi, x, &rate, &rate_y, &distortion, best_yrd, 0);
rate2 += rate;
distortion2 += distortion;
@@ -2033,6 +2754,41 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
}
}
break;
+ case I8X8_PRED:
+ {
+ int tmp_rd;
+ tmp_rd = rd_pick_intra8x8mby_modes(cpi,
+ x, &rate, &rate_y, &distortion, best_yrd);
+ rate2 += rate;
+ distortion2 += distortion;
+
+ mode8x8[0][0]= x->e_mbd.mode_info_context->bmi[0].as_mode.first;
+ mode8x8[0][1]= x->e_mbd.mode_info_context->bmi[2].as_mode.first;
+ mode8x8[0][2]= x->e_mbd.mode_info_context->bmi[8].as_mode.first;
+ mode8x8[0][3]= x->e_mbd.mode_info_context->bmi[10].as_mode.first;
+#if CONFIG_COMP_INTRA_PRED
+ mode8x8[1][0]= x->e_mbd.mode_info_context->bmi[0].as_mode.second;
+ mode8x8[1][1]= x->e_mbd.mode_info_context->bmi[2].as_mode.second;
+ mode8x8[1][2]= x->e_mbd.mode_info_context->bmi[8].as_mode.second;
+ mode8x8[1][3]= x->e_mbd.mode_info_context->bmi[10].as_mode.second;
+#endif
+
+ /* TODO: uv rate maybe over-estimated here since there is UV intra
+ mode coded in I8X8_PRED prediction */
+ if(tmp_rd < best_yrd)
+ {
+ rate2 += uv_intra_rate;
+ rate_uv = uv_intra_rate_tokenonly;
+ distortion2 += uv_intra_distortion;
+ distortion_uv = uv_intra_distortion;
+ }
+ else
+ {
+ this_rd = INT_MAX;
+ disable_skip = 1;
+ }
+ }
+ break;
case SPLITMV:
{
@@ -2069,16 +2825,32 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
case H_PRED:
case TM_PRED:
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+ // FIXME compound intra prediction
RECON_INVOKE(&cpi->common.rtcd.recon, build_intra_predictors_mby)
(&x->e_mbd);
- macro_block_yrd(x, &rate_y, &distortion, IF_RTCD(&cpi->rtcd.encodemb)) ;
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ macro_block_yrd_8x8(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd)) ;
+ else
+ macro_block_yrd(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd.encodemb)) ;
rate2 += rate_y;
distortion2 += distortion;
rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.mode];
- rate2 += uv_intra_rate;
- rate_uv = uv_intra_rate_tokenonly;
- distortion2 += uv_intra_distortion;
- distortion_uv = uv_intra_distortion;
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ {
+ rate2 += uv_intra_rate_8x8;
+ rate_uv = uv_intra_rate_tokenonly_8x8;
+ distortion2 += uv_intra_distortion_8x8;
+ distortion_uv = uv_intra_distortion_8x8;
+ }
+ else
+ {
+ rate2 += uv_intra_rate;
+ rate_uv = uv_intra_rate_tokenonly;
+ distortion2 += uv_intra_distortion;
+ distortion_uv = uv_intra_distortion;
+ }
break;
case NEWMV:
@@ -2135,7 +2907,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
bestsme = cpi->diamond_search_sad(x, b, d, &mvp_full, &d->bmi.mv,
step_param, sadpb, &num00,
&cpi->fn_ptr[BLOCK_16X16],
- x->mvcost, &best_ref_mv);
+ XMVCOST, &best_ref_mv);
mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
// Further step/diamond searches as necessary
@@ -2159,8 +2931,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
{
thissme = cpi->diamond_search_sad(x, b, d, &mvp_full,
&d->bmi.mv, step_param + n, sadpb, &num00,
- &cpi->fn_ptr[BLOCK_16X16], x->mvcost,
- &best_ref_mv);
+ &cpi->fn_ptr[BLOCK_16X16],
+ XMVCOST, &best_ref_mv);
/* check to see if refining search is needed. */
if (num00 > (further_steps-n))
@@ -2191,7 +2963,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
//thissme = cpi->full_search_sad(x, b, d, &d->bmi.mv.as_mv, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, &best_ref_mv);
thissme = cpi->refining_search_sad(x, b, d, &d->bmi.mv, sadpb,
search_range, &cpi->fn_ptr[BLOCK_16X16],
- x->mvcost, &best_ref_mv);
+ XMVCOST, &best_ref_mv);
if (thissme < bestsme)
{
@@ -2216,13 +2988,21 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv, &best_ref_mv,
x->errorperbit,
&cpi->fn_ptr[BLOCK_16X16],
- x->mvcost, &dis, &sse);
+ XMVCOST, &dis, &sse);
}
+ mc_search_result[x->e_mbd.mode_info_context->mbmi.ref_frame].as_int = d->bmi.mv.as_int;
mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
// Add the new motion vector cost to our rolling cost variable
- rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv, x->mvcost, 96);
+#if CONFIG_HIGH_PRECISION_MV
+ rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv,
+ XMVCOST, 96,
+ x->e_mbd.allow_high_precision_mv);
+#else
+ rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv,
+ XMVCOST, 96);
+#endif
}
case NEARESTMV:
@@ -2246,6 +3026,9 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
vp8_build_inter16x16_predictors_mby(&x->e_mbd);
+ compmode_cost =
+ vp8_cost_bit( get_pred_prob( cm, xd, PRED_COMP ), 0 );
+
if (cpi->active_map_enabled && x->active_ptr[0] == 0) {
x->skip = 1;
}
@@ -2291,58 +3074,199 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
}
}
}
-
-
//intermodecost[mode_index] = vp8_cost_mv_ref(this_mode, mdcounts); // Experimental debug code
// Add in the Mv/mode cost
- rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+ rate2 += vp8_cost_mv_ref(&cpi->common, this_mode, mdcounts);
// Y cost and distortion
- macro_block_yrd(x, &rate_y, &distortion, IF_RTCD(&cpi->rtcd.encodemb));
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ macro_block_yrd_8x8(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd));
+ else
+ macro_block_yrd(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd.encodemb));
+
rate2 += rate_y;
distortion2 += distortion;
// UV cost and distortion
- rd_inter16x16_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel);
+ vp8_build_inter16x16_predictors_mbuv(&x->e_mbd);
+
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ rd_inter16x16_uv_8x8(cpi, x, &rate_uv,
+ &distortion_uv,
+ cpi->common.full_pixel);
+ else
+ rd_inter16x16_uv(cpi, x, &rate_uv,
+ &distortion_uv,
+ cpi->common.full_pixel);
rate2 += rate_uv;
distortion2 += distortion_uv;
+ mode_excluded = cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY;
break;
default:
break;
}
+ else /* x->e_mbd.mode_info_context->mbmi.second_ref_frame != 0 */
+ {
+ int ref1 = x->e_mbd.mode_info_context->mbmi.ref_frame;
+ int ref2 = x->e_mbd.mode_info_context->mbmi.second_ref_frame;
+
+ mode_excluded = cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY;
+ switch (this_mode)
+ {
+ case NEWMV:
+ if (mc_search_result[ref1].as_int == INVALID_MV ||
+ mc_search_result[ref2].as_int == INVALID_MV)
+ continue;
+ x->e_mbd.mode_info_context->mbmi.mv.as_int = mc_search_result[ref1].as_int;
+ x->e_mbd.mode_info_context->mbmi.second_mv.as_int = mc_search_result[ref2].as_int;
+#if CONFIG_HIGH_PRECISION_MV
+ rate2 += vp8_mv_bit_cost(&mc_search_result[ref1],
+ &frame_best_ref_mv[ref1],
+ XMVCOST, 96,
+ x->e_mbd.allow_high_precision_mv);
+ rate2 += vp8_mv_bit_cost(&mc_search_result[ref2],
+ &frame_best_ref_mv[ref2],
+ XMVCOST, 96,
+ x->e_mbd.allow_high_precision_mv);
+#else
+ rate2 += vp8_mv_bit_cost(&mc_search_result[ref1],
+ &frame_best_ref_mv[ref1],
+ XMVCOST, 96);
+ rate2 += vp8_mv_bit_cost(&mc_search_result[ref2],
+ &frame_best_ref_mv[ref2],
+ XMVCOST, 96);
+#endif
+ break;
+ case ZEROMV:
+ x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+ x->e_mbd.mode_info_context->mbmi.second_mv.as_int = 0;
+ break;
+ case NEARMV:
+ if (frame_near_mv[ref1].as_int == 0 || frame_near_mv[ref2].as_int == 0)
+ continue;
+ x->e_mbd.mode_info_context->mbmi.mv.as_int = frame_near_mv[ref1].as_int;
+ x->e_mbd.mode_info_context->mbmi.second_mv.as_int = frame_near_mv[ref2].as_int;
+ break;
+ case NEARESTMV:
+ if (frame_nearest_mv[ref1].as_int == 0 || frame_nearest_mv[ref2].as_int == 0)
+ continue;
+ x->e_mbd.mode_info_context->mbmi.mv.as_int = frame_nearest_mv[ref1].as_int;
+ x->e_mbd.mode_info_context->mbmi.second_mv.as_int = frame_nearest_mv[ref2].as_int;
+ break;
+ default:
+ break;
+ }
+
+ /* Add in the Mv/mode cost */
+ rate2 += vp8_cost_mv_ref(&cpi->common,this_mode, mdcounts);
+
+ vp8_clamp_mv2(&x->e_mbd.mode_info_context->mbmi.mv, xd);
+ vp8_clamp_mv2(&x->e_mbd.mode_info_context->mbmi.second_mv, xd);
+ if (((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row >> 3) < x->mv_row_min) ||
+ ((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row >> 3) > x->mv_row_max) ||
+ ((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col >> 3) < x->mv_col_min) ||
+ ((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col >> 3) > x->mv_col_max) ||
+ ((x->e_mbd.mode_info_context->mbmi.second_mv.as_mv.row >> 3) < x->mv_row_min) ||
+ ((x->e_mbd.mode_info_context->mbmi.second_mv.as_mv.row >> 3) > x->mv_row_max) ||
+ ((x->e_mbd.mode_info_context->mbmi.second_mv.as_mv.col >> 3) < x->mv_col_min) ||
+ ((x->e_mbd.mode_info_context->mbmi.second_mv.as_mv.col >> 3) > x->mv_col_max))
+ continue;
+
+ /* build first and second prediction */
+ vp8_build_inter16x16_predictors_mby(&x->e_mbd);
+ vp8_build_inter16x16_predictors_mbuv(&x->e_mbd);
+ /* do second round and average the results */
+ x->e_mbd.second_pre.y_buffer = y_buffer[ref2];
+ x->e_mbd.second_pre.u_buffer = u_buffer[ref2];
+ x->e_mbd.second_pre.v_buffer = v_buffer[ref2];
+ vp8_build_2nd_inter16x16_predictors_mb(&x->e_mbd, x->e_mbd.predictor,
+ &x->e_mbd.predictor[256],
+ &x->e_mbd.predictor[320], 16, 8);
+
+ /* Y cost and distortion */
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ macro_block_yrd_8x8(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd));
+ else
+ macro_block_yrd(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd.encodemb));
+
+ rate2 += rate_y;
+ distortion2 += distortion;
+
+ /* UV cost and distortion */
+ if(cpi->common.txfm_mode == ALLOW_8X8)
+ rd_inter16x16_uv_8x8(cpi, x, &rate_uv,
+ &distortion_uv,
+ cpi->common.full_pixel);
+ else
+ rd_inter16x16_uv(cpi, x, &rate_uv,
+ &distortion_uv,
+ cpi->common.full_pixel);
+ rate2 += rate_uv;
+ distortion2 += distortion_uv;
+
+ /* don't bother w/ skip, we would never have come here if skip were enabled */
+ x->e_mbd.mode_info_context->mbmi.mode = this_mode;
+
+ /* We don't include the cost of the second reference here, because there are only
+ * three options: Last/Golden, ARF/Last or Golden/ARF, or in other words if you
+ * present them in that order, the second one is always known if the first is known */
+ compmode_cost =
+ vp8_cost_bit( get_pred_prob( cm, xd, PRED_COMP ), 1 );
+ }
// Where skip is allowable add in the default per mb cost for the no skip case.
// where we then decide to skip we have to delete this and replace it with the
// cost of signallying a skip
if (cpi->common.mb_no_coeff_skip)
{
- other_cost += vp8_cost_bit(cpi->prob_skip_false, 0);
- rate2 += other_cost;
+ int prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 0);
+ other_cost += prob_skip_cost;
+ rate2 += prob_skip_cost;
+ }
+
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
+ {
+ rate2 += compmode_cost;
}
- /* Estimate the reference frame signaling cost and add it
- * to the rolling cost variable.
- */
- rate2 +=
- x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+
+ // Estimate the reference frame signaling cost and add it
+ // to the rolling cost variable.
+ rate2 += ref_costs[x->e_mbd.mode_info_context->mbmi.ref_frame];
if (!disable_skip)
{
// Test for the condition where skip block will be activated because there are no non zero coefficients and make any necessary adjustment for rate
if (cpi->common.mb_no_coeff_skip)
{
- int tteob;
-
- tteob = 0;
-
- for (i = 0; i <= 24; i++)
+ int mb_skippable;
+ int has_y2 = ( this_mode!=SPLITMV
+ &&this_mode!=B_PRED
+ &&this_mode!=I8X8_PRED);
+ if((cpi->common.txfm_mode == ALLOW_8X8) && has_y2)
+ {
+ if(x->e_mbd.mode_info_context->mbmi.ref_frame!=INTRA_FRAME)
+ mb_skippable = mb_is_skippable_8x8(&x->e_mbd);
+ else
+ mb_skippable = uv_intra_skippable_8x8
+ & mby_is_skippable_8x8(&x->e_mbd);
+ }
+ else
{
- tteob += x->e_mbd.block[i].eob;
+ if(x->e_mbd.mode_info_context->mbmi.ref_frame!=INTRA_FRAME)
+ mb_skippable = mb_is_skippable(&x->e_mbd, has_y2);
+ else
+ mb_skippable = uv_intra_skippable
+ & mby_is_skippable(&x->e_mbd, has_y2);
}
- if (tteob == 0)
+ if (mb_skippable)
{
rate2 -= (rate_y + rate_uv);
//for best_yrd calculation
@@ -2377,38 +3301,57 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
*returnintra = distortion2 ;
}
+ if (!disable_skip &&
+ (this_mode == SPLITMV || x->e_mbd.mode_info_context->mbmi.ref_frame == INTRA_FRAME))
+ {
+ if (this_rd < best_comp_rd)
+ best_comp_rd = this_rd;
+ if (this_rd < best_single_rd)
+ best_single_rd = this_rd;
+ if (this_rd < best_hybrid_rd)
+ best_hybrid_rd = this_rd;
+ }
+
// Did this mode help.. i.i is it the new best mode
if (this_rd < best_rd || x->skip)
{
- // Note index of best mode so far
- best_mode_index = mode_index;
-
- if (this_mode <= B_PRED)
+ if (!mode_excluded)
{
- x->e_mbd.mode_info_context->mbmi.uv_mode = uv_intra_mode;
- /* required for left and above block mv */
- x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
- }
+ // Note index of best mode so far
+ best_mode_index = mode_index;
- other_cost +=
- x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+ if (this_mode <= B_PRED)
+ {
+ if( cpi->common.txfm_mode == ALLOW_8X8
+ && this_mode != B_PRED
+ && this_mode != I8X8_PRED)
+ x->e_mbd.mode_info_context->mbmi.uv_mode = uv_intra_mode_8x8;
+ else
+ x->e_mbd.mode_info_context->mbmi.uv_mode = uv_intra_mode;
+ /* required for left and above block mv */
+ x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+ }
- /* Calculate the final y RD estimate for this mode */
- best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),
- (distortion2-distortion_uv));
+ other_cost += ref_costs[x->e_mbd.mode_info_context->mbmi.ref_frame];
- *returnrate = rate2;
- *returndistortion = distortion2;
- best_rd = this_rd;
- vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi, sizeof(MB_MODE_INFO));
- vpx_memcpy(&best_partition, x->partition_info, sizeof(PARTITION_INFO));
+ /* Calculate the final y RD estimate for this mode */
+ best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),
+ (distortion2-distortion_uv));
- if ((this_mode == B_PRED) || (this_mode == SPLITMV))
- for (i = 0; i < 16; i++)
- {
- best_bmodes[i] = x->e_mbd.block[i].bmi;
- }
+ *returnrate = rate2;
+ *returndistortion = distortion2;
+ best_rd = this_rd;
+ vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi, sizeof(MB_MODE_INFO));
+ vpx_memcpy(&best_partition, x->partition_info, sizeof(PARTITION_INFO));
+ if ((this_mode == B_PRED)
+ ||(this_mode == I8X8_PRED)
+ || (this_mode == SPLITMV))
+ for (i = 0; i < 16; i++)
+ {
+ best_bmodes[i] = x->e_mbd.block[i].bmi;
+ }
+ }
// Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
@@ -2426,6 +3369,43 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
}
+ /* keep record of best compound/single-only prediction */
+ if (!disable_skip &&
+ x->e_mbd.mode_info_context->mbmi.ref_frame != INTRA_FRAME &&
+ this_mode != SPLITMV)
+ {
+ int single_rd, hybrid_rd, single_rate, hybrid_rate;
+
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION)
+ {
+ single_rate = rate2 - compmode_cost;
+ hybrid_rate = rate2;
+ }
+ else
+ {
+ single_rate = rate2;
+ hybrid_rate = rate2 + compmode_cost;
+ }
+
+ single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
+ hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
+
+ if (x->e_mbd.mode_info_context->mbmi.second_ref_frame == INTRA_FRAME &&
+ single_rd < best_single_rd)
+ {
+ best_single_rd = single_rd;
+ }
+ else if (x->e_mbd.mode_info_context->mbmi.second_ref_frame != INTRA_FRAME &&
+ single_rd < best_comp_rd)
+ {
+ best_comp_rd = single_rd;
+ }
+ if (hybrid_rd < best_hybrid_rd)
+ {
+ best_hybrid_rd = hybrid_rd;
+ }
+ }
+
if (x->skip)
break;
@@ -2460,8 +3440,14 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
// Note how often each mode chosen as best
cpi->mode_chosen_counts[best_mode_index] ++;
-
- if (cpi->is_src_frame_alt_ref &&
+ // This code force Altref,0,0 and skip for the frame that overlays a
+ // an alrtef unless Altref is filtered. However, this is unsafe if
+ // segment level coding of ref frame or mode is enabled for this
+ // segment.
+ if (!segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ) &&
+ !segfeature_active( xd, segment_id, SEG_LVL_MODE ) &&
+ cpi->is_src_frame_alt_ref &&
+ (cpi->oxcf.arnr_max_frames == 0) &&
(best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
{
x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
@@ -2472,6 +3458,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
(cpi->common.mb_no_coeff_skip) ? 1 : 0;
x->e_mbd.mode_info_context->mbmi.partitioning = 0;
+ *best_single_rd_diff = *best_comp_rd_diff = *best_hybrid_rd_diff = 0;
+
return;
}
@@ -2482,7 +3470,15 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
if (best_mbmode.mode == B_PRED)
{
for (i = 0; i < 16; i++)
+ {
xd->mode_info_context->bmi[i].as_mode = best_bmodes[i].as_mode;
+ xd->block[i].bmi.as_mode = xd->mode_info_context->bmi[i].as_mode;
+ }
+ }
+
+ if (best_mbmode.mode == I8X8_PRED)
+ {
+ set_i8x8_block_modes(x, mode8x8);
}
if (best_mbmode.mode == SPLITMV)
@@ -2498,19 +3494,34 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
rd_update_mvcount(cpi, x, &frame_best_ref_mv[xd->mode_info_context->mbmi.ref_frame]);
-
-
+ if (best_single_rd == INT_MAX)
+ *best_single_rd_diff = INT_MIN;
+ else
+ *best_single_rd_diff = best_rd - best_single_rd;
+ if (best_comp_rd == INT_MAX)
+ *best_comp_rd_diff = INT_MIN;
+ else
+ *best_comp_rd_diff = best_rd - best_comp_rd;
+ if (best_hybrid_rd == INT_MAX)
+ *best_hybrid_rd_diff = INT_MIN;
+ else
+ *best_hybrid_rd_diff = best_rd - best_hybrid_rd;
}
void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate_)
{
- int error4x4, error16x16;
- int rate4x4, rate16x16 = 0, rateuv;
- int dist4x4, dist16x16, distuv;
+ MACROBLOCKD *xd = &x->e_mbd;
+ int error4x4, error16x16, error4x4d;
+ int rate4x4, rate16x16 = 0, rateuv, rate4x4d;
+ int dist4x4, dist16x16, distuv, dist4x4d;
int rate;
int rate4x4_tokenonly = 0;
int rate16x16_tokenonly = 0;
int rateuv_tokenonly = 0;
+ int error8x8, rate8x8_tokenonly=0;
+ int rate8x8, dist8x8;
+ int mode16x16;
+ int mode8x8[2][4];
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
@@ -2520,20 +3531,65 @@ void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate_)
error16x16 = rd_pick_intra16x16mby_mode(cpi, x,
&rate16x16, &rate16x16_tokenonly,
&dist16x16);
+ mode16x16 = x->e_mbd.mode_info_context->mbmi.mode;
+
+ error8x8 = rd_pick_intra8x8mby_modes(cpi, x,
+ &rate8x8, &rate8x8_tokenonly,
+ &dist8x8, error16x16);
+ mode8x8[0][0]= x->e_mbd.mode_info_context->bmi[0].as_mode.first;
+ mode8x8[0][1]= x->e_mbd.mode_info_context->bmi[2].as_mode.first;
+ mode8x8[0][2]= x->e_mbd.mode_info_context->bmi[8].as_mode.first;
+ mode8x8[0][3]= x->e_mbd.mode_info_context->bmi[10].as_mode.first;
+#if CONFIG_COMP_INTRA_PRED
+ mode8x8[1][0]= x->e_mbd.mode_info_context->bmi[0].as_mode.second;
+ mode8x8[1][1]= x->e_mbd.mode_info_context->bmi[2].as_mode.second;
+ mode8x8[1][2]= x->e_mbd.mode_info_context->bmi[8].as_mode.second;
+ mode8x8[1][3]= x->e_mbd.mode_info_context->bmi[10].as_mode.second;
+#endif
error4x4 = rd_pick_intra4x4mby_modes(cpi, x,
&rate4x4, &rate4x4_tokenonly,
- &dist4x4, error16x16);
+ &dist4x4, error16x16, 0);
+ error4x4d = rd_pick_intra4x4mby_modes(cpi, x,
+ &rate4x4d, &rate4x4_tokenonly,
+ &dist4x4d, error16x16, 1);
- if (error4x4 < error16x16)
+ if(error8x8> error16x16)
{
- x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
- rate += rate4x4;
+ if (error4x4 < error16x16)
+ {
+ rate += (error4x4d < error4x4) ? rate4x4d : rate4x4;
+ if (error4x4d >= error4x4) // FIXME save original modes etc.
+ error4x4 = rd_pick_intra4x4mby_modes(cpi, x, &rate4x4,
+ &rate4x4_tokenonly,
+ &dist4x4, error16x16, 0);
+ x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
+ }
+ else
+ {
+ x->e_mbd.mode_info_context->mbmi.mode = mode16x16;
+ rate += rate16x16;
+
+ }
}
else
{
- rate += rate16x16;
- }
+ if (error4x4 < error8x8)
+ {
+ rate += (error4x4d < error4x4) ? rate4x4d : rate4x4;
+ if (error4x4d >= error4x4) // FIXME save original modes etc.
+ error4x4 = rd_pick_intra4x4mby_modes(cpi, x, &rate4x4,
+ &rate4x4_tokenonly,
+ &dist4x4, error16x16, 0);
+ x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
+ }
+ else
+ {
+ x->e_mbd.mode_info_context->mbmi.mode = I8X8_PRED;
+ set_i8x8_block_modes(x, mode8x8);
+ rate += rate8x8;
+ }
+ }
*rate_ = rate;
}
diff --git a/vp8/encoder/rdopt.h b/vp8/encoder/rdopt.h
index 95134cb81..9bb7e404b 100644
--- a/vp8/encoder/rdopt.h
+++ b/vp8/encoder/rdopt.h
@@ -13,9 +13,12 @@
#define __INC_RDOPT_H
#define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
+#define RDCOST_8x8(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
extern void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue);
-extern void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra);
+extern void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset,
+ int *returnrate, int *returndistortion, int *returnintra,
+ int *best_single_rd_diff, int *best_comp_rd_diff, int *best_hybrid_rd_diff);
extern void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate);
extern void vp8_mv_pred
@@ -29,6 +32,8 @@ extern void vp8_mv_pred
int *sr,
int near_sadidx[]
);
-void vp8_cal_sad(VP8_COMP *cpi, MACROBLOCKD *xd, MACROBLOCK *x, int recon_yoffset, int near_sadidx[]);
+extern void vp8_cal_sad(VP8_COMP *cpi, MACROBLOCKD *xd, MACROBLOCK *x, int recon_yoffset, int near_sadidx[]);
+extern void vp8_init_me_luts();
+extern void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv);
#endif
diff --git a/vp8/encoder/sad_c.c b/vp8/encoder/sad_c.c
index 3b6e26c4e..c734458a9 100644
--- a/vp8/encoder/sad_c.c
+++ b/vp8/encoder/sad_c.c
@@ -10,7 +10,7 @@
#include <stdlib.h>
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx/vpx_integer.h"
unsigned int vp8_sad16x16_c(
diff --git a/vp8/encoder/satd_c.c b/vp8/encoder/satd_c.c
new file mode 100644
index 000000000..88c304b1f
--- /dev/null
+++ b/vp8/encoder/satd_c.c
@@ -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.
+ */
+
+#include <stdlib.h>
+#include "dct.h"
+#include "vpx_ports/mem.h"
+
+unsigned int vp8_satd16x16_c(const unsigned char *src_ptr,
+ int src_stride,
+ const unsigned char *ref_ptr,
+ int ref_stride,
+ unsigned int *psatd)
+{
+ int r, c, i;
+ unsigned int satd = 0;
+ DECLARE_ALIGNED(16, short, diff_in[256]);
+ DECLARE_ALIGNED(16, short, diff_out[16]);
+ short *in;
+
+ for (r = 0; r < 16; r++)
+ {
+ for (c = 0; c < 16; c++)
+ {
+ diff_in[r * 16 + c] = src_ptr[c] - ref_ptr[c];
+ }
+ src_ptr += src_stride;
+ ref_ptr += ref_stride;
+ }
+
+ in = diff_in;
+ for (r = 0; r < 16; r += 4)
+ {
+ for (c = 0; c < 16; c+=4)
+ {
+ vp8_short_walsh4x4_c(in + c, diff_out, 32);
+ for(i = 0; i < 16; i++)
+ satd += abs(diff_out[i]);
+ }
+ in += 64;
+ }
+
+ if (psatd)
+ *psatd = satd;
+
+ return satd;
+}
diff --git a/vp8/encoder/segmentation.c b/vp8/encoder/segmentation.c
index fc0967db3..c36246a02 100644
--- a/vp8/encoder/segmentation.c
+++ b/vp8/encoder/segmentation.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ * 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
@@ -9,8 +9,10 @@
*/
-#include "segmentation.h"
+#include "limits.h"
#include "vpx_mem/vpx_mem.h"
+#include "segmentation.h"
+#include "vp8/common/pred_common.h"
void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x)
{
@@ -37,8 +39,10 @@ void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x)
// If using golden then set GF active flag if not already set.
// If using last frame 0,0 mode then leave flag as it is
- // else if using non 0,0 motion or intra modes then clear flag if it is currently set
- if ((this_mb_mode_info->mbmi.ref_frame == GOLDEN_FRAME) || (this_mb_mode_info->mbmi.ref_frame == ALTREF_FRAME))
+ // else if using non 0,0 motion or intra modes then clear
+ // flag if it is currently set
+ if ((this_mb_mode_info->mbmi.ref_frame == GOLDEN_FRAME) ||
+ (this_mb_mode_info->mbmi.ref_frame == ALTREF_FRAME))
{
if (*(x->gf_active_ptr) == 0)
{
@@ -46,14 +50,15 @@ void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x)
cpi->gf_active_count ++;
}
}
- else if ((this_mb_mode_info->mbmi.mode != ZEROMV) && *(x->gf_active_ptr))
+ else if ((this_mb_mode_info->mbmi.mode != ZEROMV) &&
+ *(x->gf_active_ptr))
{
*(x->gf_active_ptr) = 0;
cpi->gf_active_count--;
}
x->gf_active_ptr++; // Step onto next entry
- this_mb_mode_info++; // skip to next mb
+ this_mb_mode_info++; // skip to next mb
}
@@ -62,3 +67,251 @@ void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x)
}
}
}
+
+void vp8_enable_segmentation(VP8_PTR ptr)
+{
+ VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+ // Set the appropriate feature bit
+ cpi->mb.e_mbd.segmentation_enabled = 1;
+ cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+ cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+}
+
+void vp8_disable_segmentation(VP8_PTR ptr)
+{
+ VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+ // Clear the appropriate feature bit
+ cpi->mb.e_mbd.segmentation_enabled = 0;
+}
+
+void vp8_set_segmentation_map(VP8_PTR ptr,
+ unsigned char *segmentation_map)
+{
+ VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+ // Copy in the new segmentation map
+ vpx_memcpy( cpi->segmentation_map, segmentation_map,
+ (cpi->common.mb_rows * cpi->common.mb_cols) );
+
+ // Signal that the map should be updated.
+ cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+ cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+}
+
+void vp8_set_segment_data(VP8_PTR ptr,
+ signed char *feature_data,
+ unsigned char abs_delta)
+{
+ VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+ cpi->mb.e_mbd.mb_segment_abs_delta = abs_delta;
+
+ vpx_memcpy(cpi->mb.e_mbd.segment_feature_data, feature_data,
+ sizeof(cpi->mb.e_mbd.segment_feature_data));
+
+ // TBD ?? Set the feature mask
+ // vpx_memcpy(cpi->mb.e_mbd.segment_feature_mask, 0,
+ // sizeof(cpi->mb.e_mbd.segment_feature_mask));
+}
+
+// Based on set of segment counts calculate a probability tree
+static void calc_segtree_probs( MACROBLOCKD * xd,
+ int * segcounts,
+ vp8_prob * segment_tree_probs )
+{
+ int count1,count2;
+ int tot_count;
+ int i;
+
+ // Blank the strtucture to start with
+ vpx_memset(segment_tree_probs, 0, sizeof(segment_tree_probs));
+
+ // Total count for all segments
+ count1 = segcounts[0] + segcounts[1];
+ count2 = segcounts[2] + segcounts[3];
+ tot_count = count1 + count2;
+
+ // Work out probabilities of each segment
+ if (tot_count)
+ segment_tree_probs[0] = (count1 * 255) / tot_count;
+ if (count1 > 0)
+ segment_tree_probs[1] = (segcounts[0] * 255) / count1;
+ if (count2 > 0)
+ segment_tree_probs[2] = (segcounts[2] * 255) / count2;
+
+ // Clamp probabilities to minimum allowed value
+ for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
+ {
+ if (segment_tree_probs[i] == 0)
+ segment_tree_probs[i] = 1;
+ }
+}
+
+// Based on set of segment counts and probabilities calculate a cost estimate
+static int cost_segmap( MACROBLOCKD * xd,
+ int * segcounts,
+ vp8_prob * probs )
+{
+ int cost;
+ int count1,count2;
+
+ // Cost the top node of the tree
+ count1 = segcounts[0] + segcounts[1];
+ count2 = segcounts[2] + segcounts[3];
+ cost = count1 * vp8_cost_zero(probs[0]) +
+ count2 * vp8_cost_one(probs[0]);
+
+ // Now add the cost of each individual segment branch
+ if (count1 > 0)
+ cost += segcounts[0] * vp8_cost_zero(probs[1]) +
+ segcounts[1] * vp8_cost_one(probs[1]);
+
+ if (count2 > 0)
+ cost += segcounts[2] * vp8_cost_zero(probs[2]) +
+ segcounts[3] * vp8_cost_one(probs[2]) ;
+
+ return cost;
+
+}
+
+void choose_segmap_coding_method( VP8_COMP *cpi )
+{
+ VP8_COMMON *const cm = & cpi->common;
+ MACROBLOCKD *const xd = & cpi->mb.e_mbd;
+
+ int i;
+ int tot_count;
+ int no_pred_cost;
+ int t_pred_cost = INT_MAX;
+ int pred_context;
+
+ int mb_row, mb_col;
+ int segmap_index = 0;
+ unsigned char segment_id;
+
+ int temporal_predictor_count[PREDICTION_PROBS][2];
+ int no_pred_segcounts[MAX_MB_SEGMENTS];
+ int t_unpred_seg_counts[MAX_MB_SEGMENTS];
+
+ vp8_prob no_pred_tree[MB_FEATURE_TREE_PROBS];
+ vp8_prob t_pred_tree[MB_FEATURE_TREE_PROBS];
+ vp8_prob t_nopred_prob[PREDICTION_PROBS];
+
+ // Set default state for the segment tree probabilities and the
+ // temporal coding probabilities
+ vpx_memset(xd->mb_segment_tree_probs, 255,
+ sizeof(xd->mb_segment_tree_probs));
+ vpx_memset(cm->segment_pred_probs, 255,
+ sizeof(cm->segment_pred_probs));
+
+ vpx_memset(no_pred_segcounts, 0, sizeof(no_pred_segcounts));
+ vpx_memset(t_unpred_seg_counts, 0, sizeof(t_unpred_seg_counts));
+ vpx_memset(temporal_predictor_count, 0, sizeof(temporal_predictor_count));
+
+ // First of all generate stats regarding how well the last segment map
+ // predicts this one
+
+ // Initialize macroblock decoder mode info context for the first mb
+ // in the frame
+ xd->mode_info_context = cm->mi;
+
+ for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+ {
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+ {
+ segment_id = xd->mode_info_context->mbmi.segment_id;
+
+ // Count the number of hits on each segment with no prediction
+ no_pred_segcounts[segment_id]++;
+
+ // Temporal prediction not allowed on key frames
+ if (cm->frame_type != KEY_FRAME)
+ {
+ // Test to see if the segment id matches the predicted value.
+ int seg_predicted =
+ (segment_id == get_pred_mb_segid( cm, segmap_index ));
+
+ // Get the segment id prediction context
+ pred_context =
+ get_pred_context( cm, xd, PRED_SEG_ID );
+
+ // Store the prediction status for this mb and update counts
+ // as appropriate
+ set_pred_flag( xd, PRED_SEG_ID, seg_predicted );
+ temporal_predictor_count[pred_context][seg_predicted]++;
+
+ if ( !seg_predicted )
+ // Update the "unpredicted" segment count
+ t_unpred_seg_counts[segment_id]++;
+ }
+
+ // Step on to the next mb
+ xd->mode_info_context++;
+
+ // Step on to the next entry in the segment maps
+ segmap_index++;
+ }
+
+ // this is to account for the border in mode_info_context
+ xd->mode_info_context++;
+ }
+
+ // Work out probability tree for coding segments without prediction
+ // and the cost.
+ calc_segtree_probs( xd, no_pred_segcounts, no_pred_tree );
+ no_pred_cost = cost_segmap( xd, no_pred_segcounts, no_pred_tree );
+
+ // Key frames cannot use temporal prediction
+ if (cm->frame_type != KEY_FRAME)
+ {
+ // Work out probability tree for coding those segments not
+ // predicted using the temporal method and the cost.
+ calc_segtree_probs( xd, t_unpred_seg_counts, t_pred_tree );
+ t_pred_cost = cost_segmap( xd, t_unpred_seg_counts, t_pred_tree );
+
+ // Add in the cost of the signalling for each prediction context
+ for ( i = 0; i < PREDICTION_PROBS; i++ )
+ {
+ tot_count = temporal_predictor_count[i][0] +
+ temporal_predictor_count[i][1];
+
+ // Work out the context probabilities for the segment
+ // prediction flag
+ if ( tot_count )
+ {
+ t_nopred_prob[i] = ( temporal_predictor_count[i][0] * 255 ) /
+ tot_count;
+
+ // Clamp to minimum allowed value
+ if ( t_nopred_prob[i] < 1 )
+ t_nopred_prob[i] = 1;
+ }
+ else
+ t_nopred_prob[i] = 1;
+
+ // Add in the predictor signaling cost
+ t_pred_cost += ( temporal_predictor_count[i][0] *
+ vp8_cost_zero(t_nopred_prob[i]) ) +
+ ( temporal_predictor_count[i][1] *
+ vp8_cost_one(t_nopred_prob[i]) );
+ }
+ }
+
+ // Now choose which coding method to use.
+ if ( t_pred_cost < no_pred_cost )
+ {
+ cm->temporal_update = 1;
+ vpx_memcpy( xd->mb_segment_tree_probs,
+ t_pred_tree, sizeof(t_pred_tree) );
+ vpx_memcpy( &cm->segment_pred_probs,
+ t_nopred_prob, sizeof(t_nopred_prob) );
+ }
+ else
+ {
+ cm->temporal_update = 0;
+ vpx_memcpy( xd->mb_segment_tree_probs,
+ no_pred_tree, sizeof(no_pred_tree) );
+ }
+}
diff --git a/vp8/encoder/segmentation.h b/vp8/encoder/segmentation.h
index 12815b087..a7e1f7cfe 100644
--- a/vp8/encoder/segmentation.h
+++ b/vp8/encoder/segmentation.h
@@ -13,4 +13,31 @@
#include "vp8/common/blockd.h"
#include "onyx_int.h"
+#ifndef __INC_SEGMENTATION_H__
+#define __INC_SEGMENTATION_H__ 1
+
extern void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x);
+
+extern void vp8_enable_segmentation(VP8_PTR ptr);
+extern void vp8_disable_segmentation(VP8_PTR ptr);
+
+// Valid values for a segment are 0 to 3
+// Segmentation map is arrange as [Rows][Columns]
+extern void vp8_set_segmentation_map(VP8_PTR ptr, unsigned char *segmentation_map);
+
+// The values given for each segment can be either deltas (from the default
+// value chosen for the frame) or absolute values.
+//
+// Valid range for abs values is (0-127 for MB_LVL_ALT_Q) , (0-63 for
+// SEGMENT_ALT_LF)
+// Valid range for delta values are (+/-127 for MB_LVL_ALT_Q) , (+/-63 for
+// SEGMENT_ALT_LF)
+//
+// abs_delta = SEGMENT_DELTADATA (deltas) abs_delta = SEGMENT_ABSDATA (use
+// the absolute values given).
+//
+extern void vp8_set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned char abs_delta);
+
+extern void choose_segmap_coding_method( VP8_COMP *cpi );
+
+#endif /* __INC_SEGMENTATION_H__ */
diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c
index b9ade1c6c..7440883e0 100644
--- a/vp8/encoder/temporal_filter.c
+++ b/vp8/encoder/temporal_filter.c
@@ -26,7 +26,6 @@
#include "vpx_scale/yv12extend.h"
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/swapyv12buffer.h"
-#include "vp8/common/threading.h"
#include "vpx_ports/vpx_timer.h"
#include <math.h>
@@ -37,6 +36,7 @@
#if VP8_TEMPORAL_ALT_REF
+
static void vp8_temporal_filter_predictors_mb_c
(
MACROBLOCKD *x,
@@ -51,14 +51,20 @@ static void vp8_temporal_filter_predictors_mb_c
{
int offset;
unsigned char *yptr, *uptr, *vptr;
+ int omv_row, omv_col;
// Y
yptr = y_mb_ptr + (mv_row >> 3) * stride + (mv_col >> 3);
if ((mv_row | mv_col) & 7)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ x->subpixel_predict16x16(yptr, stride,
+ (mv_col & 7)<<1, (mv_row & 7)<<1, &pred[0], 16);
+#else
x->subpixel_predict16x16(yptr, stride,
- mv_col & 7, mv_row & 7, &pred[0], 16);
+ mv_col & 7, mv_row & 7, &pred[0], 16);
+#endif
}
else
{
@@ -66,6 +72,8 @@ static void vp8_temporal_filter_predictors_mb_c
}
// U & V
+ omv_row = mv_row;
+ omv_col = mv_col;
mv_row >>= 1;
mv_col >>= 1;
stride = (stride + 1) >> 1;
@@ -73,6 +81,15 @@ static void vp8_temporal_filter_predictors_mb_c
uptr = u_mb_ptr + offset;
vptr = v_mb_ptr + offset;
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ if ((omv_row | omv_col) & 15)
+ {
+ x->subpixel_predict8x8(uptr, stride,
+ (omv_col & 15), (omv_row & 15), &pred[256], 8);
+ x->subpixel_predict8x8(vptr, stride,
+ (omv_col & 15), (omv_row & 15), &pred[320], 8);
+ }
+#else
if ((mv_row | mv_col) & 7)
{
x->subpixel_predict8x8(uptr, stride,
@@ -80,6 +97,7 @@ static void vp8_temporal_filter_predictors_mb_c
x->subpixel_predict8x8(vptr, stride,
mv_col & 7, mv_row & 7, &pred[320], 8);
}
+#endif
else
{
RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, stride, &pred[256], 8);
@@ -98,7 +116,7 @@ void vp8_temporal_filter_apply_c
unsigned short *count
)
{
- int i, j, k;
+ unsigned int i, j, k;
int modifier;
int byte = 0;
@@ -137,6 +155,9 @@ void vp8_temporal_filter_apply_c
#if ALT_REF_MC_ENABLED
static int dummy_cost[2*mv_max+1];
+#if CONFIG_HIGH_PRECISION_MV
+static int dummy_cost_hp[2*mv_max_hp+1];
+#endif
static int vp8_temporal_filter_find_matching_mb_c
(
@@ -160,6 +181,10 @@ static int vp8_temporal_filter_find_matching_mb_c
int *mvcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] };
int *mvsadcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] };
+#if CONFIG_HIGH_PRECISION_MV
+ int *mvcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost_hp[mv_max_hp+1] };
+ int *mvsadcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost_hp[mv_max_hp+1] };
+#endif
// Save input state
unsigned char **base_src = b->base_src;
@@ -203,7 +228,13 @@ static int vp8_temporal_filter_find_matching_mb_c
step_param,
sadpb,
&cpi->fn_ptr[BLOCK_16X16],
- mvsadcost, mvcost, &best_ref_mv1);
+#if CONFIG_HIGH_PRECISION_MV
+ x->e_mbd.allow_high_precision_mv?mvsadcost_hp:mvsadcost,
+ x->e_mbd.allow_high_precision_mv?mvcost_hp:mvcost,
+#else
+ mvsadcost, mvcost,
+#endif
+ &best_ref_mv1);
#if ALT_REF_SUBPEL_ENABLED
// Try sub-pixel MC?
@@ -214,7 +245,12 @@ static int vp8_temporal_filter_find_matching_mb_c
bestsme = cpi->find_fractional_mv_step(x, b, d,
&d->bmi.mv, &best_ref_mv1,
x->errorperbit, &cpi->fn_ptr[BLOCK_16X16],
- mvcost, &distortion, &sse);
+#if CONFIG_HIGH_PRECISION_MV
+ x->e_mbd.allow_high_precision_mv?mvcost_hp:mvcost,
+#else
+ mvcost,
+#endif
+ &distortion, &sse);
}
#endif
@@ -263,17 +299,17 @@ static void vp8_temporal_filter_iterate_c
#if ALT_REF_MC_ENABLED
// Source frames are extended to 16 pixels. This is different than
// L/A/G reference frames that have a border of 32 (VP8BORDERINPIXELS)
- // A 6 tap filter is used for motion search. This requires 2 pixels
+ // A 6/8 tap filter is used for motion search. This requires 2 pixels
// before and 3 pixels after. So the largest Y mv on a border would
- // then be 16 - 3. The UV blocks are half the size of the Y and
+ // then be 16 - INTERP_EXTEND. The UV blocks are half the size of the Y and
// therefore only extended by 8. The largest mv that a UV block
- // can support is 8 - 3. A UV mv is half of a Y mv.
- // (16 - 3) >> 1 == 6 which is greater than 8 - 3.
+ // can support is 8 - INTERP_EXTEND. A UV mv is half of a Y mv.
+ // (16 - INTERP_EXTEND) >> 1 which is greater than 8 - INTERP_EXTEND.
// To keep the mv in play for both Y and UV planes the max that it
- // can be on a border is therefore 16 - 5.
- cpi->mb.mv_row_min = -((mb_row * 16) + (16 - 5));
+ // can be on a border is therefore 16 - (2*INTERP_EXTEND+1).
+ cpi->mb.mv_row_min = -((mb_row * 16) + (17 - 2*INTERP_EXTEND));
cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16)
- + (16 - 5);
+ + (17 - 2*INTERP_EXTEND);
#endif
for (mb_col = 0; mb_col < mb_cols; mb_col++)
@@ -285,9 +321,9 @@ static void vp8_temporal_filter_iterate_c
vpx_memset(count, 0, 384*sizeof(unsigned short));
#if ALT_REF_MC_ENABLED
- cpi->mb.mv_col_min = -((mb_col * 16) + (16 - 5));
+ cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2*INTERP_EXTEND));
cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16)
- + (16 - 5);
+ + (17 - 2*INTERP_EXTEND);
#endif
for (frame = 0; frame < frame_count; frame++)
diff --git a/vp8/encoder/tokenize.c b/vp8/encoder/tokenize.c
index 15e7336b1..c86e022ba 100644
--- a/vp8/encoder/tokenize.c
+++ b/vp8/encoder/tokenize.c
@@ -17,23 +17,30 @@
#include "tokenize.h"
#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/seg_common.h"
+
/* Global event counters used for accumulating statistics across several
compressions, then generating context.c = initial stats. */
#ifdef ENTROPY_STATS
_int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
+_int64 context_counters_8x8[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
#endif
void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
+void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
void vp8_fix_contexts(MACROBLOCKD *x);
static TOKENVALUE dct_value_tokens[DCT_MAX_VALUE*2];
const TOKENVALUE *vp8_dct_value_tokens_ptr;
static int dct_value_cost[DCT_MAX_VALUE*2];
const int *vp8_dct_value_cost_ptr;
-#if 0
-int skip_true_count = 0;
-int skip_false_count = 0;
+
+#ifdef ENC_DEBUG
+extern int mb_row_debug;
+extern int mb_col_debug;
+extern int enc_debug;
#endif
+
static void fill_value_tokens()
{
@@ -93,9 +100,81 @@ static void fill_value_tokens()
vp8_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
}
+static void tokenize2nd_order_b_8x8
+(
+ MACROBLOCKD *xd,
+ const BLOCKD *const b,
+ TOKENEXTRA **tp,
+ const int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+ const FRAME_TYPE frametype,
+ ENTROPY_CONTEXT *a,
+ ENTROPY_CONTEXT *l,
+ VP8_COMP *cpi
+)
+{
+ int pt; /* near block/prev token context index */
+ int c = 0; /* start at DC */
+ const int eob = b->eob; /* one beyond last nonzero coeff */
+ TOKENEXTRA *t = *tp; /* store tokens starting here */
+ int x;
+ const short *qcoeff_ptr = b->qcoeff;
+
+ int seg_eob = 4;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
+
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+
+
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+ assert(eob<=4);
+
+ do
+ {
+ const int band = vp8_coef_bands[c];
+
+ if (c < eob)
+ {
+ int rc = vp8_default_zig_zag1d[c];
+ const int v = qcoeff_ptr[rc];
+
+ assert(-DCT_MAX_VALUE <= v && v < (DCT_MAX_VALUE));
+
+ t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+ x = vp8_dct_value_tokens_ptr[v].Token;
+ }
+ else
+ x = DCT_EOB_TOKEN;
+
+ t->Token = x;
+ //printf("Token : %d\n", x);
+ t->context_tree = cpi->common.fc.coef_probs_8x8 [type] [band] [pt];
+
+ t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
+
+#ifdef ENC_DEBUG
+ if (t->skip_eob_node && vp8_coef_encodings[x].Len==1)
+ printf("Trouble 2 x=%d Len=%d skip=%d eob=%d c=%d band=%d type=%d: [%d %d %d]\n",
+ x, vp8_coef_encodings[x].Len, t->skip_eob_node, eob, c, band, type,
+ cpi->count, mb_row_debug, mb_col_debug);
+#endif
+
+ ++cpi->coef_counts_8x8 [type] [band] [pt] [x];
+ }
+ while (pt = vp8_prev_token_class[x], ++t, c < eob && ++c <seg_eob);
+
+ *tp = t;
+ pt = (c != !type); /* 0 <-> all coeff data is zero */
+ *a = *l = pt;
+
+}
+
static void tokenize2nd_order_b
(
- MACROBLOCKD *x,
+ MACROBLOCKD *xd,
TOKENEXTRA **tp,
VP8_COMP *cpi
)
@@ -109,10 +188,18 @@ static void tokenize2nd_order_b
ENTROPY_CONTEXT * l;
int band, rc, v, token;
- b = x->block + 24;
+ int seg_eob = 16;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
+
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+
+ b = xd->block + 24;
qcoeff_ptr = b->qcoeff;
- a = (ENTROPY_CONTEXT *)x->above_context + 8;
- l = (ENTROPY_CONTEXT *)x->left_context + 8;
+ a = (ENTROPY_CONTEXT *)xd->above_context + 8;
+ l = (ENTROPY_CONTEXT *)xd->left_context + 8;
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -135,7 +222,8 @@ static void tokenize2nd_order_b
pt = vp8_prev_token_class[token];
t++;
}
- if (c < 16)
+
+ if (c < seg_eob)
{
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
@@ -154,9 +242,77 @@ static void tokenize2nd_order_b
}
+static void tokenize1st_order_b_8x8
+(
+ MACROBLOCKD *xd,
+ const BLOCKD *const b,
+ TOKENEXTRA **tp,
+ const int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+ const FRAME_TYPE frametype,
+ ENTROPY_CONTEXT *a,
+ ENTROPY_CONTEXT *l,
+ VP8_COMP *cpi
+)
+{
+ int pt; /* near block/prev token context index */
+ int c = type ? 0 : 1; /* start at DC unless type 0 */
+ const int eob = b->eob; /* one beyond last nonzero coeff */
+ TOKENEXTRA *t = *tp; /* store tokens starting here */
+ int x;
+ const short *qcoeff_ptr = b->qcoeff;
+
+ int seg_eob = 64;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
+
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+ do
+ {
+ const int band = vp8_coef_bands_8x8[c];
+
+ x = DCT_EOB_TOKEN;
+
+ if (c < eob)
+ {
+ int rc = vp8_default_zig_zag1d_8x8[c];
+ const int v = qcoeff_ptr[rc];
+
+ assert(-DCT_MAX_VALUE <= v && v < (DCT_MAX_VALUE));
+
+ t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+ x = vp8_dct_value_tokens_ptr[v].Token;
+ }
+
+ t->Token = x;
+ t->context_tree = cpi->common.fc.coef_probs_8x8 [type] [band] [pt];
+
+ t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
+
+#ifdef ENC_DEBUG
+ if (t->skip_eob_node && vp8_coef_encodings[x].Len==1)
+ printf("Trouble 1 x=%d Len=%d skip=%d eob=%d c=%d band=%d type=%d: [%d %d %d]\n", x, vp8_coef_encodings[x].Len, t->skip_eob_node, eob, c, band, type, cpi->count, mb_row_debug, mb_col_debug);
+#endif
+
+ ++cpi->coef_counts_8x8 [type] [band] [pt] [x];
+ }
+ while (pt = vp8_prev_token_class[x], ++t, c < eob && ++c < seg_eob);
+
+ *tp = t;
+ pt = (c != !type); /* 0 <-> all coeff data is zero */
+ *a = *l = pt;
+}
+
+
+
+
static void tokenize1st_order_b
(
- MACROBLOCKD *x,
+ MACROBLOCKD *xd,
TOKENEXTRA **tp,
int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
VP8_COMP *cpi
@@ -174,15 +330,23 @@ static void tokenize1st_order_b
int band, rc, v;
int tmp1, tmp2;
- b = x->block;
+ int seg_eob = 16;
+ int segment_id = xd->mode_info_context->mbmi.segment_id;
+
+ if ( segfeature_active( xd, segment_id, SEG_LVL_EOB ) )
+ {
+ seg_eob = get_segdata( xd, segment_id, SEG_LVL_EOB );
+ }
+
+ b = xd->block;
/* Luma */
for (block = 0; block < 16; block++, b++)
{
tmp1 = vp8_block2above[block];
tmp2 = vp8_block2left[block];
qcoeff_ptr = b->qcoeff;
- a = (ENTROPY_CONTEXT *)x->above_context + tmp1;
- l = (ENTROPY_CONTEXT *)x->left_context + tmp2;
+ a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
+ l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -208,7 +372,8 @@ static void tokenize1st_order_b
pt = vp8_prev_token_class[token];
t++;
}
- if (c < 16)
+
+ if (c < seg_eob)
{
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
@@ -232,8 +397,8 @@ static void tokenize1st_order_b
tmp1 = vp8_block2above[block];
tmp2 = vp8_block2left[block];
qcoeff_ptr = b->qcoeff;
- a = (ENTROPY_CONTEXT *)x->above_context + tmp1;
- l = (ENTROPY_CONTEXT *)x->left_context + tmp2;
+ a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
+ l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
@@ -256,7 +421,8 @@ static void tokenize1st_order_b
pt = vp8_prev_token_class[token];
t++;
}
- if (c < 16)
+
+ if (c < seg_eob)
{
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
@@ -276,7 +442,7 @@ static void tokenize1st_order_b
}
-static int mb_is_skippable(MACROBLOCKD *x, int has_y2_block)
+int mby_is_skippable(MACROBLOCKD *x, int has_y2_block)
{
int skip = 1;
int i = 0;
@@ -285,30 +451,95 @@ static int mb_is_skippable(MACROBLOCKD *x, int has_y2_block)
{
for (i = 0; i < 16; i++)
skip &= (x->block[i].eob < 2);
+ skip &= (!x->block[24].eob);
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ skip &= (!x->block[i].eob);
}
+ return skip;
+}
- for (; i < 24 + has_y2_block; i++)
+int mbuv_is_skippable(MACROBLOCKD *x)
+{
+ int skip = 1;
+ int i;
+
+ for (i = 16; i < 24; i++)
skip &= (!x->block[i].eob);
+ return skip;
+}
+
+int mb_is_skippable(MACROBLOCKD *x, int has_y2_block)
+{
+ return (mby_is_skippable(x, has_y2_block) &
+ mbuv_is_skippable(x));
+}
+
+int mby_is_skippable_8x8(MACROBLOCKD *x)
+{
+ int skip = 1;
+ int i = 0;
+ for (i = 0; i < 16; i+=4)
+ skip &= (x->block[i].eob < 2);
+ skip &= (!x->block[24].eob);
return skip;
}
+int mbuv_is_skippable_8x8(MACROBLOCKD *x)
+{
+ return (!x->block[16].eob) & (!x->block[20].eob);
+}
+
+int mb_is_skippable_8x8(MACROBLOCKD *x)
+{
+ return (mby_is_skippable_8x8(x) & mbuv_is_skippable_8x8(x));
+}
+
void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
{
int plane_type;
int has_y2_block;
+ int b;
+ int tx_type = x->mode_info_context->mbmi.txfm_size;
+
+ // If the MB is going to be skipped because of a segment level flag
+ // exclude this from the skip count stats used to calculate the
+ // transmitted skip probability;
+ int skip_inc;
+ int segment_id = x->mode_info_context->mbmi.segment_id;
+
+ if ( !segfeature_active( x, segment_id, SEG_LVL_EOB ) ||
+ ( get_segdata( x, segment_id, SEG_LVL_EOB ) != 0) )
+ {
+ skip_inc = 1;
+ }
+ else
+ skip_inc = 0;
has_y2_block = (x->mode_info_context->mbmi.mode != B_PRED
+ && x->mode_info_context->mbmi.mode != I8X8_PRED
&& x->mode_info_context->mbmi.mode != SPLITMV);
- x->mode_info_context->mbmi.mb_skip_coeff = mb_is_skippable(x, has_y2_block);
+ x->mode_info_context->mbmi.mb_skip_coeff =
+ (( tx_type == TX_8X8 ) ?
+ mb_is_skippable_8x8(x) :
+ mb_is_skippable(x, has_y2_block));
+
if (x->mode_info_context->mbmi.mb_skip_coeff)
{
- cpi->skip_true_count++;
+ cpi->skip_true_count += skip_inc;
if (!cpi->common.mb_no_coeff_skip)
- vp8_stuff_mb(cpi, x, t) ;
+ {
+ if ( tx_type == TX_8X8 )
+ vp8_stuff_mb_8x8(cpi, x, t) ;
+ else
+ vp8_stuff_mb(cpi, x, t) ;
+ }
else
{
vp8_fix_contexts(x);
@@ -317,18 +548,55 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
return;
}
- cpi->skip_false_count++;
+ cpi->skip_false_count += skip_inc;
plane_type = 3;
if(has_y2_block)
{
- tokenize2nd_order_b(x, t, cpi);
- plane_type = 0;
+ if ( tx_type == TX_8X8 )
+ {
+ ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
+ ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
+ tokenize2nd_order_b_8x8(x,
+ x->block + 24, t, 1, x->frame_type,
+ A + vp8_block2above_8x8[24],
+ L + vp8_block2left_8x8[24], cpi);
+ }
+ else
+ tokenize2nd_order_b(x, t, cpi);
+
+ plane_type = 0;
}
- tokenize1st_order_b(x, t, plane_type, cpi);
+ if ( tx_type == TX_8X8 )
+ {
+ ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
+ ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
+ for (b = 0; b < 16; b+=4)
+ {
+ tokenize1st_order_b_8x8(x,
+ x->block + b, t, plane_type, x->frame_type,
+ A + vp8_block2above_8x8[b],
+ L + vp8_block2left_8x8[b],
+ cpi);
+ *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
+ *(L + vp8_block2left_8x8[b] + 1) = *(L + vp8_block2left_8x8[b] );
+ }
+ for (b = 16; b < 24; b+=4)
+ {
+ tokenize1st_order_b_8x8(x,
+ x->block + b, t, 2, x->frame_type,
+ A + vp8_block2above_8x8[b],
+ L + vp8_block2left_8x8[b],
+ cpi);
+ *(A + vp8_block2above_8x8[b]+1) = *(A + vp8_block2above_8x8[b]);
+ *(L + vp8_block2left_8x8[b]+1 ) = *(L + vp8_block2left_8x8[b]);
+ }
+ }
+ else
+ tokenize1st_order_b(x, t, plane_type, cpi);
}
@@ -337,6 +605,7 @@ void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
void init_context_counters(void)
{
vpx_memset(context_counters, 0, sizeof(context_counters));
+ vpx_memset(context_counters_8x8, 0, sizeof(context_counters_8x8));
}
void print_context_counters()
@@ -381,6 +650,54 @@ void print_context_counters()
const _int64 x = context_counters [type] [band] [pt] [t];
const int y = (int) x;
+ assert(x == (INT64) y); /* no overflow handling yet */
+ fprintf(f, "%s %d", Comma(t), y);
+
+ }
+ while (++t < MAX_ENTROPY_TOKENS);
+
+ fprintf(f, "}");
+ }
+ while (++pt < PREV_COEF_CONTEXTS);
+
+ fprintf(f, "\n }");
+
+ }
+ while (++band < COEF_BANDS);
+
+ fprintf(f, "\n }");
+ }
+ while (++type < BLOCK_TYPES);
+
+ fprintf(f, "int Contexts_8x8[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];\n\n");
+
+ fprintf(f, "const int default_contexts_8x8[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS] = {");
+
+ type = 0;
+
+ do
+ {
+ fprintf(f, "%s\n { /* block Type %d */", Comma(type), type);
+
+ band = 0;
+
+ do
+ {
+ fprintf(f, "%s\n { /* Coeff Band %d */", Comma(band), band);
+
+ pt = 0;
+
+ do
+ {
+ fprintf(f, "%s\n {", Comma(pt));
+
+ t = 0;
+
+ do
+ {
+ const _int64 x = context_counters [type] [band] [pt] [t];
+ const int y = (int) x;
+
assert(x == (_int64) y); /* no overflow handling yet */
fprintf(f, "%s %d", Comma(t), y);
@@ -412,6 +729,133 @@ void vp8_tokenize_initialize()
}
+static __inline void stuff2nd_order_b_8x8
+(
+ const BLOCKD *const b,
+ TOKENEXTRA **tp,
+ const int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+ const FRAME_TYPE frametype,
+ ENTROPY_CONTEXT *a,
+ ENTROPY_CONTEXT *l,
+ VP8_COMP *cpi
+)
+{
+ int pt; /* near block/prev token context index */
+ TOKENEXTRA *t = *tp; /* store tokens starting here */
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+ (void) frametype;
+ (void) type;
+ (void) b;
+
+ t->Token = DCT_EOB_TOKEN;
+ t->context_tree = cpi->common.fc.coef_probs_8x8 [1] [0] [pt];
+ //t->section = 11;
+ t->skip_eob_node = 0;
+ ++cpi->coef_counts_8x8 [1] [0] [pt] [DCT_EOB_TOKEN];
+ ++t;
+
+ *tp = t;
+ pt = 0;
+ *a = *l = pt;
+
+}
+
+static __inline void stuff1st_order_b_8x8
+(
+ const BLOCKD *const b,
+ TOKENEXTRA **tp,
+ const int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+ const FRAME_TYPE frametype,
+ ENTROPY_CONTEXT *a,
+ ENTROPY_CONTEXT *l,
+ VP8_COMP *cpi
+)
+{
+ int pt; /* near block/prev token context index */
+ TOKENEXTRA *t = *tp; /* store tokens starting here */
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+ (void) frametype;
+ (void) type;
+ (void) b;
+
+ t->Token = DCT_EOB_TOKEN;
+ t->context_tree = cpi->common.fc.coef_probs_8x8 [0] [1] [pt];
+ //t->section = 8;
+ t->skip_eob_node = 0;
+ ++cpi->coef_counts_8x8 [0] [1] [pt] [DCT_EOB_TOKEN];
+ ++t;
+ *tp = t;
+ pt = 0; /* 0 <-> all coeff data is zero */
+ *a = *l = pt;
+
+
+}
+
+static __inline
+void stuff1st_order_buv_8x8
+(
+ const BLOCKD *const b,
+ TOKENEXTRA **tp,
+ const int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+ const FRAME_TYPE frametype,
+ ENTROPY_CONTEXT *a,
+ ENTROPY_CONTEXT *l,
+ VP8_COMP *cpi
+)
+{
+ int pt; /* near block/prev token context index */
+ TOKENEXTRA *t = *tp; /* store tokens starting here */
+ VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+ (void) frametype;
+ (void) type;
+ (void) b;
+
+ t->Token = DCT_EOB_TOKEN;
+ t->context_tree = cpi->common.fc.coef_probs_8x8 [2] [0] [pt];
+ //t->section = 13;
+ t->skip_eob_node = 0;
+ ++cpi->coef_counts_8x8[2] [0] [pt] [DCT_EOB_TOKEN];
+ ++t;
+ *tp = t;
+ pt = 0; /* 0 <-> all coeff data is zero */
+ *a = *l = pt;
+
+}
+
+void vp8_stuff_mb_8x8(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
+{
+ ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
+ ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
+ int plane_type;
+ int b;
+
+ stuff2nd_order_b_8x8(x->block + 24, t, 1, x->frame_type,
+ A + vp8_block2above_8x8[24],
+ L + vp8_block2left_8x8[24], cpi);
+ plane_type = 0;
+
+ for (b = 0; b < 16; b+=4)
+ {
+ stuff1st_order_b_8x8(x->block + b, t, plane_type, x->frame_type,
+ A + vp8_block2above_8x8[b],
+ L + vp8_block2left_8x8[b],
+ cpi);
+ *(A + vp8_block2above_8x8[b] + 1) = *(A + vp8_block2above_8x8[b]);
+ *(L + vp8_block2left_8x8[b] + 1) = *(L + vp8_block2left_8x8[b] );
+ }
+
+ for (b = 16; b < 24; b+=4)
+ {
+ stuff1st_order_buv_8x8(x->block + b, t, 2, x->frame_type,
+ A + vp8_block2above[b],
+ L + vp8_block2left[b],
+ cpi);
+ *(A + vp8_block2above_8x8[b]+1) = *(A + vp8_block2above_8x8[b]);
+ *(L + vp8_block2left_8x8[b]+1 ) = *(L + vp8_block2left_8x8[b]);
+ }
+}
+
+
static __inline void stuff2nd_order_b
(
TOKENEXTRA **tp,
@@ -507,7 +951,9 @@ void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
void vp8_fix_contexts(MACROBLOCKD *x)
{
/* Clear entropy contexts for Y2 blocks */
- if (x->mode_info_context->mbmi.mode != B_PRED && x->mode_info_context->mbmi.mode != SPLITMV)
+ if (x->mode_info_context->mbmi.mode != B_PRED
+ && x->mode_info_context->mbmi.mode != I8X8_PRED
+ && x->mode_info_context->mbmi.mode != SPLITMV)
{
vpx_memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
vpx_memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
diff --git a/vp8/encoder/tokenize.h b/vp8/encoder/tokenize.h
index 04a8879cf..0608102d0 100644
--- a/vp8/encoder/tokenize.h
+++ b/vp8/encoder/tokenize.h
@@ -33,13 +33,20 @@ typedef struct
int rd_cost_mby(MACROBLOCKD *);
+extern int mby_is_skippable(MACROBLOCKD *x,int has_y2_block);
+extern int mbuv_is_skippable(MACROBLOCKD *x);
+extern int mb_is_skippable(MACROBLOCKD *x,int has_y2_block);
+extern int mby_is_skippable_8x8(MACROBLOCKD *x);
+extern int mbuv_is_skippable_8x8(MACROBLOCKD *x);
+extern int mb_is_skippable_8x8(MACROBLOCKD *x);
+
#ifdef ENTROPY_STATS
void init_context_counters();
void print_context_counters();
extern _int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
+extern _int64 context_counters_8x8[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
#endif
-
extern const int *vp8_dct_value_cost_ptr;
/* TODO: The Token field should be broken out into a separate char array to
* improve cache locality, since it's needed for costing when the rest of the
diff --git a/vp8/encoder/treewriter.c b/vp8/encoder/treewriter.c
index 03967c835..3a777f222 100644
--- a/vp8/encoder/treewriter.c
+++ b/vp8/encoder/treewriter.c
@@ -37,3 +37,9 @@ void vp8_cost_tokens(int *c, const vp8_prob *p, vp8_tree t)
{
cost(c, t, p, 0, 0);
}
+
+void vp8_cost_tokens_skip(int *c, const vp8_prob *p, vp8_tree t)
+{
+ cost(c, t, p, 2, 0);
+}
+
diff --git a/vp8/encoder/variance.h b/vp8/encoder/variance.h
index d9bf66975..fde8ade09 100644
--- a/vp8/encoder/variance.h
+++ b/vp8/encoder/variance.h
@@ -315,11 +315,6 @@ extern prototype_getmbss(vp8_variance_getmbss);
#endif
extern prototype_variance(vp8_variance_mse16x16);
-#ifndef vp8_variance_get4x4sse_cs
-#define vp8_variance_get4x4sse_cs vp8_get4x4sse_cs_c
-#endif
-extern prototype_get16x16prederror(vp8_variance_get4x4sse_cs);
-
#ifndef vp8_ssimpf_8x8
#define vp8_ssimpf_8x8 vp8_ssim_parms_8x8_c
#endif
@@ -330,6 +325,11 @@ extern prototype_ssimpf(vp8_ssimpf_8x8)
#endif
extern prototype_ssimpf(vp8_ssimpf_16x16)
+#ifndef vp8_variance_satd16x16
+#define vp8_variance_satd16x16 vp8_satd16x16_c
+#endif
+extern prototype_variance(vp8_variance_satd16x16);
+
typedef prototype_sad(*vp8_sad_fn_t);
typedef prototype_sad_multi_same_address(*vp8_sad_multi_fn_t);
typedef prototype_sad_multi_same_address_1(*vp8_sad_multi1_fn_t);
@@ -368,8 +368,6 @@ typedef struct
vp8_getmbss_fn_t getmbss;
vp8_variance_fn_t mse16x16;
- vp8_get16x16prederror_fn_t get4x4sse_cs;
-
vp8_sad_multi_fn_t sad16x16x3;
vp8_sad_multi_fn_t sad16x8x3;
vp8_sad_multi_fn_t sad8x16x3;
@@ -397,6 +395,7 @@ typedef struct
vp8_ssimpf_fn_t ssimpf_16x16;
#endif
+ vp8_variance_fn_t satd16x16;
} vp8_variance_rtcd_vtable_t;
typedef struct
diff --git a/vp8/encoder/variance_c.c b/vp8/encoder/variance_c.c
index c7b9c2209..402ff0450 100644
--- a/vp8/encoder/variance_c.c
+++ b/vp8/encoder/variance_c.c
@@ -363,8 +363,13 @@ unsigned int vp8_variance_halfpixvar16x16_h_c(
int recon_stride,
unsigned int *sse)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 8, 0,
+ ref_ptr, recon_stride, sse);
+#else
return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 0,
ref_ptr, recon_stride, sse);
+#endif
}
@@ -375,8 +380,13 @@ unsigned int vp8_variance_halfpixvar16x16_v_c(
int recon_stride,
unsigned int *sse)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 0, 8,
+ ref_ptr, recon_stride, sse);
+#else
return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 0, 4,
ref_ptr, recon_stride, sse);
+#endif
}
@@ -387,8 +397,13 @@ unsigned int vp8_variance_halfpixvar16x16_hv_c(
int recon_stride,
unsigned int *sse)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 8, 8,
+ ref_ptr, recon_stride, sse);
+#else
return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 4,
ref_ptr, recon_stride, sse);
+#endif
}
diff --git a/vp8/encoder/x86/variance_impl_sse2.asm b/vp8/encoder/x86/variance_impl_sse2.asm
index 762922091..b13beee6e 100644
--- a/vp8/encoder/x86/variance_impl_sse2.asm
+++ b/vp8/encoder/x86/variance_impl_sse2.asm
@@ -1348,12 +1348,32 @@ align 16
xmm_bi_rd:
times 8 dw 64
align 16
+%if CONFIG_SIXTEENTH_SUBPEL_UV
vp8_bilinear_filters_sse2:
dw 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0
+ dw 120, 120, 120, 120, 120, 120, 120, 120, 8, 8, 8, 8, 8, 8, 8, 8
dw 112, 112, 112, 112, 112, 112, 112, 112, 16, 16, 16, 16, 16, 16, 16, 16
+ dw 104, 104, 104, 104, 104, 104, 104, 104, 24, 24, 24, 24, 24, 24, 24, 24
dw 96, 96, 96, 96, 96, 96, 96, 96, 32, 32, 32, 32, 32, 32, 32, 32
+ dw 88, 88, 88, 88, 88, 88, 88, 88, 40, 40, 40, 40, 40, 40, 40, 40
dw 80, 80, 80, 80, 80, 80, 80, 80, 48, 48, 48, 48, 48, 48, 48, 48
+ dw 72, 72, 72, 72, 72, 72, 72, 72, 56, 56, 56, 56, 56, 56, 56, 56
dw 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+ dw 56, 56, 56, 56, 56, 56, 56, 56, 72, 72, 72, 72, 72, 72, 72, 72
dw 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80
+ dw 40, 40, 40, 40, 40, 40, 40, 40, 88, 88, 88, 88, 88, 88, 88, 88
dw 32, 32, 32, 32, 32, 32, 32, 32, 96, 96, 96, 96, 96, 96, 96, 96
+ dw 24, 24, 24, 24, 24, 24, 24, 24, 104, 104, 104, 104, 104, 104, 104, 104
dw 16, 16, 16, 16, 16, 16, 16, 16, 112, 112, 112, 112, 112, 112, 112, 112
+ dw 8, 8, 8, 8, 8, 8, 8, 8, 120, 120, 120, 120, 120, 120, 120, 120
+%else
+vp8_bilinear_filters_sse2:
+ dw 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0
+ dw 112, 112, 112, 112, 112, 112, 112, 112, 16, 16, 16, 16, 16, 16, 16, 16
+ dw 96, 96, 96, 96, 96, 96, 96, 96, 32, 32, 32, 32, 32, 32, 32, 32
+ dw 80, 80, 80, 80, 80, 80, 80, 80, 48, 48, 48, 48, 48, 48, 48, 48
+ dw 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+ dw 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80
+ dw 32, 32, 32, 32, 32, 32, 32, 32, 96, 96, 96, 96, 96, 96, 96, 96
+ dw 16, 16, 16, 16, 16, 16, 16, 16, 112, 112, 112, 112, 112, 112, 112, 112
+%endif
diff --git a/vp8/encoder/x86/variance_impl_ssse3.asm b/vp8/encoder/x86/variance_impl_ssse3.asm
index 97e8b0e2e..d60d53daa 100644
--- a/vp8/encoder/x86/variance_impl_ssse3.asm
+++ b/vp8/encoder/x86/variance_impl_ssse3.asm
@@ -353,6 +353,25 @@ align 16
xmm_bi_rd:
times 8 dw 64
align 16
+%if CONFIG_SIXTEENTH_SUBPEL_UV
+vp8_bilinear_filters_ssse3:
+ times 8 db 128, 0
+ times 8 db 120, 8
+ times 8 db 112, 16
+ times 8 db 104, 24
+ times 8 db 96, 32
+ times 8 db 88, 40
+ times 8 db 80, 48
+ times 8 db 72, 56
+ times 8 db 64, 64
+ times 8 db 56, 72
+ times 8 db 48, 80
+ times 8 db 40, 88
+ times 8 db 32, 96
+ times 8 db 24, 104
+ times 8 db 16, 112
+ times 8 db 8, 120
+%else
vp8_bilinear_filters_ssse3:
times 8 db 128, 0
times 8 db 112, 16
@@ -362,3 +381,4 @@ vp8_bilinear_filters_ssse3:
times 8 db 48, 80
times 8 db 32, 96
times 8 db 16, 112
+%endif
diff --git a/vp8/encoder/x86/variance_mmx.c b/vp8/encoder/x86/variance_mmx.c
index 92b695f17..b84d00034 100644
--- a/vp8/encoder/x86/variance_mmx.c
+++ b/vp8/encoder/x86/variance_mmx.c
@@ -204,6 +204,27 @@ unsigned int vp8_variance8x16_mmx(
// the mmx function that does the bilinear filtering and var calculation //
// int one pass //
///////////////////////////////////////////////////////////////////////////
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+DECLARE_ALIGNED(16, const short, vp8_vp7_bilinear_filters_mmx[16][8]) =
+{
+ { 128, 128, 128, 128, 0, 0, 0, 0 },
+ { 120, 120, 120, 120, 8, 8, 8, 8 },
+ { 112, 112, 112, 112, 16, 16, 16, 16 },
+ { 104, 104, 104, 104, 24, 24, 24, 24 },
+ { 96, 96, 96, 96, 32, 32, 32, 32 },
+ { 88, 88, 88, 88, 40, 40, 40, 40 },
+ { 80, 80, 80, 80, 48, 48, 48, 48 },
+ { 72, 72, 72, 72, 56, 56, 56, 56 },
+ { 64, 64, 64, 64, 64, 64, 64, 64 },
+ { 56, 56, 56, 56, 72, 72, 72, 72 },
+ { 48, 48, 48, 48, 80, 80, 80, 80 },
+ { 40, 40, 40, 40, 88, 88, 88, 88 },
+ { 32, 32, 32, 32, 96, 96, 96, 96 },
+ { 24, 24, 24, 24, 104, 104, 104, 104 },
+ { 16, 16, 16, 16, 112, 112, 112, 112 },
+ { 8, 8, 8, 8, 120, 120, 120, 120 }
+};
+#else
DECLARE_ALIGNED(16, const short, vp8_vp7_bilinear_filters_mmx[8][8]) =
{
{ 128, 128, 128, 128, 0, 0, 0, 0 },
@@ -215,6 +236,7 @@ DECLARE_ALIGNED(16, const short, vp8_vp7_bilinear_filters_mmx[8][8]) =
{ 32, 32, 32, 32, 96, 96, 96, 96 },
{ 16, 16, 16, 16, 112, 112, 112, 112 }
};
+#endif
unsigned int vp8_sub_pixel_variance4x4_mmx
(
@@ -279,7 +301,6 @@ unsigned int vp8_sub_pixel_variance16x16_mmx
int xsum0, xsum1;
unsigned int xxsum0, xxsum1;
-
vp8_filter_block2d_bil_var_mmx(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
@@ -287,7 +308,6 @@ unsigned int vp8_sub_pixel_variance16x16_mmx
&xsum0, &xxsum0
);
-
vp8_filter_block2d_bil_var_mmx(
src_ptr + 8, src_pixels_per_line,
dst_ptr + 8, dst_pixels_per_line, 16,
@@ -386,8 +406,13 @@ unsigned int vp8_variance_halfpixvar16x16_h_mmx(
int recon_stride,
unsigned int *sse)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 8, 0,
+ ref_ptr, recon_stride, sse);
+#else
return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 4, 0,
ref_ptr, recon_stride, sse);
+#endif
}
@@ -398,8 +423,13 @@ unsigned int vp8_variance_halfpixvar16x16_v_mmx(
int recon_stride,
unsigned int *sse)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 0, 8,
+ ref_ptr, recon_stride, sse);
+#else
return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 0, 4,
ref_ptr, recon_stride, sse);
+#endif
}
@@ -410,6 +440,11 @@ unsigned int vp8_variance_halfpixvar16x16_hv_mmx(
int recon_stride,
unsigned int *sse)
{
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+ return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 8, 8,
+ ref_ptr, recon_stride, sse);
+#else
return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 4, 4,
ref_ptr, recon_stride, sse);
+#endif
}
diff --git a/vp8/encoder/x86/variance_sse2.c b/vp8/encoder/x86/variance_sse2.c
index 24062eb9b..e3c6268ea 100644
--- a/vp8/encoder/x86/variance_sse2.c
+++ b/vp8/encoder/x86/variance_sse2.c
@@ -13,6 +13,12 @@
#include "vp8/common/pragmas.h"
#include "vpx_ports/mem.h"
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define HALFNDX 8
+#else
+#define HALFNDX 4
+#endif
+
extern void filter_block1d_h6_mmx(const unsigned char *src_ptr, unsigned short *output_ptr, unsigned int src_pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
extern void filter_block1d_v6_mmx(const short *src_ptr, unsigned char *output_ptr, unsigned int pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
extern void filter_block1d8_h6_sse2(const unsigned char *src_ptr, unsigned short *output_ptr, unsigned int src_pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
@@ -135,7 +141,11 @@ void vp8_half_vert_variance16x_h_sse2
unsigned int *sumsquared
);
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+DECLARE_ALIGNED(16, extern short, vp8_vp7_bilinear_filters_mmx[16][8]);
+#else
DECLARE_ALIGNED(16, extern short, vp8_vp7_bilinear_filters_mmx[8][8]);
+#endif
unsigned int vp8_variance4x4_wmt(
const unsigned char *src_ptr,
@@ -284,21 +294,21 @@ unsigned int vp8_sub_pixel_variance8x8_wmt
int xsum;
unsigned int xxsum;
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
vp8_half_horiz_variance8x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 8,
&xsum, &xxsum);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
vp8_half_vert_variance8x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 8,
&xsum, &xxsum);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
vp8_half_horiz_vert_variance8x_h_sse2(
src_ptr, src_pixels_per_line,
@@ -335,21 +345,21 @@ unsigned int vp8_sub_pixel_variance16x16_wmt
// note we could avoid these if statements if the calling function
// just called the appropriate functions inside.
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
vp8_half_horiz_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
&xsum0, &xxsum0);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
vp8_half_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
&xsum0, &xxsum0);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
vp8_half_horiz_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
@@ -408,21 +418,21 @@ unsigned int vp8_sub_pixel_variance16x8_wmt
int xsum0, xsum1;
unsigned int xxsum0, xxsum1;
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
vp8_half_horiz_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 8,
&xsum0, &xxsum0);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
vp8_half_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 8,
&xsum0, &xxsum0);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
vp8_half_horiz_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
@@ -464,21 +474,21 @@ unsigned int vp8_sub_pixel_variance8x16_wmt
int xsum;
unsigned int xxsum;
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
vp8_half_horiz_variance8x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
&xsum, &xxsum);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
vp8_half_vert_variance8x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
&xsum, &xxsum);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
vp8_half_horiz_vert_variance8x_h_sse2(
src_ptr, src_pixels_per_line,
diff --git a/vp8/encoder/x86/variance_ssse3.c b/vp8/encoder/x86/variance_ssse3.c
index 73f2e01a2..fc2a3c3f2 100644
--- a/vp8/encoder/x86/variance_ssse3.c
+++ b/vp8/encoder/x86/variance_ssse3.c
@@ -13,6 +13,12 @@
#include "vp8/common/pragmas.h"
#include "vpx_ports/mem.h"
+#if CONFIG_SIXTEENTH_SUBPEL_UV
+#define HALFNDX 8
+#else
+#define HALFNDX 4
+#endif
+
extern unsigned int vp8_get16x16var_sse2
(
const unsigned char *src_ptr,
@@ -81,21 +87,21 @@ unsigned int vp8_sub_pixel_variance16x16_ssse3
// note we could avoid these if statements if the calling function
// just called the appropriate functions inside.
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
vp8_half_horiz_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
&xsum0, &xxsum0);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
vp8_half_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 16,
&xsum0, &xxsum0);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
vp8_half_horiz_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
@@ -130,21 +136,21 @@ unsigned int vp8_sub_pixel_variance16x8_ssse3
int xsum0;
unsigned int xxsum0;
- if (xoffset == 4 && yoffset == 0)
+ if (xoffset == HALFNDX && yoffset == 0)
{
vp8_half_horiz_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 8,
&xsum0, &xxsum0);
}
- else if (xoffset == 0 && yoffset == 4)
+ else if (xoffset == 0 && yoffset == HALFNDX)
{
vp8_half_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
dst_ptr, dst_pixels_per_line, 8,
&xsum0, &xxsum0);
}
- else if (xoffset == 4 && yoffset == 4)
+ else if (xoffset == HALFNDX && yoffset == HALFNDX)
{
vp8_half_horiz_vert_variance16x_h_sse2(
src_ptr, src_pixels_per_line,
diff --git a/vp8/encoder/x86/variance_x86.h b/vp8/encoder/x86/variance_x86.h
index 4b41b5436..0971f11b0 100644
--- a/vp8/encoder/x86/variance_x86.h
+++ b/vp8/encoder/x86/variance_x86.h
@@ -42,7 +42,6 @@ extern prototype_subpixvariance(vp8_sub_pixel_mse16x16_mmx);
extern prototype_getmbss(vp8_get_mb_ss_mmx);
extern prototype_variance(vp8_mse16x16_mmx);
extern prototype_variance2(vp8_get8x8var_mmx);
-extern prototype_get16x16prederror(vp8_get4x4sse_cs_mmx);
#if !CONFIG_RUNTIME_CPU_DETECT
#undef vp8_variance_sad4x4
@@ -108,9 +107,6 @@ extern prototype_get16x16prederror(vp8_get4x4sse_cs_mmx);
#undef vp8_variance_mse16x16
#define vp8_variance_mse16x16 vp8_mse16x16_mmx
-#undef vp8_variance_get4x4sse_cs
-#define vp8_variance_get4x4sse_cs vp8_get4x4sse_cs_mmx
-
#endif
#endif
diff --git a/vp8/encoder/x86/x86_csystemdependent.c b/vp8/encoder/x86/x86_csystemdependent.c
index 191d61c60..0c30e3707 100644
--- a/vp8/encoder/x86/x86_csystemdependent.c
+++ b/vp8/encoder/x86/x86_csystemdependent.c
@@ -9,7 +9,7 @@
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/x86.h"
#include "vp8/encoder/variance.h"
#include "vp8/encoder/onyx_int.h"
@@ -152,8 +152,6 @@ void vp8_arch_x86_encoder_init(VP8_COMP *cpi)
cpi->rtcd.variance.mse16x16 = vp8_mse16x16_mmx;
cpi->rtcd.variance.getmbss = vp8_get_mb_ss_mmx;
- cpi->rtcd.variance.get4x4sse_cs = vp8_get4x4sse_cs_mmx;
-
cpi->rtcd.fdct.short4x4 = vp8_short_fdct4x4_mmx;
cpi->rtcd.fdct.short8x4 = vp8_short_fdct8x4_mmx;
cpi->rtcd.fdct.fast4x4 = vp8_short_fdct4x4_mmx;
@@ -201,8 +199,6 @@ void vp8_arch_x86_encoder_init(VP8_COMP *cpi)
cpi->rtcd.variance.mse16x16 = vp8_mse16x16_wmt;
cpi->rtcd.variance.getmbss = vp8_get_mb_ss_sse2;
- /* cpi->rtcd.variance.get4x4sse_cs not implemented for wmt */;
-
cpi->rtcd.fdct.short4x4 = vp8_short_fdct4x4_sse2;
cpi->rtcd.fdct.short8x4 = vp8_short_fdct8x4_sse2;
cpi->rtcd.fdct.fast4x4 = vp8_short_fdct4x4_sse2;
@@ -217,12 +213,8 @@ void vp8_arch_x86_encoder_init(VP8_COMP *cpi)
cpi->rtcd.encodemb.submby = vp8_subtract_mby_sse2;
cpi->rtcd.encodemb.submbuv = vp8_subtract_mbuv_sse2;
- cpi->rtcd.quantize.quantb = vp8_regular_quantize_b_sse2;
cpi->rtcd.quantize.fastquantb = vp8_fast_quantize_b_sse2;
-
-#if !(CONFIG_REALTIME_ONLY)
cpi->rtcd.temporal.apply = vp8_temporal_filter_apply_sse2;
-#endif
#if CONFIG_INTERNAL_STATS
#if ARCH_X86_64
@@ -278,8 +270,6 @@ void vp8_arch_x86_encoder_init(VP8_COMP *cpi)
cpi->rtcd.variance.sad8x8x8 = vp8_sad8x8x8_sse4;
cpi->rtcd.variance.sad4x4x8 = vp8_sad4x4x8_sse4;
cpi->rtcd.search.full_search = vp8_full_search_sadx8;
-
- cpi->rtcd.quantize.quantb = vp8_regular_quantize_b_sse4;
}
#endif
diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk
index f7fbea1f4..de645eb8a 100644
--- a/vp8/vp8_common.mk
+++ b/vp8/vp8_common.mk
@@ -19,7 +19,6 @@ VP8_COMMON_SRCS-yes += common/asm_com_offsets.c
VP8_COMMON_SRCS-yes += common/blockd.c
VP8_COMMON_SRCS-yes += common/coefupdateprobs.h
VP8_COMMON_SRCS-yes += common/debugmodes.c
-VP8_COMMON_SRCS-yes += common/default_coef_probs.h
VP8_COMMON_SRCS-yes += common/entropy.c
VP8_COMMON_SRCS-yes += common/entropymode.c
VP8_COMMON_SRCS-yes += common/entropymv.c
@@ -33,6 +32,7 @@ VP8_COMMON_SRCS-yes += common/alloccommon.h
VP8_COMMON_SRCS-yes += common/blockd.h
VP8_COMMON_SRCS-yes += common/common.h
VP8_COMMON_SRCS-yes += common/common_types.h
+VP8_COMMON_SRCS-yes += common/defaultcoefcounts.h
VP8_COMMON_SRCS-yes += common/entropy.h
VP8_COMMON_SRCS-yes += common/entropymode.h
VP8_COMMON_SRCS-yes += common/entropymv.h
@@ -46,16 +46,19 @@ VP8_COMMON_SRCS-yes += common/loopfilter.h
VP8_COMMON_SRCS-yes += common/modecont.h
VP8_COMMON_SRCS-yes += common/mv.h
VP8_COMMON_SRCS-yes += common/onyxc_int.h
+VP8_COMMON_SRCS-yes += common/pred_common.h
+VP8_COMMON_SRCS-yes += common/pred_common.c
VP8_COMMON_SRCS-yes += common/quant_common.h
VP8_COMMON_SRCS-yes += common/recon.h
VP8_COMMON_SRCS-yes += common/reconinter.h
VP8_COMMON_SRCS-yes += common/reconintra.h
VP8_COMMON_SRCS-yes += common/reconintra4x4.h
+VP8_COMMON_SRCS-yes += common/seg_common.h
+VP8_COMMON_SRCS-yes += common/seg_common.c
VP8_COMMON_SRCS-yes += common/setupintrarecon.h
VP8_COMMON_SRCS-yes += common/subpixel.h
VP8_COMMON_SRCS-yes += common/swapyv12buffer.h
VP8_COMMON_SRCS-yes += common/systemdependent.h
-VP8_COMMON_SRCS-yes += common/threading.h
VP8_COMMON_SRCS-yes += common/treecoder.h
VP8_COMMON_SRCS-yes += common/invtrans.c
VP8_COMMON_SRCS-yes += common/loopfilter.c
@@ -72,6 +75,10 @@ VP8_COMMON_SRCS-yes += common/setupintrarecon.c
VP8_COMMON_SRCS-yes += common/swapyv12buffer.c
VP8_COMMON_SRCS-$(CONFIG_POSTPROC_VISUALIZER) += common/textblit.c
VP8_COMMON_SRCS-yes += common/treecoder.c
+VP8_COMMON_SRCS-yes += common/implicit_segmentation.c
+VP8_COMMON_SRCS-yes += common/predict_rotated.c
+VP8_COMMON_SRCS-yes += common/rotate.h
+VP8_COMMON_SRCS-yes += common/rotate2.h
VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/idct_x86.h
VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/subpixel_x86.h
@@ -101,6 +108,11 @@ VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/postproc_sse2.asm
endif
# common (c)
+ifeq ($(CONFIG_CSM),yes)
+VP8_COMMON_SRCS-yes += common/maskingmv.c
+VP8_COMMON_SRCS-$(HAVE_SSE3) += common/x86/mask_sse3.asm
+endif
+
VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/arm_systemdependent.c
VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/bilinearfilter_arm.c
VP8_COMMON_SRCS-$(ARCH_ARM) += common/arm/bilinearfilter_arm.h
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
index 9f703a3c4..4f34569e0 100644
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -56,13 +56,8 @@ static const struct extraconfig_map extracfg_map[] =
0,
{
NULL,
-#if !(CONFIG_REALTIME_ONLY)
VP8_BEST_QUALITY_ENCODING, /* Encoding Mode */
0, /* cpu_used */
-#else
- VP8_REAL_TIME_ENCODING, /* Encoding Mode */
- 4, /* cpu_used */
-#endif
0, /* enable_auto_alt_ref */
0, /* noise_sensitivity */
0, /* Sharpness */
@@ -149,11 +144,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
RANGE_CHECK_HI(cfg, g_threads, 64);
-#if !(CONFIG_REALTIME_ONLY)
RANGE_CHECK_HI(cfg, g_lag_in_frames, 25);
-#else
- RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
-#endif
RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_CQ);
RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
@@ -164,11 +155,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
-#if !(CONFIG_REALTIME_ONLY)
RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
-#else
- RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
-#endif
/* VP8 does not support a lower bound on the keyframe interval in
* automatic keyframe placement mode.
@@ -181,13 +168,8 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
-#if !(CONFIG_REALTIME_ONLY)
RANGE_CHECK(vp8_cfg, encoding_mode, VP8_BEST_QUALITY_ENCODING, VP8_REAL_TIME_ENCODING);
RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
-#else
- RANGE_CHECK(vp8_cfg, encoding_mode, VP8_REAL_TIME_ENCODING, VP8_REAL_TIME_ENCODING);
- RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0);
-#endif
RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION, VP8_EIGHT_TOKENPARTITION);
RANGE_CHECK_HI(vp8_cfg, Sharpness, 7);
@@ -196,7 +178,6 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
-#if !(CONFIG_REALTIME_ONLY)
if (cfg->g_pass == VPX_RC_LAST_PASS)
{
size_t packet_sz = sizeof(FIRSTPASS_STATS);
@@ -218,7 +199,6 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
if ((int)(stats->count + 0.5) != n_packets - 1)
ERROR("rc_twopass_stats_in missing EOS stats packet");
}
-#endif
return VPX_CODEC_OK;
}
@@ -249,7 +229,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
vpx_codec_enc_cfg_t cfg,
struct vp8_extracfg vp8_cfg)
{
- oxcf->multi_threaded = cfg.g_threads;
oxcf->Version = cfg.g_profile;
oxcf->Version |= vp8_cfg.experimental? 0x4 : 0;
@@ -263,8 +242,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->frame_rate = 30;
}
- oxcf->error_resilient_mode = cfg.g_error_resilient;
-
switch (cfg.g_pass)
{
case VPX_RC_ONE_PASS:
@@ -289,25 +266,14 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->lag_in_frames = cfg.g_lag_in_frames;
}
- oxcf->allow_df = (cfg.rc_dropframe_thresh > 0);
- oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh;
-
- oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
- oxcf->resample_up_water_mark = cfg.rc_resize_up_thresh;
- oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;
-
- if (cfg.rc_end_usage == VPX_VBR)
- {
- oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
- }
- else if (cfg.rc_end_usage == VPX_CBR)
- {
- oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
- }
- else if (cfg.rc_end_usage == VPX_CQ)
- {
- oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
- }
+ // VBR only supported for now.
+ // CBR code has been deprectated for experimental phase.
+ // CQ mode not yet tested
+ oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
+ /*if (cfg.rc_end_usage == VPX_CQ)
+ oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
+ else
+ oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;*/
oxcf->target_bandwidth = cfg.rc_target_bitrate;
oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
@@ -341,7 +307,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
oxcf->Sharpness = vp8_cfg.Sharpness;
- oxcf->token_partitions = vp8_cfg.token_partitions;
oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
oxcf->output_pkt_list = vp8_cfg.pkt_list;
@@ -371,11 +336,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
printf("fixed_q: %d\n", oxcf->fixed_q);
printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
- printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
- printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
- printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
- printf("allow_df: %d\n", oxcf->allow_df);
- printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
@@ -383,7 +343,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
printf("play_alternate: %d\n", oxcf->play_alternate);
printf("Version: %d\n", oxcf->Version);
- printf("multi_threaded: %d\n", oxcf->multi_threaded);
printf("encode_breakout: %d\n", oxcf->encode_breakout);
*/
return VPX_CODEC_OK;
@@ -618,41 +577,11 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
{
unsigned int new_qc;
-#if !(CONFIG_REALTIME_ONLY)
/* Use best quality mode if no deadline is given. */
- new_qc = MODE_BESTQUALITY;
-
if (deadline)
- {
- uint64_t duration_us;
-
- /* Convert duration parameter from stream timebase to microseconds */
- duration_us = (uint64_t)duration * 1000000
- * (uint64_t)ctx->cfg.g_timebase.num
- / (uint64_t)ctx->cfg.g_timebase.den;
-
- /* If the deadline is more that the duration this frame is to be shown,
- * use good quality mode. Otherwise use realtime mode.
- */
- new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
- }
-
-#else
- new_qc = MODE_REALTIME;
-#endif
-
- switch (ctx->deprecated_mode)
- {
- case VP8_BEST_QUALITY_ENCODING:
- new_qc = MODE_BESTQUALITY;
- break;
- case VP8_GOOD_QUALITY_ENCODING:
new_qc = MODE_GOODQUALITY;
- break;
- case VP8_REAL_TIME_ENCODING:
- new_qc = MODE_REALTIME;
- break;
- }
+ else
+ new_qc = MODE_BESTQUALITY;
if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
new_qc = MODE_FIRSTPASS;
@@ -756,8 +685,8 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
- if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
- ((VP8_COMP *)ctx->cpi)->output_partition = 1;
+ //if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
+ // ((VP8_COMP *)ctx->cpi)->output_partition = 1;
/* Convert API flags to internal codec lib flags */
lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
@@ -826,11 +755,10 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
if (cpi->droppable)
pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
- if (cpi->output_partition)
+ /*if (cpi->output_partition)
{
int i;
- const int num_partitions =
- (1 << cpi->common.multi_token_partition) + 1;
+ const int num_partitions = 1;
pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
@@ -839,7 +767,7 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
pkt.data.frame.buf = cx_data;
pkt.data.frame.sz = cpi->partition_sz[i];
pkt.data.frame.partition_id = i;
- /* don't set the fragment bit for the last partition */
+ // don't set the fragment bit for the last partition
if (i == (num_partitions - 1))
pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
@@ -847,7 +775,7 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
cx_data_sz -= cpi->partition_sz[i];
}
}
- else
+ else*/
{
pkt.data.frame.buf = cx_data;
pkt.data.frame.sz = size;
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index ad8cd5e95..e59c877a1 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -19,9 +19,6 @@
#include "decoder/onyxd_int.h"
#define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
-#define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \
- VPX_CODEC_CAP_ERROR_CONCEALMENT : 0)
-
typedef vpx_codec_stream_info_t vp8_stream_info_t;
/* Structures for handling memory allocations */
@@ -396,11 +393,6 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
oxcf.Version = 9;
oxcf.postprocess = 0;
oxcf.max_threads = ctx->cfg.threads;
- oxcf.error_concealment =
- (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT);
- oxcf.input_partition =
- (ctx->base.init_flags & VPX_CODEC_USE_INPUT_PARTITION);
-
optr = vp8dx_create_decompressor(&oxcf);
/* If postprocessing was enabled by the application and a
@@ -740,7 +732,7 @@ CODEC_INTERFACE(vpx_codec_vp8_dx) =
{
"WebM Project VP8 Decoder" VERSION_STRING,
VPX_CODEC_INTERNAL_ABI_VERSION,
- VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT |
+ VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC |
VPX_CODEC_CAP_INPUT_PARTITION,
/* vpx_codec_caps_t caps; */
vp8_init, /* vpx_codec_init_fn_t init; */
@@ -771,7 +763,7 @@ vpx_codec_iface_t vpx_codec_vp8_algo =
{
"WebM Project VP8 Decoder (Deprecated API)" VERSION_STRING,
VPX_CODEC_INTERNAL_ABI_VERSION,
- VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT,
+ VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC,
/* vpx_codec_caps_t caps; */
vp8_init, /* vpx_codec_init_fn_t init; */
vp8_destroy, /* vpx_codec_destroy_fn_t destroy; */
diff --git a/vp8/vp8cx.mk b/vp8/vp8cx.mk
index b71a54aea..113490237 100644
--- a/vp8/vp8cx.mk
+++ b/vp8/vp8cx.mk
@@ -34,7 +34,6 @@ VP8_CX_SRCS-yes += vp8_cx_iface.c
#INCLUDES += encoder
VP8_CX_SRCS-yes += encoder/asm_enc_offsets.c
-VP8_CX_SRCS-yes += encoder/defaultcoefcounts.h
VP8_CX_SRCS-yes += encoder/bitstream.c
VP8_CX_SRCS-yes += encoder/boolhuff.c
VP8_CX_SRCS-yes += encoder/dct.c
@@ -42,7 +41,6 @@ VP8_CX_SRCS-yes += encoder/encodeframe.c
VP8_CX_SRCS-yes += encoder/encodeintra.c
VP8_CX_SRCS-yes += encoder/encodemb.c
VP8_CX_SRCS-yes += encoder/encodemv.c
-VP8_CX_SRCS-$(CONFIG_MULTITHREAD) += encoder/ethreading.c
VP8_CX_SRCS-yes += encoder/firstpass.c
VP8_CX_SRCS-yes += encoder/generic/csystemdependent.c
VP8_CX_SRCS-yes += encoder/block.h
@@ -58,7 +56,6 @@ VP8_CX_SRCS-yes += encoder/lookahead.h
VP8_CX_SRCS-yes += encoder/mcomp.h
VP8_CX_SRCS-yes += encoder/modecosts.h
VP8_CX_SRCS-yes += encoder/onyx_int.h
-VP8_CX_SRCS-yes += encoder/pickinter.h
VP8_CX_SRCS-yes += encoder/psnr.h
VP8_CX_SRCS-yes += encoder/quantize.h
VP8_CX_SRCS-yes += encoder/ratectrl.h
@@ -69,13 +66,13 @@ VP8_CX_SRCS-yes += encoder/variance.h
VP8_CX_SRCS-yes += encoder/mcomp.c
VP8_CX_SRCS-yes += encoder/modecosts.c
VP8_CX_SRCS-yes += encoder/onyx_if.c
-VP8_CX_SRCS-yes += encoder/pickinter.c
VP8_CX_SRCS-yes += encoder/picklpf.c
VP8_CX_SRCS-yes += encoder/psnr.c
VP8_CX_SRCS-yes += encoder/quantize.c
VP8_CX_SRCS-yes += encoder/ratectrl.c
VP8_CX_SRCS-yes += encoder/rdopt.c
VP8_CX_SRCS-yes += encoder/sad_c.c
+VP8_CX_SRCS-yes += encoder/satd_c.c
VP8_CX_SRCS-yes += encoder/segmentation.c
VP8_CX_SRCS-yes += encoder/segmentation.h
VP8_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/ssim.c
@@ -86,11 +83,10 @@ VP8_CX_SRCS-$(CONFIG_INTERNAL_STATS) += common/postproc.h
VP8_CX_SRCS-$(CONFIG_INTERNAL_STATS) += common/postproc.c
VP8_CX_SRCS-yes += encoder/temporal_filter.c
VP8_CX_SRCS-yes += encoder/temporal_filter.h
+VP8_CX_SRCS-yes += encoder/find_rotation.c
+VP8_CX_SRCS-yes += encoder/mbgraph.c
+VP8_CX_SRCS-yes += encoder/mbgraph.h
-ifeq ($(CONFIG_REALTIME_ONLY),yes)
-VP8_CX_SRCS_REMOVE-yes += encoder/firstpass.c
-VP8_CX_SRCS_REMOVE-yes += encoder/temporal_filter.c
-endif
VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodemb_x86.h
VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/dct_x86.h
@@ -123,9 +119,5 @@ VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/quantize_mmx.asm
VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodeopt.asm
VP8_CX_SRCS-$(ARCH_X86_64) += encoder/x86/ssim_opt.asm
-ifeq ($(CONFIG_REALTIME_ONLY),yes)
-VP8_CX_SRCS_REMOVE-$(HAVE_SSE2) += encoder/x86/temporal_filter_apply_sse2.asm
-endif
-
VP8_CX_SRCS-yes := $(filter-out $(VP8_CX_SRCS_REMOVE-yes),$(VP8_CX_SRCS-yes))
diff --git a/vp8/vp8dx.mk b/vp8/vp8dx.mk
index d88b595fb..5de493ddc 100644
--- a/vp8/vp8dx.mk
+++ b/vp8/vp8dx.mk
@@ -54,22 +54,15 @@ VP8_DX_SRCS-yes += decoder/decodemv.c
VP8_DX_SRCS-yes += decoder/decodframe.c
VP8_DX_SRCS-yes += decoder/dequantize.c
VP8_DX_SRCS-yes += decoder/detokenize.c
-VP8_DX_SRCS-$(CONFIG_ERROR_CONCEALMENT) += decoder/ec_types.h
-VP8_DX_SRCS-$(CONFIG_ERROR_CONCEALMENT) += decoder/error_concealment.h
-VP8_DX_SRCS-$(CONFIG_ERROR_CONCEALMENT) += decoder/error_concealment.c
VP8_DX_SRCS-yes += decoder/generic/dsystemdependent.c
VP8_DX_SRCS-yes += decoder/dboolhuff.h
VP8_DX_SRCS-yes += decoder/decodemv.h
-VP8_DX_SRCS-yes += decoder/decoderthreading.h
VP8_DX_SRCS-yes += decoder/dequantize.h
VP8_DX_SRCS-yes += decoder/detokenize.h
VP8_DX_SRCS-yes += decoder/onyxd_int.h
VP8_DX_SRCS-yes += decoder/treereader.h
VP8_DX_SRCS-yes += decoder/onyxd_if.c
-VP8_DX_SRCS-$(CONFIG_MULTITHREAD) += decoder/threading.c
VP8_DX_SRCS-yes += decoder/idct_blk.c
-VP8_DX_SRCS-$(CONFIG_MULTITHREAD) += decoder/reconintra_mt.h
-VP8_DX_SRCS-$(CONFIG_MULTITHREAD) += decoder/reconintra_mt.c
VP8_DX_SRCS-yes := $(filter-out $(VP8_DX_SRCS_REMOVE-yes),$(VP8_DX_SRCS-yes))