${toggle_internal_stats} output of encoder internal stats for debug, if supported (encoders)
${toggle_mem_tracker} track memory usage
${toggle_postproc} postprocessing
- ${toggle_multithread} multithreaded encoding and decoding.
${toggle_spatial_resampling} spatial sampling (scaling) support
- ${toggle_realtime_only} enable this option while building for real-time encoding
- ${toggle_error_concealment} enable this option to get a decoder which is able to conceal losses
${toggle_runtime_cpu_detect} runtime cpu detection
${toggle_shared} shared library support
${toggle_static} static library support
enable fast_unaligned #allow unaligned accesses, if supported by hw
enable md5
enable spatial_resampling
-enable multithread
enable os_support
[ -d ${source_path}/../include ] && enable alt_tree_layout
unistd_h
"
EXPERIMENT_LIST="
- extend_qrange
+ t8x8
+ csm
+ qimode
+ uvintra
+ compred
+ enhanced_interp
+ featureupdates
+ high_precision_mv
+ sixteenth_subpel_uv
+ comp_intra_pred
"
CONFIG_LIST="
external_build
dc_recon
runtime_cpu_detect
postproc
- multithread
internal_stats
${CODECS}
${CODEC_FAMILIES}
decoders
static_msvcrt
spatial_resampling
- realtime_only
- error_concealment
shared
static
small
dequant_tokens
dc_recon
postproc
- multithread
internal_stats
${CODECS}
${CODEC_FAMILIES}
static_msvcrt
mem_tracker
spatial_resampling
- realtime_only
- error_concealment
shared
static
small
enabled debug_libs && DIST_DIR="${DIST_DIR}-debug"
enabled codec_srcs && DIST_DIR="${DIST_DIR}-src"
! enabled postproc && DIST_DIR="${DIST_DIR}-nopost"
- ! enabled multithread && DIST_DIR="${DIST_DIR}-nomt"
! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs"
DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}"
case "${tgt_os}" in
vpxdec.SRCS += md5_utils.c md5_utils.h
vpxdec.SRCS += vpx_ports/vpx_timer.h
vpxdec.SRCS += vpx/vpx_integer.h
-vpxdec.SRCS += args.c args.h
+vpxdec.SRCS += args.c args.h vpx_ports/config.h
vpxdec.SRCS += tools_common.c tools_common.h
vpxdec.SRCS += nestegg/halloc/halloc.h
vpxdec.SRCS += nestegg/halloc/src/align.h
UTILS-$(CONFIG_ENCODERS) += vpxenc.c
vpxenc.SRCS += args.c args.h y4minput.c y4minput.h
vpxenc.SRCS += tools_common.c tools_common.h
-vpxenc.SRCS += vpx_ports/mem_ops.h
+vpxenc.SRCS += vpx_ports/config.h vpx_ports/mem_ops.h
vpxenc.SRCS += vpx_ports/mem_ops_aligned.h
vpxenc.SRCS += libmkv/EbmlIDs.h
vpxenc.SRCS += libmkv/EbmlWriter.c
endif
decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
decode_with_drops.DESCRIPTION = Drops frames while decoding
-ifeq ($(CONFIG_DECODERS),yes)
-GEN_EXAMPLES-$(CONFIG_ERROR_CONCEALMENT) += decode_with_partial_drops.c
-endif
-decode_with_partial_drops.GUID = 61C2D026-5754-46AC-916F-1343ECC5537E
-decode_with_partial_drops.DESCRIPTION = Drops parts of frames while decoding
GEN_EXAMPLES-$(CONFIG_ENCODERS) += error_resilient.c
error_resilient.GUID = DF5837B9-4145-4F92-A031-44E4F832E00C
error_resilient.DESCRIPTION = Error Resiliency Feature
+++ /dev/null
-@TEMPLATE decoder_tmpl.c
-Decode With Partial Drops Example
-=========================
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
-This is an example utility which drops a series of frames (or parts of frames),
-as specified on the command line. This is useful for observing the error
-recovery features of the codec.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
-#include <time.h>
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
-struct parsed_header
-{
- char key_frame;
- int version;
- char show_frame;
- int first_part_size;
-};
-
-int next_packet(struct parsed_header* hdr, int pos, int length, int mtu)
-{
- int size = 0;
- int remaining = length - pos;
- /* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */
- int uncomp_part_size = (hdr->key_frame ? 10 : 3);
- /* number of bytes yet to send from header and the first partition */
- int remainFirst = uncomp_part_size + hdr->first_part_size - pos;
- if (remainFirst > 0)
- {
- if (remainFirst <= mtu)
- {
- size = remainFirst;
- }
- else
- {
- size = mtu;
- }
-
- return size;
- }
-
- /* second partition; just slot it up according to MTU */
- if (remaining <= mtu)
- {
- size = remaining;
- return size;
- }
- return mtu;
-}
-
-void throw_packets(unsigned char* frame, int* size, int loss_rate,
- int* thrown, int* kept)
-{
- unsigned char loss_frame[256*1024];
- int pkg_size = 1;
- int pos = 0;
- int loss_pos = 0;
- struct parsed_header hdr;
- unsigned int tmp;
- int mtu = 1500;
-
- if (*size < 3)
- {
- return;
- }
- putc('|', stdout);
- /* parse uncompressed 3 bytes */
- tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0];
- hdr.key_frame = !(tmp & 0x1); /* inverse logic */
- hdr.version = (tmp >> 1) & 0x7;
- hdr.show_frame = (tmp >> 4) & 0x1;
- hdr.first_part_size = (tmp >> 5) & 0x7FFFF;
-
- /* don't drop key frames */
- if (hdr.key_frame)
- {
- int i;
- *kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */
- for (i=0; i < *kept; i++)
- putc('.', stdout);
- return;
- }
-
- while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0)
- {
- int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0);
- if (*thrown == 0 && !loss_event)
- {
- memcpy(loss_frame + loss_pos, frame + pos, pkg_size);
- loss_pos += pkg_size;
- (*kept)++;
- putc('.', stdout);
- }
- else
- {
- (*thrown)++;
- putc('X', stdout);
- }
- pos += pkg_size;
- }
- memcpy(frame, loss_frame, loss_pos);
- memset(frame + loss_pos, 0, *size - loss_pos);
- *size = loss_pos;
-}
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
-/* Initialize codec */
-flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
-res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
-if(res)
- die_codec(&codec, "Failed to initialize decoder");
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
-
-Usage
------
-This example adds a single argument to the `simple_decoder` example,
-which specifies the range or pattern of frames to drop. The parameter is
-parsed as follows:
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
-if(argc < 4 || argc > 6)
- die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
- argv[0]);
-{
- char *nptr;
- int arg_num = 3;
- if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
- dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
- n = strtol(argv[arg_num], &nptr, 0);
- mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
-
- m = strtol(nptr+1, NULL, 0);
- if((!n && !m) || (*nptr != '-' && *nptr != '/' &&
- *nptr != '\0' && *nptr != ','))
- die("Couldn't parse pattern %s\n", argv[3]);
-}
-seed = (m > 0) ? m : (unsigned int)time(NULL);
-srand(seed);thrown_frame = 0;
-printf("Seed: %u\n", seed);
-printf("Threads: %d\n", dec_cfg.threads);
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
-
-
-Dropping A Range Of Frames
---------------------------
-To drop a range of frames, specify the starting frame and the ending
-frame to drop, separated by a dash. The following command will drop
-frames 5 through 10 (base 1).
-
- $ ./decode_with_partial_drops in.ivf out.i420 5-10
-
-
-Dropping A Pattern Of Frames
-----------------------------
-To drop a pattern of frames, specify the number of frames to drop and
-the number of frames after which to repeat the pattern, separated by
-a forward-slash. The following command will drop 3 of 7 frames.
-Specifically, it will decode 4 frames, then drop 3 frames, and then
-repeat.
-
- $ ./decode_with_partial_drops in.ivf out.i420 3/7
-
-Dropping Random Parts Of Frames
--------------------------------
-A third argument tuple is available to split the frame into 1500 bytes pieces
-and randomly drop pieces rather than frames. The frame will be split at
-partition boundaries where possible. The following example will seed the RNG
-with the seed 123 and drop approximately 5% of the pieces. Pieces which
-are depending on an already dropped piece will also be dropped.
-
- $ ./decode_with_partial_drops in.ivf out.i420 5,123
-
-
-Extra Variables
----------------
-This example maintains the pattern passed on the command line in the
-`n`, `m`, and `is_range` variables:
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
-int n, m, mode;
-unsigned int seed;
-int thrown=0, kept=0;
-int thrown_frame=0, kept_frame=0;
-vpx_codec_dec_cfg_t dec_cfg = {0};
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
-
-
-Making The Drop Decision
-------------------------
-The example decides whether to drop the frame based on the current
-frame number, immediately before decoding the frame.
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
-/* Decide whether to throw parts of the frame or the whole frame
- depending on the drop mode */
-thrown_frame = 0;
-kept_frame = 0;
-switch (mode)
-{
-case 0:
- if (m - (frame_cnt-1)%m <= n)
- {
- frame_sz = 0;
- }
- break;
-case 1:
- if (frame_cnt >= n && frame_cnt <= m)
- {
- frame_sz = 0;
- }
- break;
-case 2:
- throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame);
- break;
-default: break;
-}
-if (mode < 2)
-{
- if (frame_sz == 0)
- {
- putc('X', stdout);
- thrown_frame++;
- }
- else
- {
- putc('.', stdout);
- kept_frame++;
- }
-}
-thrown += thrown_frame;
-kept += kept_frame;
-fflush(stdout);
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "blockd.h"
#include "vpx_mem/vpx_mem.h"
#include "onyxc_int.h"
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
}
}
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)
}
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);
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;
}
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:
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)
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;
/* 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)
*/
-#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"
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include <math.h>
#include "vp8/common/filter.h"
#include "vp8/common/subpixel.h"
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/recon.h"
#include "vp8/common/blockd.h"
*/
-#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"
#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
{
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
+};
+
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
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,
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,
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)
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;
};
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
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;
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;
/* 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;
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;
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 */
},
},
};
+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, },
+ },
+ },
+
+};
#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"
#define vp8_zero_array( Dest, N) vpx_memset( Dest, 0, N * sizeof( *Dest));
-
#endif /* common_h */
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 ");
--- /dev/null
+/*
+ * 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}
+ }
+ }
+ };
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]) =
{
};
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 */
{
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)
};
#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()
#include "treecoder.h"
#include "blockd.h"
-
+#include "common.h"
/* Coefficient token alphabet */
#define ZERO_TOKEN 0 /* 0 Extra Bits 0+0 */
#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 */
#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
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
*/
+#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] =
{
/* 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,
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] =
{
-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 */
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));
+
}
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,
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");
+ }
}
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[];
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];
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]);
#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] =
{
{{
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 */
-
}}
};
#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 */
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
#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 },
{ 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]) =
{
{ 0, -1, 12, 123, -6, 0 },
};
+#endif // CONFIG_ENHANCED_INTERP
+
static void filter_block2d_first_pass
(
unsigned char *src_ptr,
{
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;
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;
}
}
+/*
+ * 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
(
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);
}
{
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,
{
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);
}
{
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);
+}
/****************************************************************************
*
}
}
+/*
+ * 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;
+ }
+}
/****************************************************************************
*
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
(
}
+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,
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);
+}
* 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
/* 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,
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;
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;
}
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
/* 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])
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;
}
-
#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)
(
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]
);
--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:
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))
{
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:
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
*/
-#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"
#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
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;
#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 */
}
#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
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
* 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;
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;
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;
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++)
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;
}
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++)
{
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;
+}
+
--- /dev/null
+/*
+ * 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");
+ }
+}
+
}
}
+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);
}
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 */
}
}
+
+
+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);
+ }
+
+}
+
#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);
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
#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);
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)
{
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)
{
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;
}
void vp8_loop_filter_frame_init(VP8_COMMON *cm,
- MACROBLOCKD *mbd,
+ MACROBLOCKD *xd,
int default_filt_lvl)
{
int seg, /* segment number */
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
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;
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;
void vp8_loop_filter_frame
(
VP8_COMMON *cm,
- MACROBLOCKD *mbd
+ MACROBLOCKD *xd
)
{
YV12_BUFFER_CONFIG *post = cm->frame_to_show;
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;
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)
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
{
void vp8_loop_filter_frame_yonly
(
VP8_COMMON *cm,
- MACROBLOCKD *mbd,
+ MACROBLOCKD *xd,
int default_filt_lvl
)
{
#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;
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];
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
{
}
}
+#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
)
{
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;
{
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;
}
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);
#include "vpx_ports/mem.h"
#include "vpx_config.h"
+#include "blockd.h"
#define MAX_LOOP_FILTER 63
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
#include <stdlib.h>
+#include "vpx_config.h"
#include "loopfilter.h"
#include "onyxc_int.h"
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]);
}
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,
{
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
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;
}
{
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);
}
/* 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'
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;
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);
--- /dev/null
+/*
+ ============================================================================
+ 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;
+}
#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},
};
#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
typedef enum
{
- MODE_REALTIME = 0x0,
MODE_GOODQUALITY = 0x1,
MODE_BESTQUALITY = 0x2,
MODE_FIRSTPASS = 0x3,
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;
// 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 ;
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,
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
/* 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;
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;
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
#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
int Version;
int postprocess;
int max_threads;
- int error_concealment;
int input_partition;
} VP8D_CONFIG;
typedef enum
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_scale/yv12config.h"
#include "postproc.h"
#include "vpx_scale/yv12extend.h"
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);
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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
+
+
+
+
#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)
{
QIndex = QIndex + Delta;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
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;
}
QIndex = QIndex + Delta;
- if (QIndex > 117)
- QIndex = 117;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
{
int retval;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
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)
QIndex = QIndex + Delta;
- if (QIndex > 127)
- QIndex = 127;
+ if (QIndex > MAXQ)
+ QIndex = MAXQ;
else if (QIndex < 0)
QIndex = 0;
#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);
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "recon.h"
#include "blockd.h"
}
}
+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,
#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
#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
#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
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
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
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx/vpx_integer.h"
#include "recon.h"
#include "subpixel.h"
}
+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,
}
+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,
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
{
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
{
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
{
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;
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);
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
{
* 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,
unsigned char *ptr;
unsigned char *uptr, *vptr;
+ int_mv _o16x16mv;
int_mv _16x16mv;
unsigned char *ptr_base = x->pre.y_buffer;
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;
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)
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);
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);
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);
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
x->block[uoffset].bmi.mv.as_mv.col = (temp / 8) & x->fullpixel_mask;
+ 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);
{
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
{
build_inter4x4_predictors_mb(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);
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "recon.h"
#include "reconintra.h"
#include "vpx_mem/vpx_mem.h"
}
}
-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++)
}
/* for Y */
- switch (x->mode_info_context->mbmi.mode)
+ switch (mode)
{
case DC_PRED:
{
{
average += yleft_col[i];
}
-
}
-
-
-
shift = 3 + x->up_available + x->left_available;
expected_dc = (average + (1 << (shift - 1))) >> shift;
}
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:
((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;
{
vpx_memset(ypred_ptr, yleft_col[r], 16);
- ypred_ptr += 16;
+ ypred_ptr += y_stride;
}
}
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:
}
}
-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];
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++)
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:
{
}
- 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:
{
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;*/
}
}
{
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;*/
}
}
vpred_ptr[j] = predv;
}
- upred_ptr += 8;
- vpred_ptr += 8;
+ upred_ptr += uv_stride; /*8;*/
+ vpred_ptr += uv_stride; /*8;*/
}
}
}
}
+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
+ */
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "recon.h"
#include "vpx_mem/vpx_mem.h"
#include "reconintra.h"
}
}
+
+#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.
*/
--- /dev/null
+ // 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
--- /dev/null
+ // 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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__ */
+
#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
#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
{
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;
*/
-#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()
--- /dev/null
+"""
+ * 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
+"""
+++ /dev/null
-/*
- * 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
--- /dev/null
+;
+; 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
+
* 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"
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
*/
-#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
(
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];
)
{
+#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;
)
{
+#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;
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;
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)
{
{
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)
{
{
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)
{
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 24*24);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict16x16_ssse3\n");
+#endif
if (xoffset)
{
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 256);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x8_ssse3\n");
+#endif
if (xoffset)
{
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 256);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict8x4_ssse3\n");
+#endif
if (xoffset)
{
)
{
DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 4*9);
+#ifdef ANNOUNCE_FUNCTION
+ printf("vp8_sixtap_predict4x4_ssse3\n");
+#endif
if (xoffset)
{
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;
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;
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;
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/arm.h"
#include "vp8/common/blockd.h"
#include "vp8/common/pragmas.h"
* 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"
*/
-#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"
* 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"
#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"
/*
- * 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
#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);
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)
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)
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)
{
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 */
{
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);
{
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
}
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)
{
-
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))
{
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:
{
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;
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;
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,
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;
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
/* 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
}
}
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;
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
+
+
+}
+++ /dev/null
-/*
- * 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
#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;
{
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 */
}
}
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.
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)
{
((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;
((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);
+
}
FILE *vpxlog = 0;
#endif
-
-
static void
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;
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;
++xd->mode_info_context; /* skip prediction column */
}
-
static unsigned int read_partition_size(const unsigned char *cx_size)
{
const unsigned int 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)
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)
{
/* 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));
*/
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
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
{
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;
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;
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
{
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");
/* 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,
* 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;
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
}
}
}
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);
}
}
- 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);
{
/* 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;
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);
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");
}
{
- 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]))
*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);
/* 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. */
{
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
fclose(f);
}
#endif
+ //printf("Frame %d Done\n", frame_count++);
return 0;
}
*/
-#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;
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
+}
+
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
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));
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;
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
#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
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
#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
#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));
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); \
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); \
}\
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;
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;
+ 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;
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;
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);
CAT_FIVE_CONTEXT_NODE_0_);
val = CAT6_MIN_VAL;
- bits_count = CONFIG_EXTEND_QRANGE?12:10;
+ bits_count = 12;
do
{
bc->value = value;
bc->count = count;
bc->range = range;
+
return eobtotal;
}
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 */
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/decoder/dequantize.h"
#include "vp8/decoder/onyxd_int.h"
/* 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;
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
}
* 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"
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);
+}
+
#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>
#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
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()
{
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));
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.
*/
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;
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);
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
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)
#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))
{
#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)
{
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);*/
pbi->ready_for_new_data = 0;
pbi->last_time_stamp = time_stamp;
- pbi->num_partitions = 0;
pbi->source_sz = 0;
#if 0
#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
{
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;
BOOL_DECODER *current_bc;
vp8_prob const *coef_probs[4];
+ vp8_prob const *coef_probs_8x8[4];
UINT8 eob[25];
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;
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;
*/
-#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"
#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
+++ /dev/null
-/*
- * 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 */
-}
* 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"
* 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"
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/x86.h"
#include "vp8/decoder/onyxd_int.h"
*/
-#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"
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;
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;
#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
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);
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);
//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
#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
#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];
#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
int count_mb_seg[4] = { 0, 0, 0, 0 };
#endif
-
static void update_mode(
vp8_writer *const w,
int n,
);
}
{
+#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
}
}
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);
}
-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
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)
}
}
+// 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;
+
+ int i;
+ int pred_context;
- 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];
- MODE_INFO *m = pc->mi, *ms;
+ MODE_INFO *m = pc->mi;
+ MODE_INFO *prev_m = pc->prev_mi;
+
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;
+ // Values used in prediction model coding
+ vp8_prob pred_prob;
+ unsigned char prediction_flag;
- if (!prob_last_coded)
- prob_last_coded = 1;
-
- 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;
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)
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
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 (pc->mb_no_coeff_skip)
- vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false);
+ // 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);
+ }
+
+ // 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
+
+#else
+ write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
+#endif /*CONFIG_UVINTRA*/
- write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
+ }
}
- else /* inter coded */
+ else
{
int_mv best_mv;
- vp8_prob mv_ref_p [VP8_MVREFS-1];
+ int ct[4];
- vp8_write(w, 1, cpi->prob_intra_coded);
-
- 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
+#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);
+ 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;
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])
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;
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);
+ 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] +
+ rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
+ 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(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] +
+ rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
+ rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
+ 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);
+
+
+ /* 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];
- newtotal =
- rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
- rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
- rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
- rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
+ 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);
- // 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);
+ const int s = old_b - new_b - update_b;
- oldtotal =
- rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
- rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
- rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
- rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
+ if (s > 0)
+ savings8x8 += s;
- savings += (oldtotal - newtotal) / 256;
- }
+
+ }
+ while (++t < MAX_ENTROPY_TOKENS - 1);
- if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
- savings += independent_coef_context_savings(cpi);
- else
- savings += default_coef_context_savings(cpi);
+ }
+ while (++k < PREV_COEF_CONTEXTS);
+ }
+ while (++j < COEF_BANDS);
+ }
+ while (++i < BLOCK_TYPES);
+ savings += savings8x8 >> 8;
+ }
return savings;
}
{
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};
+
+ 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;
- vp8_write(w, u, upd);
+ 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];
+ ++ 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
+ 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;
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;
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)
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 );
- // Frame level data
- if (Data)
+
+#if CONFIG_FEATUREUPDATES
+
+ // 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];
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);
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)
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);
{
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);
}
//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);
// 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);
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
if (pc->frame_type == KEY_FRAME)
{
+#if CONFIG_QIMODE
+ decide_kf_ymode_entropy(cpi);
+#endif
write_kfmodes(cpi);
#ifdef ENTROPY_STATS
{
pack_inter_mode_mvs(cpi);
+ vp8_update_mode_context(&cpi->common);
+
#ifdef ENTROPY_STATS
active_section = 1;
#endif
}
*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;
- pack_tokens_into_partitions(cpi, cx_data + bc->pos, num_part, &asize);
+ vp8_start_encode(&cpi->bc2, cx_data + bc->pos);
- *size += asize;
- }
- else
- {
- vp8_start_encode(&cpi->bc2, cx_data + bc->pos);
-
-#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);
+ pack_tokens(&cpi->bc2, cpi->tok, cpi->tok_count);
- vp8_stop_encode(&cpi->bc2);
+ vp8_stop_encode(&cpi->bc2);
- *size += cpi->bc2.pos;
- cpi->partition_sz[1] = cpi->bc2.pos;
- }
+ *size += cpi->bc2.pos;
}
#ifdef ENTROPY_STATS
}
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
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
int src;
int src_stride;
-// MV enc_mv;
- int force_empty;
+ int eob_max_offset;
+ int eob_max_offset_8x8;
} BLOCK;
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
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;
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;
#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;
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;
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;
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++;
}
#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
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;
+++ /dev/null
-/*
- * 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,},
- },
- },
-};
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "encodemb.h"
#include "encodemv.h"
#include "vp8/common/common.h"
#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
#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);
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
MACROBLOCK *x,
MACROBLOCKD *xd,
TOKENEXTRA **tp,
- int *segment_counts,
int *totalrate)
{
int recon_yoffset, recon_uvoffset;
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;
// 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
//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
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.
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
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
}
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;
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;
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)
&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
{
&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;
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);
// 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;
}
-
- // 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
}
#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;
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)
{
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];
{
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)
{
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);
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)
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)
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;
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
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
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);
}
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)
cpi->skip_false_count ++;
}
}
-
return rate;
}
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/common/idct.h"
#include "quantize.h"
#include "vp8/common/reconintra.h"
#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;
{
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);
}
}
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);
{
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);
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);
+ }
+}
#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
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "encodemb.h"
#include "vp8/common/reconinter.h"
#include "quantize.h"
#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);
}
}
+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;
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)
{
}
}
+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{
// 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]=
{
*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;
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;
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]);
}
}
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;
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]);
}
}
}
}
+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);
#ifndef __INC_ENCODEMB_H
#define __INC_ENCODEMB_H
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "block.h"
#define prototype_mberr(sym) \
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
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,
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
}
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]);
}
}
#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
}
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;
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);
{
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
}
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
);
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 */
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
+++ /dev/null
-/*
- * 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
--- /dev/null
+/*
+ * 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
#include "vp8/common/swapyv12buffer.h"
#include <stdio.h>
#include "rdopt.h"
+#include "ratectrl.h"
#include "vp8/common/quant_common.h"
#include "encodemv.h"
#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
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)
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,
stats->MVrv,
stats->MVcv,
stats->mv_in_out_count,
+ stats->new_mv_count,
stats->count,
stats->duration);
fclose(fpfile);
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;
}
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)
// 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;
}
// 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)
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;
{
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;
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;
//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
{
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)
{
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;
}
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
? 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);
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.
{
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;
// 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;
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);
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;
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);
// 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;
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)
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
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
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;
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)
{
// 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);
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);
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))
}
}
- // 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;
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;
FIRSTPASS_STATS *start_pos;
+ int overhead_bits;
+
if (!cpi->twopass.stats_in)
{
return ;
// 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)
// 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.
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 )
// 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
// 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 );
}
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;
// 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);
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)
// 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
// 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);
- }
- }
}
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vp8/encoder/variance.h"
#include "vp8/encoder/onyx_int.h"
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;
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
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
}
#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
{
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 __INC_MBGRAPH_H__
+#define __INC_MBGRAPH_H__ 1
+
+extern void vp8_update_mbgraph_stats(VP8_COMP *cpi);
+
+#endif /* __INC_MBGRAPH_H__ */
#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>
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
// 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)
{
* error_per_bit + 128) >> 8;
}
+
void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride)
{
int Len;
* 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))
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. */
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
// 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;
}
// 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;
}
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)))
#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,
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;
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)
{
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)
{
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)
{
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)
{
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)
{
// 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;
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)
{
}
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)
{
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)
{
}
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)
{
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
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);
}
}
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;
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)
{
*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,
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;
// 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)
{
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)
{
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)
{
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)
{
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)
{
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;
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;
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
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;
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,
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;
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;
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;
}
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;
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;
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;
}
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;
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;
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;
}
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;
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;
}
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;
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
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");
}
}
/* 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));
}
#endif/* END MV ref count ENTROPY_STATS stats code */
-
-#endif
#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);
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);
}
#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
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"
#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;
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;
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;
}
}
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);
// 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;
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)
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 ++)
{
switch (Mode)
{
-#if !(CONFIG_REALTIME_ONLY)
case 0: // best quality mode
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROG ] = 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_I8X8_PRED] = 2000;
sf->thresh_mult[THR_TM ] = 1000;
sf->thresh_mult[THR_NEWMV ] = 1000;
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;
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;
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;
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;
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)
{
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)
{
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)
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)
{
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;
}
- 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
+ break;
- }
+ }; /* switch */
- if (Speed > 4)
- {
- sf->auto_filter = 0; // Faster selection of loop filter
+ /* disable frame modes if flags not set */
+ if (!(cpi->ref_frame_flags & VP8_LAST_FLAG))
+ {
+ sf->thresh_mult[THR_NEWMV ] = INT_MAX;
+ sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
+ sf->thresh_mult[THR_ZEROMV ] = INT_MAX;
+ sf->thresh_mult[THR_NEARMV ] = INT_MAX;
+ sf->thresh_mult[THR_SPLITMV ] = INT_MAX;
+ }
- 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))
+ {
+ sf->thresh_mult[THR_NEARESTG ] = INT_MAX;
+ sf->thresh_mult[THR_ZEROG ] = INT_MAX;
+ sf->thresh_mult[THR_NEARG ] = INT_MAX;
+ sf->thresh_mult[THR_NEWG ] = INT_MAX;
+ sf->thresh_mult[THR_SPLITG ] = INT_MAX;
+ }
- 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))
+ {
+ sf->thresh_mult[THR_NEARESTA ] = INT_MAX;
+ sf->thresh_mult[THR_ZEROA ] = INT_MAX;
+ sf->thresh_mult[THR_NEARA ] = INT_MAX;
+ sf->thresh_mult[THR_NEWA ] = INT_MAX;
+ sf->thresh_mult[THR_SPLITA ] = INT_MAX;
+ }
- 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_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_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_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_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 ((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;
+ }
- break;
-#endif
- case 2:
+ // Slow quant, dct and trellis not worthwhile for first pass
+ // so make sure they are always turned off.
+ if ( cpi->pass == 1 )
+ {
+ sf->improved_quant = 0;
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;
+ sf->improved_dct = 0;
+ }
- 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 */
-
- /* disable frame modes if flags not set */
- if (!(cpi->ref_frame_flags & VP8_LAST_FLAG))
- {
- sf->thresh_mult[THR_NEWMV ] = INT_MAX;
- sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
- sf->thresh_mult[THR_ZEROMV ] = INT_MAX;
- sf->thresh_mult[THR_NEARMV ] = INT_MAX;
- sf->thresh_mult[THR_SPLITMV ] = INT_MAX;
- }
-
- if (!(cpi->ref_frame_flags & VP8_GOLD_FLAG))
- {
- sf->thresh_mult[THR_NEARESTG ] = INT_MAX;
- sf->thresh_mult[THR_ZEROG ] = INT_MAX;
- sf->thresh_mult[THR_NEARG ] = INT_MAX;
- sf->thresh_mult[THR_NEWG ] = INT_MAX;
- sf->thresh_mult[THR_SPLITG ] = INT_MAX;
- }
-
- if (!(cpi->ref_frame_flags & VP8_ALT_FLAG))
- {
- sf->thresh_mult[THR_NEARESTA ] = INT_MAX;
- sf->thresh_mult[THR_ZEROA ] = INT_MAX;
- sf->thresh_mult[THR_NEARA ] = INT_MAX;
- sf->thresh_mult[THR_NEWA ] = INT_MAX;
- sf->thresh_mult[THR_SPLITA ] = INT_MAX;
- }
-
-
- // Slow quant, dct and trellis not worthwhile for first pass
- // so make sure they are always turned off.
- if ( cpi->pass == 1 )
- {
- sf->improved_quant = 0;
- sf->optimize_coefficients = 0;
- sf->improved_dct = 0;
- }
-
- if (cpi->sf.search_method == NSTEP)
- {
- vp8_init3smotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
- }
- else if (cpi->sf.search_method == DIAMOND)
- {
- vp8_init_dsmotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
- }
+ if (cpi->sf.search_method == NSTEP)
+ {
+ vp8_init3smotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
+ }
+ else if (cpi->sf.search_method == DIAMOND)
+ {
+ vp8_init_dsmotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
+ }
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)
{
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
{
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);
{
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
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);
}
-// 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)
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);
cpi->oxcf = *oxcf;
- cpi->auto_gold = 1;
- cpi->auto_adjust_gold_quantizer = 1;
cpi->goldfreq = 7;
cm->version = oxcf->Version;
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
+ cpi->static_mb_pct = 0;
+
#if VP8_TEMPORAL_ALT_REF
{
int i;
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;
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;
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;
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
{
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;
cpi->alt_ref_source = NULL;
cpi->is_src_frame_alt_ref = 0;
-
#if 0
// Experimental RD Code
cpi->frame_distortion = 0;
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;
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
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();
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;
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;
#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");
cpi->output_pkt_list = oxcf->output_pkt_list;
-#if !(CONFIG_REALTIME_ONLY)
-
if (cpi->pass == 1)
{
vp8_init_first_pass(cpi);
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)
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);
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;
}
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();
#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");
- 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];
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)
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);
}
#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;
}
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;
}
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
}
-#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);
#ifdef OUTPUT_YUV_SRC
fclose(yuv_file);
#endif
+#ifdef OUTPUT_YUV_REC
+ fclose(yuv_rec_file);
+#endif
#if 0
}
-#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;
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;
// 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;
}
}
-// 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)
{
// 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))) ||
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)
{
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.
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);
}
+// 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,
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;
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;
// 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
(cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0)))
{
// Key frame from VFW/auto-keyframe/first frame
- 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 various flags etc to special state if it is a key frame
- if (cm->frame_type == KEY_FRAME)
- {
- int i;
-
- // 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;
- }
-
- // The alternate reference frame cannot be active for a key frame
- cpi->source_alt_ref_active = FALSE;
-
- // Reset the RD threshold multipliers to default of * 1 (128)
- for (i = 0; i < MAX_MODES; i++)
- {
- cpi->rd_thresh_mult[i] = 128;
- }
- }
-
- // 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 (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);
+ cm->frame_type = KEY_FRAME;
}
- // 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)
+ // 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)
{
- 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;
- }
+ int i;
+
+ // Reset the loop filter deltas and segmentation map
+ setup_features(cpi);
- // 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 )
+ // If segmentation is enabled force a map update for key frames
+ if (xd->segmentation_enabled)
{
- cpi->decimation_count = cpi->decimation_factor;
+ xd->update_mb_segmentation_map = 1;
+ xd->update_mb_segmentation_data = 1;
}
- 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;
+ // The alternate reference frame cannot be active for a key frame
+ cpi->source_alt_ref_active = FALSE;
- return;
+ // Reset the RD threshold multipliers to default of * 1 (128)
+ for (i = 0; i < MAX_MODES; i++)
+ {
+ cpi->rd_thresh_mult[i] = 128;
}
- else
- cpi->decimation_count = cpi->decimation_factor;
}
+//#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
+
+ // Test code for new segment features
+ init_seg_features( cpi );
+
// Decide how big to make the frame
if (!vp8_pick_frame_size(cpi))
{
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;
}
}
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
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.
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)
{
{
vp8_clear_system_state(); //__asm emms;
- /*
- if(cpi->is_src_frame_alt_ref)
- Q = 127;
- */
-
vp8_set_quantizer(cpi, Q);
this_q = Q;
*/
}
- //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;
}
-
-#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);
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 )
{
&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:
// 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)
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)
last_zbin_oq = cpi->zbin_over_quant;
}
else
-#endif
Loop = FALSE;
if (cpi->is_src_frame_alt_ref)
// 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 */
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);
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.
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;
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;
#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;
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)
{
}
// 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
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));
+ }
}
#endif
}
-#if !(CONFIG_REALTIME_ONLY)
static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
{
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
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,
cpi->is_src_frame_alt_ref = 0;
}
}
-#endif
if (!cpi->source)
{
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)
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;
assert(i < NUM_YV12_BUFFERS );
}
-#if !(CONFIG_REALTIME_ONLY)
-
if (cpi->pass == 1)
{
Pass1Encode(cpi, size, dest, frame_flags);
Pass2Encode(cpi, size, dest, frame_flags);
}
else
-#endif
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
- if (cpi->compressor_speed == 2)
- {
- 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)
+ if(cm->refresh_entropy_probs)
{
- 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
}
}
-#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
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;
}
#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"
#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"
#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
#define MV_ZBIN_BOOST 4
#define ZBIN_OQ_MAX 192
-#if !(CONFIG_REALTIME_ONLY)
#define VP8_TEMPORAL_ALT_REF 1
-#endif
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];
double MVrv;
double MVcv;
double mv_in_out_count;
+ double new_mv_count;
double duration;
double count;
}
} 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
{
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;
typedef struct
{
MACROBLOCK mb;
- int segment_counts[MAX_MB_SEGMENTS];
int totalrate;
} MB_ROW_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 ;
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;
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;
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;
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;
int compressor_speed;
int interquantizer;
- int auto_gold;
- int auto_adjust_gold_quantizer;
int goldfreq;
int auto_worst_q;
int cpu_used;
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];
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;
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
{
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;
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;
+++ /dev/null
-/*
- * 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;
-}
(*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)
{
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;
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;
}
// 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;
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);
cm->filter_level = filt_best;
}
+#endif
+
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);
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);
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;
#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;
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++)
{
d->eob = eob + 1;
}
-#endif
+
#ifdef EXACT_QUANT
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];
}
#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++)
{
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++)
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
}
-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,
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;
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;
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;
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;
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;
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;
}
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
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
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
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;
}
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);
}
-
#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
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;
#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);
#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];
#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] =
{
80, 85, 90, 95, 100, 100, 100, 100,
};
-
static const int gf_adjust_table[101] =
{
100,
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)
{
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);
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);
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
// 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)
{
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;
}
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
// 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;
}
}
// 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)
{
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;
// 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++;
}
}
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;
}
}
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;
}
#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);
// 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
#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"
#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] =
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] =
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(
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+ {
+
+ 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);
+ vp8_cost_tokens((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree);
+ }
}
};
// 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)
{
}
-
-
-
void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
{
int q;
int i;
- int *thresh;
- int threshmult;
vp8_clear_system_state(); //__asm emms;
// 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
(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;
(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);
}
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
// 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;
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;
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);
*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);
}
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;
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)
}
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;
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;
{
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;
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];
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;
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);
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)
{
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(x);
- vp8_quantize_mbuv(x);
+ vp8_transform_mbuv(x);
+ vp8_quantize_mbuv(x);
+
+ *rate = rd_cost_mbuv(x);
+ *distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+
+ 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)
+{
+ 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);
+ vp8_transform_mbuv(x);
+ vp8_quantize_mbuv(x);
+
+ rate_to = rd_cost_mbuv(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;
+#if CONFIG_COMP_INTRA_PRED
+ mode2_selected = mode2;
+ }
+#endif
+ }
+ }
- *rate = rd_cost_mbuv(x);
- *distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+ *rate = r;
+ *distortion = d;
- return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
+ 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(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *rate_tokenonly, int *distortion)
+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);
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(x);
- vp8_quantize_mbuv(x);
+ vp8_transform_mbuv_8x8(x);
- rate_to = rd_cost_mbuv(x);
- rate = rate_to + x->intra_uv_mode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.uv_mode];
+ vp8_quantize_mbuv_8x8(x);
- distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+ 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)
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);
}
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);
}
-
static const unsigned int segmentation_to_sseshift[4] = {3, 3, 2, 0};
// 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;
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;
&mvp_full, &temp_mv,
step_param + n, sadpb,
&num00, v_fn_ptr,
- x->mvcost, bsi->ref_mv);
+ XMVCOST,
+ bsi->ref_mv);
if (thissme < bestsme)
{
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)
{
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) ||
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 */
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);
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;
{
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_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)
+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;
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;
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;
//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;
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;
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])
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 */
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 )
vp8_update_zbin_extra(cpi, x);
}
+
+ if (!x->e_mbd.mode_info_context->mbmi.second_ref_frame)
switch (this_mode)
{
case B_PRED:
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;
+
+ 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 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;
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:
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
{
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))
//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)
{
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:
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;
}
}
}
}
-
-
//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
*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;
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;
// 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;
(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;
}
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)
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;
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;
}
#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
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
#include <stdlib.h>
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx/vpx_integer.h"
unsigned int vp8_sad16x16_c(
--- /dev/null
+/*
+ * 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;
+}
/*
- * 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
*/
-#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)
{
// 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)
{
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
}
}
}
}
+
+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) );
+ }
+}
#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__ */
#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>
#if VP8_TEMPORAL_ALT_REF
+
static void vp8_temporal_filter_predictors_mb_c
(
MACROBLOCKD *x,
{
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
{
}
// U & V
+ omv_row = mv_row;
+ omv_col = mv_col;
mv_row >>= 1;
mv_col >>= 1;
stride = (stride + 1) >> 1;
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,
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);
unsigned short *count
)
{
- int i, j, k;
+ unsigned int i, j, k;
int modifier;
int byte = 0;
#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
(
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;
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?
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
#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++)
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++)
#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()
{
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
)
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);
pt = vp8_prev_token_class[token];
t++;
}
- if (c < 16)
+
+ if (c < seg_eob)
{
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
}
+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
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);
pt = vp8_prev_token_class[token];
t++;
}
- if (c < 16)
+
+ if (c < seg_eob)
{
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
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);
pt = vp8_prev_token_class[token];
t++;
}
- if (c < 16)
+
+ if (c < seg_eob)
{
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
}
-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;
{
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);
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);
}
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()
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);
+
+ }
+ 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);
}
+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,
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));
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
{
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);
+}
+
#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
#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);
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;
vp8_ssimpf_fn_t ssimpf_16x16;
#endif
+ vp8_variance_fn_t satd16x16;
} vp8_variance_rtcd_vtable_t;
typedef struct
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
}
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
}
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
}
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
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
times 8 db 48, 80
times 8 db 32, 96
times 8 db 16, 112
+%endif
// 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 },
{ 32, 32, 32, 32, 96, 96, 96, 96 },
{ 16, 16, 16, 16, 112, 112, 112, 112 }
};
+#endif
unsigned int vp8_sub_pixel_variance4x4_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,
&xsum0, &xxsum0
);
-
vp8_filter_block2d_bil_var_mmx(
src_ptr + 8, src_pixels_per_line,
dst_ptr + 8, dst_pixels_per_line, 16,
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
}
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
}
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
}
#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);
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,
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,
// 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,
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,
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,
#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,
// 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,
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,
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
#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
*/
-#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"
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;
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;
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
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
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
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
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
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
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
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 */
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);
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.
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);
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);
if ((int)(stats->count + 0.5) != n_packets - 1)
ERROR("rc_twopass_stats_in missing EOS stats packet");
}
-#endif
return VPX_CODEC_OK;
}
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;
oxcf->frame_rate = 30;
}
- oxcf->error_resilient_mode = cfg.g_error_resilient;
-
switch (cfg.g_pass)
{
case VPX_RC_ONE_PASS:
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;
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;
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);
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;
{
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;
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;
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;
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);
cx_data_sz -= cpi->partition_sz[i];
}
}
- else
+ else*/
{
pkt.data.frame.buf = cx_data;
pkt.data.frame.sz = size;
#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 */
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
{
"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; */
{
"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; */
#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
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
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
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
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
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))
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))
res = VPX_CODEC_INCAPABLE;
else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC))
res = VPX_CODEC_INCAPABLE;
- else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) &&
- !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT))
- res = VPX_CODEC_INCAPABLE;
else if ((flags & VPX_CODEC_USE_INPUT_PARTITION) &&
!(iface->caps & VPX_CODEC_CAP_INPUT_PARTITION))
res = VPX_CODEC_INCAPABLE;
#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice callbacks */
#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame callbacks */
#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
-#define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000 /**< Can conceal errors due to
- packet loss */
#define VPX_CODEC_CAP_INPUT_PARTITION 0x100000 /**< Can receive encoded frames
one partition at a time */
* The available flags are specified by VPX_CODEC_USE_* defines.
*/
#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
-#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded
- frames */
#define VPX_CODEC_USE_INPUT_PARTITION 0x40000 /**< The input frame should be
passed to the decoder one
partition at a time */
#ifndef __VPX_MEM_INTRNL_H__
#define __VPX_MEM_INTRNL_H__
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#ifndef CONFIG_MEM_MANAGER
# if defined(VXWORKS)
in the memory_tracker struct as well as calls to create/destroy/lock/unlock
the mutex in vpx_memory_tracker_init/Destroy and memory_tracker_lock_mutex/unlock_mutex
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#if defined(__uClinux__)
# include <lddk.h>
#ifndef VPX_PORTS_ARM_H
#define VPX_PORTS_ARM_H
#include <stdlib.h>
-#include "vpx_config.h"
+#include "config.h"
/*ARMv5TE "Enhanced DSP" instructions.*/
#define HAS_EDSP 0x01
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
-
-
-#ifndef __INC_PICKINTER_H
-#define __INC_PICKINTER_H
#include "vpx_config.h"
-#include "vp8/common/onyxc_int.h"
-
-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
*mem = (uint##sz##_t)raw;\
}
-#include "vpx_config.h"
+#include "config.h"
#if CONFIG_BIG_ENDIAN
#define mem_get_be_aligned_generic(sz) mem_get_ne_aligned_generic(be,sz)
#define mem_get_sbe_aligned_generic(sz) mem_get_sne_aligned_generic(be,sz)
#ifndef __VPXTYPES_H__
#define __VPXTYPES_H__
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
//#include <sys/types.h>
#ifdef _MSC_VER
#ifndef VPX_PORTS_X86_H
#define VPX_PORTS_X86_H
#include <stdlib.h>
-#include "vpx_config.h"
+#include "config.h"
typedef enum
{
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_ports/arm.h"
#include "vpx_scale/vpxscale.h"
*/
-#include "vpx_config.h"
+#include "vpx_ports/config.h"
#include "vpx_scale/vpxscale.h"
****************************************************************************/
void vp8_scale_machine_specific_config()
{
-#if CONFIG_SPATIAL_RESAMPLING
- vp8_horizontal_line_1_2_scale = vp8cx_horizontal_line_1_2_scale_c;
- vp8_vertical_band_1_2_scale = vp8cx_vertical_band_1_2_scale_c;
- vp8_last_vertical_band_1_2_scale = vp8cx_last_vertical_band_1_2_scale_c;
- vp8_horizontal_line_3_5_scale = vp8cx_horizontal_line_3_5_scale_c;
- vp8_vertical_band_3_5_scale = vp8cx_vertical_band_3_5_scale_c;
- vp8_last_vertical_band_3_5_scale = vp8cx_last_vertical_band_3_5_scale_c;
- vp8_horizontal_line_3_4_scale = vp8cx_horizontal_line_3_4_scale_c;
- vp8_vertical_band_3_4_scale = vp8cx_vertical_band_3_4_scale_c;
- vp8_last_vertical_band_3_4_scale = vp8cx_last_vertical_band_3_4_scale_c;
- vp8_horizontal_line_2_3_scale = vp8cx_horizontal_line_2_3_scale_c;
- vp8_vertical_band_2_3_scale = vp8cx_vertical_band_2_3_scale_c;
- vp8_last_vertical_band_2_3_scale = vp8cx_last_vertical_band_2_3_scale_c;
- vp8_horizontal_line_4_5_scale = vp8cx_horizontal_line_4_5_scale_c;
- vp8_vertical_band_4_5_scale = vp8cx_vertical_band_4_5_scale_c;
- vp8_last_vertical_band_4_5_scale = vp8cx_last_vertical_band_4_5_scale_c;
-
-
- vp8_vertical_band_5_4_scale = vp8cx_vertical_band_5_4_scale_c;
- vp8_vertical_band_5_3_scale = vp8cx_vertical_band_5_3_scale_c;
- vp8_vertical_band_2_1_scale = vp8cx_vertical_band_2_1_scale_c;
- vp8_vertical_band_2_1_scale_i = vp8cx_vertical_band_2_1_scale_i_c;
- vp8_horizontal_line_2_1_scale = vp8cx_horizontal_line_2_1_scale_c;
- vp8_horizontal_line_5_3_scale = vp8cx_horizontal_line_5_3_scale_c;
- vp8_horizontal_line_5_4_scale = vp8cx_horizontal_line_5_4_scale_c;
-#endif
-
vp8_yv12_extend_frame_borders_ptr = vp8_yv12_extend_frame_borders;
vp8_yv12_copy_frame_yonly_ptr = vp8_yv12_copy_frame_yonly;
vp8_yv12_copy_frame_ptr = vp8_yv12_copy_frame;
#endif
#define VP7BORDERINPIXELS 48
+
+#if CONFIG_ENHANCED_INTERP
+#define VP8BORDERINPIXELS 64
+#define INTERP_EXTEND 4
+#else
#define VP8BORDERINPIXELS 32
+#define INTERP_EXTEND 3
+#endif
/*************************************
For INT_YUV:
"Max threads to use");
static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
"Show version string");
-static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0,
- "Enable decoder error-concealment");
-
#if CONFIG_MD5
static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
#if CONFIG_MD5
&md5arg,
#endif
- &error_concealment,
NULL
};
FILE *infile;
int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
- int ec_enabled = 0;
vpx_codec_iface_t *iface = NULL;
unsigned int fourcc;
unsigned long dx_time = 0;
vp8_dbg_display_mv = flags;
}
}
- else if (arg_match(&arg, &error_concealment, argi))
- {
- ec_enabled = 1;
- }
#endif
else
break;
}
- dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
- (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
+ dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0);
if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface, &cfg,
dec_flags))
{
#include <fcntl.h>
#include <unistd.h>
#endif
+#include "vpx_config.h"
+#include "vpx_version.h"
#include "vpx/vp8cx.h"
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/vpx_timer.h"
unsigned int fourcc;
} codecs[] =
{
+#if CONFIG_EXPERIMENTAL && CONFIG_VP8_ENCODER
+ {"vp8x", &vpx_codec_vp8x_cx_algo, 0x78385056},
+#endif
#if CONFIG_VP8_ENCODER
{"vp8", &vpx_codec_vp8_cx_algo, 0x30385056},
#endif
//segment info
EbmlLoc startInfo;
uint64_t frame_time;
- char version_string[64];
-
- /* Assemble version string */
- if(ebml->debug)
- strcpy(version_string, "vpxenc");
- else
- {
- strcpy(version_string, "vpxenc ");
- strncat(version_string,
- vpx_codec_version_str(),
- sizeof(version_string) - 1 - strlen(version_string));
- }
frame_time = (uint64_t)1000 * ebml->framerate.den
/ ebml->framerate.num;
Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
Ebml_SerializeFloat(ebml, Segment_Duration,
ebml->last_pts_ms + frame_time);
- Ebml_SerializeString(ebml, 0x4D80, version_string);
- Ebml_SerializeString(ebml, 0x5741, version_string);
+ Ebml_SerializeString(ebml, 0x4D80,
+ ebml->debug ? "vpxenc" : "vpxenc" VERSION_STRING);
+ Ebml_SerializeString(ebml, 0x5741,
+ ebml->debug ? "vpxenc" : "vpxenc" VERSION_STRING);
Ebml_EndSubElement(ebml, &startInfo);
}
}
}
#include "math.h"
-
+#define MAX_PSNR 100
static double vp8_mse2psnr(double Samples, double Peak, double Mse)
{
double psnr;
if ((double)Mse > 0.0)
psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
else
- psnr = 60; // Limit to prevent / 0
+ psnr = MAX_PSNR; // Limit to prevent / 0
- if (psnr > 60)
- psnr = 60;
+ if (psnr > MAX_PSNR)
+ psnr = MAX_PSNR;
return psnr;
}
/* Handle codec specific options */
#if CONFIG_VP8_ENCODER
- if (codec->iface == &vpx_codec_vp8_cx_algo)
+ if (codec->iface == &vpx_codec_vp8_cx_algo
+#if CONFIG_EXPERIMENTAL
+ || codec->iface == &vpx_codec_vp8x_cx_algo
+#endif
+ )
{
ctrl_args = vp8_args;
ctrl_args_map = vp8_arg_ctrl_map;