From b8b90c3001f6dd208191ae53bfabc0bd7c791a13 Mon Sep 17 00:00:00 2001 From: Dongcunhui <48936648+Dongcunhui@users.noreply.github.com> Date: Tue, 25 Jan 2022 12:21:18 +0800 Subject: [PATCH] Add files via upload --- .../EZBC0a/inc/context_status_consts.h | 169 + .../EZBC0a/inc/dwt_bitplane_codec.h | 324 + Interframe EZBC/EZBC0a/inc/dwt_bitplane_dec.h | 107 + Interframe EZBC/EZBC0a/inc/dwt_bitplane_enc.h | 109 + .../EZBC0a/src/dec_subband_tree.cpp | 79 + .../EZBC0a/src/dwt_bitplane_codec.cpp | 699 ++ .../EZBC0a/src/dwt_bitplane_dec.cpp | 412 + .../EZBC0a/src/dwt_bitplane_dec_cxt_AC.cpp | 1376 +++ .../src/dwt_bitplane_dec_pos_dep_cxt_AC.cpp | 562 + .../EZBC0a/src/dwt_bitplane_enc.cpp | 423 + .../EZBC0a/src/dwt_bitplane_enc_cxt_AC.cpp | 1160 +++ .../src/dwt_bitplane_enc_pos_dep_cxt_AC.cpp | 428 + .../EZBC0a/src/enc_subband_tree.cpp | 87 + .../EZBC0a/src/setup_cxt_tables.cpp | 1244 +++ Interframe EZBC/MATLAB files/JP2K2YUV.m | 162 + Interframe EZBC/MATLAB files/YUV2JP2K.m | 331 + Interframe EZBC/TempSub/inc/Choisubband.h | 5 + Interframe EZBC/TempSub/inc/analsyn.h | 103 + Interframe EZBC/TempSub/inc/arcode.h | 32 + Interframe EZBC/TempSub/inc/basic.h | 45 + Interframe EZBC/TempSub/inc/binarcode.h | 18 + Interframe EZBC/TempSub/inc/bmeN.h | 94 + Interframe EZBC/TempSub/inc/bme_tools.h | 26 + Interframe EZBC/TempSub/inc/chrom.h | 7 + Interframe EZBC/TempSub/inc/coderN.h | 158 + Interframe EZBC/TempSub/inc/decoderN.h | 19 + .../TempSub/inc/directional_iblock.h | 44 + Interframe EZBC/TempSub/inc/dpx.h | 125 + Interframe EZBC/TempSub/inc/encoderN.h | 20 + Interframe EZBC/TempSub/inc/golomb.h | 11 + Interframe EZBC/TempSub/inc/hvsbm_fullres.h | 19 + Interframe EZBC/TempSub/inc/initN.h | 1 + Interframe EZBC/TempSub/inc/init_decN.h | 1 + Interframe EZBC/TempSub/inc/init_encN.h | 14 + Interframe EZBC/TempSub/inc/ioN.h | 20 + Interframe EZBC/TempSub/inc/layer_mv.h | 37 + Interframe EZBC/TempSub/inc/memoryN.h | 17 + Interframe EZBC/TempSub/inc/miscN.h | 27 + Interframe EZBC/TempSub/inc/mode_decision.h | 27 + Interframe EZBC/TempSub/inc/mv_ec.h | 94 + Interframe EZBC/TempSub/inc/mv_statistics.h | 24 + Interframe EZBC/TempSub/inc/mvcodingN.h | 23 + Interframe EZBC/TempSub/inc/obmc_varblk.h | 16 + Interframe EZBC/TempSub/inc/pstatN.h | 7 + Interframe EZBC/TempSub/inc/pull_res.h | 96 + Interframe EZBC/TempSub/inc/rasterfile.h | 62 + Interframe EZBC/TempSub/inc/structN.h | 2122 ++++ Interframe EZBC/TempSub/inc/unix_pc.h | 1 + Interframe EZBC/TempSub/inc/util_filtering.h | 37 + Interframe EZBC/TempSub/inc/zconf.h | 326 + Interframe EZBC/TempSub/inc/zlib.h | 1200 +++ Interframe EZBC/TempSub/src/anal.c | 1679 +++ Interframe EZBC/TempSub/src/arcode.cpp | 533 + Interframe EZBC/TempSub/src/binarcode.cpp | 205 + Interframe EZBC/TempSub/src/bitalloc.c | 2428 +++++ Interframe EZBC/TempSub/src/bmeN.c | 1865 ++++ Interframe EZBC/TempSub/src/bme_tools.cpp | 663 ++ Interframe EZBC/TempSub/src/chrom.c | 344 + Interframe EZBC/TempSub/src/cnv_data_4_1.c | 23 + Interframe EZBC/TempSub/src/dataio.c | 116 + Interframe EZBC/TempSub/src/decoderN.c | 366 + .../TempSub/src/directional_iblock.c | 3731 +++++++ Interframe EZBC/TempSub/src/display.c | 199 + Interframe EZBC/TempSub/src/dpxio.c | 609 ++ Interframe EZBC/TempSub/src/encoderN.c | 1685 +++ Interframe EZBC/TempSub/src/golomb.cpp | 76 + Interframe EZBC/TempSub/src/hvsbm_fullres.c | 843 ++ Interframe EZBC/TempSub/src/init_decN.c | 204 + Interframe EZBC/TempSub/src/init_encN.c | 517 + Interframe EZBC/TempSub/src/intra_dec.c | 42 + Interframe EZBC/TempSub/src/intra_enc.c | 34 + Interframe EZBC/TempSub/src/ioN.c | 1437 +++ Interframe EZBC/TempSub/src/layer_mv.c | 1210 +++ .../TempSub/src/lifting-only write Y.c | 2214 ++++ Interframe EZBC/TempSub/src/lifting.c | 2426 +++++ Interframe EZBC/TempSub/src/memoryN.c | 414 + Interframe EZBC/TempSub/src/miscN.c | 557 + Interframe EZBC/TempSub/src/mode_decision.c | 5993 +++++++++++ Interframe EZBC/TempSub/src/mv_ec.cpp | 548 + Interframe EZBC/TempSub/src/mv_statistics.cpp | 172 + Interframe EZBC/TempSub/src/mvcodingN.c | 9006 +++++++++++++++++ Interframe EZBC/TempSub/src/obmc_varblk.c | 872 ++ Interframe EZBC/TempSub/src/pstatN.c | 308 + Interframe EZBC/TempSub/src/pull.c | 2079 ++++ Interframe EZBC/TempSub/src/ras_util.c | 255 + Interframe EZBC/TempSub/src/showtime.c | 28 + Interframe EZBC/TempSub/src/simul_func.cpp | 516 + Interframe EZBC/TempSub/src/simul_pull.c | 509 + Interframe EZBC/TempSub/src/spatial.c | 150 + Interframe EZBC/TempSub/src/subband_choi.c | 762 ++ Interframe EZBC/TempSub/src/syn.c | 1406 +++ Interframe EZBC/Utils/inc/ar_code.h | 565 ++ Interframe EZBC/Utils/inc/general.h | 197 + Interframe EZBC/Utils/inc/ifc.h | 81 + Interframe EZBC/Utils/inc/image_bw.h | 238 + Interframe EZBC/Utils/inc/subband.h | 275 + Interframe EZBC/Utils/src/ar_code.cpp | 793 ++ Interframe EZBC/Utils/src/general.cpp | 159 + Interframe EZBC/Utils/src/image_bw.cpp | 1131 +++ Interframe EZBC/Utils/src/subband.cpp | 452 + 100 files changed, 63465 insertions(+) create mode 100644 Interframe EZBC/EZBC0a/inc/context_status_consts.h create mode 100644 Interframe EZBC/EZBC0a/inc/dwt_bitplane_codec.h create mode 100644 Interframe EZBC/EZBC0a/inc/dwt_bitplane_dec.h create mode 100644 Interframe EZBC/EZBC0a/inc/dwt_bitplane_enc.h create mode 100644 Interframe EZBC/EZBC0a/src/dec_subband_tree.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_codec.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_dec.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_cxt_AC.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_pos_dep_cxt_AC.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_enc.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_cxt_AC.cpp create mode 100644 Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_pos_dep_cxt_AC.cpp create mode 100644 Interframe EZBC/EZBC0a/src/enc_subband_tree.cpp create mode 100644 Interframe EZBC/EZBC0a/src/setup_cxt_tables.cpp create mode 100644 Interframe EZBC/MATLAB files/JP2K2YUV.m create mode 100644 Interframe EZBC/MATLAB files/YUV2JP2K.m create mode 100644 Interframe EZBC/TempSub/inc/Choisubband.h create mode 100644 Interframe EZBC/TempSub/inc/analsyn.h create mode 100644 Interframe EZBC/TempSub/inc/arcode.h create mode 100644 Interframe EZBC/TempSub/inc/basic.h create mode 100644 Interframe EZBC/TempSub/inc/binarcode.h create mode 100644 Interframe EZBC/TempSub/inc/bmeN.h create mode 100644 Interframe EZBC/TempSub/inc/bme_tools.h create mode 100644 Interframe EZBC/TempSub/inc/chrom.h create mode 100644 Interframe EZBC/TempSub/inc/coderN.h create mode 100644 Interframe EZBC/TempSub/inc/decoderN.h create mode 100644 Interframe EZBC/TempSub/inc/directional_iblock.h create mode 100644 Interframe EZBC/TempSub/inc/dpx.h create mode 100644 Interframe EZBC/TempSub/inc/encoderN.h create mode 100644 Interframe EZBC/TempSub/inc/golomb.h create mode 100644 Interframe EZBC/TempSub/inc/hvsbm_fullres.h create mode 100644 Interframe EZBC/TempSub/inc/initN.h create mode 100644 Interframe EZBC/TempSub/inc/init_decN.h create mode 100644 Interframe EZBC/TempSub/inc/init_encN.h create mode 100644 Interframe EZBC/TempSub/inc/ioN.h create mode 100644 Interframe EZBC/TempSub/inc/layer_mv.h create mode 100644 Interframe EZBC/TempSub/inc/memoryN.h create mode 100644 Interframe EZBC/TempSub/inc/miscN.h create mode 100644 Interframe EZBC/TempSub/inc/mode_decision.h create mode 100644 Interframe EZBC/TempSub/inc/mv_ec.h create mode 100644 Interframe EZBC/TempSub/inc/mv_statistics.h create mode 100644 Interframe EZBC/TempSub/inc/mvcodingN.h create mode 100644 Interframe EZBC/TempSub/inc/obmc_varblk.h create mode 100644 Interframe EZBC/TempSub/inc/pstatN.h create mode 100644 Interframe EZBC/TempSub/inc/pull_res.h create mode 100644 Interframe EZBC/TempSub/inc/rasterfile.h create mode 100644 Interframe EZBC/TempSub/inc/structN.h create mode 100644 Interframe EZBC/TempSub/inc/unix_pc.h create mode 100644 Interframe EZBC/TempSub/inc/util_filtering.h create mode 100644 Interframe EZBC/TempSub/inc/zconf.h create mode 100644 Interframe EZBC/TempSub/inc/zlib.h create mode 100644 Interframe EZBC/TempSub/src/anal.c create mode 100644 Interframe EZBC/TempSub/src/arcode.cpp create mode 100644 Interframe EZBC/TempSub/src/binarcode.cpp create mode 100644 Interframe EZBC/TempSub/src/bitalloc.c create mode 100644 Interframe EZBC/TempSub/src/bmeN.c create mode 100644 Interframe EZBC/TempSub/src/bme_tools.cpp create mode 100644 Interframe EZBC/TempSub/src/chrom.c create mode 100644 Interframe EZBC/TempSub/src/cnv_data_4_1.c create mode 100644 Interframe EZBC/TempSub/src/dataio.c create mode 100644 Interframe EZBC/TempSub/src/decoderN.c create mode 100644 Interframe EZBC/TempSub/src/directional_iblock.c create mode 100644 Interframe EZBC/TempSub/src/display.c create mode 100644 Interframe EZBC/TempSub/src/dpxio.c create mode 100644 Interframe EZBC/TempSub/src/encoderN.c create mode 100644 Interframe EZBC/TempSub/src/golomb.cpp create mode 100644 Interframe EZBC/TempSub/src/hvsbm_fullres.c create mode 100644 Interframe EZBC/TempSub/src/init_decN.c create mode 100644 Interframe EZBC/TempSub/src/init_encN.c create mode 100644 Interframe EZBC/TempSub/src/intra_dec.c create mode 100644 Interframe EZBC/TempSub/src/intra_enc.c create mode 100644 Interframe EZBC/TempSub/src/ioN.c create mode 100644 Interframe EZBC/TempSub/src/layer_mv.c create mode 100644 Interframe EZBC/TempSub/src/lifting-only write Y.c create mode 100644 Interframe EZBC/TempSub/src/lifting.c create mode 100644 Interframe EZBC/TempSub/src/memoryN.c create mode 100644 Interframe EZBC/TempSub/src/miscN.c create mode 100644 Interframe EZBC/TempSub/src/mode_decision.c create mode 100644 Interframe EZBC/TempSub/src/mv_ec.cpp create mode 100644 Interframe EZBC/TempSub/src/mv_statistics.cpp create mode 100644 Interframe EZBC/TempSub/src/mvcodingN.c create mode 100644 Interframe EZBC/TempSub/src/obmc_varblk.c create mode 100644 Interframe EZBC/TempSub/src/pstatN.c create mode 100644 Interframe EZBC/TempSub/src/pull.c create mode 100644 Interframe EZBC/TempSub/src/ras_util.c create mode 100644 Interframe EZBC/TempSub/src/showtime.c create mode 100644 Interframe EZBC/TempSub/src/simul_func.cpp create mode 100644 Interframe EZBC/TempSub/src/simul_pull.c create mode 100644 Interframe EZBC/TempSub/src/spatial.c create mode 100644 Interframe EZBC/TempSub/src/subband_choi.c create mode 100644 Interframe EZBC/TempSub/src/syn.c create mode 100644 Interframe EZBC/Utils/inc/ar_code.h create mode 100644 Interframe EZBC/Utils/inc/general.h create mode 100644 Interframe EZBC/Utils/inc/ifc.h create mode 100644 Interframe EZBC/Utils/inc/image_bw.h create mode 100644 Interframe EZBC/Utils/inc/subband.h create mode 100644 Interframe EZBC/Utils/src/ar_code.cpp create mode 100644 Interframe EZBC/Utils/src/general.cpp create mode 100644 Interframe EZBC/Utils/src/image_bw.cpp create mode 100644 Interframe EZBC/Utils/src/subband.cpp diff --git a/Interframe EZBC/EZBC0a/inc/context_status_consts.h b/Interframe EZBC/EZBC0a/inc/context_status_consts.h new file mode 100644 index 0000000..3bca04d --- /dev/null +++ b/Interframe EZBC/EZBC0a/inc/context_status_consts.h @@ -0,0 +1,169 @@ +/* ========================================================================= */ +/* Description: definition and configuration of EZBC */ +/* Notes: modified from ebcot_constants.h */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +/* ========================================================================= */ +/*****************************************************************************/ +/* Copyright 1998, Hewlett-Packard Company */ +/* All rights reserved */ +/* File: "ebcot_constants.h" */ +/* Description: Constants which configure the EBCOT encoder and decoder */ +/* Author: David Taubman */ +/* Affiliation: Hewlett-Packard and */ +/* The University of New South Wales, Australia */ +/* Version: V3.1A */ +/* Last Revised: 14 January, 1999 */ +/*****************************************************************************/ +#ifndef _CONTEXT_CONSTANTS_H +#define _CONTEXTCONSTANTS_H +#include + +/* ========================================================================= */ +/* ---------------------------- Context Assignment ------------------------- */ +/* ========================================================================= */ + +#define TL_POS 0 /* Bit-pos for significance of top-left neighbour */ +#define TC_POS 1 /* Bit-pos for significance of top-centre neighbour */ + +#define TC2_POS 2 /*2nd Bit_pos for significance of top-centre neighbour */ + +#define TR_POS 3 /* Bit-pos for significance of top-right neighbour */ +#define CL_POS 4 /* Bit-pos for significance of centre-left neighbour */ +#define CL2_POS 5 /*2nd Bit-pos for significance of centre-left neighbour */ +#define CR_POS 6 /* Bit-pos for significance of centre-right neighbour */ +#define CR2_POS 7 /*2nd Bit-pos for significance of centre-right neighbour */ +#define BL_POS 8 /* Bit-pos for significance of bottom-left neighbour */ +#define BC_POS 9 /* Bit-pos for significance of bottom-centre neighbour */ +#define BC2_POS 10 /*2nd Bit-pos for significance of bottom-centre neighbour */ +#define BR_POS 11 /* Bit-pos for significance of bottom-right neighbour */ + +#define OUT_OF_BOUNDS_POS 15 /* May be used to identify context words which + lie beyond the boundaries of the code block */ + +#define TL_SIG ((std_short)(1< +#include "ar_code.h" +#include "subband.h" +#include "context_status_consts.h" + +//----------------------------------------------------------------------------- +typedef HistoBiModel MODEL_TYPE; //type of context prob models +typedef HistoBi STAT_MODEL_TYPE; //type of context prob models + +typedef SubSetLayer SUBBAND_TREE_TYPE; //class SubSetLayer: public SubSet in Utils/subband.h + + +typedef std_short PEL_CXT_TYPE; +typedef std_short NODE_CXT_TYPE; +typedef std_byte SIGN_CXT_TYPE; + + +struct Image_Coord_Sht +{ + std_short r, c; +}; + +struct Quad_Tree +{ + int depth; + int qtree_sz; + Image_Coord_Sht *dims; + SUB_COEFF_TYPE ***nodes; +}; + +struct Node_Entry +{ + int level; + std_int node; +}; + +struct List +{ + std_int *LIP; + std_int *LIP_end; + std_int *LIP_prev_mark; + std_int *LIP_old_end; + std_int LIP_sz; + std_int *LSP; + std_int *LSP_end; + std_int LSP_mark[sizeof( SUB_COEFF_TYPE ) * 8]; + int LSP_plane; + std_int **LIS; + std_int **LIS_end; + std_int **LIS_prev_mark; + std_int **LIS_old_end; + Node_Entry *LIS_stack; + Node_Entry *LIS_stack_top; + + std_int **LSP_bit_idx_marks; + std_int ***LSP_ids; +}; + +struct PassStats +{ + std_int cumulative_bytes; + double delta_mse; + float rd_slope; + std_int pass_bytes; +}; + +struct BitPlaneStats +{ + PassStats *passes; +}; + +struct CodingStats +{ + BitPlaneStats *bitplanes; +}; + +struct Cxt_States +{ + int cxt_qtree_sz; + NODE_CXT_TYPE ***cxt_nodes; + PEL_CXT_TYPE **base_cxt; + SIGN_CXT_TYPE **base_sign_cxt; + int *sig_cxts; + int *sig_offsets; + std_byte **sig_tabs; + int *node_cxts; + int *node_offsets; + std_byte **node_tabs; + int LIP_cxts; + int LIP_offset; + std_byte *LIP_tab; + int LSP_cxts; + int LSP_offset; + std_byte *LSP_tab; + int sign_cxts; + int sign_offset; + SUB_COEFF_TYPE *sign_tab; //SUB_COEFF_TYPE used, + //see setup_cxt_tables() for details + int total_cxts; + MODEL_TYPE *cxt_models; + + int **jsig_cxts; + int **jsig_offsets; + std_byte ***jsig_tabs; +}; + +class SubbandCodec +{ +protected: + int bit_idx, max_bit_idx, min_bit_idx, no_bitplanes, no_passes, cur_pass, + cur_lev; + SUB_COEFF_TYPE **base_coeff, bit_idx_mask; + SUBBAND_TYPE *band; + List node_list; + Quad_Tree qtree; + Cxt_States cxt_qtree, *child_cxt_qtree, *grand_child_cxt_qtree; +#ifdef GET_PARENT_MODELS + Cxt_States *par_cxt_qtree; +#endif + CodingStats coding_stats; + FILE *fpout; + + void initialize_node_list( void ); + void clear_node_list( void ); + void create_coding_stats( void ); + void delete_coding_stats( void ); + void set_bit_idx_mask( void ) + { + bit_idx_mask = ( SUB_COEFF_TYPE ) ( 0x1 << bit_idx ); + } + void initialize_cxt_models( void ); //cxt related + void create_cxt_models_AC0( void ); + void create_cxt_models_EBCOT( void ); + void create_cxt_models( void ); + void reset_cxt_models( void ); + void update_node_cxts( void ); + + +//============================================================================= + +//static variables, cxt lookup tables + +//=========================================================================== +// static long BYTE_BUDGET; + static std_byte *sm0_sp_main_node_lut, *sm0_sp_diag_node_lut; + + static std_byte *mid_inter_and_sp_main_node_lut; + static std_byte *mid_inter_and_sp_diag_node_lut; + static int sm0_sp_main_node_cxts, sm0_sp_diag_node_cxts; + + static int mid_inter_and_sp_main_node_cxts; + static int mid_inter_and_sp_diag_node_cxts; + + static std_byte *mid_main_jsig_00_lut, *mid_diag_jsig_00_lut; + static std_byte *mid_main_jsig_01_lut, *mid_diag_jsig_01_lut; + static std_byte *mid_main_jsig_10_lut, *mid_diag_jsig_10_lut; + static std_byte *mid_main_jsig_11_lut, *mid_diag_jsig_11_lut; + + static int mid_main_jsig_00_cxts, mid_diag_jsig_00_cxts; + static int mid_main_jsig_01_cxts, mid_diag_jsig_01_cxts; + static int mid_main_jsig_10_cxts, mid_diag_jsig_10_cxts; + static int mid_main_jsig_11_cxts, mid_diag_jsig_11_cxts; + + static std_byte *mid_main_jsig0_00_lut, *mid_diag_jsig0_00_lut; + static std_byte *mid_main_jsig0_01_lut, *mid_diag_jsig0_01_lut; + static std_byte *mid_main_jsig0_10_lut, *mid_diag_jsig0_10_lut; + static std_byte *mid_main_jsig0_11_lut, *mid_diag_jsig0_11_lut; + + static int mid_main_jsig0_00_cxts, mid_diag_jsig0_00_cxts; + static int mid_main_jsig0_01_cxts, mid_diag_jsig0_01_cxts; + static int mid_main_jsig0_10_cxts, mid_diag_jsig0_10_cxts; + static int mid_main_jsig0_11_cxts, mid_diag_jsig0_11_cxts; + + static std_byte *mid_main_LSP_lut, *mid_diag_LSP_lut; + static int mid_main_LSP_cxts, mid_diag_LSP_cxts; + +#ifdef TWO_SIGNIF_BITS + + static std_byte *sm3_2_signif_bits_main_LSP_lut; + static std_byte *sm3_2_signif_bits_diag_LSP_lut; + static int sm3_2_signif_bits_main_LSP_cxts, sm3_2_signif_bits_diag_LSP_cxts; +#endif + + + static SUB_COEFF_TYPE *mid_main_sign_lut, *mid_diag_sign_lut; + static int mid_main_sign_cxts, mid_diag_sign_cxts; + +public: + SubbandCodec( void ) + { + fpout = stdout; + } + SubbandCodec( SUBBAND_TYPE * subband ) { + initialize( subband ); + } + ~SubbandCodec( void ); + int initialize( SUBBAND_TYPE * subband ); + void reset_band( SUBBAND_TYPE * subband ) + { + band = subband; + } + //int get_no_bitplanes(void){return no_bitplanes;} + int get_max_bit_idx( ) + { + return max_bit_idx; + } + void set_fpout( FILE * fp ) + { + fpout = fp; + } + void reset_band_codec( SUBBAND_TYPE * subband ); + int get_qtree_depth( void ) + { + return qtree.depth; + } + + + static void setup_luts( void ); + static void delete_cxt_tables( void ); + /*static void set_byte_budget(long assigned_bytes){ + BYTE_BUDGET = assigned_bytes;} */ + static void initialize_zc_luts( void ); + static void initialize_sc_lut( void ); + + static void initialize_sm0_sp_node_luts( void ); + static void initialize_inter_and_sp_node_luts( void ); + + static void initialize_mid_LSP_luts( void ); + + static void initialize_mid_sign_luts( void ); + +#ifdef TWO_SIGNIF_BITS + static void initialize_sm3_2_signif_bits_LSP_luts( void ); +#endif + + static void initialize_mid_jsig_luts( void ); + + static void initialize_mid_jsig0_00_luts( void ); + static void initialize_mid_jsig0_01_luts( void ); + static void initialize_mid_jsig0_10_luts( void ); + static void initialize_mid_jsig0_11_luts( void ); +}; + +class SubbandTreeCodec +{ +protected: + SUBBAND_TREE_TYPE * subband_tree; + int tree_msb, tree_lsb; + long total_byte_budget; + int subblock_dim; + FILE *fpout; +public: + SubbandTreeCodec( void ) + { + subband_tree = NULL; + fpout = stdout; + } + SubbandTreeCodec( SUBBAND_TREE_TYPE * subs ); + ~SubbandTreeCodec( void ); + int get_tree_msb( ) + { + return tree_msb; + } + int get_tree_lsb( ) + { + return tree_lsb; + } + void set_total_byte_budget( long total_byte ) + { + total_byte_budget = total_byte; + } + void set_fpout( FILE * fp ) + { + fpout = fp; + } + void initialize( SUBBAND_TREE_TYPE * subs ); + void reset_tree_codec( SUBBAND_TREE_TYPE * subs ); +}; + +#define UPDATE_CXT(cp, row_gap){ (cp)[-1] |= CR_SIG;\ + (cp)[1] |= CL_SIG; (cp)[-row_gap] |= BC_SIG; (cp)[row_gap] |= TC_SIG;\ + (cp)[-row_gap-1] |= BR_SIG; (cp)[-row_gap+1] |= BL_SIG;\ + (cp)[row_gap-1] |= TR_SIG; (cp)[row_gap+1] |= TL_SIG;} + + + +#ifdef UPDATE_SIGN_DIAG_CXT + +#define UPDATE_SIGN_CXT(cp, row_gap, sign_bit){ \ + if(sign_bit){ (cp)[-1] |= H_NVE_MASK; (cp)[1] |= H_NVE_MASK;\ + (cp)[-row_gap] |= V_NVE_MASK; (cp)[row_gap] |= V_NVE_MASK;\ + (cp)[-row_gap-1] |= NW_NVE_MASK; (cp)[-row_gap+1] |= NE_NVE_MASK;\ + (cp)[row_gap+1] |= NW_NVE_MASK; (cp)[row_gap-1] |= NE_NVE_MASK;}\ + else{ (cp)[-1] |= H_PVE_MASK; (cp)[1] |= H_PVE_MASK;\ + (cp)[-row_gap] |= V_PVE_MASK; (cp)[row_gap] |= V_PVE_MASK;\ + (cp)[row_gap+1] |= NW_PVE_MASK; (cp)[row_gap-1] |= NE_PVE_MASK;}} + +#else + + +#define UPDATE_SIGN_CXT(cp, row_gap, sign_bit){ \ + if(sign_bit){ (cp)[-1] |= H_NVE_MASK; (cp)[1] |= H_NVE_MASK;\ + (cp)[-row_gap] |= V_NVE_MASK; (cp)[row_gap] |= V_NVE_MASK;}\ + else{ (cp)[-1] |= H_PVE_MASK; (cp)[1] |= H_PVE_MASK;\ + (cp)[-row_gap] |= V_PVE_MASK; (cp)[row_gap] |= V_PVE_MASK;}} + +#endif + + +#define UPDATE_1_CD_NODE(cd_node){*cd_node |= PA_SIG;} +#define UPDATE_4_CD_NODES(cd_node, cd_node_row_gap){\ + cd_node[0] |= PA_SIG; cd_node[1] |= PA_SIG; \ + cd_node[cd_node_row_gap] |= PA_SIG; cd_node[cd_node_row_gap+1] |= PA_SIG;} + +#endif // file dwt_bitplane_codec.h diff --git a/Interframe EZBC/EZBC0a/inc/dwt_bitplane_dec.h b/Interframe EZBC/EZBC0a/inc/dwt_bitplane_dec.h new file mode 100644 index 0000000..8bc0847 --- /dev/null +++ b/Interframe EZBC/EZBC0a/inc/dwt_bitplane_dec.h @@ -0,0 +1,107 @@ +/* ========================================================================= */ +/* Description: definition for class DecSubband and DecSubbandTree */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ +#ifndef _DWT_DEC_H +#define _DWT_DEC_H + +#include "dwt_bitplane_codec.h" + +typedef Decoder DECODER_TYPE; + +class DecSubband; //forward def. +class DecSubbandTree; +class EzbcDec3d; + +typedef DecSubband DEC_SUBBAND_TYPE; +typedef DecSubbandTree DEC_SUBBAND_TREE_TYPE; + + +class DecSubband:public SubbandCodec +{ + friend class DecSubbandTree; + friend class EzbcDec3d; +protected: + DecSubbandTree * dec_band_tree; + DECODER_TYPE *sub_decoder; + std_int *LSP_break_pt; + + void create_max_and_cxt_qtrees( void ); + void setup_cxt_qtrees( void ); + void set_functions( void ); + void reset_band_dec( SUBBAND_TYPE * subband ); + + void decode_LIP_cxt_AC( void ); //dwt_bitplane_dec_cxt_AC.C + void decode_sig_leaf_cxt_AC( std_int cur_coord ); + void decode_sig_node_cxt_AC( std_int cur_coord, int lev ); + void decode_LIS_leaves_cxt_AC( void ); + void decode_cur_qtree_level_cxt_AC( void ); + void decode_LSP_cxt_AC( void ); + void decode_LSP_cxt_AC_and_bit_idx( void ); + + //dwt_bitplane_enc_pos_dep_cxt_AC.C + void decode_sig_leaf_pos_dep_cxt_AC( std_int cur_coord ); + void decode_sig_node_pos_dep_cxt_AC( std_int cur_coord, int lev ); + + void ( DecSubband::*decode_LIP ) ( void ); + void ( DecSubband::*decode_LSP ) ( void ); + void ( DecSubband::*decode_sig_node ) ( std_int cur_coord, int lev ); + void ( DecSubband::*decode_sig_leaf ) ( std_int cur_coord ); + void ( DecSubband::*decode_LIS_leaves ) ( void ); + void ( DecSubband::*decode_cur_qtree_level ) ( void ); + void decode_LIS_nodes( void ); + void decode_LIS_stack( ); +public: + DecSubband( void ) + { + sub_decoder = NULL; + dec_band_tree = NULL; + } + // ~DecSubband(void){if (sub_decoder) delete [] sub_decoder; } + DecSubband( SUBBAND_TYPE * band, DecSubbandTree * dec_tree, + DECODER_TYPE * dec ) + { + initialize( band, dec_tree, dec ); + } + void initialize( SUBBAND_TYPE * subband, DecSubbandTree * dec_tree, + DECODER_TYPE * dec = NULL ); + + void initialize2( SUBBAND_TYPE * subband, DecSubbandTree * dec_tree ); + + + int start_dec_subband( void ); + void rec_subband( ); +}; + +class DecSubbandTree:public SubbandTreeCodec +{ + friend class DecSubband; + friend class EzbcDec3d; +protected: + DECODER_TYPE * decoder; + DEC_SUBBAND_TYPE *dec_subs; +public: + DecSubbandTree( void ) + { + dec_subs = NULL; + } + DecSubbandTree( SUBBAND_TREE_TYPE * subs, DECODER_TYPE * dec ); + ~DecSubbandTree( void ) + { + if( dec_subs ) + delete[]dec_subs; + } + void set_decoder( DECODER_TYPE * dec ) + // int set_decoder( DECODER_TYPE * dec ) + { + decoder = dec; + } + void rec_subbands( void ); + void initialize( SUBBAND_TREE_TYPE * subs, DECODER_TYPE * dec ); + void initialize( SUBBAND_TREE_TYPE * subs, int *subband_ACcoder, DECODER_TYPE * enc ); //062602 + void reset_tree_dec( SUBBAND_TREE_TYPE * subs ); +}; + +#endif diff --git a/Interframe EZBC/EZBC0a/inc/dwt_bitplane_enc.h b/Interframe EZBC/EZBC0a/inc/dwt_bitplane_enc.h new file mode 100644 index 0000000..ba22c34 --- /dev/null +++ b/Interframe EZBC/EZBC0a/inc/dwt_bitplane_enc.h @@ -0,0 +1,109 @@ +/* ========================================================================= */ +/* Description: definition for classes EncSubband and EncSubbandTree */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#ifndef _DWT_ENC_H +#define _DWT_ENC_H + +#include "dwt_bitplane_codec.h" + +typedef Encoder ENCODER_TYPE; + +class EncSubband; //forward def. +class EncSubbandTree; +class EzbcEnc3d; + +typedef EncSubband ENC_SUBBAND_TYPE; +typedef EncSubbandTree ENC_SUBBAND_TREE_TYPE; + +class EncSubband:public SubbandCodec // class SubbandCodec defined in dwt_bitplane_codec.h +{ + friend class EncSubbandTree; + friend class EzbcEnc3d; +protected: + SUB_COEFF_TYPE mag_mask; //typedef ifc_int SUB_COEFF_TYPE;Utils/subband.h + EncSubbandTree *enc_band_tree; + ENCODER_TYPE *sub_encoder; + + void create_max_and_cxt_qtrees( void ); + void setup_max_and_cxt_qtrees( void ); + void set_functions( void ); + + void encode_LIP_cxt_AC( void ); //dwt_bitplane_enc_cxt_AC.C + void encode_sig_leaf_cxt_AC( std_int cur_coord ); + void encode_sig_node_cxt_AC( std_int cur_coord, int lev ); + void encode_LIS_leaves_cxt_AC( void ); + void encode_cur_qtree_level_cxt_AC( void ); + void encode_LSP_cxt_AC( void ); + void encode_LSP_cxt_AC_and_bit_idx( void ); + + //dwt_bitplane_enc_pos_dep_cxt_AC.C + void encode_sig_leaf_pos_dep_cxt_AC( std_int cur_coord ); + void encode_sig_node_pos_dep_cxt_AC( std_int cur_coord, int lev ); + + void ( EncSubband::*encode_LIP ) ( void ); // see EncSubband::set_functions + void ( EncSubband::*encode_sig_node ) ( std_int cur_coord, int lev ); + void ( EncSubband::*encode_sig_leaf ) ( std_int cur_coord ); + void ( EncSubband::*encode_LIS_leaves ) ( void ); + void ( EncSubband::*encode_cur_qtree_level ) ( void ); + void ( EncSubband::*encode_LSP ) ( void ); + void encode_LIS_nodes( void ); + void encode_LIS_stack( void ); + void set_mag_mask( void ) + { + mag_mask = ( SUB_COEFF_TYPE ) ( MAX_SUB_COEFF & ( ( -1 ) << bit_idx ) ); + } + +public: + EncSubband( void ):SubbandCodec( ) + { + sub_encoder = NULL; + enc_band_tree = NULL; + } +// EncSubband(SUBBAND_TYPE* band, EncSubbandTree *enc_tree , ENCODER_TYPE *enc) //comment out 062602 +// {initialize(band, enc_tree, enc);} +// ~EncSubband(void){ if (sub_encoder) delete [] sub_encoder;} + + void initialize( SUBBAND_TYPE * subband, EncSubbandTree * enc_tree, + ENCODER_TYPE * enc = NULL ); + + //void initialize2(SUBBAND_TYPE* subband, EncSubbandTree *enc_tree); //062602 + + int start_enc_subband( void ); + void reset_band_enc( SUBBAND_TYPE * band ); +}; + + +class EncSubbandTree:public SubbandTreeCodec +{ + + friend class EncSubband; + friend class EzbcEnc3d; +protected: + ENCODER_TYPE * encoder; + ENC_SUBBAND_TYPE *enc_subs; +public: + EncSubbandTree( void ):SubbandTreeCodec( ) + { + enc_subs = NULL; + encoder = NULL; + } + EncSubbandTree( SUBBAND_TREE_TYPE * subs, ENCODER_TYPE * enc ); + ~EncSubbandTree( void ) + { + if( enc_subs ) + delete[]enc_subs; + } + void set_encoder( ENCODER_TYPE * enc ) + { + encoder = enc; + } + void initialize( SUBBAND_TREE_TYPE * subs, int *subband_ACcoder, ENCODER_TYPE * enc ); //062602 + void initialize( SUBBAND_TREE_TYPE * subs, ENCODER_TYPE * enc ); + void reset_tree_enc( SUBBAND_TREE_TYPE * subs ); +}; + +#endif diff --git a/Interframe EZBC/EZBC0a/src/dec_subband_tree.cpp b/Interframe EZBC/EZBC0a/src/dec_subband_tree.cpp new file mode 100644 index 0000000..f2fd2ec --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dec_subband_tree.cpp @@ -0,0 +1,79 @@ +/* ========================================================================= */ +/* Description: menber functions for class DecSubbandTree */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include "dwt_bitplane_dec.h" + +DecSubbandTree::DecSubbandTree( SUBBAND_TREE_TYPE * subs, DECODER_TYPE * dec ) +:SubbandTreeCodec( subs ), decoder( dec ) +{ + + int nbands = subband_tree->get_nband( ); + NEW_VECTOR( dec_subs, nbands, DEC_SUBBAND_TYPE, "SubbandDec" ); + for( int k = 0; k < nbands; k++ ) + dec_subs[k].initialize( subband_tree->get_band_ptr( k ), this, dec ); +} + +void +DecSubbandTree::initialize( SUBBAND_TREE_TYPE * subs, DECODER_TYPE * dec ) +{ + SubbandTreeCodec::initialize( subs ); + decoder = dec; + + int nbands = subband_tree->get_nband( ); + NEW_VECTOR( dec_subs, nbands, DEC_SUBBAND_TYPE, "SubbandDec" ); + for( int k = 0; k < nbands; k++ ) + dec_subs[k].initialize( subband_tree->get_band_ptr( k ), this, dec ); + +} + +void +DecSubbandTree:: + +initialize( SUBBAND_TREE_TYPE * subs, int *subband_ACcoder, + DECODER_TYPE * dec ) +{ +// SubbandTreeCodec::initialize(subs); + + int nbands = subband_tree->get_nband( ); + NEW_VECTOR( dec_subs, nbands, DEC_SUBBAND_TYPE, "SubbandDec" ); + + + for( int k = 0; k < nbands; k++ ) + dec_subs[k].initialize( subband_tree->get_band_ptr( k ), this, + &dec[subband_ACcoder[k]] ); + +} + +void +DecSubbandTree::reset_tree_dec( SUBBAND_TREE_TYPE * subs ) +{ + reset_tree_codec( subs ); + int nbands = subband_tree->get_nband( ); + for( int k = 0; k < nbands; k++ ) { + dec_subs[k].reset_band_dec( subband_tree->get_band_ptr( k ) ); + } +} + + + +//----------------------------------------------------------------------------- + +// rec_subbands(void) + +//----------------------------------------------------------------------------- +void +DecSubbandTree::rec_subbands( void ) +{ + int pyr_lev, nband; + + pyr_lev = subband_tree->get_pyr_levels( ); + nband = subband_tree->get_nband( ); + + for( int k = 0; k < nband; dec_subs[k++].rec_subband( ) ); +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_codec.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_codec.cpp new file mode 100644 index 0000000..059a670 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_codec.cpp @@ -0,0 +1,699 @@ +/* ========================================================================= */ +/* Description: menber functions for class SubbandCodec */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ +#include +#include +#include "dwt_bitplane_codec.h" + +#ifdef NDEBUG +#define myassert(seq) seq +#else +#define myassert(seq) assert(seq) +#endif + +//long SubbandCodec::BYTE_BUDGET = MAX_STD_INT; + +SubbandCodec::~SubbandCodec( ) +{ + + delete_coding_stats( ); + + if( qtree.nodes ) { + delete[]qtree.nodes[1][0]; + delete[]qtree.nodes[1]; + DELETE_VECTOR( qtree.nodes ); + } + + if( cxt_qtree.cxt_nodes ) { + cxt_qtree.cxt_nodes[1][-WIDTH_OF_CXT_BDY] -= WIDTH_OF_CXT_BDY; + delete[]cxt_qtree.cxt_nodes[1][-WIDTH_OF_CXT_BDY]; + cxt_qtree.cxt_nodes[1] -= WIDTH_OF_CXT_BDY; + delete[]cxt_qtree.cxt_nodes[1]; + DELETE_VECTOR( cxt_qtree.cxt_nodes ); + } + if( cxt_qtree.base_cxt ) { + delete[]( cxt_qtree.base_cxt[-WIDTH_OF_CXT_BDY] - WIDTH_OF_CXT_BDY ); + cxt_qtree.base_cxt -= WIDTH_OF_CXT_BDY; + DELETE_VECTOR( cxt_qtree.base_cxt ); + } + if( cxt_qtree.base_sign_cxt ) { + delete[]( cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY] - WIDTH_OF_CXT_BDY ); + cxt_qtree.base_sign_cxt -= WIDTH_OF_CXT_BDY; + DELETE_VECTOR( cxt_qtree.base_sign_cxt ); + } + + clear_node_list( ); + + DELETE_VECTOR( qtree.dims ); + DELETE_VECTOR( cxt_qtree.sig_cxts ); + DELETE_VECTOR( cxt_qtree.sig_offsets ); + DELETE_VECTOR( cxt_qtree.sig_tabs ); + + if( cxt_qtree.node_cxts ) { + cxt_qtree.node_cxts++; + DELETE_VECTOR( cxt_qtree.node_cxts ); + } + if( cxt_qtree.node_offsets ) { + cxt_qtree.node_offsets++; + DELETE_VECTOR( cxt_qtree.node_offsets ); + } + if( cxt_qtree.node_tabs ) { + cxt_qtree.node_tabs++; + DELETE_VECTOR( cxt_qtree.node_tabs ); + } + DELETE_VECTOR( cxt_qtree.cxt_models ); + + if( cxt_qtree.jsig_cxts ) { + delete[]cxt_qtree.jsig_cxts[0]; + DELETE_VECTOR( cxt_qtree.jsig_cxts ); + } + if( cxt_qtree.jsig_offsets ) { + delete[]cxt_qtree.jsig_offsets[0]; + DELETE_VECTOR( cxt_qtree.jsig_offsets ); + } + if( cxt_qtree.jsig_tabs ) { + delete[]cxt_qtree.jsig_tabs[0]; + DELETE_VECTOR( cxt_qtree.jsig_tabs ); + } +} + +void +SubbandCodec::delete_coding_stats( void ) +{ + if( coding_stats.bitplanes ) { + for( int n = 0; n < no_bitplanes; n++ ) + delete[]coding_stats.bitplanes[EXTRA_BIT + n].passes; + coding_stats.bitplanes += EXTRA_BIT; + DELETE_VECTOR( coding_stats.bitplanes ); + } +} + +//----------------------------------------------------------------------------- + +// initialize() + +//----------------------------------------------------------------------------- +int +SubbandCodec::initialize( SUBBAND_TYPE * subband ) +{ + memset( this, 0, sizeof( SubbandCodec ) ); + + //assert(band = subband); + myassert( band = subband ); + if( subband->get_orientation( ) == HL ) + subband->transpose( ); + base_coeff = band->get_coeff( ); + + fpout = stdout; + + return 0; +} + +void +SubbandCodec::reset_band_codec( SUBBAND_TYPE * subband ) +{ + //assert(band = subband); + myassert( band = subband ); + if( subband->get_orientation( ) == HL ) + subband->transpose( ); + base_coeff = band->get_coeff( ); + cur_pass = cur_lev = 0; + for( int i = cxt_qtree.total_cxts - 1; i >= 0; + cxt_qtree.cxt_models[i--].reset( ) ); +} + +//----------------------------------------------------------------------------- + +// initialize_node_list() + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_node_list( void ) +{ + clear_node_list( ); + + int i, depth = qtree.depth; + Image_Coord_Sht *dims = qtree.dims; + std_int band_size = dims[0].r * dims[0].c; + int tree_sz = qtree.qtree_sz; + + + node_list.LIP_sz = ( std_int ) band_size; + NEW_VECTOR( node_list.LIP, band_size, std_int, "node_list.LIP" ); + node_list.LSP = node_list.LIP; + NEW_VECTOR( node_list.LIS, depth, std_int *, "node_list.LIS" ); + ( node_list.LIS )--; + + std_int **LIS = node_list.LIS; + + NEW_VECTOR( LIS[1], tree_sz, std_int, "node_list.LIS[1]" ); + int lev; + for( lev = 1; lev < depth; lev++ ) { + LIS[lev + 1] = LIS[lev] + dims[lev].r * dims[lev].c; + } + NEW_VECTOR( node_list.LIS_end, depth, std_int *, "node_list.LIS_end" ); + ( node_list.LIS_end )--; + for( lev = 1; lev <= depth; lev++ ) { + node_list.LIS_end[lev] = node_list.LIS[lev] - 1; + } + //*(++node_list.LIS_end[depth]) = 0; //root node + + NEW_VECTOR( node_list.LIS_prev_mark, depth, std_int *, + "node_list.LIS_prev_mark" ); + ( node_list.LIS_prev_mark )--; + + NEW_VECTOR( node_list.LIS_old_end, depth, std_int *, + "node_list.LIS_old_end" ); + ( node_list.LIS_old_end )--; + + NEW_VECTOR( node_list.LIS_stack, depth << 2, Node_Entry, + "node_list.LIS_stack" ); + + node_list.LIS_stack_top = node_list.LIS_stack - 1; + + node_list.LSP_plane = 0; + node_list.LSP_end = node_list.LSP - 1; + node_list.LIP_end = node_list.LIP + band_size; + + NEW_VECTOR( node_list.LSP_bit_idx_marks, no_bitplanes, std_int *, + "LSP_bit_idx_marks" ); + memset( node_list.LSP_bit_idx_marks, 0, + sizeof( std_int * ) * no_bitplanes ); + node_list.LSP_bit_idx_marks -= EXTRA_BIT; + + NEW_VECTOR( node_list.LSP_ids, no_bitplanes, std_int **, "LSP_ids" ); + node_list.LSP_ids -= EXTRA_BIT; + + NEW_VECTOR( node_list.LSP_ids[EXTRA_BIT], no_bitplanes * depth, + std_int *, "LSP_ids[bit_idx]" ); + memset( node_list.LSP_ids[EXTRA_BIT], 0, + sizeof( std_int * ) * no_bitplanes * depth ); + for( i = EXTRA_BIT; i < max_bit_idx; i++ ) + node_list.LSP_ids[i + 1] = node_list.LSP_ids[i] + depth; + +} + +//----------------------------------------------------------------------------- + +// clear_node_list() + +//----------------------------------------------------------------------------- +void +SubbandCodec::clear_node_list( ) +{ + + DELETE_VECTOR( node_list.LIP ); + if( node_list.LIS ) { + DELETE_VECTOR( node_list.LIS[1] ); + ( node_list.LIS )++; + DELETE_VECTOR( node_list.LIS ); + } + if( node_list.LIS_end ) { + ( node_list.LIS_end )++; + DELETE_VECTOR( node_list.LIS_end ); + } + if( node_list.LIS_prev_mark ) { + ( node_list.LIS_prev_mark )++; + DELETE_VECTOR( node_list.LIS_prev_mark ); + } + if( node_list.LIS_old_end ) { + ( node_list.LIS_old_end )++; + DELETE_VECTOR( node_list.LIS_old_end ); + } + DELETE_VECTOR( node_list.LIS_stack ); + + if( node_list.LSP_ids ) { + //delete [] node_list.LSP_ids[EXTRA_BIT]; + DELETE_VECTOR( node_list.LSP_ids[EXTRA_BIT] ); //Peisong + + + node_list.LSP_ids += EXTRA_BIT; + DELETE_VECTOR( node_list.LSP_ids ); + } + if( node_list.LSP_bit_idx_marks ) { + node_list.LSP_bit_idx_marks += EXTRA_BIT; + DELETE_VECTOR( node_list.LSP_bit_idx_marks ); + } +} + +//----------------------------------------------------------------------------- + +// create_coding_stats() + +//----------------------------------------------------------------------------- +void +SubbandCodec::create_coding_stats( ) +{ + + // delete_coding_stats(); + +#ifdef LSP_BIT_IDX + no_passes = qtree.depth + 5; //LIP, 1 ~ depth-1, LSP 0-4 +#else + no_passes = qtree.depth + 1; //LIP, 1 ~ depth-1, LSP +#endif + //for now + no_passes = 32; + + NEW_VECTOR( coding_stats.bitplanes, no_bitplanes, BitPlaneStats, + "plane_stats" ); + + coding_stats.bitplanes -= EXTRA_BIT; + + for( int n = 0; n < no_bitplanes; n++ ) { + NEW_VECTOR( coding_stats.bitplanes[EXTRA_BIT + n].passes, + no_passes, PassStats, "PassStat" ); + memset( coding_stats.bitplanes[EXTRA_BIT + n].passes, 0, + sizeof( PassStats ) * no_passes ); + } +} + +//----------------------------------------------------------------------------- + +// initialize_cxt_models() + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_cxt_models( ) +{ + int i, depth = qtree.depth; + + //0 ~ depth-1 + NEW_VECTOR( cxt_qtree.sig_cxts, depth, int, "sig_cxts" ); + NEW_VECTOR( cxt_qtree.sig_offsets, depth, int, "sig_offsets" ); + NEW_VECTOR( cxt_qtree.sig_tabs, depth, std_byte *, "sig_tabs" ); + + //0 ~ depth-1 + NEW_VECTOR( cxt_qtree.jsig_cxts, depth, int *, "sig_cxts" ); + NEW_VECTOR( cxt_qtree.jsig_offsets, depth, int *, "sig_offsets" ); + NEW_VECTOR( cxt_qtree.jsig_tabs, depth, std_byte **, "sig_tabs" ); + + NEW_VECTOR( cxt_qtree.jsig_cxts[0], depth << 2, int, "sig_cxts" ); + NEW_VECTOR( cxt_qtree.jsig_offsets[0], depth << 2, int, "sig_offsets" ); + NEW_VECTOR( cxt_qtree.jsig_tabs[0], depth << 2, std_byte *, "sig_tabs" ); + + for( i = 1; i < depth; i++ ) { + cxt_qtree.jsig_cxts[i] = cxt_qtree.jsig_cxts[i - 1] + 4; + cxt_qtree.jsig_offsets[i] = cxt_qtree.jsig_offsets[i - 1] + 4; + cxt_qtree.jsig_tabs[i] = cxt_qtree.jsig_tabs[i - 1] + 4; + } + //1 ~ depth-1, lev0 is represented by LIP + NEW_VECTOR( cxt_qtree.node_cxts, depth - 1, int, "node_cxts" ); + cxt_qtree.node_cxts--; + NEW_VECTOR( cxt_qtree.node_offsets, depth - 1, int, "node_offsets" ); + cxt_qtree.node_offsets--; + NEW_VECTOR( cxt_qtree.node_tabs, depth - 1, std_byte *, "node_tabs" ); + cxt_qtree.node_tabs--; + + create_cxt_models( ); + + int total = cxt_qtree.total_cxts; + + NEW_VECTOR( cxt_qtree.cxt_models, total, MODEL_TYPE, "MODEL_TYPE" ); + + for( i = total - 1; i >= 0; cxt_qtree.cxt_models[i--].set_symbols( 2 ) ); +} + + +//----------------------------------------------------------------------------- + +// create_cxt_models() + +//----------------------------------------------------------------------------- +void +SubbandCodec::create_cxt_models( void ) +{ + int i, lev, total; + int node_zc_cxts, LIP_zc_cxts, LSP_cxts, sign_cxts; + std_byte *node_zc_lut, *LIP_zc_lut, *LSP_lut; + SUB_COEFF_TYPE *sign_lut; + // Image_Coord_Sht *dims = qtree.dims; + + int sig_zc_cxts[4], sig0_zc_cxts[4]; + std_byte *sig_zc_lut[4], *sig0_zc_lut[4]; + + int depth = qtree.depth; + + if( band->get_orientation( ) == HH ) { + + //assert(LIP_zc_lut = sm0_sp_diag_node_lut); + myassert( LIP_zc_lut = sm0_sp_diag_node_lut ); + LIP_zc_cxts = sm0_sp_diag_node_cxts; + + //assert(node_zc_lut = mid_inter_and_sp_diag_node_lut); + myassert( node_zc_lut = mid_inter_and_sp_diag_node_lut ); + node_zc_cxts = mid_inter_and_sp_diag_node_cxts; + + //assert(sig0_zc_lut[0] = mid_diag_jsig0_00_lut); + myassert( sig0_zc_lut[0] = mid_diag_jsig0_00_lut ); + sig0_zc_cxts[0] = mid_diag_jsig0_00_cxts; + + //assert(sig_zc_lut[0] = mid_diag_jsig_00_lut); + myassert( sig_zc_lut[0] = mid_diag_jsig_00_lut ); + sig_zc_cxts[0] = mid_diag_jsig_00_cxts; + + + //assert(sig0_zc_lut[1] = mid_diag_jsig0_01_lut); + myassert( sig0_zc_lut[1] = mid_diag_jsig0_01_lut ); + sig0_zc_cxts[1] = mid_diag_jsig0_01_cxts; + //assert(sig_zc_lut[1] = mid_diag_jsig_01_lut); + myassert( sig_zc_lut[1] = mid_diag_jsig_01_lut ); + sig_zc_cxts[1] = mid_diag_jsig_01_cxts; + + + //assert(sig0_zc_lut[2] = mid_diag_jsig0_10_lut); + myassert( sig0_zc_lut[2] = mid_diag_jsig0_10_lut ); + sig0_zc_cxts[2] = mid_diag_jsig0_10_cxts; + //assert(sig_zc_lut[2] = mid_diag_jsig_10_lut); + myassert( sig_zc_lut[2] = mid_diag_jsig_10_lut ); + sig_zc_cxts[2] = mid_diag_jsig_10_cxts; + + //assert(sig0_zc_lut[3] = mid_diag_jsig0_11_lut); + myassert( sig0_zc_lut[3] = mid_diag_jsig0_11_lut ); + sig0_zc_cxts[3] = mid_diag_jsig0_11_cxts; + //assert(sig_zc_lut[3] = mid_diag_jsig_11_lut); + myassert( sig_zc_lut[3] = mid_diag_jsig_11_lut ); + sig_zc_cxts[3] = mid_diag_jsig_11_cxts; + + } else { + + //assert(LIP_zc_lut = sm0_sp_main_node_lut); + myassert( LIP_zc_lut = sm0_sp_main_node_lut ); + LIP_zc_cxts = sm0_sp_main_node_cxts; + + //assert(node_zc_lut = mid_inter_and_sp_main_node_lut); + myassert( node_zc_lut = mid_inter_and_sp_main_node_lut ); + node_zc_cxts = mid_inter_and_sp_main_node_cxts; + + //assert(sig0_zc_lut[0] = mid_main_jsig0_00_lut); + myassert( sig0_zc_lut[0] = mid_main_jsig0_00_lut ); + sig0_zc_cxts[0] = mid_main_jsig0_00_cxts; + //assert(sig_zc_lut[0] = mid_main_jsig_00_lut); + myassert( sig_zc_lut[0] = mid_main_jsig_00_lut ); + sig_zc_cxts[0] = mid_main_jsig_00_cxts; + + + //assert(sig0_zc_lut[1] = mid_main_jsig0_01_lut); + myassert( sig0_zc_lut[1] = mid_main_jsig0_01_lut ); + sig0_zc_cxts[1] = mid_main_jsig0_01_cxts; + //assert(sig_zc_lut[1] = mid_main_jsig_01_lut); + myassert( sig_zc_lut[1] = mid_main_jsig_01_lut ); + sig_zc_cxts[1] = mid_main_jsig_01_cxts; + + //assert(sig0_zc_lut[2] = mid_main_jsig0_10_lut); + myassert( sig0_zc_lut[2] = mid_main_jsig0_10_lut ); + sig0_zc_cxts[2] = mid_main_jsig0_10_cxts; + //assert(sig_zc_lut[2] = mid_main_jsig_10_lut); + myassert( sig_zc_lut[2] = mid_main_jsig_10_lut ); + sig_zc_cxts[2] = mid_main_jsig_10_cxts; + + //assert(sig0_zc_lut[3] = mid_main_jsig0_11_lut); + myassert( sig0_zc_lut[3] = mid_main_jsig0_11_lut ); + sig0_zc_cxts[3] = mid_main_jsig0_11_cxts; + //assert(sig_zc_lut[3] = mid_main_jsig_11_lut); + myassert( sig_zc_lut[3] = mid_main_jsig_11_lut ); + sig_zc_cxts[3] = mid_main_jsig_11_cxts; + + } + + //assignments of LUTS for LSP coding + +#ifdef LSP_LUT + + if( band->get_orientation( ) == HH ) { + +#ifdef TWO_SIGNIF_BITS + //assert(LSP_lut = sm3_2_signif_bits_diag_LSP_lut); + myassert( LSP_lut = sm3_2_signif_bits_diag_LSP_lut ); + LSP_cxts = sm3_2_signif_bits_diag_LSP_cxts; +#else + //assert(LSP_lut = mid_diag_LSP_lut); + myassert( LSP_lut = mid_diag_LSP_lut ); + LSP_cxts = mid_diag_LSP_cxts; +#endif + } else { + +#ifdef TWO_SIGNIF_BITS + //assert(LSP_lut = sm3_2_signif_bits_main_LSP_lut); + myassert( LSP_lut = sm3_2_signif_bits_main_LSP_lut ); + LSP_cxts = sm3_2_signif_bits_main_LSP_cxts; +#else + //assert(LSP_lut = mid_main_LSP_lut); + myassert( LSP_lut = mid_main_LSP_lut ); + LSP_cxts = mid_main_LSP_cxts; +#endif + } +#endif //LSP_LUT + + //sign luts + + if( band->get_orientation( ) == HH ) { + //assert(sign_lut = mid_diag_sign_lut); + myassert( sign_lut = mid_diag_sign_lut ); + sign_cxts = mid_diag_sign_cxts; + + } else { + //assert(sign_lut = mid_main_sign_lut); + myassert( sign_lut = mid_main_sign_lut ); + sign_cxts = mid_main_sign_cxts; + } + + cxt_qtree.sig_offsets[0] = total = 0; + for( i = 0; i < 4; i++ ) { + cxt_qtree.jsig_offsets[0][i] = total; + cxt_qtree.jsig_cxts[0][i] = sig0_zc_cxts[i]; + cxt_qtree.jsig_tabs[0][i] = sig0_zc_lut[i]; + total += sig0_zc_cxts[i]; + } + cxt_qtree.sig_cxts[0] = total - cxt_qtree.sig_offsets[0]; + + for( lev = 1; lev < 3; lev++ ) { + cxt_qtree.sig_offsets[lev] = total; + for( i = 0; i < 4; i++ ) { + cxt_qtree.jsig_offsets[lev][i] = total; + cxt_qtree.jsig_cxts[lev][i] = sig_zc_cxts[i]; + cxt_qtree.jsig_tabs[lev][i] = sig_zc_lut[i]; + total += sig_zc_cxts[i]; + } + cxt_qtree.sig_cxts[lev] = total - cxt_qtree.sig_offsets[lev]; + } + + + + for( lev = 3; lev < depth; lev++ ) { // 3 ~ depth-1 + cxt_qtree.sig_offsets[lev] = cxt_qtree.sig_offsets[2]; + for( i = 0; i < 4; i++ ) { + cxt_qtree.jsig_offsets[lev][i] = cxt_qtree.jsig_offsets[2][i]; + cxt_qtree.jsig_cxts[lev][i] = 0; + cxt_qtree.jsig_tabs[lev][i] = cxt_qtree.jsig_tabs[2][i]; + } + cxt_qtree.sig_cxts[lev] = 0; + } + cxt_qtree.LIP_offset = total; + cxt_qtree.LIP_cxts = LIP_zc_cxts; + cxt_qtree.LIP_tab = LIP_zc_lut; + total += cxt_qtree.LIP_cxts; + + for( lev = 1; lev < 3; lev++ ) { + cxt_qtree.node_offsets[lev] = total; + cxt_qtree.node_cxts[lev] = node_zc_cxts; + cxt_qtree.node_tabs[lev] = node_zc_lut; + total += cxt_qtree.node_cxts[lev]; + } + + for( lev = 3; lev < depth; lev++ ) { // 3 ~ depth-1 + cxt_qtree.node_offsets[lev] = cxt_qtree.node_offsets[2]; + cxt_qtree.node_cxts[lev] = 0; + cxt_qtree.node_tabs[lev] = cxt_qtree.node_tabs[2]; + } + + cxt_qtree.LSP_offset = total; + +#ifdef LSP_BIT_IDX + + +#ifdef LSP_LUT + +#ifndef MERGE_ALL_LSP_PLANES + cxt_qtree.LSP_cxts = 79; +#else + cxt_qtree.LSP_cxts = LSP_cxts; +#endif //MERGE_ALL_LSP_PLANES + + cxt_qtree.LSP_tab = LSP_lut; +#else //LSP_LUT + cxt_qtree.LSP_cxts = 15; +#endif //LSP_LUT + + +#else //LSP_BIT_IDX + +#ifdef LSP_LUT + cxt_qtree.LSP_cxts = LSP_cxts + 1; + cxt_qtree.LSP_tab = LSP_lut; +#else + cxt_qtree.LSP_cxts = MAG_CONTEXTS; +#endif + +#endif //LSP_BIT_IDX + + total += cxt_qtree.LSP_cxts; + + cxt_qtree.sign_offset = total; + + cxt_qtree.sign_cxts = sign_cxts; + cxt_qtree.sign_tab = sign_lut; + + total += cxt_qtree.sign_cxts; + + cxt_qtree.total_cxts = total; + +} + +//----------------------------------------------------------------------------- + +// reset_cxt_models() + +//----------------------------------------------------------------------------- +void +SubbandCodec::reset_cxt_models( void ) +{ + + for( int i = cxt_qtree.total_cxts - 1; i >= 0; + cxt_qtree.cxt_models[i--].taub_scale( ) ); +} + +//----------------------------------------------------------------------------- + +// reset_node_cxts(void) + +//----------------------------------------------------------------------------- +void +SubbandCodec::update_node_cxts( void ) +{ + std_int *LIP_cur, *LIP_end, *LIS_cur, *LIS_end, coord_cur; + PEL_CXT_TYPE *base_cxt_sp, **base_cxt; + NODE_CXT_TYPE *cxt_node_sp, **cxt_node; + + LIP_cur = node_list.LSP + node_list.LIP_sz; + LIP_end = node_list.LIP_end; + base_cxt = cxt_qtree.base_cxt; + + + while( LIP_cur > LIP_end ) { + coord_cur = *( --LIP_cur ); + base_cxt_sp = base_cxt[coord_cur >> 16] + ( coord_cur & 0xFFFF ); + + if( *base_cxt_sp & TC_SIG ) + *base_cxt_sp |= TC2_SIG; + + if( *base_cxt_sp & CL_SIG ) + *base_cxt_sp |= CL2_SIG; + + if( *base_cxt_sp & CR_SIG ) + *base_cxt_sp |= CR2_SIG; + + if( *base_cxt_sp & BC_SIG ) + *base_cxt_sp |= BC2_SIG; + } + + int depth = qtree.depth; + for( int lev = 1; lev < depth; lev++ ) { + LIS_cur = node_list.LIS[lev] - 1; + LIS_end = node_list.LIS_end[lev]; + cxt_node = cxt_qtree.cxt_nodes[lev]; + while( LIS_cur < LIS_end ) { + coord_cur = *( ++LIS_cur ); + cxt_node_sp = cxt_node[coord_cur >> 16] + ( coord_cur & 0xFFFF ); + + if( *cxt_node_sp & TC_SIG ) + *cxt_node_sp |= TC2_SIG; + + if( *cxt_node_sp & CL_SIG ) + *cxt_node_sp |= CL2_SIG; + + if( *cxt_node_sp & CR_SIG ) + *cxt_node_sp |= CR2_SIG; + + if( *cxt_node_sp & BC_SIG ) + *cxt_node_sp |= BC2_SIG; + } + } + + std_int *LSP_cur = node_list.LSP - 1; + std_int *LSP_end = node_list.LSP_end; + + while( LSP_cur < LSP_end ) { + coord_cur = *( ++LSP_cur ); + base_cxt_sp = base_cxt[coord_cur >> 16] + ( coord_cur & 0xFFFF ); + + if( *base_cxt_sp & TC_SIG ) + *base_cxt_sp |= TC2_SIG; + + if( *base_cxt_sp & CL_SIG ) + *base_cxt_sp |= CL2_SIG; + + if( *base_cxt_sp & CR_SIG ) + *base_cxt_sp |= CR2_SIG; + + if( *base_cxt_sp & BC_SIG ) + *base_cxt_sp |= BC2_SIG; + } + +} + +//----------------------------------------------------------------------------- + +// setup_luts(void) + +//----------------------------------------------------------------------------- + +void +SubbandCodec::setup_luts( void ) +{ + initialize_zc_luts( ); /* in setup_cxt_tables.C */ + initialize_sc_lut( ); +} + +//----------------------------------------------------------------------------- + +// Member function of class SubbandTreeCodec() + +//----------------------------------------------------------------------------- + +SubbandTreeCodec::SubbandTreeCodec( SUBBAND_TREE_TYPE * subs ) +:fpout( stdout ) +{ + //assert(subband_tree = subs); + myassert( subband_tree = subs ); + total_byte_budget = MAX_STD_INT; +} + +//----------------------------------------------------------------------------- + +// ~SubbandTreeCodec() + +//----------------------------------------------------------------------------- +SubbandTreeCodec::~SubbandTreeCodec( void ) +{ +} + +void +SubbandTreeCodec::initialize( SUBBAND_TREE_TYPE * subs ) +{ + //assert(subband_tree = subs); + myassert( subband_tree = subs ); + total_byte_budget = MAX_STD_INT; + + fpout = stdout; +} + +void +SubbandTreeCodec::reset_tree_codec( SUBBAND_TREE_TYPE * subs ) +{ + //assert(subband_tree = subs); + myassert( subband_tree = subs ); +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec.cpp new file mode 100644 index 0000000..bf50e97 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec.cpp @@ -0,0 +1,412 @@ +/* ========================================================================= */ +/* Description: menber functions for class DecSubband */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include "dwt_bitplane_dec.h" + + +void +DecSubband:: + +initialize( SUBBAND_TYPE * subband, + DecSubbandTree * dec_tree, DECODER_TYPE * dec ) +{ + SubbandCodec::initialize( subband ); + dec_band_tree = dec_tree; + sub_decoder = dec; + create_max_and_cxt_qtrees( ); + initialize_cxt_models( ); + set_functions( ); +} + +/*void DecSubband:: +initialize2(SUBBAND_TYPE* subband, + DecSubbandTree *dec_tree) +{ + SubbandCodec::initialize(subband); + dec_band_tree = dec_tree; + + + NEW_VECTOR(sub_decoder, 1, DECODER_TYPE, "sub_decoder (dwt_bitplane_enc.cpp)") ; + + create_max_and_cxt_qtrees(); + initialize_cxt_models(); + set_functions(); +} +*/ + +void +DecSubband::reset_band_dec( SUBBAND_TYPE * subband ) +{ + reset_band_codec( subband ); +} + +//----------------------------------------------------------------------------- + +// create_max_and_cxt_qtrees() + +//----------------------------------------------------------------------------- +void +DecSubband::create_max_and_cxt_qtrees( ) +{ + NODE_CXT_TYPE ***cxt_nodes; + Image_Coord_Sht *dims; + int depth; + + Image_Coord band_dim = band->get_dim( ); + int rows = band_dim.x; + int cols = band_dim.y; + + depth = qtree.depth = Max( log2( rows - 1 ), log2( cols - 1 ) ) + 1; + + NEW_VECTOR( qtree.dims, depth + 1, Image_Coord_Sht, "qtree.nodes" ); + dims = qtree.dims; + dims[0].r = rows; + dims[0].c = cols; + + + NEW_VECTOR( cxt_qtree.cxt_nodes, depth + 1, NODE_CXT_TYPE **, + "qtree.nodes" ); + cxt_nodes = cxt_qtree.cxt_nodes; + + //compute dims + int lev, r, c, cxt_r_sz, cxt_node_sz, node_sz; //r_sz, + Image_Coord_Sht *mem_dims; + + NEW_VECTOR( mem_dims, depth + 1, Image_Coord_Sht, "qtree.nodes" ); + + node_sz = cxt_r_sz = cxt_node_sz = 0; + for( lev = 1, r = rows, c = cols; lev <= depth; lev++ ) { + dims[lev].r = r = 1 + ( ( r - 1 ) >> 1 ); + dims[lev].c = c = 1 + ( ( c - 1 ) >> 1 ); + + mem_dims[lev].r = r = ( ( r + 1 ) >> 1 ) << 1; // make r, c always even + mem_dims[lev].c = c = ( ( c + 1 ) >> 1 ) << 1; + + cxt_r_sz += r + WIDTH_OF_CXT_BDY_X_2; + node_sz += r * c; + cxt_node_sz += + ( r + WIDTH_OF_CXT_BDY_X_2 ) * ( c + WIDTH_OF_CXT_BDY_X_2 ); + } + qtree.qtree_sz = node_sz; + qtree.nodes = NULL; + cxt_qtree.cxt_qtree_sz = cxt_node_sz; + + NEW_VECTOR( cxt_nodes[1], cxt_r_sz, NODE_CXT_TYPE *, "NODE_CXT_TYPE*" ); + cxt_nodes[1] += WIDTH_OF_CXT_BDY; + NEW_VECTOR( cxt_nodes[1][-WIDTH_OF_CXT_BDY], cxt_node_sz, NODE_CXT_TYPE, + "NODE_CXT_TYPE" ); + cxt_nodes[1][-WIDTH_OF_CXT_BDY] += WIDTH_OF_CXT_BDY; + + for( lev = 2; lev <= depth; lev++ ) { + r = mem_dims[lev - 1].r; + c = mem_dims[lev - 1].c; + cxt_nodes[lev] = cxt_nodes[lev - 1] + r + WIDTH_OF_CXT_BDY_X_2; + cxt_nodes[lev][-WIDTH_OF_CXT_BDY] = + cxt_nodes[lev - 1][-WIDTH_OF_CXT_BDY] + ( r + + WIDTH_OF_CXT_BDY_X_2 ) * ( c + + WIDTH_OF_CXT_BDY_X_2 ); + } + + for( lev = 1; lev <= depth; lev++ ) { + int c_cxt = mem_dims[lev].c + WIDTH_OF_CXT_BDY_X_2; + NODE_CXT_TYPE **node_cxt_dptr = cxt_nodes[lev] - WIDTH_OF_CXT_BDY; + NODE_CXT_TYPE **node_cxt_end_dptr = node_cxt_dptr + + mem_dims[lev].r + WIDTH_OF_CXT_BDY_X_2 - 1; + for( ; node_cxt_dptr != node_cxt_end_dptr; node_cxt_dptr++ ) + node_cxt_dptr[1] = *node_cxt_dptr + c_cxt; + } + // even dim. all the time + r = ( ( ( rows + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2; + c = ( ( ( cols + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2; + int rc = r * c; + + NEW_VECTOR( cxt_qtree.base_cxt, r, PEL_CXT_TYPE *, "base_cxt*" ); + cxt_qtree.base_cxt += WIDTH_OF_CXT_BDY; + NEW_VECTOR( cxt_qtree.base_cxt[-WIDTH_OF_CXT_BDY], rc, PEL_CXT_TYPE, + "base_cxt" ); + cxt_qtree.base_cxt[-WIDTH_OF_CXT_BDY] += WIDTH_OF_CXT_BDY; + + PEL_CXT_TYPE **pel_cxt_dptr = cxt_qtree.base_cxt - WIDTH_OF_CXT_BDY; + PEL_CXT_TYPE **pel_cxt_end_dptr = pel_cxt_dptr + r - 1; + for( ; pel_cxt_dptr != pel_cxt_end_dptr; pel_cxt_dptr++ ) + pel_cxt_dptr[1] = *pel_cxt_dptr + c; + + NEW_VECTOR( cxt_qtree.base_sign_cxt, r, SIGN_CXT_TYPE *, "base_sign_cxt*" ); + cxt_qtree.base_sign_cxt += WIDTH_OF_CXT_BDY; + NEW_VECTOR( cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY], rc, SIGN_CXT_TYPE, + "base_sign_cxt" ); + cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY] += WIDTH_OF_CXT_BDY; + + SIGN_CXT_TYPE **base_sign_cxt_dptr = cxt_qtree.base_sign_cxt - + WIDTH_OF_CXT_BDY; + SIGN_CXT_TYPE **base_sign_cxt_end_dptr = base_sign_cxt_dptr + r - 1; + for( ; base_sign_cxt_dptr != base_sign_cxt_end_dptr; base_sign_cxt_dptr++ ) + base_sign_cxt_dptr[1] = *base_sign_cxt_dptr + c; + //for inter subbands correlations + +#ifdef INTERBANDS + + if( !( band->get_band_idx( ) ) || ( band->get_band_level( ) == 1 ) ) + child_cxt_qtree = NULL; //bottom bands have no kids and the top level + //only use info within subbands + else + child_cxt_qtree = + &( dec_band_tree->dec_subs[band->get_child_band_idx( )].cxt_qtree ); + +#endif + + +#ifdef GET_PARENT_MODELS + int par_idx = band->get_par( ); + if( ( par_idx < 0 ) + || ( ( par_idx == 0 ) && ( band->get_orientation( ) == HH ) ) ) + par_cxt_qtree = NULL; + else + par_cxt_qtree = &( dec_band_tree->dec_subs[par_idx].cxt_qtree ); + +#endif + + delete[]mem_dims; + +} + +//----------------------------------------------------------------------------- + +// setup_cxt_qtrees() + +//----------------------------------------------------------------------------- +void +DecSubband::setup_cxt_qtrees( ) +{ + int r, c, rc, lev; + PEL_CXT_TYPE *pel_cxt_ptr; + NODE_CXT_TYPE *node_cxt_ptr; + NODE_CXT_TYPE ***cxt_nodes = cxt_qtree.cxt_nodes; + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + Image_Coord_Sht *dims = qtree.dims; + int depth = qtree.depth; + Image_Coord band_dim = band->get_dim( ); + int rows = band_dim.x; + int cols = band_dim.y; + + rc = ( ( ( ( rows + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2 ) * + ( ( ( ( cols + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2 ); + + pel_cxt_ptr = &( base_cxt[-WIDTH_OF_CXT_BDY][-WIDTH_OF_CXT_BDY] ); + PEL_CXT_TYPE *pel_cxt_end_ptr = pel_cxt_ptr + rc; + while( pel_cxt_end_ptr != pel_cxt_ptr ) + *( pel_cxt_ptr++ ) = OUT_OF_BOUNDS; + + for( r = rows - 1; r >= 0; r-- ) { //initialize cxt = 0 for pels within the bounds + pel_cxt_ptr = base_cxt[r]; + memset( pel_cxt_ptr, 0, sizeof( PEL_CXT_TYPE ) * cols ); + } + + memset( &( cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY][-WIDTH_OF_CXT_BDY] ), + 0, sizeof( SIGN_CXT_TYPE ) * rc ); + + node_cxt_ptr = &( cxt_nodes[1][-WIDTH_OF_CXT_BDY][-WIDTH_OF_CXT_BDY] ); + NODE_CXT_TYPE *node_cxt_end_ptr = node_cxt_ptr + cxt_qtree.cxt_qtree_sz; + while( node_cxt_ptr != node_cxt_end_ptr ) + *( node_cxt_ptr++ ) = OUT_OF_BOUNDS; + + //setup cxt + for( lev = 1; lev <= depth; lev++ ) { + for( c = dims[lev].c, r = dims[lev].r - 1; r >= 0; r-- ) { + node_cxt_ptr = cxt_nodes[lev][r]; + memset( node_cxt_ptr, 0, sizeof( NODE_CXT_TYPE ) * c ); + } + } +} + +//----------------------------------------------------------------------------- + +// set_functions(void) + +//----------------------------------------------------------------------------- +void +DecSubband::set_functions( void ) +{ + + + decode_LIP = &DecSubband::decode_LIP_cxt_AC; + decode_LIS_leaves = &DecSubband::decode_LIS_leaves_cxt_AC; + decode_cur_qtree_level = &DecSubband::decode_cur_qtree_level_cxt_AC; + +#ifdef LSP_BIT_IDX + decode_LSP = &DecSubband::decode_LSP_cxt_AC_and_bit_idx; +#else + decode_LSP = &DecSubband::decode_LSP_cxt_AC; +#endif + + decode_sig_node = &DecSubband::decode_sig_node_pos_dep_cxt_AC; + decode_sig_leaf = &DecSubband::decode_sig_leaf_pos_dep_cxt_AC; +} + +//----------------------------------------------------------------------------- + +// decode_LIS_stack() + +//----------------------------------------------------------------------------- +void +DecSubband::decode_LIS_stack( ) +{ + do { + +//added by Peisong + if( node_list.LIS_stack > node_list.LIS_stack_top ) { + //cout<<"=======>LIS_stack="<set_max_msb( max_bit_idx + band->get_lsb( ) ); + setup_cxt_qtrees( ); + initialize_node_list( ); + create_coding_stats( ); + LSP_break_pt = node_list.LSP; + + return 0; +} + + +//----------------------------------------------------------------------------- + +// rec_subband() + +//----------------------------------------------------------------------------- + +void +DecSubband::rec_subband( ) +{ + std_int *last, *sp; + SUB_COEFF_TYPE mask = bit_idx_mask >> 1; + + for( sp = node_list.LSP_end; sp >= LSP_break_pt; sp-- ) + base_coeff[*sp >> 16][*sp & 0xFFFF] |= mask; + + mask = bit_idx_mask; + + for( last = node_list.LSP; sp >= last; sp-- ) + base_coeff[*sp >> 16][*sp & 0xFFFF] |= mask; + +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_cxt_AC.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_cxt_AC.cpp new file mode 100644 index 0000000..be07518 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_cxt_AC.cpp @@ -0,0 +1,1376 @@ +/* ========================================================================= */ +/* Description: menber functions for class DecSubband with contex modeling */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include +#include "dwt_bitplane_dec.h" + +//----------------------------------------------------------------------------- + +// decode_LIP_cxt_AC() + +//----------------------------------------------------------------------------- +void +DecSubband::decode_LIP_cxt_AC( ) +{ + std_short r, c; + std_int cur_coord; + PEL_CXT_TYPE *cxt_sp; + std_int *LIP_cur, *LIP_end, *LIP_old_end; + + + std_int *LSP_end = node_list.LSP_end; + // std_int *LSP = node_list.LSP; + std_int *LIP = node_list.LIP; + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + std_short row_gap = base_cxt[1] - base_cxt[0]; + MODEL_TYPE *LIP_models = cxt_qtree.cxt_models + cxt_qtree.LIP_offset; + std_byte *cxt_tab = cxt_qtree.LIP_tab; + + //sign related data........ + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + SUB_COEFF_TYPE *sign_cxt_tab = cxt_qtree.sign_tab; + SIGN_CXT_TYPE *sign_cxt_sp, **base_sign_cxt = cxt_qtree.base_sign_cxt; + std_short sign_cxt_row_gap = base_sign_cxt[1] - base_sign_cxt[0]; + SUB_COEFF_TYPE sign_predict, sign_bit; + + //interband related data +#ifdef INTERBANDS + int cd_base_cxt_row_gap; + PEL_CXT_TYPE *cd_base_cxt_sp, **cd_base_cxt; + NODE_CXT_TYPE *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_base_cxt = child_cxt_qtree->base_cxt; + cd_base_cxt_row_gap = cd_base_cxt[1] - cd_base_cxt[0]; + cd_cxt_node = child_cxt_qtree->cxt_nodes[1]; + } +#endif + +#ifdef INITIALIZE_LIP_MODELS_FROM_PAR + MODEL_TYPE *par_LIP_models; + + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + assert( cxt_qtree.LIP_cxts == par_cxt_qtree->LIP_cxts ); + par_LIP_models = par_cxt_qtree->cxt_models + par_cxt_qtree->LIP_offset; + for( int i = cxt_qtree.LIP_cxts - 1; i >= 0; + LIP_models[i].reset( par_LIP_models[i] ), + LIP_models[i--].taub_scale( ) ); + } +#endif + + LIP_cur = LIP_end = LIP + node_list.LIP_sz; + LIP_old_end = node_list.LIP_end; + + while( LIP_cur != LIP_old_end ) { + cur_coord = *( --LIP_cur ); + r = cur_coord >> 16; + c = cur_coord & 0xFFFF; + cxt_sp = base_cxt[r] + c; + + if( sub_decoder->decode_symbol( LIP_models[cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + if( ++LSP_end == LIP_old_end ) //LSP_pos runs beyond the end of the LSP + *( LIP_cur++ ) = *( LIP_old_end++ ); + *LSP_end = cur_coord; + + base_coeff[r][c] |= bit_idx_mask; + UPDATE_CXT( cxt_sp, row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cxt_sp = cd_base_cxt[r << 1] + ( c << 1 ); + UPDATE_4_CD_NODES( cd_base_cxt_sp, cd_base_cxt_row_gap ); + cd_cxt_node_sp = cd_cxt_node[r] + c; + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + sign_cxt_sp = base_sign_cxt[r] + c; + sign_predict = sign_cxt_tab[*sign_cxt_sp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + + if( sign_bit ) + base_coeff[r][c] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cxt_sp, sign_cxt_row_gap, sign_bit ); + + } else + *( --LIP_end ) = cur_coord; + +#ifdef TEST_CODING_RATE + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + node_list.LSP_end = LSP_end; + return; + } +#endif + + } + node_list.LSP_end = LSP_end; + node_list.LIP_end = LIP_end; + +#ifdef LSP_BIT_IDX + node_list.LSP_ids[bit_idx][0] = LSP_end; +#endif +} + +//----------------------------------------------------------------------------- + +// decode_sig_leaf_cxt_AC() + +//----------------------------------------------------------------------------- +void + DecSubband:: +//bool DecSubband:: +decode_sig_leaf_cxt_AC( std_int cur_coord ) +{ + // std_short dim_r = qtree.dims[0].r; + // std_short dim_c = qtree.dims[0].c; + std_short + row_gap = + base_coeff[1] - + base_coeff[0]; + std_short + cxt_row_gap = + cxt_qtree. + base_cxt[1] - + cxt_qtree. + base_cxt[0]; + std_short + r = ( cur_coord >> 16 ) << + 1; + std_short + c = ( cur_coord & 0xFFFF ) << + 1; + + SUB_COEFF_TYPE * + sp = + base_coeff[r] + + c; + PEL_CXT_TYPE * + cp, * + cxt_sp = + cxt_qtree. + base_cxt[r] + + c; + MODEL_TYPE * + sig_models = + cxt_qtree. + cxt_models + + cxt_qtree. + sig_offsets[0]; + std_byte * + cxt_tab = + cxt_qtree. + sig_tabs[0]; + + //sign related data........ + MODEL_TYPE * + sign_models = + cxt_qtree. + cxt_models + + cxt_qtree. + sign_offset; + SUB_COEFF_TYPE * + sign_cxt_tab = + cxt_qtree. + sign_tab; + SIGN_CXT_TYPE ** + base_sign_cxt = + cxt_qtree. + base_sign_cxt; + SIGN_CXT_TYPE * + sign_cp, * + sign_cxt_sp = + base_sign_cxt[r] + + c; + std_short + sign_cxt_row_gap = + base_sign_cxt[1] - + base_sign_cxt[0]; + SUB_COEFF_TYPE + sign_predict, + sign_bit; + + //interband related data +#ifdef INTERBANDS + int + cd_base_cxt_row_gap, + cd_cxt_node_row_gap; + PEL_CXT_TYPE * + cd_base_cp, * + cd_base_cxt_sp, ** + cd_base_cxt; + NODE_CXT_TYPE * + cd_node_cp, * + cd_cxt_node_sp, ** + cd_cxt_node; + + if( child_cxt_qtree ) { + cd_base_cxt = child_cxt_qtree->base_cxt; + cd_base_cxt_row_gap = cd_base_cxt[1] - cd_base_cxt[0]; + cd_base_cxt_sp = cd_base_cxt[r << 1] + ( c << 1 ); + cd_cxt_node = child_cxt_qtree->cxt_nodes[1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int + nbits = + 0; + cur_coord <<= 1; + + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + *sp |= bit_idx_mask; + UPDATE_CXT( cxt_sp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_4_CD_NODES( cd_base_cxt_sp, cd_base_cxt_row_gap ); + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + sign_predict = sign_cxt_tab[*sign_cxt_sp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + *sp |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cxt_sp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord; + nbits++; + } else { + *--node_list.LIP_end = cur_coord; + } + + + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + + + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + sp[1] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + sp[1] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x1; + nbits++; + } else { + *--node_list.LIP_end = cur_coord | 0x1; + } + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cp & ZC_MASK]] ) ) { + + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + sp[row_gap] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ); + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + sp[row_gap] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10000; + nbits++; + } else { + *--node_list.LIP_end = cur_coord | 0x10000; + } +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + + + + + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( nbits ) { + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cp & ZC_MASK]] ) ) { + + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + sp[row_gap + 1] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + sp[row_gap + 1] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + } else { + *--node_list.LIP_end = cur_coord | 0x10001; + + } + } else { + sp[row_gap + 1] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + + if( sign_bit ) + sp[row_gap + 1] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + } + } + + + return; +} + +//----------------------------------------------------------------------------- + +// decode_sig_node_cxt_AC() + +//----------------------------------------------------------------------------- + +void +DecSubband::decode_sig_node_cxt_AC( std_int cur_coord, int lev ) +{ + std_short cxt_row_gap = + cxt_qtree.cxt_nodes[lev][1] - cxt_qtree.cxt_nodes[lev][0]; + std_short r = ( cur_coord >> 16 ) << 1; + std_short c = ( cur_coord & 0xFFFF ) << 1; + NODE_CXT_TYPE *cp, *cxt_sp = cxt_qtree.cxt_nodes[lev][r] + c; + MODEL_TYPE *sig_models = cxt_qtree.cxt_models + cxt_qtree.sig_offsets[lev]; + std_byte *sig_cxt_tab = cxt_qtree.sig_tabs[lev]; + + //new stuffs + std_int coord_buf[4]; + +#ifdef INTERBANDS + int cd_cxt_node_row_gap; + NODE_CXT_TYPE *cd_node_cp, *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[lev + 1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int nbits = 0; + cur_coord <<= 1; + + if( sub_decoder-> + decode_symbol( sig_models[sig_cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + + coord_buf[nbits++] = cur_coord; + + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + //nbits++; + } else + *( ++node_list.LIS_end[lev] ) = cur_coord; + + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sub_decoder->decode_symbol( sig_models[sig_cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + coord_buf[nbits++] = cur_coord | 0x1; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x1; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sub_decoder->decode_symbol( sig_models[sig_cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + coord_buf[nbits++] = cur_coord | 0x10000; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10000; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( nbits ) { + if( sub_decoder-> + decode_symbol( sig_models[sig_cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + coord_buf[nbits++] = cur_coord | 0x10001; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + } else + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10001; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + } else { + coord_buf[nbits++] = cur_coord | 0x10001; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + } + } + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + while( nbits ) { + ( ++node_list.LIS_stack_top )->node = coord_buf[--nbits]; + node_list.LIS_stack_top->level = lev; + } + +} + +//----------------------------------------------------------------------------- + +// decode_LIS_leaves_cxt_AC(void) + +//----------------------------------------------------------------------------- +void +DecSubband::decode_LIS_leaves_cxt_AC( void ) +{ + int i; + std_short r, c; + std_int cur_coord, *LIS_cur, *LIS_end, *LIS_end_old; + NODE_CXT_TYPE *cxt_sp; + NODE_CXT_TYPE **cxt_nodes = cxt_qtree.cxt_nodes[1]; + std_short cxt_row_gap = cxt_nodes[1] - cxt_nodes[0]; + MODEL_TYPE *leaf_models = cxt_qtree.cxt_models + cxt_qtree.node_offsets[1]; + std_byte *leaf_cxt_tab = cxt_qtree.node_tabs[1]; + +#ifdef INTERBANDS + NODE_CXT_TYPE *cd_cxt_node_sp, **cd_cxt_node; + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[2]; + } +#endif + + +#ifdef SCALE_SIGN_MODELS_AT_LEVEL_ENDS + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + for( i = cxt_qtree.sign_cxts - 1; i >= 0; sign_models[i--].taub_scale( ) ); +#endif + + +#ifdef INITIALIZE_NODE_MODELS_FROM_PAR + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + MODEL_TYPE *par_leaf_models; + + assert( cxt_qtree.node_cxts[1] == par_cxt_qtree->node_cxts[1] ); + par_leaf_models = par_cxt_qtree->cxt_models + + par_cxt_qtree->node_offsets[1]; + for( i = cxt_qtree.node_cxts[1] - 1; i >= 0; + leaf_models[i].reset( par_leaf_models[i] ), + leaf_models[i--].taub_scale( ) ); + } +#endif + + LIS_cur = LIS_end = node_list.LIS[1] - 1; + LIS_end_old = node_list.LIS_end[1]; + + for( ; LIS_cur < LIS_end_old; ) { + cur_coord = *( ++LIS_cur ); + r = cur_coord >> 16; + c = cur_coord & 0xFFFF; + cxt_sp = cxt_nodes[r] + c; + + if( sub_decoder-> + decode_symbol( leaf_models[leaf_cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + ( this->*decode_sig_leaf ) ( cur_coord ); + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + + + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_cxt_node_sp = cd_cxt_node[r] + c; + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + } else + *++LIS_end = cur_coord; + +#ifdef TEST_CODING_RATE + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + } + node_list.LIS_end[1] = LIS_end; + +#ifdef LSP_BIT_IDX + node_list.LSP_ids[bit_idx][1] = node_list.LSP_end; +#endif +} + +//----------------------------------------------------------------------------- + +// decode_cur_qtree_level_cxt_AC(void) + +//----------------------------------------------------------------------------- + +void +DecSubband::decode_cur_qtree_level_cxt_AC( void ) +{ + assert( cur_lev < qtree.depth ); + + int i; + std_short r, c; + std_int cur_coord, *pLIS_cur, *pLIS_end, *pLIS_end_old; //, *cLIS_end + NODE_CXT_TYPE *cxt_sp, **cxt_nodes = cxt_qtree.cxt_nodes[cur_lev]; + std_short cxt_row_gap = cxt_nodes[1] - cxt_nodes[0]; + MODEL_TYPE *node_models = + cxt_qtree.cxt_models + cxt_qtree.node_offsets[cur_lev]; + std_byte *node_cxt_tab = cxt_qtree.node_tabs[cur_lev]; + +#ifdef INTERBANDS + NODE_CXT_TYPE *cd_cxt_node_sp, **cd_cxt_node; + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[cur_lev + 1]; + } +#endif + +#ifdef SCALE_SIGN_MODELS_AT_LEVEL_ENDS + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + for( i = cxt_qtree.sign_cxts - 1; i >= 0; sign_models[i--].taub_scale( ) ); +#endif + + + pLIS_cur = pLIS_end = node_list.LIS[cur_lev] - 1; + pLIS_end_old = node_list.LIS_end[cur_lev]; + while( pLIS_cur < pLIS_end_old ) { + cur_coord = *( ++pLIS_cur ); + r = cur_coord >> 16; + c = cur_coord & 0xFFFF; + cxt_sp = cxt_nodes[r] + c; + if( sub_decoder-> + decode_symbol( node_models[node_cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_cxt_node_sp = cd_cxt_node[r] + c; + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + ( this->*decode_sig_node ) ( cur_coord, cur_lev - 1 ); + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + decode_LIS_stack( ); + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } else + *++pLIS_end = cur_coord; + +#ifdef TEST_CODING_RATE + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + } + node_list.LIS_end[cur_lev] = pLIS_end; + +#ifdef LSP_BIT_IDX + node_list.LSP_ids[bit_idx][cur_lev] = node_list.LSP_end; +#endif + cur_lev++; +} + +//----------------------------------------------------------------------------- + +// decode_LSP_cxt_AC() + +//----------------------------------------------------------------------------- +void +DecSubband::decode_LSP_cxt_AC( ) +{ + + std_short r, c; + std_int *last, *sp, LSP_offset; + SUB_COEFF_TYPE mag; + std_int LSP_plane = node_list.LSP_plane; + std_int *LSP_mark = node_list.LSP_mark; + MODEL_TYPE *LSP_models = cxt_qtree.cxt_models + cxt_qtree.LSP_offset; +#ifdef LSP_LUT + std_byte *LSP_cxt_tab = cxt_qtree.LSP_tab; +#endif + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + + LSP_mark[LSP_plane] = node_list.LSP_end - node_list.LSP; + + if( LSP_plane ) { + last = node_list.LSP + LSP_mark[LSP_plane - 1]; +// for (sp = node_list.LSP; sp <= last; sp++){ + for( sp = last; sp >= node_list.LSP; sp-- ) { + r = *sp >> 16; + c = *sp & 0xFFFF; + mag = ( base_coeff[r][c] & MAG_MASK ) >> bit_idx; + + LSP_offset = 0; + +#ifdef LSP_LUT + if( mag < 4 ) { + LSP_offset = LSP_cxt_tab[base_cxt[r][c]] + 1; + } +#else + if( mag < 4 ) { + if( base_cxt[r][c] & 0x0FFF ) + LSP_offset++; + } else + LSP_offset += 2; +#endif + + // if(sub_decoder->decode_symbol(*LSP_models)) + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + } + } + ++( node_list.LSP_plane ); + LSP_break_pt = node_list.LSP; +} + +//----------------------------------------------------------------------------- + +// decode_LSP_cxt_AC_and_bit_idx() + +//----------------------------------------------------------------------------- +void +DecSubband::decode_LSP_cxt_AC_and_bit_idx( ) +{ + + + std_short r, c; + std_int *last, *sp, LSP_offset; + std_int LSP_plane = node_list.LSP_plane; + std_int *LSP_mark = node_list.LSP_mark; + + std_int **LSP_bit_idx_marks = node_list.LSP_bit_idx_marks; + std_int ***LSP_ids = node_list.LSP_ids; + int i, depth = qtree.depth; + + MODEL_TYPE *LSP_models = cxt_qtree.cxt_models + cxt_qtree.LSP_offset; +#ifdef LSP_LUT + std_byte *LSP_cxt_tab = cxt_qtree.LSP_tab; +#endif + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + + LSP_mark[LSP_plane] = node_list.LSP_end - node_list.LSP; + + LSP_bit_idx_marks[bit_idx] = node_list.LSP_end; + +//new stuffs +#ifdef INITIALIZE_LSP_MODELS_FROM_PAR + MODEL_TYPE *par_LSP_models; + + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + assert( cxt_qtree.LSP_cxts == par_cxt_qtree->LSP_cxts ); + par_LSP_models = par_cxt_qtree->cxt_models + par_cxt_qtree->LSP_offset; + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i].reset( par_LSP_models[i] ), + LSP_models[i--].taub_scale( ) ); + } +#endif + +#ifdef LSP_LUT + + int LSP_lev, LSP_set_offset; + if( bit_idx < max_bit_idx ) { +#ifdef MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE + + LSP_lev = depth - 1; +#ifdef MERGE_ALL_LSP_PLANES + LSP_set_offset = 0; +#else + LSP_set_offset = 20; +#endif + +#else + LSP_lev = ( depth < 6 ) ? ( depth - 1 ) : 5; +#endif + + for( sp = LSP_bit_idx_marks[bit_idx + 1]; LSP_lev > 1; LSP_lev-- ) { + +#ifndef MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE + LSP_set_offset = LSP_lev * 10; +#endif + for( last = LSP_ids[bit_idx + 1][LSP_lev - 1]; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + //end of decoding unit................................. + } + +/* June15 +#ifdef TEST_CODING_RATE + if(sub_decoder->bytes_used() > sub_decoder->byte_budget){ + LSP_break_pt = sp + 1; + return; + } +#endif +*/ + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i--].taub_scale( ) ); +#endif + } + + + if( bit_idx < max_bit_idx - 1 ) { + //from leaves + last = LSP_ids[bit_idx + 1][0]; + +#ifndef MERGE_SETS_OF_TOP_LSP_PLANE + LSP_set_offset = 10; +#else + //for(i = cxt_qtree.LSP_cxts - 1; i >= 0; LSP_models[i--].taub_scale()); +#endif + + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } +/* June15 +#ifdef TEST_CODING_RATE + if(sub_decoder->bytes_used() > sub_decoder->byte_budget){ + LSP_break_pt = sp + 1; + return; + } +#endif +*/ + +#ifdef MERGE_SETS_0_1_OF_TOP_PLANE + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i--].taub_scale( ) ); +#endif + +#else + LSP_set_offset = 0; +#endif + + last = LSP_bit_idx_marks[bit_idx + 2]; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } + +/* June15 +#ifdef TEST_CODING_RATE + if(sub_decoder->bytes_used() > sub_decoder->byte_budget){ + LSP_break_pt = sp + 1; + return; + } +#endif +*/ + + } + } + + if( bit_idx < max_bit_idx - 1 ) { + + +#ifdef SEPARATE_SETS_OF_PLANE_1 + +#ifndef MERGE_LSP_PLANE_1 + LSP_set_offset = 60; +#else + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; LSP_models[i--].taub_scale( ) ); +#endif + +#endif //MERGE_LSP_PLANE_1 + + LSP_lev = depth - 1; + for( ; LSP_lev >= 0; LSP_lev-- ) { + if( LSP_lev ) + last = LSP_ids[bit_idx + 2][LSP_lev - 1]; + else + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } + +/* June15 +#ifdef TEST_CODING_RATE + if(sub_decoder->bytes_used() > sub_decoder->byte_budget){ + LSP_break_pt = sp + 1; + return; + } +#endif +*/ + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i--].taub_scale( ) ); + + } + +#else //SEPARATE_SETS_OF_PLANE_1 + + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + LSP_set_offset = 60; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + //end of decoding unit................................. + } + +/* June15 +#ifdef TEST_CODING_RATE + if(sub_decoder->bytes_used() > sub_decoder->byte_budget){ + LSP_break_pt = sp + 1; + return; + } +#endif +*/ + +#endif + } + + if( bit_idx < max_bit_idx - 2 ) { + +#ifndef MERGE_LOWER_LSP_PLANE + LSP_set_offset = 70; + +#else + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; LSP_models[i--].taub_scale( ) ); +#endif + +#endif + + last = node_list.LSP - 1; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + //end of decoding unit................................. + } + +/* June15 +#ifdef TEST_CODING_RATE + if(sub_decoder->bytes_used() > sub_decoder->byte_budget){ + LSP_break_pt = sp + 1; + return; + } +#endif +*/ + } +#else + int LSP_lev; + if( bit_idx < max_bit_idx ) { + LSP_lev = ( depth < 6 ) ? ( depth - 1 ) : 5; + for( sp = LSP_bit_idx_marks[bit_idx + 1]; LSP_lev > 1; LSP_lev-- ) { + LSP_offset = LSP_lev; + for( last = LSP_ids[bit_idx + 1][LSP_lev - 1]; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } + } + + + if( bit_idx < max_bit_idx - 1 ) { + //from leaves + last = LSP_ids[bit_idx + 1][0]; + LSP_offset = 1; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } + + last = LSP_bit_idx_marks[bit_idx + 2]; + LSP_offset = 0; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + //end of decoding unit................................. + } + } + } + + + if( bit_idx < max_bit_idx - 1 ) { + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + LSP_offset = 10; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + //end of decoding unit................................. + } + } + + if( bit_idx < max_bit_idx - 2 ) { + last = node_list.LSP - 1; + LSP_offset = 11; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } + } + //3 seperate levs......................................... + +#ifdef 3LEVS_AC0 + if( bit_idx < max_bit_idx ) { + last = ( bit_idx == max_bit_idx - 1 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 2]; + LSP_offset = 0; + for( sp = LSP_bit_idx_marks[bit_idx + 1]; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + + //end of decoding unit................................. + } + } + + if( bit_idx < max_bit_idx - 1 ) { + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + LSP_offset = 1; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + //end of decoding unit................................. + } + } + + if( bit_idx < max_bit_idx - 2 ) { + last = node_list.LSP - 1; + LSP_offset = 2; + for( ; sp > last; sp-- ) { + //decoding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + if( sub_decoder->decode_symbol( LSP_models[LSP_offset] ) ) + base_coeff[r][c] |= bit_idx_mask; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) { + LSP_break_pt = sp + 1; + return; + } +#endif + + //end of decoding unit................................. + } + } +#endif //3LEVS_AC0 + +#endif //LSP_LUT + + ++( node_list.LSP_plane ); + LSP_break_pt = node_list.LSP; +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_pos_dep_cxt_AC.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_pos_dep_cxt_AC.cpp new file mode 100644 index 0000000..2b744ad --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_dec_pos_dep_cxt_AC.cpp @@ -0,0 +1,562 @@ +/* ========================================================================= */ +/* Description: menber functions for class DecSubband */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include +#include "dwt_bitplane_dec.h" + +//----------------------------------------------------------------------------- + +// decode_sig_leaf_pos_dep_cxt_AC() + +//----------------------------------------------------------------------------- + +void + DecSubband:: +//bool DecSubband:: +decode_sig_leaf_pos_dep_cxt_AC( std_int cur_coord ) +{ + // std_short dim_r = qtree.dims[0].r; + // std_short dim_c = qtree.dims[0].c; + std_short + row_gap = + base_coeff[1] - + base_coeff[0]; + std_short + cxt_row_gap = + cxt_qtree. + base_cxt[1] - + cxt_qtree. + base_cxt[0]; + std_short + r = ( cur_coord >> 16 ) << + 1; + std_short + c = ( cur_coord & 0xFFFF ) << + 1; + + SUB_COEFF_TYPE * + sp = + base_coeff[r] + + c; + PEL_CXT_TYPE * + cp, * + cxt_sp = + cxt_qtree. + base_cxt[r] + + c; + + + MODEL_TYPE * + sig_models, * + cxt_models = + cxt_qtree. + cxt_models; + int * + jsig_offsets = + cxt_qtree. + jsig_offsets[0]; + std_byte * + cxt_tab, ** + jsig_tabs = + cxt_qtree. + jsig_tabs[0]; + + + //sign related data........ + MODEL_TYPE * + sign_models = + cxt_qtree. + cxt_models + + cxt_qtree. + sign_offset; + SUB_COEFF_TYPE * + sign_cxt_tab = + cxt_qtree. + sign_tab; + SIGN_CXT_TYPE ** + base_sign_cxt = + cxt_qtree. + base_sign_cxt; + SIGN_CXT_TYPE * + sign_cp, * + sign_cxt_sp = + base_sign_cxt[r] + + c; + std_short + sign_cxt_row_gap = + base_sign_cxt[1] - + base_sign_cxt[0]; + SUB_COEFF_TYPE + sign_predict, + sign_bit; + + //interband related data +#ifdef INTERBANDS + int + cd_base_cxt_row_gap, + cd_cxt_node_row_gap; + PEL_CXT_TYPE * + cd_base_cp, * + cd_base_cxt_sp, ** + cd_base_cxt; + NODE_CXT_TYPE * + cd_node_cp, * + cd_cxt_node_sp, ** + cd_cxt_node; + + if( child_cxt_qtree ) { + cd_base_cxt = child_cxt_qtree->base_cxt; + cd_base_cxt_row_gap = cd_base_cxt[1] - cd_base_cxt[0]; + cd_base_cxt_sp = cd_base_cxt[r << 1] + ( c << 1 ); + cd_cxt_node = child_cxt_qtree->cxt_nodes[1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int + nbits = + 0; + cur_coord <<= 1; + + //#ifdef DEBUG + //fprintf( stderr, "LEAF, coord = %8x, (%2d,%2d)\n", cur_coord, r, c ); + //#endif + + sig_models = cxt_models + jsig_offsets[0]; + cxt_tab = jsig_tabs[0]; + + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + *sp |= bit_idx_mask; + UPDATE_CXT( cxt_sp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_4_CD_NODES( cd_base_cxt_sp, cd_base_cxt_row_gap ); + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + sign_predict = sign_cxt_tab[*sign_cxt_sp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + *sp |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cxt_sp, sign_cxt_row_gap, sign_bit ); + *++node_list.LSP_end = cur_coord; + nbits++; + } else { + *--node_list.LIP_end = cur_coord; + } + + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + + + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[1]; + cxt_tab = jsig_tabs[1]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[1]; + cxt_tab = jsig_tabs[1]; + } +#endif + + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + sp[1] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + sp[1] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x1; + nbits++; + } else { + *--node_list.LIP_end = cur_coord | 0x1; + } + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[2]; + cxt_tab = jsig_tabs[2]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[2]; + cxt_tab = jsig_tabs[2]; + } +#endif + + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + sp[row_gap] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ); + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + sp[row_gap] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + *++node_list.LSP_end = cur_coord | 0x10000; + nbits++; + } else { + *--node_list.LIP_end = cur_coord | 0x10000; + } +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + sig_models = cxt_models + jsig_offsets[3]; + cxt_tab = jsig_tabs[3]; + if( nbits ) { + if( sub_decoder->decode_symbol( sig_models[cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE // June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + sp[row_gap + 1] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + if( sign_bit ) + sp[row_gap + 1] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + } else { + *--node_list.LIP_end = cur_coord | 0x10001; + } + } else { + sp[row_gap + 1] |= bit_idx_mask; + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = + sub_decoder-> + decode_symbol( sign_models[sign_predict & SIGN_CXT_MASK] ) + ? ( sign_predict & SIGN_BIT ) ^ SIGN_BIT : sign_predict & SIGN_BIT; + + if( sign_bit ) + sp[row_gap + 1] |= SIGN_BIT; + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + } + } + + return; +} + +//----------------------------------------------------------------------------- + +// decode_sig_node_pos_dep_cxt_AC() + +//----------------------------------------------------------------------------- + +void +DecSubband::decode_sig_node_pos_dep_cxt_AC( std_int cur_coord, int lev ) +{ + std_short cxt_row_gap = + cxt_qtree.cxt_nodes[lev][1] - cxt_qtree.cxt_nodes[lev][0]; + std_short r = ( cur_coord >> 16 ) << 1; + std_short c = ( cur_coord & 0xFFFF ) << 1; + NODE_CXT_TYPE *cp, *cxt_sp = cxt_qtree.cxt_nodes[lev][r] + c; + + MODEL_TYPE *sig_models, *cxt_models = cxt_qtree.cxt_models; + int *jsig_offsets = cxt_qtree.jsig_offsets[lev]; + std_byte *sig_cxt_tab, **jsig_tabs = cxt_qtree.jsig_tabs[lev]; + + std_int coord_buf[4]; + + //...................................... +#ifdef INTERBANDS + int cd_cxt_node_row_gap; + NODE_CXT_TYPE *cd_node_cp, *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[lev + 1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int nbits = 0; + cur_coord <<= 1; + //#ifdef DEBUG + //fprintf( stderr, "pop node_%2d, coord = %8x, (%2d,%2d)\n", + // lev, cur_coord, r, c ); + //#endif + + sig_models = cxt_models + jsig_offsets[0]; + sig_cxt_tab = jsig_tabs[0]; + + if( sub_decoder-> + decode_symbol( sig_models[sig_cxt_tab[*cxt_sp & ZC_MASK]] ) ) { + + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + coord_buf[nbits++] = cur_coord; + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + } else + *( ++node_list.LIS_end[lev] ) = cur_coord; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[1]; + sig_cxt_tab = jsig_tabs[1]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + sig_cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[1]; + sig_cxt_tab = jsig_tabs[1]; + } +#endif + + if( sub_decoder->decode_symbol( sig_models[sig_cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + + coord_buf[nbits++] = cur_coord | 0x1; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x1; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[2]; + sig_cxt_tab = jsig_tabs[2]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + sig_cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[2]; + sig_cxt_tab = jsig_tabs[2]; + } +#endif + + if( sub_decoder->decode_symbol( sig_models[sig_cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + coord_buf[nbits++] = cur_coord | 0x10000; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10000; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } + + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + sig_models = cxt_models + jsig_offsets[3]; + sig_cxt_tab = jsig_tabs[3]; + if( nbits ) { + if( sub_decoder-> + decode_symbol( sig_models[sig_cxt_tab[*cp & ZC_MASK]] ) ) { + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + coord_buf[nbits++] = cur_coord | 0x10001; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + } else + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10001; + +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + } else { + coord_buf[nbits++] = cur_coord | 0x10001; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } + } +#ifdef TEST_CODING_RATE //June15 + if( sub_decoder->bytes_used( ) > sub_decoder->byte_budget ) + return; +#endif + + while( nbits ) { + ( ++node_list.LIS_stack_top )->node = coord_buf[--nbits]; + node_list.LIS_stack_top->level = lev; + } + +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc.cpp new file mode 100644 index 0000000..0c9287a --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc.cpp @@ -0,0 +1,423 @@ +/* ========================================================================= */ +/* Description: member functions for class EncSubband */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include +#include "dwt_bitplane_enc.h" + +void +EncSubband:: + +initialize( SUBBAND_TYPE * subband, EncSubbandTree * enc_tree, + ENCODER_TYPE * enc ) +{ + SubbandCodec::initialize( subband ); + enc_band_tree = enc_tree; + sub_encoder = enc; + + create_max_and_cxt_qtrees( ); + initialize_cxt_models( ); + set_functions( ); + +} + +/*void EncSubband:: +initialize2(SUBBAND_TYPE* subband, EncSubbandTree *enc_tree) +{ + SubbandCodec::initialize(subband); + enc_band_tree = enc_tree; + + NEW_VECTOR(sub_encoder, 1, ENCODER_TYPE, "sub_encoder (dwt_bitplane_enc.cpp)") ; + + sub_encoder->new_open_file(); + + create_max_and_cxt_qtrees(); + initialize_cxt_models(); + set_functions(); +}*/ + + +void +EncSubband::reset_band_enc( SUBBAND_TYPE * subband ) +{ + reset_band_codec( subband ); +} + +//----------------------------------------------------------------------------- + +// create_max_and_cxt_qtrees() + +// The dims of qtree.nodes are always even. +// The dims of cxt_qtree.nodes = qtree.nodes + WIDTH_OF_CXT_BDY_X_2. +// The results of this def. is that the dim of the root = 2 x 2 +// +//----------------------------------------------------------------------------- +void +EncSubband::create_max_and_cxt_qtrees( ) +{ + SUB_COEFF_TYPE ***nodes; + NODE_CXT_TYPE ***cxt_nodes; + Image_Coord_Sht *dims; + int depth; + + Image_Coord band_dim = band->get_dim( ); + int rows = band_dim.x; + int cols = band_dim.y; + + depth = qtree.depth = Max( log2( rows - 1 ), log2( cols - 1 ) ) + 1; + + assert( depth < 15 ); //dim is only short int + + // 0 - depth + NEW_VECTOR( qtree.dims, depth + 1, Image_Coord_Sht, "qtree.nodes" ); + NEW_VECTOR( qtree.nodes, depth + 1, SUB_COEFF_TYPE **, "qtree.nodes" ); + + dims = qtree.dims; + nodes = qtree.nodes; + + nodes[0] = band->get_coeff( ); + dims[0].r = rows; + dims[0].c = cols; + + NEW_VECTOR( cxt_qtree.cxt_nodes, depth + 1, NODE_CXT_TYPE **, + "qtree.nodes" ); + cxt_nodes = cxt_qtree.cxt_nodes; + + //compute dims + int lev, r, c, cxt_r_sz, r_sz, cxt_node_sz, node_sz; + Image_Coord_Sht *mem_dims; + + NEW_VECTOR( mem_dims, depth + 1, Image_Coord_Sht, "qtree.nodes" ); + + r_sz = node_sz = cxt_r_sz = cxt_node_sz = 0; + for( lev = 1, r = rows, c = cols; lev <= depth; lev++ ) { + dims[lev].r = r = 1 + ( ( r - 1 ) >> 1 ); + dims[lev].c = c = 1 + ( ( c - 1 ) >> 1 ); + + mem_dims[lev].r = r = ( ( r + 1 ) >> 1 ) << 1; // make r, c always even + mem_dims[lev].c = c = ( ( c + 1 ) >> 1 ) << 1; + r_sz += r; + cxt_r_sz += r + WIDTH_OF_CXT_BDY_X_2; + node_sz += r * c; + cxt_node_sz += + ( r + WIDTH_OF_CXT_BDY_X_2 ) * ( c + WIDTH_OF_CXT_BDY_X_2 ); + } + + qtree.qtree_sz = node_sz; + cxt_qtree.cxt_qtree_sz = cxt_node_sz; + + //memory allocation + + NEW_VECTOR( nodes[1], r_sz, SUB_COEFF_TYPE *, "qtree.nodes[1]" ); + NEW_VECTOR( nodes[1][0], node_sz, SUB_COEFF_TYPE, "qtree.nodes[1][0]" ); + + NEW_VECTOR( cxt_nodes[1], cxt_r_sz, NODE_CXT_TYPE *, "NODE_CXT_TYPE*" ); + cxt_nodes[1] += WIDTH_OF_CXT_BDY; + NEW_VECTOR( cxt_nodes[1][-WIDTH_OF_CXT_BDY], cxt_node_sz, NODE_CXT_TYPE, + "NODE_CXT_TYPE" ); + cxt_nodes[1][-WIDTH_OF_CXT_BDY] += WIDTH_OF_CXT_BDY; + + for( lev = 2; lev <= depth; lev++ ) { + r = mem_dims[lev - 1].r; + c = mem_dims[lev - 1].c; + nodes[lev] = nodes[lev - 1] + r; + nodes[lev][0] = nodes[lev - 1][0] + r * c; + + cxt_nodes[lev] = cxt_nodes[lev - 1] + r + WIDTH_OF_CXT_BDY_X_2; + cxt_nodes[lev][-WIDTH_OF_CXT_BDY] = + cxt_nodes[lev - 1][-WIDTH_OF_CXT_BDY] + ( r + + WIDTH_OF_CXT_BDY_X_2 ) * ( c + + WIDTH_OF_CXT_BDY_X_2 ); + } + + + for( lev = 1; lev <= depth; lev++ ) { + c = mem_dims[lev].c; + r = mem_dims[lev].r; + SUB_COEFF_TYPE **node_dptr = nodes[lev]; + SUB_COEFF_TYPE **node_end_dptr = node_dptr + r - 1; + for( ; node_dptr != node_end_dptr; node_dptr++ ) + node_dptr[1] = *node_dptr + c; + + int c_cxt = c + WIDTH_OF_CXT_BDY_X_2; + NODE_CXT_TYPE **node_cxt_dptr = cxt_nodes[lev] - WIDTH_OF_CXT_BDY; + NODE_CXT_TYPE **node_cxt_end_dptr = node_cxt_dptr + + r + WIDTH_OF_CXT_BDY_X_2 - 1; + + for( ; node_cxt_dptr != node_cxt_end_dptr; node_cxt_dptr++ ) + node_cxt_dptr[1] = *node_cxt_dptr + c_cxt; + } + + //memory allocation for pel context + + // even dim. all the time + r = ( ( ( rows + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2; + c = ( ( ( cols + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2; + int rc = r * c; + + NEW_VECTOR( cxt_qtree.base_cxt, r, PEL_CXT_TYPE *, "base_cxt*" ); + cxt_qtree.base_cxt += WIDTH_OF_CXT_BDY; + NEW_VECTOR( cxt_qtree.base_cxt[-WIDTH_OF_CXT_BDY], rc, PEL_CXT_TYPE, + "base_cxt" ); + cxt_qtree.base_cxt[-WIDTH_OF_CXT_BDY] += WIDTH_OF_CXT_BDY; + + PEL_CXT_TYPE **pel_cxt_dptr = cxt_qtree.base_cxt - WIDTH_OF_CXT_BDY; + PEL_CXT_TYPE **pel_cxt_end_dptr = pel_cxt_dptr + r - 1; + for( ; pel_cxt_dptr != pel_cxt_end_dptr; pel_cxt_dptr++ ) + pel_cxt_dptr[1] = *pel_cxt_dptr + c; + NEW_VECTOR( cxt_qtree.base_sign_cxt, r, SIGN_CXT_TYPE *, "base_sign_cxt*" ); + cxt_qtree.base_sign_cxt += WIDTH_OF_CXT_BDY; + NEW_VECTOR( cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY], rc, SIGN_CXT_TYPE, + "base_sign_cxt" ); + + cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY] += WIDTH_OF_CXT_BDY; + + SIGN_CXT_TYPE **base_sign_cxt_dptr = cxt_qtree.base_sign_cxt - + WIDTH_OF_CXT_BDY; + SIGN_CXT_TYPE **base_sign_cxt_end_dptr = base_sign_cxt_dptr + r - 1; + for( ; base_sign_cxt_dptr != base_sign_cxt_end_dptr; base_sign_cxt_dptr++ ) + base_sign_cxt_dptr[1] = *base_sign_cxt_dptr + c; + + //for inter subbands correlations +#ifdef INTERBANDS + if( !( band->get_band_idx( ) ) || ( band->get_band_level( ) == 1 ) ) + child_cxt_qtree = NULL; //bottom bands have no kids and the top level + //only use info within subbands + else + child_cxt_qtree = + &( enc_band_tree->enc_subs[band->get_child_band_idx( )].cxt_qtree ); + +#endif + + +#ifdef GET_PARENT_MODELS + int par_idx = band->get_par( ); + if( ( par_idx < 0 ) + || ( ( par_idx == 0 ) && ( band->get_orientation( ) == HH ) ) ) + par_cxt_qtree = NULL; + else + par_cxt_qtree = &( enc_band_tree->enc_subs[par_idx].cxt_qtree ); + +#endif + + delete[]mem_dims; +} + +//----------------------------------------------------------------------------- + +//void EncSubband::setup_max_and_cxt_qtrees() + +//----------------------------------------------------------------------------- +void +EncSubband::setup_max_and_cxt_qtrees( ) +{ + int r, c, rc, lev; + PEL_CXT_TYPE *pel_cxt_ptr; + NODE_CXT_TYPE *node_cxt_ptr; + SUB_COEFF_TYPE *node_ptr, *cnode_ptr; + + SUB_COEFF_TYPE ***nodes = qtree.nodes; + NODE_CXT_TYPE ***cxt_nodes = cxt_qtree.cxt_nodes; + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + Image_Coord_Sht *dims = qtree.dims; + int depth = qtree.depth; + + Image_Coord band_dim = band->get_dim( ); + int rows = band_dim.x; + int cols = band_dim.y; + + rc = ( ( ( ( rows + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2 ) * + ( ( ( ( cols + 1 ) >> 1 ) << 1 ) + WIDTH_OF_CXT_BDY_X_2 ); + + //pel cxt state initialization + pel_cxt_ptr = &( base_cxt[-WIDTH_OF_CXT_BDY][-WIDTH_OF_CXT_BDY] ); + + PEL_CXT_TYPE *pel_cxt_end_ptr = pel_cxt_ptr + rc; + + while( pel_cxt_end_ptr != pel_cxt_ptr ) + *( pel_cxt_ptr++ ) = OUT_OF_BOUNDS; + + for( r = rows - 1; r >= 0; r-- ) { //initialize cxt = 0 for pels within the bounds + memset( base_cxt[r], 0, sizeof( PEL_CXT_TYPE ) * cols ); + } + + // OUT_OF_BOUNDS for all node_cxt + node_cxt_ptr = &( cxt_nodes[1][-WIDTH_OF_CXT_BDY][-WIDTH_OF_CXT_BDY] ); + NODE_CXT_TYPE *node_cxt_end_ptr = node_cxt_ptr + cxt_qtree.cxt_qtree_sz; + while( node_cxt_ptr != node_cxt_end_ptr ) + *( node_cxt_ptr++ ) = OUT_OF_BOUNDS; + + //reset node states + memset( nodes[1][0], 0, qtree.qtree_sz * sizeof( SUB_COEFF_TYPE ) ); + nodes[0] = base_coeff; + + for( lev = 1; lev <= depth; lev++ ) { + c = dims[lev].c; + int crow_gap = nodes[lev - 1][1] - nodes[lev - 1][0]; + for( r = dims[lev].r - 1; r >= 0; r-- ) { + node_ptr = nodes[lev][r]; + cnode_ptr = nodes[lev - 1][r << 1]; + node_cxt_ptr = cxt_nodes[lev][r]; + for( SUB_COEFF_TYPE * node_end_ptr = node_ptr + c; + node_ptr != node_end_ptr; cnode_ptr += 2 ) { + *( node_ptr++ ) = ( cnode_ptr[0] | cnode_ptr[1] | cnode_ptr[crow_gap] + | cnode_ptr[crow_gap + 1] ) & MAG_MASK; + *( node_cxt_ptr++ ) = 0; + } + } + } + // sign cxt state initialization + memset( &( cxt_qtree.base_sign_cxt[-WIDTH_OF_CXT_BDY][-WIDTH_OF_CXT_BDY] ), + 0, sizeof( SIGN_CXT_TYPE ) * rc ); +} + +//----------------------------------------------------------------------------- + +// set_functions(void) + +//----------------------------------------------------------------------------- +void +EncSubband::set_functions( void ) +{ + + encode_LIP = &EncSubband::encode_LIP_cxt_AC; + encode_LIS_leaves = &EncSubband::encode_LIS_leaves_cxt_AC; + encode_cur_qtree_level = &EncSubband::encode_cur_qtree_level_cxt_AC; + +#ifdef LSP_BIT_IDX + encode_LSP = &EncSubband::encode_LSP_cxt_AC_and_bit_idx; +#else + encode_LSP = &EncSubband::encode_LSP_cxt_AC; + +#endif + + encode_sig_leaf = &EncSubband::encode_sig_leaf_pos_dep_cxt_AC; + encode_sig_node = &EncSubband::encode_sig_node_pos_dep_cxt_AC; +} + +//----------------------------------------------------------------------------- + +// start_enc_subband() + +//----------------------------------------------------------------------------- +int +EncSubband::start_enc_subband( ) +{ + + assert( band ); + delete_coding_stats( ); + + setup_max_and_cxt_qtrees( ); + max_bit_idx = band->get_max_msb( ) - band->get_lsb( ); + bit_idx = max_bit_idx + 1; + no_bitplanes = max_bit_idx - EXTRA_BIT + 1; + if( no_bitplanes <= 0 ) { + no_bitplanes = 1; + } //printf("error\n"); + min_bit_idx = EXTRA_BIT; + + initialize_node_list( ); + create_coding_stats( ); + + //for now + sub_encoder->code_bits( 5, band->get_max_msb( ) + EXTRA_BIT ); + //printf("band->get_max_msb %d \n", band->get_max_msb()); + return 0; +} + + +//----------------------------------------------------------------------------- + +// enc_LIS_stack() + +//----------------------------------------------------------------------------- + +void +EncSubband::encode_LIS_stack( ) +{ + + do { + if( node_list.LIS_stack_top->level > 1 ) { + std_int node = node_list.LIS_stack_top->node; + int level = ( node_list.LIS_stack_top-- )->level - 1; + ( this->*encode_sig_node ) ( node, level ); + + //(this->*encode_sig_node)(node_list.LIS_stack_top->node, + //(node_list.LIS_stack_top--)->level-1); + // Rusert, 13.09.02 + } + else + ( this->*encode_sig_leaf ) ( ( node_list.LIS_stack_top-- )->node ); + } while( node_list.LIS_stack <= node_list.LIS_stack_top ); +} + +//----------------------------------------------------------------------------- + +// encode_LIS_nodes() + +//----------------------------------------------------------------------------- +void +EncSubband::encode_LIS_nodes( ) +{ +#ifdef INITIALIZE_NODE_MODELS_FROM_PAR + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + int lev, cxts, par_cxts; + MODEL_TYPE *par_node_models, *node_models; + + cxts = par_cxts = 0; + for( lev = qtree.depth - 2; lev > 1; lev-- ) { + //parent band with depth = qtree.depth - 1 + cxts += cxt_qtree.node_cxts[lev]; + par_cxts += par_cxt_qtree->node_cxts[lev]; + assert( cxts == par_cxts ); + } + node_models = cxt_qtree.cxt_models + cxt_qtree.node_offsets[2]; + par_node_models = + par_cxt_qtree->cxt_models + par_cxt_qtree->node_offsets[2]; + for( int i = cxts - 1; i >= 0; ) { + node_models[i].reset( par_node_models[i] ); + node_models[i--].taub_scale( ); + } + } +#endif + +#ifdef SCALE_JSIG_MODELS_AT_LEVEL_ENDS + int jsig_cxts = 0; + MODEL_TYPE *jsig_models = cxt_qtree.cxt_models + cxt_qtree.sig_offsets[0]; + for( int lev = qtree.depth - 1; lev >= 0; + jsig_cxts += cxt_qtree.sig_cxts[lev--] ); +#endif //SCALE_JSIG_MODELS_AT_LEVEL_ENDS + + + +#ifdef SCALE_NODE_MODELS_AT_LEVEL_ENDS + int node_cxts; + MODEL_TYPE *node_models; + + node_models = cxt_qtree.cxt_models + cxt_qtree.node_offsets[2]; + node_cxts = cxt_qtree.node_cxts[2]; +#endif //SCALE_NODE_MODELS_AT_LEVEL_ENDS + + cur_lev = 2; + + while( cur_lev < qtree.depth ) { + +#ifdef SCALE_JSIG_MODELS_AT_LEVEL_ENDS + for( int i = jsig_cxts - 1; i >= 0; + // jsig_models[i--].scale()); + jsig_models[i--].taub_scale( ) ); +#endif + + +#ifdef SCALE_NODE_MODELS_AT_LEVEL_ENDS + for( int i = node_cxts - 1; i >= 0; node_models[i--].taub_scale( ) ); +#endif + + ( this->*encode_cur_qtree_level ) ( ); + } +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_cxt_AC.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_cxt_AC.cpp new file mode 100644 index 0000000..0d8bdd7 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_cxt_AC.cpp @@ -0,0 +1,1160 @@ +/* ========================================================================= */ +/* Description:menber functions for class EncSubband with context modeling */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include +#include "dwt_bitplane_enc.h" + +//----------------------------------------------------------------------------- + +// encode_LIP_cxt_AC() + +//----------------------------------------------------------------------------- + +void +EncSubband::encode_LIP_cxt_AC( ) +{ + std_short r, c; + std_int cur_coord; + SUB_COEFF_TYPE coeff_cur; + PEL_CXT_TYPE *cxt_sp; + std_int *LIP_cur, *LIP_end, *LIP_old_end; + + + std_int *LSP_end = node_list.LSP_end; + // std_int *LSP = node_list.LSP; + std_int *LIP = node_list.LIP; + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + std_short cxt_row_gap = base_cxt[1] - base_cxt[0]; + MODEL_TYPE *LIP_models = cxt_qtree.cxt_models + cxt_qtree.LIP_offset; + std_byte *LIP_cxt_tab = cxt_qtree.LIP_tab; + + //sign related data........ + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + SUB_COEFF_TYPE *sign_cxt_tab = cxt_qtree.sign_tab; + SIGN_CXT_TYPE *sign_cxt_sp, **base_sign_cxt = cxt_qtree.base_sign_cxt; + std_short sign_cxt_row_gap = base_sign_cxt[1] - base_sign_cxt[0]; + SUB_COEFF_TYPE sign_predict, sign_bit; + + //interband related data +#ifdef INTERBANDS + int cd_base_cxt_row_gap; + PEL_CXT_TYPE *cd_base_cxt_sp, **cd_base_cxt; + NODE_CXT_TYPE *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_base_cxt = child_cxt_qtree->base_cxt; + cd_base_cxt_row_gap = cd_base_cxt[1] - cd_base_cxt[0]; + cd_cxt_node = child_cxt_qtree->cxt_nodes[1]; + } +#endif + +#ifdef INITIALIZE_LIP_MODELS_FROM_PAR + MODEL_TYPE *par_LIP_models; + + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + assert( cxt_qtree.LIP_cxts == par_cxt_qtree->LIP_cxts ); + par_LIP_models = par_cxt_qtree->cxt_models + par_cxt_qtree->LIP_offset; + for( int i = cxt_qtree.LIP_cxts - 1; i >= 0; + LIP_models[i].reset( par_LIP_models[i] ), + LIP_models[i--].taub_scale( ) ); + } +#endif + LIP_cur = LIP_end = LIP + node_list.LIP_sz; + LIP_old_end = node_list.LIP_end; + + //#ifdef DEBUG + //fprintf( stderr, "\nbit_idx %2d, encode_LIP.....\n", bit_idx ); + //#endif + + while( LIP_cur != LIP_old_end ) { + cur_coord = *( --LIP_cur ); + r = cur_coord >> 16; + c = cur_coord & 0xFFFF; + cxt_sp = base_cxt[r] + c; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + if( ( coeff_cur = base_coeff[r][c] ) & mag_mask ) { + if( ++LSP_end == LIP_old_end ) //LSP_pos runs beyond the end of the LSP + *( LIP_cur++ ) = *( LIP_old_end++ ); + *LSP_end = cur_coord; + + sub_encoder->code_symbol( 1, + LIP_models[LIP_cxt_tab[*cxt_sp & ZC_MASK]] ); + UPDATE_CXT( cxt_sp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cxt_sp = cd_base_cxt[r << 1] + ( c << 1 ); + UPDATE_4_CD_NODES( cd_base_cxt_sp, cd_base_cxt_row_gap ); + cd_cxt_node_sp = cd_cxt_node[r] + c; + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + sign_cxt_sp = base_sign_cxt[r] + c; + sign_predict = sign_cxt_tab[*sign_cxt_sp & SIGN_CXT_MASK]; + sign_bit = coeff_cur & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cxt_sp, sign_cxt_row_gap, sign_bit ); + + } else { + + *( --LIP_end ) = cur_coord; + sub_encoder->code_symbol( 0, + LIP_models[LIP_cxt_tab[*cxt_sp & ZC_MASK]] ); + } + } + node_list.LSP_end = LSP_end; + node_list.LIP_end = LIP_end; + +#ifdef LSP_BIT_IDX + node_list.LSP_ids[bit_idx][0] = LSP_end; +#endif + + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + +} + + + +//----------------------------------------------------------------------------- + +// encode_sig_leaf_cxt_AC() + +//----------------------------------------------------------------------------- +void +EncSubband::encode_sig_leaf_cxt_AC( std_int cur_coord ) +{ + // std_short dim_r = qtree.dims[0].r; + // std_short dim_c = qtree.dims[0].c; + std_short row_gap = base_coeff[1] - base_coeff[0]; + std_short cxt_row_gap = cxt_qtree.base_cxt[1] - cxt_qtree.base_cxt[0]; + + std_short r = ( cur_coord >> 16 ) << 1; + std_short c = ( cur_coord & 0xFFFF ) << 1; + + SUB_COEFF_TYPE *sp = base_coeff[r] + c; + PEL_CXT_TYPE *cp, *cxt_sp = cxt_qtree.base_cxt[r] + c; + MODEL_TYPE *sig_models = cxt_qtree.cxt_models + cxt_qtree.sig_offsets[0]; + std_byte *cxt_tab = cxt_qtree.sig_tabs[0]; + + //sign related data........ + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + SUB_COEFF_TYPE *sign_cxt_tab = cxt_qtree.sign_tab; + SIGN_CXT_TYPE **base_sign_cxt = cxt_qtree.base_sign_cxt; + SIGN_CXT_TYPE *sign_cp, *sign_cxt_sp = base_sign_cxt[r] + c; + std_short sign_cxt_row_gap = base_sign_cxt[1] - base_sign_cxt[0]; + SUB_COEFF_TYPE sign_predict, sign_bit; + + //interband related data +#ifdef INTERBANDS + int cd_base_cxt_row_gap, cd_cxt_node_row_gap; + PEL_CXT_TYPE *cd_base_cp, *cd_base_cxt_sp, **cd_base_cxt; + NODE_CXT_TYPE *cd_node_cp, *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_base_cxt = child_cxt_qtree->base_cxt; + cd_base_cxt_row_gap = cd_base_cxt[1] - cd_base_cxt[0]; + cd_base_cxt_sp = cd_base_cxt[r << 1] + ( c << 1 ); + cd_cxt_node = child_cxt_qtree->cxt_nodes[1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int nbits = 0; + cur_coord <<= 1; + + //#ifdef DEBUG + //fprintf( stderr, "LEAF, coord = %8x, (%d,%d)\n", cur_coord, r, c ); + //#endif + + + if( *sp & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cxt_sp & ZC_MASK]] ); + UPDATE_CXT( cxt_sp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_4_CD_NODES( cd_base_cxt_sp, cd_base_cxt_row_gap ); + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + sign_predict = sign_cxt_tab[*sign_cxt_sp & SIGN_CXT_MASK]; + sign_bit = *sp & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cxt_sp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord; + + nbits++; + + } else { + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cxt_sp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord; + + } + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sp[1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cp & ZC_MASK]] ); + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[1] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x1; + nbits++; + + } else { + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord | 0x1; + + } + } + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sp[row_gap] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cp & ZC_MASK]] ); + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ); + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[row_gap] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10000; + nbits++; + + } else { + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord | 0x10000; + + } + } + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( nbits ) { + if( sp[row_gap + 1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cp & ZC_MASK]] ); + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[row_gap + 1] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + *++node_list.LSP_end = cur_coord | 0x10001; + + } else { + + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord | 0x10001; + + } + } else { + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[row_gap + 1] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + + } + } + +} + + +//----------------------------------------------------------------------------- + +// encode_sig_node_cxt_AC() + +// sp[0] is always assumed to be within the image boundaries. +//----------------------------------------------------------------------------- + +void +EncSubband::encode_sig_node_cxt_AC( std_int cur_coord, int lev ) +{ + std_short row_gap = qtree.nodes[lev][1] - qtree.nodes[lev][0]; + std_short cxt_row_gap = + cxt_qtree.cxt_nodes[lev][1] - cxt_qtree.cxt_nodes[lev][0]; + std_short r = ( cur_coord >> 16 ) << 1; + std_short c = ( cur_coord & 0xFFFF ) << 1; + SUB_COEFF_TYPE *sp = qtree.nodes[lev][r] + c; + NODE_CXT_TYPE *cp, *cxt_sp = cxt_qtree.cxt_nodes[lev][r] + c; + MODEL_TYPE *sig_models = cxt_qtree.cxt_models + cxt_qtree.sig_offsets[lev]; + std_byte *sig_cxt_tab = cxt_qtree.sig_tabs[lev]; + + //new stuffs + std_int coord_buf[4]; + +#ifdef INTERBANDS + int cd_cxt_node_row_gap; + NODE_CXT_TYPE *cd_node_cp, *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[lev + 1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int nbits = 0; + cur_coord <<= 1; + + if( *sp & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cxt_sp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord; + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cxt_sp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord; + + } + + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sp[1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord | 0x1; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x1; + + } + } + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( sp[row_gap] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord | 0x10000; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10000; + + } + } + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + if( nbits ) { + if( sp[row_gap + 1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord | 0x10001; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10001; + + } + } else { + coord_buf[nbits++] = cur_coord | 0x10001; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + } + } + + while( nbits ) { + ( ++node_list.LIS_stack_top )->node = coord_buf[--nbits]; + node_list.LIS_stack_top->level = lev; + } + +} + +//----------------------------------------------------------------------------- + +// encode_LIS_leaves_cxt_AC(void) + +//----------------------------------------------------------------------------- +void +EncSubband::encode_LIS_leaves_cxt_AC( void ) +{ + int i; + std_short r, c; + std_int cur_coord, *LIS_cur, *LIS_end, *LIS_end_old; + + SUB_COEFF_TYPE **node = qtree.nodes[1]; + NODE_CXT_TYPE *cxt_sp, **cxt_nodes = cxt_qtree.cxt_nodes[1]; + std_short cxt_row_gap = cxt_nodes[1] - cxt_nodes[0]; + MODEL_TYPE *leaf_models = cxt_qtree.cxt_models + cxt_qtree.node_offsets[1]; + std_byte *leaf_cxt_tab = cxt_qtree.node_tabs[1]; + +#ifdef INTERBANDS + NODE_CXT_TYPE *cd_cxt_node_sp, **cd_cxt_node; + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[2]; + } +#endif + +#ifdef SCALE_SIGN_MODELS_AT_LEVEL_ENDS + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + for( i = cxt_qtree.sign_cxts - 1; i >= 0; sign_models[i--].taub_scale( ) ); +#endif + + +#ifdef INITIALIZE_NODE_MODELS_FROM_PAR + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + MODEL_TYPE *par_leaf_models; + + assert( cxt_qtree.node_cxts[1] == par_cxt_qtree->node_cxts[1] ); + par_leaf_models = par_cxt_qtree->cxt_models + + par_cxt_qtree->node_offsets[1]; + for( i = cxt_qtree.node_cxts[1] - 1; i >= 0; + leaf_models[i].reset( par_leaf_models[i] ), + leaf_models[i--].taub_scale( ) ); + } +#endif + + + LIS_cur = LIS_end = node_list.LIS[1] - 1; + LIS_end_old = node_list.LIS_end[1]; + //#ifdef DEBUG + //fprintf( stderr, "\nbit_idx %2d, encode_LIS_leaves.....\n", bit_idx ); + //#endif + + + for( ; LIS_cur < LIS_end_old; ) { + cur_coord = *( ++LIS_cur ); + r = cur_coord >> 16; + c = cur_coord & 0xFFFF; + cxt_sp = cxt_nodes[r] + c; + //#ifdef DEBUG + //fprintf( stderr, "%8x\n", cur_coord ); + //#endif + if( node[r][c] & mag_mask ) { + + sub_encoder->code_symbol( 1, + leaf_models[leaf_cxt_tab + [*cxt_sp & ZC_MASK]] ); + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_cxt_node_sp = cd_cxt_node[r] + c; + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + ( this->*encode_sig_leaf ) ( cur_coord ); + + } else { + + *++LIS_end = cur_coord; + sub_encoder->code_symbol( 0, + leaf_models[leaf_cxt_tab + [*cxt_sp & ZC_MASK]] ); + + } + } + node_list.LIS_end[1] = LIS_end; + + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + +#ifdef LSP_BIT_IDX + node_list.LSP_ids[bit_idx][1] = node_list.LSP_end; +#endif + +} + +//----------------------------------------------------------------------------- + +// encode_cur_qtree_level_cxt_AC() + +//----------------------------------------------------------------------------- +void +EncSubband::encode_cur_qtree_level_cxt_AC( ) +{ + assert( cur_lev < qtree.depth ); + + int i; + std_short r, c; + std_int cur_coord, *pLIS_cur, *pLIS_end, *pLIS_end_old; + SUB_COEFF_TYPE **pnode; + NODE_CXT_TYPE *cxt_sp, **cxt_nodes = cxt_qtree.cxt_nodes[cur_lev]; + std_short cxt_row_gap = cxt_nodes[1] - cxt_nodes[0]; + MODEL_TYPE *node_models = + cxt_qtree.cxt_models + cxt_qtree.node_offsets[cur_lev]; + std_byte *node_cxt_tab = cxt_qtree.node_tabs[cur_lev]; + +#ifdef INTERBANDS + NODE_CXT_TYPE *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[cur_lev + 1]; + } +#endif +#ifdef GRANDBANDS + NODE_CXT_TYPE *gd_cxt_node_sp, **gd_cxt_node; + + if( grand_child_cxt_qtree ) { + gd_cxt_node = grand_child_cxt_qtree->cxt_nodes[cur_lev + 2]; + } +#endif + +#ifdef SCALE_SIGN_MODELS_AT_LEVEL_ENDS + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + for( i = cxt_qtree.sign_cxts - 1; i >= 0; sign_models[i--].taub_scale( ) ); +#endif + + pLIS_cur = pLIS_end = node_list.LIS[cur_lev] - 1; + pLIS_end_old = node_list.LIS_end[cur_lev]; + pnode = qtree.nodes[cur_lev]; + + while( pLIS_cur < pLIS_end_old ) { + cur_coord = *( ++pLIS_cur ); + r = cur_coord >> 16; + c = cur_coord & 0xFFFF; + cxt_sp = cxt_nodes[r] + c; + //#ifdef DEBUG + //fprintf( stderr, "%8x\n", cur_coord ); + //#endif + if( pnode[r][c] & mag_mask ) { + + sub_encoder->code_symbol( 1, + node_models[node_cxt_tab + [*cxt_sp & ZC_MASK]] ); + UPDATE_CXT( cxt_sp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_cxt_node_sp = cd_cxt_node[r] + c; + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + ( this->*encode_sig_node ) ( cur_coord, cur_lev - 1 ); + + + encode_LIS_stack( ); + + } else { + + *++pLIS_end = cur_coord; + sub_encoder->code_symbol( 0, + node_models[node_cxt_tab + [*cxt_sp & ZC_MASK]] ); + } + } + + //new stuffs +#ifdef LSP_BIT_IDX + node_list.LSP_ids[bit_idx][cur_lev] = node_list.LSP_end; +#endif + + node_list.LIS_end[cur_lev++] = pLIS_end; + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + +} + +//----------------------------------------------------------------------------- + +// encode_LSP_cxt_AC() + +//---------------------------------------------------------------------------- +void +EncSubband::encode_LSP_cxt_AC( ) +{ + std_short r, c; + std_int *last, *sp, LSP_offset; + SUB_COEFF_TYPE mag; + std_int LSP_plane = node_list.LSP_plane; + std_int *LSP_mark = node_list.LSP_mark; + MODEL_TYPE *LSP_models = cxt_qtree.cxt_models + cxt_qtree.LSP_offset; + +#ifdef LSP_LUT + std_byte *LSP_cxt_tab = cxt_qtree.LSP_tab; +#endif + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + + + LSP_mark[LSP_plane] = node_list.LSP_end - node_list.LSP; + + //#ifdef DEBUG + //fprintf( stderr, "\nbit_idx %2d, encode_LSP.....\n", bit_idx ); + //#endif + + if( LSP_plane ) { + last = node_list.LSP + LSP_mark[LSP_plane - 1]; + for( sp = node_list.LSP; sp <= last; sp++ ) { + r = *sp >> 16; + c = *sp & 0xFFFF; + mag = ( base_coeff[r][c] & MAG_MASK ) >> bit_idx; + LSP_offset = 0; + + +#ifdef LSP_LUT + if( mag < 4 ) { + LSP_offset = LSP_cxt_tab[base_cxt[r][c]] + 1; + } +#else + if( mag < 4 ) { + if( base_cxt[r][c] & 0x0FFF ) + LSP_offset++; + } else + LSP_offset += 2; +#endif + + sub_encoder->code_symbol( mag & ( SUB_COEFF_TYPE ) 1, + LSP_models[LSP_offset] ); + + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", *sp >> 16, *sp & 0xFFFF ); + //#endif + + } + } + ++( node_list.LSP_plane ); + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + +} + +//new stuffs......................................... + +//----------------------------------------------------------------------------- + +// encode_LSP_cxt_AC_and_bit_idx(void) + +//----------------------------------------------------------------------------- + +void +EncSubband::encode_LSP_cxt_AC_and_bit_idx( void ) +{ + std_short r, c; + std_int *last, *sp, LSP_offset; + std_int LSP_plane = node_list.LSP_plane; + std_int *LSP_mark = node_list.LSP_mark; + + std_int **LSP_bit_idx_marks = node_list.LSP_bit_idx_marks; + std_int ***LSP_ids = node_list.LSP_ids; + int i, depth = qtree.depth; + + MODEL_TYPE *LSP_models = cxt_qtree.cxt_models + cxt_qtree.LSP_offset; + +#ifdef LSP_LUT + std_byte *LSP_cxt_tab = cxt_qtree.LSP_tab; +#endif + PEL_CXT_TYPE **base_cxt = cxt_qtree.base_cxt; + + LSP_mark[LSP_plane] = node_list.LSP_end - node_list.LSP; + + LSP_bit_idx_marks[bit_idx] = node_list.LSP_end; + + //#ifdef DEBUG + //fprintf( stderr, "\nbit_idx %2d, encode_LSP.....\n", bit_idx ); + //#endif + +//new stuffs +#ifdef INITIALIZE_LSP_MODELS_FROM_PAR + MODEL_TYPE *par_LSP_models; + + if( ( bit_idx == max_bit_idx - 1 ) && ( par_cxt_qtree ) ) { + assert( cxt_qtree.LSP_cxts == par_cxt_qtree->LSP_cxts ); + par_LSP_models = par_cxt_qtree->cxt_models + par_cxt_qtree->LSP_offset; + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i].reset( par_LSP_models[i] ), + LSP_models[i--].taub_scale( ) ); + } +#endif + + + +#ifdef LSP_LUT + int LSP_lev, LSP_set_offset; + if( bit_idx < max_bit_idx ) { + +#ifdef MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE + + LSP_lev = depth - 1; +#ifdef MERGE_ALL_LSP_PLANES + LSP_set_offset = 0; +#else + LSP_set_offset = 20; +#endif + +#else //MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE + LSP_lev = ( depth < 6 ) ? ( depth - 1 ) : 5; +#endif //MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE + + + for( sp = LSP_bit_idx_marks[bit_idx + 1]; LSP_lev > 1; LSP_lev-- ) { + +#ifndef MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE + LSP_set_offset = LSP_lev * 10; +#endif + + for( last = LSP_ids[bit_idx + 1][LSP_lev - 1]; sp > last; sp-- ) { + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + + //end of coding unit + } + +#ifdef MERGE_HIGH_IDX_SETS_OF_TOP_LSP_PLANE +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i--].taub_scale( ) ); +#endif +#endif + } + + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + + if( bit_idx < max_bit_idx - 1 ) { + //from leaves + last = LSP_ids[bit_idx + 1][0]; + +#ifndef MERGE_SETS_OF_TOP_LSP_PLANE + LSP_set_offset = 10; +#else + +#endif + for( ; sp > last; sp-- ) { + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + + //end of coding unit + } + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + +#ifdef MERGE_SETS_0_1_OF_TOP_PLANE + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i--].taub_scale( ) ); +#endif + +#else + LSP_set_offset = 0; +#endif + + last = LSP_bit_idx_marks[bit_idx + 2]; + for( ; sp > last; sp-- ) { + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + + //end of coding unit + + } + } + } + + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + + if( bit_idx < max_bit_idx - 1 ) { + + +#ifdef SEPARATE_SETS_OF_PLANE_1 + +#ifndef MERGE_LSP_PLANE_1 + LSP_set_offset = 60; +#else + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; LSP_models[i--].taub_scale( ) ); +#endif + +#endif + + LSP_lev = depth - 1; + for( ; LSP_lev >= 0; LSP_lev-- ) { + if( LSP_lev ) + last = LSP_ids[bit_idx + 2][LSP_lev - 1]; + else + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + + } + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; + LSP_models[i--].taub_scale( ) ); + } +#else + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + + LSP_set_offset = 60; + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + + } + +#endif + + } + + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + + if( bit_idx < max_bit_idx - 2 ) { +#ifndef MERGE_LOWER_LSP_PLANE + LSP_set_offset = 70; +#else + +#ifdef SCALE_AT_LSP_BREAK_PTS + for( i = cxt_qtree.LSP_cxts - 1; i >= 0; LSP_models[i--].taub_scale( ) ); +#endif + +#endif + + last = node_list.LSP - 1; + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + LSP_offset = LSP_set_offset + LSP_cxt_tab[base_cxt[r][c]]; + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + + } + } +#else //LSP_LUT + + + + int LSP_lev; + if( bit_idx < max_bit_idx ) { + //#if 0 //6 coding sets + LSP_lev = ( depth < 6 ) ? ( depth - 1 ) : 5; + for( sp = LSP_bit_idx_marks[bit_idx + 1]; LSP_lev > 1; LSP_lev-- ) { + LSP_offset = LSP_lev; + for( last = LSP_ids[bit_idx + 1][LSP_lev - 1]; sp > last; sp-- ) { + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + + //end of coding unit + + } + + } + + if( bit_idx < max_bit_idx - 1 ) { + //from leaves + last = LSP_ids[bit_idx + 1][0]; + LSP_offset = 1; + for( ; sp > last; sp-- ) { + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit + } + + + last = LSP_bit_idx_marks[bit_idx + 2]; + LSP_offset = 0; + for( ; sp > last; sp-- ) { + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + + //end of coding unit + } + } + } + + if( bit_idx < max_bit_idx - 1 ) { + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + LSP_offset = 10; + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + + } + } + + if( bit_idx < max_bit_idx - 2 ) { + last = node_list.LSP - 1; + LSP_offset = 11; + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + + } + } + //3 seperate levs......................................... + +#ifdef 3LEVS_AC0 + if( bit_idx < max_bit_idx ) { + last = ( bit_idx == max_bit_idx - 1 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 2]; + LSP_offset = 0; + for( sp = LSP_bit_idx_marks[bit_idx + 1]; sp > last; sp-- ) { + + + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit + } + } + if( bit_idx < max_bit_idx - 1 ) { + last = ( bit_idx == max_bit_idx - 2 ) ? + node_list.LSP - 1 : LSP_bit_idx_marks[bit_idx + 3]; + LSP_offset = 1; + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + + } + } + if( bit_idx < max_bit_idx - 2 ) { + last = node_list.LSP - 1; + LSP_offset = 2; + for( ; sp > last; sp-- ) { + //coding unit................................. + r = *sp >> 16; + c = *sp & 0xFFFF; + + //#ifdef DEBUG + //fprintf( stderr, "(%2d, %2d) ", r, c ); + //#endif + + sub_encoder->code_symbol( base_coeff[r][c] & bit_idx_mask, + LSP_models[LSP_offset] ); + //end of coding unit................................. + } + } +#endif //ifdef 3LEVS_AC0 + +#endif //LSP_LUT + + ++( node_list.LSP_plane ); + coding_stats.bitplanes[bit_idx].passes[cur_pass++].cumulative_bytes = + sub_encoder->bytes_used( ); + +} diff --git a/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_pos_dep_cxt_AC.cpp b/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_pos_dep_cxt_AC.cpp new file mode 100644 index 0000000..900b484 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/dwt_bitplane_enc_pos_dep_cxt_AC.cpp @@ -0,0 +1,428 @@ +/* ========================================================================= */ +/* Description: menber functions for class EncSubband*/ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include +#include "dwt_bitplane_enc.h" + +//----------------------------------------------------------------------------- + +// encode_sig_leaf_pos_dep_cxt_AC() + +//----------------------------------------------------------------------------- + +void +EncSubband::encode_sig_leaf_pos_dep_cxt_AC( std_int cur_coord ) +{ + // std_short dim_r = qtree.dims[0].r; + // std_short dim_c = qtree.dims[0].c; + std_short row_gap = base_coeff[1] - base_coeff[0]; + std_short cxt_row_gap = cxt_qtree.base_cxt[1] - cxt_qtree.base_cxt[0]; + + std_short r = ( cur_coord >> 16 ) << 1; + std_short c = ( cur_coord & 0xFFFF ) << 1; + + SUB_COEFF_TYPE *sp = base_coeff[r] + c; + PEL_CXT_TYPE *cp, *cxt_sp = cxt_qtree.base_cxt[r] + c; + + + MODEL_TYPE *sig_models, *cxt_models = cxt_qtree.cxt_models; + int *jsig_offsets = cxt_qtree.jsig_offsets[0]; + std_byte *cxt_tab, **jsig_tabs = cxt_qtree.jsig_tabs[0]; + + //sign related data........ + MODEL_TYPE *sign_models = cxt_qtree.cxt_models + cxt_qtree.sign_offset; + SUB_COEFF_TYPE *sign_cxt_tab = cxt_qtree.sign_tab; + SIGN_CXT_TYPE **base_sign_cxt = cxt_qtree.base_sign_cxt; + SIGN_CXT_TYPE *sign_cp, *sign_cxt_sp = base_sign_cxt[r] + c; + std_short sign_cxt_row_gap = base_sign_cxt[1] - base_sign_cxt[0]; + SUB_COEFF_TYPE sign_predict, sign_bit; + + //interband related data +#ifdef INTERBANDS + int cd_base_cxt_row_gap, cd_cxt_node_row_gap; + PEL_CXT_TYPE *cd_base_cp, *cd_base_cxt_sp, **cd_base_cxt; + NODE_CXT_TYPE *cd_node_cp, *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_base_cxt = child_cxt_qtree->base_cxt; + cd_base_cxt_row_gap = cd_base_cxt[1] - cd_base_cxt[0]; + cd_base_cxt_sp = cd_base_cxt[r << 1] + ( c << 1 ); + cd_cxt_node = child_cxt_qtree->cxt_nodes[1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int nbits = 0; + cur_coord <<= 1; + + //#ifdef DEBUG + //fprintf( stderr, "LEAF, coord = %8x, (%d,%d)\n", cur_coord, r, c ); + //#endif + + + sig_models = cxt_models + jsig_offsets[0]; + cxt_tab = jsig_tabs[0]; + + if( *sp & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cxt_sp & ZC_MASK]] ); + UPDATE_CXT( cxt_sp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_4_CD_NODES( cd_base_cxt_sp, cd_base_cxt_row_gap ); + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + sign_predict = sign_cxt_tab[*sign_cxt_sp & SIGN_CXT_MASK]; + sign_bit = *sp & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cxt_sp, sign_cxt_row_gap, sign_bit ); + + + *++node_list.LSP_end = cur_coord; + nbits++; + + } else { + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cxt_sp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord; + } + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[1]; + cxt_tab = jsig_tabs[1]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[1]; + cxt_tab = jsig_tabs[1]; + } +#endif + + if( sp[1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cp & ZC_MASK]] ); + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[1] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x1; + nbits++; + + } else { + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord | 0x1; + + } + } + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[2]; + cxt_tab = jsig_tabs[2]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[2]; + cxt_tab = jsig_tabs[2]; + } +#endif + + if( sp[row_gap] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cp & ZC_MASK]] ); + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ); + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + sign_cxt_row_gap; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[row_gap] & SIGN_BIT; + + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10000; + nbits++; + + } else { + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord | 0x10000; + + } + } + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + sig_models = cxt_models + jsig_offsets[3]; + cxt_tab = jsig_tabs[3]; + + if( nbits ) { + if( sp[row_gap + 1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[cxt_tab[*cp & ZC_MASK]] ); + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[row_gap + 1] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + + } else { + + sub_encoder->code_symbol( 0, sig_models[cxt_tab[*cp & ZC_MASK]] ); + *--node_list.LIP_end = cur_coord | 0x10001; + } + } else { + UPDATE_CXT( cp, cxt_row_gap ); + +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_base_cp = cd_base_cxt_sp + ( cd_base_cxt_row_gap << 1 ) + 2; + UPDATE_4_CD_NODES( cd_base_cp, cd_base_cxt_row_gap ); + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + sign_cp = sign_cxt_sp + sign_cxt_row_gap + 1; + sign_predict = sign_cxt_tab[*sign_cp & SIGN_CXT_MASK]; + sign_bit = sp[row_gap + 1] & SIGN_BIT; + + sub_encoder->code_symbol( ( sign_predict & SIGN_BIT ) ^ sign_bit, + sign_models[sign_predict & SIGN_CXT_MASK] ); + UPDATE_SIGN_CXT( sign_cp, sign_cxt_row_gap, sign_bit ); + + *++node_list.LSP_end = cur_coord | 0x10001; + } + } +} + +//----------------------------------------------------------------------------- + +// encode_sig_node_pos_dep_cxt_AC() + +// sp[0] is always assumed to be within the image boundaries. +//----------------------------------------------------------------------------- + +void +EncSubband::encode_sig_node_pos_dep_cxt_AC( std_int cur_coord, int lev ) +{ + std_short row_gap = qtree.nodes[lev][1] - qtree.nodes[lev][0]; + std_short cxt_row_gap = + cxt_qtree.cxt_nodes[lev][1] - cxt_qtree.cxt_nodes[lev][0]; + std_short r = ( cur_coord >> 16 ) << 1; + std_short c = ( cur_coord & 0xFFFF ) << 1; + SUB_COEFF_TYPE *sp = qtree.nodes[lev][r] + c; + NODE_CXT_TYPE *cp, *cxt_sp = cxt_qtree.cxt_nodes[lev][r] + c; + + MODEL_TYPE *sig_models, *cxt_models = cxt_qtree.cxt_models; + int *jsig_offsets = cxt_qtree.jsig_offsets[lev]; + std_byte *sig_cxt_tab, **jsig_tabs = cxt_qtree.jsig_tabs[lev]; + + std_int coord_buf[4]; + + //...................................... + +#ifdef INTERBANDS + int cd_cxt_node_row_gap; + NODE_CXT_TYPE *cd_node_cp, *cd_cxt_node_sp, **cd_cxt_node; + + if( child_cxt_qtree ) { + cd_cxt_node = child_cxt_qtree->cxt_nodes[lev + 1]; + cd_cxt_node_row_gap = cd_cxt_node[1] - cd_cxt_node[0]; + cd_cxt_node_sp = cd_cxt_node[r] + c; + } +#endif + + int nbits = 0; + cur_coord <<= 1; + + sig_models = cxt_models + jsig_offsets[0]; + sig_cxt_tab = jsig_tabs[0]; + + if( *sp & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cxt_sp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord; + UPDATE_CXT( cxt_sp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + UPDATE_1_CD_NODE( cd_cxt_node_sp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cxt_sp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord; + + } + + cp = cxt_sp + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[1]; + sig_cxt_tab = jsig_tabs[1]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + sig_cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[1]; + sig_cxt_tab = jsig_tabs[1]; + } +#endif + + if( sp[1] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord | 0x1; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x1; + + } + } + + cp = cxt_sp + cxt_row_gap; + if( !( *cp & OUT_OF_BOUNDS ) ) { + +#ifdef SEPARATE_JSIG_MODELS + sig_models = cxt_models + jsig_offsets[2]; + sig_cxt_tab = jsig_tabs[2]; +#else + if( nbits ) { + sig_models = cxt_models + jsig_offsets[3]; + sig_cxt_tab = jsig_tabs[3]; + } else { + sig_models = cxt_models + jsig_offsets[2]; + sig_cxt_tab = jsig_tabs[2]; + } +#endif + + if( sp[row_gap] & mag_mask ) { + + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord | 0x10000; + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else { + + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10000; + + } + } + + cp = cxt_sp + cxt_row_gap + 1; + if( !( *cp & OUT_OF_BOUNDS ) ) { + sig_models = cxt_models + jsig_offsets[3]; + sig_cxt_tab = jsig_tabs[3]; + + if( nbits ) { + if( sp[row_gap + 1] & mag_mask ) { + sub_encoder->code_symbol( 1, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + coord_buf[nbits++] = cur_coord | 0x10001; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + + } else { + sub_encoder->code_symbol( 0, sig_models[sig_cxt_tab[*cp & ZC_MASK]] ); + *( ++node_list.LIS_end[lev] ) = cur_coord | 0x10001; + + } + } else { + coord_buf[nbits++] = cur_coord | 0x10001; + + UPDATE_CXT( cp, cxt_row_gap ); +#ifdef INTERBANDS + if( child_cxt_qtree ) { + cd_node_cp = cd_cxt_node_sp + cd_cxt_node_row_gap + 1; + UPDATE_1_CD_NODE( cd_node_cp ); + } +#endif + } + } + + while( nbits ) { + ( ++node_list.LIS_stack_top )->node = coord_buf[--nbits]; + node_list.LIS_stack_top->level = lev; + } +} diff --git a/Interframe EZBC/EZBC0a/src/enc_subband_tree.cpp b/Interframe EZBC/EZBC0a/src/enc_subband_tree.cpp new file mode 100644 index 0000000..178b477 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/enc_subband_tree.cpp @@ -0,0 +1,87 @@ +/* ========================================================================= */ +/* Description: member functions for class EncSubbandTree */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + + +#include +#include +#include +#include "dwt_bitplane_enc.h" + +//============================================================================= +//----------------------------------------------------------------------------- + +// EncSubbandTree +// class EncSubbandTree:public SubbandTreeCodec +//----------------------------------------------------------------------------- +//comment out 062602 +/*EncSubbandTree:: +EncSubbandTree(SUBBAND_TREE_TYPE *subs, ENCODER_TYPE *enc) + : SubbandTreeCodec(subs), encoder(enc) +{ + tree_msb = subband_tree->get_max_msb(); + tree_lsb = subband_tree->get_band_ptr(0)->get_lsb(); + + NEW_VECTOR(enc_subs, subband_tree->get_nband(), ENC_SUBBAND_TYPE, + "SubbandEnc"); + int nbands = subband_tree->get_nband(); + for(int k = 0; k < nbands; k++){ + enc_subs[k].initialize(subband_tree->get_band_ptr(k), this, enc); + } +} +*/ +void +EncSubbandTree::initialize( SUBBAND_TREE_TYPE * subs, ENCODER_TYPE * enc ) +{ + SubbandTreeCodec::initialize( subs ); + encoder = enc; + + tree_msb = subband_tree->get_max_msb( ); // SUBBAND_TREE_TYPE *subband_tree; + tree_lsb = subband_tree->get_band_ptr( 0 )->get_lsb( ); + + NEW_VECTOR( enc_subs, subband_tree->get_nband( ), ENC_SUBBAND_TYPE, + "SubbandEnc" ); + int nbands = subband_tree->get_nband( ); + + for( int k = 0; k < nbands; k++ ) { + enc_subs[k].initialize( subband_tree->get_band_ptr( k ), this, encoder ); + } + +} +void +EncSubbandTree:: + +initialize( SUBBAND_TREE_TYPE * subs, int *subband_ACcoder, + ENCODER_TYPE * enc ) +{ + +// SubbandTreeCodec::initialize(subs); + + tree_msb = subband_tree->get_max_msb( ); // SUBBAND_TREE_TYPE *subband_tree; + tree_lsb = subband_tree->get_band_ptr( 0 )->get_lsb( ); + + int nbands = subband_tree->get_nband( ); + + NEW_VECTOR( enc_subs, nbands, ENC_SUBBAND_TYPE, "SubbandEnc" ); + + for( int k = 0; k < nbands; k++ ) { + enc_subs[k].initialize( subband_tree->get_band_ptr( k ), this, + &enc[subband_ACcoder[k]] ); + } + +} + + +void +EncSubbandTree::reset_tree_enc( SUBBAND_TREE_TYPE * subs ) +{ + reset_tree_codec( subs ); + tree_msb = subband_tree->get_max_msb( ); + int nbands = subband_tree->get_nband( ); + for( int k = 0; k < nbands; k++ ) { + enc_subs[k].reset_band_enc( subband_tree->get_band_ptr( k ) ); + } +} diff --git a/Interframe EZBC/EZBC0a/src/setup_cxt_tables.cpp b/Interframe EZBC/EZBC0a/src/setup_cxt_tables.cpp new file mode 100644 index 0000000..4f53214 --- /dev/null +++ b/Interframe EZBC/EZBC0a/src/setup_cxt_tables.cpp @@ -0,0 +1,1244 @@ +/* ========================================================================= */ +/* Description: luts for context-based AR. coding*/ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + + +#include "dwt_bitplane_codec.h" + + +std_byte * + SubbandCodec::sm0_sp_main_node_lut = + NULL; +std_byte * + SubbandCodec::sm0_sp_diag_node_lut = + NULL; + +std_byte * + SubbandCodec::mid_inter_and_sp_main_node_lut = + NULL; +std_byte * + SubbandCodec::mid_inter_and_sp_diag_node_lut = + NULL; + +std_byte * + SubbandCodec::mid_main_LSP_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_LSP_lut = + NULL; + +SUB_COEFF_TYPE * + SubbandCodec::mid_main_sign_lut = + NULL; +SUB_COEFF_TYPE * + SubbandCodec::mid_diag_sign_lut = + NULL; + +int + SubbandCodec::sm0_sp_main_node_cxts = + 4; +int + SubbandCodec::sm0_sp_diag_node_cxts = + 3; + +int + SubbandCodec::mid_inter_and_sp_main_node_cxts = + 10; +int + SubbandCodec::mid_inter_and_sp_diag_node_cxts = + 9; + +int + SubbandCodec::mid_main_LSP_cxts = + 5; +int + SubbandCodec::mid_diag_LSP_cxts = + 4; + +int + SubbandCodec::mid_main_sign_cxts = + 9; +int + SubbandCodec::mid_diag_sign_cxts = + 9; + +#ifdef TWO_SIGNIF_BITS + +std_byte * + SubbandCodec::sm3_2_signif_bits_main_LSP_lut = + NULL; +std_byte * + SubbandCodec::sm3_2_signif_bits_diag_LSP_lut = + NULL; + +int + SubbandCodec::sm3_2_signif_bits_main_LSP_cxts = + 3; +int + SubbandCodec::sm3_2_signif_bits_diag_LSP_cxts = + 3; +#endif + +std_byte * + SubbandCodec::mid_main_jsig_00_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig_00_lut = + NULL; +std_byte * + SubbandCodec::mid_main_jsig0_00_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig0_00_lut = + NULL; + +std_byte * + SubbandCodec::mid_main_jsig_01_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig_01_lut = + NULL; +std_byte * + SubbandCodec::mid_main_jsig0_01_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig0_01_lut = + NULL; + +std_byte * + SubbandCodec::mid_main_jsig_10_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig_10_lut = + NULL; +std_byte * + SubbandCodec::mid_main_jsig0_10_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig0_10_lut = + NULL; + +std_byte * + SubbandCodec::mid_main_jsig_11_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig_11_lut = + NULL; +std_byte * + SubbandCodec::mid_main_jsig0_11_lut = + NULL; +std_byte * + SubbandCodec::mid_diag_jsig0_11_lut = + NULL; + +int + SubbandCodec::mid_main_jsig_00_cxts = + 10; +int + SubbandCodec::mid_diag_jsig_00_cxts = + 10; +int + SubbandCodec::mid_main_jsig0_00_cxts = + 10; +int + SubbandCodec::mid_diag_jsig0_00_cxts = + 10; + +int + SubbandCodec::mid_main_jsig_01_cxts = + 10; +int + SubbandCodec::mid_diag_jsig_01_cxts = + 10; +int + SubbandCodec::mid_main_jsig0_01_cxts = + 10; +int + SubbandCodec::mid_diag_jsig0_01_cxts = + 10; + +int + SubbandCodec::mid_main_jsig_10_cxts = + 30; +int + SubbandCodec::mid_diag_jsig_10_cxts = + 30; +int + SubbandCodec::mid_main_jsig0_10_cxts = + 30; +int + SubbandCodec::mid_diag_jsig0_10_cxts = + 30; + +int + SubbandCodec::mid_main_jsig_11_cxts = + 11; +int + SubbandCodec::mid_diag_jsig_11_cxts = + 11; +int + SubbandCodec::mid_main_jsig0_11_cxts = + 11; +int + SubbandCodec::mid_diag_jsig0_11_cxts = + 11; + +//=========================================================================== + +void +SubbandCodec::initialize_zc_luts( void ) +{ + initialize_sm0_sp_node_luts( ); + + initialize_inter_and_sp_node_luts( ); + + initialize_mid_LSP_luts( ); + + initialize_sm3_2_signif_bits_LSP_luts( ); + + initialize_mid_jsig_luts( ); + + initialize_mid_jsig0_00_luts( ); + initialize_mid_jsig0_01_luts( ); + initialize_mid_jsig0_10_luts( ); + initialize_mid_jsig0_11_luts( ); + +} + +//----------------------------------------------------------------------------- + +// initialize_sc_lut() + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_sc_lut( void ) +{ + initialize_mid_sign_luts( ); +} + +//----------------------------------------------------------------------------- + +//STATIC delete_cxt_tables() + +//----------------------------------------------------------------------------- +void +SubbandCodec::delete_cxt_tables( ) +{ + DELETE_VECTOR( sm0_sp_main_node_lut ); + DELETE_VECTOR( sm0_sp_diag_node_lut ); + + DELETE_VECTOR( mid_inter_and_sp_main_node_lut ); + DELETE_VECTOR( mid_inter_and_sp_diag_node_lut ); + + DELETE_VECTOR( mid_main_sign_lut ); + DELETE_VECTOR( mid_diag_sign_lut ); + + DELETE_VECTOR( mid_main_LSP_lut ); + DELETE_VECTOR( mid_diag_LSP_lut ); + +#ifdef TWO_SIGNIF_BITS + DELETE_VECTOR( sm3_2_signif_bits_main_LSP_lut ); + DELETE_VECTOR( sm3_2_signif_bits_diag_LSP_lut ); +#endif + + + DELETE_VECTOR( mid_main_jsig_00_lut ); + DELETE_VECTOR( mid_diag_jsig_00_lut ); + DELETE_VECTOR( mid_main_jsig0_00_lut ); + DELETE_VECTOR( mid_diag_jsig0_00_lut ); + + DELETE_VECTOR( mid_main_jsig_01_lut ); + DELETE_VECTOR( mid_diag_jsig_01_lut ); + DELETE_VECTOR( mid_main_jsig0_01_lut ); + DELETE_VECTOR( mid_diag_jsig0_01_lut ); + + DELETE_VECTOR( mid_main_jsig_10_lut ); + DELETE_VECTOR( mid_diag_jsig_10_lut ); + DELETE_VECTOR( mid_main_jsig0_10_lut ); + DELETE_VECTOR( mid_diag_jsig0_10_lut ); + + DELETE_VECTOR( mid_main_jsig_11_lut ); + DELETE_VECTOR( mid_diag_jsig_11_lut ); + DELETE_VECTOR( mid_main_jsig0_11_lut ); + DELETE_VECTOR( mid_diag_jsig0_11_lut ); +} + + + +//----------------------------------------------------------------------------- + +// initialize_sm0_sp_node_luts() + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_sm0_sp_node_luts( void ) +{ + std_short idx, ctxt, v1, v2, v3, diag_ctxt; + + NEW_VECTOR( sm0_sp_main_node_lut, ZC_MASK + 1, std_byte, + "sm0_sp_main_node_lut" ); + + NEW_VECTOR( sm0_sp_diag_node_lut, ZC_MASK + 1, std_byte, + "sm0_sp_diag_node_lut" ); + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + /* First, form the context map for the horizontal and vertical bands. + These both use the same context map, because the horizontally + high-pass band is physically transposed before encoding. */ + + v1 = ( ( idx >> CL_POS ) & 1 ) + ( ( idx >> CR_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + + if( ( v1 == 0 ) && ( v2 == 0 ) && ( v3 == 1 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 0 ) && ( v2 == 1 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 1 ) && ( v2 == 0 ) ) { + ctxt = 2; + diag_ctxt = 1; + } else if( ( ( v1 == 0 ) && ( v2 == 2 ) ) + || ( ( v1 == 2 ) && ( v2 == 0 ) ) ) { + ctxt = 3; + diag_ctxt = 2; + } else if( ( v1 + v2 ) > 2 ) { + ctxt = 3; + diag_ctxt = 2; + } else { //(v1 == 1) && (v2 == 1) + ctxt = 3; + diag_ctxt = 2; + } + + assert( ctxt < sm0_sp_main_node_cxts ); + sm0_sp_main_node_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < sm0_sp_diag_node_cxts ); + sm0_sp_diag_node_lut[idx] = ( std_byte ) diag_ctxt; + } +} + +//----------------------------------------------------------------------------- + +// initialize_inter_and_sp_node_luts() + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_inter_and_sp_node_luts( void ) +{ + + std_short idx, ctxt, v1, v2, v3, diag_ctxt, v0; + + NEW_VECTOR( mid_inter_and_sp_main_node_lut, ZC_MASK + 1, std_byte, + "mid_inter_and_sp_main_node_lut" ); + NEW_VECTOR( mid_inter_and_sp_diag_node_lut, ZC_MASK + 1, std_byte, + "mid_inter_and_sp_diag_node_lut" ); + + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + + v0 = ( ( idx >> PA_POS ) & 1 ); + v1 = ( ( idx >> CL_POS ) & 1 ) + ( ( idx >> CR_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + if( v0 ) { + if( ( v1 == 0 ) && ( v2 == 0 ) && ( v3 == 1 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 0 ) && ( v2 == 1 ) ) { + ctxt = 1; + diag_ctxt = ( v3 < 3 ) ? 1 : 2; + } else if( ( v1 == 1 ) && ( v2 == 0 ) ) { + ctxt = 2; + diag_ctxt = ( v3 < 3 ) ? 1 : 2; + } else if( ( ( v1 == 0 ) && ( v2 == 2 ) ) + || ( ( v1 == 2 ) && ( v2 == 0 ) ) ) { + ctxt = 3; + diag_ctxt = 2; + } else if( ( v1 + v2 ) > 2 ) { + ctxt = 4; + diag_ctxt = 3; + } else { //(v1 == 1) && (v2 == 1) + ctxt = 3; + diag_ctxt = ( v3 < 2 ) ? 1 : 2; + } + } else { + if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 5; + diag_ctxt = 4; + } else if( ( v1 + v2 == 1 ) ) { + ctxt = ( v3 < 3 ) ? 5 : 6; + diag_ctxt = ( v3 < 3 ) ? 4 : 5; + } else if( ( ( v1 == 0 ) && ( v2 == 2 ) ) + || ( ( v1 == 2 ) && ( v2 == 0 ) ) ) { + ctxt = 6; + diag_ctxt = 5; + } else if( ( v1 + v2 ) > 2 ) { + ctxt = 7; + diag_ctxt = 6; + } else { //(v1 == 1) && (v2 == 1) + ctxt = 6; + diag_ctxt = 5; + } + } + + assert( ctxt < mid_inter_and_sp_main_node_cxts ); + mid_inter_and_sp_main_node_lut[idx] = ( std_byte ) ctxt; + assert( diag_ctxt < mid_inter_and_sp_diag_node_cxts ); + mid_inter_and_sp_diag_node_lut[idx] = ( std_byte ) diag_ctxt; + + + } +} + + +//----------------------------------------------------------------------------- + +// initialize_mid_sign_luts(void) + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_mid_sign_luts( void ) +{ + + ifc_int idx, vpos, vneg, hpos, hneg, ctxt, predict, v1, v2; + ifc_int diag_ctxt, diag_predict; + ifc_int nwpos, nwneg, nepos, neneg, v3, v4; + + NEW_VECTOR( mid_main_sign_lut, SIGN_CXT_MASK + 1, SUB_COEFF_TYPE, + "mid_main_sign_lut" ); + NEW_VECTOR( mid_diag_sign_lut, SIGN_CXT_MASK + 1, SUB_COEFF_TYPE, + "mid_diag_sign_lut" ); + + for( idx = 0; idx <= SIGN_CXT_MASK; idx++ ) { + + vpos = ( idx >> ( V_PVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + vneg = ( idx >> ( V_NVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + hpos = ( idx >> ( H_PVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + hneg = ( idx >> ( H_NVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + + v1 = hpos - hneg; + v2 = vpos - vneg; + + if( v2 > 0 ) { + diag_predict = predict = MIN_IFC_INT; + } else { + diag_predict = predict = 0; + if( v2 < 0 ) { + v1 = -v1; + v2 = -v2; + } + } + + if( v2 == 0 ) { + if( v1 < 0 ) { + predict = MIN_IFC_INT; + ctxt = 1, diag_ctxt = 1; + } else if( v1 > 0 ) { + diag_predict = MIN_IFC_INT; + ctxt = 1, diag_ctxt = 1; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + ctxt = 3 + v1; + diag_ctxt = 3 + v1; + } + + if( ctxt == 0 ) { + nwpos = ( idx >> ( NW_PVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + nwneg = ( idx >> ( NW_NVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + + nepos = ( idx >> ( NE_PVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + neneg = ( idx >> ( NE_NVE_BIT_POS - SIGN_BIT_POS ) ) & 1; + + v3 = nwpos - nwneg; + v4 = nepos - neneg; + + if( v3 < 0 ) { + v3 = -v3; + v4 = -v4; + diag_predict = predict = MIN_IFC_INT; + } + + if( v3 == 0 ) { + if( v4 < 0 ) { + diag_predict = MIN_IFC_INT; + ctxt = 5, diag_ctxt = 5; + //predict = MIN_IFC_INT; + } else if( v4 > 0 ) { + predict = MIN_IFC_INT; + ctxt = 5, diag_ctxt = 5; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + ctxt = 5; + diag_ctxt = 5; + } + } + assert( ( ctxt >= 0 ) && ( ctxt < mid_main_sign_cxts ) ); + mid_main_sign_lut[idx] = ctxt | predict; + + assert( ( diag_ctxt >= 0 ) && ( diag_ctxt < mid_diag_sign_cxts ) ); + mid_diag_sign_lut[idx] = diag_ctxt | diag_predict; + } + +} + + +//----------------------------------------------------------------------------- + +// initialize_mid_LSP_lut() + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_mid_LSP_luts( void ) +{ + std_short idx, ctxt, v1, v2, v3, diag_ctxt; + + NEW_VECTOR( mid_main_LSP_lut, ZC_MASK + 1, std_byte, "mid_main_LSP_lut" ); + + NEW_VECTOR( mid_diag_LSP_lut, ZC_MASK + 1, std_byte, "mid_main_LSP_lut" ); + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + /* First, form the context map for the horizontal and vertical bands. + These both use the same context map, because the horizontally + high-pass band is physically transposed before encoding. */ + + v1 = ( ( idx >> CL_POS ) & 1 ) + ( ( idx >> CR_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( v1 == 0 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v2 == 0 ) ) { + ctxt = 2; + diag_ctxt = 1; + } else if( ( v1 == 2 ) && ( v2 == 2 ) ) { + ctxt = 4; + diag_ctxt = 3; + } else { + ctxt = 3; + diag_ctxt = 2; + } + + assert( ctxt < mid_main_LSP_cxts ); + mid_main_LSP_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_LSP_cxts ); + mid_diag_LSP_lut[idx] = ( std_byte ) diag_ctxt; + + } +} + +#ifdef TWO_SIGNIF_BITS + +//----------------------------------------------------------------------------- + +// initialize_sm3_2_signif_bits_LSP_luts(void) + +//----------------------------------------------------------------------------- +void +SubbandCodec::initialize_sm3_2_signif_bits_LSP_luts( void ) +{ + std_short idx, ctxt, v1, v2, v3, vv1, vv2, diag_ctxt; + + NEW_VECTOR( sm3_2_signif_bits_main_LSP_lut, ZC_MASK + 1, std_byte, + "sm3_2_signif_bits_main_LSP_lut" ); + + NEW_VECTOR( sm3_2_signif_bits_diag_LSP_lut, ZC_MASK + 1, std_byte, + "sm3_2_signif_bits_diag_LSP_lut" ); + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + /* First, form the context map for the horizontal and vertical bands. + These both use the same context map, because the horizontally + high-pass band is physically transposed before encoding. */ + + vv1 = ( ( idx >> CL2_POS ) & 1 ) + ( ( idx >> CR2_POS ) & 1 ); + vv2 = ( ( idx >> TC2_POS ) & 1 ) + ( ( idx >> BC2_POS ) & 1 ); + + v1 = ( ( idx >> CL_POS ) & 1 ) + ( ( idx >> CR_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + + if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( vv1 == 0 ) && ( vv2 == 0 ) && ( v3 < 2 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( vv1 == 0 ) && ( vv2 == 0 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( vv1 == 0 ) ) { + ctxt = 2; + diag_ctxt = 1; + } else if( ( vv2 == 0 ) ) { + ctxt = 2; + diag_ctxt = 1; + } else if( ( vv1 == 2 ) && ( vv2 == 2 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( vv1 == 2 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( vv2 == 2 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else { + ctxt = 2; + diag_ctxt = 1; + } + + + assert( ctxt < sm3_2_signif_bits_main_LSP_cxts ); + sm3_2_signif_bits_main_LSP_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < sm3_2_signif_bits_diag_LSP_cxts ); + sm3_2_signif_bits_diag_LSP_lut[idx] = ( std_byte ) diag_ctxt; + } +} +#endif + +void +SubbandCodec::initialize_mid_jsig_luts( void ) +{ + std_short idx, ctxt, diag_ctxt, v1, v2, v3, p, l, r, t, bc, tr; //v0, + + NEW_VECTOR( mid_main_jsig_00_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig_00_lut" ); + NEW_VECTOR( mid_diag_jsig_00_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig_00_lut" ); + + NEW_VECTOR( mid_main_jsig_01_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig_01_lut" ); + NEW_VECTOR( mid_diag_jsig_01_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig_01_lut" ); + + NEW_VECTOR( mid_main_jsig_10_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig_10_lut" ); + NEW_VECTOR( mid_diag_jsig_10_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig_10_lut" ); + + NEW_VECTOR( mid_main_jsig_11_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig_11_lut" ); + NEW_VECTOR( mid_diag_jsig_11_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig_11_lut" ); + + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + + p = ( ( idx >> PA_POS ) & 1 ); + l = ( ( idx >> CL_POS ) & 1 ); + t = ( ( idx >> TC_POS ) & 1 ); + v3 = + ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ); + + if( p == 0 ) { + if( ( l && t ) ) { + ctxt = 3; + diag_ctxt = 3; + } else if( l || t ) { + ctxt = 1; + diag_ctxt = 1; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + if( ( l && t ) ) { + ctxt = 3; + diag_ctxt = 3; + } else if( l || t ) { + ctxt = 2; + diag_ctxt = 2; + } else if( v3 > 1 ) { + ctxt = 1; + diag_ctxt = 2; + } else { + ctxt = 1; + diag_ctxt = 1; + } + } + + assert( ctxt < mid_main_jsig_00_cxts ); + mid_main_jsig_00_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig_00_cxts ); + mid_diag_jsig_00_lut[idx] = ( std_byte ) diag_ctxt; + + + r = ( ( idx >> CR_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BR_POS ) & 1 ); + + + if( l == 0 ) { //sig + if( p == 0 ) { + if( r && t ) { + ctxt = 2; + diag_ctxt = 2; + } else if( r || t ) { + ctxt = 1; + diag_ctxt = 1; + } else if( v3 > 1 ) { + ctxt = 0; + diag_ctxt = 1; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + if( r || t ) { + ctxt = 2; + diag_ctxt = 2; + } else if( v3 > 1 ) { + ctxt = 1; + diag_ctxt = 2; + } else { + ctxt = 1; + diag_ctxt = 1; + } + } + } else { + if( p == 0 ) { + if( r && t ) { + ctxt = 7; + diag_ctxt = 7; + } else if( r || t ) { + ctxt = 4; + diag_ctxt = 4; + } else if( v3 > 1 ) { + ctxt = 3; + diag_ctxt = 4; + } else { + ctxt = 3; + diag_ctxt = 3; + } + } else { + if( r && t ) { + ctxt = 7; + diag_ctxt = 7; + } else if( r || t ) { + ctxt = 6; + diag_ctxt = 6; + } else if( v3 > 1 ) { + ctxt = 5; + diag_ctxt = 6; + } else { + ctxt = 5; + diag_ctxt = 5; + } + } + } + + assert( ctxt < mid_main_jsig_01_cxts ); + mid_main_jsig_01_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig_01_cxts ); + mid_diag_jsig_01_lut[idx] = ( std_byte ) diag_ctxt; + + + bc = ( ( idx >> BC_POS ) & 1 ); + tr = ( ( idx >> TR_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + if( ( t == 0 ) && ( tr == 0 ) ) { + if( p == 0 ) { + if( bc && l ) { + ctxt = 3; + diag_ctxt = 3; + } else if( bc || l ) { + ctxt = 1; + diag_ctxt = 2; + } else if( v3 ) { + ctxt = 0; + diag_ctxt = ( v3 > 1 ) ? 1 : 0; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + if( l ) { + ctxt = 3; + diag_ctxt = 3; + } else if( bc ) { + ctxt = 2; + diag_ctxt = 3; + } else if( v3 > 1 ) { + ctxt = 1; + diag_ctxt = 3; + } else { + ctxt = 1; + diag_ctxt = 2; + } + } + } else { + if( p == 0 ) { + if( t ) { + if( l && bc ) { + ctxt = 8; + diag_ctxt = 9; + } else if( l || bc ) { + ctxt = 7; + diag_ctxt = 8; + } else if( v3 ) { + ctxt = 5; + diag_ctxt = ( v3 > 1 ) ? 8 : 7; + } else { + ctxt = 5; + diag_ctxt = 5; + } + } else { + if( l || bc ) { + ctxt = 6; + diag_ctxt = 6; + } else if( v3 > 1 ) { + ctxt = 5; + diag_ctxt = 6; + } else { + ctxt = 4; + diag_ctxt = 4; + } + } + } else { + if( t ) { + if( l && bc ) { + ctxt = 12; + diag_ctxt = 13; + } else if( l || bc ) { + ctxt = 11; + diag_ctxt = 12; + } else if( v3 ) { + ctxt = 9; + diag_ctxt = ( v3 > 1 ) ? 12 : 10; + } else { + ctxt = 9; + diag_ctxt = 10; + } + } else { + if( l && bc ) { + ctxt = 12; + diag_ctxt = 13; + } else if( l || bc ) { + ctxt = 10; + diag_ctxt = 11; + } else if( v3 > 1 ) { + ctxt = 9; + diag_ctxt = 11; + } else { + ctxt = 9; + diag_ctxt = 10; + } + } + } + } + + assert( ctxt < mid_main_jsig_10_cxts ); + mid_main_jsig_10_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig_10_cxts ); + mid_diag_jsig_10_lut[idx] = ( std_byte ) diag_ctxt; + + + v1 = ( ( idx >> CL_POS ) & 1 ) + ( ( idx >> CR_POS ) & 1 ); + + if( p ) { + if( ( v1 == 0 ) && ( v2 == 0 ) && ( v3 == 1 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 0 ) && ( v2 == 1 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 1 ) && ( v2 == 0 ) ) { + ctxt = 2; + diag_ctxt = 1; + } else if( ( v1 + v2 ) > 2 ) { + ctxt = 4; + diag_ctxt = 3; + } else { //(v1 == 1) && (v2 == 1) + ctxt = 3; + diag_ctxt = 2; + } + } else { + if( ( v1 == 0 ) && ( v2 == 0 ) && ( v3 == 1 ) ) { + ctxt = 5; + diag_ctxt = 4; + } else if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 6; + diag_ctxt = 5; + } else if( ( v1 == 0 ) && ( v2 == 1 ) ) { + ctxt = 6; + diag_ctxt = 5; + } else if( ( v1 == 1 ) && ( v2 == 0 ) ) { + ctxt = 6; + diag_ctxt = 5; + } else if( ( v1 + v2 ) > 2 ) { + ctxt = 8; + diag_ctxt = 7; + } else { //(v1 == 1) && (v2 == 1) + ctxt = 7; + diag_ctxt = 6; + } + } + + assert( ctxt < mid_main_jsig_11_cxts ); + mid_main_jsig_11_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig_11_cxts ); + mid_diag_jsig_11_lut[idx] = ( std_byte ) diag_ctxt; + + } +} + + +//----------------------------------------------------------------------------- + +// initialize_mid_jsig0_00_luts(void) + +//---------------------------------------------------------------------------- + +void +SubbandCodec::initialize_mid_jsig0_00_luts( void ) +{ + std_short idx, ctxt, v0, v1, v2, v3, diag_ctxt; + + NEW_VECTOR( mid_main_jsig0_00_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig0_00_lut" ); + + NEW_VECTOR( mid_diag_jsig0_00_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig0_00_lut" ); + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + + v0 = ( ( idx >> PA_POS ) & 1 ); + v1 = ( ( idx >> CL_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ); + + if( v1 && v2 ) { + ctxt = 5; + diag_ctxt = 3; + } else if( v1 ) { + ctxt = ( v0 ) ? 4 : 2; + diag_ctxt = 2; + } else if( v2 ) { + ctxt = ( v0 ) ? 3 : 2; + diag_ctxt = 2; + } else if( v3 > 1 ) { + ctxt = 1; + diag_ctxt = 2; + } else if( v3 ) { + ctxt = 1; + diag_ctxt = 1; + } else { + ctxt = 0; + diag_ctxt = 0; + } + + assert( ctxt < mid_main_jsig0_00_cxts ); + mid_main_jsig0_00_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig0_00_cxts ); + mid_diag_jsig0_00_lut[idx] = ( std_byte ) diag_ctxt; + } + +} + + +void +SubbandCodec::initialize_mid_jsig0_01_luts( void ) +{ + std_short idx, ctxt, p, l, r, t, v3, diag_ctxt; + + NEW_VECTOR( mid_main_jsig0_01_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig0_01_lut" ); + + NEW_VECTOR( mid_diag_jsig0_01_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig0_01_lut" ); + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + p = ( ( idx >> PA_POS ) & 1 ); + l = ( ( idx >> CL_POS ) & 1 ); + r = ( ( idx >> CR_POS ) & 1 ); + t = ( ( idx >> TC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BR_POS ) & 1 ); + + if( l == 0 ) { + if( r && t ) { + ctxt = 4; + diag_ctxt = 3; + } else if( r ) { + ctxt = ( p ) ? 3 : 2; + diag_ctxt = 2; + } else if( t ) { + ctxt = ( p ) ? 3 : 2; + diag_ctxt = 2; + } else if( v3 > 1 ) { + ctxt = 1; + diag_ctxt = 2; + } else if( v3 ) { + ctxt = 1; + diag_ctxt = 1; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + if( r && t ) { + ctxt = 7; + diag_ctxt = 6; + } else if( r || t ) { + ctxt = ( p ) ? 7 : 6; + diag_ctxt = ( p ) ? 6 : 5; + } else if( v3 > 1 ) { + ctxt = 5; + diag_ctxt = ( p ) ? 6 : 5; + } else { + ctxt = 5; + diag_ctxt = 4; + } + } + + assert( ctxt < mid_main_jsig0_01_cxts ); + mid_main_jsig0_01_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig0_01_cxts ); + mid_diag_jsig0_01_lut[idx] = ( std_byte ) diag_ctxt; + + } +} + + + +void +SubbandCodec::initialize_mid_jsig0_10_luts( void ) +{ + std_short idx, ctxt, p, l, t, tr, bc, v2, v3, diag_ctxt; // r, + + NEW_VECTOR( mid_main_jsig0_10_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig0_10_lut" ); + + NEW_VECTOR( mid_diag_jsig0_10_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig0_10_lut" ); + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + + p = ( ( idx >> PA_POS ) & 1 ); + l = ( ( idx >> CL_POS ) & 1 ); + t = ( ( idx >> TC_POS ) & 1 ); + bc = ( ( idx >> BC_POS ) & 1 ); + tr = ( ( idx >> TR_POS ) & 1 ); + + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + if( ( t == 0 ) && ( tr == 0 ) ) { + if( p == 0 ) { + if( bc && l ) { + ctxt = 5; + diag_ctxt = 4; + } else if( bc || l ) { + ctxt = 1; + diag_ctxt = 1; + } else if( v3 ) { + ctxt = 2; + diag_ctxt = ( v3 > 1 ) ? 1 : 2; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } else { + if( bc && l ) { + ctxt = 5; + diag_ctxt = 4; + } else if( l ) { + ctxt = 4; + diag_ctxt = 3; + } else if( bc ) { + ctxt = 3; + diag_ctxt = 3; + } else if( v3 > 1 ) { + ctxt = 2; + diag_ctxt = 3; + } else if( v3 ) { + ctxt = 2; + diag_ctxt = 2; + } else { + ctxt = 0; + diag_ctxt = 0; + } + } + } else { + if( p == 0 ) { + if( t ) { + if( l && bc ) { + ctxt = 19; + diag_ctxt = 18; + } else if( l ) { + ctxt = 17; + diag_ctxt = 17; + } else if( bc ) { + ctxt = 17; + diag_ctxt = 17; + } else if( v3 ) { + ctxt = 15; + diag_ctxt = ( v3 > 1 ) ? 17 : 15; + } else { + ctxt = 15; + diag_ctxt = 14; + } + } else { + if( l && bc ) { + ctxt = 12; + diag_ctxt = 12; + } else if( l ) { + ctxt = 12; + diag_ctxt = 12; + } else if( bc ) { + ctxt = 12; + diag_ctxt = 12; + } else if( v3 > 1 ) { + ctxt = 15; + diag_ctxt = 12; + } else { + ctxt = 10; + diag_ctxt = 10; + } + } + } else { + if( t ) { + if( l && bc ) { + ctxt = 24; + diag_ctxt = 23; + } else if( l ) { + ctxt = 27; + diag_ctxt = 27; + } else if( bc ) { + ctxt = 27; + diag_ctxt = 27; + } else if( v3 ) { + ctxt = 25; + diag_ctxt = ( v3 > 1 ) ? 27 : 24; + } else { + ctxt = 25; + diag_ctxt = 24; + } + } else { + if( l && bc ) { + ctxt = 24; + diag_ctxt = 23; + } else if( l ) { + ctxt = 22; + diag_ctxt = 22; + } else if( bc ) { + ctxt = 22; + diag_ctxt = 22; + } else if( v3 > 1 ) { + ctxt = 25; + diag_ctxt = ( v3 == 2 ) ? 22 : 22; + } else { + ctxt = 25; + diag_ctxt = 24; + } + } + } + } + + assert( ctxt < mid_main_jsig0_10_cxts ); + mid_main_jsig0_10_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig0_10_cxts ); + mid_diag_jsig0_10_lut[idx] = ( std_byte ) diag_ctxt; + } +} + + + +void +SubbandCodec::initialize_mid_jsig0_11_luts( void ) +{ + std_short idx, ctxt, v1, v2, v3, diag_ctxt, v0; + + + NEW_VECTOR( mid_main_jsig0_11_lut, ZC_MASK + 1, std_byte, + "mid_main_jsig0_11_lut" ); + NEW_VECTOR( mid_diag_jsig0_11_lut, ZC_MASK + 1, std_byte, + "mid_diag_jsig0_11_lut" ); + + + for( idx = 0; idx <= ZC_MASK; idx++ ) { + + v0 = ( ( idx >> PA_POS ) & 1 ); + v1 = ( ( idx >> CL_POS ) & 1 ) + ( ( idx >> CR_POS ) & 1 ); + v2 = ( ( idx >> TC_POS ) & 1 ) + ( ( idx >> BC_POS ) & 1 ); + v3 = ( ( idx >> TL_POS ) & 1 ) + ( ( idx >> TR_POS ) & 1 ) + + ( ( idx >> BL_POS ) & 1 ) + ( ( idx >> BR_POS ) & 1 ); + + if( ( v1 == 0 ) && ( v2 == 0 ) && ( v3 == 1 ) ) { + ctxt = 0; + diag_ctxt = 0; + } else if( ( v1 == 0 ) && ( v2 == 0 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 0 ) && ( v2 == 1 ) ) { + ctxt = 1; + diag_ctxt = 1; + } else if( ( v1 == 1 ) && ( v2 == 0 ) ) { + ctxt = 2; + diag_ctxt = 1; + } else if( ( v1 == 0 ) && ( v2 == 2 ) ) { + ctxt = 3; + diag_ctxt = 2; + } else if( ( v1 == 2 ) && ( v2 == 0 ) ) { + ctxt = 3; + diag_ctxt = 2; + } else if( ( v1 + v2 ) > 2 ) { + ctxt = 4; + diag_ctxt = 3; + } else { //(v1 == 1) && (v2 == 1) + ctxt = 3; + diag_ctxt = 2; + } + + assert( ctxt < mid_main_jsig0_11_cxts ); + mid_main_jsig0_11_lut[idx] = ( std_byte ) ctxt; + + assert( diag_ctxt < mid_diag_jsig0_11_cxts ); + mid_diag_jsig0_11_lut[idx] = ( std_byte ) diag_ctxt; + + } +} diff --git a/Interframe EZBC/MATLAB files/JP2K2YUV.m b/Interframe EZBC/MATLAB files/JP2K2YUV.m new file mode 100644 index 0000000..1bd51bb --- /dev/null +++ b/Interframe EZBC/MATLAB files/JP2K2YUV.m @@ -0,0 +1,162 @@ +clear all; +clc; + +num_frames = 144; +GOPsz = 32; + +GOPnum = num_frames / GOPsz; +GOPres = num_frames - GOPsz * floor(GOPnum); +GOPnum = floor(GOPnum); + +width = 352; +height = 288; +y_size = width*height; +c_size = y_size / 4; +f_size = y_size + 2*c_size; + +Y = zeros(y_size*num_frames,1); +U = zeros(c_size*num_frames,1); +V = zeros(c_size*num_frames,1); + +outfid = fopen('BUS_352x288_30_dec_jp2k_01.yuv','wb'); + +% %expand JP2K data and write back into subbands +% for i = 0:(GOPnum-1) +% +% jpx_name = ['tmp_mob' num2str(i) '.j2c']; +% % system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl ' ' -raw_components ']); +% system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,y64.rawl,y65.rawl,y66.rawl,y67.rawl,y68.rawl,y69.rawl,y70.rawl,y71.rawl,y72.rawl,y73.rawl,y74.rawl,y75.rawl,y76.rawl,y77.rawl,y78.rawl,y79.rawl,y80.rawl,y81.rawl,y82.rawl,y83.rawl,y84.rawl,y85.rawl,y86.rawl,y87.rawl,y88.rawl,y89.rawl,y90.rawl,y91.rawl,y92.rawl,y93.rawl,y94.rawl,y95.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,u16.rawl,u17.rawl,u18.rawl,u19.rawl,u20.rawl,u21.rawl,u22.rawl,u23.rawl,u24.rawl,u25.rawl,u26.rawl,u27.rawl,u28.rawl,u29.rawl,u30.rawl,u31.rawl,u32.rawl,u33.rawl,u34.rawl,u35.rawl,u36.rawl,u37.rawl,u38.rawl,u39.rawl,u40.rawl,u41.rawl,u42.rawl,u43.rawl,u44.rawl,u45.rawl,u46.rawl,u47.rawl,u48.rawl,u49.rawl,u50.rawl,u51.rawl,u52.rawl,u53.rawl,u54.rawl,u55.rawl,u56.rawl,u57.rawl,u58.rawl,u59.rawl,u60.rawl,u61.rawl,u62.rawl,u63.rawl,u64.rawl,u65.rawl,u66.rawl,u67.rawl,u68.rawl,u69.rawl,u70.rawl,u71.rawl,u72.rawl,u73.rawl,u74.rawl,u75.rawl,u76.rawl,u77.rawl,u78.rawl,u79.rawl,u80.rawl,u81.rawl,u82.rawl,u83.rawl,u84.rawl,u85.rawl,u86.rawl,u87.rawl,u88.rawl,u89.rawl,u90.rawl,u91.rawl,u92.rawl,u93.rawl,u94.rawl,u95.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl,v16.rawl,v17.rawl,v18.rawl,v19.rawl,v20.rawl,v21.rawl,v22.rawl,v23.rawl,v24.rawl,v25.rawl,v26.rawl,v27.rawl,v28.rawl,v29.rawl,v30.rawl,v31.rawl,v32.rawl,v33.rawl,v34.rawl,v35.rawl,v36.rawl,v37.rawl,v38.rawl,v39.rawl,v40.rawl,v41.rawl,v42.rawl,v43.rawl,v44.rawl,v45.rawl,v46.rawl,v47.rawl,v48.rawl,v49.rawl,v50.rawl,v51.rawl,v52.rawl,v53.rawl,v54.rawl,v55.rawl,v56.rawl,v57.rawl,v58.rawl,v59.rawl,v60.rawl,v61.rawl,v62.rawl,v63.rawl,v64.rawl,v65.rawl,v66.rawl,v67.rawl,v68.rawl,v69.rawl,v70.rawl,v71.rawl,v72.rawl,v73.rawl,v74.rawl,v75.rawl,v76.rawl,v77.rawl,v78.rawl,v79.rawl,v80.rawl,v81.rawl,v82.rawl,v83.rawl,v84.rawl,v85.rawl,v86.rawl,v87.rawl,v88.rawl,v89.rawl,v90.rawl,v91.rawl,v92.rawl,v93.rawl,v94.rawl,v95.rawl ' ' -raw_components ']); +% +% % system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,u16.rawl,u17.rawl,u18.rawl,u19.rawl,u20.rawl,u21.rawl,u22.rawl,u23.rawl,u24.rawl,u25.rawl,u26.rawl,u27.rawl,u28.rawl,u29.rawl,u30.rawl,u31.rawl,u32.rawl,u33.rawl,u34.rawl,u35.rawl,u36.rawl,u37.rawl,u38.rawl,u39.rawl,u40.rawl,u41.rawl,u42.rawl,u43.rawl,u44.rawl,u45.rawl,u46.rawl,u47.rawl,u48.rawl,u49.rawl,u50.rawl,u51.rawl,u52.rawl,u53.rawl,u54.rawl,u55.rawl,u56.rawl,u57.rawl,u58.rawl,u59.rawl,u60.rawl,u61.rawl,u62.rawl,u63.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl,v16.rawl,v17.rawl,v18.rawl,v19.rawl,v20.rawl,v21.rawl,v22.rawl,v23.rawl,v24.rawl,v25.rawl,v26.rawl,v27.rawl,v28.rawl,v29.rawl,v30.rawl,v31.rawl,v32.rawl,v33.rawl,v34.rawl,v35.rawl,v36.rawl,v37.rawl,v38.rawl,v39.rawl,v40.rawl,v41.rawl,v42.rawl,v43.rawl,v44.rawl,v45.rawl,v46.rawl,v47.rawl,v48.rawl,v49.rawl,v50.rawl,v51.rawl,v52.rawl,v53.rawl,v54.rawl,v55.rawl,v56.rawl,v57.rawl,v58.rawl,v59.rawl,v60.rawl,v61.rawl,v62.rawl,v63.rawl ' ' -raw_components ']); +% % system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,y64.rawl,y65.rawl,y66.rawl,y67.rawl,y68.rawl,y69.rawl,y70.rawl,y71.rawl,y72.rawl,y73.rawl,y74.rawl,y75.rawl,y76.rawl,y77.rawl,y78.rawl,y79.rawl,y80.rawl,y81.rawl,y82.rawl,y83.rawl,y84.rawl,y85.rawl,y86.rawl,y87.rawl,y88.rawl,y89.rawl,y90.rawl,y91.rawl,y92.rawl,y93.rawl,y94.rawl,y95.rawl ' ' -raw_components ']); +% +% for j = 0:(GOPsz-1) +% +% fid_name1 = ['y' num2str( j ) '.rawl']; +% fid_name2 = ['u' num2str( j ) '.rawl']; +% fid_name3 = ['v' num2str( j ) '.rawl']; +% +% fp = fopen(fid_name1,'rb'); +% Y = fread(fp,y_size,'int16'); +% fclose(fp); +% +% fp = fopen(fid_name2,'rb'); +% U = fread(fp,c_size,'int16'); +% fclose(fp); +% +% fp = fopen(fid_name3,'rb'); +% V = fread(fp,c_size,'int16'); +% fclose(fp); +% +% % fp = fopen(fid_name1,'rb'); +% % Y = fread(fp,y_size,'int16'); +% % U = fread(fp,c_size,'int16'); +% % V = fread(fp,c_size,'int16'); +% % fclose(fp); +% +% Y = (Y/32); +% U = (U/32); +% V = (V/32); +% +% % if j == 0 || j == 32 +% % U = U + 128; +% % V = V + 128; +% % end +% +% fwrite(outfid,Y,'float32'); +% fwrite(outfid,U,'float32'); +% fwrite(outfid,V,'float32'); +% +% % if j == 0 +% % Yd = reshape(Y,width,height); +% % Ud = reshape(U,width/2,height/2); +% % Vd = reshape(V,width/2,height/2); +% % end +% +% end +% +% end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% GOPsz = 144; +% GOPnum = 1; +% GOPres = 0; +%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%expand JP2K data and write back into subbands +for i = 0:(GOPnum-1) + + jpx_name = ['tmp_bq' num2str(i) '.j2c']; +% system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl ' ' -raw_components ']); +% system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,y64.rawl,y65.rawl,y66.rawl,y67.rawl,y68.rawl,y69.rawl,y70.rawl,y71.rawl,y72.rawl,y73.rawl,y74.rawl,y75.rawl,y76.rawl,y77.rawl,y78.rawl,y79.rawl,y80.rawl,y81.rawl,y82.rawl,y83.rawl,y84.rawl,y85.rawl,y86.rawl,y87.rawl,y88.rawl,y89.rawl,y90.rawl,y91.rawl,y92.rawl,y93.rawl,y94.rawl,y95.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,u16.rawl,u17.rawl,u18.rawl,u19.rawl,u20.rawl,u21.rawl,u22.rawl,u23.rawl,u24.rawl,u25.rawl,u26.rawl,u27.rawl,u28.rawl,u29.rawl,u30.rawl,u31.rawl,u32.rawl,u33.rawl,u34.rawl,u35.rawl,u36.rawl,u37.rawl,u38.rawl,u39.rawl,u40.rawl,u41.rawl,u42.rawl,u43.rawl,u44.rawl,u45.rawl,u46.rawl,u47.rawl,u48.rawl,u49.rawl,u50.rawl,u51.rawl,u52.rawl,u53.rawl,u54.rawl,u55.rawl,u56.rawl,u57.rawl,u58.rawl,u59.rawl,u60.rawl,u61.rawl,u62.rawl,u63.rawl,u64.rawl,u65.rawl,u66.rawl,u67.rawl,u68.rawl,u69.rawl,u70.rawl,u71.rawl,u72.rawl,u73.rawl,u74.rawl,u75.rawl,u76.rawl,u77.rawl,u78.rawl,u79.rawl,u80.rawl,u81.rawl,u82.rawl,u83.rawl,u84.rawl,u85.rawl,u86.rawl,u87.rawl,u88.rawl,u89.rawl,u90.rawl,u91.rawl,u92.rawl,u93.rawl,u94.rawl,u95.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl,v16.rawl,v17.rawl,v18.rawl,v19.rawl,v20.rawl,v21.rawl,v22.rawl,v23.rawl,v24.rawl,v25.rawl,v26.rawl,v27.rawl,v28.rawl,v29.rawl,v30.rawl,v31.rawl,v32.rawl,v33.rawl,v34.rawl,v35.rawl,v36.rawl,v37.rawl,v38.rawl,v39.rawl,v40.rawl,v41.rawl,v42.rawl,v43.rawl,v44.rawl,v45.rawl,v46.rawl,v47.rawl,v48.rawl,v49.rawl,v50.rawl,v51.rawl,v52.rawl,v53.rawl,v54.rawl,v55.rawl,v56.rawl,v57.rawl,v58.rawl,v59.rawl,v60.rawl,v61.rawl,v62.rawl,v63.rawl,v64.rawl,v65.rawl,v66.rawl,v67.rawl,v68.rawl,v69.rawl,v70.rawl,v71.rawl,v72.rawl,v73.rawl,v74.rawl,v75.rawl,v76.rawl,v77.rawl,v78.rawl,v79.rawl,v80.rawl,v81.rawl,v82.rawl,v83.rawl,v84.rawl,v85.rawl,v86.rawl,v87.rawl,v88.rawl,v89.rawl,v90.rawl,v91.rawl,v92.rawl,v93.rawl,v94.rawl,v95.rawl ' ' -raw_components ']); + +% system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,u16.rawl,u17.rawl,u18.rawl,u19.rawl,u20.rawl,u21.rawl,u22.rawl,u23.rawl,u24.rawl,u25.rawl,u26.rawl,u27.rawl,u28.rawl,u29.rawl,u30.rawl,u31.rawl,u32.rawl,u33.rawl,u34.rawl,u35.rawl,u36.rawl,u37.rawl,u38.rawl,u39.rawl,u40.rawl,u41.rawl,u42.rawl,u43.rawl,u44.rawl,u45.rawl,u46.rawl,u47.rawl,u48.rawl,u49.rawl,u50.rawl,u51.rawl,u52.rawl,u53.rawl,u54.rawl,u55.rawl,u56.rawl,u57.rawl,u58.rawl,u59.rawl,u60.rawl,u61.rawl,u62.rawl,u63.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl,v16.rawl,v17.rawl,v18.rawl,v19.rawl,v20.rawl,v21.rawl,v22.rawl,v23.rawl,v24.rawl,v25.rawl,v26.rawl,v27.rawl,v28.rawl,v29.rawl,v30.rawl,v31.rawl,v32.rawl,v33.rawl,v34.rawl,v35.rawl,v36.rawl,v37.rawl,v38.rawl,v39.rawl,v40.rawl,v41.rawl,v42.rawl,v43.rawl,v44.rawl,v45.rawl,v46.rawl,v47.rawl,v48.rawl,v49.rawl,v50.rawl,v51.rawl,v52.rawl,v53.rawl,v54.rawl,v55.rawl,v56.rawl,v57.rawl,v58.rawl,v59.rawl,v60.rawl,v61.rawl,v62.rawl,v63.rawl ' ' -raw_components ']); +% system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,y64.rawl,y65.rawl,y66.rawl,y67.rawl,y68.rawl,y69.rawl,y70.rawl,y71.rawl,y72.rawl,y73.rawl,y74.rawl,y75.rawl,y76.rawl,y77.rawl,y78.rawl,y79.rawl,y80.rawl,y81.rawl,y82.rawl,y83.rawl,y84.rawl,y85.rawl,y86.rawl,y87.rawl,y88.rawl,y89.rawl,y90.rawl,y91.rawl,y92.rawl,y93.rawl,y94.rawl,y95.rawl ' ' -raw_components ']); + +% system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,y32.rawl,y33.rawl,y34.rawl,y35.rawl,y36.rawl,y37.rawl,y38.rawl,y39.rawl,y40.rawl,y41.rawl,y42.rawl,y43.rawl,y44.rawl,y45.rawl,y46.rawl,y47.rawl,y48.rawl,y49.rawl,y50.rawl,y51.rawl,y52.rawl,y53.rawl,y54.rawl,y55.rawl,y56.rawl,y57.rawl,y58.rawl,y59.rawl,y60.rawl,y61.rawl,y62.rawl,y63.rawl,y64.rawl,y65.rawl,y66.rawl,y67.rawl,y68.rawl,y69.rawl,y70.rawl,y71.rawl,y72.rawl,y73.rawl,y74.rawl,y75.rawl,y76.rawl,y77.rawl,y78.rawl,y79.rawl,y80.rawl,y81.rawl,y82.rawl,y83.rawl,y84.rawl,y85.rawl,y86.rawl,y87.rawl,y88.rawl,y89.rawl,y90.rawl,y91.rawl,y92.rawl,y93.rawl,y94.rawl,y95.rawl,y96.rawl,y97.rawl,y98.rawl,y99.rawl,y100.rawl,y101.rawl,y102.rawl,y103.rawl,y104.rawl,y105.rawl,y106.rawl,y107.rawl,y108.rawl,y109.rawl,y110.rawl,y111.rawl,y112.rawl,y113.rawl,y114.rawl,y115.rawl,y116.rawl,y117.rawl,y118.rawl,y119.rawl,y120.rawl,y121.rawl,y122.rawl,y123.rawl,y124.rawl,y125.rawl,y126.rawl,y127.rawl,y128.rawl,y129.rawl,y130.rawl,y131.rawl,y132.rawl,y133.rawl,y134.rawl,y135.rawl,y136.rawl,y137.rawl,y138.rawl,y139.rawl,y140.rawl,y141.rawl,y142.rawl,y143.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,u16.rawl,u17.rawl,u18.rawl,u19.rawl,u20.rawl,u21.rawl,u22.rawl,u23.rawl,u24.rawl,u25.rawl,u26.rawl,u27.rawl,u28.rawl,u29.rawl,u30.rawl,u31.rawl,u32.rawl,u33.rawl,u34.rawl,u35.rawl,u36.rawl,u37.rawl,u38.rawl,u39.rawl,u40.rawl,u41.rawl,u42.rawl,u43.rawl,u44.rawl,u45.rawl,u46.rawl,u47.rawl,u48.rawl,u49.rawl,u50.rawl,u51.rawl,u52.rawl,u53.rawl,u54.rawl,u55.rawl,u56.rawl,u57.rawl,u58.rawl,u59.rawl,u60.rawl,u61.rawl,u62.rawl,u63.rawl,u64.rawl,u65.rawl,u66.rawl,u67.rawl,u68.rawl,u69.rawl,u70.rawl,u71.rawl,u72.rawl,u73.rawl,u74.rawl,u75.rawl,u76.rawl,u77.rawl,u78.rawl,u79.rawl,u80.rawl,u81.rawl,u82.rawl,u83.rawl,u84.rawl,u85.rawl,u86.rawl,u87.rawl,u88.rawl,u89.rawl,u90.rawl,u91.rawl,u92.rawl,u93.rawl,u94.rawl,u95.rawl,u96.rawl,u97.rawl,u98.rawl,u99.rawl,u100.rawl,u101.rawl,u102.rawl,u103.rawl,u104.rawl,u105.rawl,u106.rawl,u107.rawl,u108.rawl,u109.rawl,u110.rawl,u111.rawl,u112.rawl,u113.rawl,u114.rawl,u115.rawl,u116.rawl,u117.rawl,u118.rawl,u119.rawl,u120.rawl,u121.rawl,u122.rawl,u123.rawl,u124.rawl,u125.rawl,u126.rawl,u127.rawl,u128.rawl,u129.rawl,u130.rawl,u131.rawl,u132.rawl,u133.rawl,u134.rawl,u135.rawl,u136.rawl,u137.rawl,u138.rawl,u139.rawl,u140.rawl,u141.rawl,u142.rawl,u143.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl,v16.rawl,v17.rawl,v18.rawl,v19.rawl,v20.rawl,v21.rawl,v22.rawl,v23.rawl,v24.rawl,v25.rawl,v26.rawl,v27.rawl,v28.rawl,v29.rawl,v30.rawl,v31.rawl,v32.rawl,v33.rawl,v34.rawl,v35.rawl,v36.rawl,v37.rawl,v38.rawl,v39.rawl,v40.rawl,v41.rawl,v42.rawl,v43.rawl,v44.rawl,v45.rawl,v46.rawl,v47.rawl,v48.rawl,v49.rawl,v50.rawl,v51.rawl,v52.rawl,v53.rawl,v54.rawl,v55.rawl,v56.rawl,v57.rawl,v58.rawl,v59.rawl,v60.rawl,v61.rawl,v62.rawl,v63.rawl,v64.rawl,v65.rawl,v66.rawl,v67.rawl,v68.rawl,v69.rawl,v70.rawl,v71.rawl,v72.rawl,v73.rawl,v74.rawl,v75.rawl,v76.rawl,v77.rawl,v78.rawl,v79.rawl,v80.rawl,v81.rawl,v82.rawl,v83.rawl,v84.rawl,v85.rawl,v86.rawl,v87.rawl,v88.rawl,v89.rawl,v90.rawl,v91.rawl,v92.rawl,v93.rawl,v94.rawl,v95.rawl,v96.rawl,v97.rawl,v98.rawl,v99.rawl,v100.rawl,v101.rawl,v102.rawl,v103.rawl,v104.rawl,v105.rawl,v106.rawl,v107.rawl,v108.rawl,v109.rawl,v110.rawl,v111.rawl,v112.rawl,v113.rawl,v114.rawl,v115.rawl,v116.rawl,v117.rawl,v118.rawl,v119.rawl,v120.rawl,v121.rawl,v122.rawl,v123.rawl,v124.rawl,v125.rawl,v126.rawl,v127.rawl,v128.rawl,v129.rawl,v130.rawl,v131.rawl,v132.rawl,v133.rawl,v134.rawl,v135.rawl,v136.rawl,v137.rawl,v138.rawl,v139.rawl,v140.rawl,v141.rawl,v142.rawl,v143.rawl ' ' -raw_components ']); + + + system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,y16.rawl,y17.rawl,y18.rawl,y19.rawl,y20.rawl,y21.rawl,y22.rawl,y23.rawl,y24.rawl,y25.rawl,y26.rawl,y27.rawl,y28.rawl,y29.rawl,y30.rawl,y31.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,u16.rawl,u17.rawl,u18.rawl,u19.rawl,u20.rawl,u21.rawl,u22.rawl,u23.rawl,u24.rawl,u25.rawl,u26.rawl,u27.rawl,u28.rawl,u29.rawl,u30.rawl,u31.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl,v16.rawl,v17.rawl,v18.rawl,v19.rawl,v20.rawl,v21.rawl,v22.rawl,v23.rawl,v24.rawl,v25.rawl,v26.rawl,v27.rawl,v28.rawl,v29.rawl,v30.rawl,v31.rawl ' ' -raw_components ']); + + for k = 0:(GOPsz-1) + fid_name1 = ['y' num2str( k ) '.rawl']; + fid_name2 = ['u' num2str( k ) '.rawl']; + fid_name3 = ['v' num2str( k ) '.rawl']; + + fp = fopen(fid_name1,'rb'); + Y = fread(fp,y_size,'int16'); + fclose(fp); + + fp = fopen(fid_name2,'rb'); + U = fread(fp,c_size,'int16'); + fclose(fp); + + fp = fopen(fid_name3,'rb'); + V = fread(fp,c_size,'int16'); + fclose(fp); + + Y = (Y/16); + U = (U/16); + V = (V/16); + + fwrite(outfid,Y,'float32'); + fwrite(outfid,U,'float32'); + fwrite(outfid,V,'float32'); + end + +end + + +if GOPres ~= 0 + jpx_name = ('tmp_bq_res.j2c'); + system([ ' kdu_expand ' ' -i ' jpx_name ' -o ' ' y0.rawl,y1.rawl,y2.rawl,y3.rawl,y4.rawl,y5.rawl,y6.rawl,y7.rawl,y8.rawl,y9.rawl,y10.rawl,y11.rawl,y12.rawl,y13.rawl,y14.rawl,y15.rawl,u0.rawl,u1.rawl,u2.rawl,u3.rawl,u4.rawl,u5.rawl,u6.rawl,u7.rawl,u8.rawl,u9.rawl,u10.rawl,u11.rawl,u12.rawl,u13.rawl,u14.rawl,u15.rawl,v0.rawl,v1.rawl,v2.rawl,v3.rawl,v4.rawl,v5.rawl,v6.rawl,v7.rawl,v8.rawl,v9.rawl,v10.rawl,v11.rawl,v12.rawl,v13.rawl,v14.rawl,v15.rawl ' ' -raw_components ']); + + for k = 0:(GOPres-1) + fid_name1 = ['y' num2str( k ) '.rawl']; + fid_name2 = ['u' num2str( k ) '.rawl']; + fid_name3 = ['v' num2str( k ) '.rawl']; + + fp = fopen(fid_name1,'rb'); + Y = fread(fp,y_size,'int16'); + fclose(fp); + + fp = fopen(fid_name2,'rb'); + U = fread(fp,c_size,'int16'); + fclose(fp); + + fp = fopen(fid_name3,'rb'); + V = fread(fp,c_size,'int16'); + fclose(fp); + + Y = (Y/16); + U = (U/16); + V = (V/16); + + fwrite(outfid,Y,'float32'); + fwrite(outfid,U,'float32'); + fwrite(outfid,V,'float32'); + end + +end + +fclose(outfid); \ No newline at end of file diff --git a/Interframe EZBC/MATLAB files/YUV2JP2K.m b/Interframe EZBC/MATLAB files/YUV2JP2K.m new file mode 100644 index 0000000..17a5b7e --- /dev/null +++ b/Interframe EZBC/MATLAB files/YUV2JP2K.m @@ -0,0 +1,331 @@ +clear all; +clc; + +fp = fopen('BUS_352x288_30_all_out_jp2k_01.yuv','rb'); + +%mv_bytes = [9822 9940 10274 9675 6304 7814 9016 9263 9308]; + +num_frames = 144; +width = 352; +height = 288; +GOPsz = 32; +GOPnum = (num_frames) / GOPsz; + +frame_rate = 30; + +GOPres = num_frames - GOPsz * floor(GOPnum); + +GOPnum = floor(GOPnum); + +if GOPnum < 1 + GOPnum = 1; + GOPsz = num_frames; +end + +% bitrate = 1300; +% +% total_rate = 1000/8 * bitrate; + +%GOP_budget = total_rate * num_frames / 30; + +y_size = width*height; +c_size = y_size / 4; +f_size = y_size + 2*c_size; +M = fread(fp,f_size*num_frames,'float32'); +fclose(fp); + +coef = sqrt(3/2); +scene_3 = 0.8686; + +% M is a column vector with the y,u,v components stacked +% Next, extract the y, u and v frames into separate files + +y = zeros(y_size*num_frames,1); +u = zeros(c_size*num_frames,1); +v = zeros(c_size*num_frames,1); + +y_count = 0; +u_count = 0; +v_count = 0; + +for f=1:num_frames + y_start = (f-1)*y_size + 1; + c_start = (f-1)*c_size + 1; + f_start = (f-1)*f_size + 1; + y(y_start:y_start+y_size-1) = M(f_start:f_start+y_size-1); + u(c_start:c_start+c_size-1) = M(f_start+y_size:f_start+y_size+c_size-1); + v(c_start:c_start+c_size-1) = M(f_start+y_size+c_size:f_start+y_size+2*c_size-1); + +% if f == 1 || f == 33 +% u(c_start:c_start+c_size-1) = u(c_start:c_start+c_size-1) - 128; +% v(c_start:c_start+c_size-1) = v(c_start:c_start+c_size-1) - 128; +% end + +% if f == 1 +% y_out = y(y_start:y_start+y_size-1); +% u_out = u(c_start:c_start+c_size-1); +% v_out = v(c_start:c_start+c_size-1); +% +% y_out = y_out/coef/coef/coef/scene_3; +% u_out = u_out/coef/coef/coef/scene_3; +% v_out = v_out/coef/coef/coef/scene_3; +% +% y_out_orig = y_out; +% u_out_orig = u_out; +% v_out_orig = v_out; +% +% %Y +% for n = 1 : length(y_out) +% if y_out(n)>255 +% y_out(n) = 255; +% y_count = y_count + 1; +% elseif y_out(n)<0 +% y_out(n) = 0; +% y_count = y_count + 1; +% end +% end +% %U +% for n = 1 : length(u_out) +% if u_out(n)>255 +% u_out(n) = 255; +% u_count = u_count + 1; +% elseif u_out(n)<0 +% u_out(n) = 0; +% u_count = u_count + 1; +% end +% end +% %V +% for n = 1 : length(v_out) +% if v_out(n)>255 +% v_out(n) = 255; +% v_count = v_count + 1; +% elseif v_out(n)<0 +% v_out(n) = 0; +% v_count = v_count + 1; +% end +% end +% +% fwrite(out_fp,y_out,'uint8'); +% fwrite(out_fp,u_out,'uint8'); +% fwrite(out_fp,v_out,'uint8'); +% end + +end + +clear M; + +y0 = (y)*16; +u0 = (u)*16; +v0 = (v)*16; + +clear y; +clear u; +clear v; + +%248076 - 1000 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% fp = fopen('bus_t_y.rawl','wb'); +% fwrite(fp,y0,'int16'); +% fclose(fp); +% +% fp = fopen('bus_t_u.rawl','wb'); +% fwrite(fp,u0,'int16'); +% fclose(fp); +% +% fp = fopen('bus_t_v.rawl','wb'); +% fwrite(fp,v0,'int16'); +% fclose(fp); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +begin = 0; + +% y1 = reshape(y(begin*y_size+1:(begin+1)*y_size),width,height); +% u1 = reshape(u(begin*c_size+1:(begin+1)*c_size),width/2,height/2); +% v1 = reshape(v(begin*c_size+1:(begin+1)*c_size),width/2,height/2); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Finish by writing the frames out + +% for i = 0:(GOPnum-1) +% +% begin = i; +% +% y2 = y0(begin*GOPsz*y_size+1:(begin+1)*GOPsz*y_size); +% u2 = u0(begin*GOPsz*c_size+1:(begin+1)*GOPsz*c_size); +% v2 = v0(begin*GOPsz*c_size+1:(begin+1)*GOPsz*c_size); +% +% y2 = round(y2); +% u2 = round(u2); +% v2 = round(v2); +% +% % Finish by writing the frames out +% +% y_name = ['ter_t1_y' num2str(i) '.rawl' ]; +% +% fp = fopen(y_name,'wb'); +% fwrite(fp,y2,'int16'); +% fclose(fp); +% +% u_name = ['ter_t1_u' num2str(i) '.rawl' ]; +% +% fp = fopen(u_name,'wb'); +% fwrite(fp,u2,'int16'); +% fclose(fp); +% +% v_name = ['ter_t1_v' num2str(i) '.rawl' ]; +% +% fp = fopen(v_name,'wb'); +% fwrite(fp,v2,'int16'); +% fclose(fp); +% +% % total_name = ['tmp_t' num2str(i) '.rawl' ]; +% % +% % fp = fopen(total_name,'wb'); +% % for j = 0:(GOPsz-1) +% % fwrite(fp,y2(j*y_size+1 : j*y_size+y_size),'int16'); +% % fwrite(fp,u2(j*c_size+1 : j*c_size+c_size),'int16'); +% % fwrite(fp,v2(j*c_size+1 : j*c_size+c_size),'int16'); +% % end +% % fclose(fp); +% +% end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% GOPnum = 1; +% GOPsz = 144; +% GOPres = 0; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +for i = 0:(GOPnum-1) + +begin = i; + +y2 = y0(begin*GOPsz*y_size+1:(begin+1)*GOPsz*y_size); +u2 = u0(begin*GOPsz*c_size+1:(begin+1)*GOPsz*c_size); +v2 = v0(begin*GOPsz*c_size+1:(begin+1)*GOPsz*c_size); + +y2 = round(y2); +u2 = round(u2); +v2 = round(v2); + +% Finish by writing the frames out + +y_name = ['bq_t1_y' num2str(i) '.rawl' ]; + +fp = fopen(y_name,'wb'); +fwrite(fp,y2,'int16'); +fclose(fp); + +u_name = ['bq_t1_u' num2str(i) '.rawl' ]; + +fp = fopen(u_name,'wb'); +fwrite(fp,u2,'int16'); +fclose(fp); + +v_name = ['bq_t1_v' num2str(i) '.rawl' ]; + +fp = fopen(v_name,'wb'); +fwrite(fp,v2,'int16'); +fclose(fp); + +end + +if GOPres ~= 0 + begin = GOPnum; + + y2 = y0(begin*GOPsz*y_size+1:(begin*GOPsz+GOPres)*y_size); + u2 = u0(begin*GOPsz*c_size+1:(begin*GOPsz+GOPres)*c_size); + v2 = v0(begin*GOPsz*c_size+1:(begin*GOPsz+GOPres)*c_size); + + y2 = round(y2); + u2 = round(u2); + v2 = round(v2); + + % Finish by writing the frames out + + y_name = ('bq_t1_y_res.rawl'); + + fp = fopen(y_name,'wb'); + fwrite(fp,y2,'int16'); + fclose(fp); + + u_name = ('bq_t1_u_res.rawl'); + + fp = fopen(u_name,'wb'); + fwrite(fp,u2,'int16'); + fclose(fp); + + v_name = ('bq_t1_v_res.rawl'); + + fp = fopen(v_name,'wb'); + fwrite(fp,v2,'int16'); + fclose(fp); +end + + +% sub_rate = 41474; +% +% +% rate_str = num2str(sub_rate); + +%Bus +% -slope 40900,40960,41013,41038,41060,41096,41213,41279,41358,41495,41564 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +for i = 0:(GOPnum-1) + y_name = ['bq_t1_y' num2str(i) '.rawl' ]; + u_name = ['bq_t1_u' num2str(i) '.rawl' ]; + v_name = ['bq_t1_v' num2str(i) '.rawl' ]; + +% total_name = ['tmp_t' num2str(i) '.rawl' ]; + out_name = ['tmp_bq' num2str(i) '.j2c']; + + +% system([' kdu_compress ' ' -i ' y_name '*16@4147200,' u_name '*16@1036800,' v_name '*16@1036800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' "Sdims={1080,1920},{1080,1920},{1080,1920},{1080,1920},{540,960}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=2 Clevels:C0=5 Clevels:C4=5 Clevels:C8=5 ' ' -rate ' rate_str]); + % 41500,41624,41668,41704,41755,41811,41863,41908,41970,42062,42125,42230,42400,42600 +% system([' kdu_compress ' ' -i ' y_name '*16@4147200,' u_name '*16@1036800,' v_name '*16@1036800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0001 Qstep:C16=0.0001 Qstep:C32=0.0001 ' ' "Sdims={1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{540,960}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 Clevels:C32=5 ' ' -slope 41908 ' ]);41050,41152,41260, + +% system([' kdu_compress ' ' -i ' y_name '*32@4147200,' u_name '*32@1036800,' v_name '*32@1036800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.0001 Qstep:C0=0.0001 Qstep:C32=0.0001 Qstep:C64=0.0001 ' ' "Sdims={1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{540,960}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=6 ' ' -slope 40825 ' ]);%40980,41050,41152,41260,41342,41420,41500,41582,41660,41842,41970 + +% system([' kdu_compress ' ' -i ' y_name '*32@1843200,' u_name '*32@460800,' v_name '*32@460800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.0001 Qstep:C0=0.0001 Qstep:C32=0.0001 Qstep:C64=0.0001 ' ' "Sdims={720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{360,640}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=6 ' ' -slope 41500 ' ]);%41600,41750,41900,41950,42000,42110,42230,42350,42460,42560,42670 + + +% -slope 41816,42144,42254,42364,42474 +% system([' kdu_compress ' ' -i ' y_name '*16@202752,' u_name '*16@50688,' v_name '*16@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0003 Qstep:C16=0.0003 Qstep:C32=0.0003 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 ' ' -slope 40000,41800,42100,42300,42500 ' ]); +% system([' kdu_compress ' ' -i ' y_name '*16@202752,' u_name '*16@50688,' v_name '*16@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0003 Qstep:C16=0.0003 Qstep:C32=0.0003 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 ' ' -rate 7,5.8,5,4.2,3.7 ' ]); +% system([' kdu_compress ' ' -i ' y_name '*96@202752,' u_name '*96@50688,' v_name '*96@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0003 Qstep:C1=0.0003 Qstep:C2=0.0003 Qstep:C3=0.0003 Qstep:C4=0.0003 Qstep:C5=0.0003 Qstep:C96=0.0003 Qstep:C97=0.0003 Qstep:C98=0.0003 Qstep:C99=0.0003 Qstep:C100=0.0003 Qstep:C101=0.0003 Qstep:C192=0.0003 Qstep:C193=0.0003 Qstep:C194=0.0003 Qstep:C195=0.0003 Qstep:C196=0.0003 Qstep:C197=0.0003 ' ' Ssize={288,704} "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C1=5 Clevels:C2=5 Clevels:C3=5 Clevels:C4=5 Clevels:C5=5 Clevels:C96=5 Clevels:C97=5 Clevels:C98=5 Clevels:C99=5 Clevels:C100=5 Clevels:C101=5 Clevels:C192=5 Clevels:C193=5 Clevels:C194=5 Clevels:C195=5 Clevels:C196=5 Clevels:C197=5 ' ' -slope 41200,41711,41742,41773,41825,41894,41977,42014,42160,42210,42270 ' ]); +% system([' kdu_compress ' ' -i ' y_name '*64@202752,' u_name '*64@50688,' v_name '*64@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.001 Qstep:C0=0.0003 Qstep:C32=0.0003 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=5 Clevels:C96=5 Clevels:C128=5 Clevels:C160=5 ' ' -slope 41471,41900,42200,42300 ' ]); +% Qstep:C96=0.0003 Qstep:C112=0.0003 Qstep:C128=0.0003 Qstep:C144=0.0003 Qstep:C160=0.0003 Qstep:C176=0.0003 Qstep:C192=0.0003 Qstep:C208=0.0003 Qstep:C224=0.0003 Qstep:C240=0.0003 Qstep:C256=0.0003 Qstep:C272=0.0003 +% system([' kdu_compress ' ' -i ' y_name '*96@202752,' u_name '*96@50688,' v_name '*96@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.001 Qstep:C0=0.0003 Qstep:C32=0.0003 Qstep:C64=0.0003 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=6 Clevels:C96=5 Clevels:C128=5 Clevels:C160=5 Clevels:C192=5 Clevels:C224=5 Clevels:C256=5 ' ' -slope 41372,42170,42280,42390,42400 ' ]); + +% system([' kdu_compress ' ' -i ' total_name '*96@304128,' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0003 Qstep:C16=0.0003 Qstep:C32=0.0003 Qstep:C48=0.0003 Qstep:C64=0.0003 Qstep:C80=0.0003 ' ' "Sdims={432,352}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 Clevels:C32=5 Clevels:C48=5 Clevels:C64=5 Clevels:C80=5 ' ' -slope 41987 ' ]); + +% system([' kdu_compress ' ' -i ' y_name '*144@202752,' u_name '*144@50688,' v_name '*144@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.0005 Qstep:C0=0.0001 Qstep:C32=0.0001 Qstep:C64=0.0001 Qstep:C96=0.0001 Qstep:C128=0.0001 Qstep:C160=0.0001 Qstep:C192=0.0001 Qstep:C224=0.0001 Qstep:C256=0.0001 Qstep:C288=0.0001 Qstep:C320=0.0001 Qstep:C352=0.0001 Qstep:C384=0.0001 Qstep:C400=0.0001 Qstep:C416=0.0001 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=6 Clevels:C96=6 Clevels:C128=6 Clevels:C160=6 Clevels:C192=6 Clevels:C224=6 Clevels:C256=6 Clevels:C288=6 Clevels:C320=6 Clevels:C352=6 Clevels:C384=5 Clevels:C400=5 Clevels:C416=5 ' ' -slope 40900,40960,41013,41038,41060,41096,41213,41279,41358,41495,41564 ' ]); + +% system([' kdu_compress ' ' -i ' y_name '*240@202752,' u_name '*240@50688,' v_name '*240@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.0005 Qstep:C0=0.0001 Qstep:C32=0.0001 Qstep:C64=0.0001 Qstep:C96=0.0001 Qstep:C128=0.0001 Qstep:C160=0.0001 Qstep:C192=0.0001 Qstep:C224=0.0001 Qstep:C256=0.0001 Qstep:C288=0.0001 Qstep:C320=0.0001 Qstep:C352=0.0001 Qstep:C384=0.0001 Qstep:C416=0.0001 Qstep:C448=0.0001 Qstep:C480=0.0001 Qstep:C512=0.0001 Qstep:C544=0.0001 Qstep:C576=0.0001 Qstep:C608=0.0001 Qstep:C640=0.0001 Qstep:C656=0.0001 Qstep:C672=0.0001 Qstep:C688=0.0001 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=6 Clevels:C96=6 Clevels:C128=6 Clevels:C160=6 Clevels:C192=6 Clevels:C224=6 Clevels:C256=6 Clevels:C288=6 Clevels:C320=6 Clevels:C352=6 Clevels:C384=6 Clevels:C416=6 Clevels:C448=6 Clevels:C480=6 Clevels:C512=6 Clevels:C544=6 Clevels:C576=6 Clevels:C608=6 Clevels:C640=6 Clevels:C656=5 Clevels:C672=5 Clevels:C688=5 ' ' -slope 42000 ' ]); + + system([' kdu_compress ' ' -i ' y_name '*32@202752,' u_name '*32@50688,' v_name '*32@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.0005 Qstep:C0=0.00005 Qstep:C32=0.00005 Qstep:C64=0.00005 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C32=6 Clevels:C64=6 ' ' -slope 41420,41500,41582,41660,41842,41970 ' ]); %41050,41152,41260,41342, +% % 40992,41013,41042,41094,41196,41262,41448,41527,41647,41856 for tempete + % 41071,41125,41239,41296,41363,41469,41532,41571,41684 for flower + + +% system([' kdu_compress ' ' -i ' y_name '*32@798720,' u_name '*32@199680,' v_name '*32@199680 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.00001 Qstep:C0=0.000001 Qstep:C1=0.000001 Qstep:C2=0.000001 Qstep:C3=0.000001 Qstep:C4=0.000001 Qstep:C5=0.000001 Qstep:C6=0.000001 Qstep:C7=0.000001 Qstep:C8=0.000001 Qstep:C9=0.000001 Qstep:C10=0.000001 Qstep:C11=0.000001 Qstep:C12=0.000001 Qstep:C13=0.000001 Qstep:C14=0.000001 Qstep:C15=0.000001 Qstep:C16=0.000001 Qstep:C17=0.000001 Qstep:C18=0.000001 Qstep:C19=0.000001 Qstep:C20=0.000001 Qstep:C21=0.000001 Qstep:C22=0.000001 Qstep:C23=0.000001 Qstep:C24=0.000001 Qstep:C25=0.000001 Qstep:C26=0.000001 Qstep:C27=0.000001 Qstep:C28=0.000001 Qstep:C29=0.000001 Qstep:C30=0.000001 Qstep:C31=0.000001 ' ' "Sdims={480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{480,832},{240,416}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=6 Clevels:C1=3 Clevels:C32=5 Clevels:C64=5 ' ' -slope 41288,41551,41750,42087,42797 ' ]); + % 41236,41280,41395,41524,41663,41834,42063,42457 % 41288,41422,41551,41686,41817,41980,42087,42256,42505,42797 +% system([' kdu_compress ' ' -i ' y_name '*32@691200,' u_name '*32@172800,' v_name '*32@172800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.00001 Qstep:C0=0.00001 Qstep:C1=0.00001 Qstep:C2=0.00001 Qstep:C3=0.00001 Qstep:C32=0.001 Qstep:C33=0.001 Qstep:C34=0.001 Qstep:C35=0.001 Qstep:C64=0.001 Qstep:C65=0.001 Qstep:C66=0.001 Qstep:C67=0.001 ' ' "Sdims={480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{480,720},{240,360}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C1=3 Clevels:C2=3 Clevels:C3=3 Clevels:C4=1 Clevels:C5=1 Clevels:C6=1 Clevels:C7=1 Clevels:C32=5 Clevels:C33=1 Clevels:C64=5 Clevels:C65=1 ' ' -slope 41441 ' ]); +end % 41415,41481,41559,41607,41662,41778,41875 + +if GOPres ~= 0 + y_name = ('bq_t1_y_res.rawl'); + u_name = ('bq_t1_u_res.rawl'); + v_name = ('bq_t1_v_res.rawl'); + %,41220,41275,41346,41483,41559,41650 + %,41056,41275,41346,41483,41559 + out_name = ('tmp_bq_res.j2c'); + + system([' kdu_compress ' ' -i ' y_name '*16@202752,' u_name '*16@50688,' v_name '*16@50688 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep=0.0005 Qstep:C0=0.00005 Qstep:C16=0.00005 Qstep:C32=0.00005 ' ' "Sdims={288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{288,352},{144,176}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 Clevels:C32=5 ' ' -slope 41420,41500,41582,41660,41842,41970 ' ]); %41050,41152,41260,41342, +% 41500,41624,41668,41704,41755,41811,41863,41908,41970,42062,42125,42230,42400,42600 +% %41050,41152,41260,41342,41420,41500,41582,41660,41842,41970 + +% system([' kdu_compress ' ' -i ' y_name '*16@4147200,' u_name '*16@1036800,' v_name '*16@1036800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0001 Qstep:C16=0.0001 Qstep:C32=0.0001 ' ' "Sdims={1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{1080,1920},{540,960}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 Clevels:C32=5 ' ' -slope 40825 ' ]);%40980,41050,41152,41260,41342,41420,41500,41582,41660,41842,41970 + +% system([' kdu_compress ' ' -i ' y_name '*16@1843200,' u_name '*16@460800,' v_name '*16@460800 ' ' -o ' out_name ' Nprecision=16 ' ' Nsigned=yes ' ' Qstep:C0=0.0001 Qstep:C16=0.0001 Qstep:C32=0.0001 ' ' "Sdims={720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{720,1280},{360,640}" ' ' Cycc=no ' ' -no_weights ' ' Clevels=1 Clevels:C0=5 Clevels:C16=5 Clevels:C32=5 ' ' -slope 41500 ' ]);% 41600,41750,41900,41950,42000,42110,42230,42350,42460,42560,42670 +end diff --git a/Interframe EZBC/TempSub/inc/Choisubband.h b/Interframe EZBC/TempSub/inc/Choisubband.h new file mode 100644 index 0000000..d5296bc --- /dev/null +++ b/Interframe EZBC/TempSub/inc/Choisubband.h @@ -0,0 +1,5 @@ +void analysis( float *in, int sx, int sy, int lenx, int leny, int hor, + int ver, int filterType ); +void synthesis( float *in, int sx, int sy, int lenx, int leny, int hor, + int ver, int filterType ); +int filter_coeff( float **lpf, float **hpf, int FILTER_TYPE, int analsyn ); diff --git a/Interframe EZBC/TempSub/inc/analsyn.h b/Interframe EZBC/TempSub/inc/analsyn.h new file mode 100644 index 0000000..a5b9d7b --- /dev/null +++ b/Interframe EZBC/TempSub/inc/analsyn.h @@ -0,0 +1,103 @@ +#define USED 1 +#define UNUSED 0 +#define ANAL 0 +#define SYN 1 +#define PRUNE 1 /* overlapped block matching */ +#define Global 0 +#define Local 1 +#define UN 0 +#define CT 1 /* central */ +#define HO 2 /* horizontal */ +#define VE 3 /* vertical */ +#define DI 4 /* diagonal */ +#define Bi 5 /* Bi-direction or intra mode */ +#define ER 6 /* error */ +#define orign 0 + +long int denoise_mctf_anal_ezbc( int curr, int GOP_counter,videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs ); +long int mctf_anal_ezbc( int curr, int GOP_counter, videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs, long int *sum_mv, int simul_enc, float *upframe1, float *upframe2, float *upsamp_x); + +void save_enc_status(videoinfo *info); + +void resume_enc_status(videoinfo *info); + +void denoise_mctf_syn_ezbc( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info, enum FLAG first_GOP, + enum FLAG Level_change, int remaining_frs ); +void mctf_syn_ezbc( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info, enum FLAG first_GOP, + enum FLAG Level_change, int remaining_frs, int simul_dec, int theo_dec ); + +long int intra_encode( int curr, int GOP_counter, videoinfo info ); +void intra_decode( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info ); + +long int three_D_anal( int curr, int GOP_counter, videoinfo info ); +void three_D_syn( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info ); + +long int mc_anal( int curr, int GOP_counter, videoinfo info, enum FLAG first_GOP, + enum FLAG Level_change, int remaining_frs, int simul_enc, float *upframe1, float *upframe2, float *upsamp_x ); +void mc_syn( int curr, long int *total_bytes_past, videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, int remaining_frs, int simul_dec, int theo_dec ); + +void mc_analysis( float *L1, float *H1, float *H0, float *fr1, float *fr2, float *fr3, + float *mvx1, float *mvy1, float *mvx2, float *mvy2, float *mvx3, float *mvy3, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + float *mvx3_int, float *mvy3_int, vector_ptr mv_ref1, vector_ptr mv_ref2, + vector_ptr mv_ref3, int hor, int ver, int level, int remaining_frs, + videoinfo info ); + +void get_value_for_neighbor_mv(int cpos, int pos, ImageMEinfo *imagemeinfo, float *fr1, float *fr3, + float *neighbor_value, float *self_weight, float neighbor_weight, + int cx, int cy, videoinfo info, int hor, int ver, + int UVcom, int t_level); + + +// by Yongjun Wu MCTF analysis with OBMC +void +mc_analysis_with_OBMC( float *L1, float *H1, float *H0, float *fr1, float *fr2, float *fr3, + float *mvx1, float *mvy1, float *mvx2, float *mvy2, float *mvx3, float *mvy3, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + float *mvx3_int, float *mvy3_int, vector_ptr mv_ref1, vector_ptr mv_ref2, + vector_ptr mv_ref3, int hor, int ver, int level, int remaining_frs, + videoinfo info, ImageMEinfo *imagemeinfo, Varblkarrayinfo *varblkarray, int UVcom, + enum FLAG left_scene, enum FLAG right_scene, int type); + + +void mc_synthesis( float *fr0, float *fr1, float *H0, float *L1, float *H1, float *frp, + float *mvx0, float *mvy0, float *mvx1, float *mvy1, + float *mvx2, float *mvy2, float *mvx0_int, float *mvy0_int, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + vector_ptr mv_ref0, vector_ptr mv_ref1, vector_ptr mv_ref2, + int hor, int ver, int level, videoinfo info ); + +void +mc_synthesis_with_OBMC( float *fr0, float *fr1, float *H0, float *L1, float *H1, float *frp, + float *mvx0, float *mvy0, float *mvx1, float *mvy1, + float *mvx2, float *mvy2, float *mvx0_int, float *mvy0_int, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + vector_ptr mv_ref0, vector_ptr mv_ref1, vector_ptr mv_ref2, + int hor, int ver, int level, videoinfo info, + ImageMEinfo *imagemeinfo, Varblkarrayinfo *varblkarray, int UVcom, int type ); + + +void spatial_anal( float *full, int hor, int ver, float *ll, float *lh, + float *hl, float *hh, int filterType ); +void spatial_syn( float *full, int hor, int ver, float *ll, float *lh, + float *hl, float *hh, int filterType ); + +void spatial_anal_frame( YUVimage_ptr fr, videoinfo info, YUVimage_ptr low, + YUVimage_ptr high0, YUVimage_ptr high1, + YUVimage_ptr high2, int filterType ); +void spatial_syn_frame( YUVimage_ptr fr, videoinfo info, YUVimage_ptr low, + YUVimage_ptr high0, YUVimage_ptr high1, + YUVimage_ptr high2, int filterType ); + +void +synscheme3( int curr, videoinfo info, enum FLAG first_GOP, + enum FLAG Level_change, int remaining_frs, int simul_dec, int theo_dec ); diff --git a/Interframe EZBC/TempSub/inc/arcode.h b/Interframe EZBC/TempSub/inc/arcode.h new file mode 100644 index 0000000..62ebbcb --- /dev/null +++ b/Interframe EZBC/TempSub/inc/arcode.h @@ -0,0 +1,32 @@ +#ifndef ARCODE_H +#define ARCODE_H + +#include "structN.h" + +#define Top_value 65535 /* largest code value */ +#define Max_frequency 16383 /* largest frequency count */ +#define First_qtr Top_value/4+1 +#define Half 2*First_qtr +#define Third_qtr 3*First_qtr + +EXTERN int low, high, value, **freq, **cmf, **int2sym, **sym2int; +EXTERN int bits_to_follow; + +EXTERN int aff_low, aff_high, aff_value, **aff_freq, **aff_cmf, **aff_int2sym, **aff_sym2int; +EXTERN int aff_bits_to_follow; + +void encode_symbol(int symbol, int context = 0); +void ardecode_init(int symbols, int contexts = 1, + const int **freq_init = NULL); +void ardecode_end(); +void arencode_init(int symbols, int contexts = 1, + const int **freq_init = NULL); +void arencode_end(int context = 0); +int decode_symbol(int context = 0); + +void encode_word(int word, int context = 0); +int decode_word(int context = 0); +void update_model(int word, int context = 0); +float get_expected_length(int word, int context = 0); + +#endif // ARCODE_H diff --git a/Interframe EZBC/TempSub/inc/basic.h b/Interframe EZBC/TempSub/inc/basic.h new file mode 100644 index 0000000..b4fc050 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/basic.h @@ -0,0 +1,45 @@ +#ifndef __BASICH__ +#define __BASICH__ + +#include + +#define U8 unsigned char /* unsigned 8 bit integer (FF hex) */ +#define U16 unsigned short int /* unsigned 16 bit integer (FFFF hex) */ +#define U32 unsigned int /* unsigned 32 bit integer (FFFFFFFF hex) */ +#define S32 signed int /* signed 32 bit integer (80000000 hex) */ +#define R32 float /*32 bit real number (7F800000 hex (+ infinity)) */ +#define ASCII char /*(NULL 00 hex) */ + +typedef unsigned char CharImg; +typedef int IntImg; + +#define MY_SQUARE(A) (A)*(A) +#define MY_SQUARE_NORM(A,B) (MY_SQUARE(A)) + (MY_SQUARE(B)) +#define MY_ABS(A) (((A) < 0) ? ((-1)*(A)) : (A)) +#define MY_ABS_DIFF(A,B) (MY_ABS((A) - (B))) +#define MY_MAX(A,B) ((A) > (B) ? (A) : (B)) +#define MY_MIN(A,B) ((A) > (B) ? (B) : (A)) +#define MY_SIGN(A) ((A) < 0 ? -1 : 1) +#define MY_DELTA(A,B) (((A) == (B)) ? (1) : (0)) +#define nint(a) (((a)<0) ? ((int)(a - 0.5)) : ((int)(a + 0.5))) // 远零取整 + +int scanargs( int argc, char *argv[], char *format, ... ); +struct rasterfile *read_charimg( char *name, unsigned char **img ); +struct rasterfile *read_floatimg( char *name, float **img ); +char *getarray( int num, int siz, char *name ); +void write_charimg( char *name, struct rasterfile *rhead, + unsigned char *data ); +void write_floatimg1( char *name, struct rasterfile *rhead, float *data ); +void write_floatimg4( char *name, struct rasterfile *rhead, float *data ); +void cnv_data_1_4( unsigned char *y, float *x, int n ); +void cnv_data_4_1( float *y, unsigned char *x, int n ); +void cnv_data_1_2( unsigned char *y, int *x, int n ); +void cnv_data_2_1( int *y, unsigned char *x, int n ); +float **getmatrix( int nrl, int nrh, int ncl, int nch ); +void freematrix( float **m, int nrl, int nrh, int ncl, int nch ); +void write_intimg1( char *name, struct rasterfile *rhead, int *data ); +struct rasterfile *read_intimg( char *name, int **img ); +void writeFloatImg1( char *name, struct rasterfile *rhead, float *data ); +/* Std ANSI prototypes (missing in SunOS include files) */ + +#endif diff --git a/Interframe EZBC/TempSub/inc/binarcode.h b/Interframe EZBC/TempSub/inc/binarcode.h new file mode 100644 index 0000000..cf81a5e --- /dev/null +++ b/Interframe EZBC/TempSub/inc/binarcode.h @@ -0,0 +1,18 @@ +#ifndef BINARCODE_H +#define BINARCODE_H + +#include "structN.h" + +void binar_enc_init(int contexts, const int numSepBins, + const int *multiContexts, const int **freq_init = NULL); +void binar_enc_end(int context = 0); +void binar_dec_init(int contexts, const int numSepBins, + const int *multiContexts, const int **freq_init = NULL); +void binar_dec_end(); + +void binar_encode_word(int word, int context); +int binar_decode_word(int context); +void binar_update_model(int word, int context); +float binar_get_expected_length(int word, int context); + +#endif // BINARCODE_H diff --git a/Interframe EZBC/TempSub/inc/bmeN.h b/Interframe EZBC/TempSub/inc/bmeN.h new file mode 100644 index 0000000..095596f --- /dev/null +++ b/Interframe EZBC/TempSub/inc/bmeN.h @@ -0,0 +1,94 @@ +#ifndef BME_H +#define BME_H + +#define NOISE_VAR 3.0 + +#define FIR88 88 +#define BILINEAR 22 +#ifdef use_BILINEAR_type +#define TYPE BILINEAR // BILINEAR +#else +#define TYPE FIR88 // BILINEAR +#endif + +#define AFF_TYPE BILINEAR + + +void block_matching( vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, vector_ptr fmv4, + YUVimage *fr_cur, YUVimage *fr_ref1, YUVimage *fr_ref2, + enum FLAG *sc1, enum FLAG *sc2, + videoinfo info, int level, int dist, int subpel, float *upframe1, float *upframe2, float *upsamp_x ); +void position( int *px, int *py, float pfx, float pfy, float mvx, float mvy, + int hor, int ver ); +int inbound( float x, float y, int hor, int ver ); +void blockmv2pixelmv( vector_ptr fmv, float **ymvx, float **ymvy, + float **cmvx, float **cmvy, enum LiftingMode block_mode, + videoinfo info, int t_level ); + +void get_cvector( float *cmvx, float *cmvy, float *ymvx, float *ymvy, + int yhor, int yver, int chor, int cver, videoinfo info, int t_level ); + +void full_search_fast( float *mvx1, float *mvy1, + float *frame_cur, float *frame_ref1, float *frame_ref2, + float *upframe1, float *upframe2, + float mvx2, float mvy2, + int cx, int cy, int xblock, int yblock, + int maxx, int maxy, int hor, int ver, int half, + float lambda, float pmvx, float pmvy, + int ctx_x, int ctx_y, + float *sad_cost, float *bit_cost, float *total_cost, + int do_parallel); // add parallel mode. mwi + +/* int overlap_size( int x ); */ +float MCP_Error( float *frame1, int m, float *frame0, int n, int oxblk, + int oyblk, int hor, float *first_pred, int k, int xblk_max ); +float MCP_Error2(float *frame1, int m, float *frame0, int n, int oxblk, + int oyblk, int hor, float *first_pred, float min_cost, + float *frame2, int n2); // add parallel mode. mwi +float Subpel_MCP_Error( float *frame1, int m, float *frame0, float px, + float hx, float py, float hy, int xblk, int yblk, + int hor, int ver, + float *first_pred, int k, int xblk_max, + float *frame2, float ppx, float ppy); // add parallel mode. mwi +float Subpel_MCP_Error2( float *frame1, int m, float *upframe, int px, int hx, + int py, int hy, int xblk, int yblk, int hor, int ver, + int uphor, int upver, int step, + float *first_pred, int k, int xblk_max ); +float Subpel_MCP_Error3( float *frame1, int m, float *upframe, int px, int py, + int xblk, int yblk, int hor, int ver, + int uphor, int upver, int step, float *first_pred, + float min_cost, + float *upframe2, int ppx, int ppy); +float Subpel_MCP_Error4( float *frame_cur, + int cx, int cy, int xblock, int yblock, + float *frame_ref1, float *upframe_ref1, + float mvx1, float mvy1, + float *frame_ref2, float *upframe_ref2, + float mvx2, float mvy2, + int hor, int ver, int subpel ); +void generate_child( vector_ptr fmv, float *mvx, float *mvy, float *mad ); + +void find_MSE( vector_ptr fmv1, vector_ptr fmv2, + float *frame_cur, float *frame_ref1, float *frame_ref2, + int cx, int cy, int xblock, int yblock, int hor, int ver, + int t_level ); + +void initialize_spiral_search(int search_range); +void clean_up_spiral_search(int search_range); + +float getFrameSATD(float *fr, int hor, int ver); + +void find_diff( vector_ptr fmv, float *frame1, float *frame2, float *D, + int cx, int cy, int xblock, int yblock, int hor, int ver, + int t_level, int type); + +float local_diff_search( float *mvx, float *mvy, float *D1, float *D2, int *Dx, + int xblk, int yblk, int hor, int ver, int t_level ); + +float get_sad( float mvx, float mvy, float *D1, float *D2, int *Dx, + int xblk, int yblk, int t_level, int type ); + +int two_comp_est( float *mvx, float *mvy, vector_ptr fmv, float *frame_cur, float *frame_ref1, float *frame_ref2, float *SAD, + int cx, int cy, int xblk, int yblk, int hor, int ver, int t_level ); + +#endif // BME_H diff --git a/Interframe EZBC/TempSub/inc/bme_tools.h b/Interframe EZBC/TempSub/inc/bme_tools.h new file mode 100644 index 0000000..9bdc693 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/bme_tools.h @@ -0,0 +1,26 @@ +#ifndef BME_TOOLS_H +#define BME_TOOLS_H + +#include "structN.h" + +void get_dmv(float *dmvx, float *dmvy, enum FLAG *is_predictor, + vector_ptr fmv, int x_dst, int y_dst, videoinfo info, int t_level, int blk_thresh); + +void get_predictor(float *pmvx, float *pmvy, enum FLAG *is_predictor, + vector_ptr fmv, int x_dest, int y_dest, videoinfo info, int t_level, + enum BiMode *block_mode, int *propagate_iblk, int blk_thresh); + // by Yongjun Wu: get the block mode + +void clear_predictors(vector_ptr fmv, videoinfo info, int t_level); + +float get_bit_cost(float lambda, float mvx, float mvy, float pmvx, float pmvy, + int ctx_x, int ctx_y, int subpel); + +void get_median_predictor(float *pmvx, float *pmvy, vector_ptr fmv, vector_ptr prev_fmv, + vector_ptr prev_fmv2, int x_pos, int y_pos, int xblock, int yblock, + videoinfo info, int t_level, int blk_thresh); + +//Added by Yuan Liu +int enc_trans_info(int aff_idx); + +#endif diff --git a/Interframe EZBC/TempSub/inc/chrom.h b/Interframe EZBC/TempSub/inc/chrom.h new file mode 100644 index 0000000..7706ce4 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/chrom.h @@ -0,0 +1,7 @@ +void f420_444( videoinfo info, YUVimage * frame ); +void f444_420( videoinfo info, YUVimage * frame ); + +void f444_422( videoinfo info, YUVimage * frame ); +void f422_444( videoinfo info, YUVimage * frame ); +void YUV2RGB( float Y, float U, float V, float *R, float *G, float *B ); +void RGB2YUV( float R, float G, float B, float *Y, float *U, float *V ); diff --git a/Interframe EZBC/TempSub/inc/coderN.h b/Interframe EZBC/TempSub/inc/coderN.h new file mode 100644 index 0000000..8ba9c96 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/coderN.h @@ -0,0 +1,158 @@ +#pragma once + +#ifndef CODERN_H +#define CODERN_H + +#define ADAPT_LEVEL 5 + +EXTERN YUVimage end_of_lastGOP; +//Added on 02.03.2018 +EXTERN YUVimage buff_end_of_lastGOP; + +EXTERN FILE *fpbit; +EXTERN Rate FrsRate; + +EXTERN vector_ptr tmp_yfmv; +EXTERN vector_ptr *yfmv; /* motion vector */ +EXTERN vector_ptr *yfmv_bigGOP; /* only help for different GOP */ +EXTERN vector_ptr *mv_ref; /* arrays of MV references */ +EXTERN vector_ptr *mv_ref_bigGOP; + +//Added on 02.03.2018 +EXTERN vector_ptr buff_tmp_yfmv; +EXTERN vector_ptr *buff_yfmv; /* motion vector */ +EXTERN vector_ptr *buff_yfmv_bigGOP; /* only help for different GOP */ +EXTERN vector_ptr *buff_mv_ref; /* arrays of MV references */ +EXTERN vector_ptr *buff_mv_ref_bigGOP; + +EXTERN vector_ptr *dec_yfmv; /* motion vector */ +EXTERN vector_ptr *dec_yfmv_bigGOP; /* only help for different GOP */ +EXTERN vector_ptr *dec_mv_ref_bigGOP; + +//Added on 02.03.2018 +EXTERN vector_ptr *buff_dec_yfmv; /* motion vector */ +EXTERN vector_ptr *buff_dec_yfmv_bigGOP; /* only help for different GOP */ +EXTERN vector_ptr *buff_dec_mv_ref_bigGOP; + +EXTERN YUVimage_ptr pyrFrs; /* frames after temporal decomposition */ +EXTERN YUVimage_ptr pyrFrs_bigGOP; /* only help for different GOP */ +EXTERN YUVimage_ptr pyrFrs_first; /* first L-Frame by decoding */ + +//Added on 02.03.2018 +EXTERN YUVimage_ptr buff_pyrFrs; /* frames after temporal decomposition */ +EXTERN YUVimage_ptr buff_pyrFrs_bigGOP; /* only help for different GOP */ +EXTERN YUVimage_ptr buff_pyrFrs_first; /* first L-Frame by decoding */ + +EXTERN YUVimage_ptr dec_pyrFrs; /* frames after temporal decomposition 解码端的Frs*/ +EXTERN YUVimage_ptr dec_pyrFrs_bigGOP; /* only help for different GOP */ +EXTERN YUVimage_ptr dec_pyrFrs_first; /* first L-Frame by decoding */ + +//Added on 02.03.2018 +EXTERN YUVimage_ptr buff_dec_pyrFrs; /* frames after temporal decomposition */ +EXTERN YUVimage_ptr buff_dec_pyrFrs_bigGOP; /* only help for different GOP */ +EXTERN YUVimage_ptr buff_dec_pyrFrs_first; /* first L-Frame by decoding */ + +EXTERN enum FLAG **scene_change; // 第一维表示时域分解的第几层, 第二维表示一层时域分解内部的每个帧 +//Added on 02.03.2018 +EXTERN enum FLAG **buff_scene_change; + +EXTERN enum FLAG **simul_scene_change; + +EXTERN enum FLAG scene_change_help; +//Added on 02.03.2018 +EXTERN enum FLAG buff_scene_change_help; + +EXTERN enum FLAG **dec_scene_change; +//Added on 02.03.2018 +EXTERN enum FLAG **buff_dec_scene_change; + +EXTERN YUVimage_ptr *pyrTemp; /* temporary memory for temporally filtering */ +//Added on 02.03.2018 +EXTERN YUVimage_ptr *buff_pyrTemp; /* temporary memory for temporally filtering */ + +EXTERN YUVimage_ptr Four_GOP, Four_bigGOP; /* only used if info.denoise_flag == YES */ +EXTERN YUVimage_ptr spatial_high[3]; /* only used if info.denoise_flag == YES */ + +EXTERN YUVimage_ptr *dec_pyrTemp; +//Added on 02.03.2018 +EXTERN YUVimage_ptr *buff_dec_pyrTemp; + +EXTERN float HPW1[3], HPW2[3], HPW3[3], HPW4[3], /* filter for temporal decomposition */ // 依次为双向滤波系数、前向、后向、 + HPW1_pred[3], HPW2_pred[3], HPW3_pred[3], HPW4_pred[3], + LPW1[3], LPW2[3], LPW3[3], LPW4[3]; // 后面四个是低频帧的系数,共四种模式,双向、前向、后向、帧内 + +EXTERN float FIR14[FIR_LEN], FIR12[FIR_LEN], FIR34[FIR_LEN], FIR18[FIR_LEN], FIR38[FIR_LEN], FIR58[FIR_LEN], + FIR78[FIR_LEN], FIR1hex[FIR_LEN], FIR3hex[FIR_LEN], FIR5hex[FIR_LEN], FIR7hex[FIR_LEN], FIR9hex[FIR_LEN], + FIR11hex[FIR_LEN], FIR13hex[FIR_LEN], FIR15hex[FIR_LEN]; + +/* Check */ +EXTERN float **frY; /*pointer for coding */ + +EXTERN float **frU; +EXTERN float **frV; + +EXTERN int connected, unreferred, pre_connected, multi_connected, + next_connected, case4; +EXTERN long int totalY[5], totalU[5], totalV[5], totalmap[5], totalMV[5]; +EXTERN float avgpsnr[3][16]; /* avgpsnr[y,u,v][frames in several levels] averaged psnr over all GOPS */ +EXTERN float avgpsnr_cod[3][16]; /* avgpsnr_cod[y,u,v][frames in several levels] averaged psnr over all GOPS */ +EXTERN float avgvar[3][16]; /* avgvar[y,u,v][frames in several levels] averaged variance over all GOPS */ + +EXTERN long int *unconnectedL; + + +// by Yongjun Wu +// for directional spatial prediction from RPI +#define IBLOCK_MAX_SIZE 8 // the maximum block size for directional IBLOCK +EXTERN float neighborA[IBLOCK_MAX_SIZE]; +EXTERN float neighborB[IBLOCK_MAX_SIZE]; +EXTERN float neighborC[IBLOCK_MAX_SIZE]; +EXTERN float neighborD[IBLOCK_MAX_SIZE]; +EXTERN float neighborD1[IBLOCK_MAX_SIZE]; +EXTERN float neighborE[IBLOCK_MAX_SIZE]; +EXTERN float neighborF[IBLOCK_MAX_SIZE]; +EXTERN float neighborG[IBLOCK_MAX_SIZE]; +EXTERN float neighborH; +EXTERN float predict_blkY[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE]; +EXTERN float neighborUA[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUB[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUC[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUD[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUD1[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUE[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUF[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUG[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUH; +EXTERN float predict_blkU[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; +EXTERN float neighborVA[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVB[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVC[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVD[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVD1[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVE[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVF[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVG[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVH; +EXTERN float predict_blkV[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; + +// for IBLOCK in OBMC framework +EXTERN float neighbor_predictY[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE]; +EXTERN float neighbor_predictU[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; +EXTERN float neighbor_predictV[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; +EXTERN float self_weight_matrix[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE]; +EXTERN float self_weight_matrixUV[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; + +EXTERN Varblkarrayinfo *varblkarray; +EXTERN ImageMEinfo *frameMEinfo; + +EXTERN ImageMEinfo *buff_frameMEinfo; //Added on 05.22.2018 +EXTERN float gop_block; //Added on 06.28.2018 +EXTERN int frame_cnt; //Added on 06.28.2018 +EXTERN int simul_skip; //Added on 06.30.2018 + +EXTERN int skip_frame; //Added on 06.30.2018 +EXTERN float orig_lambda[ADAPT_LEVEL]; + +/* Check */ + +#endif // CODERN_H diff --git a/Interframe EZBC/TempSub/inc/decoderN.h b/Interframe EZBC/TempSub/inc/decoderN.h new file mode 100644 index 0000000..715dcd5 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/decoderN.h @@ -0,0 +1,19 @@ +#include "structN.h" + +EXTERN videoinfo info; +EXTERN videoheader header; + +EXTERN YUVimage efr; /* prediction error frame */ +EXTERN YUVimage pcode; /* coded previous frame */ + +EXTERN FILE *fpbit; + +EXTERN vector_ptr *yfmv; /* motion vector */ +EXTERN vector_ptr *yfmv_bigGOP; +EXTERN vector_ptr *mv_ref; /* arrays of MV references */ +EXTERN vector_ptr *mv_ref_bigGOP; + +EXTERN YUVimage_ptr pyrFrs; /*frames after temporal decomposition */ +EXTERN YUVimage_ptr pyrFrs_first; /* first L-frames in each GOP */ +EXTERN YUVimage_ptr pyrFrs_bigGOP; +EXTERN YUVimage_ptr *pyrTemp; /*temporary memory for temporally filtering */ diff --git a/Interframe EZBC/TempSub/inc/directional_iblock.h b/Interframe EZBC/TempSub/inc/directional_iblock.h new file mode 100644 index 0000000..12df2f1 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/directional_iblock.h @@ -0,0 +1,44 @@ + +#ifndef DIRECTIONAL_IBLOCK_H +#define DIRECTIONAL_IBLOCK_H + + +#include "structN.h" + +//Added by Yuan Liu +void rec_directional_iblock_analysis(vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int t_level, int remaining_frs, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray); +//Added by Yuan Liu + +void directional_iblock_detection(videoinfo info, vector_ptr fmv1_array, float *fr_cur, + int cx, int cy, int xblock, int yblock, int hor, int ver, int t_level, + vector *tmv1, float *fadditional_penalty ); + +void rec_directional_iblock_analysis_with_OBMC(vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int t_level, int remaining_frs, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray); + +void rec_directional_iblock_synthesis_with_OBMC( vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int level, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray); + +#endif \ No newline at end of file diff --git a/Interframe EZBC/TempSub/inc/dpx.h b/Interframe EZBC/TempSub/inc/dpx.h new file mode 100644 index 0000000..65ebf1c --- /dev/null +++ b/Interframe EZBC/TempSub/inc/dpx.h @@ -0,0 +1,125 @@ +#include "basic.h" +#define Gamma 2.2 +#define Refblack 95 //95 +#define Refwhite 685 //685 +//#define KODAK +#define PEAK 1023 +#define DCtest + +/*generic image data header */ +typedef struct file_information +{ + U32 magic_num; /* magic number 0x53445058 (SDPX) or 0x58504453 (XPDS) */ + U32 offset; /* offset to image data in bytes */ + ASCII vers[8]; /* which header format version is being used (v1.0) */ + U32 file_size; /* file size in bytes */ + ASCII Undefined1[16]; + ASCII Undefined2[624]; + ASCII Undefined3[108]; + +/*U32 ditto_key; *//* read time short cut - 0 = same, 1 = new */ +/*U32 gen_hdr_size; *//* generic header length in bytes */ +/*U32 ind_hdr_size; *//* industry header length in bytes */ +/*U32 user_data_size; *//* user-defined data length in bytes */ +/*ASCII file_name[100]; *//* iamge file name */ +/*ASCII create_time[24]; *//* file creation date "yyyy:mm:dd:hh:mm:ss:LTZ" */ +/*ASCII creator[100]; *//* file creator's name */ +/*ASCII project[200]; *//* project name */ +/*ASCII copyright[200]; *//* right to use or copyright info */ +/*U32 key; *//* encryption ( FFFFFFFF = unencrypted ) */ +/*ASCII Reserved[104]; *//* reserved field TBD (need to pad) */ +} +FileInformation; + + +/*Image Information Header*/ +typedef struct _image_information +{ + U16 orientation; /* image orientation */ + U16 element_number; /* number of image elements */ + U32 pixels_per_line; /* or x value */ + U32 lines_per_image_ele; /* or y value, per element */ + ASCII Undefined1[16]; + + /*struct _image_element */ + /*{ */ + U32 data_sign; /* data sign (0 = unsigned, 1 = signed ) */ + + /* "Core set images are unsigned" */ +/*U32 ref_low_data; *//* reference low data code value */ +/*R32 ref_low_quantity; *//* reference low quantity represented */ +/*U32 ref_high_data; *//* reference high data code value */ +/*R32 ref_high_quantity; *//* reference high quantity represented */ + U8 descriptor; /* descriptor for image element */ + U8 transfer; /* transfer characteristics for element */ + U8 colorimetric; /* colormetric specification for element */ + U8 bit_size; /* bit size for element */ + U16 packing; /* packing for element */ + U16 encoding; /* encoding for element */ + U32 data_offset; /* offset to data of element */ + + +/*U32 eol_padding; *//* end of line padding used in element */ +/*U32 eo_image_padding; *//* end of image padding used in element */ +/*ASCII description[32]; *//* description of element */ +/*} image_element[8]; *//* NOTE THERE ARE EIGHT OF THESE */ +#ifdef DCtest + ASCII Undefined3[7380]; +#else + ASCII Undefined3[64724]; +#endif +/*U8 reserved[52]; *//* reserved for future use (padding) */ +} +Image_Information; + +/*Image Orientation Information*/ +typedef struct _image_orientation +{ + U32 x_offset; /* X offset */ + U32 y_offset; /* Y offset */ + R32 x_center; /* X center */ + R32 y_center; /* Y center */ + U32 x_orig_size; /* X original size */ + U32 y_orig_size; /* Y original size */ + ASCII file_name[250]; /* source image file name */ + ASCII creation_time[24]; /* source image creation date and time */ + ASCII input_dev[32]; /* input device name */ + ASCII input_serial[32]; /* input device serial number */ + U16 border[4]; /* border validity (XL, XR, YT, YB) */ + U32 pixel_aspect[2]; /* pixel aspect ratio (H:V) */ + U8 reserved[28]; /* reserved for future use (padding) */ +} +Image_Orientation; + + +typedef struct dpx +{ + FileInformation fileinfo; + Image_Information imageinfo; +} +DPXHEADER; + + +/*Image Data +The image data is stored as an array of 32-bit elements made up of four signed or unsigned character values. Unsigned values are the default for DPX image data. */ +typedef struct _image_data_element +{ + U32 *Data; +} +Image_Data_Element; + + + + +U16 *read_dpx( char *dpxname, struct dpx **dpxheader, int *nr, int *nc ); +void write_dpx( char *dpxname, float *RGB, videoinfo info ); +void dpxrange( U16 * RGBframe, int row, int col, U16 * Bmin, U16 * Bmax, + U16 * Gmin, U16 * Gmax, U16 * Rmin, U16 * Rmax ); + +float *linearize( U16 * RGBframe, int row, int col, videoinfo info ); +float *Nonlinearize( float *LRGB, int row, int col, videoinfo info ); +void Pack( U32 * data, int comp, U8 bitdepth ); +void save_dpx_header( videoinfo info, int index ); +struct dpx *read_dpx_header( char *filename ); +void compute_colorLUT( int bits, enum CODING_DOMAIN coding_domain ); +float convertLOG( int peak, float data, enum CODING_DOMAIN coding_domain ); diff --git a/Interframe EZBC/TempSub/inc/encoderN.h b/Interframe EZBC/TempSub/inc/encoderN.h new file mode 100644 index 0000000..f89ebbf --- /dev/null +++ b/Interframe EZBC/TempSub/inc/encoderN.h @@ -0,0 +1,20 @@ +#include "structN.h" + +EXTERN videoinfo info; +EXTERN videoheader header; + +EXTERN YUVimage efr; /* prediction error frame */ +EXTERN YUVimage pcode; /* coded previous frame */ + +EXTERN FILE *fpbit; +EXTERN Rate FrsRate; + +EXTERN vector_ptr tmp_yfmv; /* motion vector */ +EXTERN vector_ptr *yfmv; /* motion vector */ +EXTERN vector_ptr *yfmv_bigGOP; /* motion vector for bigGOP */ +EXTERN YUVimage_ptr pyrFrs; /* frames after temporal decomposition */ +EXTERN YUVimage_ptr pyrFrs_bigGOP; /* frames of bigGOP */ +EXTERN YUVimage_ptr *pyrTemp; /* temporary memory for temporally filtering */ +EXTERN float **frY; /* pointer for coding */ +EXTERN float **frU; +EXTERN float **frV; diff --git a/Interframe EZBC/TempSub/inc/golomb.h b/Interframe EZBC/TempSub/inc/golomb.h new file mode 100644 index 0000000..cad7d34 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/golomb.h @@ -0,0 +1,11 @@ +#ifndef GOLOMB_H +#define GOLOMB_H + +#define MAX_LEVELS 100 +#define GRAD0 0 + +void golomb_init(int grad0 = GRAD0, int maxLevels = MAX_LEVELS); +int golomb_encode_word(int word, int write); +int golomb_decode_word(); + +#endif // GOLOMB_H diff --git a/Interframe EZBC/TempSub/inc/hvsbm_fullres.h b/Interframe EZBC/TempSub/inc/hvsbm_fullres.h new file mode 100644 index 0000000..8016493 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/hvsbm_fullres.h @@ -0,0 +1,19 @@ +#ifndef HVSBM_FULLRES_H +#define HVSBM_FULLRES_H + +#include "structN.h" + +float hvsbm_fullres(vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, vector_ptr fmv4, + float *fr_cur, float *fr_ref1, float *fr_ref2, + float *upframe1, float *upframe2, + int t_level, int dist, videoinfo info, int dec); + +void rdme(vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, vector_ptr fmv4, + YUVimage *fr_cur, YUVimage *fr_ref1, YUVimage *fr_ref2, + enum FLAG *sc1, enum FLAG *sc2, int t_level, int dist, videoinfo info, + float *upframe1, float *upframe2, float *upsamp_x ); + +int get_searchrange(int dist, videoinfo info); + +#endif // HVSBM_FULLRES_H + diff --git a/Interframe EZBC/TempSub/inc/initN.h b/Interframe EZBC/TempSub/inc/initN.h new file mode 100644 index 0000000..a8dad64 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/initN.h @@ -0,0 +1 @@ +void reset( videoinfo info ); diff --git a/Interframe EZBC/TempSub/inc/init_decN.h b/Interframe EZBC/TempSub/inc/init_decN.h new file mode 100644 index 0000000..b5a6950 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/init_decN.h @@ -0,0 +1 @@ +void init_dec( videoinfo info ); diff --git a/Interframe EZBC/TempSub/inc/init_encN.h b/Interframe EZBC/TempSub/inc/init_encN.h new file mode 100644 index 0000000..8104dc5 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/init_encN.h @@ -0,0 +1,14 @@ +//EXTERN rdsum rd[3]; +/*EXTERN mvnode_ptr mvtop; APR23*/ +//EXTERN int yfclass_flag; + +/* New */ +extern long int totalY[5], totalU[5], totalV[5], totalmap[5], totalMV[5]; +/* New */ + +long int ezbc3d_enc( int curr, YUVimage * pyrFrs, videoinfo info, + long int GOP_counter, float &gop_mse ); +void release_3dezbc_enc( ); +void print_time( double sc ); + +void init_enc( videoinfo * info ); diff --git a/Interframe EZBC/TempSub/inc/ioN.h b/Interframe EZBC/TempSub/inc/ioN.h new file mode 100644 index 0000000..dfdfbca --- /dev/null +++ b/Interframe EZBC/TempSub/inc/ioN.h @@ -0,0 +1,20 @@ +void read_frame( YUVimage_ptr frame, videoinfo info, char *inname, int index, + enum FORMAT format ); +void write_frame( YUVimage frame, videoinfo info, char *inname, int index, + enum FORMAT format ); + +void print_mv( vector_ptr fmv, int cx, int cy, int xblk, int yblk, int hor, + int ver ); +void write_GOP( int curr, YUVimage ** pyrTemp, YUVimage * pyrFrs, + videoinfo info, enum FLAG first_GOP, int remaining_frs ); + +void write_block_mode_motion_vector(char *direction, int GOP_counter, int count, int frame_type, + vector_ptr fmv, videoinfo info, int t_level); + +void write_frame_into_file(YUVimage frame, videoinfo info, int index, int GOP_counter); + +void read_jp2k_frame( YUVimage_ptr frame, videoinfo info, char *inname, int index, + enum FORMAT format ); +void write_jp2k_frame( YUVimage frame, videoinfo info, char *inname, int index, + enum FORMAT format ); + diff --git a/Interframe EZBC/TempSub/inc/layer_mv.h b/Interframe EZBC/TempSub/inc/layer_mv.h new file mode 100644 index 0000000..d0f3700 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/layer_mv.h @@ -0,0 +1,37 @@ +void update_frame_motion_field(FRAME_MOTION_FIELD *frame_motion_field, int x, int y, + int xblk, int yblk, videoinfo info, vector_ptr fmv, float dmvx, float dmvy, + float mvx, float mvy); + +void clear_frame_motion_field(FRAME_MOTION_FIELD *frame_motion_field, videoinfo info); + +void clear_frame_motion_field_simp(SIMP_FRAME_MOTION_FIELD *frame_motion_field, videoinfo info); + +void copy_frame_motion_field(FRAME_MOTION_FIELD *src_frame_motion_field, SIMP_FRAME_MOTION_FIELD *dest_frame_motion_field, videoinfo info); + +void copy_frame_motion_field2(SIMP_FRAME_MOTION_FIELD *src_frame_motion_field, SIMP_FRAME_MOTION_FIELD *dest_frame_motion_field, videoinfo info); + +void layer_structure_mv_subsample(videoinfo info, int t_level, int tindex, + vector_ptr fmv, int encoder_side); + +void +replace_enhancement_mv( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ); + +void layer_structure_mv_trim(videoinfo info, int t_level, int tindex, vector_ptr fmv, + int count); + + +void get_median_predictor_motion_field(float *pmvx, float *pmvy, + FRAME_MOTION_FIELD *frame_motion_field, SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field, + int x_pos, int y_pos, int xblock, int yblock, + videoinfo info, int t_level, int blk_thresh); + +void ec_get_contexts_motion_field(int *ctx_x, int *ctx_y, FRAME_MOTION_FIELD *frame_motion_field, + int x, int y, videoinfo info, int t_level, int blk_thresh); + + +void test( videoinfo info, unsigned char *qp, int estimated_overhead, unsigned long int *gop_mv, int curr_last, int type ); + diff --git a/Interframe EZBC/TempSub/inc/memoryN.h b/Interframe EZBC/TempSub/inc/memoryN.h new file mode 100644 index 0000000..940306d --- /dev/null +++ b/Interframe EZBC/TempSub/inc/memoryN.h @@ -0,0 +1,17 @@ +#ifndef MEMORY_H +#define MEMORY_H + +void enc_destructor( videoinfo info ); +void dec_destructor( videoinfo info ); + +void alloc_vector( vector_ptr fmv, videoinfo info ); +void free_vector( vector_ptr fmv, videoinfo info ); +void free_mvs( vector_ptr * yfmv, videoinfo info ); + +void frame_alloc( YUVimage_ptr frame, videoinfo info ); +void free_frame( YUVimage frame ); + +void alloc_transmap( transmap ** map, int hor, int ver ); +void free_transmap( transmap * map ); + +#endif // MEMORY_H diff --git a/Interframe EZBC/TempSub/inc/miscN.h b/Interframe EZBC/TempSub/inc/miscN.h new file mode 100644 index 0000000..35fe459 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/miscN.h @@ -0,0 +1,27 @@ +#ifndef _MISCN_H_ +#define _MISCN_H_ + +void info2header( videoheader_ptr header, videoinfo info ); /* miscN.c */ +void header2info( videoinfo_ptr info, videoheader header ); +void read_header( char *name, videoinfo * info ); +void write_header( char *name, videoinfo info ); +long int get_GOP_num( videoinfo info ); + +int get_mvBytes( FILE * fp_mv ); + +float get_mean( float *frame, int lenx, int leny, int hor ); + +int subband_location( int *sx, int *sy, int *lenx, int *leny, int curr, + int band, int hor, int ver ); +float variance( float *frame, int lenx, int leny, int hor ); + +double variance_mean( float *frame, int lenx, int leny, float *mean ); +void varianceGOP( YUVimage_ptr frames, videoinfo info, Rate_ptr alloc ); +void wcopyframe( YUVimage * source, YUVimage * dest, float weight, + videoinfo info ); +void copyframe( YUVimage * source, YUVimage * dest, videoinfo info ); +void computegain( YUVimage lowband, YUVimage highband, videoinfo info ); + +void mv_copy( vector_ptr source, vector_ptr dest, videoinfo info ); + +#endif // _MISCN_H_ diff --git a/Interframe EZBC/TempSub/inc/mode_decision.h b/Interframe EZBC/TempSub/inc/mode_decision.h new file mode 100644 index 0000000..9884c51 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/mode_decision.h @@ -0,0 +1,27 @@ +#ifndef MODE_DECISION_H +#define MODE_DECISION_H + +#include "structN.h" + +/*void find_best_mode(vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *fr_cur, float *fr_ref1, float *fr_ref2, + float *upframe1, float *upframe2, + int x, int y, int xblk, int yblk, int maxx, int maxy, + int hor, int ver, int t_level, videoinfo info, + int ctx1x, int ctx1y, int ctx2x, int ctx2y, + float *pmv1x, float *pmv1y, float *pmv2x, float *pmv2y, int dec);*/ + +void find_best_mode(vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3_array, vector_ptr fmv4_array, + float *fr_cur, float *fr_ref1, float *fr_ref2, + float *upframe1, float *upframe2, + int x, int y, int xblk, int yblk, int maxx, int maxy, + int hor, int ver, int t_level, videoinfo info, + int ctx1x, int ctx1y, int ctx2x, int ctx2y, + float *pmv1x, float *pmv1y, float *pmv2x, float *pmv2y, int dec); + +vector_ptr find_block(int x, int y, vector_ptr root, videoinfo info, int t_level, float *mvx, + float *mvy, int *get_xblk, int *get_yblk, int get_addx, int get_addy); + +int compare_mv(vector_ptr left1, vector_ptr right1, vector_ptr left2, vector_ptr right2); + +#endif // MODE_DECISION_H diff --git a/Interframe EZBC/TempSub/inc/mv_ec.h b/Interframe EZBC/TempSub/inc/mv_ec.h new file mode 100644 index 0000000..4448297 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/mv_ec.h @@ -0,0 +1,94 @@ +#ifndef MV_EC_H +#define MV_EC_H + +#include +#include +#include "structN.h" + +#define Code_value_bits 16 + +enum coderType {AR_NARY = 0, GOLOMB, AR_BINARY}; + +extern int buffer, bits_to_go, garbage_bits, outbyte, inbyte; +extern FILE *fptmp; +extern FILE *fpbit; + +void ec_enc_init(videoinfo info, coderType coder, + int symbols, int contexts = 1, int write = 1); +void ec_enc_end1(); +void ec_enc_end2(); +long int ec_dec_preinit(FILE *fp); +void ec_dec_init(coderType coder, int symbols, int contexts = 1); +void ec_dec_end1(); +long int ec_dec_end2(); +void ec_encode_word(int word, int context = 0); +int ec_decode_word(int context = 0); +void ec_update_model(int word, int context = 0); +float ec_get_expected_length(int word, int context = 0); + +void ec_freeze(); +void ec_unfreeze(int keep_current_states); + +void ec_get_contexts(int *ctx_x, int *ctx_y, vector_ptr fmv, int x, int y, + videoinfo info, int t_level, int blk_thresh); + +void done_splitted_bytes(unsigned char store_splitted_bytes[65535], + unsigned int splitted_byte_num, videoinfo info, + int t_level); + +void get_splitted_bytes(unsigned char *store_splitted_bytes, + unsigned int *splitted_byte_num, videoinfo info, + int t_level, FILE *fpbit, long int starting_pos); + + +/****************************************************************************/ +/****************************************************************************/ + +void encode_init(videoinfo info); +void encode_end(int with, videoinfo info); +void decode_init(); +void decode_end(); + +/****************************************************************************/ +/* output_bit() */ +/****************************************************************************/ +#define output_bit(bit) \ + /** int bit; **/ \ +{ \ + buffer >>=1; \ + if(bit) buffer |= 0x80; /* put bit in top of buffer */ \ + bits_to_go--; \ + if(!bits_to_go){ /* output buffer if it is full */ \ + putc(buffer, fptmp); \ + bits_to_go=8; \ + outbyte++; \ + } \ +} + + +/****************************************************************************/ +/* input_bit() 读一个bit */ +/****************************************************************************/ +#define input_bit(bit) \ +/*** int bit ***/ \ +{ \ + if(!bits_to_go){ /* Read the next byte if no bits are left in buffer */ \ + if(inbyte>0) { /* prevent reading for continous one bit files */ \ + buffer=getc(fpbit); \ + inbyte--; \ + } \ + else{ \ + buffer = EOF; \ + garbage_bits++; /* return arbitrary bits */ \ + if(garbage_bits>Code_value_bits-2){ /* after EOF, but check */ \ + printf("Bad input file\n"); /* for too many such */ \ + } \ + } \ + bits_to_go = 8; \ + } \ + bit = buffer&1; /* return the next bit from */ \ + buffer>>=1; /* the bottom of the byte */ \ + bits_to_go--; \ +} + +#endif // MV_EC_H diff --git a/Interframe EZBC/TempSub/inc/mv_statistics.h b/Interframe EZBC/TempSub/inc/mv_statistics.h new file mode 100644 index 0000000..c648f6c --- /dev/null +++ b/Interframe EZBC/TempSub/inc/mv_statistics.h @@ -0,0 +1,24 @@ +#ifndef MV_STATISTICS_H +#define MV_STATISTICS_H + +#include "structN.h" + +void mvStat_open(char *filename); +void mvStat_setFrame(int GOP, int level, int frame); +void mvStat_setPos(int x, int y); +void mvStat_setDMV(float dmvx, float dmvy); +void mvStat_setCTX(float dmvx_hor, float dmvy_hor, + float dmvx_ver, float dmvy_ver, + float dmvx_dia, float dmvy_dia); +void mvStat_writeDMVCTX(); +void mvStat_writeFreqNumber(int ctx, int cum, int number); +void mvStat_writeFreq(int freq); +void mvStat_close(); + +#ifdef BLOCKMODE_STATISTICS +void record_blockmode_statistics(int xblk, int yblk, enum BiMode, + int bi, int hor, int ver); +void dump_blockmode_statistics(char *filename); +#endif + +#endif diff --git a/Interframe EZBC/TempSub/inc/mvcodingN.h b/Interframe EZBC/TempSub/inc/mvcodingN.h new file mode 100644 index 0000000..48253ea --- /dev/null +++ b/Interframe EZBC/TempSub/inc/mvcodingN.h @@ -0,0 +1,23 @@ +#ifndef MVCODINGN_H +#define MVCODINGN_H + +#include "structN.h" +#include + +extern VLCtable blockmodeVLC[2]; + +int read_GOPheader( enum FLAG **dec_scene_change, videoinfo info ); +int write_GOPheader( enum FLAG **scene_change, videoinfo info ); +int mv_encoding( videoinfo info, Rate FrsRate, vector_ptr * yfmv, + int GOP_counter, int simul_enc, int curr ); +long int mv_decoding( videoinfo info, vector_ptr * yfmv, int GOP_counter, long int starting_pos, int simul_dec, int theo_dec ); +int get_mvBytes( FILE * fp_mv ); +int write_GOPheader( enum FLAG **scene_change, videoinfo info ); + +void decode_MV( long int *total_bytes_past, videoinfo info, int GOP_counter, long int starting_pos, int simul_dec, int theo_dec ); + +int get_mode_coding_cost(enum BiMode bi_mode, vector_ptr fmv2, int bi_sign, int t_level); + +void clean_mrg_mv(vector_ptr fmv); + +#endif diff --git a/Interframe EZBC/TempSub/inc/obmc_varblk.h b/Interframe EZBC/TempSub/inc/obmc_varblk.h new file mode 100644 index 0000000..588166e --- /dev/null +++ b/Interframe EZBC/TempSub/inc/obmc_varblk.h @@ -0,0 +1,16 @@ +#ifndef MCTF_OBMC_H +#define MCTF_OBMC_H + + +#include "structN.h" + +void get_mv_side_information(videoinfo info, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref2, vector_ptr mv_ref3, + ImageMEinfo *imagemeinfo, Varblkarrayinfo *imageblkarray, + int *total_blk, int i, int j, + enum FLAG left_scene, enum FLAG right_scene, int encoder_sign); + +void mv_weight_info(videoinfo info, ImageMEinfo *pixelmeinfo, Varblkarrayinfo *blockinfoarray, + int total_varblk, int t_level, int tindex); + +#endif \ No newline at end of file diff --git a/Interframe EZBC/TempSub/inc/pstatN.h b/Interframe EZBC/TempSub/inc/pstatN.h new file mode 100644 index 0000000..5e7e6d8 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/pstatN.h @@ -0,0 +1,7 @@ +void snr_frame( float *ysnr, float *usnr, float *vsnr, YUVimage_ptr codeframe, + YUVimage_ptr inframe, videoinfo info ); +float calsnr( int start, int last, videoinfo info ); +void calsnr1( YUVimage_ptr fr0, YUVimage_ptr fr1, int start, int last, + videoinfo info ); +/* void print_stat( videoinfo info ); */ +void print_mvbits( videoinfo info, Rate FrsRate ); diff --git a/Interframe EZBC/TempSub/inc/pull_res.h b/Interframe EZBC/TempSub/inc/pull_res.h new file mode 100644 index 0000000..549bf9b --- /dev/null +++ b/Interframe EZBC/TempSub/inc/pull_res.h @@ -0,0 +1,96 @@ +#ifndef CODERN_H +#define CODERN_H + +EXTERN YUVimage end_of_lastGOP; +EXTERN FILE *fpbit; +EXTERN Rate FrsRate; + +EXTERN vector_ptr tmp_yfmv; +EXTERN vector_ptr *yfmv; /* motion vector */ +EXTERN vector_ptr *yfmv_bigGOP; /* only help for different GOP */ +EXTERN vector_ptr *mv_ref; /* arrays of MV references */ +EXTERN vector_ptr *mv_ref_bigGOP; + +EXTERN YUVimage_ptr pyrFrs; /* frames after temporal decomposition */ +EXTERN YUVimage_ptr pyrFrs_bigGOP; /* only help for different GOP */ +EXTERN YUVimage_ptr pyrFrs_first; /* first L-Frame by decoding */ + +EXTERN enum FLAG **scene_change; +EXTERN enum FLAG scene_change_help; + +EXTERN YUVimage_ptr *pyrTemp; /* temporary memory for temporally filtering */ +EXTERN YUVimage_ptr Four_GOP, Four_bigGOP; /* only used if info.denoise_flag == YES */ +EXTERN YUVimage_ptr spatial_high[3]; /* only used if info.denoise_flag == YES */ + +EXTERN float HPW1[3], HPW2[3], HPW3[3], HPW4[3], /* filter for temporal decomposition */ + HPW1_pred[3], HPW2_pred[3], HPW3_pred[3], HPW4_pred[3], + LPW1[3], LPW2[3], LPW3[3], LPW4[3]; + +EXTERN float FIR14[FIR_LEN], FIR12[FIR_LEN], FIR34[FIR_LEN], FIR18[FIR_LEN], FIR38[FIR_LEN], FIR58[FIR_LEN], + FIR78[FIR_LEN], FIR1hex[FIR_LEN], FIR3hex[FIR_LEN], FIR5hex[FIR_LEN], FIR7hex[FIR_LEN], FIR9hex[FIR_LEN], + FIR11hex[FIR_LEN], FIR13hex[FIR_LEN], FIR15hex[FIR_LEN]; + +/* Check */ +EXTERN float **frY; /*pointer for coding */ + +EXTERN float **frU; +EXTERN float **frV; + +EXTERN int connected, unreferred, pre_connected, multi_connected, + next_connected, case4; +EXTERN long int totalY[5], totalU[5], totalV[5], totalmap[5], totalMV[5]; +EXTERN float avgpsnr[3][16]; /* avgpsnr[y,u,v][frames in several levels] averaged psnr over all GOPS */ +EXTERN float avgpsnr_cod[3][16]; /* avgpsnr_cod[y,u,v][frames in several levels] averaged psnr over all GOPS */ +EXTERN float avgvar[3][16]; /* avgvar[y,u,v][frames in several levels] averaged variance over all GOPS */ + +EXTERN long int *unconnectedL; + + +// by Yongjun Wu +// for directional spatial prediction from RPI +#define IBLOCK_MAX_SIZE 8 // the maximum block size for directional IBLOCK +EXTERN float neighborA[IBLOCK_MAX_SIZE]; +EXTERN float neighborB[IBLOCK_MAX_SIZE]; +EXTERN float neighborC[IBLOCK_MAX_SIZE]; +EXTERN float neighborD[IBLOCK_MAX_SIZE]; +EXTERN float neighborD1[IBLOCK_MAX_SIZE]; +EXTERN float neighborE[IBLOCK_MAX_SIZE]; +EXTERN float neighborF[IBLOCK_MAX_SIZE]; +EXTERN float neighborG[IBLOCK_MAX_SIZE]; +EXTERN float neighborH; +EXTERN float predict_blkY[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE]; +EXTERN float neighborUA[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUB[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUC[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUD[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUD1[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUE[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUF[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUG[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborUH; +EXTERN float predict_blkU[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; +EXTERN float neighborVA[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVB[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVC[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVD[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVD1[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVE[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVF[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVG[IBLOCK_MAX_SIZE/2]; +EXTERN float neighborVH; +EXTERN float predict_blkV[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; + +// for IBLOCK in OBMC framework +EXTERN float neighbor_predictY[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE]; +EXTERN float neighbor_predictU[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; +EXTERN float neighbor_predictV[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; +EXTERN float self_weight_matrix[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE]; +EXTERN float self_weight_matrixUV[IBLOCK_MAX_SIZE*IBLOCK_MAX_SIZE/4]; + +EXTERN Varblkarrayinfo *varblkarray; +EXTERN ImageMEinfo *frameMEinfo; + + +/* Check */ + +#endif // CODERN_H diff --git a/Interframe EZBC/TempSub/inc/rasterfile.h b/Interframe EZBC/TempSub/inc/rasterfile.h new file mode 100644 index 0000000..229894e --- /dev/null +++ b/Interframe EZBC/TempSub/inc/rasterfile.h @@ -0,0 +1,62 @@ +/* @(#)rasterfile.h 1.11 89/08/21 SMI */ + +/* + * Description of header for files containing raster images + */ + +#ifndef _rasterfile_h +#define _rasterfile_h + +#define GRAYDATA 8 +#define RGBDATA 24 + +struct rasterfile +{ + int ras_magic; /* magic number */ + int ras_width; /* width (pixels) of image */ + int ras_height; /* height (pixels) of image */ + int ras_depth; /* depth (1, 8, or 24 bits) of pixel */ + int ras_length; /* length (bytes) of image */ + int ras_type; /* type of file; see RT_* below */ + int ras_maptype; /* type of colormap; see RMT_* below */ + int ras_maplength; /* length (bytes) of following map */ + /* color map follows for ras_maplength bytes, followed by image */ +}; +#define RAS_MAGIC 0x59a66a95 + + /* Sun supported ras_type's */ +#define RT_OLD 0 /* Raw pixrect image in 68000 byte order */ +#define RT_STANDARD 1 /* Raw pixrect image in 68000 byte order */ +#define RT_BYTE_ENCODED 2 /* Run-length compression of bytes */ +#define RT_FORMAT_RGB 3 /* XRGB or RGB instead of XBGR or BGR */ +#define RT_FORMAT_TIFF 4 /* tiff <-> standard rasterfile */ +#define RT_FORMAT_IFF 5 /* iff (TAAC format) <-> standard rasterfile */ +#define RT_EXPERIMENTAL 0xffff /* Reserved for testing */ + + /* Sun registered ras_maptype's */ +#define RMT_RAW 2 + /* Sun supported ras_maptype's */ +#define RMT_NONE 0 /* ras_maplength is expected to be 0 */ +#define RMT_EQUAL_RGB 1 /* red[ras_maplength/3],green[],blue[] */ + +/* + * NOTES: + * Each line of the image is rounded out to a multiple of 16 bits. + * This corresponds to the rounding convention used by the memory pixrect + * package (/usr/include/pixrect/memvar.h) of the SunWindows system. + * The ras_encoding field (always set to 0 by Sun's supported software) + * was renamed to ras_length in release 2.0. As a result, rasterfiles + * of type 0 generated by the old software claim to have 0 length; for + * compatibility, code reading rasterfiles must be prepared to compute the + * true length from the width, height, and depth fields. + */ + +#endif /*!_rasterfile_h */ + + + +struct rasterfile make_header( int hor, int ver, int depth ); +struct rasterfile *read_ras( char *filename, unsigned char **frame ); +struct rasterfile *read_charimg24( char *name, unsigned char **img ); +void write_ras( char *filename, struct rasterfile header, + unsigned char *frame ); diff --git a/Interframe EZBC/TempSub/inc/structN.h b/Interframe EZBC/TempSub/inc/structN.h new file mode 100644 index 0000000..61f2eb2 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/structN.h @@ -0,0 +1,2122 @@ +#ifndef STRUCTN_H +#define STRUCTN_H + +#define SMALL_DIFF 0.001 +#define FIR_LEN 8 // 12 or 8 + +#define EXT 0 +#define EXTRACT_TMP 2 + +#define ADD_SUB 0 +#define LAMBDA_ADPT_LEVEL 2 + +#define THRES_RATIO 0.71 + +/*******改动********/ +//#define COUT_MV_UPDATE +//#define CNN_wavelet +//#define CNN_TEMPORAL_WAVELET +//#define NO_UPDATE +//#define NO_CONNECT 79行帧内块 +//#define use_BILINEAR_type +//#define NO_NORMALIZATION +//#define NO_EZBC +//#define NO_OBMC +/*******改动********/ + +#include + +/************************************************************************* + ***************************** RDO ME ************************************/ + +//#define JP2K_SUBBAND + +#define IBLOCK_FACTOR 0.5 +#define BIME_ITERATIONS 2 +#define RDMD_INTRA_FACTOR 0.85f +#define MEDIAN_PREDICTION +#define ECSIM_TYPE GOLOMB // AR_BINARY +//#define AFFINE_APPLY +//#define TWO_COMP +//#define TEST_LAMBDA + +//#define ECSIM_USE_CONTEXTS +//#define EC_SIM_TYPE AR_BINARY + +#define G_LEVEL 4 +#define MAX_HUFF_NUM 4 +#define AFF_SUBPEL 1000 +/************************************************************************* + ************************* Bit allocation ********************************/ +// +#define PREQUANT_WEIGHTING //正常打开 +#define COPYCOMPENSATION_WEIGHTING +//#define COPYCOMPENSATION_WEIGHTING_FORPREDICTED + + +/************************************************************************* + **************************** Debug **************************************/ + +//#define BLOCKMODE_STATISTICS +//#define MY_SCALE 512 + + +/************************************************************************* + **************************** General ************************************/ + +#define PRE_INTERPOL 4 // maximum interpolation steps prior to mode decision +#define MAX_TLEVELS 8 // maximum number of temporal levels + // determines array sizes in videoinfo structure +#define BILINEAR 22 +//#define SUPPORT_INTRA +//#define THREE_D +#define DENOISE_FILTER 2 // spatial filter type for denoising (2, 7 = Daubechies, cmp. subband_choi.c) +#define YUV420 0 // downsample full resolution U V component (conversion 444 -> 420) +//#define DPX_SUPPORT +//#define INTRA_SUPPORT + +/*=======================================================================*/ + +#define LAYER_NUM 2 +#define MAX_AGP_LEVEL 3 +//#define DEGUB_DIRECTIONAL_IBLOCK_OBMC +//#define MCTF_WITH_OBMC 关掉 +//#define DIRECTIONAL_IBLOCK_EMPLOYED // 帧内块 +//#define FREQUENCY_ROLL_OFF // visual optimization of low resolution videos +//#define ROLL_STRUCTURE_ONE 关掉 +//#define ROLL_STRUCTURE_TWO + +#define VBR_DEC + +// here we must enable FREQUENCY_ROLL_OFF & ROLL_STRUCTURE_ONE or +// FREQUENCY_ROLL_OFF & ROLL_STRUCTURE_TWO +// for SD sequence, we can use structure two for frequency roll off +// however for CIF sequence, we can only use structure one for frequency roll off +// moreover for structure two, we need to disable interband context modelling + +/*=======================================================================*/ + +/************************************************************************* + ************************** Data Types & Constants ***********************/ + +enum FORMAT +{ YUV, RAS, DPX }; +enum FLAG +{ NO = 0, YES }; +//{ YES, NO }; +enum CODING_DOMAIN +{ LOG, LINEAR, VIDEO }; +enum PixelMode +{ UNI, MULTI, INTRA, UNDEF }; + /* UNI: uniconnected; MULTI: multiconnected; INTRA: unmatched pixel; UNDEF: have not been decided + In the reference, pixels could only be UNI, MULTI finally. + In the current frame, pixels could be UNI, MULTI, and INTRA finally. + */ +typedef struct +{ + float *Y; + float *U; + float *V; +} +YUVimage, *YUVimage_ptr; + +///Added by Yuan Liu +enum directMODE { + NONAFF = -1, + DIRECT, INDIRECT +}; +enum mergeMODE{ + INEFFECTIVE = -1, + MERGE, INTER +}; +enum mergeDIR{ + MUDA = -1, + UP, LEFT, TRAN_P, PAL_L +}; + +enum aff_transPRED{ + DIR,INDIR,PARA +}; //PARA is only applied to BI_DIRECTIONAL_AFF cases +//////////////////// + +/*********** general collection of necessary data for encoder **********/ +typedef struct +{ + char inname[250]; /* input sequence */ + char decname[250]; /* decoded sequence */ + char bitname[250]; /* encoded bit file and temp file */ + char statname[250]; /* statistics */ + char tmpname[250]; + char mvname[250]; /* motion vectors */ + +#ifdef CNN_wavelet + char hpcbindata[250]; // 二进制数据 +#endif + + char jp2kname[250]; //Added on 09.14.2016 + char jp2k_decname[250]; //Added on 09.14.2016 + + char mvstatname[250]; /* number of bytes spent for individual GOPs */ + char tsubname[250]; /* prefix of temporal subband files */ + + int framerate; /* general information */ + int ywidth; /* spatial resolution for Y, U and V */ + int yheight; + int org_ywidth; // the origial resolution for the video by Yongjun Wu + int org_yheight; + int cwidth; + int cheight; + int start; /* start - last */ + int last; + int act_last; + int verbose; /* for debugging */ + enum FORMAT format; /* image format */ + + int simul_rate; + + unsigned char pixeldepth; // 位深 + + int level[MAX_TLEVELS]; /* fixed or variable-size block matching 由配置文件指定 */ + int ME; /* motion estimation scheme */ + float lambda[MAX_TLEVELS]; /* for HVSBM */ + float aff_lambda[MAX_TLEVELS]; /* for affine blocks in HVSBM, added by Yuan Liu on 05.06.2016 */ + int subpel[MAX_TLEVELS]; /* accuracy for MC temporal analysis 对应参数MVaccuracy*/ + int xblk[MAX_TLEVELS]; /* block size 每一次的块大小 */ + int yblk[MAX_TLEVELS]; + int searchrange; /* hvsbm_fullres search range */ + int maxsearchrange; /* hvsbm_fullres maximum search range */ + int xnum[MAX_TLEVELS]; /* number of blocks */ + int ynum[MAX_TLEVELS]; + int maxMBnum; /* maximum number of blocks */ + + int bitrate; /* overall target rate kbps */ + int GOPbytes; /* target rate for GOP */ + + unsigned char qp; + unsigned char SLTF_range; /* SLTF transition range */ + unsigned char SHTF_range; /* SHTF transition range */ + + enum FLAG denoise_flag; + + short int t_level;// 时域第几次小波变换 + short int s_level;// 空域第几次小波变换 + short int tPyrLev; // 时域进行几次小波, 在配置文件中读取 + int GOPsz; + int bigGOP; // 等于( 0x1 << ( header.tPyrLev + 1 ) ) - 1,永远都是这样 + int eff_GOPsz; + int lambda_adapt_thres; + + // scalable motion vector coding + + int AGP_level[MAX_TLEVELS]; // AGP + int AGP_exist[MAX_TLEVELS]; // how many sub-symbols exist。表示mv的scalable + + int bi_mv[MAX_TLEVELS]; // for alternative Haar reconstruction with 5/3 decomposition + int bi_exist[MAX_TLEVELS]; + // bi_mv[]==1 RIGHT_CONNECTED mode exists: + // mv must be bi-directional and bi_exist[] must be 1 + // bi_mv[]==0 RIGHT_CONNECTED mode is prevented: + // mv on RIGHT side can be discarded and bi_exist[] can be 0 or 1. + + int layer_mv[MAX_TLEVELS]; // layered structure for motion vector coding + int layer_exist[MAX_TLEVELS]; +} +videoinfo, *videoinfo_ptr; + +// 头信息 +/*********** general collection of necessary data for decoder **********/ +typedef struct +{ + short int framerate; /* general information */ + short int ywidth; /* spatial resolution for Y, U and V */ + short int yheight; + short int cwidth; + short int cheight; + + short int start; /* start - last */ + short int last; + unsigned short int bitrate; + short int level[MAX_TLEVELS]; /* fixed or variable-size block matching */ + short int subpel[MAX_TLEVELS];/* accurate for MC temporal analysis */ + short int xblk[MAX_TLEVELS]; /* block size */ + short int yblk[MAX_TLEVELS]; + + enum FLAG denoise_flag; + + short int t_level; + short int s_level; + short int tPyrLev; + + unsigned char SLTF_range; /* SLTF transition range */ + unsigned char SHTF_range; /* SHTF transition range */ + +} +videoheader, *videoheader_ptr; + + +// lifting modes (uni-directional): +// bi-directional prediction for 5/3 temporal filters 双向预测使用5/3小波 +// IGNORED: vector not used, not transmitted 不使用向量,不传输 +// CONNECTED: prediction + update 连贯的:预测加更新 +// PREDICTED: prediction only 预测:仅预测 +enum LiftingMode +{ + IGNORED = -1, CONNECTED, PREDICTED, SPATIAL_PREDICTED, UNDECIDED +}; + +// UNDECIDED lifting mode is specially designed for the newly introduced BLOCK MERGING mode + +// bi-directional modes +#define NUMBER_OF_BI_MODES 12 // 8+1 add directional IBLOCK by Yongjun Wu + // 5 additional affine modes are added by Yuan Liu +#define NUMBER_OF_TRANS_MODES 9 // 8+1 Translational modes + +enum BiMode // 双向预测的模式 + {UNDEFINED = -1, + BI_CONNECTED, // 0 + LEFT_CONNECTED, // 1 + RIGHT_CONNECTED, // 2 + BI_PREDICTED, // 3 + LEFT_PREDICTED, // 4 + RIGHT_PREDICTED, // 5 + PARALLEL, // 6 + BLOCK_MERGING, //7 + DIRECTIONAL_IBLOCK, //8 // by Yongjun Wu 帧内模式 + + BI_CONNECTED_AFF, //9 // by Yuan Liu + LEFT_CONNECTED_AFF,//10 + RIGHT_CONNECTED_AFF//11 + }; + +// map bi modes onto lifting modes +const enum LiftingMode left_mode[NUMBER_OF_BI_MODES] = + {CONNECTED, CONNECTED, IGNORED, PREDICTED, PREDICTED, IGNORED, CONNECTED, UNDECIDED, SPATIAL_PREDICTED, + CONNECTED, CONNECTED, IGNORED }; +const enum LiftingMode right_mode[NUMBER_OF_BI_MODES] = + {CONNECTED, IGNORED, CONNECTED, PREDICTED, IGNORED, PREDICTED, CONNECTED, UNDECIDED, SPATIAL_PREDICTED, + CONNECTED, IGNORED, CONNECTED }; + +/* type definitions for variable length code table entries */ +typedef struct +{ + unsigned char code; /* right justified */ + char len; +} +VLCtable; + + + +// by Yongjun Wu, May 18 +// now assume all the modes with the same probabilities 9 spatial prediction modes +#define DIRECTIONAL_IBLOCK_BIAS (float)1.5 +#define PRE_MODE_NUM 9 +enum spatialMODE { INVALID_SPATIAL_MODE = -1, + SPATIAL_VERTICAL, SPATIAL_HORIZONTAL, SPATIAL_DC, + SPATIAL_DOWN_LEFT, SPATIAL_DOWN_RIGHT, SPATIAL_VERTICAL_RIGHT, + SPATIAL_HORIZONTAL_DOWN, SPATIAL_VERTICAL_LEFT, SPATIAL_HORIZANTAL_UP }; + +////////////// Added by Yuan Liu on 02.28.2016 //////////////////// +const VLCtable tripleHuffPred[MAX_HUFF_NUM - 1] = { + //code, len + {0, 1}, //huffman code = 0 + {2, 2}, //huffman code = 10 + {3, 2} //huffman code = 11 +}; + +const VLCtable quartetHuffPredS[MAX_HUFF_NUM] = { + //code, len + {0, 1}, //huffman code = 0 + {2, 2}, //huffman code = 10 + {6, 3}, //huffman code = 110 + {7, 3} //huffman code = 111 +}; +///////////////////////////////////////////////////////////////////// + +const VLCtable spatialmodeVLC[PRE_MODE_NUM]={ + //code, len + {0, 3}, //SPATIAL_VERTICAL huffman code = 000 + {1, 3}, //SPATIAL_HORIZONTAL huffman code = 001 + {2, 3}, //SPATIAL_DC huffman code = 010 + {3, 3}, //SPATIAL_DOWN_LEFT huffman code = 011 + {4, 3}, //SPATIAL_DOWN_RIGHT huffman code = 100 + {5, 3}, //SPATIAL_VERTICAL_RIGHT huffman code = 101 + {6, 3}, //SPATIAL_HORIZONTAL_DOWN huffman code = 110 + {14, 4}, //SPATIAL_VERTICAL_LEFT huffman code = 1110 + {15, 4} //SPATIAL_HORIZANTAL_UP huffman code = 1111 +}; + + + + +// The elements of blockmode should correspond to the elements of enum BlockMode +extern VLCtable blockmodeVLC[2]; +extern int mv_res_bits; +extern int mv_bits; + +// VLC table for bi-directional MVF, the codes are constructed from a Huffman tree +//////////////modified by Yuan Liu//////////////////////// +/* +const VLCtable bi_mode_VLC_0[NUMBER_OF_BI_MODES] = { + { 0, 4}, // BI_CONNECTED 0000 + { 2, 2}, // LEFT_CONNECTED 10 + { 0, -1}, // RIGHT_CONNECTED illegal + { 1, 3}, // BI_PREDICTED 001 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 3, 2}, // PARALLEL 11 + { 1, 2}, // BLOCK_MERGING 01 + { 1, 4} // DIRECTIONAL_IBLOCK 0001 +};*/ + +const VLCtable bi_mode_VLC_0[NUMBER_OF_BI_MODES] = { + { 0, 5}, // BI_CONNECTED 00000 + { 4, 3}, // LEFT_CONNECTED 100 + { 0, -1}, // RIGHT_CONNECTED illegal + { 1, 3}, // BI_PREDICTED 001 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 3, 2}, // PARALLEL 11 + { 1, 2}, // BLOCK_MERGING 01 + { 1, 4}, // DIRECTIONAL_IBLOCK 0001 + + { 1, 5}, // BI_CONNECTED_AFF 00001 + { 5, 3}, // LEFT_CONNECTED_AFF 101 + { 0, -1} // RIGHT_CONNECTED_AFF illegal +}; +//////////////modified by Yuan Liu//////////////////////// + +/* +const VLCtable bi_mode_VLC_1[NUMBER_OF_BI_MODES] = { + { 0, 4}, // BI_CONNECTED 0000 + { 2, 2}, // LEFT_CONNECTED 10 + { 3, 2}, // RIGHT_CONNECTED 11 + { 3, 5}, // 00011 //{ 1, 4}, // BI_PREDICTED 0001 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 1, 3}, // PARALLEL 001 + { 1, 2}, // BLOCK_MERGING 01 + { 2, 5} // DIRECTIONAL_IBLOCK 00010 // by Yongjun Wu + +}; +*/ + +#define CORRELATED_TEMPORAL_LEVELS 2 + +//////////////modified by Yuan Liu//////////////////////// +/* +const VLCtable bi_mode_VLC_1_012[NUMBER_OF_BI_MODES] = { + { 0, 4}, // BI_CONNECTED 0000 + { 2, 2}, // LEFT_CONNECTED 10 + { 3, 2}, // RIGHT_CONNECTED 11 + { 3, 5}, // BI_PREDICTED 00011 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 1, 3}, // PARALLEL 001 + { 1, 2}, // BLOCK_MERGING 01 + { 2, 5} // DIRECTIONAL_IBLOCK 00010 // by Yongjun Wu + +};*/ +const VLCtable bi_mode_VLC_1_012[NUMBER_OF_BI_MODES] = { + { 0, 5}, // BI_CONNECTED 00000 + { 2, 2}, // LEFT_CONNECTED 10 + { 3, 2}, // RIGHT_CONNECTED 11 + { 3, 5}, // BI_PREDICTED 00011 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 2, 4}, // PARALLEL 0010 + { 1, 2}, // BLOCK_MERGING 01 + { 4, 6}, // DIRECTIONAL_IBLOCK 000100 // by Yongjun Wu + + { 5, 6}, // BI_CONNECTED_AFF 000101 + { 3, 4}, // LEFT_CONNECTED_AFF 0011 // by Yuan Liu + { 1, 5}, // RIGHT_CONNECTED_AFF 00001 +}; +///////////////////modified by Yuan Liu//////////////////////// + +const VLCtable bi_mode_VLC_enc_1_012[NUMBER_OF_BI_MODES] = { + { 0, 5}, // BI_CONNECTED 00000 + { 2, 3}, // LEFT_CONNECTED 010 + { 3, 3}, // RIGHT_CONNECTED 011 + { 3, 5}, // BI_PREDICTED 00011 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 2, 4}, // PARALLEL 0010 + { 1, 1}, // BLOCK_MERGING 1 + { 4, 6}, // DIRECTIONAL_IBLOCK 000100 // by Yongjun Wu + + { 5, 6}, // BI_CONNECTED_AFF 000101 + { 3, 4}, // LEFT_CONNECTED_AFF 0011 // by Yuan Liu + { 1, 5}, // RIGHT_CONNECTED_AFF 00001 +}; + +///////////////////modified by Yuan Liu//////////////////////// +/* +const VLCtable bi_mode_VLC_1_345[NUMBER_OF_BI_MODES] = { + { 1, 3}, // BI_CONNECTED 001 + { 2, 2}, // LEFT_CONNECTED 10 + { 3, 2}, // RIGHT_CONNECTED 11 + { 0, 4}, // BI_PREDICTED 0000 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 3, 5}, // PARALLEL 00011 + { 1, 2}, // BLOCK_MERGING 01 + { 2, 5} // DIRECTIONAL_IBLOCK 00010 // by Yongjun Wu + +};*/ + +const VLCtable bi_mode_VLC_1_345[NUMBER_OF_BI_MODES] = { + { 1, 3}, // BI_CONNECTED 001 + { 2, 2}, // LEFT_CONNECTED 10 + { 3, 2}, // RIGHT_CONNECTED 11 + { 0, 5}, // BI_PREDICTED 00000 + { 0, -1}, // LEFT_PREDICTED illegal + { 0, -1}, // RIGHT_PREDICTED illegal + { 6, 6}, // PARALLEL 000110 + { 1, 2}, // BLOCK_MERGING 01 + { 4, 6}, // DIRECTIONAL_IBLOCK 000100 // by Yongjun Wu + + { 5, 6}, // BI_CONNECTED_AFF 000101 + { 1, 5}, // LEFT_CONNECTED_AFF 00001 + { 7, 6}, // RIGHT_CONNECTED_AFF 000111 +}; +///////////////////modified by Yuan Liu//////////////////// + +// VLC table for uni-directional MVF (always left), the codes are constructed from a Huffman tree + +///////////////////modified by Yuan Liu//////////////////// +/* +const VLCtable uni_mode_VLC[NUMBER_OF_BI_MODES] = { + {0, -1}, // BI_CONNECTED illegal + {0, 1}, // LEFT_CONNECTED 0 + {0, -1}, // RIGHT_CONNECTED illegal + {0, -1}, // BI_PREDICTED illegal + {2, 2}, // code 10 //{1, 1}, // LEFT_PREDICTED 1 // by Yongjun Wu + {0, -1}, // RIGHT_PREDICTED illegal + {0, -1}, // PARALLEL illegal + {0, -1}, // BLOCK_MERGING illegal // uni-dir spatial could be included here as well + {3, 2} // DIRECTIONAL_IBLOCK 11 // by Yongjun Wu +};*/ + +const VLCtable uni_mode_VLC[NUMBER_OF_BI_MODES] = { + {0, -1}, // BI_CONNECTED illegal + {0, 2}, // LEFT_CONNECTED 00 + {0, -1}, // RIGHT_CONNECTED illegal + {0, -1}, // BI_PREDICTED illegal + {2, 2}, // code 10 //{1, 1}, // LEFT_PREDICTED 1 // by Yongjun Wu + {0, -1}, // RIGHT_PREDICTED illegal + {0, -1}, // PARALLEL illegal + {1, 2}, // BLOCK_MERGING 01 // uni-dir spatial could be included here as well + {6, 3}, // DIRECTIONAL_IBLOCK 110 // by Yongjun Wu + + {0, -1}, // BI_CONNECTED_AFF illegal + {7, 3}, // LEFT_CONNECTED_AFF 111 // by Yuan Liu + {0, -1}, // RIGHT_CONNECTED_AFF illegal +}; +///////////////////modified by Yuan Liu//////////////////// + +typedef struct { + float mvx; + float mvy; + + float dmvx; + float dmvy; + + int med_idx; //Added by Yuan Liu on 01.18.2016 +// int aff_med_idx; + + ///// Added by Yuan Liu ////// + int direct_idx; + int merge_idx; + int merge_dir; + int aff_idx; + + int aff_mrg; + + float aff1_mvx; + float aff1_mvy; + float aff2_mvx; + float aff2_mvy; + float aff3_mvx; + float aff3_mvy; + ////////////////////////////// + + float sad_cost; + float mse; + float bit_cost; + float total_cost; + enum FLAG is_valid; + enum FLAG is_predictor; + enum spatialMODE iblock_spatial_mode; + enum LiftingMode lifting_mode; +} ModeInfo; + +const ModeInfo invalid_mode_info = + {(float)HUGE_VAL, (float)HUGE_VAL, + (float)HUGE_VAL, (float)HUGE_VAL, (float)HUGE_VAL, NO, NO, INVALID_SPATIAL_MODE}; + +typedef struct Vector +{ + int child; + enum LiftingMode lifting_mode; + enum BiMode bi_mode; + ModeInfo mode_info[NUMBER_OF_BI_MODES]; + + enum spatialMODE iblock_spatial_mode; // the spatial prediction mode of the IBLOCK + int propagate_iblk; + +// int Ymean; +// int Umean; +// int Vmean; + unsigned char meandepth; + float mvx; + float mvy; + float mad; // Jan27 +// float bi_mvx; +// float bi_mvy; +// float bi_mad; // Jan27 + float mse; + float var; +// int dL; /* decrease of number of leaf */ +// int dMAP; /* decrease of number of mvbit */ +// int dMV; /* decrease of number of mvbit */ +// int dD; /* increase of distortion */ +// float slope; /* slope */ +// float mslope; + enum FLAG merge; + + // Ru: new items for RD mode decision + float dmvx; // for CABAC (contexts) + float dmvy; // for CABAC (contexts) + + int med_idx; //Added on 01.17.2016 +// int aff_med_idx; + + ///////Added by Yuan Liu/////////////// + // Affine model is first predicted by neighbor information, then △V will be coded if AFFINE_INTER mode is chosen + + int trans_pred_idx; + int direct_idx; + int merge_idx; + int merge_dir; + int aff_idx; + + int aff_mrg; + + float aff1_mvx; + float aff1_mvy; + float aff2_mvx; + float aff2_mvy; + float aff3_mvx; + float aff3_mvy; + + float aff1_dmvx; + float aff1_dmvy; + float aff2_dmvx; + float aff2_dmvy; + float aff3_dmvx; + float aff3_dmvy; + /////////////////////////////////////// + //For MERGE test only +/* + float mrg_mvx[4]; + float mrg_mvy[4]; + + float mrg_aff_mvx1[4]; + float mrg_aff_mvx2[4]; + float mrg_aff_mvx3[4]; + + float mrg_aff_mvy1[4]; + float mrg_aff_mvy2[4]; + float mrg_aff_mvy3[4]; +*/ +//For affine test only + float aff1_pred_mvx[3],aff1_pred_mvy[3],aff2_pred_mvx[3],aff2_pred_mvy[3],aff3_pred_mvx[3],aff3_pred_mvy[3]; + //////////////////////////////////////// + + enum FLAG is_predictor; + float sad_cost; + float bit_cost; + float total_cost; + + // for layer-structure motion vector coding + int merge_sign; + int mv_exist; + float sample_mvx; + float sample_mvy; + + int two_comp_src; //added on 12.10.2016 + + struct Vector *child0; + struct Vector *child1; + struct Vector *child2; + struct Vector *child3; + + struct Vector *parent; + + int skip_sign; //Added on 08.11.2018 +} +vector, *vector_ptr; + +typedef struct +{ + int *map; + int **mv; + int ***submv; // for scalable motion vector coding: AGP + + int *ybit; + int *ubit; + int *vbit; + + float *yvar; + float *uvar; + float *vvar; +} +Rate, *Rate_ptr; + +typedef struct +{ + int *cmode; /* block mode map of current pixels*/ + int *dist; /* minimal distance to nearest pixel + with different block mode */ + int *tmode; /* block mode map of nearest pixels + with different block mode */ +} +transmap, *transmap_ptr; + + +typedef struct{ + int leftx; // left corner position in image for this block + int topy; // top corner position in image for this block + int blksize; // block size for this block in quad-tree + enum BiMode bi_mode; // block mode for this block 这个块的模式 + enum spatialMODE iblock_spatial_mode; // spatial mode for a directional IBLOCK 空间方向信息 + float self_weight; // the weight from its own block 自身权重 + float h_weight; // the weight from horizontal neighbor -- left or right + float v_weight; // the weight from vertical neighbor -- top or bottom + int blocknum; // the number for this block in quad-tree visting order 在四叉树的块中的第几个 + float left_mvx; // mv信息 + float left_mvy; + float right_mvx; + float right_mvy; + + int aff_mrg; + int mrg_blk_bdr; + int mk_sign; + int skip_sign; + + int two_comp_src; + int two_comp_bdr; + +//#ifdef CNN_TEMPORAL_WAVELET +// float cnn_ptmp0; +// float cnn_ptmp1; +//#endif + ///////////////////////////////////////// +} ImageMEinfo; // motion information for each pixel 每个像素的运动信息 + + +typedef struct{ + float dmvx; + float dmvy; + float mvx; + float mvy; + + ////////// Added by Yuan Liu ////// + /////////////////////////////////// + + short int available; +} FRAME_MOTION_FIELD; + +typedef struct{ + float mvx; + float mvy; + + short int available; +}SIMP_FRAME_MOTION_FIELD; + +typedef struct{ + int leftx; // left corner position + int topy; // top corner position + int blksize; // block size +} Varblkarrayinfo; // variable block size array information 表示块的大小和位置 + +#define SMALLEST_BLKSIZE 4 + + +const float blk4_cur[4][4] = { // weighting for current block + 2, 3, 3, 2, + 3, 4, 4, 3, + 3, 4, 4, 3, + 2, 3, 3, 2 +}; +const float blk4_hor[4][2] = { // weighting to the right (be able to used for the left) + 1, 0, + 1, 0, + 1, 0, + 1, 0 +}; +const float blk4_ver[2][4] = { // weighting to the below (be able to used for the above) + 1, 1, 1, 1, + 0, 0, 0, 0 +}; + + +const float blk4_cur_iblk[4][4] = { // Weighting for current block + 2, 2, 2, 2, + 2, 4, 4, 2, + 2, 4, 4, 2, + 2, 2, 2, 2 +}; +const float blk4_hor_iblk[4][2] = { // weighting to the right (be able to used for the left) + 1, 0, + 2, 0, + 2, 0, + 1, 0 +}; +const float blk4_ver_iblk[2][4] = { // weighting to the below (be able to used for the above) + 1, 2, 2, 1, + 0, 0, 0, 0 +}; + + +const float blk8_cur[8][8] = { // Weighting for current block + 4, 5, 5, 5, 5, 5, 5, 4, + 5, 6, 6, 6, 6, 6, 6, 5, + 5, 6, 6, 7, 7, 6, 6, 5, + 5, 6, 7, 8, 8, 7, 6, 5, + 5, 6, 7, 8, 8, 7, 6, 5, + 5, 6, 6, 7, 7, 6, 6, 5, + 5, 6, 6, 6, 6, 6, 6, 5, + 4, 5, 5, 5, 5, 5, 5, 4 +}; +const float blk8_hor[8][4] = { // for block to the left or right + 2, 1, 1, 0, + 2, 1, 1, 0, + 2, 1, 1, 0, + 3, 2, 1, 0, + 3, 2, 1, 0, + 2, 1, 1, 0, + 2, 1, 1, 0, + 2, 1, 1, 0 +}; +const float blk8_ver[4][8] = { // for block above or below + 2, 2, 2, 3, 3, 2, 2, 2, + 1, 1, 1, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +const float blk8_cur_iblk[8][8] = { // Weighting for current block + 3.0, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.0, + 3.5, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 3.5, + 3.5, 5.0, 5.0, 6.5, 6.5, 5.0, 5.0, 3.5, + 3.5, 5.0, 6.5, 8.0, 8.0, 6.5, 5.0, 3.5, + 3.5, 5.0, 6.5, 8.0, 8.0, 6.5, 5.0, 3.5, + 3.5, 5.0, 5.0, 6.5, 6.5, 5.0, 5.0, 3.5, + 3.5, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 3.5, + 3.0, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.0, +}; + +const float blk8_hor_iblk[8][4] = { // for block to the left or right + 2.5, 1.5, 1.5, 0, + 3.0, 1.5, 1.5, 0, + 3.0, 1.5, 1.5, 0, + 4.5, 3.0, 1.5, 0, + 4.5, 3.0, 1.5, 0, + 3.0, 1.5, 1.5, 0, + 3.0, 1.5, 1.5, 0, + 2.5, 1.5, 1.5, 0, +}; + +const float blk8_ver_iblk[4][8] = { // for block above or below + 2.5, 3.0, 3.0, 4.5, 4.5, 3.0, 3.0, 2.5, + 1.5, 1.5, 1.5, 3.0, 3.0, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const float blk16_cur[16][16] = { // Weighting for current block + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, + 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, + 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, + 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 10, 9, + 9, 10, 11, 12, 12, 13, 13, 13, 13, 13, 13, 12, 12, 11, 10, 9, + 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 13, 12, 11, 10, 9, + 9, 10, 11, 12, 13, 14, 14, 15, 15, 14, 14, 13, 12, 11, 10, 9, + 9, 10, 11, 12, 13, 14, 15, 16, 16, 15, 14, 13, 12, 11, 10, 9, + 9, 10, 11, 12, 13, 14, 15, 16, 16, 15, 14, 13, 12, 11, 10, 9, + 9, 10, 11, 12, 13, 14, 14, 15, 15, 14, 14, 13, 12, 11, 10, 9, + 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 13, 12, 11, 10, 9, + 9, 10, 11, 12, 12, 13, 13, 13, 13, 13, 13, 12, 12, 11, 10, 9, + 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 10, 9, + 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, + 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8 +}; +const float blk16_hor[16][8] = { // for block to the right + 4, 2, 1, 1, 1, 1, 1, 0, + 5, 3, 2, 1, 1, 1, 1, 0, + 6, 4, 3, 2, 1, 1, 1, 0, + 6, 5, 3, 2, 1, 1, 1, 0, + 6, 5, 4, 3, 2, 1, 1, 0, + 6, 5, 4, 3, 2, 1, 1, 0, + 6, 5, 4, 3, 2, 1, 1, 0, + 7, 6, 5, 4, 3, 2, 1, 0, + 7, 6, 5, 4, 3, 2, 1, 0, + 6, 5, 4, 3, 2, 1, 1, 0, + 6, 5, 4, 3, 2, 1, 1, 0, + 6, 5, 4, 3, 2, 1, 1, 0, + 6, 5, 3, 2, 1, 1, 1, 0, + 6, 4, 3, 2, 1, 1, 1, 0, + 5, 3, 2, 1, 1, 1, 1, 0, + 4, 2, 1, 1, 1, 1, 1, 0 +}; +const float blk16_ver[8][16] = { // for block below + 4, 5, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 5, 4, + 2, 3, 4, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 4, 3, 2, + 1, 2, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 3, 3, 2, 1, + 1, 1, 2, 2, 3, 3, 3, 4, 4, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +const float blk32_cur[32][32] = { // Weighting for current block + 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, + 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, + 17, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 18, 17, + 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 18, 17, + 17, 18, 19, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 29, 29, 29, 29, 29, 29, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 31, 31, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 31, 31, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 29, 29, 29, 29, 29, 29, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 20, 19, 18, 17, + 17, 18, 19, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 19, 18, 17, + 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 18, 17, + 17, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 18, 17, + 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, + 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16 +}; +const float blk32_hor[32][16] = { // for block to the left or right + 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, + 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, + 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, + 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, + 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, + 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, + 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, + 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 +}; + +const float blk32_ver[16][32] = { // for block above or below + 8, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 12, 11, 10, 9, 8, + 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 7, 6, + 5, 6, 7, 7, 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 10, 9, 7, 7, 6, 5, + 4, 5, 6, 6, 7, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 9, 8, 7, 6, 6, 5, 4, + 3, 4, 4, 5, 6, 6, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 9, 8, 6, 6, 5, 4, 4, 3, + 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, + 1, 2, 2, 3, 3, 4, 5, 5, 7, 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 7, 5, 5, 4, 3, 3, 2, 2, 1, + 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 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 +}; + +const float blk64_cur[64][64] = { // Weighting for current block + 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, + 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, + 33, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 33, + 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 34, 33, + 33, 34, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 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, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 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, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 60, 61, 61, 61, 61, 61, 61, 60, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 63, 63, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 63, 63, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 60, 61, 61, 61, 61, 61, 61, 60, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 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, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 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, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 36, 35, 34, 33, + 33, 34, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 34, 33, + 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 34, 33, + 33, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 33, + 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, + 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32 +}; + +const float blk64_hor[64][32] = { // for block to the left or right + 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 18, 16, 15, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 19, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 20, 18, 17, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 21, 19, 18, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 22, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 23, 21, 20, 18, 17, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 24, 22, 21, 19, 18, 16, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 25, 23, 22, 20, 19, 17, 16, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 9, 8, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 9, 8, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 25, 23, 22, 20, 19, 17, 16, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 24, 22, 21, 19, 18, 16, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 23, 21, 20, 18, 17, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 22, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 21, 19, 18, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 20, 18, 17, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 19, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 18, 16, 15, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 +}; + +const float blk64_ver[32][64] = { // for block above or below + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, + 13, 14, 15, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 15, 15, 14, 13, + 12, 13, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 14, 13, 12, + 11, 12, 12, 13, 14, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 14, 13, 12, 12, 11, + 10, 11, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 12, 11, 11, 10, + 9, 10, 10, 11, 11, 12, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 13, 13, 12, 11, 11, 10, 10, 9, + 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 12, 11, 10, 10, 9, 9, 8, + 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, + 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, + 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 18, 17, 16, 15, 14, 13, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, + 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, + 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 12, 13, 14, 15, 16, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 16, 15, 14, 13, 12, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, + 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 15, 14, 13, 12, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, + 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, + 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 12, 11, 10, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 10, 9, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 9, 8, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 7, 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 7, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const float blk128_cur[128][128] = { // Weighting for current block +64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 64, +65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 65, +65, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 66, 66, 65, +65, 66, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 67, 66, 65, +65, 66, 67, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 68, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 70, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 72, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 74, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 76, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 78, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 80, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 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, 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, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 84, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 86, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 92, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 125, 125, 125, 125, 124, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 126, 126, 126, 126, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 126, 127, 127, 126, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 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, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 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, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 126, 127, 127, 126, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 126, 126, 126, 126, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 125, 125, 125, 125, 124, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 92, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 86, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 84, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 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, 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, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 80, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 78, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 76, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 74, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 72, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 71, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 71, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 70, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 69, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 69, 68, 67, 66, 65, +65, 66, 67, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 68, 68, 67, 66, 65, +65, 66, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 67, 66, 65, +65, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 66, 66, 65, +65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 65, +64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 64 +}; + +const float blk128_hor[128][64] = { // for block to the left or right +32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +34, 32, 31, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +35, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +36, 34, 33, 31, 30, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +37, 35, 34, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +38, 36, 35, 33, 32, 30, 29, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +39, 37, 36, 34, 33, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +40, 38, 37, 35, 34, 32, 31, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +41, 39, 38, 36, 35, 33, 32, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 9, 8, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, +63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 9, 8, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +41, 39, 38, 36, 35, 33, 32, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +40, 38, 37, 35, 34, 32, 31, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +39, 37, 36, 34, 33, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +38, 36, 35, 33, 32, 30, 29, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +37, 35, 34, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +36, 34, 33, 31, 30, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +35, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +34, 32, 31, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 +}; + +const float blk128_ver[64][128] = { // for block above or below +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, +30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, +29, 30, 31, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 31, 30, 29, +28, 29, 30, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 30, 29, 28, +27, 28, 28, 29, 30, 30, 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, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 30, 29, 28, 28, 27, +26, 27, 27, 28, 29, 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, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 29, 28, 27, 27, 26, +25, 26, 26, 27, 27, 28, 29, 29, 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, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 29, 29, 28, 27, 27, 26, 26, 25, +24, 25, 25, 26, 26, 27, 28, 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, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 28, 27, 26, 26, 25, 25, 24, +23, 24, 24, 25, 25, 26, 26, 27, 28, 28, 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, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 28, 28, 27, 26, 26, 25, 25, 24, 24, 23, +22, 23, 23, 24, 24, 25, 25, 26, 27, 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, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, 23, 22, +21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 27, 27, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, +20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 26, 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, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 26, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, +19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 26, 26, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, +18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 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, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 25, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, +17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 25, 25, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, +16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 24, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, +15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 24, 24, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, +14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, +13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 23, 23, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, +12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 22, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, +11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 22, 22, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, +10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 21, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 21, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, +9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 21, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 21, 21, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, +8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, +7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, +6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, +5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, +4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 18, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, +3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 18, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, +2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 17, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, +1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 17, 17, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, +1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, +1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 15, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 14, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 14, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 13, 13, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 18, 17, 16, 15, 14, 13, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 12, 13, 14, 15, 16, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 16, 15, 14, 13, 12, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 15, 14, 13, 12, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 12, 11, 10, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 10, 9, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 9, 8, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 7, 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 7, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const float blk256_cur[256][256] = { // Weighting for current block + 128, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, +129, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 129, +129, 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 129, +129, 130, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 130, 129, +129, 130, 131, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 136, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 146, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 154, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 156, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 158, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 160, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 162, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 164, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 166, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 168, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 176, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 178, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 190, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 192, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 198, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 202, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 208, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 216, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 218, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 224, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 238, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 240, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 244, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 252, 253, 253, 253, 253, 253, 253, 252, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 254, 254, 254, 254, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 254, 255, 255, 254, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 254, 255, 255, 254, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 254, 254, 254, 254, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 252, 253, 253, 253, 253, 253, 253, 252, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 244, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 240, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 238, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 224, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 218, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 216, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 208, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 207, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 205, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 202, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 198, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 192, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 190, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 178, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 176, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 168, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 166, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 164, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 162, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 160, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 158, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 156, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 154, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +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, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 146, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 136, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 135, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 133, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 133, 132, 131, 130, 129, +129, 130, 131, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 131, 130, 129, +129, 130, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 130, 129, +129, 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 129, +129, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 129, +128, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128 +}; + +const float blk256_hor[256][128] = { // for block to the left or right +64, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +65, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +66, 64, 63, 62, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +67, 65, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +68, 66, 65, 63, 62, 61, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +69, 67, 66, 64, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +70, 68, 67, 65, 64, 62, 61, 60, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +71, 69, 68, 66, 65, 63, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +72, 70, 69, 67, 66, 64, 63, 61, 60, 59, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +73, 71, 70, 68, 67, 65, 64, 62, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 58, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 57, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 56, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 55, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 54, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 53, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 52, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 51, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 50, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 49, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 48, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 46, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 44, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 43, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 42, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 41, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 40, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 39, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 38, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 37, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 36, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 35, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +121, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +122, 120, 119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 34, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +123, 121, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +124, 122, 121, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +125, 123, 122, 120, 119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 124, 123, 121, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 122, 121, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 120, 119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 9, 8, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, +127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 4, 3, 2, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 10, 9, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 11, 9, 8, 6, 5, 4, 2, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 11, 10, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 5, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 9, 8, 7, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 16, 15, 14, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 19, 18, 17, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 20, 19, 18, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 21, 20, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 22, 21, 20, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 23, 22, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 27, 26, 25, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 28, 27, 26, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 32, 31, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 121, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 123, 122, 120, 119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 33, 32, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 125, 124, 122, 121, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +126, 124, 123, 121, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +125, 123, 122, 120, 119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +124, 122, 121, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 35, 34, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +123, 121, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +122, 120, 119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 36, 35, 34, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +121, 119, 118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 35, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +119, 117, 116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +118, 116, 115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 36, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +116, 114, 113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 39, 38, 37, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +115, 113, 112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +114, 112, 111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 38, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +113, 111, 110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +112, 110, 109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 41, 40, 39, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +111, 109, 108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +110, 108, 107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41, 40, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +109, 107, 106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +108, 106, 105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 43, 42, 41, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +107, 105, 104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +106, 104, 103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 44, 43, 42, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +105, 103, 102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +104, 102, 101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 43, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +103, 101, 100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +102, 100, 99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 46, 45, 44, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +101, 99, 98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +100, 98, 97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 47, 46, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +99, 97, 96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +98, 96, 95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 46, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +97, 95, 94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +96, 94, 93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +95, 93, 92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +94, 92, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 50, 49, 48, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +93, 91, 90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +92, 90, 89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 51, 50, 49, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +90, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 52, 51, 50, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +89, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 53, 52, 51, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +87, 85, 84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 54, 53, 52, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +84, 82, 81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54, 53, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +83, 81, 80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 56, 55, 54, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +81, 79, 78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +80, 78, 77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 57, 56, 55, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +79, 77, 76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +78, 76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 56, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +77, 75, 74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +76, 74, 73, 71, 70, 68, 67, 65, 64, 62, 61, 59, 58, 57, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +74, 72, 71, 69, 68, 66, 65, 63, 62, 60, 59, 58, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +73, 71, 70, 68, 67, 65, 64, 62, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +72, 70, 69, 67, 66, 64, 63, 61, 60, 59, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +71, 69, 68, 66, 65, 63, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +70, 68, 67, 65, 64, 62, 61, 60, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +69, 67, 66, 64, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +68, 66, 65, 63, 62, 61, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +67, 65, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +66, 64, 63, 62, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +65, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, +64, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 +}; + +const float blk256_ver[128][256] = { // for block to the left or right +64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, +61, 62, 63, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 63, 63, 62, 61, +60, 61, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 62, 61, 60, +59, 60, 60, 61, 62, 62, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 62, 62, 61, 60, 60, 59, +58, 59, 59, 60, 61, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 61, 60, 59, 59, 58, +57, 58, 58, 59, 59, 60, 61, 61, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 61, 61, 60, 59, 59, 58, 58, 57, +56, 57, 57, 58, 58, 59, 60, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 60, 59, 58, 58, 57, 57, 56, +55, 56, 56, 57, 57, 58, 58, 59, 60, 60, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 60, 60, 59, 58, 58, 57, 57, 56, 56, 55, +54, 55, 55, 56, 56, 57, 57, 58, 59, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 59, 58, 57, 57, 56, 56, 55, 55, 54, +53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 59, 59, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 59, 59, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, +52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 58, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 58, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, +51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 58, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 58, 58, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, +50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 57, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 57, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, +49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 57, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 57, 57, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, +48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, +47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 56, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 56, 56, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, +46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 55, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, +45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 55, 55, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, +44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 54, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 54, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, +43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 54, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 54, 54, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, +42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 53, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, +41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 53, 53, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, +40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 52, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, +39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 52, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 52, 52, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, +38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 51, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 51, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, +37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 51, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 51, 51, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, +36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, +35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 50, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 50, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, +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, 47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 49, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, +33, 34, 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, 47, 48, 49, 49, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 49, 49, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, +32, 33, 33, 34, 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, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 48, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, +31, 32, 32, 33, 33, 34, 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, 48, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 48, 48, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, +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, 43, 44, 44, 45, 45, 46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 47, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, +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, 43, 44, 44, 45, 45, 46, 47, 47, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 47, 47, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, +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, 43, 44, 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, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 46, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, +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, 43, 44, 44, 45, 46, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 46, 46, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, +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, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, +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, 43, 44, 45, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 45, 45, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, +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, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 44, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, +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, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 44, 44, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, +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, 43, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 43, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, +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, 43, 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 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, 85, 85, 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, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 43, 43, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, +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, 42, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 42, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, +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, 42, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 42, 42, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, +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, 41, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 82, 82, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 41, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, +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, 41, 41, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 41, 41, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, +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, 40, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 40, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, +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, 40, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 40, 40, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, +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, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 39, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, +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, 39, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 39, 39, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, +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, 38, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 76, 76, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 38, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, +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, 38, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 38, 38, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, +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, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 37, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, +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, 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, 37, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 37, 37, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, +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, 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, 36, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 72, 72, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 36, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, +7, 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, 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, 36, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 36, 36, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, +6, 7, 7, 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, 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, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 70, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 35, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, +5, 6, 6, 7, 7, 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, 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, 35, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 35, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, +4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 34, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 34, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, +3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 34, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 34, 34, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, +2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 33, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, +1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 33, 33, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, +1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, +1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 32, 32, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 31, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 31, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 31, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 30, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 30, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 30, 30, 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, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 30, 30, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 29, 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, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 29, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 29, 29, 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, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 29, 29, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, 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, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, 28, 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, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 28, 28, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 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, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 27, 27, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 26, 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, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 26, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 26, 26, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 25, 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, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 25, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 23, 24, 25, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 25, 25, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 24, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 24, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 22, 23, 24, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 24, 24, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 22, 23, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 23, 23, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 22, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 22, 22, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 21, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 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, 21, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 21, 21, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 18, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 18, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 17, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 17, 17, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 15, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 14, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 14, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 13, 13, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 18, 17, 16, 15, 14, 13, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 12, 13, 14, 15, 16, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 16, 15, 14, 13, 12, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 15, 14, 13, 12, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 12, 11, 10, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 10, 9, 7, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 9, 8, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 7, 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 7, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +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, 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, 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, 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, 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 +}; + +#endif // STRUCTN_H diff --git a/Interframe EZBC/TempSub/inc/unix_pc.h b/Interframe EZBC/TempSub/inc/unix_pc.h new file mode 100644 index 0000000..08d2510 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/unix_pc.h @@ -0,0 +1 @@ +U32 exchange_4byte_order( U32 data ); diff --git a/Interframe EZBC/TempSub/inc/util_filtering.h b/Interframe EZBC/TempSub/inc/util_filtering.h new file mode 100644 index 0000000..adf0aa0 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/util_filtering.h @@ -0,0 +1,37 @@ +#ifndef UTIL_FILTERING_H +#define UTIL_FILTERING_H + +#define ANAL 0 +#define SYN 1 + +extern const float static_prequant_weight_high[]; +extern const float static_prequant_weight_low[]; + +extern const float prequant_weight_high[]; +extern const float prequant_weight_low[]; +extern const float copycomp_weight_high[]; +extern const float copycomp_weight_low[]; + + +int next_roundtrip_index( int curr_i, float *array, int length, int *direction ); +void extend_line( float *orig_line, int orig_len, int margin, + int algorithm, int flag, float *new_line ); + +void line_convolve( float *input, float *extension, int length, float *fco, + int flength, int analsyn_flag, float *out ); +void interpolate_filter( ); +void temporal_filter( ); + +float FIRinterpolate( float fx, float fy, float *frame, int length, int hor, + int ver ); + +float interpolate( float fx, float fy, float *frame, int hor, int ver, + int type ); + +void Interpolate_frame( float *frame, int hor, int ver, float **upframe, + int *uph, int *upv, int subpel ); + +void Interpolate_frame2( float *frame, int hor, int ver, float **upframe, float *upsamp_x, + int subpel ); + +#endif // UTIL_FILTERING_H diff --git a/Interframe EZBC/TempSub/inc/zconf.h b/Interframe EZBC/TempSub/inc/zconf.h new file mode 100644 index 0000000..b849dbb --- /dev/null +++ b/Interframe EZBC/TempSub/inc/zconf.h @@ -0,0 +1,326 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2004 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/Interframe EZBC/TempSub/inc/zlib.h b/Interframe EZBC/TempSub/inc/zlib.h new file mode 100644 index 0000000..e067b12 --- /dev/null +++ b/Interframe EZBC/TempSub/inc/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.2, October 3rd, 2004 + + Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.2" +#define ZLIB_VERNUM 0x1220 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/Interframe EZBC/TempSub/src/anal.c b/Interframe EZBC/TempSub/src/anal.c new file mode 100644 index 0000000..4769816 --- /dev/null +++ b/Interframe EZBC/TempSub/src/anal.c @@ -0,0 +1,1679 @@ +#include +#include +#include +#include +#include +#define EXTERN extern +#include "rasterfile.h" +#include "basic.h" +#include "structN.h" +#include "coderN.h" +#include "analsyn.h" +#include "ioN.h" +#include "miscN.h" +#include "memoryN.h" +#include "chrom.h" +#include "dwt_bitplane_enc.h" +#include "ezbc_enc_3d.h" +#include "bmeN.h" +#include "mvcodingN.h" +#include "pstatN.h" +#include "util_filtering.h" +#include + +#include "directional_iblock.h" +#include "obmc_varblk.h" +#include "layer_mv.h" + +#define LAMBDA_SWITCH_POINT 208 +#define LAMBDA_SWITCH_POINT2 64 + +EXTERN unsigned long int *gop_mv; + +int simul_alert; + +float image_entropy(float *image, int hor, int ver){ + int ii,jj,k; + int ss,tt; + float *tem; + int cnt; + double p; + float H; + + tem = (float *)getarray( hor*ver,sizeof(float),"tem" ); + + for(tt = 1;tt < ver-1; tt ++) + for(ss = 1;ss < hor-1; ss ++) + tem[tt*hor + ss] = (image[(tt-1)*hor + ss] + image[(tt+1)*hor + ss] + image[tt*hor + (ss-1)] + image[tt*hor + (ss+1)]) /4; + + H = 0; + + for(ii = 0;ii < 255; ii ++){ + for(jj = 0;jj < 255; jj ++){ + cnt = 0; + for(tt = 0;tt < ver; tt ++){ + for(ss = 0;ss < hor; ss ++){ + if( floor(image[tt*hor + ss]) == ii && floor(tem[tt*hor + ss]) == jj ) + cnt ++; + } + } + + if(cnt > 0){ + p = ((double)cnt)/((double)(ver*hor)); + H = H - p * log((double)p)/log((double)2); + } + + } + } + + free(tem); + return H; +} + +void save_enc_status(videoinfo *info){ + int i, j, xblk, yblk, hor, ver, bigGOP, rel_s_level; + int num_mv_bigGOP, num_mv_GOP, num_pyrFrs_bigGOP, GOPsz;//, num_scene_change; + + num_mv_bigGOP = 1; // 4, 11, 26, 57, ... + num_mv_GOP = 1; // 4, 9, 18, 35, ... + num_pyrFrs_bigGOP = 1; // 2, 4, 12, 27, ... + + // calculation of base indices for MV-sets and frames + for( i = info->tPyrLev-1; i >= 0; i-- ){ + num_pyrFrs_bigGOP += info->bigGOP / (int)(pow ( (float)2, (int)(i + 1))); + num_mv_bigGOP += info->bigGOP / (int)(pow ( (float)2, (int)i)); + num_mv_GOP += info->GOPsz / (int)(pow ( (float)2, (int)i)) + 1; + } + +//enc MV sets + for( j = 1; j <= num_mv_bigGOP; j++ ) + if( yfmv_bigGOP[j] != NULL ){ + free_vector(buff_yfmv_bigGOP[j], *info); + mv_copy(yfmv_bigGOP[j], buff_yfmv_bigGOP[j], *info); + } + + for( j = 1; j <= num_mv_GOP; j++ ) + if( yfmv[j] != NULL ){ + free_vector(buff_yfmv[j], *info); + mv_copy(yfmv[j], buff_yfmv[j], *info); + } + + + if( tmp_yfmv != NULL ){ + free_vector(buff_tmp_yfmv, *info); + mv_copy(tmp_yfmv, buff_tmp_yfmv, *info); + } + + for( j = 0; j < num_mv_bigGOP; j++ ) + buff_mv_ref_bigGOP[j] = mv_ref_bigGOP[j]; + +//Simul dec MV sets + for( j = 0; j < num_mv_GOP; j++ ) + buff_mv_ref[j] = mv_ref[j]; + + for( j = 1; j <= num_mv_GOP; j++ ) + if( dec_yfmv_bigGOP[j] != NULL ){ + free_vector(buff_dec_yfmv_bigGOP[j], *info); + mv_copy(dec_yfmv_bigGOP[j], buff_dec_yfmv_bigGOP[j], *info); + } + + for( j = 1; j <= num_mv_GOP; j++ ) + if( dec_yfmv[j] != NULL ){ + free_vector(buff_dec_yfmv[j], *info); + mv_copy(dec_yfmv[j], buff_dec_yfmv[j], *info); + } + + for( j = 0; j < num_mv_GOP; j++ ) + buff_dec_mv_ref_bigGOP[j] = dec_mv_ref_bigGOP[j]; + +//enc frame sets + copyframe(&end_of_lastGOP, &buff_end_of_lastGOP, *info); + + if( info->tPyrLev >= 1 ){ + for(i = 0; i < num_pyrFrs_bigGOP; i++) + copyframe(&pyrFrs_bigGOP[i], &buff_pyrFrs_bigGOP[i], *info); + + for(i = 0; i < info->GOPsz; i++) + copyframe(&pyrFrs[i], &buff_pyrFrs[i], *info); + + for( i = 0; i < info->tPyrLev; i++ ) + copyframe(&pyrFrs_first[i], &buff_pyrFrs_first[i], *info); + + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + for(j = 0; j < bigGOP; j++){ + copyframe( &pyrTemp[i][j], &buff_pyrTemp[i][j], *info ); + } + bigGOP /= 2; + } + +//dec frame sets + for(i = 0; i < num_pyrFrs_bigGOP; i++) + copyframe( &dec_pyrFrs_bigGOP[i], &buff_dec_pyrFrs_bigGOP[i], *info ); + + for(i = 0; i < info->GOPsz; i++) + copyframe( &dec_pyrFrs[i], &buff_dec_pyrFrs[i], *info ); + + for( i = 0; i < info->tPyrLev; i++ ) + copyframe( &dec_pyrFrs_first[i], &buff_dec_pyrFrs_first[i], *info ); + + GOPsz = info->GOPsz; + for( i = 0; i < info->tPyrLev; i++ ) { + for(j = 0; j < GOPsz; j++){ + copyframe( &dec_pyrTemp[i][j], &buff_dec_pyrTemp[i][j], *info ); + } + GOPsz /= 2; + } + +//scene change info + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + for( j = 0; j <= bigGOP ; j++ ){ + buff_scene_change[i][j] = scene_change[i][j]; + } + bigGOP /= 2; + } + + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + GOPsz += 1; + for( j = 0; j < GOPsz ; j++ ){ + buff_dec_scene_change[i][j] = dec_scene_change[i][j]; + } + bigGOP /= 2; + } + + }else{ + assert(0); + } + +} + +void resume_enc_status(videoinfo *info){ + int i, j, xblk, yblk, hor, ver, bigGOP, rel_s_level; + int num_mv_bigGOP, num_mv_GOP, num_pyrFrs_bigGOP, GOPsz;//, num_scene_change; + + num_mv_bigGOP = 1; // 4, 11, 26, 57, ... + num_mv_GOP = 1; // 4, 9, 18, 35, ... + num_pyrFrs_bigGOP = 1; // 2, 4, 12, 27, ... + + // calculation of base indices for MV-sets and frames + for( i = info->tPyrLev-1; i >= 0; i-- ){ + num_pyrFrs_bigGOP += info->bigGOP / (int)(pow ( (float)2, (int)(i + 1))); + num_mv_bigGOP += info->bigGOP / (int)(pow ( (float)2, (int)i)); + num_mv_GOP += info->GOPsz / (int)(pow ( (float)2, (int)i)) + 1; + } + +//enc MV sets + for( j = 1; j <= num_mv_bigGOP; j++ ) + if( yfmv_bigGOP[j] != NULL ){ + free_vector(yfmv_bigGOP[j], *info); + mv_copy(buff_yfmv_bigGOP[j], yfmv_bigGOP[j], *info); + } + + for( j = 1; j <= num_mv_GOP; j++ ) + if( yfmv[j] != NULL ){ + free_vector(yfmv[j], *info); + mv_copy(buff_yfmv[j], yfmv[j], *info); + } + + + if( tmp_yfmv != NULL ){ + free_vector(tmp_yfmv, *info); + mv_copy(buff_tmp_yfmv, tmp_yfmv, *info); + } + + for( j = 0; j < num_mv_bigGOP; j++ ) + mv_ref_bigGOP[j] = buff_mv_ref_bigGOP[j]; + +// printf("\nhere!\n"); + +//Simul dec MV sets + for( j = 0; j < num_mv_GOP; j++ ) + mv_ref[j] = buff_mv_ref[j]; + + for( j = 1; j <= num_mv_GOP; j++ ) + if( dec_yfmv_bigGOP[j] != NULL ){ + free_vector(dec_yfmv_bigGOP[j], *info); + mv_copy(buff_dec_yfmv_bigGOP[j], dec_yfmv_bigGOP[j], *info); + } + + for( j = 1; j <= num_mv_GOP; j++ ) + if( dec_yfmv[j] != NULL ){ + free_vector(dec_yfmv[j], *info); + mv_copy(buff_dec_yfmv[j], dec_yfmv[j], *info); + } + + for( j = 0; j < num_mv_GOP; j++ ) + dec_mv_ref_bigGOP[j] = buff_dec_mv_ref_bigGOP[j]; + +//enc frame sets + copyframe(&buff_end_of_lastGOP, &end_of_lastGOP, *info); + + if( info->tPyrLev >= 1 ){ + for(i = 0; i < num_pyrFrs_bigGOP; i++) + copyframe(&buff_pyrFrs_bigGOP[i], &pyrFrs_bigGOP[i], *info); + + for(i = 0; i < info->GOPsz; i++) + copyframe(&buff_pyrFrs[i], &pyrFrs[i], *info); + + for( i = 0; i < info->tPyrLev; i++ ) + copyframe(&buff_pyrFrs_first[i], &pyrFrs_first[i], *info); + + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + for(j = 0; j < bigGOP; j++){ + copyframe( &buff_pyrTemp[i][j], &pyrTemp[i][j], *info ); + } + bigGOP /= 2; + } + +//dec frame sets + for(i = 0; i < num_pyrFrs_bigGOP; i++) + copyframe( &buff_dec_pyrFrs_bigGOP[i], &dec_pyrFrs_bigGOP[i], *info ); + + for(i = 0; i < info->GOPsz; i++) + copyframe( &buff_dec_pyrFrs[i], &dec_pyrFrs[i], *info ); + + for( i = 0; i < info->tPyrLev; i++ ) + copyframe( &buff_dec_pyrFrs_first[i], &dec_pyrFrs_first[i], *info ); + + GOPsz = info->GOPsz; + for( i = 0; i < info->tPyrLev; i++ ) { + for(j = 0; j < GOPsz; j++){ + copyframe( &buff_dec_pyrTemp[i][j], &dec_pyrTemp[i][j], *info ); + } + GOPsz /= 2; + } + +//scene change info + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + for( j = 0; j <= bigGOP ; j++ ){ + scene_change[i][j] = buff_scene_change[i][j]; + } + bigGOP /= 2; + } + + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + GOPsz += 1; + for( j = 0; j < GOPsz ; j++ ){ + dec_scene_change[i][j] = buff_dec_scene_change[i][j]; + } + bigGOP /= 2; + } + + }else{ + assert(0); + } + +} + +//Added on 09.10.2017 +void lambda_revise2(float *lambda, int t_level, float add_num){ + *lambda += add_num; + + if( *lambda <= 1 ) + *lambda -= add_num; +} + +void anal_file_copy(char *dest_name, char *source_name){ + + FILE * file1,*file2; + //使用二进制模式打开文件 + file1 = fopen(source_name,"rb"); // rb 表示读 + file2 = fopen(dest_name,"wb"); // wb 表示写 + if(!file1) + { + printf("文件%s打开失败!",source_name); + return; + } + char c; + int index = 0; + fseek(file1,0,SEEK_END); //将源文件定位到文件尾 + int length = ftell(file1); //获取当前位置,即文件大小(按字节算) + //printf("%d\n",length); //此处可输出字节数,以进行验证 + if(!length) + return; + while(!fseek(file1,index,SEEK_SET)) //循环定位文件,向后移动一个字节 + { + fread(&c,1,1,file1); //从源文件读取一个字节的内容到 中间变量 c + fwrite(&c,1,1,file2); //将这个字节的内容写入目标文件 + if(index == length - 1) //如果已经读到文件尾,则跳出循环 + { + break; + } + index++; //往后推进一个字节 + } + fclose(file1); //关闭源文件 + fclose(file2); //关闭目标文件 +} + + +// use left_scene and right_scene for connection checking 使用左右场景进行连接检查 +void +directional_iblock_analysis_with_OBMC( YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int t_level, int remaining_frs, videoinfo info, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray, + enum FLAG left_scene, enum FLAG right_scene) +{ + int x, y, X, Y, yhor, yver; + int xnum, ynum, xblk, yblk; + vector_ptr fmv; + + // left scene change and right scene change + // this is a intra coded frame + if( left_scene == YES && right_scene == YES ) return; + + yhor = info.ywidth; + yver = info.yheight; + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + + if (left_scene == NO ) + fmv = fmv2; + else if ( right_scene == NO ) + fmv = fmv3; + else + assert(0); // validity checking + + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) { // 逐个块进行 + // fmv is non-NULL quad-tree root for current high temporal frame H1 + // fmv[Y * xnum + X] is current Macro-block + rec_directional_iblock_analysis_with_OBMC( &fmv[Y * xnum + X], x, y, xblk, yblk, yhor, yver, + L1, H1, H0, fr1, fr2, fr3, + fmv1, fmv2, fmv3, mv_ref1, mv_ref2, mv_ref3, + t_level, remaining_frs, info, fmv, + frameMEinfo, varblkarray); + } + } +} + + +/* + * temporal_analysis + */ + +void +temporal_analysis( YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int level, int remaining_frs, videoinfo info ) + /* fr0--previous, fr1--current(reference), fr2--next */ +{ + int yhor, yver, chor, cver; + float *ymvx1, *ymvy1, *ymvx2, *ymvy2, *ymvx3, *ymvy3; + float *cmvx1, *cmvy1, *cmvx2, *cmvy2, *cmvx3, *cmvy3; + float *ymvx1_int, *ymvy1_int, *ymvx2_int, *ymvy2_int, *ymvx3_int, *ymvy3_int; + float *cmvx1_int, *cmvy1_int, *cmvx2_int, *cmvy2_int, *cmvx3_int, *cmvy3_int; + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + blockmv2pixelmv( fmv1, &ymvx1, &ymvy1, &cmvx1, &cmvy1, CONNECTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2, &ymvy2, &cmvx2, &cmvy2, CONNECTED, info, level ); + blockmv2pixelmv( fmv3, &ymvx3, &ymvy3, &cmvx3, &cmvy3, CONNECTED, info, level ); + blockmv2pixelmv( fmv1, &ymvx1_int, &ymvy1_int, &cmvx1_int, &cmvy1_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2_int, &ymvy2_int, &cmvx2_int, &cmvy2_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv3, &ymvx3_int, &ymvy3_int, &cmvx3_int, &cmvy3_int, PREDICTED, info, level ); + + /* Y, U, V */ + mc_analysis( L1->Y, H1->Y, H0->Y, fr1->Y, fr2->Y, fr3->Y, + ymvx1, ymvy1, ymvx2, ymvy2, ymvx3, ymvy3, + ymvx1_int, ymvy1_int, ymvx2_int, ymvy2_int, + ymvx3_int, ymvy3_int, mv_ref1, mv_ref2, mv_ref3, + yhor, yver, level, remaining_frs, info ); + + if( info.cwidth && info.cheight ) + { + mc_analysis( L1->U, H1->U, H0->U, fr1->U, fr2->U, fr3->U, + cmvx1, cmvy1, cmvx2, cmvy2, cmvx3, cmvy3, + cmvx1_int, cmvy1_int, cmvx2_int, cmvy2_int, + cmvx3_int, cmvy3_int, mv_ref1, mv_ref2, mv_ref3, + chor, cver, level, remaining_frs, info ); + mc_analysis( L1->V, H1->V, H0->V, fr1->V, fr2->V, fr3->V, + cmvx1, cmvy1, cmvx2, cmvy2, cmvx3, cmvy3, + cmvx1_int, cmvy1_int, cmvx2_int, cmvy2_int, + cmvx3_int, cmvy3_int, mv_ref1, mv_ref2, mv_ref3, + chor, cver, level, remaining_frs, info ); + } + + free( ymvx1 ); + free( ymvy1 ); + free( cmvx1 ); + free( cmvy1 ); + + free( ymvx2 ); + free( ymvy2 ); + free( cmvx2 ); + free( cmvy2 ); + + free( ymvx3 ); + free( ymvy3 ); + free( cmvx3 ); + free( cmvy3 ); + + free( ymvx1_int ); + free( ymvy1_int ); + free( cmvx1_int ); + free( cmvy1_int ); + + free( ymvx2_int ); + free( ymvy2_int ); + free( cmvx2_int ); + free( cmvy2_int ); + + free( ymvx3_int ); + free( ymvy3_int ); + free( cmvx3_int ); + free( cmvy3_int ); +} + + +/* + * temporal_analysis_with_OBMC 带obmc的时域分解 + */ + +void +temporal_analysis_with_OBMC( YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int level, int remaining_frs, videoinfo info, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray, + enum FLAG left_scene, enum FLAG right_scene) + /* fr0--previous, fr1--current(reference), fr2--next */ +{ + int yhor, yver, chor, cver; + float *ymvx1, *ymvy1, *ymvx2, *ymvy2, *ymvx3, *ymvy3; + float *cmvx1, *cmvy1, *cmvx2, *cmvy2, *cmvx3, *cmvy3; + float *ymvx1_int, *ymvy1_int, *ymvx2_int, *ymvy2_int, *ymvx3_int, *ymvy3_int; + float *cmvx1_int, *cmvy1_int, *cmvx2_int, *cmvy2_int, *cmvx3_int, *cmvy3_int; + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + // connected使用预测加更新 predicted只使用预测,不更新 + blockmv2pixelmv( fmv1, &ymvx1, &ymvy1, &cmvx1, &cmvy1, CONNECTED, info, level );// 块mv转为像素mv,其中色度直接复用的亮度mv + blockmv2pixelmv( fmv2, &ymvx2, &ymvy2, &cmvx2, &cmvy2, CONNECTED, info, level ); + blockmv2pixelmv( fmv3, &ymvx3, &ymvy3, &cmvx3, &cmvy3, CONNECTED, info, level ); + blockmv2pixelmv( fmv1, &ymvx1_int, &ymvy1_int, &cmvx1_int, &cmvy1_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2_int, &ymvy2_int, &cmvx2_int, &cmvy2_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv3, &ymvx3_int, &ymvy3_int, &cmvx3_int, &cmvy3_int, PREDICTED, info, level ); + + // Y componet MCTF analysis with OBMC Y分量MCTF分解 + mc_analysis_with_OBMC( L1->Y, H1->Y, H0->Y, fr1->Y, fr2->Y, fr3->Y, + ymvx1, ymvy1, ymvx2, ymvy2, ymvx3, ymvy3, + ymvx1_int, ymvy1_int, ymvx2_int, ymvy2_int, + ymvx3_int, ymvy3_int, mv_ref1, mv_ref2, mv_ref3, + yhor, yver, level, remaining_frs, info, frameMEinfo, varblkarray, 0, + left_scene, right_scene, 0); + + if( info.cwidth && info.cheight ) + { + mc_analysis_with_OBMC( L1->U, H1->U, H0->U, fr1->U, fr2->U, fr3->U, + cmvx1, cmvy1, cmvx2, cmvy2, cmvx3, cmvy3, + cmvx1_int, cmvy1_int, cmvx2_int, cmvy2_int, + cmvx3_int, cmvy3_int, mv_ref1, mv_ref2, mv_ref3, + chor, cver, level, remaining_frs, info, frameMEinfo, varblkarray, 1, + left_scene, right_scene, 1); + mc_analysis_with_OBMC( L1->V, H1->V, H0->V, fr1->V, fr2->V, fr3->V, + cmvx1, cmvy1, cmvx2, cmvy2, cmvx3, cmvy3, + cmvx1_int, cmvy1_int, cmvx2_int, cmvy2_int, + cmvx3_int, cmvy3_int, mv_ref1, mv_ref2, mv_ref3, + chor, cver, level, remaining_frs, info, frameMEinfo, varblkarray, 1, + left_scene, right_scene, 0); + } + + free( ymvx1 ); + free( ymvy1 ); + free( cmvx1 ); + free( cmvy1 ); + + free( ymvx2 ); + free( ymvy2 ); + free( cmvx2 ); + free( cmvy2 ); + + free( ymvx3 ); + free( ymvy3 ); + free( cmvx3 ); + free( cmvy3 ); + + free( ymvx1_int ); + free( ymvy1_int ); + free( cmvx1_int ); + free( cmvy1_int ); + + free( ymvx2_int ); + free( ymvy2_int ); + free( cmvx2_int ); + free( cmvy2_int ); + + free( ymvx3_int ); + free( ymvy3_int ); + free( cmvx3_int ); + free( cmvy3_int ); +} + + +// by Yongjun Wu +// In decoder mv_ref0, mv_ref1 and mv_ref2 (whether it's NULL ) can exactly indicate the scene change +// information and the existence of motion vectors in left and/or rigth directions. +// However, in encoder mv_ref1, mv_ref2 and mv_ref3 can not exactly indicate the information. +// Sometimes scene is changed but mv_refi is still not NULL. +// hence we have to use the correpsonding scene_change[][] to indicate the information. + + +/*********************************************************************/ +/* */ +/* analscheme3 进行一个gop的时域分解,完成所有次数的时域分解 */ +/* */ +/*********************************************************************/ +void +analscheme3( int curr, videoinfo info, enum FLAG first_GOP, + enum FLAG Level_change, int remaining_frs, int simul_enc, float *upframe1, float *upframe2, float *upsamp_x ) +{ + int i, j, k, tPyrLev, dist, yhor, yver, chor, cver; + int num_pyrFrs_bigGOP, bigGOP, GOPsz, half_bigGOP, half_GOPsz; + int leaving_frs, eff_GOPsz; // leaving_frs表示是否有前面bigGOP剩余的已经处理的帧 + + int ind_mv_bigGOP[20], ind_mv_GOP[20], ind_pyrFrs_bigGOP[20]; + +#ifdef DEBUG_BLOCK_MODE_MV_INFO + int curr_mv_index, frame_type; +#endif + + enum FLAG *sc_ref1, *sc_ref2; // 是否参考标志1、2 + vector_ptr mv_ref1, mv_ref2, mv_ref3, mv_ref4; + YUVimage *fr_cur, *fr_ref1, *fr_ref2;// 当前帧、参考帧1、2 + int total_varblk; + + float buff_lambda; + + printf("remaining_frs = %d\n",remaining_frs); + + // scene_change[i][j] shows whether frame i has scene change compared + // with its previous frame i-1, so whether we can do mctf depends on + // entries at odd-index places. + temporal_filter(); // 初始化系数 + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + tPyrLev = info.tPyrLev; + bigGOP = info.bigGOP; // 31, 15, 7, 3 + half_bigGOP = info.bigGOP / 2; // 15, 7, 3, 1 + GOPsz = info.GOPsz; // 16, 8, 4, 2 + half_GOPsz = info.GOPsz / 2; // 8, 4, 2, 1 + eff_GOPsz = info.eff_GOPsz; // effective GOP size (cmp. encoderN.c) + dist = 1; // frame difference of a pair of frames 或 temporal distance between fr1 and fr0 + + // by Yongjun Wu + // the starting points for the motion vector set in each level of bigGOP (size 31)在每一层bigGOP中,为运动向量集的起始点 + // An example of 4 level MCTF: + // level 3 starts from 1 and ends at 3, level 2 starts from 4 and ends at 10 + // level 1 starts from 11 and ends at 25, level 0 starts from 26 and ends at 56 + + ind_mv_bigGOP [tPyrLev] = 0; // 1, 4, 11, 26, ... 这几个设置与encodern.c 1334处公式 设置相同 + + // by Yongjun Wu + // MV indices for transmission, e.g. for total tPyrLev = 4: + // Level 0: 18-34; Level 1: 9-17; Level 2: 4-8; Level 3: 1-3 + // here the first set of motion vectors in each level, + // i.e. motion vector sets 1, 4, 9, 18 come from previous GOP (not bigGOP) 运动向量1,、4/9/18来自前面的gop + ind_mv_GOP [tPyrLev] = -1; // 1, 4, 9, 18, ... + + // indices of highpass frames in each temporal level + ind_pyrFrs_bigGOP[tPyrLev] = 1; // 1, 2, 5, 12, ... + + // lowpass of last level plus number of all highpass frames + num_pyrFrs_bigGOP = 1; // 2, 5, 12, 27, ... + + // calculation of base indices for MV-sets and frames: 计算这几个mv的每一层时域滤波的索引 + for( i = tPyrLev - 1; i >= 0; i-- ){ + ind_mv_bigGOP[i] = ind_mv_bigGOP[i+1] + bigGOP / (int)(pow (2, i+1)); // + ind_mv_GOP [i] = 1+ ind_mv_GOP[i+1] + GOPsz / (int)(pow (2, i+1)); + ind_pyrFrs_bigGOP[i] = ind_pyrFrs_bigGOP[i+1] + half_bigGOP / (int)(pow (2, i+1)); + num_pyrFrs_bigGOP += half_bigGOP / (int)(pow (2, i)); + } + + /////////////////////////////////// + printf("curr = %d\n\n",curr); +/* + if(curr >= 0 && curr <= LAMBDA_SWITCH_POINT2){ + for(i = 0; i < tPyrLev; i ++) + lambda_revise2(&info.lambda[i],i,-1); + } +*/ +/* + if(curr >= LAMBDA_SWITCH_POINT){ + for(i = 0; i < tPyrLev; i ++) + lambda_revise2(&info.lambda[i],i,5); + } +*/ /////////////////////////////////// + + /*************** + Base Settings + ****************/ + // 如果不是first_GOP,就会将上一个bigGOP的后半部分复制到当前的bigGOP内 + if( first_GOP == YES ) // *** first GOP *** + { + leaving_frs = 0; + simul_alert = 0; + + // initialize scene changes TR 20041302 + bigGOP = info.bigGOP; + for( i = 0; i < tPyrLev; i++ ) // 设置默认的场景改变,每一层的第一帧默认场景改变,后续帧默认场景不改变 + { + scene_change[i][0] = YES; // 第一帧默认场景改变,后续帧默认场景不改变 + for( j = 1; j <= bigGOP; j++ ) { + scene_change[i][j] = NO; // video_scene_change[curr + j]; + } + bigGOP /= 2; + + free_vector( yfmv_bigGOP[ind_mv_bigGOP[i]], info ); // the first set of motion vector does not exist always in the first GOP + mv_ref_bigGOP[ind_mv_bigGOP[i]] = NULL; // the first set of motion vector does not exist always in the first GOP + } + bigGOP = info.bigGOP; + + // scene_change_help / tmp_yfmv initialization + scene_change_help = YES; + free_vector(tmp_yfmv, info); + mv_ref_bigGOP[1] = NULL; // the first set of motion vector does not exist always in the first GOP + + } + else // *** next GOPs *** + { + bigGOP = info.bigGOP; + leaving_frs = half_bigGOP; // = info.bigGOP - info.GOPsz; + // no complete GOP available, thus adapt indices for next (smaller) GOP + + for( i = 0; i < tPyrLev - 1; i++ ){ + + scene_change[i][0] = YES; // do not transmit MVs 场景改变则不传输mv。如果...大于一个阈值,就会判为场景改变。 + + // get scene_change information from last GOP 从上一个gop获取场景改变信息。下面两个for使得gop之间的scene_change连续 + for( j = 1; j < leaving_frs; j++ ) + { + scene_change[i][j] = scene_change[i][j + GOPsz]; + // printf( "scene_change[%d][%d] = scene_change[%d][%d + GOPsz %d = %d];\n",i,j,i,j,GOPsz,j+GOPsz ); + } + for( j = leaving_frs; j <= bigGOP; j++ ) + { // 后半个gop的场景改变设为不改变 + scene_change[i][j] = NO; // video_scene_change[curr + j]; + } + + // put last processed L frames to correct position by Yongjun Wu 下面的if for把前面的gop的产生的高低频帧存起来 +// if(simul_alert == 0) + copyframe( &pyrFrs_first[i], &pyrTemp[i + 1][leaving_frs / 2 - 1], info ); + // copy last calculated highpass frames to the beginning of pyrFrs_bigGOP + for( j = 0; j < leaving_frs / 2; j++ ){ // (30 - 16) Frames +// if(simul_alert == 0) + copyframe( &pyrFrs_bigGOP[j + half_GOPsz + ind_pyrFrs_bigGOP[i]], &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], info ); + } + + for( k = 1; k < leaving_frs; k++ ){ + // BTW: number of vectors (bigGOP) per level: 2, 6, 14, 30, ... = 2x half_bigGOP + // copy the motion vectors from previous bigGOP to current bigGOP by Yongjun Wu 从前面的biggop的信息拷贝到当前biggop +// if(simul_alert == 0){ + free_vector ( yfmv_bigGOP[k + ind_mv_bigGOP[i]], info ); + mv_copy( yfmv_bigGOP[k + ind_mv_bigGOP[i] + GOPsz], yfmv_bigGOP[k + ind_mv_bigGOP[i]], info ); + // mv_ref_bigGOP[k + ind_mv_bigGOP[i]] = mv_ref_bigGOP[k + ind_mv_bigGOP[i] + GOPsz]; + mv_ref_bigGOP[k + ind_mv_bigGOP[i]] = mv_ref_bigGOP[k + ind_mv_bigGOP[i] + GOPsz] ? + yfmv_bigGOP[k + ind_mv_bigGOP[i]] : NULL; +// }//if simul + } + half_bigGOP /= 2; + half_GOPsz /= 2; + GOPsz /= 2; + leaving_frs/= 2; + bigGOP /= 2; + } + half_bigGOP = info.bigGOP / 2; + half_GOPsz = info.GOPsz / 2; + GOPsz = info.GOPsz; + leaving_frs = half_bigGOP; // = info.bigGOP - info.GOPsz; + bigGOP = info.bigGOP; + } + + printf("leaving_frs = %d, GOPsz = %d, info.bigGOP = %d, half_bigGOP = %d\n",leaving_frs,GOPsz,info.bigGOP,half_bigGOP); + + + /******************** + Temporal Filtering + *********************/ + + for( i = 0; i < tPyrLev - 1; i++ )// 逐层次的进行1.时域补偿,2.时域分解 + { + printf("\n"); + printf("temporal pyramid level %d (mc_anal)\n", i+1 ); + + // mark end of sequence with a scene_changes level_change是true表示是最后一个gop了 + if ( Level_change == YES ) { + for (j = eff_GOPsz; j <= bigGOP; j++ ) + scene_change[i][j] = YES; + printf("scene_change[%d][eff_GOPsz=%d] = YES\n", i, eff_GOPsz); + // corresponding MV will be cleared during ME + } + + printf("bigGOP = %d, level_change = %d, eff_GOPsz = %d\n",bigGOP, Level_change, eff_GOPsz ); + + /*** motion estimation ***/ // 运动估计。感觉就是设置了一点东西,在最后面进行了块的匹配 + assert((leaving_frs + (first_GOP==YES)) % 2 != 0);// 剩余帧是奇数或者是第一个gop + for( j = leaving_frs + (first_GOP==YES); j < bigGOP; j += 2 ) // 从1或leaving_frs开始,到bigGop结束,一帧一帧进行处理 + { + if (j == bigGOP - 1 && scene_change[i][j] == NO) { + assert(0); // 这种情况是错误的,退出 + + printf("ME (uni) for frames %.3d / %.3d\n", + curr + (j - 1) * dist, curr + j * dist); + sc_ref1 = &scene_change[i][j]; + sc_ref2 = NULL; + mv_ref1 = yfmv_bigGOP[j + ind_mv_bigGOP[i]]; + mv_ref2 = NULL; + fr_cur = &pyrTemp[i][j]; + fr_ref1 = &pyrTemp[i][j - 1]; + fr_ref2 = NULL; + mv_ref_bigGOP[j + ind_mv_bigGOP[i]] = yfmv_bigGOP[j + ind_mv_bigGOP[i]]; + mv_ref_bigGOP[j + 1 + ind_mv_bigGOP[i]] = NULL; + } + else if (scene_change[i][j] == NO && scene_change[i][j + 1] == NO) // 左右场景都没有改变,可以双向参考 + { + printf("ME (bi) for frames %.3d / %.3d / %.3d\n", + curr + (j - 1) * dist, curr + j * dist, curr + (j + 1) * dist); + sc_ref1 = &scene_change[i][j]; + sc_ref2 = &scene_change[i][j + 1]; + mv_ref1 = yfmv_bigGOP[j + ind_mv_bigGOP[i]]; // + mv_ref2 = yfmv_bigGOP[j + 1 + ind_mv_bigGOP[i]];// + + if( (j - 2 + ind_mv_bigGOP[i]) - ind_mv_bigGOP[i] >= 0 ) + mv_ref3 = yfmv_bigGOP[j - 2 + ind_mv_bigGOP[i]]; + else + mv_ref3 = NULL; +/* + if( ( (first_GOP==NO) && (j == leaving_frs + 2) ) || (j == (int)( pow(2, info.tPyrLev - i) + 1 ) && (first_GOP==YES) ) ) + mv_ref3 = NULL; +*/ + if( (j - 1 + ind_mv_bigGOP[i]) - ind_mv_bigGOP[i] >= 0 ) + mv_ref4 = yfmv_bigGOP[j - 1 + ind_mv_bigGOP[i]]; + else + mv_ref4 = NULL; +/* + if( ( (first_GOP==NO) && (j == leaving_frs + 2) ) || (j == (int)( pow(2, info.tPyrLev - i) + 1 ) && (first_GOP==YES) ) ) + mv_ref4 = NULL; +*/ + fr_cur = &pyrTemp[i][j]; + fr_ref1 = &pyrTemp[i][j - 1]; + fr_ref2 = &pyrTemp[i][j + 1]; + mv_ref_bigGOP[j + ind_mv_bigGOP[i]] = yfmv_bigGOP[j + ind_mv_bigGOP[i]]; + mv_ref_bigGOP[j + 1 + ind_mv_bigGOP[i]] = yfmv_bigGOP[j + 1 + ind_mv_bigGOP[i]]; + + printf("(int)( pow(2, info.tPyrLev - i) ) = %d\n",(int)( pow(2, info.tPyrLev - i) )); + printf("prev left = %d, prev right = %d, ind_mv_bigGOP[i] = %d, ind_mv_GOP[i] = %d\n" + ,j - 2 + ind_mv_bigGOP[i], j - 1 + ind_mv_bigGOP[i], ind_mv_bigGOP[i], ind_mv_GOP[i]); + printf("i = %d, j = %d, leaving_frs = %d, first_GOP = %d\n",i,j,leaving_frs, first_GOP); + } + else if (scene_change[i][j] == NO) { + printf("ME (left) for frames %.3d / %.3d / %.3d\n", + curr + (j - 1) * dist, curr + j * dist, curr + (j + 1) * dist); + sc_ref1 = &scene_change[i][j]; + sc_ref2 = NULL; + mv_ref1 = yfmv_bigGOP[j + ind_mv_bigGOP[i]]; + mv_ref2 = NULL; + + if( (j - 2 + ind_mv_bigGOP[i]) - (ind_mv_bigGOP[i]) >= 0 ) + mv_ref3 = yfmv_bigGOP[j - 2 + ind_mv_bigGOP[i]]; + else + mv_ref3 = NULL; +/* + if( ( (first_GOP==NO) && (j == leaving_frs + 2) ) || (j == (int)( pow(2, info.tPyrLev - i) + 1 ) && (first_GOP==YES) ) ) + mv_ref3 = NULL; +*/ + mv_ref4 = NULL; + + fr_cur = &pyrTemp[i][j]; + fr_ref1 = &pyrTemp[i][j - 1]; + fr_ref2 = NULL; + mv_ref_bigGOP[j + ind_mv_bigGOP[i]] = yfmv_bigGOP[j + ind_mv_bigGOP[i]]; + mv_ref_bigGOP[j + 1 + ind_mv_bigGOP[i]] = NULL; + assert(scene_change[i][j + 1] == YES); + + printf("prev left = %d, prev right = %d, ind_mv_bigGOP[i] = %d, ind_mv_GOP[i] = %d\n" + ,j - 2 + ind_mv_bigGOP[i], j - 1 + ind_mv_bigGOP[i], ind_mv_bigGOP[i], ind_mv_GOP[i]); + printf("i = %d, j = %d, leaving_frs = %d, first_GOP = %d\n",i,j,leaving_frs, first_GOP); + } + else if (scene_change[i][j + 1] == NO) { +// assert(0); + + printf("ME (right) for frames %.3d / %.3d / %.3d\n", + curr + (j - 1) * dist, curr + j * dist, curr + (j + 1) * dist); + sc_ref1 = &scene_change[i][j + 1]; + sc_ref2 = NULL; + mv_ref1 = yfmv_bigGOP[j + 1 + ind_mv_bigGOP[i]]; + mv_ref2 = NULL; + fr_cur = &pyrTemp[i][j]; + fr_ref1 = &pyrTemp[i][j + 1]; + fr_ref2 = NULL; + mv_ref_bigGOP[j + ind_mv_bigGOP[i]] = NULL; + mv_ref_bigGOP[j + 1 + ind_mv_bigGOP[i]] = yfmv_bigGOP[j + 1 + ind_mv_bigGOP[i]]; + assert(scene_change[i][j] == YES); + // free_vector( yfmv_bigGOP[j + ind_mv_bigGOP[i]], info ); + } + else { + sc_ref1 = sc_ref2 = NULL; + mv_ref1 = mv_ref2 = NULL; + mv_ref3 = NULL; + mv_ref4 = NULL; + fr_cur = fr_ref1 = fr_ref2 = NULL; + mv_ref_bigGOP[j + ind_mv_bigGOP[i]] = NULL; + mv_ref_bigGOP[j + 1 + ind_mv_bigGOP[i]] = NULL; + } + + // free_vector before motion estimation + free_vector( yfmv_bigGOP[j + ind_mv_bigGOP[i]], info ); + free_vector( yfmv_bigGOP[j + 1 + ind_mv_bigGOP[i]], info ); + +#ifndef VBR_DEC + if( j == (leaving_frs + (first_GOP==YES)) && simul_skip == YES){ + buff_lambda = info.lambda[i]; + + if(i <= 2){ + info.lambda[i] = orig_lambda[i]; + }else{ + info.lambda[i] = orig_lambda[2]; + } + + } +#endif + + if (sc_ref1 != NULL) { // 左向参考存在,进行划分,补偿 + block_matching(mv_ref1, mv_ref2, mv_ref3, mv_ref4, fr_cur, fr_ref1, fr_ref2, + sc_ref1, sc_ref2, info, i, dist, info.subpel[i], upframe1, upframe2, upsamp_x); + } +#ifndef VBR_DEC + if( j == (leaving_frs + (first_GOP==YES)) && simul_skip == YES){ + info.lambda[i] = buff_lambda; + } +#endif + } + + /*** temporal analysis 时域分解***/ + // 从1或leaving_frs开始,到half bigGop结束,一帧一帧进行处理完本层的时域小波的所有帧 + for( j = (half_GOPsz - 1)*(first_GOP == NO); j < half_bigGOP; j++ ) + { +#ifdef MCTF_WITH_OBMC + // get the side information for each block: mode, mv and so on + // in encoder use "scene_change[i][2 * j + 1], scene_change[i][2 * j + 2], 1" + // for connection checking + get_mv_side_information(info, // 获得mv信息,放在了imageneinfo中 + yfmv_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // fmv2 + yfmv_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // fmv3 + mv_ref_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // mv_ref2 + mv_ref_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // mv_ref3 + frameMEinfo, varblkarray, + &total_varblk, i, j, + scene_change[i][2 * j + 1], scene_change[i][2 * j + 2], 1); + // get the weighting coefficients for self mv and neighbor mvs 获得mv的权重系数 + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // for the analysis of directional iblock + // for convenience we separate from the function of temporal_analysis() +#ifdef DEGUB_DIRECTIONAL_IBLOCK_OBMC + FILE *fiblk = fopen("iblock_info_encoder.txt", "at"); + fprintf(fiblk, "i=%d\t j=%d\n", i, j); + fclose(fiblk); +#endif + + directional_iblock_analysis_with_OBMC( + &pyrTemp[i + 1][j], // L1 + &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], // H1 + &pyrFrs_bigGOP[j - 1 + ind_pyrFrs_bigGOP[i]], // H0 &dump for j=0 + &pyrTemp[i][2 * j], // fr1 + &pyrTemp[i][2 * j + 1], // fr2 + &pyrTemp[i][2 * j + 2], // fr3 + yfmv_bigGOP[2 * j + ind_mv_bigGOP[i]], // fmv1 + yfmv_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // fmv2 + yfmv_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // fmv3 + mv_ref_bigGOP[2 * j + ind_mv_bigGOP[i]], // mv_ref1 + mv_ref_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // mv_ref2 + mv_ref_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // mv_ref3 + i, remaining_frs, info, + frameMEinfo, varblkarray, + scene_change[i][2 * j + 1], scene_change[i][2 * j + 2]); +#ifdef DEGUB_DIRECTIONAL_IBLOCK_OBMC + fiblk = fopen("iblock_info_encoder.txt", "at"); + fprintf(fiblk, "\n\n"); + fclose(fiblk); +#endif + +#endif + printf("level and frame: i = %d, j = %d\n",i,j); + + temporal_analysis_with_OBMC( + &pyrTemp[i + 1][j], // L1 // 下一层的L1放入这个里面 + &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], // H1 // 生成的H1 + &pyrFrs_bigGOP[j - 1 + ind_pyrFrs_bigGOP[i]], // &dump for j=0 + &pyrTemp[i][2 * j], // fr1 + &pyrTemp[i][2 * j + 1], // fr2 + &pyrTemp[i][2 * j + 2], // fr3 + yfmv_bigGOP[2 * j + ind_mv_bigGOP[i]], // fmv1 + yfmv_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // fmv2 + yfmv_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // fmv3 + mv_ref_bigGOP[2 * j + ind_mv_bigGOP[i]], // mv_ref1 + mv_ref_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // mv_ref2 + mv_ref_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // mv_ref3 + i, remaining_frs, info, + frameMEinfo, varblkarray, + scene_change[i][2 * j + 1], scene_change[i][2 * j + 2]); +#else + // NO OBMC for MCTF + // there are always the first layer quad-tree in yfmv_bigGOP + // so we need mv_ref_bigGOP to indicate whether the motion vector set is NULL or not + printf("level and frame: i = %d, j = %d\n",i,j); + + get_mv_side_information(info, + yfmv_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // fmv2 + yfmv_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // fmv3 + mv_ref_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // mv_ref2 + mv_ref_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // mv_ref3 + frameMEinfo, varblkarray, + &total_varblk, i, j, + scene_change[i][2 * j + 1], scene_change[i][2 * j + 2], 1); + // get the weighting coefficients for self mv and neighbor mvs + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // for the analysis of directional iblock + // for convenience we separate from the function of temporal_analysis() + + // get the side information for each block: mode, mv and so on + // in encoder use "scene_change[i][2 * j + 1], scene_change[i][2 * j + 2], 1" + // for connection checking + + directional_iblock_analysis_with_OBMC( + &pyrTemp[i + 1][j], // L1 + &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], // H1 + &pyrFrs_bigGOP[j - 1 + ind_pyrFrs_bigGOP[i]], // H0 &dump for j=0 + &pyrTemp[i][2 * j], // fr1 + &pyrTemp[i][2 * j + 1], // fr2 + &pyrTemp[i][2 * j + 2], // fr3 + yfmv_bigGOP[2 * j + ind_mv_bigGOP[i]], // fmv1 + yfmv_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // fmv2 + yfmv_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // fmv3 + mv_ref_bigGOP[2 * j + ind_mv_bigGOP[i]], // mv_ref1 + mv_ref_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // mv_ref2 + mv_ref_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // mv_ref3 + i, remaining_frs, info, + frameMEinfo, varblkarray, + scene_change[i][2 * j + 1], scene_change[i][2 * j + 2]); + +#endif + + temporal_analysis( &pyrTemp[i + 1][j], // L1 + &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], // H1 + &pyrFrs_bigGOP[j - 1 + ind_pyrFrs_bigGOP[i]], // H0 &dump for j=0 + &pyrTemp[i][2 * j], // fr1 + &pyrTemp[i][2 * j + 1], // fr2 + &pyrTemp[i][2 * j + 2], // fr3 + yfmv_bigGOP[2 * j + ind_mv_bigGOP[i]], // fmv1 + yfmv_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], // fmv2 + yfmv_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], // fmv3 + mv_ref_bigGOP[2 * j + ind_mv_bigGOP[i]], + mv_ref_bigGOP[2 * j + 1 + ind_mv_bigGOP[i]], + mv_ref_bigGOP[2 * j + 2 + ind_mv_bigGOP[i]], + i, remaining_frs, info ); + +#endif + + if (scene_change[i][2 * j] == YES && scene_change[i][2 * j + 1] == YES) + { + + printf("enter here! i = %d, j = %d\n",i,j); + +#ifdef COPYCOMPENSATION_WEIGHTING + wcopyframe(&pyrTemp[i][2 * j], &pyrTemp[i + 1][j], + LPW4[1] * copycomp_weight_low[i], info); +#else + // propagate L frame with factor 1 + copyframe(&pyrTemp[i][2 * j], &pyrTemp[i + 1][j], info); +#endif + + // propagate double scene change + scene_change[i + 1][j] = YES; + scene_change[i + 1][j + 1] = YES; + } + + if (scene_change[i][2 * j + 1] == YES && scene_change[i][2 * j + 2] == YES) + { +#ifdef COPYCOMPENSATION_WEIGHTING + wcopyframe(&pyrTemp[i][2 * j + 1], + &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], + HPW4[1] * copycomp_weight_high[i], info); +#else + // propagate H frame with factor 1 + copyframe(&pyrTemp[i][2 * j + 1], &pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], info); +#endif + } + }//for j 一层的所有帧 + + // save frames for spatial analysis 只保存高频帧.从后往前放,因此越低频帧越在前面 + for( k = 0; k < half_GOPsz; k++ ) { + copyframe( &pyrFrs_bigGOP[k + ind_pyrFrs_bigGOP[i]], + &pyrFrs[k + half_GOPsz], info ); // these high temporal frames belong to current GOP, which will be coded for this GOP + } + + // copy MV-sets, the motion vector sets in current GOP, which will be encoded for this GOP, by Yongjun复制当前GOPsz的mv + for( k = 0; k <= GOPsz; k++ ) { + free_vector ( yfmv[k + ind_mv_GOP[i]], info ); + mv_copy( yfmv_bigGOP[k + ind_mv_bigGOP[i]], yfmv[k + ind_mv_GOP[i]], info ); + } + + bigGOP /= 2; + GOPsz /= 2; + half_bigGOP /= 2; + half_GOPsz /= 2; + leaving_frs /= 2; + dist *= 2; + + if ( Level_change == YES ) { + eff_GOPsz = (int) ceil ((double)remaining_frs / (pow (2, i + 1))); + } + else { + eff_GOPsz = bigGOP; + } + + } // i + + /**************/ + /* last level */ + /**************/ + printf("\n"); + printf("*** last level ***\n"); + printf("temporal pyramid level %d (mc_anal)\n", tPyrLev ); + + printf("bigGOP = %d, level_change = %d, eff_GOPsz = %d\n",bigGOP, Level_change, eff_GOPsz ); + + scene_change[tPyrLev - 1][1] = NO; + scene_change[tPyrLev - 1][2] = NO; + + // mark end of sequence with a scene_change + if ( Level_change == YES ) { + for (j = eff_GOPsz; j <= 2; j++ ) { + scene_change[tPyrLev - 1][j] = YES; + } + printf("scene_change[%d][eff_GOPsz=%d] = YES\n", tPyrLev-1, eff_GOPsz); + } + + // scene_change from preceeding GOP + scene_change[tPyrLev - 1][0] = scene_change_help; + + if(scene_change[tPyrLev - 1][1] == NO && scene_change[tPyrLev - 1][2] == NO){ + printf("ME (bi) for frames %.3d / %.3d / %.3d\n", + curr, curr + dist, curr + 2 * dist); + sc_ref1 = &scene_change[tPyrLev - 1][1]; + sc_ref2 = &scene_change[tPyrLev - 1][2]; + mv_ref1 = mv_ref_bigGOP[2] = yfmv[2]; + mv_ref2 = mv_ref_bigGOP[3] = yfmv[3]; + + mv_ref3 = NULL; + mv_ref4 = NULL; + + fr_cur = &pyrTemp[tPyrLev - 1][1]; + fr_ref1 = &pyrTemp[tPyrLev - 1][0]; + fr_ref2 = &pyrTemp[tPyrLev - 1][2]; + } else if (scene_change[tPyrLev - 1][1] == NO) { + printf("ME (left) for frames %.3d / %.3d / %.3d\n", + curr, curr + dist, curr + 2 * dist); + sc_ref1 = &scene_change[tPyrLev - 1][1]; + sc_ref2 = NULL; + mv_ref1 = mv_ref_bigGOP[2] = yfmv[2]; + mv_ref2 = mv_ref_bigGOP[3] = NULL; + + mv_ref3 = NULL; + mv_ref4 = NULL; + + fr_cur = &pyrTemp[tPyrLev - 1][1]; + fr_ref1 = &pyrTemp[tPyrLev - 1][0]; + fr_ref2 = NULL; + assert(scene_change[tPyrLev - 1][2] == YES); + mv_ref_bigGOP[3] = NULL; + } else if (scene_change[tPyrLev - 1][2] == NO) { + + printf("ME (right) for frames %.3d / %.3d / %.3d\n", + curr, curr + dist, curr + 2 * dist); + sc_ref1 = &scene_change[tPyrLev - 1][2]; + sc_ref2 = NULL; + mv_ref1 = mv_ref_bigGOP[3] = yfmv[3]; + mv_ref2 = mv_ref_bigGOP[2] = NULL; + + mv_ref3 = NULL; + mv_ref4 = NULL; + + fr_cur = &pyrTemp[tPyrLev - 1][1]; + fr_ref1 = &pyrTemp[tPyrLev - 1][2]; + fr_ref2 = NULL; + assert(scene_change[tPyrLev - 1][1] == YES); + mv_ref_bigGOP[2] = NULL; + } else { + sc_ref1 = sc_ref2 = NULL; + mv_ref1 = mv_ref_bigGOP[2] = NULL; + mv_ref2 = mv_ref_bigGOP[3] = NULL; + fr_cur = fr_ref1 = fr_ref2 = NULL; + } + // free_vector before motion estimation + free_vector( yfmv[2], info ); + free_vector( yfmv[3], info ); + + assert( (tPyrLev - 1) >= 2); + +#ifndef VBR_DEC + if( simul_skip == YES){ + buff_lambda = info.lambda[tPyrLev - 1]; + info.lambda[tPyrLev - 1] = orig_lambda[tPyrLev - 1]; + } +#endif + + if (sc_ref1 != NULL) { + block_matching(mv_ref1, mv_ref2, mv_ref3, mv_ref4, fr_cur, fr_ref1, fr_ref2, + sc_ref1, sc_ref2, info, i, dist, info.subpel[i], upframe1, upframe2, upsamp_x); + } + +#ifndef VBR_DEC + if( simul_skip == YES){ + info.lambda[tPyrLev - 1] = buff_lambda; + } +#endif + +#ifdef MCTF_WITH_OBMC + get_mv_side_information(info, + yfmv[2], // fmv2 + yfmv[3], // fmv3 + mv_ref_bigGOP[2], // mv_ref2 + mv_ref_bigGOP[3], // mv_ref3 + frameMEinfo, varblkarray, + &total_varblk, tPyrLev - 1, 1, + scene_change[tPyrLev - 1][1], scene_change[tPyrLev - 1][2], 1); + + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // for the analysis of directional iblock + // for convenience we separate from the function of temporal_analysis() + directional_iblock_analysis_with_OBMC( &pyrFrs[0], // L1 + &pyrFrs[1], // H1 + &end_of_lastGOP, // dump in 1.GOP // H0 &dump for j=0 + &pyrTemp[tPyrLev - 1][0], // fr1 + &pyrTemp[tPyrLev - 1][1], // fr2 + &pyrTemp[tPyrLev - 1][2], // fr3 + tmp_yfmv, //yfmv[1] in 1.GOP // fmv1 + yfmv[2], // fmv2 + yfmv[3], // fmv3 + mv_ref_bigGOP[1], // mv_ref1 + mv_ref_bigGOP[2], // mv_ref2 + mv_ref_bigGOP[3], // mv_ref3 + tPyrLev - 1, remaining_frs, info, + frameMEinfo, varblkarray, + scene_change[tPyrLev - 1][1], scene_change[tPyrLev - 1][2]); + +#endif + + temporal_analysis_with_OBMC( + &pyrFrs[0], // L1 + &pyrFrs[1], // H1 + &end_of_lastGOP, // dump in 1.GOP // H0 + &pyrTemp[tPyrLev - 1][0], // fr1 + &pyrTemp[tPyrLev - 1][1], // fr2 + &pyrTemp[tPyrLev - 1][2], // fr3 + tmp_yfmv, //yfmv[1] in 1.GOP // fmv1 + yfmv[2], // fmv2 + yfmv[3], // fmv3 + mv_ref_bigGOP[1], // mv_ref1 + mv_ref_bigGOP[2], // mv_ref2 + mv_ref_bigGOP[3], // mv_ref3 + tPyrLev - 1, remaining_frs, info, + frameMEinfo, varblkarray, + scene_change[tPyrLev - 1][1], scene_change[tPyrLev - 1][2]); + +#else + + get_mv_side_information(info, + yfmv[2], // fmv2 + yfmv[3], // fmv3 + mv_ref_bigGOP[2], // mv_ref2 + mv_ref_bigGOP[3], // mv_ref3 + frameMEinfo, varblkarray, + &total_varblk, tPyrLev - 1, 1, + scene_change[tPyrLev - 1][1], scene_change[tPyrLev - 1][2], 1); + + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // for the analysis of directional iblock + // for convenience we separate from the function of temporal_analysis() + + directional_iblock_analysis_with_OBMC( &pyrFrs[0], // L1 + &pyrFrs[1], // H1 + &end_of_lastGOP, // dump in 1.GOP // H0 &dump for j=0 + &pyrTemp[tPyrLev - 1][0], // fr1 + &pyrTemp[tPyrLev - 1][1], // fr2 + &pyrTemp[tPyrLev - 1][2], // fr3 + tmp_yfmv, //yfmv[1] in 1.GOP // fmv1 + yfmv[2], // fmv2 + yfmv[3], // fmv3 + mv_ref_bigGOP[1], // mv_ref1 + mv_ref_bigGOP[2], // mv_ref2 + mv_ref_bigGOP[3], // mv_ref3 + tPyrLev - 1, remaining_frs, info, + frameMEinfo, varblkarray, + scene_change[tPyrLev - 1][1], scene_change[tPyrLev - 1][2]); + +#endif + + temporal_analysis( &pyrFrs[0], // L1 + &pyrFrs[1], // H1 + &end_of_lastGOP, // dump in 1.GOP // H0 + &pyrTemp[tPyrLev - 1][0], // fr1 + &pyrTemp[tPyrLev - 1][1], // fr2 + &pyrTemp[tPyrLev - 1][2], // fr3 + tmp_yfmv, //yfmv[1] in 1.GOP // fmv1 + yfmv[2], // fmv2 + yfmv[3], // fmv3 + mv_ref_bigGOP[1], // mv_ref1 + mv_ref_bigGOP[2], // mv_ref2 + mv_ref_bigGOP[3], // mv_ref3 + tPyrLev - 1, remaining_frs, info ); + +#endif + + + if (scene_change[tPyrLev - 1][0] == YES && scene_change[tPyrLev - 1][1] == YES) { +#ifdef COPYCOMPENSATION_WEIGHTING + wcopyframe(&pyrTemp[tPyrLev - 1][0], &pyrFrs[0], + LPW4[1] * copycomp_weight_low[tPyrLev - 1], info); +#else + // propagate L frame with factor 1 + copyframe(&pyrTemp[tPyrLev - 1][0], &pyrFrs[0], info); +#endif + } + if (scene_change[tPyrLev - 1][1] == YES && scene_change[tPyrLev - 1][2] == YES) { +#ifdef COPYCOMPENSATION_WEIGHTING + wcopyframe(&pyrTemp[tPyrLev - 1][1], &pyrFrs[1], + HPW4[1] * copycomp_weight_high[tPyrLev - 1], info); +#else + // propagate H frame with factor 1 + copyframe(&pyrTemp[tPyrLev - 1][1], &pyrFrs[1], info); +#endif + } + +// if(simul_enc == NO){ + // save last calculated lowpass frames of bigGOP + bigGOP = info.bigGOP; + for( i = 0; i < tPyrLev - 1; i++ ){ + copyframe( &pyrTemp[i + 1][bigGOP / 2 - 1], + &pyrFrs_first[i], info ); + bigGOP /= 2; + } + scene_change[tPyrLev - 1][0] = YES; // just to be sure + + // save last calculated highpass frame of last level + copyframe( &pyrFrs[1], &end_of_lastGOP, info ); + + // save yfmv[3] for next GOP + free_vector ( tmp_yfmv, info ); + mv_copy( yfmv[3], tmp_yfmv, info ); + mv_ref_bigGOP[1] = mv_ref_bigGOP[3] ? tmp_yfmv : NULL; + + // save scene_change for next GOP + scene_change_help = scene_change[tPyrLev - 1][2]; +// }// if not simulative encoding + + free_vector( yfmv[1], info ); + + if(simul_enc == YES) + simul_alert = 1; + else + simul_alert = 0; + +} + + +/* + * mc_anal + 进行mctf 当前第几帧、当前第几个gop、info、是否为第一个gop、是否最后一个gop不足一个biggop、剩余帧。预估码率、 + */ +long int +mc_anal( int curr, int GOP_counter, videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs, int simul_enc, float *upframe1, float *upframe2, float *upsamp_x ) +{ + int GOPheader_bytes, mvbits; // GOP头的花费bit, mv的bit + FILE *fpstat; // 写stst文件 + + if( !( fpstat = fopen( info.statname, "at+" ) ) ) { + printf( "Can not open %s\n", info.statname ); + exit( 1 ); + } + fprintf( fpstat, " frame %.3d - %.3d (%.3d) ......\n", + curr, curr + info.GOPsz - 1, curr + info.eff_GOPsz -1 ); + fclose( fpstat ); + + if( info.tPyrLev >= 1 ) { // 进行时域分解 对一个gop内的几个时域进行分解 + analscheme3( curr, info, first_GOP, Level_change, remaining_frs, simul_enc, upframe1, upframe2, upsamp_x ); + + GOPheader_bytes = write_GOPheader( scene_change, info ); // 写sence_change进码流 + mvbits = mv_encoding( info, FrsRate, yfmv, GOP_counter, simul_enc, curr ); + free_mvs( yfmv, info ); // initialize MVs for next GOP + + printf("GOPheader_bytes = %d, mvbits = %d\n",GOPheader_bytes, mvbits); + + } + else // 不进行时域分解 + { // info.tPyrLev == 0 // necessary? KH, 2003-12-13 + mvbits = 0; + // no GOPheader output + copyframe( &pyrTemp[0][0], &pyrFrs[0], info ); + } + + // print_mvbits( info, FrsRate ); //pstatN.c + + return mvbits; +} + + +/* + * denoise_mctf_anal_ezbc() + * + */ +long int +denoise_mctf_anal_ezbc( int curr, int GOP_counter, videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs ) +{ + int i, j, filterType = DENOISE_FILTER; + YUVimage tempfr; + long int output_GOP_bytes; + char strtmp[256], rd_name[256]; + + for( j = 0; j < info.GOPsz; j++ ) { + Four_GOP[j] = pyrFrs[j]; + } + for( i = 0; i < ((YUV420 == 1) ? 1 : 3); i++ ) { + for( j = 0; j < info.GOPsz; j++ ) { + Four_GOP[( i + 1 ) * info.GOPsz + j] = spatial_high[i][j]; + } + } + + /************/ + /* spatial */ + /* analysis */ + /************/ + info.ywidth *= 2; + info.yheight *= 2; + info.cwidth *= 2; + info.cheight *= 2; + + for( i = 0; i < info.eff_GOPsz; i++ ) { + + frame_alloc( &tempfr, info ); + read_frame( &tempfr, info, info.inname, curr + i, info.format ); + + if( YUV420 == 1 ) { // down-conversion to 420 + f444_420( info, &tempfr ); + spatial_anal( tempfr.Y, info.ywidth, info.yheight, pyrTemp[0][i].Y, + spatial_high[0][i].Y, spatial_high[0][i].U, + spatial_high[0][i].V, filterType ); + for( j = 0; j < info.cwidth * info.cheight / 4; j++ ) { + pyrTemp[0][i].U[j] = tempfr.U[j] / 4; + pyrTemp[0][i].V[j] = tempfr.V[j] / 4; + } + } else { + spatial_anal_frame( &tempfr, info, &pyrTemp[0][i], &spatial_high[0][i], + &spatial_high[1][i], &spatial_high[2][i], + filterType ); + } + + free_frame( tempfr ); + + } + + info.ywidth /= 2; + info.yheight /= 2; + info.cwidth /= 2; + info.cheight /= 2; + + /********/ + /* MCTF */ + /********/ + mc_anal( curr, GOP_counter, info, first_GOP, Level_change, remaining_frs, NO, NULL, NULL, NULL ); + + /********/ + /* EZBC */ + /********/ + output_GOP_bytes = ezbc3d_enc_GOP( curr, Four_GOP, info, GOP_counter ); + + return output_GOP_bytes; +} + + +/* + * mctf_anal_ezbc() + * 编码一个gop + */ +long int +mctf_anal_ezbc( int curr, int GOP_counter, videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs, long int *sum_mv, int simul_enc, float *upframe1, float *upframe2, float *upsamp_x ) +{ + int i,j; + long int output_GOP_bytes; + long target_bitrate; + long subband_budget; + + long int mv_bits; + + int t_level,dist,nfrs; + float bpp, pwr_factor; + float H; + + printf("\nsimul_enc = %d\n",simul_enc); + + target_bitrate = (info.simul_rate * 1000 * info.GOPsz) / (8 * info.framerate); + + for( i = 0; i < info.eff_GOPsz; i++ ) { // 读取eff_gop的帧 + read_frame( &pyrTemp[0][i], info, info.inname, curr + i, info.format ); + } + + //H = image_entropy((&pyrTemp[0][0])->Y,info.ywidth,info.yheight); +// printf("image entropy for curr %d: %f\n",curr,H); + + /********/ + /* MCTF */ + /********/ + // 处理一个gop的信息 + *sum_mv = mc_anal( curr, GOP_counter, info, first_GOP, Level_change, remaining_frs, simul_enc, upframe1, upframe2, upsamp_x ); + *sum_mv = *sum_mv / 8; + + printf("\n GOP_counter = %d, sum_mv = %ld\n",GOP_counter,*sum_mv); + +/* + subband_budget = target_bitrate - *sum_mv; + printf("\nsubband_budget = %d, target_bitrate = %d\n",subband_budget,target_bitrate); + + bpp = (float)subband_budget * 8 / (info.GOPsz * info.yheight * info.ywidth * 1.5); + pwr_factor = pow(2, (-2)*bpp); + printf("bpp = %f, pwr_factor = %f\n",bpp,pwr_factor); +*/ + + /********/ + /* EZBC */ + /********/ +#ifdef CNN_wavelet + { + //// 标记目前编码了几个gop,来表示进度 + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 4); + //name[strlen(info.bitname) - 4] = '_'; + //snprintf(start, 9, "%03d", info.start); + //for (int i = 0; i < 3; i++) + //{ + // name[strlen(info.bitname) - 3 + i] = start[i]; + //} + //name[strlen(info.bitname)] = '\0'; // + //sprintf(data_file_name, "%s.encode_number", name); + //std::ofstream file(data_file_name, std::ios::app); + //file << GOP_counter << std::endl; + //file.close(); + } + {// 写文本文件 + char name[256], data_file_name[256], start[10]; + strncpy(name, info.bitname, strlen(info.bitname) - 4); + name[strlen(info.bitname) - 4] = '_'; + snprintf(start, 9, "%03d", info.start); + for (int i = 0; i < 3; i++) + { + name[strlen(info.bitname) - 3 + i] = start[i]; + } + name[strlen(info.bitname)] = '\0'; // + sprintf(data_file_name, "%s.data", name); + std::cout << data_file_name << std::endl; + std::ofstream myfile(data_file_name, std::ios::app); + for (int pic = 0; pic < info.GOPsz; pic++) + { + for (int i = 0; i < info.yheight; i++) + { + for (int j = 0; j < info.ywidth; j++) + { + //int temp = round(pyrFrs[pic].Y[i*info.ywidth + j]); + float temp = (pyrFrs[pic].Y[i*info.ywidth + j]); + myfile << temp << " "; + } + myfile << std::endl; + } + } + for (int pic = 0; pic < info.GOPsz; pic++) + { + for (int i = 0; i < info.cheight; i++) + { + for (int j = 0; j < info.cwidth; j++) + { + //int temp = round(pyrFrs[pic].U[i*info.cwidth + j]); + float temp = (pyrFrs[pic].U[i*info.cwidth + j]); + myfile << temp << " "; + } + myfile << std::endl; + } + } + for (int pic = 0; pic < info.GOPsz; pic++) + { + for (int i = 0; i < info.cheight; i++) + { + for (int j = 0; j < info.cwidth; j++) + { + //int temp = round(pyrFrs[pic].V[i*info.cwidth + j]); + float temp = (pyrFrs[pic].V[i*info.cwidth + j]); + myfile << temp << " "; + } + myfile << std::endl; + } + } + myfile.close(); + } + { + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 4); + //name[strlen(info.bitname) - 4] = '_'; + //snprintf(start, 9, "%03d", info.start); + //for (int i = 0; i < 3; i++) + //{ + // name[strlen(info.bitname) - 3 + i] = start[i]; + //} + //name[strlen(info.bitname)] = '\0'; // + //sprintf(data_file_name, "%s.bindata", name); + //std::ofstream myfile(data_file_name, std::ios::binary | std::ios::app); + //uint8_t *buf = new uint8_t[1]; + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // int temp = round(pyrFrs[pic].Y[i*info.ywidth + j]); + // short int temp1 = temp; + // if (temp != temp1) + // { + // std::cout << temp << " " << temp1 << std::endl; + // std::cout << "cuolw" << std::endl; + // exit(0); + // } + // myfile.write((char*)(&temp1), sizeof(short int)); + // } + // } + //} + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // int temp = round(pyrFrs[pic].U[i*info.cwidth + j]); + // short int temp1 = temp; + // if (temp != temp1) + // { + // std::cout << temp << " " << temp1 << std::endl; + // std::cout << "cuolu" << std::endl; + // exit(0); + // } + // myfile.write((char*)(&temp1), sizeof(short int)); + // } + // } + //} + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // int temp = round(pyrFrs[pic].V[i*info.cwidth + j]); + // short int temp1 = temp; + // if (temp != temp1) + // { + // std::cout << temp << " " << temp1 << std::endl; + // std::cout << "cuolv" << std::endl; + // exit(0); + // } + // myfile.write((char*)(&temp1), sizeof(short int)); + // } + // } + //} + //myfile.close(); + } + output_GOP_bytes = ezbc3d_enc_GOP( curr, pyrFrs, info, GOP_counter ); + //output_GOP_bytes = 0; + //exit(0); +#else +#ifdef NO_EZBC + output_GOP_bytes = 0; +#else + output_GOP_bytes = ezbc3d_enc_GOP(curr, pyrFrs, info, GOP_counter); +#endif +#endif + printf("\n GOP_counter = %d, output_GOP_bytes = %ld\n",GOP_counter,output_GOP_bytes); + + return output_GOP_bytes; +} diff --git a/Interframe EZBC/TempSub/src/arcode.cpp b/Interframe EZBC/TempSub/src/arcode.cpp new file mode 100644 index 0000000..e9f75af --- /dev/null +++ b/Interframe EZBC/TempSub/src/arcode.cpp @@ -0,0 +1,533 @@ +#include +#include +#include +#define EXTERN extern +#include "arcode.h" +#include +#include "mv_ec.h" +#include "mv_statistics.h" + +//#define SEND_EOF_SYMBOL + +int num_contexts; +int num_symbol; + +/*H----------------------------*/ +double log2(double f) +{ + double x; + + x = log10(f); + x /= log10(2.0); + return (x); +} + +/*H----------------------------*/ + +/****************************************************************************/ +/* bit_plus_follow() */ +/****************************************************************************/ +void bit_plus_follow(int bit) +{ + output_bit(bit); /* output the bit */ + mv_bits ++; +// printf("ONE BIT!\n"); + while (bits_to_follow > 0) + { + output_bit(!bit); /* output bits_to_follow opposite bits */ + mv_bits ++; +// printf("ONE BIT!\n"); + bits_to_follow--; /* set bits_to_follow to zero */ + } +} + + + +/****************************************************************************/ +/* encode_symbol() */ +/****************************************************************************/ +void encode_symbol(int symbol, int context) +{ + int range; /* size of the current code region */ + + // printf("encode_symbol\n"); + + if (symbol < 0 || symbol > num_symbol + 1) + { + printf("error in encode_symbol() %d\n", symbol); + exit(1); + } + + if (context < 0 || context >= num_contexts) + { + printf("illegal context number in encode_symbol() (%d)\n", context); + exit(1); + } + + range = high - low + 1; + high = low + (range * cmf[context][symbol - 1]) / cmf[context][0] - 1; /* narrow the code */ + low = low + (range * cmf[context][symbol]) / cmf[context][0]; /* region */ + + for (;;) + { /* loop to output bits */ + if (high < Half) + { + mv_bits = 0; + bit_plus_follow(0); /* output 0 if in low half */ + mv_res_bits += mv_bits; + } + else if (low >= Half) + { /* output 1 if in high half */ + mv_bits = 0; + bit_plus_follow(1); + mv_res_bits += mv_bits; + low -= Half; /* subtract offset to top */ + high -= Half; + } + else if (low >= First_qtr && high < Third_qtr) + { /* output an opposite bit */ + bits_to_follow++; /* later if in middle half */ + low -= First_qtr; /* subtract offset to middle */ + high -= First_qtr; + } + else + break; /* otherwise exit loop */ + + low = 2 * low; /* scale up code range */ + high = 2 * high + 1; + } +} + + + +void encode_word(int word, int context) +{ + if (word < 0 || word > num_symbol - 1) + { + printf("illegal word in encode_word() (%d)\n", word); + exit(1); + } + if (context < 0 || context > num_contexts - 1) + { + printf("illegal context number in encode_word() (%d)\n", context); + exit(1); + } + + encode_symbol(int2sym[context][word], context); +} + + +/****************************************************************************/ +/* arencode_end() */ +/****************************************************************************/ +void arencode_end(int context) +{ + int i, j; + +#ifdef SEND_EOF_SYMBOL + encode_symbol(num_symbol + 1, context); /* EOF symbol */ +#endif + + bits_to_follow++; /* output two bits for underflow */ + (low < First_qtr) ? bit_plus_follow(0) : bit_plus_follow(1); + + /* release the memory */ + for (i = 0; i < num_contexts; i++) + { + mvStat_writeFreqNumber(i, cmf[i][0], num_symbol); + for (j = 0; j < num_symbol; j++) { + mvStat_writeFreq(freq[i][int2sym[i][j]]); + } + + free(freq[i]); + free(cmf[i]); + free(int2sym[i]); + free(sym2int[i]); + } + free(freq); + free(cmf); + free(int2sym); + free(sym2int); +} + +/****************************************************************************/ +/* start_model() */ +/****************************************************************************/ +void start_model(int context = 0, const int *freq_init = NULL) +{ + int i; + + if (context < 0 || context >= num_contexts) + { + printf("illegal context number in start_model() (%d)\n", context); + exit(1); + } + + for (i = 0; i < num_symbol; i++) + { /* setup the tables that */ + int2sym[context][i] = i + 1; /* translate between symbol */ + sym2int[context][i + 1] = i; /* indexes and characters */ + } + + if (freq_init) + { +#ifdef SEND_EOF_SYMBOL + freq[context][num_symbol + 1] = 1; +#else + freq[context][num_symbol + 1] = 0; +#endif + cmf[context][num_symbol + 1] = 0; + for (i = num_symbol; i >= 0; i--) + { + freq[context][i] = freq_init[sym2int[context][i]]; + cmf[context][i] = cmf[context][i + 1] + freq[context][i + 1]; + } + + freq[context][0] = 0; + } + else + { + +#ifdef SEND_EOF_SYMBOL + for (i = 0; i <= num_symbol + 1; i++) + { + freq[context][i] = 1; + cmf[context][i] = num_symbol + 1 - i; + } +#else + freq[context][0] = 0; // EOF + for (i = 0; i <= num_symbol; i++) + { + freq[context][i] = 1; + cmf[context][i] = num_symbol - i; + } +#endif // SEND_EOF_SYMBOL + + freq[context][0] = 0; + } +} + +/****************************************************************************/ +/* arencode_init() */ +/****************************************************************************/ +void arencode_init(int symbols, int contexts, const int **freq_init) +{ + int i; + + if (symbols < 1) + { + printf("illegal number of symbols in arencode_init() (%d)\n", symbols); + exit(1); + } + + if (contexts < 1) + { + printf("illegal number of contexts in arencode_init() (%d)\n", contexts); + exit(1); + } + + num_symbol = symbols; //num_symbol = 2 + num_contexts = contexts; //num_contexts = 5 + + /* memory allocation */ + freq = (int **) calloc(num_contexts, sizeof(int *)); + cmf = (int **) calloc(num_contexts, sizeof(int *)); + int2sym = (int **) calloc(num_contexts, sizeof(int *)); + sym2int = (int **) calloc(num_contexts, sizeof(int *)); + for (i = 0; i < num_contexts; i++) + { + freq[i] = (int *) calloc(num_symbol + 2, sizeof(int)); + cmf[i] = (int *) calloc(num_symbol + 2, sizeof(int)); + int2sym[i] = (int *) calloc(num_symbol, sizeof(int)); + sym2int[i] = (int *) calloc(num_symbol + 2, sizeof(int)); + } + + /* initialize variables */ + bits_to_follow = 0; + + /* start model */ + for (i = 0; i < num_contexts; i++) + { + start_model(i, freq_init ? freq_init[i] : NULL); + } + low = 0; + high = Top_value; +} + +/****************************************************************************/ +/* ardecode_end() */ +/****************************************************************************/ +void ardecode_end() +{ + int i, j; + + for (i = 0; i < num_contexts; i++) + { + mvStat_writeFreqNumber(i, cmf[i][0], num_symbol); + for (j = 0; j < num_symbol; j++) { + mvStat_writeFreq(freq[i][int2sym[i][j]]); + } + + free(freq[i]); + free(cmf[i]); + free(int2sym[i]); + free(sym2int[i]); + } + free(freq); + free(cmf); + free(int2sym); + free(sym2int); +} + +/****************************************************************************/ +/* ardecode_init() */ +/****************************************************************************/ +void ardecode_init(int symbols, int contexts, const int **freq_init) +{ + int i, bit; + + if (symbols < 1) + { + printf("illegal number of symbols in ardecode_init() (%d)\n", symbols); + exit(1); + } + + if (contexts < 1) + { + printf("number of contexts number in ardecode_init() (%d)\n", contexts); + exit(1); + } + + num_symbol = symbols; + num_contexts = contexts; + + /* memory allocation */ + freq = (int **) calloc(num_contexts, sizeof(int *)); + cmf = (int **) calloc(num_contexts, sizeof(int *)); + int2sym = (int **) calloc(num_contexts, sizeof(int *)); + sym2int = (int **) calloc(num_contexts, sizeof(int *)); + for (i = 0; i < num_contexts; i++) + { + freq[i] = (int *) calloc(num_symbol + 2, sizeof(int)); + cmf[i] = (int *) calloc(num_symbol + 2, sizeof(int)); + int2sym[i] = (int *) calloc(num_symbol, sizeof(int)); + sym2int[i] = (int *) calloc(num_symbol + 2, sizeof(int)); + + start_model(i, freq_init ? freq_init[i] : NULL); + } + + bits_to_follow = 0; + + low = 0; + high = Top_value; + value = 0; /* input bits ot fill the */ + + for (i = 1; i <= Code_value_bits; i++) + { /* code value */ + input_bit(bit); + value = 2 * value + bit; + } +} + +/****************************************************************************/ +/* decode_symbol() */ +/****************************************************************************/ +int decode_symbol(int context) +{ + int range; /* size of current code region */ + int cum; /* cumulative frequency calculated */ + int symbol; /* symbol decoded */ + int bit; + + if (context < 0 || context >= num_contexts) + { + printf("illegal context number in decode_symbol() (%d)\n", context); + exit(1); + } + + range = high - low + 1; + cum = (((value - low) + 1) * cmf[context][0] - 1) / range; /*find cum freq for value */ + + for (symbol = 1; cmf[context][symbol] > cum; symbol++); /* then find symbol */ + + high = low + (range * cmf[context][symbol - 1]) / cmf[context][0] - 1; + low = low + (range * cmf[context][symbol]) / cmf[context][0]; + for (;;) + { /* loop to get rid of bits */ + if (high < Half); /* do nothing */ + else if (low >= Half) + { /* expand low half */ + value -= Half; + low -= Half; /* subtract offset to top */ + high -= Half; + } + else if (low >= First_qtr && high < Third_qtr) + { /* expand middle half */ + value -= First_qtr; + low -= First_qtr; /* subtract offset to middle */ + high -= First_qtr; + } + else + break; /* otherwise exit loop */ + + low = 2 * low; + high = 2 * high + 1; /* scale up code range */ + input_bit(bit); + value = 2 * value + bit; /* move in next input bit */ + } + + return symbol; +} + +int decode_word(int context) +{ + int symbol = decode_symbol(context); + + if (symbol < 1 || symbol > num_symbol) + { + return -1; + } + else + { + return sym2int[context][symbol]; + } +} + + +/****************************************************************************/ +/* update_model() */ +/****************************************************************************/ +void update_model(int word, int context) +{ + int i; /* new index for symbol */ + int cum; + int ch_i, ch_symbol; + int symbol; + + if (word < 0 || word > num_symbol - 1) + { + printf("illegal word in update_model() (%d)\n", word); + exit(1); + } + + if (context < 0 || context >= num_contexts) + { + printf("illegal context number in update_model() (%d)\n", context); + exit(1); + } + + symbol = int2sym[context][word]; + + if (cmf[context][0] >= Max_frequency) + { /* see if frequency counts */ + mvStat_writeFreqNumber(context, cmf[context][0], num_symbol); + for (i = 0; i < num_symbol; i++) { + mvStat_writeFreq(freq[context][int2sym[context][i]]); + } + cum = 0; + for (i = num_symbol + 1; i >= 0; i--) + { /* if so, halve all the counts */ + freq[context][i] = (freq[context][i] + 1) / 2; /* (keeping them non-zero) */ + cmf[context][i] = cum; + cum += freq[context][i]; + } + } + + for (i = symbol; freq[context][i] == freq[context][i - 1]; i--); /* find symbol's new index */ + + if (i < symbol) + { + ch_i = sym2int[context][i]; + ch_symbol = sym2int[context][symbol]; /* update the translation */ + sym2int[context][i] = ch_symbol; /* tables if the symbol has */ + sym2int[context][symbol] = ch_i; /* moved */ + int2sym[context][ch_i] = symbol; + int2sym[context][ch_symbol] = i; + } + freq[context][i]++; /* increment the frequency */ + while (i > 0) + { + i--; /* count for the symbol and */ + cmf[context][i]++; /* update the cumulative freq. */ + } +} + +float get_expected_length(int word, int context) +{ + if (word < 0 || word > num_symbol - 1) + { + printf("illegal word in get_expected_length() (%d)\n", word); + exit(1); + } + + if (context < 0 || context >= num_contexts) + { + printf("illegal context number in get_expected_length() (%d)\n", context); + exit(1); + } + + return -float(log2(double(freq[context][int2sym[context][word]]) / double(cmf[context][0]))); +} + + +/****************************************************************************/ +/* est_number() */ +/****************************************************************************/ +int est_number(int inum) +{ + int numbyte; + + if (inum < 0) + { + printf("error in est_number() %d\n", inum); + exit(1); + } + + if (inum < 128) + numbyte = 1; + /*else if(inum<32786) numbyte=2; */ + else if (inum <= (int)0xffff) + numbyte = 2; + else if (inum <= (int)0xffffffff) + numbyte = 4; + else + { + printf("error in est_number() too large\n"); + exit(1); + } + + return numbyte; +} + + + +/*****************************************************************************/ +/* entropy() */ +/*****************************************************************************/ +float entropy(int codeMAX, int total, int *pmf) +{ + int i, sum; + float H, tprob; + + if (!total) + return 0.; + + H = 0.; + sum = 0; + for (i = 0; i < codeMAX; i++) + { + tprob = (float) pmf[i] / total; + if (tprob > 0. && tprob <= 1.) + H += -tprob * (float) log2(tprob); + else if (tprob < 0. || tprob > 1.) + { + printf("error in entropy() 1\n"); + exit(1); + } + sum += pmf[i]; + } + if (sum != total) + printf("error in entropy() sum = %d, total = %d\n", sum, total); + + return H; +} diff --git a/Interframe EZBC/TempSub/src/binarcode.cpp b/Interframe EZBC/TempSub/src/binarcode.cpp new file mode 100644 index 0000000..419578c --- /dev/null +++ b/Interframe EZBC/TempSub/src/binarcode.cpp @@ -0,0 +1,205 @@ +#include +#include "mv_ec.h" +#define EXTERN extern +#include "arcode.h" + +int **contextMap = NULL; +int numSeparateBins = -1; + +int generateContextMap(int contexts, const int *multiContexts) +{ + int i, j; + int contextCounter; + + assert(contextMap == NULL); + + contextCounter = 0; + contextMap = (int**)malloc((numSeparateBins + 2) * sizeof(int*)); + for (i = 0; i < numSeparateBins + 2; i++) + { + contextMap[i] = (int*)malloc(contexts * sizeof(int)); + + if (multiContexts[i]) + { + for (j = 0; j < contexts; j++) + { + contextMap[i][j] = contextCounter; + contextCounter++; + } + } else { + for (j = 0; j < contexts; j++) + { + contextMap[i][j] = contextCounter; + } + contextCounter++; + } + } + + return contextCounter; +} + +void freeContextMap() +{ + int i; + + assert(contextMap != NULL); + + for (i = 0; i < numSeparateBins + 2; i++) + { + free(contextMap[i]); + } + free(contextMap); + + contextMap = NULL; +} + +/****************************************************************************/ +/* arencode_init() */ +/****************************************************************************/ +void binar_enc_init(int contexts, const int numSepBins, + const int *multiContexts, const int **freq_init) +{ + int totalContexts; + + numSeparateBins = numSepBins; + + totalContexts = generateContextMap(contexts, multiContexts); + + arencode_init(2, totalContexts, freq_init); +} + +/****************************************************************************/ +/* arencode_end() */ +/****************************************************************************/ +void binar_enc_end(int context) +{ + assert(contextMap != NULL); + + arencode_end(); + + freeContextMap(); +} + +/****************************************************************************/ +/* ardecode_init() */ +/****************************************************************************/ +void binar_dec_init(int contexts, const int numSepBins, + const int *multiContexts, const int **freq_init) +{ + int totalContexts; + + numSeparateBins = numSepBins; + + totalContexts = generateContextMap(contexts, multiContexts); + + ardecode_init(2, totalContexts, freq_init); +} + +/****************************************************************************/ +/* ardecode_end() */ +/****************************************************************************/ +void binar_dec_end() +{ + assert(contextMap != NULL); + + ardecode_end(); + + freeContextMap(); +} + +void binar_encode_word(int word, int context) +{ + int i; + int abs_word, bin; + + assert(contextMap != NULL); + + abs_word = (word < 0) ? (-word) : word; + + bin = 0; + for (i = 0; i < abs_word; i++) { + encode_word(0, contextMap[bin][context]); + if (bin < numSeparateBins) bin++; + } + encode_word(1, contextMap[bin][context]); + + if (word != 0) { + encode_word(word < 0, contextMap[numSeparateBins + 1][context]); + } +} + +int binar_decode_word(int context) +{ + int bin, abs_word; + + assert(contextMap != NULL); + + bin = 0; + abs_word = 0; + for (;;) { + if (decode_word(contextMap[bin][context])) break; + abs_word++; + if (bin < numSeparateBins) bin++; + } + + if (abs_word == 0) + { + return 0; + } else { + return decode_word(contextMap[numSeparateBins + 1][context]) ? + (-abs_word) : abs_word; + } +} + +/****************************************************************************/ +/* update_model() */ +/****************************************************************************/ +void binar_update_model(int word, int context) +{ + int i; + int abs_word, bin; + + assert(contextMap != NULL); + + abs_word = (word < 0) ? (-word) : word; + + bin = 0; + for (i = 0; i < abs_word; i++) { + update_model(0, contextMap[bin][context]); + if (bin < numSeparateBins) bin++; + } + update_model(1, contextMap[bin][context]); + + if (word != 0) { + update_model(word < 0, contextMap[numSeparateBins + 1][context]); + } +} + +float binar_get_expected_length(int word, int context) +{ + float length; + int i; + int abs_word, bin; + + assert(contextMap != NULL); + + length = 0.; + + abs_word = (word < 0) ? (-word) : word; + + bin = 0; + for (i = 0; i < abs_word; i++) { + length += get_expected_length(0, contextMap[bin][context]); + if (bin < numSeparateBins) bin++; + } + length += get_expected_length(1, contextMap[bin][context]); + + if (word != 0) { + length += get_expected_length(word < 0, + contextMap[numSeparateBins + 1][context]); + } + + return length; +} + + diff --git a/Interframe EZBC/TempSub/src/bitalloc.c b/Interframe EZBC/TempSub/src/bitalloc.c new file mode 100644 index 0000000..2b64071 --- /dev/null +++ b/Interframe EZBC/TempSub/src/bitalloc.c @@ -0,0 +1,2428 @@ +#include +#include +#include +#include +#include +#include "basic.h" +#include "structN.h" +#include "miscN.h" +#include "subband.h" +#include "general.h" + +#include "layer_mv.h" + +#include "zlib.h" +#include "dpx.h" + +#define EXTERN extern +#include "coderN.h" +#include "miscN.h" +#include "ioN.h" +#include "pstatN.h" +#include "basic.h" + +enum STRING{ + MAIN, RES +}; + +/* + * This function computes the bytes for each sub-bitstream in constant bit plane coding. + * Since the bytes for subband header (mean, msb) are counted in the bytes of the highest bitplane, all subbands will be + * allocated bytes for at least that bitplane. + * Here subband means sub-bitstream, since I group subbands from Y U and V at the same resolution level together. + * num_subband: number of subbands of each frame, counting on subbands of Y U V + * subband_header_bytes[frame_index][subband_index]: bytes for the subband header + * delta_r[frame_index][subband bitplane index]: increase of bytes from that subband bitplane + * num_subband_bp[frame_index]: number of subband bitplanes of that frame + * new_r[frame_index][subband bitplane index]: bytes upto that subband bitplane. + * : since subband header is included in the statistic of the first bitplane, we will sent the first bitplane of + * all subbands. + */ + +// by Yongjun Wu 不是CBR也不是VBR的进入此函数 +// change the bit allocation scheme back to the original version from Rensselaer Polytechnic Institute +// Namely the bit section is read in and arranged in 3-D style instead of 2-D style from RWTH group +int bit_alloc_VBR( videoinfo info, unsigned char *qp, long int sum_mv, long int overhead ) +{ + enum FRAME_RES { SD2, SD, CIF, HD, INVALID_RES } frame_res; + + int i, j, k, m, counter, GOPsz, curr, last, ncomps, flag, exact_b = 0, b1, + bit_plane, skipped_subband, log_my_scale = 0; + int remaining_frs, frame_rate, max_msb = 0, nbands[3]; // *GOP_header_bytes + int num_of_GOP, seq_len, num_subband, num_subband_bp; + int **subband_header_bytes, *total_subband_header_bytes; // all kinds of headers + int eff_GOPsz[20], GOP_multiplier = 1, dist, s_level; + long ***delta_r, ***bytes_upto_bp, ***delta_new_r, ***new_r, **scan, *rate, **subband_bytes; + double b, *sum_r, budget, sum_k, s_r, slope; + char seq_name[250], bitplanename[250]; + char *subband_flag, **subband_mask; + char bit_alloc_name[256]; + FILE *FID; + int qtree_depth = 0; + int *frame_max_bitplane, roll_level1, roll_level2; // by Yongjun Wu + int max_subplane=0, max_bitplane=0, *frame_max_subplane; + int exact_bp, exact_subband; + + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); + seq_name[strlen( info.bitname ) - 4] = '\0'; + + if (info.org_yheight == 480 && info.org_ywidth == 832 ) + frame_res = SD; + else if (info.org_yheight == 288 && info.org_ywidth == 352 ) + frame_res = CIF; + else if (info.org_yheight == 1080 && info.org_ywidth == 1920) + frame_res = HD; + else if (info.org_yheight == 576 && info.org_ywidth == 704) + frame_res = SD2; + + // now each frame is coded independently --- by Yongjun Wu + // it's 2-D EZBC coder instead of 3-D EZBC coder 每一帧都被单独编码,使用的是2D而不是3D EZBC + seq_len = info.last - info.start + 1; + frame_rate = info.framerate; + num_of_GOP = get_GOP_num( info ); + + if( info.denoise_flag == YES ) { + GOP_multiplier = ( YUV420 == 1 ) ? 2 : 4; + seq_len *= GOP_multiplier; + } + + // maximum bitplane number in each frame by Yongjun Wu + frame_max_bitplane = (int *)getarray(seq_len, sizeof(int), "frame_max_bitplane"); + // maximum sub-bitplane number in each frame + frame_max_subplane = (int *)getarray(seq_len, sizeof(int), "frame_max_subplane"); + // delta_r[i][j][k]: each data item, [i]: frame number, [j]: subband number, [k]: sub-bitplane number + delta_r = ( long *** )getarray( seq_len, sizeof( long * ), "delta_r" ); + // accumulated data items + bytes_upto_bp = ( long *** )getarray( seq_len, sizeof( long * ), "bytes_upto_bp" ); + + subband_header_bytes = ( int ** )getarray( seq_len, sizeof( int * ), "subband_header_bytes" ); + total_subband_header_bytes = ( int * )getarray( seq_len, sizeof( int ), "total_subband_header_bytes" ); + scan = (long **)getarray(seq_len, sizeof(long *), "scan"); + + sprintf( bitplanename, "%s.rd_sample_dat", seq_name ); + bitplanename[strlen( seq_name ) + 15] = '\0'; // + FID = fopen( bitplanename, "rb" ); + if( FID == NULL ) { + printf( "can not open file bit_rd_sample.dat\n" ); + exit( 1 ); + } + + ncomps = 1; + num_subband = 0; + for( m = 0; m < ncomps; m++ ) { // 只进行一次 + // read in the number of substreams of each frame + fscanf( FID, "%d\n", &( nbands[m] ) ); +#ifdef FREQUENCY_ROLL_OFF + if (frame_res == HD ) //Added by Yuan Liu + { +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + roll_level1 = 5; roll_level2=4; // the subband levels where we need frequency roll-off + } + else if (frame_res == SD2) + { +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + + roll_level1 = 5; roll_level2=4; // the subband levels where we need frequency roll-off + } + else if (frame_res == SD ) + { +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + + roll_level1 = 5; roll_level2=4; // the subband levels where we need frequency roll-off + } + else if (frame_res==CIF) + { + num_subband += nbands[m]+2; // the independent coded bitstreams + roll_level1=roll_level2=4; + } + else printf("Error in frequency roll-off!\n"); + +#else + num_subband += nbands[m]; // the independent coded bitstreams +#endif + } + fseek( FID, 0, SEEK_SET ); + + for(i = 0; i < seq_len; i++){ + delta_r[i] = (long **)getarray(num_subband, sizeof(long *), "delta_r[i]"); + bytes_upto_bp[i] = (long **)getarray(num_subband, sizeof(long *), "bytes_upto_bp[i]"); + subband_header_bytes[i] = (int *)getarray(num_subband, sizeof(int), "subband_header_bytes[i]"); + } + + // generate subband mask 生成子带mask + subband_mask = ( char ** )getarray( seq_len, sizeof( char * ), "subband_mask(bitalloc.c)" ); + for( i = 0; i < seq_len; i++ ) { + subband_mask[i] = ( char * )getarray( num_subband, sizeof( char ), "subband_mask[i] (bitalloc.c)" ); + for( k = 0; k < num_subband; k++ ) { + subband_mask[i][k] = 0; + } + } + + curr = info.start; + last = info.last; + counter = 0; + skipped_subband = 0; + // 设置mask等 + while( curr <= last ) { // 逐个gop处理 + remaining_frs = last - curr + 1; + // determine effective GOP size in level i + GOPsz = info.GOPsz; + for( i = 0; i <= info.tPyrLev; i++ ) { + if ( remaining_frs < info.GOPsz ) + eff_GOPsz[i] = (int) ceil ((double) remaining_frs / (pow (2, i))); + else + eff_GOPsz[i] = GOPsz; + GOPsz /= 2; + } + + // mask useless temporal high subband frames --- now each frame is coded independently 把没用的时域高频子带盖住 + GOPsz = info.GOPsz; + for( i = 0; i < info.t_level; i++ ) { + for( j = eff_GOPsz[i+1]; j < eff_GOPsz[i]; j++ ) { + for( k = 0; k < num_subband; k++ ) { + subband_mask[counter + j][k] = 1; + skipped_subband++; + } + } + } + + //mask useless spatial high subband frames; if current GOP < default GOP size, GOPsz could be 0 把没用的空域高频子带盖住 + for( i = 0; i < MY_MAX( eff_GOPsz[0], 1 ); i++ ) { + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + ncomps = 1; // since Y U V are grouped together + m = 0; + for( j = 0; j < ncomps; j++ ) { + m += nbands[j]; + +#ifdef FREQUENCY_ROLL_OFF + int subband_index; + if (frame_res == HD ) +#ifdef ROLL_STRUCTURE_ONE + subband_index = nbands[j]+2+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + subband_index = nbands[j]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD2) +#ifdef ROLL_STRUCTURE_ONE + subband_index = nbands[j]+2+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + subband_index = nbands[j]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD ) +#ifdef ROLL_STRUCTURE_ONE + subband_index = nbands[j]+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + subband_index = nbands[j]+2+11; // the independent coded bitstreams +#endif + else if (frame_res==CIF) + subband_index = nbands[j]+2; // the independent coded bitstreams + else printf("Error in frequency roll-off!\n"); +#endif + + for( k = m - s_level; k < m; k++ ) { + +#ifdef FREQUENCY_ROLL_OFF + subband_mask[counter+i][subband_index-1] = 1; + subband_index--; + skipped_subband++; + +#ifdef ROLL_STRUCTURE_ONE + if (k==roll_level1 || k==roll_level2) // additional two bands + { + for (int s=0; s<2; s++) + { + subband_mask[counter+i][subband_index-1] = 1; + subband_index--; + skipped_subband++; + } + } +#endif + +#ifdef ROLL_STRUCTURE_TWO + if (k==roll_level1 || k==roll_level2) + { + int band_num; + if (k==roll_level1) band_num = 11; // additional 11 bands + if (k==roll_level2) band_num = 2; // additional 2 bands + for (int s=0; s 0 ) { + for( i = 1; i < GOP_multiplier; i++ ) { + // mark all spatial highpass frames + for( j = 0; j < eff_GOPsz[0]; j++ ) { + for( k = 0; k < num_subband; k++ ) { + subband_mask[counter + i*eff_GOPsz[0] + j][k] = 1; + skipped_subband++; + } + } + } + } + else if( info.t_level > 0 ) { + dist = 1 << info.t_level; + for( i = 1; i < GOP_multiplier; i++ ) { + // first mark all + for( j = 0; j < eff_GOPsz[0]; j++ ) { + for( k = 0; k < num_subband; k++ ) { + subband_mask[counter + i*eff_GOPsz[0] + j][k] = 1; + skipped_subband++; + } + } + // then select temporal subbands that remain in bit stream + for( j = 0; j < eff_GOPsz[0]; j += dist ) { + for( k = 0; k < num_subband; k++ ) { + subband_mask[counter + i*eff_GOPsz[0] + j][k] = 0; + skipped_subband--; + } + } + } + } + } + + curr += info.GOPsz; + counter += info.GOPsz * GOP_multiplier; + + } /* while */ + + // *** overhead bytes for subband allocation table *** 为子带分配表的字节支出 + // sizeof(unsigned short int) is for header, 3 is the extra bytes at the end of each substream + overhead += ( sizeof( unsigned short int ) + 3 ) * ( num_subband * seq_len - skipped_subband ); + for( i = 0; i < seq_len; i++ ) { + num_subband = 0; + for( m = 0; m < ncomps; m++ ) { + // read in the number of subbands of each component + fscanf( FID, "%d\n", &( nbands[m] ) ); +#ifdef FREQUENCY_ROLL_OFF + if (frame_res == HD) + +#ifdef ROLL_STRUCTURE_ONE + { + num_subband += nbands[m] + 2 + 2; // the independent coded bitstreams + } + +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD2) + +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD ) +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + else if (frame_res==CIF) + num_subband += nbands[m]+2; // the independent coded bitstreams + else printf("Error in frequency roll-off!\n"); +#else + num_subband += nbands[m]; // the independent coded bitstreams +#endif + + } + + // read in the maximum bit plane of a frame 读一帧的最大比特平面 by Yongjun Wu + fscanf(FID, "%d\n", &(frame_max_bitplane[i])); + if(frame_max_bitplane[i] > max_bitplane) max_bitplane = frame_max_bitplane[i]; + // read in the maximum sub-bitplane of a frame + fscanf( FID, "%d\n", &( frame_max_subplane[i] ) ); + if( frame_max_subplane[i] > max_subplane ) max_subplane = frame_max_subplane[i]; + + // scan bit planes of each subband + for(j=0; j=0; j--){ + for(m=0; m=0; j--){ + for(m=0; m=0; j--){ + delta_new_r[i][m][j]=0; + } + } + } + } + + // form the accumulated sum of bits for each subband and save the sum in new_r + for(i=0; i=0; k--){ + new_r[i][j][k] = new_r[i][j][k+1] + delta_new_r[i][j][k]; + } + } + } + + + for(i=0; i=0; k--){ + for(j=0; j=0; j--){ + for (i=0; i budget ) { // bit plane max_msb + printf( " bitalloc.c: can not handle this case: budget is too small ( %f ).\n", budget ); + // exit( 1 ); + return 0; + } else { // else1 + if( sum_r[num_subband_bp - 1] == budget ) { + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else2 + if( sum_r[0] < budget ) { + exact_b = 0; + flag = 0; + budget = sum_r[0]; + printf( " bitalloc.c: no more data in the bit stream for allocation.\n" ); + } else { //else3 // find the interval + for( j = num_subband_bp - 2; j >= 0; j-- ) { // the other bit planes + if( sum_r[j] > budget ) { + b1 = j; // record the index + flag = 1; + break; + } else { + if( sum_r[j] == budget ) { + exact_b = j; + flag = 0; + break; + } + } + } // for(j) + } // else3 + } // else2 + } // else1 + + + subband_bytes = ( long ** )getarray( seq_len, sizeof( long * ), "subband_bytes" ); + + for( i = 0; i < seq_len; i++ ) { + subband_bytes[i] = ( long * )getarray( num_subband, sizeof( long ), "num_subband" ); + for( j = 0; j < num_subband; j++ ) { + subband_bytes[i][j] = 0; + } + } + + + if (flag == 0){ // perfect match + exact_bp = exact_b / num_subband; + exact_subband = num_subband - 1 - exact_b%num_subband; + for(i=0; i 0 ) { + if( ! subband_mask[i][j] ) { + subband_bytes[i][j] += 3; + } + } + } + + + + /**********/ + /* OUTPUT */ + /**********/ + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, info.bitrate ); + FID = fopen( bit_alloc_name, "wb" ); + + fprintf( FID, "%d\n", num_subband ); + + for( i = 0; i < seq_len; i++ ) { + for( m = 0; m < num_subband; m++ ) { + fprintf( FID, "%ld\n", subband_bytes[i][m] ); + } + } + fclose( FID ); + + + for(i=0; i max_bitplane) max_bitplane = frame_max_bitplane[i]; + // read in the maximum sub-bitplane of a frame + fscanf( FID, "%d\n", &( frame_max_subplane[i] ) ); + if( frame_max_subplane[i] > max_subplane ) max_subplane = frame_max_subplane[i]; + + // scan bit planes of each subband + for(j=0; j=0; j--){ + + for(m=0; m=0; j--){ + for(m=0; m=0; j--){ + delta_new_r[i][m][j]=0; + } + } + } + } // NOT WORKING + + // form the accumulated sum of bits for each subband and save the sum in new_r + for(i=0; i=0; k--){ + new_r[i][j][k] = new_r[i][j][k+1] + delta_new_r[i][j][k]; + } + } + } + + for(i=0; i=0; k--){ + for(j=0; j=0; j--){ + for (i=0; i budget ) { // bit plane max_msb + printf( " bitalloc.c: can not handle this case: budget is too small ( %f ).\n", budget ); + // exit( 1 ); + return 0; + } else { // else1 + if( sum_r[num_subband_bp - 1] == budget ) { + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else2 + if( sum_r[0] < budget ) { + exact_b = 0; + flag = 0; + budget = sum_r[0]; + printf( " bitalloc.c: no more data in the bit stream for allocation.\n" ); + } else { //else3 // find the interval + for( j = num_subband_bp - 2; j >= 0; j-- ) { // the other bit planes + if( sum_r[j] > budget ) { + b1 = j; // record the index + flag = 1; + break; + } else { + if( sum_r[j] == budget ) { + exact_b = j; + flag = 0; + break; + } + } + } // for(j) + } // else3 + } // else2 + } // else1 + + + if (flag == 0){ // perfect match + exact_bp = exact_b / num_subband; + exact_subband = num_subband - 1 - exact_b%num_subband; + for(i=0; i 0 ) { + if( ! subband_mask[i][j] ) { + subband_bytes[i][j] += 3; + } + } + } +*/ +/////////////////////////////// CBR ////////////////////////////////// + + curr = 0; + last = curr_last - info.start; + + for( i = 0; i < seq_len; i++ ) { + for( j = 0; j < num_subband; j++ ) { + subband_bytes[i][j] = 0; + } + } + + counter = 0; + + while( curr <= last ){ + + GOP_budget = ( double )info.bitrate * 1000 / 8 * ( info.GOPsz ) / frame_rate; + GOP_budget = GOP_budget - GOP_overhead - gop_sum_mv[counter]; + printf("GOP_overhead = %d, gop_sum_mv = %ld, GOP_budget = %f\n", GOP_overhead, gop_sum_mv[counter],GOP_budget); +//Part 1 + for (j=0; j=0; j--){ + for (i=curr; i GOP_budget ) { // bit plane max_msb + printf( " bitalloc.c: can not handle this case: GOP_budget is too small ( %f ) for GOP %d.\n", GOP_budget, counter ); +// exit( 1 ); +// return 0; +//Revised on 06.16.2019 + GOP_budget = sum_r[num_subband_bp - 1]; + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else1 + if( sum_r[num_subband_bp - 1] == GOP_budget ) { + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else2 + if( sum_r[0] < GOP_budget ) { + exact_b = 0; + flag = 0; + GOP_budget = sum_r[0]; + printf( " bitalloc.c: no more data in the bit stream for allocation.\n" ); + } else { //else3 // find the interval + for( j = num_subband_bp - 2; j >= 0; j-- ) { // the other bit planes + if( sum_r[j] > GOP_budget ) { + b1 = j; // record the index + flag = 1; + break; + } else { + if( sum_r[j] == GOP_budget ) { + exact_b = j; + flag = 0; + break; + } + } + } // for(j) + } // else3 + } // else2 + } // else1 + +//Part 3 + if (flag == 0){ // perfect match +// assert(0); + printf("perfect match detected!\n"); + exact_bp = exact_b / num_subband; + exact_subband = num_subband - 1 - exact_b%num_subband; + for(i=curr; i 0) ? (seq_len - info.GOPsz * 2) : 0; + + res_frame = info.act_last - curr + 1; + if( res_frame > 0 && res_frame < info.GOPsz ){ + do_res = YES; + for(i = 0; i < info.tPyrLev ; i ++){ + getnum = res_frame / 2; + level_res_frame[i] = getnum; + res_frame = res_frame - getnum; + } + }else{ + do_res = NO; + } + }else{ + assert(res_exist == NO); + do_res = NO; + curr = seq_len - info.GOPsz; + } + + if(do_res == NO){ + for(i = 0; i < seq_len; i ++){ + if(i < curr ) + seq_sort[i] = MAIN; + else + seq_sort[i] = RES; + } + }else{ + assert(do_res == YES && res_exist == YES); + for(i = 0; i < curr; i ++) + seq_sort[i] = MAIN; +///////////////////// + seq_sort[curr] = MAIN; + res_frame = 1; + res_level = info.tPyrLev - 1; + for(i = curr + 1; i < curr + info.GOPsz; i ++){ + if( (i-curr) == res_frame*2 ){ + res_frame = res_frame*2; + res_level --; + } + + if( (i-curr-res_frame) < level_res_frame[res_level] ) + seq_sort[i] = MAIN; + else + seq_sort[i] = RES; + } +//////////////////// + for(i = curr + info.GOPsz; i < seq_len; i ++) + seq_sort[i] = RES; + } + + getnum = 0; + for(i = 0; i < seq_len; i ++) + if(seq_sort[i] == MAIN) + getnum ++; + else + assert(seq_sort[i] == RES); + + seq_len_vbr = getnum; + + printf("res_exist = %d, do_res = %d, main frame number: %d, res frame number: %d\n", res_exist, do_res, seq_len_vbr, seq_len-seq_len_vbr); + +///////////////////////////////////////////////////////////////////////////////// +// seq_len_vbr = seq_len; + frame_rate = info.framerate; + num_of_GOP = get_GOP_num( info ); + + act_num_of_GOP = (long int) ( (seq_len_vbr - 1 - info.start + info.GOPsz) / info.GOPsz ); + + if( info.denoise_flag == YES ) { + GOP_multiplier = ( YUV420 == 1 ) ? 2 : 4; + seq_len *= GOP_multiplier; + } + + printf("seq_len = %d\n",seq_len); + + // maximum bitplane number in each frame by Yongjun Wu + frame_max_bitplane = (int *)getarray(seq_len, sizeof(int), "frame_max_bitplane"); + // maximum sub-bitplane number in each frame + frame_max_subplane = (int *)getarray(seq_len, sizeof(int), "frame_max_subplane"); + // delta_r[i][j][k]: each data item, [i]: frame number, [j]: subband number, [k]: sub-bitplane number + delta_r = ( long *** )getarray( seq_len, sizeof( long * ), "delta_r" ); + // accumulated data items + bytes_upto_bp = ( long *** )getarray( seq_len, sizeof( long * ), "bytes_upto_bp" ); + + subband_header_bytes = ( int ** )getarray( seq_len, sizeof( int * ), "subband_header_bytes" ); + total_subband_header_bytes = ( int * )getarray( seq_len, sizeof( int ), "total_subband_header_bytes" ); + scan = (long **)getarray(seq_len, sizeof(long *), "scan"); + + GOP_num_subband_bp = (int *)getarray(num_of_GOP, sizeof( int * ), "GOP_num_subband_bp" ); + + sprintf( bitplanename, "%s.rd_sample_dat", seq_name ); + bitplanename[strlen( seq_name ) + 15] = '\0'; // + FID = fopen( bitplanename, "rb" ); + if( FID == NULL ) { + printf( "can not open file bit_rd_sample.dat\n" ); + exit( 1 ); + } + + ncomps = 1; + num_subband = 0; + for( m = 0; m < ncomps; m++ ) { + // read in the number of substreams of each frame + fscanf( FID, "%d\n", &( nbands[m] ) ); +#ifdef FREQUENCY_ROLL_OFF + if (frame_res == HD ) //Added by Yuan Liu + { +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + roll_level1 = 5; roll_level2=4; // the subband levels where we need frequency roll-off + } + else if (frame_res == SD2) + { +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + + roll_level1 = 5; roll_level2=4; // the subband levels where we need frequency roll-off + } + else if (frame_res == SD ) + { +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + + roll_level1 = 5; roll_level2=4; // the subband levels where we need frequency roll-off + } + else if (frame_res==CIF) + { + num_subband += nbands[m]+2; // the independent coded bitstreams + roll_level1=roll_level2=4; + } + else printf("Error in frequency roll-off!\n"); + +#else + num_subband += nbands[m]; // the independent coded bitstreams +#endif + } + fseek( FID, 0, SEEK_SET ); + + for(i = 0; i < seq_len; i++){ + delta_r[i] = (long **)getarray(num_subband, sizeof(long *), "delta_r[i]"); + bytes_upto_bp[i] = (long **)getarray(num_subband, sizeof(long *), "bytes_upto_bp[i]"); + subband_header_bytes[i] = (int *)getarray(num_subband, sizeof(int), "subband_header_bytes[i]"); + } + + // generate subband mask + subband_mask = ( char ** )getarray( seq_len, sizeof( char * ), "subband_mask(bitalloc.c)" ); + for( i = 0; i < seq_len; i++ ) { + subband_mask[i] = ( char * )getarray( num_subband, sizeof( char ), "subband_mask[i] (bitalloc.c)" ); + for( k = 0; k < num_subband; k++ ) { + subband_mask[i][k] = 0; + } + } + + curr = info.start; + last = curr_last; + counter = 0; + skipped_subband = 0; + while( curr <= last ) { + remaining_frs = last - curr + 1; + // determine effective GOP size in level i + GOPsz = info.GOPsz; + for( i = 0; i <= info.tPyrLev; i++ ) { + if ( remaining_frs < info.GOPsz ) + eff_GOPsz[i] = (int) ceil ((double) remaining_frs / (pow (2, i))); + else + eff_GOPsz[i] = GOPsz; + GOPsz /= 2; + } + + //mask useless temporal high subband frames --- now each frame is coded independently + GOPsz = info.GOPsz; + for( i = 0; i < info.t_level; i++ ) { + for( j = eff_GOPsz[i+1]; j < eff_GOPsz[i]; j++ ) { + for( k = 0; k < num_subband; k++ ) { + assert(0); + subband_mask[counter + j][k] = 1; + skipped_subband++; + } + } + } + + //mask useless spatial high subband frames; if current GOP < default GOP size, GOPsz could be 0 + for( i = 0; i < MY_MAX( eff_GOPsz[0], 1 ); i++ ) { + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + ncomps = 1; // since Y U V are grouped together + m = 0; + for( j = 0; j < ncomps; j++ ) { + m += nbands[j]; + +#ifdef FREQUENCY_ROLL_OFF + int subband_index; + if (frame_res == HD ) +#ifdef ROLL_STRUCTURE_ONE + subband_index = nbands[j]+2+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + subband_index = nbands[j]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD2) +#ifdef ROLL_STRUCTURE_ONE + subband_index = nbands[j]+2+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + subband_index = nbands[j]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD ) +#ifdef ROLL_STRUCTURE_ONE + subband_index = nbands[j]+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + subband_index = nbands[j]+2+11; // the independent coded bitstreams +#endif + else if (frame_res==CIF) + subband_index = nbands[j]+2; // the independent coded bitstreams + else printf("Error in frequency roll-off!\n"); +#endif + + } + } + + curr += info.GOPsz; + counter += info.GOPsz * GOP_multiplier; + } /* while */ + + // *** overhead bytes for subband allocation table *** + // sizeof(unsigned short int) is for header, 3 is the extra bytes at the end of each substream + +// printf("skipped_subband = %d\n",skipped_subband); + + overhead += ( sizeof( unsigned short int ) + 3 ) * ( num_subband * (info.last - info.start + 1) - skipped_subband ); + + GOP_overhead = overhead / num_of_GOP; + + for( i = 0; i < seq_len; i++ ) { + num_subband = 0; + for( m = 0; m < ncomps; m++ ) { + // read in the number of subbands of each component + fscanf( FID, "%d\n", &( nbands[m] ) ); +#ifdef FREQUENCY_ROLL_OFF + if (frame_res == HD ) + +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD2) + +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2+2; // the independent coded bitstreams +#endif + +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + else if (frame_res == SD ) +#ifdef ROLL_STRUCTURE_ONE + num_subband += nbands[m]+2; // the independent coded bitstreams +#endif +#ifdef ROLL_STRUCTURE_TWO + num_subband += nbands[m]+2+11; // the independent coded bitstreams +#endif + else if (frame_res==CIF) + num_subband += nbands[m]+2; // the independent coded bitstreams + else printf("Error in frequency roll-off!\n"); +#else + num_subband += nbands[m]; // the independent coded bitstreams +#endif + + } + + // read in the maximum bit plane of a frame by Yongjun Wu + fscanf(FID, "%d\n", &(frame_max_bitplane[i])); + if(frame_max_bitplane[i] > max_bitplane) max_bitplane = frame_max_bitplane[i]; + // read in the maximum sub-bitplane of a frame + fscanf( FID, "%d\n", &( frame_max_subplane[i] ) ); + if( frame_max_subplane[i] > max_subplane ) max_subplane = frame_max_subplane[i]; + + // scan bit planes of each subband + for(j=0; j=0; j--){ + + for(m=0; m=0; j--){ + for(m=0; m=0; j--){ + delta_new_r[i][m][j]=0; + } + } + } + } // NOT WORKING + + // form the accumulated sum of bits for each subband and save the sum in new_r + for(i=0; i=0; k--){ + new_r[i][j][k] = new_r[i][j][k+1] + delta_new_r[i][j][k]; + } + } + } + + for(i=0; i=0; k--){ + for(j=0; j=0; j--){ + for (i=0; i=0; j--){ + for( i = 0; i < seq_len; i++ ) { + if(seq_sort[i] == MAIN) + sum_r[j] = sum_r[j] + scan[i][j]; + } + } // loop of i (no_stream) + +//Part 2 + if( sum_r[num_subband_bp - 1] > budget ) { // bit plane max_msb + printf( " bitalloc.c: can not handle this case: budget is too small ( %f ) for GOP %d.\n", budget, 0 ); + // exit( 1 ); + return 0; + } else { // else1 + if( sum_r[num_subband_bp - 1] == budget ) { + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else2 + if( sum_r[0] < budget ) { + exact_b = 0; + flag = 0; + budget = sum_r[0]; + printf( " bitalloc.c: no more data in the bit stream for allocation.\n" ); + } else { //else3 // find the interval + for( j = num_subband_bp - 2; j >= 0; j-- ) { // the other bit planes + if( sum_r[j] > budget ) { + b1 = j; // record the index + flag = 1; + break; + } else { + if( sum_r[j] == budget ) { + exact_b = j; + flag = 0; + break; + } + } + } // for(j) + } // else3 + } // else2 + } // else1 + +//Part 3 + if (flag == 0){ // perfect match +// assert(0); + printf("perfect match detected!\n"); + exact_bp = exact_b / num_subband; + exact_subband = num_subband - 1 - exact_b%num_subband; + for( i = 0; i < seq_len; i++ ) { + if(seq_sort[i] == MAIN){ + for(m=0; m<=exact_subband; m++){ + subband_bytes[i][m] = new_r[i][m][exact_bp]; + } + if(exact_bp < max_subplane){ + for(m=exact_subband+1; m=0; j--){ + for( i = 0; i < seq_len; i++ ) { + if(seq_sort[i] == RES) + sum_r[j] = sum_r[j] + scan[i][j]; + } + } // loop of i (no_stream) + +//Part 2 + if( sum_r[num_subband_bp - 1] > GOP_budget ) { // bit plane max_msb + printf( " bitalloc.c: can not handle this case: GOP_budget is too small ( %f ) for GOP %d.\n", GOP_budget, counter ); + // exit( 1 ); + return 0; + } else { // else1 + if( sum_r[num_subband_bp - 1] == GOP_budget ) { + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else2 + if( sum_r[0] < GOP_budget ) { + exact_b = 0; + flag = 0; + GOP_budget = sum_r[0]; + printf( " bitalloc.c: no more data in the bit stream for allocation.\n" ); + } else { //else3 // find the interval + for( j = num_subband_bp - 2; j >= 0; j-- ) { // the other bit planes + if( sum_r[j] > GOP_budget ) { + b1 = j; // record the index + flag = 1; + break; + } else { + if( sum_r[j] == GOP_budget ) { + exact_b = j; + flag = 0; + break; + } + } + } // for(j) + } // else3 + } // else2 + } // else1 + +//Part 3 + if (flag == 0){ // perfect match +// assert(0); + printf("perfect match detected!\n"); + exact_bp = exact_b / num_subband; + exact_subband = num_subband - 1 - exact_b%num_subband; + for( i = 0; i < seq_len; i++ ) { + if(seq_sort[i] == RES){ + for(m=0; m<=exact_subband; m++){ + subband_bytes[i][m] = new_r[i][m][exact_bp]; + } + if(exact_bp < max_subplane){ + for(m=exact_subband+1; m budget ) { // bit plane max_msb + printf( " bitalloc.c: can not handle this case: budget is too small ( %f ).\n", budget ); + // exit( 1 ); + return 0; + } else { // else1 + if( sum_r[num_subband_bp - 1] == budget ) { + exact_b = num_subband_bp - 1; + flag = 0; + } else { // else2 + if( sum_r[0] < budget ) { + exact_b = 0; + flag = 0; + budget = sum_r[0]; + printf( " bitalloc.c: no more data in the bit stream for allocation.\n" ); + } else { //else3 // find the interval + for( j = num_subband_bp - 2; j >= 0; j-- ) { // the other bit planes + if( sum_r[j] > budget ) { + b1 = j; // record the index + flag = 1; + break; + } else { + if( sum_r[j] == budget ) { + exact_b = j; + flag = 0; + break; + } + } + } // for(j) + } // else3 + } // else2 + } // else1 + + + if (flag == 0){ // perfect match + exact_bp = exact_b / num_subband; + exact_subband = num_subband - 1 - exact_b%num_subband; + for(i=0; i 0 ) { + if( ! subband_mask[i][j] ) { + subband_bytes[i][j] += 3; + } + } + } +*/ + + /**********/ + /* OUTPUT */ + /**********/ + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, info.bitrate ); + FID = fopen( bit_alloc_name, "wb" ); + + fprintf( FID, "%d\n", num_subband ); + + for( i = 0; i < seq_len; i++ ) { + for( m = 0; m < num_subband; m++ ) { + fprintf( FID, "%ld\n", subband_bytes[i][m] ); + } + } + fclose( FID ); + + + for(i=0; i +#include +#include +#include +#include +#include "iostream" +#define EXTERN extern +#include "basic.h" +#include "structN.h" +#include "coderN.h" +#include "bmeN.h" +#include "util_filtering.h" +#include "miscN.h" +#include "hvsbm_fullres.h" +#include "bme_tools.h" +#include "Choisubband.h" + +#include "mv_ec.h" + +#define FixOL 0 /* Overlap mode for FSBM */ +#define VarOL 1 /* Overlap mode for HVSBM */ + +#define bit_coef 1 + +void print_time( double sc ); + +float getFrameSATD(float *fr, int hor, int ver) +{ + int i; + int lenx, leny; + float *image; + float sum; + + // initialization + image = (float*)getarray(hor * ver, sizeof(float), "image"); + + for (i = 0; i < hor * ver; i++) { + image[i] = fr[i]; + } + + // wavelet decomposition + lenx = hor; + leny = ver; + while (!((lenx % 2) || (leny % 2))) { + // use normalized 9/7 filter + analysis(image, 0, 0, lenx, leny, hor, ver, 7); + + lenx = (lenx >> 1); + leny = (leny >> 1); + } + + // generate SAD + sum = 0.; + for (i = 0; i < hor * ver; i++) { + sum = (image[i] < 0) ? (sum - image[i]) : (sum + image[i]); + } + + // tidy up + free(image); + + return sum; +} + + +/* + * calculate MCP_MSE + * frame1 : current + * frame0 : reference + * (cx,cy): the coordinator of the upper left corner + * mvx : horizontal motion vector + * mvy : vertical motion vector + * xblk : real block width + * yblk : real block height + * hor : frame width + * ver : frame height + */ +float +MCP_MSE( float *frame_cur, int cx, int cy, + float *frame_ref1, float mvx1, float mvy1, + float *frame_ref2, float mvx2, float mvy2, + int xblk, int yblk, int hor, int ver ) +{ + int y, x, m; + float px1, py1; + float px2, py2; + float diff, ptemp, mean, sum; + + m = cy * hor + cx; + + sum = 0.; + mean = 0.; + + if (frame_ref2 == NULL) { + px1 = cx - mvx1; + py1 = cy - mvy1; + + for( y = 0; y < yblk; y++ ) { + for( x = 0; x < xblk; x++ ) { + ptemp = interpolate( px1 + x, py1 + y, frame_ref1, hor, ver, TYPE ); + diff = frame_cur[m] - ptemp; + sum += diff * diff; + mean += diff; + m++; + } /* x */ + m += hor - xblk; + } /* y */ + } else { + px1 = cx - mvx1; + py1 = cy - mvy1; + px2 = cx - mvx2; + py2 = cy - mvy2; + + for( y = 0; y < yblk; y++ ) { + for( x = 0; x < xblk; x++ ) { + ptemp = interpolate( px1 + x, py1 + y, frame_ref1, hor, ver, TYPE ) + + interpolate( px2 + x, py2 + y, frame_ref2, hor, ver, TYPE ); + diff = frame_cur[m] - 0.5f * ptemp; + sum += diff * diff; + mean += diff; + m++; + } /* x */ + m += hor - xblk; + } /* y */ + } + sum /= xblk * yblk; + + return sum; +} + +/************************************************************************** + * find_diff() + * calculate differential subband and variance of blocks at all tree nodes and decide mode. + * fmv : motion vector of a block at a tree node + * frame1 : curren + * frame0 : reference + * (cx,cy) : the coordinator of the upper left corner + * xblock : block width + * yblock : block height + * hor : frame width + * ver : frame height + * t_level : temporal decomposition level (begin with 0) + *************************************************************************/ +void +find_diff( vector_ptr fmv, float *frame1, float *frame2, float *D, + int cx, int cy, int xblock, int yblock, int hor, int ver, + int t_level, int type ) +{ + int xblk, yblk; + float pfx, pfy, ptemp1, ptemp2, diff; + float px1, py1, px2, py2; + + int x,y,m,m0; + + assert(fmv && frame1); + + m = cy * hor + cx; + m0 = 0; + + xblk = ( cx + xblock <= hor ) ? xblock : hor - cx; // real block width + yblk = ( cy + yblock <= ver ) ? yblock : ver - cy; // real block height + + if( xblk <= 0 || yblk <= 0 ) { /* if block size if null, then return */ + return; + } + + px1 = cx - fmv->mvx; + py1 = cy - fmv->mvy; + px2 = cx + fmv->mvx; + py2 = cy + fmv->mvy; + + if(type == 0){ + for( y = 0; y < yblk; y++ ) { + for( x = 0; x < xblk; x++ ) { + + ptemp2 = interpolate( px2 + x, py2 + y, frame2, hor, ver, TYPE ); + diff = ptemp2 - frame1[m]; + D[m0] = diff; + m++; + m0++; + } /* x */ + m += hor - xblk; + } + }else{ + assert(type == 1); + + for( y = 0; y < yblk; y++ ) { + for( x = 0; x < xblk; x++ ) { + ptemp1 = interpolate( px1 + x, py1 + y, frame1, hor, ver, TYPE ); + + ptemp2 = interpolate( px2 + x, py2 + y, frame2, hor, ver, TYPE ); + + diff = ptemp2 - ptemp1; + D[m0] = diff; + m++; + m0++; + } /* x */ + m += hor - xblk; + } + } + + assert( m0 == (xblk*yblk) ); + +} + + +float +get_sad( float mvx, float mvy, float *D1, float *D2, int *Dx, + int xblk, int yblk, int t_level, int type ) +{ + int i,j,m; + float pfx,pfy; + int xpos,ypos; + float ptemp, diff; + + float sum = 0; + + for(m = 0 ; m < (xblk * yblk) ; m ++){ + xpos = (m % xblk); + ypos = (int)(m/yblk); + + pfx = xpos - mvx; + pfy = ypos - mvy; + + if(xpos >= 0 && xpos < xblk && pfx >= 0 && pfx < xblk && + ypos >= 0 && ypos < yblk && pfy >= 0 && pfy < yblk ){ + ptemp = interpolate( pfx, pfy, D2, xblk, yblk, TYPE ); + + diff = D1[ypos * xblk + xpos] - ptemp; + }else{ + diff = D1[ypos * xblk + xpos]; + } + + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + if(type == 1) + Dx[ypos * xblk + xpos] = (int)fabs(diff); + } + + return sum; +} + + +int +two_comp_est( float *mvx, float *mvy, vector_ptr fmv, float *frame_cur, float *frame_ref1, float *frame_ref2, float *SAD, + int cx, int cy, int xblk, int yblk, int hor, int ver, int t_level ){ + + float i,j; + int m,n, a,b, real = 0; + float pfx1, pfy1, ptemp1,pfx2, pfy2, ptemp2; + float int_mvx, int_mvy, get_mvx, get_mvy, tpx, tpy; + float best_sad,sum; + int well_count, cum_count = 0; + + float diff; + + int range = 12; + + float thres = 2.5; + + printf("fmv1->mvx = %f, fmv1->mvy = %f\n",fmv->mvx,fmv->mvy); + + *SAD = (float)HUGE_VAL; + + for(i=(-1)*range ; i <= range; i ++){ + for(j=(-1)*range ; j <= range; j ++){ + + tpx = fmv->mvx + i; + tpy = fmv->mvy + j; + well_count = 0; + + m = cy * hor + cx; + best_sad = 0; + + for( a = 0; a < yblk; a ++ ){ + for( b = 0; b < xblk; b ++ ){ + pfx1 = (float)cx - tpx + b; + pfy1 = (float)cy - tpy + a; + pfx2 = (float)cx + tpx + b; + pfy2 = (float)cy + tpy + a; + +// printf("pfx1 = %f, pfy1 = %f, pfx2 = %f, pfy2 = %f\n",pfx1,pfy1,pfx2,pfy2); + + if( pfx1 >= hor || pfx1 < 0 || pfy1 >= ver || pfy1 < 0 || pfx2 >= hor || pfx2 < 0 || pfy2 >= ver || pfy2 < 0 ){ + printf("jump out!\n"); + goto sign_out1; + } + + ptemp1 = interpolate( pfx1, pfy1, frame_ref1, hor, ver, TYPE ); + ptemp2 = interpolate( pfx2, pfy2, frame_ref2, hor, ver, TYPE ); + +// printf("fr_cur = %f, ptemp1 = %f, ptemp2 = %f\n",frame_cur[m],ptemp1,ptemp2); + + diff = frame_cur[m] - 0.5f * (ptemp1 + ptemp2); + + best_sad = ( diff < 0 ) ? (best_sad - diff) : (best_sad + diff); + + if( fabs(diff) <= thres ){ + well_count ++; +// printf("diff = %f\n",diff); + } + + m++; + } + m += hor - xblk; + } + + if( well_count > cum_count ){ + cum_count = well_count; + *mvx = tpx; + *mvy = tpy; + } + + if(best_sad < *SAD) + *SAD = best_sad; + +sign_out1: ; + + } //j + } //i + + int_mvx = *mvx; + int_mvy = *mvy; + +//sub-pixel search + for(i= -0.75 ; i <= 0.75; i += 0.25){ + for(j= -0.75 ; j <= 0.75; j += 0.25){ + + tpx = int_mvx + i; + tpy = int_mvy + j; + well_count = 0; + + m = cy * hor + cx; + best_sad = 0; + + for( a = 0; a < yblk; a ++ ){ + for( b = 0; b < xblk; b ++ ){ + pfx1 = (float)cx - tpx + b; + pfy1 = (float)cy - tpy + a; + pfx2 = (float)cx + tpx + b; + pfy2 = (float)cy + tpy + a; + +// printf("pfx1 = %f, pfy1 = %f, pfx2 = %f, pfy2 = %f\n",pfx1,pfy1,pfx2,pfy2); + + if( pfx1 >= hor || pfx1 < 0 || pfy1 >= ver || pfy1 < 0 || pfx2 >= hor || pfx2 < 0 || pfy2 >= ver || pfy2 < 0 ){ + printf("jump out!\n"); + goto sign_out2; + } + + ptemp1 = interpolate( pfx1, pfy1, frame_ref1, hor, ver, TYPE ); + ptemp2 = interpolate( pfx2, pfy2, frame_ref2, hor, ver, TYPE ); + + diff = frame_cur[m] - 0.5f * (ptemp1 + ptemp2); + + best_sad = ( diff < 0 ) ? (best_sad - diff) : (best_sad + diff); + + if( fabs(diff) <= thres ){ + well_count ++; +// printf("diff = %f\n",diff); + } + + m++; + } + m += hor - xblk; + } + + if( well_count > cum_count ){ + cum_count = well_count; + *mvx = tpx; + *mvy = tpy; + } + + if(best_sad < *SAD) + *SAD = best_sad; + +sign_out2: ; + + } //j + } //i + + printf("cx = %d, cy = %d, xblk = %d, yblk = %d, cum_count = %d, \nsearch sad = %f\n",cx,cy,xblk,yblk,cum_count,*SAD); + + if( cum_count > (xblk*yblk/3) ){ + real = 1; + assert(*SAD != (float)HUGE_VAL); + } + + return real; +} + +/************************************************************************** + * local_diff_search() + * calculate differential subband and variance of blocks at all tree nodes and decide mode. + * fmv : motion vector of a block at a tree node + * frame1 : curren + * frame0 : reference + * (cx,cy) : the coordinator of the upper left corner + * xblock : block width + * yblock : block height + * hor : frame width + * ver : frame height + * t_level : temporal decomposition level (begin with 0) + *************************************************************************/ +float +local_diff_search( float *mvx, float *mvy, float *D1, float *D2, int *Dx, + int xblk, int yblk, int hor, int ver, int t_level ) +{ + float px2, py2; + float i,j; + float pfx, pfy, ptemp; + float px1, py1; + float best_sad,sum; + + int mvx_int, mvy_int; + + int xpos,ypos, xpos_ref, ypos_ref; + float diff; + + int x,y,m,m0; + + int range = 15; + + if( xblk <= 0 || yblk <= 0 ) { /* if block size if null, then return */ + return (float)HUGE_VAL; + } + + best_sad = 0; + + for(m = 0 ; m < (xblk * yblk) ; m ++){ + ptemp = D1[m] - D2[m]; + best_sad = ( ptemp < 0 ) ? (best_sad - ptemp) : (best_sad + ptemp); + Dx[m] = (int)fabs(ptemp); + } + + printf("original sad = %f\n\n",best_sad); + + *mvx = 0; + *mvy = 0; + +//integer position search + for(i=(-1)*range ; i <= range; i ++){ + for(j=(-1)*range ; j <= range; j ++){ + + sum = 0; + + for(m = 0 ; m < (xblk * yblk) ; m ++){ + xpos = (m % xblk); + ypos = (int)(m/yblk); + + xpos_ref = xpos - i; + ypos_ref = ypos - j; + + if(xpos >= 0 && xpos < xblk && xpos_ref >= 0 && xpos_ref < xblk && + ypos >= 0 && ypos < yblk && ypos_ref >= 0 && ypos_ref < yblk ){ + diff = D1[ypos * xblk + xpos] - D2[ypos_ref * xblk + xpos_ref]; + }else{ + diff = D1[ypos * xblk + xpos]; + } + + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + } + + if(sum < best_sad){ + best_sad = sum; + *mvx = i; + *mvy = j; + printf("best_sad = %f\n",best_sad); + } + } + } + + mvx_int = *mvx; + mvy_int = *mvy; + +//quarter-pixel search + printf("\n\nsub-pixel search\n\n"); + for(i= -0.75 ; i <= 0.75; i += 0.25){ + for(j= -0.75 ; j <= 0.75; j += 0.25){ + + sum = 0; + + for(m = 0 ; m < (xblk * yblk) ; m ++){ + xpos = (m % xblk); + ypos = (int)(m/yblk); + + pfx = xpos - mvx_int - i; + pfy = ypos - mvy_int - j; + + if(xpos >= 0 && xpos < xblk && pfx >= 0 && pfx < xblk && + ypos >= 0 && ypos < yblk && pfy >= 0 && pfy < yblk ){ + ptemp = interpolate( pfx, pfy, D2, xblk, yblk, TYPE ); + + diff = D1[ypos * xblk + xpos] - ptemp; + }else{ + diff = D1[ypos * xblk + xpos]; + } + + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + } + + if(sum < best_sad){ + best_sad = sum; + *mvx = mvx_int + i; + *mvy = mvy_int + j; + printf("best_sad = %f\n",best_sad); + } + } + } + + printf("\nmvx = %f, mvy = %f\n\n",*mvx,*mvy); + +//save difference block + + for(m = 0 ; m < (xblk * yblk) ; m ++){ + xpos = (m % xblk); + ypos = (int)(m/yblk); + + pfx = xpos - *mvx; + pfy = ypos - *mvy; + + if(xpos >= 0 && xpos < xblk && pfx >= 0 && pfx < xblk && + ypos >= 0 && ypos < yblk && pfy >= 0 && pfy < yblk ){ + + ptemp = interpolate( pfx, pfy, D2, xblk, yblk, TYPE ); + + diff = D1[ypos * xblk + xpos] - ptemp; + }else{ + diff = D1[ypos * xblk + xpos]; + } + + Dx[m] = fabs(diff); + } + + return best_sad; +} + +/************************************************************************** + * find_MSE() + * calculate MSE and variance of blocks at all tree nodes and decide mode. + * fmv : motion vector of a block at a tree node + * frame1 : curren + * frame0 : reference + * (cx,cy) : the coordinator of the upper left corner + * xblock : block width + * yblock : block height + * hor : frame width + * ver : frame height + * t_level : temporal decomposition level (begin with 0) + *************************************************************************/ + +void +find_MSE( vector_ptr fmv1, vector_ptr fmv2, + float *frame_cur, float *frame_ref1, float *frame_ref2, + int cx, int cy, int xblock, int yblock, int hor, int ver, + int t_level ) +{ + int xblk, yblk, px1, py1, px2, py2; + float pfx, pfy, ref_var; + + assert(fmv1 && frame_ref1); + assert((fmv2 && frame_ref2) || (!fmv2 && !frame_ref2)); + + temporal_filter(); + + xblk = ( cx + xblock <= hor ) ? xblock : hor - cx; // real block width + yblk = ( cy + yblock <= ver ) ? yblock : ver - cy; // real block height + + if( xblk <= 0 || yblk <= 0 ) { /* if block size if null, then return */ + return; + } + + if (fmv2 == NULL) { + fmv1->mse = MCP_MSE( frame_cur, cx, cy, frame_ref1, fmv1->mvx, fmv1->mvy, + NULL, 0., 0., xblk, yblk, hor, ver ); + fmv1->var = variance( frame_cur + cy * hor + cx, xblk, yblk, hor ); + + pfx = cx - fmv1->mvx; + pfy = cy - fmv1->mvy; + position( &px1, &py1, pfx, pfy, fmv1->mvx, fmv1->mvy, hor, ver ); + + ref_var = variance( frame_ref1 + py1 * hor + px1, xblk, yblk, hor ); + +// printf("fmv1->mse = %f, fmv1->var = %f, ref_var = %f\n",fmv1->mse,fmv1->var,ref_var); + + if( ( fmv1->mse < IBLOCK_FACTOR * fmv1->var && + fmv1->mse < IBLOCK_FACTOR * ref_var ) + || fmv1->mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ) + { + fmv1->lifting_mode = CONNECTED; + } + else + { + fmv1->lifting_mode = PREDICTED; + } + } else { + fmv1->mse = fmv2->mse = MCP_MSE( frame_cur, cx, cy, + frame_ref1, fmv1->mvx, fmv1->mvy, + frame_ref2, fmv2->mvx, fmv2->mvy, + xblk, yblk, hor, ver ); + fmv1->var = variance( frame_cur + cy * hor + cx, xblk, yblk, hor ); + + pfx = cx - fmv1->mvx; + pfy = cy - fmv1->mvy; + position( &px1, &py1, pfx, pfy, fmv1->mvx, fmv1->mvy, hor, ver ); + pfx = cx - fmv2->mvx; + pfy = cy - fmv2->mvy; + position( &px2, &py2, pfx, pfy, fmv2->mvx, fmv2->mvy, hor, ver ); + + ref_var = 0.5f * + (variance( frame_ref1 + py1 * hor + px1, xblk, yblk, hor ) + + variance( frame_ref2 + py2 * hor + px2, xblk, yblk, hor )); + +// printf("fmv1->mse = %f, fmv1->var = %f, ref_var = %f\n",fmv1->mse,fmv1->var,ref_var); + + if( ( fmv1->mse < IBLOCK_FACTOR * fmv1->var && + fmv1->mse < IBLOCK_FACTOR * ref_var ) + || fmv1->mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ) + { + fmv1->lifting_mode = CONNECTED; + fmv2->lifting_mode = CONNECTED; + } + else + { + fmv1->lifting_mode = PREDICTED; + fmv2->lifting_mode = PREDICTED; + } + } +} + + +/* + * block_matching() + * block-based motion estimation 块为基础的运动补偿 + * fr1-- current fr0-- reference + * dist: temporal distance between fr1 and fr0 + * level: temporal decomposition level (begin with 0) + */ +void +block_matching( vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, vector_ptr fmv4, + YUVimage *fr_cur, YUVimage *fr_ref1, YUVimage *fr_ref2, + enum FLAG *sc1, enum FLAG *sc2, + videoinfo info, int t_level, int dist, int subpel, float *upframe1, float *upframe2, float *upsamp_x ) +{ + + switch ( info.ME ) { + case 3: + rdme(fmv1, fmv2, fmv3, fmv4, fr_cur, fr_ref1, fr_ref2, sc1, sc2, t_level, dist, info, upframe1, upframe2, upsamp_x);// 运动估计的rd决策 + break; + default: + printf( "error in blockmatching()\n" ); + exit( 1 ); + } +} + + +static float first_pred[256*256]; + +static int *spiral_laplength; +static int **spiral_x, **spiral_y; + +void +initialize_spiral_search(int search_range) +{ + int i, j, k; + int len; + + spiral_laplength = (int*)getarray(search_range + 1, sizeof(int), + "spiral_laplength"); + spiral_x = (int**)getarray(search_range + 1, sizeof(int*), "spiral_x"); + spiral_y = (int**)getarray(search_range + 1, sizeof(int*), "spiral_y"); + + spiral_x[0] = (int*)getarray(1, sizeof(int), "spiral_x[0]"); + spiral_y[0] = (int*)getarray(1, sizeof(int), "spiral_y[0]"); + + spiral_laplength[0] = 1; + spiral_x[0][0] = 0; + spiral_y[0][0] = 0; + + for (i = 1, len = 8; i <= search_range; i++, len += 8) { + spiral_laplength[i] = len; + + spiral_x[i] = (int*)getarray(len, sizeof(int), "spiral_x[i]"); + spiral_y[i] = (int*)getarray(len, sizeof(int), "spiral_y[i]"); + + k = 0; + + spiral_x[i][k] = 0; spiral_y[i][k++] = -i; + spiral_x[i][k] = i; spiral_y[i][k++] = 0; + spiral_x[i][k] = 0; spiral_y[i][k++] = i; + spiral_x[i][k] = -i; spiral_y[i][k++] = 0; + + for (j = 1; j < i; j++) { + spiral_x[i][k] = j; spiral_y[i][k++] = -i; + spiral_x[i][k] = i; spiral_y[i][k++] = j; + spiral_x[i][k] = -j; spiral_y[i][k++] = i; + spiral_x[i][k] = -i; spiral_y[i][k++] = -j; + + spiral_x[i][k] = -j; spiral_y[i][k++] = -i; + spiral_x[i][k] = i; spiral_y[i][k++] = -j; + spiral_x[i][k] = j; spiral_y[i][k++] = i; + spiral_x[i][k] = -i; spiral_y[i][k++] = j; + } + + spiral_x[i][k] = i; spiral_y[i][k++] = i; + spiral_x[i][k] = -i; spiral_y[i][k++] = i; + spiral_x[i][k] = i; spiral_y[i][k++] = -i; + spiral_x[i][k] = -i; spiral_y[i][k++] = -i; + + assert(k == len); + } +} + +void +clean_up_spiral_search(int search_range) +{ + int i; + + for (i = 0; i <= search_range; i++) { + free(spiral_x[i]); + free(spiral_y[i]); + } + free(spiral_x); + free(spiral_y); + free(spiral_laplength); +} + +void +full_search_fast( float *mvx1, float *mvy1, + float *frame_cur, float *frame_ref1, float *frame_ref2, + float *upframe1, float *upframe2, + float mvx2, float mvy2, + int cx, int cy, int xblock, int yblock, int maxx, int maxy, + int hor, int ver, int subpel, float lambda, + float pmvx, float pmvy, int ctx_x, int ctx_y, + float *sad_cost, float *bit_cost, float *total_cost, + int do_parallel) // add parallel mode. mwi + /* frame1-- current frame0-- reference */ +{ + int i, scale, dx, dy, px, py, px2, py2, m, n, xblk, yblk; + int n2, ppx, ppy; // add parallel mode. mwi + // int upver, uphor; + int hx, hy; + float px1, py1; + float ppx2, ppy2; // add parallel mode. mwi + int x, y; +#ifdef PRE_INTERPOL + int inthor, intver, step, hx2, hy2; +#endif + float sum, bits; + float hmvx, hmvy, fmvx, fmvy; + float *tmp_first_pred; + int center_x, center_y, lap, pos, cont; + + assert(sad_cost != NULL && bit_cost != NULL && total_cost != NULL); + + // add parallel mode. mwi + if (do_parallel == YES) { + assert(frame_ref2 != NULL); + + if (upframe1 != NULL) { + assert(upframe2 != NULL); + } + } + +#ifdef PRE_INTERPOL + step = (1 << MY_MIN(PRE_INTERPOL, subpel)) ; + step = step << ADD_SUB; //Added on 02.26.2017 + inthor = (hor - 1) * step + 1; + intver = (ver - 1) * step + 1; +#endif + + xblk = ( cx + xblock <= hor ) ? xblock : hor - cx; + yblk = ( cy + yblock <= ver ) ? yblock : ver - cy; + +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); + + assert(xblk > 0 && yblk > 0); + + /* calculate existing prediction */ + if ( (frame_ref2 != NULL) && (do_parallel == NO) ) { + tmp_first_pred = first_pred; + m = 0; + n = cy * hor + cx; + for (y = cy; y < cy + yblk; y++) { + for (x = cx; x < cx + xblk; x++) { + px1 = float(x) - mvx2; + py1 = float(y) - mvy2; + + if (px1 >= 0 && px1 <= (hor - 1) && py1 >= 0 && py1 <= (ver - 1)) { + if (upframe2 && + floor(px1*step) == px1*step && floor(py1*step) == py1*step) { + // pre-interpolated + tmp_first_pred[m] = upframe2[int((py1 * inthor + px1) * step)]; + } else { + // not yet interpolated + assert(0); + tmp_first_pred[m] = FIRinterpolate(px1, py1, frame_ref2, FIR_LEN, hor, ver); + } + } else { + tmp_first_pred[m] = frame_cur[n]; + } + + m++; + n++; + } + n += hor - xblk; + } + assert(m == xblk * yblk); + } else { + tmp_first_pred = NULL; + } + + // changed by Yongjun Wu + // search center + center_x = (int)pmvx; // (pmvx > 0) ? (int)(pmvx + 0.5f) : (int)(pmvx - 0.5f); + center_y = (int)pmvy; // (pmvy > 0) ? (int)(pmvy + 0.5f) : (int)(pmvy - 0.5f); + + // first candidate + // position in reference frame + px = cx - center_x; + py = cy - center_y; + assert(px >= 0 && px <= (hor - xblk) && py >= 0 && py <= (ver - yblk)); + + // bit cost + *bit_cost = bit_coef * get_bit_cost(lambda, (float)center_x, (float)center_y, + pmvx, pmvy, ctx_x, ctx_y, subpel); + + // SAD + m = cy * hor + cx; + n = py * hor + px; + if (do_parallel == NO) { // add parallel mode. mwi + *sad_cost = MCP_Error2(frame_cur, m, frame_ref1, n, xblk, yblk, hor, + tmp_first_pred, (float)HUGE_VAL, + NULL, 0); // add parallel mode. mwi + } else { + // mirrored position in the second reference frame + ppx = cx + center_x; + ppy = cy + center_y; + if (!(ppx >= 0 && ppx <= (hor - xblk) && ppy >= 0 && ppy <= (ver - yblk))){ + *sad_cost = (float)HUGE_VAL; + } else { + n2 = ppy * hor + ppx; + *sad_cost = MCP_Error2(frame_cur, m, frame_ref1, n, xblk, yblk, hor, + tmp_first_pred, (float)HUGE_VAL, + frame_ref2, n2); // add parallel mode. mwi + } + } + + // get it + if (*sad_cost != (float)HUGE_VAL) { + *total_cost = *sad_cost + *bit_cost; + *mvx1 = (float)center_x; + *mvy1 = (float)center_y; + } else { + *total_cost = (float)HUGE_VAL; + *mvx1 = (float)HUGE_VAL; + *mvy1 = (float)HUGE_VAL; + } + + // further candidates + // spiral laps + assert(maxx >= 1); + for (lap = 1; lap <= maxx; lap++) { + cont = 0; + + // lap positions + for (pos = 0; pos < spiral_laplength[lap]; pos++) { + // candidate vector + dx = center_x + spiral_x[lap][pos]; + dy = center_y + spiral_y[lap][pos]; + + // position in reference frame + px = cx - dx; + py = cy - dy; + ppx = cx + dx; // add parallel mode. mwi + ppy = cy + dy; // add parallel mode. mwi + + // boundary check // add parallel mode. mwi + if(px >= 0 && px <= (hor - xblk) && py >= 0 && py <= (ver - yblk)) { + if ((do_parallel == NO) || ((do_parallel == YES)&& + (ppx >= 0 && ppx <= (hor - xblk) && ppy >= 0 && ppy <= (ver - yblk))) ) { + + // bit cost + bits = bit_coef * get_bit_cost(lambda, (float)dx, (float)dy, pmvx, pmvy, + ctx_x, ctx_y, subpel); + if (bits < *total_cost) { + cont = 1; + + // SAD + m = cy * hor + cx; + n = py * hor + px; + if (do_parallel == NO) { // add parallel mode. mwi + sum = MCP_Error2(frame_cur, m, frame_ref1, n, xblk, yblk, hor, + tmp_first_pred, (*total_cost) - bits, + NULL, 0); // add parallel mode. mwi + } else { + n2 = ppy * hor + ppx; + sum = MCP_Error2(frame_cur, m, frame_ref1, n, xblk, yblk, hor, + tmp_first_pred, (*total_cost) - bits, + frame_ref2, n2); // add parallel mode. mwi + + } + if( sum + bits < *total_cost ) { + *sad_cost = sum; + *bit_cost = bits; + *total_cost = sum + bits; + *mvx1 = (float)dx; + *mvy1 = (float)dy; + } + } + } + } + } + + // found any matches? + if (*total_cost == (float)HUGE_VAL) cont = 1; + + // vector cost exceeded minimum total cost in last lap? + if (!cont) break; + } + + // still no match? + if (*total_cost == (float)HUGE_VAL) { + *sad_cost = (float)HUGE_VAL; + *bit_cost = (float)HUGE_VAL; + *mvx1 = 0.0; + *mvy1 = 0.0; +// assert(0); + return; + } + + /* half-pixel search */ + // uphor = hor; + // upver = ver; + m = cy * hor + cx; + + for( i = 0; i < subpel; i++ ) { + hmvx = 0.; + hmvy = 0.; + px1 = cx - *mvx1; + py1 = cy - *mvy1; + ppx2 = cx + *mvx1; // add parallel mode. mwi + ppy2 = cy + *mvy1; // add parallel mode. mwi + scale = (1 << i); + +#ifdef PRE_INTERPOL + if (i >= MY_MIN(PRE_INTERPOL, subpel)) { +#endif + + for( hy = -1; hy <= 1; hy++ ) { + for( hx = -1; hx <= 1; hx++ ) { + + if (!(hx == 0 && hy == 0)) { + + fmvx = float(hx / 2. / float(scale)); + fmvy = float(hy / 2. / float(scale)); + + if (px1 + fmvx >= 0 && px1 + xblk + fmvx <= hor && + py1 + fmvy >= 0 && py1 + yblk + fmvy <= ver) { + // add parallel mode. mwi + if ((do_parallel == NO) || ((do_parallel == YES)&& + ppx2 - fmvx >= 0 && ppx2 + xblk - fmvx <= hor && + ppy2 - fmvy >= 0 && ppy2 + yblk - fmvy <= ver)) { + + bits = bit_coef * get_bit_cost(lambda, (*mvx1) - fmvx, (*mvy1) - fmvy, + pmvx, pmvy, ctx_x, ctx_y, subpel); + + if (bits < *total_cost) { + if (do_parallel == NO) { // add parallel mode. mwi + sum = Subpel_MCP_Error( frame_cur, m, frame_ref1, + px1, fmvx, py1, fmvy, + xblk, yblk, hor, ver, + tmp_first_pred, 0, xblk, + NULL, 0., 0.); // add parallel mode. mwi + } else { + sum = Subpel_MCP_Error( frame_cur, m, frame_ref1, + px1, fmvx, py1, fmvy, + xblk, yblk, hor, ver, + tmp_first_pred, 0, xblk, + frame_ref2, ppx2, ppy2); + } + if( sum + bits < *total_cost ) { + *sad_cost = sum; + *bit_cost = bits; + *total_cost = sum + bits; + hmvx = fmvx; + hmvy = fmvy; + } + } + } + } + } + } /* hx */ + } /* hy */ +#ifdef PRE_INTERPOL + } else { + + px2 = ( int )( px1 * step ); + py2 = ( int )( py1 * step ); + ppx = ( int )( ppx2 * step ); // add parallel mode. mwi + ppy = ( int )( ppy2 * step ); // add parallel mode. mwi + + // take care: hx/hy is *negative* refinement to mvx1/mvy1 + for( hy = -1; hy <= 1; hy++ ) { + for( hx = -1; hx <= 1; hx++ ) { + + // printf("px1 = %f, px2 = %f, hx = %d, hy = %d + if (!(hx == 0 && hy == 0)) { + assert(MY_MIN(PRE_INTERPOL, subpel) - i - 1 >= 0); + + hx2 = hx << (MY_MIN(PRE_INTERPOL, subpel + ADD_SUB) - i - 1);//Modified on 03.01.2017 + hy2 = hy << (MY_MIN(PRE_INTERPOL, subpel + ADD_SUB) - i - 1); + + fmvx = float(hx / 2. / float(scale)); + fmvy = float(hy / 2. / float(scale)); + + assert((px1 + xblk + fmvx <= hor) == (px2 + hx2 < (inthor - (xblk - 1) * step)) && + (py1 + yblk + fmvy <= ver) == (py2 + hy2 < (intver - (yblk - 1) * step))); + // parallel mode + assert((ppx2 + xblk - fmvx <= hor) == (ppx - hx2 < (inthor - (xblk - 1) * step)) && + (ppy2 + yblk - fmvy <= ver) == (ppy - hy2 < (intver - (yblk - 1) * step))); + + if (px1 + fmvx >= 0 && px1 + xblk + fmvx <= hor && + py1 + fmvy >= 0 && py1 + yblk + fmvy <= ver) { + if ((do_parallel == NO) || + ((do_parallel == YES)&& + (ppx2 - fmvx >= 0 && ppx2 + xblk - fmvx <= hor && + ppy2 - fmvy >= 0 && ppy2 + yblk - fmvy <= ver))) { + + bits = bit_coef * get_bit_cost(lambda, (*mvx1) - fmvx, (*mvy1) - fmvy, + pmvx, pmvy, ctx_x, ctx_y, subpel); + + if (do_parallel == NO) { // add parallel mode. mwi + sum = Subpel_MCP_Error3(frame_cur, m, upframe1, + px2 + hx2, py2 + hy2, + xblk, yblk, hor, ver, + inthor, intver, step, + tmp_first_pred, (*total_cost) - bits, + NULL, 0, 0); // add parallel mode. mwi + + } else { + sum = Subpel_MCP_Error3(frame_cur, m, upframe1, + px2 + hx2, py2 + hy2, + xblk, yblk, hor, ver, + inthor, intver, step, + tmp_first_pred, (*total_cost) - bits, + upframe2, ppx-hx2, ppy-hy2); + } + + if( sum + bits < *total_cost ) { + + *sad_cost = sum; + *bit_cost = bits; + *total_cost = sum + bits; + hmvx = fmvx; + hmvy = fmvy; + } + } + } + } + } /* hx */ + } /* hy */ + } +#endif + + (*mvx1) -= hmvx; + (*mvy1) -= hmvy; + } + + assert(!(fabs(*mvx1) > 1e-42 && fabs(*mvx1) < 1e-10)); + assert(!(fabs(*mvy1) > 1e-42 && fabs(*mvy1) < 1e-10)); +} + +/*****************************************************************************/ +/* generate_child() */ +/*****************************************************************************/ +void +generate_child( vector_ptr fmv, float *mvx, float *mvy, float *mad ) +{ + /* allocate the memory to the child vector pointer */ + /* save the motion vector and estimation error */ + + assert(fmv->child == 0); + + fmv->child = 1; + fmv->child0 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child0" ); + fmv->child1 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child1" ); + fmv->child2 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child2" ); + fmv->child3 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child3" ); + + fmv->child0->parent = fmv; + fmv->child1->parent = fmv; + fmv->child2->parent = fmv; + fmv->child3->parent = fmv; + + fmv->child0->child = 0; + fmv->child0->lifting_mode = CONNECTED; + fmv->child0->merge = YES; + fmv->child0->mvx = mvx[0]; + fmv->child0->mvy = mvy[0]; + fmv->child0->mad = mad[0]; + + fmv->child1->child = 0; + fmv->child1->lifting_mode = CONNECTED; + fmv->child1->merge = YES; + fmv->child1->mvx = mvx[1]; + fmv->child1->mvy = mvy[1]; + fmv->child1->mad = mad[1]; + + fmv->child2->child = 0; + fmv->child2->lifting_mode = CONNECTED; + fmv->child2->merge = YES; + fmv->child2->mvx = mvx[2]; + fmv->child2->mvy = mvy[2]; + fmv->child2->mad = mad[2]; + + fmv->child3->child = 0; + fmv->child3->lifting_mode = CONNECTED; + fmv->child3->merge = YES; + fmv->child3->mvx = mvx[3]; + fmv->child3->mvy = mvy[3]; + fmv->child3->mad = mad[3]; +} + + +/****************************************************************** + Compute MCP error with half pixel accuracy + + m: initial position in current frame-frame1 + (px, py): initial position in previous frame- frame0 + (hx, hy): sub-pixel search + xblk: block width + yblk: block height + hor: frame1 width + ver: frame1 height + add parallel mode: + (ppx,ppy):initial position in second ref.frame- frame2 +*******************************************************************/ +float +Subpel_MCP_Error( float *frame1, int m, float *frame0, float px, float hx, + float py, float hy, int xblk, int yblk, int hor, int ver, + float *first_pred, int k, int xblk_pred, + float *frame2, float ppx, float ppy) // add parallel mode. mwi +{ + int y, x; + float diff, ptemp, sum; + float ptemp2; // add parallel mode. mwi + + sum = 0.; + if (frame2 == NULL) { + if (first_pred == NULL) { + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + for( x = 0; x < xblk; x++ ) { + + ptemp = interpolate(px + hx + x, py + hy + y, frame0, hor, ver, TYPE); + + diff = frame1[m] - ptemp; + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + m++; + } /* x */ + m += hor - xblk; + } /* y */ + } else { + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + for( x = 0; x < xblk; x++ ) { + + ptemp = interpolate(px + hx + x, py + hy + y, frame0, hor, ver, TYPE); + + diff = frame1[m] - 0.5f * (first_pred[k] + ptemp); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + k++; + m++; + } /* x */ + k += xblk_pred - xblk; + m += hor - xblk; + } /* y */ + } + } else { + // add parallel mode. mwi + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + for( x = 0; x < xblk; x++ ) { + + ptemp = interpolate(px + hx + x, py + hy + y, frame0, hor, ver, TYPE); + ptemp2 = interpolate(ppx - hx + x, ppy - hy + y, frame2, hor, ver, TYPE); + + diff = frame1[m] - 0.5f * (ptemp + ptemp2); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + m++; + } /* x */ + m += hor - xblk; + } /* y */ + } + + return sum; +} + + + + +/****************************************************************** + Compute MCP error with half pixel accuracy + + m: initial position in current frame-frame1 + (px, py): initial integer position in previous frame + upframe: upsampled previous frame. (generated by Interpolate_frame) + (hx, hy): half-pixel search + xblk: block width + yblk: block height + hor: frame1 width + ver: frame1 height + uphor: upsampled frame width + upver: upsampled frame height + step : step size in reference frame (2 for once upsampled image, 4 for twice upsampled image) +*******************************************************************/ +float +Subpel_MCP_Error2( float *frame1, int m, float *upframe, int px, int hx, + int py, int hy, int xblk, int yblk, int hor, int ver, + int uphor, int upver, int step, + float *first_pred, int k, int xblk_pred ) + +{ + int y, x; + float diff, sum; + + sum = 0.; + if (first_pred == NULL) { + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + for( x = 0; x < xblk; x++ ) { + + diff = + frame1[m] - upframe[( py * 2 + y * step + hy ) * uphor + + ( px * 2 + x * step ) + hx]; + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + m++; + } /* x */ + m += hor - xblk; + } /* y */ + } else { + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + for( x = 0; x < xblk; x++ ) { + + diff = + frame1[m] - 0.5f * (upframe[( py * 2 + y * step + hy ) * uphor + + ( px * 2 + x * step ) + hx] + + first_pred[k]); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + k++; + m++; + } /* x */ + k += xblk_pred - xblk; + m += hor - xblk; + } /* y */ + } + + return sum; +} + +float +Subpel_MCP_Error3( float *frame1, int m, float *upframe, int px, int py, + int xblk, int yblk, int hor, int ver, + int uphor, int upver, int step, float *first_pred, + float min_cost, + float *upframe2, int ppx, int ppy) // add parallel mode. mwi + +{ + int x, y, k; + float diff, sum; + + sum = 0.; + if (upframe2 == NULL) { + if (first_pred == NULL) { + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + if (sum >= min_cost) break; + + for( x = 0; x < xblk; x++ ) { + + diff = + frame1[m] - upframe[( py + y * step ) * uphor + + ( px + x * step ) ]; + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + m++; + } /* x */ + + m += hor - xblk; + } /* y */ + } else { + k = 0; + + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + if (sum >= min_cost) break; + + for( x = 0; x < xblk; x++ ) { + + diff = + frame1[m] - 0.5f * (upframe[( py + y * step ) * uphor + + ( px + x * step ) ] + + first_pred[k]); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + k++; + m++; + } /* x */ + + m += hor - xblk; + } /* y */ + } + } else { + // parallel mode + for( y = 0; y < yblk; y++ ) { /* calculate the error */ + if (sum >= min_cost) break; + + for( x = 0; x < xblk; x++ ) { + + diff = + frame1[m] - 0.5f * (upframe[( py + y * step ) * uphor + + ( px + x * step ) ] + + upframe2[( ppy + y * step ) * uphor + + ( ppx + x * step ) ]); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + m++; + } /* x */ + + m += hor - xblk; + } /* y */ + } + + return sum; +} + +float +Subpel_MCP_Error4( float *frame_cur, + int cx, int cy, int xblock, int yblock, + float *frame_ref1, float *upframe_ref1, + float mvx1, float mvy1, + float *frame_ref2, float *upframe_ref2, + float mvx2, float mvy2, + int hor, int ver, int subpel ) +{ + int x, y, m; + int xblk, yblk; + float px1, py1, px2, py2; + float pred1, pred2; + float diff, sum; +#ifdef PRE_INTERPOL + int step, inthor, intver; + + step = (1 << MY_MIN(PRE_INTERPOL, subpel)) ; + + step = step << ADD_SUB; //Added on 02.26.2017 + + inthor = (hor - 1) * step + 1; + intver = (ver - 1) * step + 1; + + assert(frame_ref1 && upframe_ref1); + assert(!frame_ref2 || upframe_ref2); +#endif + + xblk = ( cx + xblock <= hor ) ? xblock : hor - cx; + yblk = ( cy + yblock <= ver ) ? yblock : ver - cy; + + assert(xblk > 0 && yblk > 0); + + sum = 0.; + + m = cy * hor + cx; + for (y = cy; y < cy + yblk; y++) { + for (x = cx; x < cx + xblk; x++) { + px1 = float(x) - mvx1; + py1 = float(y) - mvy1; + assert(px1 >= 0 && px1 <= (hor - 1) && py1 >= 0 && py1 <= (ver - 1)); + +#ifdef PRE_INTERPOL + if (floor(px1*step) == px1*step && floor(py1*step) == py1*step) { + // pre-interpolated + pred1 = upframe_ref1[int((py1 * inthor + px1) * step)]; + } else { + // not yet interpolated + pred1 = FIRinterpolate(px1, py1, frame_ref1, 12, hor, ver); + } +#else + // no pre-interpolation + pred1 = FIRinterpolate(px1, py1, frame_ref1, 12, hor, ver); +#endif + + if (frame_ref2) { + px2 = float(x) - mvx2; + py2 = float(y) - mvy2; + + assert(px2 >= 0 && px2 <= (hor - 1) && py2 >= 0 && py2 <= (ver - 1)); + +#ifdef PRE_INTERPOL + if (floor(px2*step) == px2*step && floor(py2*step) == py2*step) { + // pre-interpolated + pred2 = upframe_ref2[int((py2 * inthor + px2) * step)]; + } else { + // not yet interpolated + pred2 = FIRinterpolate(px2, py2, frame_ref2, 12, hor, ver); + } +#else + // no pre-interpolation + pred2 = FIRinterpolate(px2, py2, frame_ref2, 12, hor, ver); +#endif + } else { + pred2 = pred1; + } + + diff = frame_cur[m] - 0.5f * (pred1 + pred2); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + + m++; + } + m += hor - xblk; + } + + return sum; +} + + +/****************************************************************** + Compute MCP error with integer accuracy + + m: initial position in current frame-frame1 + n: initial position in previous frame-frame0 + oxblk: block width + oyblk: block height + hor: image width +*******************************************************************/ +float +MCP_Error(float *frame1, int m, float *frame0, int n, int oxblk, int oyblk, + int hor, float *first_pred, int k, int xblk_pred) //Never applied in practice +{ + int y, x; + float diff, sum; + + sum = 0.; + if (first_pred == NULL) { + for( y = 0; y < oyblk; y++ ) { + for( x = 0; x < oxblk; x++ ) { + diff = frame1[m] - frame0[n]; + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + /* mean absolute error */ + m++; + n++; + } + m += hor - oxblk; + n += hor - oxblk; + } + } else { + for( y = 0; y < oyblk; y++ ) { + for( x = 0; x < oxblk; x++ ) { + diff = frame1[m] - 0.5f * (frame0[n] + first_pred[k]); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + /* mean absolute error */ + k++; + m++; + n++; + } + k += xblk_pred - oxblk; + m += hor - oxblk; + n += hor - oxblk; + } + } + + return sum; +} + +float +MCP_Error2(float *frame1, int m, float *frame0, int n, int oxblk, int oyblk, + int hor, float *first_pred, float min_cost, + float *frame2, int n2) // add parallel mode. mwi +{ + int y, x, k; + float diff, sum; + + sum = 0.; + if (frame2 == NULL) { // add parallel mode. mwi + if (first_pred == NULL) { + for( y = 0; y < oyblk; y++ ) { + if (sum >= min_cost) break; + + for( x = 0; x < oxblk; x++ ) { + diff = frame1[m] - frame0[n]; + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + /* mean absolute error */ + m++; + n++; + } + + m += hor - oxblk; + n += hor - oxblk; + } + } else { + k = 0; + for( y = 0; y < oyblk; y++ ) { + if (sum >= min_cost) break; + + for( x = 0; x < oxblk; x++ ) { + diff = frame1[m] - 0.5f * (frame0[n] + first_pred[k]); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + /* mean absolute error */ + k++; + m++; + n++; + } + + m += hor - oxblk; + n += hor - oxblk; + } + } + } else { // add parallel mode. mwi + for( y = 0; y < oyblk; y++ ) { + if (sum >= min_cost) break; + + for( x = 0; x < oxblk; x++ ) { + diff = frame1[m] - 0.5f * (frame0[n] + frame2[n2]); + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + /* mean absolute error */ + m++; + n++; + n2++; + } + + m += hor - oxblk; + n += hor - oxblk; + n2+= hor - oxblk; + } + + } + + return sum; +} + + + +/* + * position1D() + * find the matching 1D integer position for sub-pixel accurate temporal filtering + * 寻找pfx的整数 + */ + +int +position1D( float pfx, float mvx ) +{ + int tmpx; + if( ( int )pfx == pfx ) + tmpx = ( int )pfx; // integer pixel + else + if( ( ( int )( pfx * 2 ) ) / 2. == pfx ) + tmpx = ( mvx > 0. ) ? ( int )ceil( pfx ) : ( int )floor( pfx ); // half pixel + else + tmpx = nint( pfx ); // otherwise + + return tmpx; +} + + +/* + * position() 返回亚像素准确时域滤波对应的整数位置 + * find the matching integer position for sub-pixel accurate temporal filtering + * + */ +void +position( int *px, int *py, float pfx, float pfy, float mvx, float mvy, + int hor, int ver ) +{ + int tmpx, tmpy; + + + tmpx = position1D( pfx, mvx );// 返回整数 + tmpy = position1D( pfy, mvy ); // 返回整数 + + // clipping ??? + if( tmpx < 0 ) + tmpx = 0; + else if( tmpx > hor - 1 ) + tmpx = hor - 1; + + if( tmpy < 0 ) + tmpy = 0; + else if( tmpy > ver - 1 ) + tmpy = ver - 1; + + *px = tmpx; + *py = tmpy; +} + + +/*****************************************************************************/ +/* inbound() */ +/*****************************************************************************/ +int +inbound( float x, float y, int hor, int ver ) +{ + if( x >= 0. && x <= ( float )( hor - 1 ) && y >= 0. + && y <= ( float )( ver - 1 ) ) + return 1; + else + return 0; +} + + +/*****************************************************************************/ +/* get_cvector */ +/*****************************************************************************/ +void +get_cvector( float *cmvx, float *cmvy, float *ymvx, float *ymvy, int yhor, + int yver, int chor, int cver, videoinfo info, int t_level ) +{ + int x, y, pos; + float dx, dy; + int t1, t2, scale; + + scale = 1 << info.subpel[t_level]; + + /* get the motion vector for the chrominance component */ + /* from the luminance vectors */ + /* half */ + /* yfv dx t1 dx cfv */ + /* +-0.5 +-.25 0 0. 0. */ + /* +-1.0 +-.5 0 +-.5 +-0.5 */ + /* +-1.5 +-.75 0 +-.5 +-0.5 */ + /* +-2.0 +-1.0 +-1 0. +-1.0 */ + /* +-2.5 +-1.25 +-1 0. +-1.0 */ + /* +-3.0 +-1.50 +-1 +-.5 +-1.5 */ + + /* quarter */ + /* yfv dx t1 dx cfv */ + /* 0.25 0.125 0 0 */ + /* 0.5 0.25 0 0.25 */ + /* 0.75 0.375 0 0.25 */ + /* 1 0.5 0 0.5 */ + /* 1.25 0.625 0 0.5 */ + /* 1.5 0.75 0 0.75 */ + /* 1.75 0.875 0 0.75 */ + + if( yver == 2 * cver && yhor == 2 * chor ) { + for( y = 0; y < cver; y++ ) { + for( x = 0; x < chor; x++ ) { + + dx = ymvx[( 2 * y ) * yhor + ( 2 * x )]; + + if( dx == (float)HUGE_VAL ) + cmvx[y * chor + x] = dx; + else { + dx /= 2.0; + t1 = ( int )dx; + dx = ( float )( ( int )( dx * scale ) % scale ) / ( float )scale; + cmvx[y * chor + x] = t1 + dx; + } + + dy = ymvy[( 2 * y ) * yhor + ( 2 * x )]; + if( dy == (float)HUGE_VAL ) + cmvy[y * chor + x] = dy; + else { + dy /= 2.0; + t2 = ( int )dy; + dy = ( float )( ( int )( dy * scale ) % scale ) / ( float )scale; + cmvy[y * chor + x] = t2 + dy; + + } + } + } + } //420 + else if( yver == cver && yhor == chor ) { // 444 + for( y = 0; y < cver; y++ ) { + for( x = 0; x < chor; x++ ) { + pos = y * chor + x; + cmvx[pos] = ymvx[pos]; + cmvy[pos] = ymvy[pos]; + } + } + } else { + printf( "can not handle this case (mctfN.c)\n" ); + exit( 1 ); + } + +} + + +/***************************************************************************** + * block2pixel2() 从块为基础的运动向量变为像素为基础的向量 每个像素执行一次这个函数 + * get dense motion field from block-based motion vectors + * except blocks with CONNECTED mode. + * + *****************************************************************************/ +void +rec_block2pixel( float *mvx, float *mvy, vector_ptr fmv, int cx, int cy, + int xblk, int yblk, int hor, int ver, + enum LiftingMode block_mode ) +{ + int i, j, xblock, yblock, pos; + + /* change the structure of motion vectors */ + /* from the block-based to the pixel-based */ + /* write the motion vector of the block recursively */ + + if( fmv->child ) { + rec_block2pixel( mvx, mvy, fmv->child0, cx, cy, xblk / 2, yblk / 2, hor, + ver, block_mode ); + rec_block2pixel( mvx, mvy, fmv->child1, cx + xblk / 2, cy, xblk / 2, + yblk / 2, hor, ver, block_mode ); + rec_block2pixel( mvx, mvy, fmv->child2, cx, cy + yblk / 2, xblk / 2, + yblk / 2, hor, ver, block_mode ); + rec_block2pixel( mvx, mvy, fmv->child3, cx + xblk / 2, cy + yblk / 2, + xblk / 2, yblk / 2, hor, ver, block_mode ); + } else { + /* consider the small block around the boundaries */ + xblock = ( cx + xblk <= hor ) ? xblk : hor - cx; + yblock = ( cy + yblk <= ver ) ? yblk : ver - cy; + + if( xblock <= 0 || yblock <= 0 ) { + /* printf("xblock<=0 || yblock<=0 in block2pixel2() !\n");*/ + return; + } + + // 得到每一个像素点的mv + if( fmv->lifting_mode == block_mode ) { + + for( i = cy; i < cy + yblock; i++ ) { + for( j = cx; j < cx + xblock; j++ ) { //Modified by Yuan Liu + if(fmv->bi_mode <= 6 || fmv->bi_mode == 8 || (fmv->bi_mode == 7 && fmv->aff_mrg == NO) ){ + pos = i * hor + j; + mvx[pos] = fmv->mvx; + mvy[pos] = fmv->mvy; + } + else if( (fmv->bi_mode >= 9 && fmv->bi_mode <= 11) || (fmv->bi_mode == 7 && fmv->aff_mrg == YES) ){ + + pos = i * hor + j; + mvx[pos] = (fmv->aff2_mvx - fmv->aff1_mvx)*((float)(j-cx))/((float)xblock) + (fmv->aff3_mvx - fmv->aff1_mvx)*((float)(i-cy))/((float)yblock) + fmv->aff1_mvx; + mvy[pos] = (fmv->aff2_mvy - fmv->aff1_mvy)*((float)(j-cx))/((float)xblock) + (fmv->aff3_mvy - fmv->aff1_mvy)*((float)(i-cy))/((float)yblock) + fmv->aff1_mvy; +// printf("%f\t",mvx[pos]); + if( fmv->aff1_mvx == (float)HUGE_VAL || fmv->aff1_mvy == (float)HUGE_VAL || + fmv->aff2_mvx == (float)HUGE_VAL || fmv->aff2_mvy == (float)HUGE_VAL || + fmv->aff3_mvx == (float)HUGE_VAL || fmv->aff3_mvy == (float)HUGE_VAL){ + + mvx[pos] = (float)HUGE_VAL; + mvy[pos] = (float)HUGE_VAL; + } + + } + } + if(fmv->bi_mode >= 9 && fmv->bi_mode <= 11); +// printf("\n"); + } + if(fmv->bi_mode >= 9 && fmv->bi_mode <= 11); +// printf("\n\n\n"); + } + else { + for( i = cy; i < cy + yblock; i++ ) { + for( j = cx; j < cx + xblock; j++ ) { + pos = i * hor + j; + mvx[pos] = (float)HUGE_VAL; + mvy[pos] = (float)HUGE_VAL; + } + } + } + + } +} + + +void +scale_down_mv_comp( float *mv, int hor, int ver, int scale, int precision ) +{ + int x, y, pos; + float dx; + int t; + + for( y = 0; y < ver; y++ ) { + for( x = 0; x < hor; x++ ) { + + pos = ( scale * y ) * ( hor * scale ) + ( scale * x ); + dx = mv[pos]; + + if( dx == (float)HUGE_VAL ) + mv[y * hor + x] = dx; + else { + dx /= scale; + t = ( int )dx; + dx = + ( float )( ( int )( dx * precision ) % precision ) / + ( float )precision; + mv[y * hor + x] = t + dx; + } + } + } +} + + +void +scale_down_mv( float *ymvx, float *ymvy, float *cmvx, float *cmvy, + videoinfo info, int t_level ) +{ + int hor, ver, scale, precision, s_level; + + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + scale = 1 << s_level; + precision = 1 << info.subpel[t_level]; + + hor = info.ywidth >> s_level; + ver = info.yheight >> s_level; + scale_down_mv_comp( ymvx, hor, ver, scale, precision ); + scale_down_mv_comp( ymvy, hor, ver, scale, precision ); + + hor = info.cwidth >> s_level; + ver = info.cheight >> s_level; + scale_down_mv_comp( cmvx, hor, ver, scale, precision ); + scale_down_mv_comp( cmvy, hor, ver, scale, precision ); + +} + +// 块级mv转换为像素级mv,放进ymvx、ymvy、cmvx、cmvy中 +void +blockmv2pixelmv( vector_ptr fmv, float **ymvx, float **ymvy, float **cmvx, + float **cmvy, enum LiftingMode block_mode, videoinfo info, int t_level ) +{ + int x, y, X, Y, yhor, yver, chor, cver; + int xnum, ynum, xblk, yblk, s_level; + + /* allocate the memory and initialization */ + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + if( s_level > 0 ) { + info.ywidth <<= s_level; + info.yheight <<= s_level; + info.cwidth <<= s_level; + info.cheight <<= s_level; + } + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + + *ymvx = ( float * )getarray( yhor * yver, sizeof( float ), "ymvx" ); + *ymvy = ( float * )getarray( yhor * yver, sizeof( float ), "ymvy" ); + *cmvx = ( float * )getarray( chor * cver, sizeof( float ), "cmvx" ); + *cmvy = ( float * )getarray( chor * cver, sizeof( float ), "cmvy" ); + +// printf("s_level= %d\n",s_level); + /* convert the block-based vectors to the pixel-based vectors 转化块为基础的向量为像素级向量 */ + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) {// + rec_block2pixel( *ymvx, *ymvy, &fmv[Y * xnum + X], x, y, xblk, yblk, + yhor, yver, block_mode ); + } + } + + /* get the chrominance motion vector from the luminance vector 从亮度向量中获得色度运动向量 */ + if( chor && cver ) { + get_cvector( *cmvx, *cmvy, *ymvx, *ymvy, yhor, yver, chor, cver, info, t_level ); + } + + if( s_level > 0 ) //Never happen + scale_down_mv( *ymvx, *ymvy, *cmvx, *cmvy, info, t_level ); +} diff --git a/Interframe EZBC/TempSub/src/bme_tools.cpp b/Interframe EZBC/TempSub/src/bme_tools.cpp new file mode 100644 index 0000000..ea40bb2 --- /dev/null +++ b/Interframe EZBC/TempSub/src/bme_tools.cpp @@ -0,0 +1,663 @@ +#include "bme_tools.h" +#include "mv_ec.h" +#include +#include +#include + +int enc_trans_info(int aff_idx){ + + int enc_trans = 0; + + if(aff_idx == 3 || aff_idx == 7 || (aff_idx >= 11 && aff_idx <= 15) ) + enc_trans = 1; + if(aff_idx == 19 || aff_idx == 23 || (aff_idx >= 27 && aff_idx <= 31) ) + enc_trans = 1; + if(aff_idx == 35 || aff_idx == 39 || (aff_idx >= 43 && aff_idx <= 47) ) + enc_trans = 1; + if(aff_idx >= 48 && aff_idx <= 63 ) + enc_trans = 1; + + return enc_trans; +} +//////////////////////////////// + +inline float median(float a, float b, float c) +{ + return ((a>b) ? ((a>c) ? ((b>c) ? b : c) : a) : + ((b>c) ? ((a>c) ? a : c) : b)); +} + +void get_dmv_from_tree(float *dmvx, float *dmvy, enum FLAG *is_predictor, + vector_ptr fmv, int x_dst, int y_dst, + int x, int y, int xblk, int yblk, int hor, int ver, int blk_thresh) +{ + int cx, cy; + int dx, dy; + + assert(!(x < 0 || x >= hor || y < 0 || y >= ver)); + + dx = x_dst - x; + dy = y_dst - y; + + assert(!(dx < 0 || dx >= xblk || dy < 0 || dy >= xblk)); + + if (fmv->child && xblk>blk_thresh) + { + if (dx < xblk / 2 && dy < yblk / 2) { + cx = x; + cy = y; + get_dmv_from_tree(dmvx, dmvy, is_predictor, fmv->child0, x_dst, y_dst, + cx, cy, xblk / 2, yblk / 2, hor, ver, blk_thresh); + } else if (dx >= xblk / 2 && dy < yblk / 2) { + cx = x + xblk / 2; + cy = y; + get_dmv_from_tree(dmvx, dmvy, is_predictor, fmv->child1, x_dst, y_dst, + cx, cy, xblk / 2, yblk / 2, hor, ver, blk_thresh); + } else if (dx < xblk / 2 && dy >= yblk / 2) { + cx = x; + cy = y + yblk / 2; + get_dmv_from_tree(dmvx, dmvy, is_predictor, fmv->child2, x_dst, y_dst, + cx, cy, xblk / 2, yblk / 2, hor, ver, blk_thresh); + } else if (dx >= xblk / 2 && dy >= yblk / 2) { + cx = x + xblk / 2; + cy = y + yblk / 2; + get_dmv_from_tree(dmvx, dmvy, is_predictor, fmv->child3, x_dst, y_dst, + cx, cy, xblk / 2, yblk / 2, hor, ver, blk_thresh); + } else { + printf("error in get_dmv_from_tree!\n"); + exit(1); + } + } + else + { + if ( !blk_thresh) // no layered structure for motion vector coding + { + *dmvx = fmv->dmvx; + *dmvy = fmv->dmvy; + *is_predictor = fmv->is_predictor; + }else // for layered structure motion vector coding + { + if ( ! fmv->child ) // all the information is availabe in this fmv + { + *dmvx = fmv->dmvx; + *dmvy = fmv->dmvy; + *is_predictor = fmv->is_predictor; + }else // it's a subsampled (blk_thresh x blk_thresh ) block + { + if ( fmv->mv_exist ) + { + *dmvx = fmv->dmvx; + *dmvy = fmv->dmvy; + *is_predictor = YES; + }else + { + *dmvx = (float)HUGE_VAL; + *dmvy = (float)HUGE_VAL; + *is_predictor = NO; + } + } + } + } +} + +void get_pred_from_tree(float *pmvx, float *pmvy, enum FLAG *is_predictor, + vector_ptr fmv, int x_dest, int y_dest, int x, int y, + int xblk, int yblk, int hor, int ver, enum BiMode *block_mode, + int *propagate_iblk, int blk_thresh) +{ //Modified by Yuan Liu on 01.04.2016 + int cx, cy; + int dx, dy; + + int xblk2,yblk2, it_mvx,it_mvy; + + int subpel = 2; + + float accu = 0.25; + int addx,addy; + float int_mvx,int_mvy; + + assert(!(x < 0 || x >= hor || y < 0 || y >= ver)); + + dx = x_dest - x; + dy = y_dest - y; + + assert(!(dx < 0 || dx >= xblk || dy < 0 || dy >= xblk)); + + if (fmv->child && xblk>blk_thresh) + { + if (dx < xblk / 2 && dy < yblk / 2) { + cx = x; + cy = y; + get_pred_from_tree(pmvx, pmvy, is_predictor, fmv->child0, x_dest, y_dest, + cx, cy, xblk / 2, yblk / 2, hor, ver, block_mode, propagate_iblk, blk_thresh); + } else if (dx >= xblk / 2 && dy < yblk / 2) { + cx = x + xblk / 2; + cy = y; + get_pred_from_tree(pmvx, pmvy, is_predictor, fmv->child1, x_dest, y_dest, + cx, cy, xblk / 2, yblk / 2, hor, ver, block_mode, propagate_iblk, blk_thresh); + } else if (dx < xblk / 2 && dy >= yblk / 2) { + cx = x; + cy = y + yblk / 2; + get_pred_from_tree(pmvx, pmvy, is_predictor, fmv->child2, x_dest, y_dest, + cx, cy, xblk / 2, yblk / 2, hor, ver, block_mode, propagate_iblk, blk_thresh); + } else if (dx >= xblk / 2 && dy >= yblk / 2) { + cx = x + xblk / 2; + cy = y + yblk / 2; + get_pred_from_tree(pmvx, pmvy, is_predictor, fmv->child3, x_dest, y_dest, + cx, cy, xblk / 2, yblk / 2, hor, ver, block_mode, propagate_iblk, blk_thresh); + } else { + printf("error in get_pred_from_tree!\n"); + exit(1); + } + } + else + { + //////////////Added on 01.10.2016////////////// + xblk2 = ( x + xblk <= hor) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver) ? yblk : ver - y; + /////////////////////////////////////////////// + if( (dx+1)/xblk2 == 1 ) + addx = 1; + else + addx = 0; + + if( (dy+1)/yblk2 == 1 ) + addy = 1; + else + addy = 0; + + if (!blk_thresh) // not for layered structure motion vector coding + { + *is_predictor = fmv->is_predictor; + *block_mode = fmv->bi_mode; // by Yongjun Wu: get the block mode + *propagate_iblk = fmv->propagate_iblk; // by Yongjun Wu: get the propagation property for the iblock + + if( (fmv->bi_mode >= 0 && fmv->bi_mode <= 6) || fmv->bi_mode == 8 || (fmv->bi_mode == 7 && fmv->aff_mrg == NO) ){ + *pmvx = fmv->mvx; + *pmvy = fmv->mvy; + ////////// Added by Yuan Liu ////////////////// + }else if( (fmv->bi_mode >= 9 && fmv->bi_mode <= 11) || (fmv->bi_mode == 7 && fmv->aff_mrg == YES) ){ + + *pmvx = (fmv->aff2_mvx - fmv->aff1_mvx)*((float)dx + addx)/((float)xblk2) + (fmv->aff3_mvx - fmv->aff1_mvx)*((float)dy + addy)/((float)yblk2) + fmv->aff1_mvx; + *pmvy = (fmv->aff2_mvy - fmv->aff1_mvy)*((float)dx + addx)/((float)xblk2) + (fmv->aff3_mvy - fmv->aff1_mvy)*((float)dy + addy)/((float)yblk2) + fmv->aff1_mvy; + } + else + assert(fmv->is_predictor == NO); + + *pmvx = *pmvx * (1 << subpel); + *pmvy = *pmvy * (1 << subpel); + + it_mvx = (int)(*pmvx); + it_mvy = (int)(*pmvy); + + *pmvx = (float)(it_mvx); + *pmvy = (float)(it_mvy); + + *pmvx = *pmvx / (1 << subpel); + *pmvy = *pmvy / (1 << subpel); + ////////////////////////////////////////////////// + + }else // for layered structure motion vector coding + { + printf("blk_thresh!!\n"); + assert(0); + if ( !fmv->child ) // all the information is availabe in this fmv + { + *pmvx = fmv->mvx; + *pmvy = fmv->mvy; + *is_predictor = fmv->is_predictor; + *block_mode = fmv->bi_mode; // by Yongjun Wu: get the block mode + *propagate_iblk = fmv->propagate_iblk; // by Yongjun Wu: get the propagation property for the iblock + }else // it's a subsampled (blk_thresh x blk_thresh ) block + { + if ( fmv->mv_exist ) + { + *pmvx = fmv->sample_mvx; + *pmvy = fmv->sample_mvy; + *is_predictor = fmv->is_predictor; + *block_mode = UNDEFINED; + *propagate_iblk = -1; + }else + { + *pmvx = (float)HUGE_VAL; + *pmvy = (float)HUGE_VAL; + *is_predictor = NO; + *block_mode = UNDEFINED; + *propagate_iblk = -1; + } + } + } + + } +} + +void get_dmv(float *dmvx, float *dmvy, enum FLAG *is_predictor, + vector_ptr fmv, int x_dest, int y_dest, videoinfo info, int t_level, int blk_thresh) +{ + int xnum, ynum, xblk, yblk, hor, ver, X, Y, x, y, pos; + + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + hor = info.ywidth; + ver = info.yheight; + + if (x_dest < 0 || x_dest >= hor || y_dest < 0 || y_dest >= ver) + { + *dmvx = 0; + *dmvy = 0; + *is_predictor = NO; + + return; + } + + X = x_dest / xblk; + Y = y_dest / yblk; + pos = Y * xnum + X; + x = X * xblk; + y = Y * yblk; + + get_dmv_from_tree(dmvx, dmvy, is_predictor, &fmv[pos], x_dest, y_dest, x, y, + xblk, yblk, hor, ver, blk_thresh); +} + +void get_predictor(float *pmvx, float *pmvy, enum FLAG *is_predictor, + vector_ptr fmv, int x_dest, int y_dest, videoinfo info, int t_level, + enum BiMode *block_mode, int *propagate_iblk, int blk_thresh) +{ + int xnum, xblk, yblk, hor, ver; + int X, Y, x, y, pos; + + // initialization + xnum = info.xnum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + hor = info.ywidth; + ver = info.yheight; + + if (x_dest < 0 || x_dest >= hor || y_dest < 0 || y_dest >= ver) + { + *pmvx = 0; + *pmvy = 0; + *is_predictor = NO; + *block_mode = UNDEFINED; + + return; + } + + X = x_dest / xblk; + Y = y_dest / yblk; + pos = Y * xnum + X; + x = X * xblk; + y = Y * yblk; + + get_pred_from_tree(pmvx, pmvy, is_predictor, &fmv[pos], + x_dest, y_dest, x, y, xblk, yblk, hor, ver, block_mode, propagate_iblk, blk_thresh); +} + +void rec_clear_predictors(vector_ptr fmv) +{ + fmv->is_predictor = NO; // by Yongjun Wu: clear predictor sign for the whole quad-tree + if (fmv->child) + { + rec_clear_predictors(fmv->child0); + rec_clear_predictors(fmv->child1); + rec_clear_predictors(fmv->child2); + rec_clear_predictors(fmv->child3); + } +} + +void clear_predictors(vector_ptr fmv, videoinfo info, int t_level) +{ + int X, Y, xnum, ynum, pos; + + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + + for( Y = 0; Y < ynum; Y++ ) { + for( X = 0; X < xnum; X++ ) { + pos = Y * xnum + X; + rec_clear_predictors(&fmv[pos]); + } + } +} + +// get median predictor for block E, using blocks A, B, C, and D +// block scheme: CBD +// AN +// E +//Modified by Yuan Liu on 01.18.2016 +void get_median_predictor(float *pmvx, float *pmvy, vector_ptr fmv, vector_ptr prev_fmv, + vector_ptr prev_fmv2, int x_pos, int y_pos, int xblock, int yblock, + videoinfo info, int t_level, int blk_thresh) +{ + int hor, ver, x_dest, y_dest, i, k; + enum FLAG is_pred_a, is_pred_b, is_pred_c, is_pred_d, is_pred_e; + enum FLAG is_pred_tmp; //Added on 02.22.2016 + float mvx_a, mvy_a; + float mvx_b, mvy_b; + float mvx_c, mvy_c; + float mvx_d, mvy_d; + float mvx_e, mvy_e; + + float mvx_tmp, mvy_tmp; //Added on 02.22.2016 + int blocks_avail, count; + enum BiMode block_mode; + int propagate_iblk=0; + + float med_px[4], med_py[4]; + + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + + // initialization + hor = info.ywidth; + ver = info.yheight; + + xblock = ( x_pos + xblock <= hor ) ? xblock : hor - x_pos; + yblock = ( y_pos + yblock <= ver ) ? yblock : ver - y_pos; + + assert(x_pos >= 0 && x_pos < hor && y_pos >= 0 && y_pos < ver); + + // try to get predictors for blocks A, B, and C + // A + x_dest = x_pos - 1; + y_dest = y_pos + yblock - 1; + if (x_dest < 0 || y_dest >= ver) { + is_pred_a = NO; + } else { + get_predictor(&mvx_a, &mvy_a, &is_pred_a, fmv, x_dest, y_dest, info, t_level, + &block_mode, &propagate_iblk, blk_thresh); + } + + // B + y_dest = y_pos - 1; + x_dest = x_pos + xblock - 1; + if (y_dest < 0 || x_dest >= hor) { + is_pred_b = NO; + } else { + get_predictor(&mvx_b, &mvy_b, &is_pred_b, fmv, x_dest, y_dest, info, t_level, + &block_mode, &propagate_iblk, blk_thresh); + } + + // C + x_dest = x_pos - 1; + y_dest = y_pos - 1; + if (x_dest < 0 || y_dest < 0) { + is_pred_c = NO; + } else { + get_predictor(&mvx_c, &mvy_c, &is_pred_c, fmv, x_dest, y_dest, info, t_level, + &block_mode, &propagate_iblk, blk_thresh); + } + + // blocks A, B, and C available? + if (is_pred_a == YES && is_pred_b == YES && is_pred_c == YES) { + pmvx[0] = mvx_a; + pmvy[0] = mvy_a; + pmvx[1] = mvx_b; + pmvy[1] = mvy_b; + pmvx[2] = mvx_c; + pmvy[2] = mvy_c; + + } else { +// try to get predictor for block D +// D + x_dest = x_pos + xblock; + y_dest = y_pos - 1; + if (x_dest >= hor || y_dest < 0) { + is_pred_d = NO; + } else { + get_predictor(&mvx_d, &mvy_d, &is_pred_d, fmv, x_dest, y_dest, info, t_level, + &block_mode, &propagate_iblk, blk_thresh); + } + +//////////////////// Added by Yuan Liu //////////////////// + if(is_pred_a == YES){ + pmvx[0] = mvx_a; + pmvy[0] = mvy_a; + } + if(is_pred_b == YES){ + pmvx[1] = mvx_b; + pmvy[1] = mvy_b; + } + if(is_pred_c == YES){ + pmvx[2] = mvx_c; + pmvy[2] = mvy_c; + } + if(is_pred_d == YES){ + pmvx[3] = mvx_d; + pmvy[3] = mvy_d; + } +//////////////////////////////////////////////////////////////// + } + +///////////// Modified by by Yuan Liu ////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } +////////////////////////////////////////////////////////// + +////////////// Added on 02.02.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 3); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + assert(pmvx[3] == (float)HUGE_VAL && pmvy[3] == (float)HUGE_VAL); +////////////////////////////////////////////////////////////// + //Set median prediction candidate if available + if(pmvx[0] != (float)HUGE_VAL && pmvy[0] != (float)HUGE_VAL && pmvx[1] != (float)HUGE_VAL && pmvy[1] != (float)HUGE_VAL + && pmvx[2] != (float)HUGE_VAL && pmvy[2] != (float)HUGE_VAL){ + pmvx[3] = median( pmvx[0],pmvx[1],pmvx[2]); + pmvy[3] = median( pmvy[0],pmvy[1],pmvy[2]); + } + + ///////////// Modified by by Yuan Liu ////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + ////////////////////////////////////////////////////////// + + ////////////// Added on 02.21.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } +////////////////////////////////////////////////////////////// + +// if(pmvx[3]==(float)HUGE_VAL && pmvy[3]==(float)HUGE_VAL && pmvx[2]!=(float)HUGE_VAL && pmvy[2]!=(float)HUGE_VAL){ +// assert( pmvx[0]!=(float)HUGE_VAL && pmvy[0]!=(float)HUGE_VAL && pmvx[1]!=(float)HUGE_VAL && pmvy[1]!=(float)HUGE_VAL ); + for( count = 0; count <= 3; count ++ ){ + if(pmvx[count] == (float)HUGE_VAL && pmvy[count] == (float)HUGE_VAL){ + if(prev_fmv != NULL){ + x_dest = x_pos; + y_dest = y_pos; + assert(x_dest >= 0 && y_dest >= 0); + get_predictor(&mvx_tmp, &mvy_tmp, &is_pred_tmp, prev_fmv, x_dest, y_dest, info, t_level, + &block_mode, &propagate_iblk, blk_thresh); + if(mvx_tmp != (float)HUGE_VAL && mvy_tmp != (float)HUGE_VAL && is_pred_tmp == YES){ + pmvx[count] = mvx_tmp; + pmvy[count] = mvy_tmp; + } + } + break; + } + } + +////////////////////////////////////////////////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } +/////////////////////////////////////////////////////// + + ////////////// Added on 02.27.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + +//block E + for( count = 0; count <= 3; count ++ ){ + if(pmvx[count] == (float)HUGE_VAL && pmvy[count] == (float)HUGE_VAL){ + x_dest = x_pos - 1; + y_dest = y_pos + yblock; + if (x_dest < 0 || y_dest >= ver) { + is_pred_e = NO; + } else { + get_predictor(&mvx_e, &mvy_e, &is_pred_e, fmv, x_dest, y_dest, info, t_level, + &block_mode, &propagate_iblk, blk_thresh); + if(mvx_e != (float)HUGE_VAL && mvy_e != (float)HUGE_VAL && is_pred_e == YES){ + pmvx[count] = mvx_e; + pmvy[count] = mvy_e; + } + } + break; + } + } + +////////////////////////////////////////////////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } +/////////////////////////////////////////////////////// + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + +} + +float get_bit_cost(float lambda, float mvx, float mvy, float pmvx, float pmvy, + int ctx_x, int ctx_y, int subpel) +{ + int dmvx, dmvy; + float float_dmvx, float_dmvy; + + if (lambda > 0.) { + + dmvx = (int) ((1 << subpel) * (mvx - pmvx)); + dmvy = (int) ((1 << subpel) * (mvy - pmvy)); + + float_dmvx = ((1 << subpel) * (mvx - pmvx)); + float_dmvy = ((1 << subpel) * (mvy - pmvy)); + + if(float_dmvx != (int)float_dmvx || float_dmvy != (int)float_dmvy){ + return (float)HUGE_VAL; + }else + return lambda * (ec_get_expected_length(dmvx, ctx_x) + + ec_get_expected_length(dmvy, ctx_y)); + } else { + return 0.; + } +} diff --git a/Interframe EZBC/TempSub/src/chrom.c b/Interframe EZBC/TempSub/src/chrom.c new file mode 100644 index 0000000..d092330 --- /dev/null +++ b/Interframe EZBC/TempSub/src/chrom.c @@ -0,0 +1,344 @@ +// this file contains functions for down/up-sampling chrominance compant by MPEG half band filters. +/* f444_422 f444_420 f420_444 f422_444 up/down-sample chrominance components. +The size of chromiance component will change correspondingly, but is not returned to its parent function*/ +#include +#include +#include +#include "structN.h" +#include "basic.h" +#include "util_filtering.h" + + +void +YUV2RGB( float Y, float U, float V, float *R, float *G, float *B ) +{ + *R = ( float )( 1.000 * Y - 0.0009 * U + 1.4017 * V ); + *G = ( float )( 1.000 * Y - 0.3437 * U - 0.7142 * V ); + *B = ( float )( 1.000 * Y + 1.7722 * U + 0.0010 * V ); +/* *R = 1.000*Y - 0.0009*V + 1.4017*U; + *G = 1.000*Y - 0.3437*V - 0.7142*U; + *B = 1.000*Y + 1.7722*V + 0.0010*U;*/ + +} + +void +RGB2YUV( float R, float G, float B, float *Y, float *U, float *V ) +{ + *Y = ( float )( 0.299 * R + 0.587 * G + 0.114 * B ); + *U = ( float )( -0.169 * R - 0.331 * G + 0.500 * B ); + *V = ( float )( 0.500 * R - 0.419 * G - 0.081 * B ); +} + + +// 240M +void +YUV2RGB_( float Y, float U, float V, float *R, float *G, float *B ) +{ + *R = ( float )( 1.000 * Y - 0.0007 * U + 1.5758 * V ); + *G = ( float )( 1.000 * Y - 0.2264 * U - 0.4765 * V ); + *B = ( float )( 1.000 * Y + 1.8260 * U - 0.0004 * V ); + +} + +//240M +void +RGB2YUV_( float R, float G, float B, float *Y, float *U, float *V ) +{ + *Y = ( float )( 0.212 * R + 0.701 * G + 0.087 * B ); + *U = ( float )( -0.116 * R - 0.384 * G + 0.500 * B ); + *V = ( float )( 0.500 * R - 0.445 * G - 0.055 * B ); +} + + + + + +void +f444_422( videoinfo info, YUVimage * frame ) +{ + int i, j, chor, cver, chor_half; + int filter_length, half_length, new_length; + float *h = NULL, *line = NULL, *extension = NULL, *outline = NULL; + float *U = NULL, *V = NULL; + + filter_length = 7; + h = ( float * )getarray( filter_length, sizeof( float ), "h" ); + h = &h[filter_length / 2]; + h[-3] = h[3] = -29 / 256.; + h[-2] = h[2] = 0.; + h[-1] = h[1] = 88 / 256.; + h[0] = 138 / 256.; + + if( info.cwidth % 2 ) { + printf( "can not handle this case!\n" ); + exit( 1 ); + } + chor = info.cwidth; + chor_half = chor / 2; + cver = info.cheight; + + U = ( float * )getarray( chor_half * cver, sizeof( float ), "U" ); + V = ( float * )getarray( chor_half * cver, sizeof( float ), "V" ); + + outline = ( float * )getarray( chor, sizeof( float ), "outline" ); + + + half_length = ( filter_length - 1 ) / 2; + new_length = chor + 2 * half_length; + extension = ( float * )getarray( new_length, sizeof( float ), "extension" ); + extension = &extension[half_length]; + + + + for( i = 0; i < cver; i++ ) { + line = &( frame->U[i * chor] ); + line_convolve( line, extension, chor, h, filter_length, ANAL, outline ); + for( j = 0; j < chor_half; j++ ) + U[i * chor_half + j] = outline[j * 2]; + + line = &( frame->V[i * chor] ); + line_convolve( line, extension, chor, h, filter_length, ANAL, outline ); + for( j = 0; j < chor_half; j++ ) + V[i * chor_half + j] = outline[j * 2]; + + } + + free( frame->U ); + free( frame->V ); + free( ( char * )&extension[-half_length] ); + + frame->U = U; + frame->V = V; + + free( outline ); + + free( ( char * )&h[-filter_length / 2] ); +} + + +void +f444_420( videoinfo info, YUVimage * frame ) +{ + int i, j, chor, cver, chor_half, cver_half; + int filter_length, half_length, new_length; + float *h = NULL, *line = NULL, *outline = NULL; + float *U = NULL, *V = NULL; + float *extension; + + filter_length = 7; + h = ( float * )getarray( filter_length, sizeof( float ), "h" ); + h = &h[filter_length / 2]; + h[-3] = h[3] = -29 / 256.; + h[-2] = h[2] = 0.; + h[-1] = h[1] = 88 / 256.; + h[0] = 138 / 256.; + + if( info.cwidth % 2 || info.cheight % 2 ) { + printf( "can not handle this case!\n" ); + exit( 1 ); + } + chor = info.cwidth; + chor_half = chor / 2; + cver = info.cheight; + cver_half = cver / 2; + + + U = ( float * )getarray( chor_half * cver, sizeof( float ), "U" ); + V = ( float * )getarray( chor_half * cver, sizeof( float ), "V" ); + + outline = + ( float * )getarray( MY_MAX( chor, cver ), sizeof( float ), "outline" ); + half_length = ( filter_length - 1 ) / 2; + new_length = MY_MAX( chor, cver ) + 2 * half_length; + extension = ( float * )getarray( new_length, sizeof( float ), "extension" ); + extension = &extension[half_length]; + + + + for( i = 0; i < cver; i++ ) { + line = &( frame->U[i * chor] ); + line_convolve( line, extension, chor, h, filter_length, ANAL, outline ); + for( j = 0; j < chor_half; j++ ) + U[i * chor_half + j] = outline[j * 2]; + } + + line = ( float * )getarray( cver, sizeof( float ), "line" ); + for( j = 0; j < chor_half; j++ ) { + for( i = 0; i < cver; i++ ) + line[i] = U[i * chor_half + j]; + line_convolve( line, extension, cver, h, filter_length, ANAL, outline ); + for( i = 0; i < cver_half; i++ ) + U[i * chor_half + j] = outline[i * 2]; + } + free( line ); + + + + for( i = 0; i < cver; i++ ) { + line = &( frame->V[i * chor] ); + line_convolve( line, extension, chor, h, filter_length, ANAL, outline ); + for( j = 0; j < chor_half; j++ ) + V[i * chor_half + j] = outline[j * 2]; + + } + + line = ( float * )getarray( cver, sizeof( float ), "line" ); + for( j = 0; j < chor_half; j++ ) { + for( i = 0; i < cver; i++ ) + line[i] = V[i * chor_half + j]; + line_convolve( line, extension, cver, h, filter_length, ANAL, outline ); + for( i = 0; i < cver_half; i++ ) + V[i * chor_half + j] = outline[i * 2]; + } + free( line ); + + free( frame->U ); + free( frame->V ); + free( outline ); + free( ( char * )&extension[-half_length] ); + + frame->U = U; + frame->V = V; + + + free( ( char * )&h[-filter_length / 2] ); +} + +void +f422_444( videoinfo info, YUVimage * frame ) +{ + int i, j, chor, cver, chor2; + int filter_length, half_length, new_length; + float *h = NULL, *line = NULL, *extension = NULL, *outline = NULL; + float *U = NULL, *V = NULL; + + filter_length = 7; + h = ( float * )getarray( filter_length, sizeof( float ), "h" ); + h = &h[filter_length / 2]; + h[-3] = h[3] = -12 / 256.; + h[-2] = h[2] = 0.; + h[-1] = h[1] = 140 / 256.; + h[0] = 256 / 256.; + + chor = info.cwidth; + chor2 = chor * 2; + cver = info.cheight; + + line = ( float * )getarray( chor2, sizeof( float ), "line" ); + outline = ( float * )getarray( chor2, sizeof( float ), "outline" ); + + half_length = ( filter_length - 1 ) / 2; + new_length = chor2 + 2 * half_length; + extension = ( float * )getarray( new_length, sizeof( float ), "extension" ); + extension = &extension[half_length]; + + U = ( float * )getarray( chor2 * cver, sizeof( float ), "U" ); + V = ( float * )getarray( chor2 * cver, sizeof( float ), "V" ); + + + for( i = 0; i < cver; i++ ) { + for( j = 0; j < chor2; j++ ) { + if( j % 2 ) + line[j] = 0.; + else + line[j] = frame->U[i * chor + j / 2]; + } + line_convolve( line, extension, chor2, h, filter_length, ANAL, outline ); + + for( j = 0; j < chor2; j++ ) + U[i * chor2 + j] = outline[j]; + + } + + for( i = 0; i < cver; i++ ) { + for( j = 0; j < chor2; j++ ) { + if( j % 2 ) + line[j] = 0; + else + line[j] = frame->V[i * chor + j / 2]; + } + line_convolve( line, extension, chor2, h, filter_length, ANAL, outline ); + + for( j = 0; j < chor2; j++ ) + V[i * chor2 + j] = outline[j]; + + } + + free( frame->U ); + free( frame->V ); + + frame->U = U; + frame->V = V; + free( outline ); + + + free( line ); + free( ( char * )&extension[-half_length] ); + free( ( char * )&h[-filter_length / 2] ); +} + + + +void +f420_422( videoinfo info, YUVimage * frame ) +{ + int i, j, chor, cver, cver2; + float *U = NULL, *V = NULL; + + chor = info.cwidth; + cver = info.cheight; + cver2 = cver * 2; + + U = ( float * )getarray( chor * cver2, sizeof( float ), "U" ); + V = ( float * )getarray( chor * cver2, sizeof( float ), "V" ); + + // transpose U and V + for( i = 0; i < cver; i++ ) { + for( j = 0; j < chor; j++ ) { + U[j * cver + i] = frame->U[i * chor + j]; + V[j * cver + i] = frame->V[i * chor + j]; + } + } + info.cwidth = cver; + info.cheight = chor; + + free( frame->U ); + free( frame->V ); + + frame->U = U; + frame->V = V; + + f422_444( info, frame ); + + + U = ( float * )getarray( chor * cver2, sizeof( float ), "U" ); + V = ( float * )getarray( chor * cver2, sizeof( float ), "V" ); + + // transpose U and V + for( i = 0; i < info.cheight; i++ ) { + for( j = 0; j < info.cwidth * 2; j++ ) { + U[j * info.cheight + i] = frame->U[i * info.cwidth * 2 + j]; + V[j * info.cheight + i] = frame->V[i * info.cwidth * 2 + j]; + } + } + + free( frame->U ); + free( frame->V ); + + frame->U = U; + frame->V = V; +} + + + + +void +f420_444( videoinfo info, YUVimage * frame ) +{ + //upsample vertically + f420_422( info, frame ); + + info.cheight *= 2; + //upsample horizontally + f422_444( info, frame ); +} diff --git a/Interframe EZBC/TempSub/src/cnv_data_4_1.c b/Interframe EZBC/TempSub/src/cnv_data_4_1.c new file mode 100644 index 0000000..a85f6e5 --- /dev/null +++ b/Interframe EZBC/TempSub/src/cnv_data_4_1.c @@ -0,0 +1,23 @@ +/* file: cnv_data_4_1.c */ +#include +#include +#include +#include +#include +#include "basic.h" + +void +cnv_data_4_1( float *y, unsigned char *x, int n ) +{ + int i, tmp; + + for( i = 0; i < n; i++ ) { + tmp = nint( y[i] + 128.0 ); + if( tmp < 0 ) + tmp = 0; + if( tmp > 255 ) + tmp = 255; + x[i] = ( unsigned char )tmp; + } + return; +} diff --git a/Interframe EZBC/TempSub/src/dataio.c b/Interframe EZBC/TempSub/src/dataio.c new file mode 100644 index 0000000..9c568f3 --- /dev/null +++ b/Interframe EZBC/TempSub/src/dataio.c @@ -0,0 +1,116 @@ +#include "stdio.h" +#include "stdlib.h" +#include + + +void +write_number_core( int outputbyte, FILE * fp ) +{ + int tmpbyte; + tmpbyte = ( outputbyte & 0xff000000 ) >> 24; + putc( tmpbyte, fp ); + tmpbyte = ( outputbyte & 0x00ff0000 ) >> 16; + putc( tmpbyte, fp ); + tmpbyte = ( outputbyte & 0x0000ff00 ) >> 8; + putc( tmpbyte, fp ); + tmpbyte = outputbyte & 0x000000ff; + putc( tmpbyte, fp ); + return; +} + +int +read_number_core( FILE * fp ) +{ + int i, tmpbyte, inputbyte; + + tmpbyte = getc( fp ); + inputbyte = tmpbyte & 0x7f; + +// printf("inputbyte = %d\n",inputbyte); + + for( i = 0; i < 3; i++ ) { + inputbyte <<= 8; + inputbyte += getc( fp ); +// printf("inputbyte = %d\n",inputbyte); + } + + return ( inputbyte ); +} + + +unsigned int +read_number_sub( FILE * fp ) +{ + int tmpbyte; + unsigned int inputbyte; + + tmpbyte = getc( fp ); + inputbyte = tmpbyte & 0xff; + + inputbyte <<= 8; + inputbyte += getc( fp ); + + return ( inputbyte ); +} + + +void +write_number_sub(unsigned int outputbyte, FILE * fp ) +{ + int tmpbyte; + + tmpbyte = ( outputbyte & 0xff00 ) >> 8; + putc( tmpbyte, fp ); + + tmpbyte = outputbyte & 0x00ff; + + putc( tmpbyte, fp ); + return; +} + +int +write_substream_length( int length, FILE * fp ) +{ + int i, tmpbyte; + + if( length <= 0x7fff ) { + for( i = 1; i >= 0; i-- ) { + tmpbyte = length >> 8 * i; + putc( tmpbyte, fp ); + } + + return 2; + } else if( length <= 0x7fffffff ) { + length = length | 0x80000000; + for( i = 3; i >= 0; i-- ) { + tmpbyte = length >> 8 * i; + putc( tmpbyte, fp ); + } + return 4; + } else { + printf( "substream %d is too long (dataio.c)\n", length ); + exit( 0 ); + } +} + +int +read_substream_length( int *length, FILE * fp ) +{ + int i, tmpbyte; + + tmpbyte = getc( fp ); + + if( tmpbyte & 0x80 ) { + for( i = 2; i >= 0; i-- ) { + tmpbyte <<= 8; + tmpbyte += getc( fp ); + } + *length = tmpbyte & 0x7fffffff;; + return 4; + } else { + tmpbyte <<= 8; + tmpbyte += getc( fp ); + *length = tmpbyte; + return 2; + } +} diff --git a/Interframe EZBC/TempSub/src/decoderN.c b/Interframe EZBC/TempSub/src/decoderN.c new file mode 100644 index 0000000..c6f7374 --- /dev/null +++ b/Interframe EZBC/TempSub/src/decoderN.c @@ -0,0 +1,366 @@ +#include +#include +#include +#include +#include +#include +#include +#define EXTERN +#include "basic.h" +#include "structN.h" +#include "coderN.h" +#include "initN.h" +#include "ioN.h" +#include "memoryN.h" +#include "miscN.h" +#include "init_decN.h" +#include "mvcodingN.h" +#include "analsyn.h" +#include "pstatN.h" +#include "chrom.h" +#include "mv_statistics.h" + +void ezbc3d_dec_GOP( YUVimage * pyrFrs, videoinfo info, long total_bytes_past, + long int GOP_counter, int curr ); + +void read_command( int argc, char **argv, videoinfo * info ); + +void print_time( double sc ); + +float global_motion_active; + +/* + * main() + */ +int +main( int argc, char **argv ) +{ + int curr, last, remaining_frs, s_level; + long mark, elp; // initial and elapsed time + double duration; + FILE *fp_stat, *fpio; + videoinfo info; + long int total_bytes_past = 0, total_bytes_past_buffer; + long int *read_GOP_bytes; + long int num_of_GOP, GOP_counter; + enum FLAG first_GOP, Level_change; + char mvstatname[512]; + + int gop_psnr_start; + int simul_count; //Added on 01.19.2018 估计的数量 + + int cx, cy, cpos; + FILE *pc; + + printf("Built on %s at %s.\n", __DATE__, __TIME__); + + mark = clock( ); + + read_command( argc, argv, &info );// 读命令行 + + read_header( info.bitname, &info ); + total_bytes_past += sizeof( videoheader ); + + /* open MV statistics file 打开MV统计文件,以便写入统计信息 */ + strcpy(mvstatname, info.statname); + strcat(mvstatname, "_mvstatistics.log"); + mvStat_open(mvstatname); + + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + // save the original resolution for frequency roll-off by Yongjun Wu + info.org_yheight = info.yheight; + info.org_ywidth = info.ywidth; + if( s_level > 0 ) { + info.ywidth >>= s_level; + info.yheight >>= s_level; + info.cwidth >>= s_level; + info.cheight >>= s_level; + } + + switch ( info.format ) { + case YUV: + case RAS: + info.pixeldepth = 8; + break; + case DPX: + info.pixeldepth = 10; + break; + default: + printf( "image format error format = %d(pstatN.c)\n", info.format ); + exit( 1 ); + } + + + // 初始化 + buff_frameMEinfo = (ImageMEinfo *)getarray( info.yheight * info.ywidth, sizeof( ImageMEinfo ), "buff_frameMEinfo" ); + for( cy = 0; cy < info.yheight; cy++ ){ + for( cx = 0; cx < info.ywidth; cx++ ){ + cpos = cy * info.ywidth + cx; + buff_frameMEinfo[cpos].left_mvx = 0; + buff_frameMEinfo[cpos].left_mvy = 0; + buff_frameMEinfo[cpos].right_mvx = 0; + buff_frameMEinfo[cpos].right_mvy = 0; + } + } + + num_of_GOP = get_GOP_num( info ); + // printf( "number of GOPs = %d\n", (int) num_of_GOP ); + + read_GOP_bytes = + ( long int * )getarray( num_of_GOP, sizeof( long int ), + "read_GOP_bytes" ); + if( !( fpio = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, total_bytes_past, SEEK_SET ); + fread( read_GOP_bytes, sizeof( long int ), num_of_GOP, fpio ); + + fclose( fpio ); + total_bytes_past += num_of_GOP * sizeof( long int ); //printf("%d\n", total_bytes_past); + + if( !( fp_stat = fopen( info.statname, "wt" ) ) ) { + printf( "Can not open %s\n", info.statname ); + exit( 1 ); + } + fprintf( fp_stat, "\n\tDecoding %.3d-%.3d\n", info.start, info.last ); + fprintf( fp_stat, "\tY: %d x %d; C: %d x %d\n", info.ywidth, + info.yheight, info.cwidth, info.cheight ); + fprintf( fp_stat, "\tOriginal video frame rate: %d fps\n", info.framerate ); + fprintf( fp_stat, "\tGOP size: %d frs\n", info.GOPsz ); + fprintf( fp_stat, "\tHeader size: %d bytes\n\n", sizeof( videoheader ) ); + fclose( fp_stat ); + + init_dec( info ); + + Level_change = NO; // full GOP + first_GOP = YES; + curr = info.start; + last = info.last; + GOP_counter = 0; + + + while( curr <= last ) { /* MCTF decoding gop级别*/ + remaining_frs = last - curr + 1; + + if ( remaining_frs < info.GOPsz ){ + Level_change = YES; + info.eff_GOPsz = remaining_frs; + // printf( "******* read last GOP (curr %d, eff_GOPsz %d, remaining_frs %d) *******\n", + // curr, info.eff_GOPsz, remaining_frs ); + } else { + Level_change = NO; // full GOP + info.eff_GOPsz = info.GOPsz; // effective GOP size + } + + if ( first_GOP == YES ) + printf( " decoding frame %d (first_GOP) .....\n", curr ); + else + printf( " decoding frame %d - %d .....\n", curr - info.GOPsz + 1, curr ); + +#ifdef SUPPORT_INTRA + switch ( info.intra ) { + case YES: + + if( info.denoise_flag == YES ) { + printf( "In intraframe coding mode, denoise = YES is not allowed\n" ); + exit( 1 ); + } + + info.GOPbytes = read_GOP_bytes[GOP_counter]; + +#ifdef THREE_D + three_D_syn( curr, GOP_counter, &total_bytes_past, info ); +#else + intra_decode( curr, GOP_counter, &total_bytes_past, info ); +#endif + total_bytes_past += info.GOPbytes; + // calsnr_seq(&cfr, &pfr, curr, curr+nFrsPyr-1, info); /* pstatN.c */ + /* cfr and pfr are just used as the memory in calsnr, and the data in cfr and pfr is not used in calsnr */ + + break; + + case NO: +#endif + info.GOPbytes = read_GOP_bytes[GOP_counter]; // 一个gop的字节数 + printf("newfat = %d\n",info.GOPbytes); + + simul_count = 0; + +// gop_block = 0; frame_cnt = 0; + + if( info.denoise_flag == YES ) { + + denoise_mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs); + } else { + + mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs, NO, NO ); // 进行解码 + } + +// printf("gop_block = %f\n",gop_block/frame_cnt); + + total_bytes_past += info.GOPbytes; +// printf("info.GOPbytes = %d\n",info.GOPbytes); + // calsnr_seq(&cfr, &pfr, curr, curr+info.GOPsz-1, info); /* pstatN.c */ + /* cfr and pfr are just used as the memory in calsnr, and the data in cfr and pfr is not used in calsnr */ +#ifdef SUPPORT_INTRA + break; + + default: + printf( "error in decoderN.c\n" ); + exit( 1 ); + } +#endif + + first_GOP = NO; + GOP_counter++; + curr += info.GOPsz; + + } // while + + // decode LAST GOP // 解码最后一个gop + { + info.eff_GOPsz = remaining_frs; + remaining_frs = 0; // no bitstream extraction of last GOP, only temporal filtering + + printf( " decoding frame %d - %d (last_GOP) .....\n", curr - info.GOPsz + 1, last ); + + info.GOPbytes = read_GOP_bytes[GOP_counter]; + + if( info.denoise_flag == YES ) { + denoise_mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs); + } else { + mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs, NO, NO ); + } + // total_bytes_past += info.GOPbytes; + } + + gop_psnr_start = info.last - info.GOPsz + 1; + + if ( info.s_level == 0 ){ // Quarter == 0 + if( info.denoise_flag == YES ){ + info.ywidth *= 2; + info.yheight *= 2; + info.cwidth *= 2; + info.cheight *= 2; + + calsnr( info.start, info.last, info ); + + info.ywidth /= 2; + info.yheight /= 2; + info.cwidth /= 2; + info.cheight /= 2; + } + else + { + calsnr( info.start, info.last, info ); + } + } + + // } + + info.bitrate = + ( int )( 8 * total_bytes_past * + ( ( float )info.framerate / ( info.last - info.start + 1 ) ) ); + if( !( fp_stat = fopen( info.statname, "at+" ) ) ) { + printf( "Can not open %s\n", info.statname ); + exit( 1 ); + } + fprintf( fp_stat, "\n\t total bytes %d, rate %d bps \n", + (int) total_bytes_past, info.bitrate ); + fclose( fp_stat ); + + elp = clock( ) - mark; + duration = ( double )elp / CLOCKS_PER_SEC; + print_time( duration ); + + mvStat_close(); + +#ifdef BLOCKMODE_STATISTICS + dump_blockmode_statistics(info.statname); +#endif + + printf( "finished.\n" ); + free(read_GOP_bytes); + + free(buff_frameMEinfo); + return 0; +} + + + +/* + * usage() + */ +void +usage( ) +{ + printf( "decoder: bitfile decname inname statname \n" ); +} + +void +read_command( int argc, char **argv, videoinfo * info ) +{ + int i, argnum = 1; + for( i = 1; i < argc; i++ ) { + if( *( argv[i] ) == '-' ) { + + switch ( *( ++argv[i] ) ) { + default: + printf( "-%c such an option is not available\n", *( argv[i] ) ); + usage( ); + exit( 1 ); + case 'h': + usage( ); + exit( 1 ); + break; + } + } else { + switch ( argnum ) { + default: + printf( "more parameters are specified\n" ); + usage( ); + exit( 1 ); + case 1: + strcpy( info->bitname, argv[i] ); + argnum++; + break; + case 2: + strcpy( info->decname, argv[i] ); + argnum++; + break; + case 3: + strcpy( info->inname, argv[i] ); + argnum++; + break; + case 4: + strcpy( info->statname, argv[i] ); + argnum++; + break; + case 5: + strcpy( info->jp2k_decname, argv[i] ); + argnum++; + break; +#ifdef CNN_wavelet + case 6: + strcpy(info->hpcbindata, argv[i]); + argnum++; + break; +#endif + } + } + } +#ifdef CNN_wavelet + if (argc != 7) { +#else + if (argc != 6) { +#endif + usage( ); + exit( 1 ); + } + +} diff --git a/Interframe EZBC/TempSub/src/directional_iblock.c b/Interframe EZBC/TempSub/src/directional_iblock.c new file mode 100644 index 0000000..9e76feb --- /dev/null +++ b/Interframe EZBC/TempSub/src/directional_iblock.c @@ -0,0 +1,3731 @@ + +#define EXTERN extern +#include "general.h" +#include "structN.h" +#include "coderN.h" +#include "bme_tools.h" +#include "basic.h" +#include "analsyn.h" + +// 5/3 filter normalization +const float alpha = (float)sqrt(23.0 / 32.0); +const float beta = (float)sqrt( 3.0 / 2.0); +#define DRIFT_PENALTY_IBLOCK 2.5 +#define PROPAGATION_PENALTY_IBLOCK 10.0 + + + // block neighbors: ( example for 4x4 block ) + // + // neighbor A ... H for some block X + // cx-1 cx+blksize + // | | + // H A A A A B B B B --- cy-1 row + // G X X X X C + // G X X X X C + // G X X X X C + // G X X X X C + // F E E E E D D D D --- cy+blksize row + // F + // F + // F + // + + +// SPATIAL_VERTICAL prediction for block X +char spatial_ver_pre(float *predict_blk, float *neighborA, float *neighborE, int xblk, int yblk, char blkthresh) +{ + int i, x, y; + char A_sign, E_sign; + + if (xblk!=yblk) + { + assert(0); + return 0; + } + + // check whether the block size is in the allowed value set + // xblk==1 is in the case of resolution scalability + if (!(xblk==1 || xblk==2 || xblk==4 || xblk==8 || xblk==16)) + return 0; + + if (xblk==0) // this is for resolution scalability in decoder ( U V components) + return 0; + else + { + E_sign = A_sign = 1; // assume neighbor A and E are available + for (i=0; i=0); + } + + + // neighbor B not available, neighbor F available + if (!B_sign1 && F_sign1) + { + // do the prediction from upper-right to down-left + x = xblk-1; y = 0; + do + { + // predict according to the values in neighbor B + predict_blk[y*xblk+x] = neighborF[0]; + x--; y++; + }while(x>=0); + } + + // neighbor B and neighbor F are available: --- the best case + if (B_sign1 && F_sign1) + { + // do the prediction from upper-right to down-left + x = xblk-1; y = 0; + upper_dist = 1; down_dist = (xblk+1)-upper_dist; + do + { + // linear interpolation according to the values in neighbor B and neighbor F + predict_blk[y*xblk+x] = (neighborB[0]*down_dist+neighborF[0]*upper_dist)/(float)(upper_dist+down_dist); + x--; y++; + upper_dist++; down_dist--; + }while(x>=0); + } + + + if (xblk>1) // when blksize is larger than 1, then the block has upper-left and down-right parts + { + // left-upper part is predicted from neighbor A and neighbor G + // neighbor A and neighbor G are not available + if (!A_sign && !G_sign) + return 0; + + // neighbor A available, neighbor G not available + if (A_sign && !G_sign) + { + for (diag_dist=0; diag_dist=0); + } + } + + // neighbor A not available, neighbor G available + if (!A_sign && G_sign) + { + for (diag_dist=0; diag_dist=0); + } + } + + // neighbor A and neighbor G are available: --- the best case + if (A_sign && G_sign) + { + for (diag_dist=0; diag_dist=0); + } + } + + // right-down diagonal part is predicted from C , E and the second parts of neighbor B and F + + // C, E, B2 and F2 are not available: 0000 + if (!C_sign && !E_sign && !B_sign2 && !F_sign2) + return 0; + + // C available, E, F2 not available (do not care about B2): 1000 or 1010 (C E B2 F2) + if (C_sign && !E_sign && !F_sign2) + { + for (diag_dist=1; diag_dist1) // when blksize is larger than 1 then it will have the following right-upper and down-right parts + { + // right-upper diagonal part is predicted from neighbor A, C and the second part of neighbor D + + // neighbor A and neighbor C are not available: 000 + if (!A_sign && !C_sign && !D_sign2) + return 0; + + // neighbor A available, C, D2 not available: 100 + if (A_sign && !C_sign && !D_sign2) + { + for (diag_dist=1; diag_dist1) + + return 1; +} + + +// NEW VERSION: SPATIAL_VERTICAL_RIGHT prediction for block X +char spatial_verright_pre(float *predict_blk, float *neighborA, float *neighborC, + float *neighborG, float *neighborE, float neighborH, float *neighborD, + int xblk, int yblk, char blkthresh) +{ + int i, x, y, diag_dist, down_dist, upper_dist; + char A_sign, E_sign, G_sign, C_sign, H_sign, D_sign, D_sign2, index; + + // it's not square, not do spatial prediction in this case --- simplify the spatial interpolation/prediction + if (xblk!=yblk) + return 0; + + // check whether the block size is in the allowed value set + // xblk==1 is in the case of resolution scalability + if (!(xblk==1 || xblk==2 || xblk==4 || xblk==8 || xblk==16)) + return 0; + + if (xblk==0) // this is for resolution scalability in decoder + return 0; + else + { + A_sign = E_sign = 1; // assume neighbor A and E are available + G_sign = C_sign = 1; // assume neighbor G and C are available + D_sign2 = 1; + for (i=0; i1) + { + // neighbor H and neighbor E are not available + if (!H_sign && !E_sign) + return 0; + + // neighbor H available, neighbor E not available + if (H_sign && !E_sign) + { + for (diag_dist=0; diag_dist2) // only xblk>2, there will be the following cases: you can check the block diagram! + { + // neighbor A and E are not available + if (!A_sign && !E_sign) + return 0; + + // neighbor A available and neighbor E not available + if (A_sign && !E_sign) + { + for (index=0; index<(xblk/2-1); index++) + for (diag_dist=0; diag_dist=xblk) break; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborA[index]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborA[index]; + } + } + + // neighbor A not available, C available (not care about D2): 010 or 011 + if (!A_sign && C_sign) + { + for (index=xblk/2; index=xblk) break; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborC[yblk-2-2*(index-xblk/2)]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborC[yblk-2-2*(index-xblk/2)]; + } + } + + + // neighbor A and C available (not care about D2): 110 or 111 + if (A_sign && C_sign) + { + for (index=xblk/2; index=xblk) break; + upper_dist = 2*diag_dist+1; down_dist = (yblk-1-2*(index-xblk/2))-upper_dist; + y = diag_dist*2; + predict_blk[y*xblk+x] = (neighborA[index]*down_dist+neighborC[yblk-2-2*(index-xblk/2)]*upper_dist)/(float)(upper_dist+down_dist); + y = diag_dist*2+1; + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborA[index]*down_dist+neighborC[yblk-2-2*(index-xblk/2)]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + // neighbor A, C not available, and D2 available: 001 + if (!A_sign && !C_sign && D_sign2) + { + for (index=xblk/2; index=xblk) break; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborD[index-xblk/2+1]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborD[index-xblk/2+1]; + } + } + + + // neighbor A available, C not available, D2 available: 101 + if (A_sign && !C_sign && D_sign2) + { + for (index=xblk/2; index=xblk) break; + upper_dist = 2*diag_dist+1; down_dist = (yblk+1)-upper_dist; + y = diag_dist*2; + predict_blk[y*xblk+x] = (neighborA[index]*down_dist+neighborD[index-xblk/2+1]*upper_dist)/(float)(upper_dist+down_dist); + y = diag_dist*2+1; + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborA[index]*down_dist+neighborD[index-xblk/2+1]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + + if (!E_sign && !G_sign) + return 0; + + if (E_sign && !G_sign) + { + for (index=1; index<=xblk/2-1; index++) + for (diag_dist=0; diag_dist2) only when xblk>2, it needs these parts + } // if (xblk>1) + else // xblk==1 + { + // neighbor H and neighbor E are not available + if (!H_sign && !E_sign) + return 0; + + // neighbor H available, neighbor E not available + if (H_sign && !E_sign) + predict_blk[0] = neighborH; + + // neighbor H not available, neighbor E available + if (!H_sign && E_sign) + predict_blk[0] = neighborE[0]; + + // neighbor H and neighbor E are available: the best case + if (H_sign && E_sign) + predict_blk[0] = (neighborH+neighborE[0])/(float)2.0; + } + + return 1; +} + + +// NEW VERSION: SPATIAL_HORIZONTAL_DOWN prediction for block X +// it's quite similar to SPATIAL_VERTICAL_RIGHT prediction for block X +char spatial_hordown_pre(float *predict_blk, float *neighborA, float *neighborC, + float *neighborG, float *neighborE, float neighborH, float neighborD, + float *neighborD1, + int xblk, int yblk, char blkthresh) +{ + int i, x, y, diag_dist, down_dist, upper_dist; + char A_sign, E_sign, G_sign, C_sign, H_sign, D_sign, D_sign1, index; + + // it's not square, not do spatial prediction in this case --- simplify spatial interpolation/prediction + if (xblk!=yblk) + return 0; + + // check whether the block size is in the allowed value set + // xblk==1 is in the case of resolution scalability + if (!(xblk==1 || xblk==2 || xblk==4 || xblk==8 || xblk==16)) + return 0; + + if (xblk==0) // this is for resolution scalability in decoder + return 0; + else + { + A_sign = E_sign = 1; // assume neighbor A and E are available + G_sign = C_sign = 1; // assume neighbor G and C are available + D_sign1 = 1; + for (i=0; i1) + { + // neighbor H and neighbor C are not available + if (!H_sign && !C_sign) + return 0; + + // neighbor H available, neighbor C not available + if (H_sign && !C_sign) + { + for (diag_dist=0; diag_dist2) + { + // neighbor G and C are not available + if (!G_sign && !C_sign) + return 0; + + // neighbor G available and neighbor C not available + if (G_sign && !C_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_dist0; index--) + for (diag_dist=0; diag_dist0; index--) + for (diag_dist=0; diag_dist0; index--) + for (diag_dist=0; diag_dist=yblk) break; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborE[(xblk-1-index)*2]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborE[(xblk-1-index)*2]; + } + } + + // neighbor E not available, G available, D1 not available: 010 + if (!E_sign && G_sign && !D_sign1) + { + for (index=yblk/2; index=yblk) break; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborG[index]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborG[index]; + } + } + + // neighbor E and neighbor G are available (not care about D1): 110 or 111 + if (E_sign && G_sign) + { + for (index=yblk/2; index=yblk) break; + x = diag_dist*2; + predict_blk[y*xblk+x] = (neighborG[index]*down_dist+neighborE[(xblk-1-index)*2]*upper_dist)/(float)(upper_dist+down_dist); + x = diag_dist*2+1; + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborG[index]*down_dist+neighborE[(xblk-1-index)*2]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + // neighbor E, G not available, D1 available: 001 + if (!E_sign && !G_sign && D_sign1) + { + for (index=yblk/2; index=yblk) break; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborD1[index-yblk/2+1]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborD1[index-yblk/2+1]; + } + } + + // neighbor E not available, G and D1 are available: 011 + if (!E_sign && G_sign && D_sign1) + { + for (index=yblk/2; index=yblk) break; + x = diag_dist*2; + predict_blk[y*xblk+x] = (neighborG[index]*down_dist+neighborD1[index-yblk/2+1]*upper_dist)/(float)(upper_dist+down_dist); + x = diag_dist*2+1; + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborG[index]*down_dist+neighborD1[index-yblk/2+1]*upper_dist)/(float)(upper_dist+down_dist); + } + } + } // if (xblk>2) only when xblk>2, it needs these parts + } // if (xblk>1) + else // xblk==1 + { + // neighbor H and neighbor C are not available + if (!H_sign && !C_sign) + return 0; + + // neighbor H available, neighbor C not available + if (H_sign && !C_sign) + predict_blk[0] = neighborH; + + // neighbor H not available, neighbor C available + if (!H_sign && C_sign) + predict_blk[0] = neighborC[0]; + + // neighbor H and neighbor C are available + if (H_sign && C_sign) + predict_blk[0] = (neighborH+neighborC[0])/(float)2.0; + } + + return 1; +} + + +// NEW VERSION: SPATIAL_VERTICAL_LEFT prediction for block X +// it's quite similar to SPATIAL_VERTICAL_RIGHT prediction for block X +char spatial_verleft_pre(float *predict_blk, float *neighborA, float *neighborC, + float *neighborG, float *neighborE, float *neighborB, float neighborF, + int xblk, int yblk, char blkthresh) +{ + int i, x, y, diag_dist, down_dist, upper_dist; + char A_sign, E_sign, G_sign, C_sign, B_sign, B_sign1, F_sign, index; + + // it's not square, not do spatial prediction in this case --- simplify spatial interpolation/prediction + if (xblk!=yblk) + return 0; + + // check whether the block size is in the allowed value set + // xblk==1 is in the case of resolution scalability + if (!(xblk==1 || xblk==2 || xblk==4 || xblk==8 || xblk==16)) + return 0; + + if (xblk==0) // this is for resolution scalability in decoder + return 0; + else + { + A_sign = E_sign = 1; // assume neighbor A and E are available + G_sign = C_sign = 1; // assume neighbor G and C are available + B_sign1 = 1; + for (i=0; i1) + { + // neighbor A and neighbor F are not available + if (!A_sign && !F_sign) + return 0; + + // neighbor A available, neighbor F not available + if (A_sign && !F_sign) + { + for (diag_dist=0; diag_distE) + x = xblk-1-diag_dist; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborB[0]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborB[0]; + } + } + + + // neighbor B not available, neighbor E available + if (!B_sign && E_sign) + { + for (diag_dist=0; diag_distE) + x = xblk-1-diag_dist; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborE[xblk/2-1]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborE[xblk/2-1]; + } + } + + // neighbor B and neighbor E are available + if (B_sign && E_sign) + { + for (diag_dist=0; diag_distE) + x = xblk-1-diag_dist; + y = diag_dist*2; + upper_dist = diag_dist*2+1; down_dist = (yblk+1)-upper_dist; + predict_blk[y*xblk+x] = (neighborE[xblk/2-1]*upper_dist+neighborB[0]*down_dist)/(float)(yblk+1); + y = diag_dist*2+1; + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborE[xblk/2-1]*upper_dist+neighborB[0]*down_dist)/(float)(yblk+1); + } + } + + + if (xblk>2) + { + // neighbor A and E are not available + if (!A_sign && !E_sign) + return 0; + + // neighbor A available and neighbor E not available + if (A_sign && !E_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_distE) + x = xblk/2+index-diag_dist; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborA[xblk/2+1+index]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborA[xblk/2+1+index];; + } + } + + // neighbor A not available and neighbor E available + if (!A_sign && E_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_distE) + x = xblk/2+index-diag_dist; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborE[index]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborE[index]; + } + } + + // neighbor A available and neighbor E available + if (A_sign && E_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_distE) + x = xblk/2+index-diag_dist; + y = diag_dist*2; + upper_dist = 2*diag_dist+1; down_dist = (yblk+1)-upper_dist; + predict_blk[y*xblk+x] = (neighborA[xblk/2+1+index]*down_dist+neighborE[index]*upper_dist)/(float)(yblk+1); + y = diag_dist*2+1; + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborA[xblk/2+1+index]*down_dist+neighborE[index]*upper_dist)/(float)(yblk+1); + } + } + + + // C, E and B1 not available: 000 + if (!C_sign && !E_sign && !B_sign1) + return 0; + + // neighbor C available, E not available (not care about B1): 100 or 101 + if (C_sign && !E_sign) + { + for (index=xblk/2; indexC) + x = index+1+diag_dist; + if (x>=xblk) break; + y = yblk-1-2*diag_dist; + predict_blk[y*xblk+x] = neighborC[(index-xblk/2)*2+1]; + y = yblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborC[(index-xblk/2)*2+1]; + } + } + + // neighbor C not available, E available, B1 not available: 010 + if (!C_sign && E_sign && !B_sign1) + { + for (index=xblk/2; indexC) + x = index+1+diag_dist; + if (x>=xblk) break; + y = yblk-1-2*diag_dist; + predict_blk[y*xblk+x] = neighborE[index]; + y = yblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborE[index]; + } + } + + // both neighbor C, E are available (not care about B1): 110 or 111 + if (C_sign && E_sign) + { + for (index=xblk/2; indexC) + x = index+1+diag_dist; + if (x>=xblk) break; + y = yblk-1-2*diag_dist; + // 2*(xblk-index)-1 is the total distance + down_dist = 2*diag_dist+1; upper_dist = (2*(xblk-index)-1)-down_dist; + predict_blk[y*xblk+x] = (neighborC[(index-xblk/2)*2+1]*down_dist+neighborE[index]*upper_dist)/(float)(upper_dist+down_dist); + y = yblk-1-(diag_dist*2+1); + down_dist++; upper_dist--; + predict_blk[y*xblk+x] = (neighborC[(index-xblk/2)*2+1]*down_dist+neighborE[index]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + // neighbor C not available, E not available, B1 available: 001 + if (!C_sign && !E_sign && B_sign1) + { + for (index=xblk/2; indexB1) + x = index+1+diag_dist; + if (x>=xblk) break; + y = yblk-1-2*diag_dist; + predict_blk[y*xblk+x] = neighborB[index-xblk/2+1]; + y = yblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborB[index-xblk/2+1]; + } + } + + + // C not available, E and B1 are available: 011 + if (!C_sign && E_sign && B_sign1) + { + for (index=xblk/2; indexC) + x = index+1+diag_dist; + if (x>=xblk) break; + y = yblk-1-2*diag_dist; + // yblk+1 is the total distance + down_dist = 2*diag_dist+1; upper_dist = (yblk+1)-down_dist; + predict_blk[y*xblk+x] = (neighborB[index-xblk/2+1]*down_dist+neighborE[index]*upper_dist)/(float)(upper_dist+down_dist); + y = yblk-1-(diag_dist*2+1); + down_dist++; upper_dist--; + predict_blk[y*xblk+x] = (neighborB[index-xblk/2+1]*down_dist+neighborE[index]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + + if (!A_sign && !G_sign) + return 0; + + // neighbor A available and neighbor G not available + if (A_sign && !G_sign) + { + for (index=0; indexG) + // y position + x = index-diag_dist; + if (x<0) break; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborA[index+1]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborA[index+1]; + } + } + + // neighbor A not available and neighbor G available + if (!A_sign && G_sign) + { + for (index=0; indexG) + // y position + x = index-diag_dist; + if (x<0) break; + y = diag_dist*2; + predict_blk[y*xblk+x] = neighborG[(index+1)*2]; + y = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborG[(index+1)*2]; + } + } + + // neighbor A and neighbor G are available -- spatial interpolation + if (A_sign && G_sign) + { + for (index=0; index2) only when xblk>2, it needs these parts + } //if (xblk>1) + else // xblk==1 + { + // neighbor B and neighbor E are not available + if (!B_sign && !E_sign) + return 0; + + // neighbor B available, neighbor E not available + if (B_sign && !E_sign) + predict_blk[0] = neighborB[0]; + + // neighbor B not available, neighbor E available + if (!B_sign && E_sign) + predict_blk[0] = neighborE[0]; + + // neighbor B and neighbor E are available + if (B_sign && E_sign) + predict_blk[0] = (neighborE[0]+neighborB[0])/(float)2.0; + + } + + return 1; +} + + +// NEW VERSION +char spatial_horup_pre(float *predict_blk, float *neighborA, float *neighborC, float *neighborG, + float *neighborE, float neighborB, float *neighborF, int xblk, int yblk, char blkthresh) +{ + int i, x, y, diag_dist, down_dist, upper_dist; + char A_sign, E_sign, G_sign, C_sign, B_sign, F_sign, F_sign1, index; + + // it's not square, not do spatial prediction in this case --- simplify spatial interpolation/prediction + if (xblk!=yblk) + return 0; + + // check whether the block size is in the allowed value set + // xblk==1 is in the case of resolution scalability + if (!(xblk==1 || xblk==2 || xblk==4 || xblk==8 || xblk==16)) + return 0; + + if (xblk==0) // this is for resolution scalability in decoder + return 0; + else + { + A_sign = E_sign = 1; // assume neighbor A and E are available + G_sign = C_sign = 1; // assume neighbor G and C are available + F_sign1 = 1; + for (i=0; i1) + { + // neighbor B and neighbor G are not available + if (!B_sign && !G_sign) + return 0; + + // neighbor B available, neighbor G not available + if (B_sign && !G_sign) + { + for (diag_dist=0; diag_distG) + y = diag_dist; + x = xblk-1-diag_dist*2; + predict_blk[y*xblk+x] = neighborB; + x = xblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborB; + } + } + + + // neighbor B not available, neighbor G available + if (!B_sign && G_sign) + { + for (diag_dist=0; diag_distG) + y = diag_dist; + x = xblk-1-diag_dist*2; + predict_blk[y*xblk+x] = neighborG[yblk/2]; + x = xblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborG[yblk/2]; + } + } + + // neighbor B available, neighbor G available: the best case + if (B_sign && G_sign) + { + for (diag_dist=0; diag_distG) + y = diag_dist; + x = yblk-1-diag_dist*2; + upper_dist = 2*diag_dist+1; down_dist = (xblk+1)-upper_dist; + predict_blk[y*xblk+x] = (neighborB*down_dist+neighborG[yblk/2]*upper_dist)/(float)(xblk+1); + x = yblk-1-(diag_dist*2+1); + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborB*down_dist+neighborG[yblk/2]*upper_dist)/(float)(xblk+1); + } + } + + + // neighbor C and neighbor F are not available + if (!C_sign && !F_sign) + return 0; + + // neighbor C available, neighbor F not available + if (C_sign && !F_sign) + { + for (diag_dist=0; diag_distC) + y = xblk-1-diag_dist; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborC[yblk/2-1]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborC[yblk/2-1]; + } + } + + + // neighbor C not available, neighbor F available + if (!C_sign && F_sign) + { + for (diag_dist=0; diag_distC) + y = xblk-1-diag_dist; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborF[0]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborF[0]; + } + } + + // neighbor C available, neighbor F available + if (C_sign && F_sign) + { + for (diag_dist=0; diag_distC) + y = xblk-1-diag_dist; + x = diag_dist*2; + down_dist = 2*diag_dist+1; upper_dist = (xblk+1)-down_dist; + predict_blk[y*xblk+x] = (neighborC[yblk/2-1]*down_dist+neighborF[0]*upper_dist)/(float)(xblk+1); + x = diag_dist*2+1; + down_dist++; upper_dist--; + predict_blk[y*xblk+x] = (neighborC[yblk/2-1]*down_dist+neighborF[0]*upper_dist)/(float)(xblk+1); + } + } + + + if (xblk>2) + { + // neighbor G and C are not available + if (!G_sign && !C_sign) + return 0; + + // neighbor G available and neighbor C not available + if (G_sign && !C_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_distC) + y = yblk/2+index-diag_dist; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborG[yblk/2+1+index]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborG[yblk/2+1+index];; + } + } + + // neighbor G not available and neighbor C available + if (!G_sign && C_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_distC) + y = yblk/2+index-diag_dist; + x = diag_dist*2; + predict_blk[y*xblk+x] = neighborC[index]; + x = diag_dist*2+1; + predict_blk[y*xblk+x] = neighborC[index]; + } + } + + // neighbor G available and neighbor C not available + if (G_sign && C_sign) + { + for (index=0; index<(yblk/2-1); index++) + for (diag_dist=0; diag_distC) + y = yblk/2+index-diag_dist; + x = diag_dist*2; + down_dist = diag_dist*2+1; upper_dist = (xblk+1)-down_dist; + predict_blk[y*xblk+x] = (neighborC[index]*down_dist+neighborG[yblk/2+1+index]*upper_dist)/(float)(xblk+1); + x = diag_dist*2+1; + down_dist++; upper_dist--; + predict_blk[y*xblk+x] = (neighborC[index]*down_dist+neighborG[yblk/2+1+index]*upper_dist)/(float)(xblk+1); + } + } + + + if (!C_sign && !E_sign && !F_sign1) + return 0; + + // neighbor C available and E and F1 not available: 100 + if (C_sign && !E_sign && !F_sign1) + { + for (index=xblk/2; indexE) + y = index+1+diag_dist; + if (y>=yblk) break; + x = xblk-1-2*diag_dist; + predict_blk[y*xblk+x] = neighborC[index]; + x = xblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborC[index]; + } + } + + // neighbor C not available, E available( not care about F1): 010 or 011 + if (!C_sign && E_sign) + { + for (index=xblk/2; indexE) + y = index+1+diag_dist; + if (y>=yblk) break; + x = xblk-1-2*diag_dist; + predict_blk[y*xblk+x] = neighborE[(index-xblk/2)*2+1]; + x = xblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborE[(index-xblk/2)*2+1]; + } + } + + // neighbor C available and E available( not care about F1): 110 or 111 + if (C_sign && E_sign) + { + for (index=xblk/2; indexE) + y = index+1+diag_dist; + if (y>=yblk) break; + x = xblk-1-2*diag_dist; + // (xblk-1-index)*2+1 is the total distance + upper_dist = diag_dist*2+1; down_dist = (xblk-1-index)*2+1-upper_dist; + predict_blk[y*xblk+x] = (neighborC[index]*down_dist+neighborE[(index-xblk/2)*2+1]*upper_dist)/(float)(upper_dist+down_dist); + x = xblk-1-(diag_dist*2+1); + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborC[index]*down_dist+neighborE[(index-xblk/2)*2+1]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + + // neighbor C and E not available and F1 available: 001 + if (!C_sign && !E_sign && F_sign1) + { + for (index=xblk/2; indexE) + y = index+1+diag_dist; + if (y>=yblk) break; + x = xblk-1-2*diag_dist; + predict_blk[y*xblk+x] = neighborF[index-xblk/2+1]; + x = xblk-1-(diag_dist*2+1); + predict_blk[y*xblk+x] = neighborF[index-xblk/2+1]; + } + } + + // neighbor C available and E not available, F1 available: 101 + if (C_sign && !E_sign && F_sign1) + { + for (index=xblk/2; indexF1) + y = index+1+diag_dist; + if (y>=yblk) break; + x = xblk-1-2*diag_dist; + // (xblk+1) is the total distance + upper_dist = diag_dist*2+1; down_dist = (xblk+1)-upper_dist; + predict_blk[y*xblk+x] = (neighborC[index]*down_dist+neighborF[index-xblk/2+1]*upper_dist)/(float)(upper_dist+down_dist); + x = xblk-1-(diag_dist*2+1); + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborC[index]*down_dist+neighborF[index-xblk/2+1]*upper_dist)/(float)(upper_dist+down_dist); + } + } + + + if (!A_sign && !G_sign) + return 0; + + // neighbor A available and neighbor G not available + if (A_sign && !G_sign) + { + for (index=0; indexG) + // y position + y = diag_dist; + x = (index+1)*2-1-2*diag_dist; + if (x<0) break; + predict_blk[y*xblk+x] = neighborA[(index+1)*2]; + x = (index+1)*2-1-(2*diag_dist+1); + predict_blk[y*xblk+x] = neighborA[(index+1)*2]; + } + } + + // neighbor A not available and neighbor G available + if (!A_sign && G_sign) + { + for (index=0; indexG) + // y position + y = diag_dist; + x = (index+1)*2-1-2*diag_dist; + if (x<0) break; + predict_blk[y*xblk+x] = neighborG[index+1]; + x = (index+1)*2-1-(2*diag_dist+1); + predict_blk[y*xblk+x] = neighborG[index+1]; + } + } + + // neighbor A available and neighbor G available + if (A_sign && G_sign) + { + for (index=0; indexG) + // y position + y = diag_dist; + x = (index+1)*2-1-2*diag_dist; + if (x<0) break; + // (index+1)*2+1 is the total distance between neighbor A and neighbor G + upper_dist = 2*diag_dist+1; down_dist = (index+1)*2+1-upper_dist; + predict_blk[y*xblk+x] = (neighborA[(index+1)*2]*down_dist+neighborG[index+1]*upper_dist)/(float)(upper_dist+down_dist); + x = (index+1)*2-1-(2*diag_dist+1); + upper_dist++; down_dist--; + predict_blk[y*xblk+x] = (neighborA[(index+1)*2]*down_dist+neighborG[index+1]*upper_dist)/(float)(upper_dist+down_dist); + } + } + } // if (xblk>2) only when xblk>2, it needs these parts + } // if (xblk>1) + else // xblk==1 + { + // neighbor B and neighbor G are not available + if (!B_sign && !G_sign) + return 0; + + // neighbor B available, neighbor G not available + if (B_sign && !G_sign) + predict_blk[0] = neighborB; + + // neighbor B not available, neighbor G available + if (!B_sign && G_sign) + predict_blk[0] = neighborG[0]; + + // neighbor B available, neighbor G available: the best case + if (B_sign && G_sign) + predict_blk[0] = (neighborB+neighborG[0])/(float)2.0; + } + + + return 1; +} + +// cx, cy, xblk, yblk, yhor, yver, chor and cver are in full resolution +void GetSpaitialNeighborPixels8x8(videoinfo info, float *fadditional_penalty, vector_ptr fmv, + float *fr_cur, int cx, int cy, int xblk, int yblk, int yhor, int yver, + int t_level, float *fr_curU, float *fr_curV) +{ + int i, chor, cver, uvx, uvy, uvblk, x_dest, y_dest; + float mvx_d, mvy_d; + enum BiMode block_mode1, block_mode2; + enum FLAG is_pred; + int s_level, blksize, uvblksize, start_x, start_y, s_yhor, s_yver; + int s_chor, s_cver, start_uvx, start_uvy; + int propagate_iblk1=0, propagate_iblk2=0; + + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + if( s_level > 0 ) { + info.ywidth <<= s_level; + info.yheight <<= s_level; + info.cwidth <<= s_level; + info.cheight <<= s_level; + } + chor = info.cwidth; + cver = info.cheight; + uvx = cx/2; + uvy = cy/2; + uvblk = xblk/2; + + // the starting position, block size and dimension size at specific resolution + blksize = xblk>>s_level; + uvblksize = blksize/2; + start_x = cx>>s_level; + start_y = cy>>s_level; + s_yhor = yhor>>s_level; + s_yver = yver>>s_level; + s_chor = chor>>s_level; + s_cver = cver>>s_level; + start_uvx = uvx>>s_level; + start_uvy = uvy>>s_level; + + if (cy-1>=0) // neighbor A is valid + { + x_dest = cx; + y_dest = cy-1; + // get the block mode for neighbor A (first part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + x_dest = cx+4; // since the basic block size is 4x4 + y_dest = cy-1; + // get the block mode for neighbor A (second part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode2, &propagate_iblk2, 0); + assert( block_mode1!= UNDEFINED && block_mode2!= UNDEFINED ); + if (block_mode1==DIRECTIONAL_IBLOCK || block_mode2==DIRECTIONAL_IBLOCK) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if (propagate_iblk1 || propagate_iblk2 ) + *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + for (i=0; i=0 && cx+xblk+xblk-1<=yhor-1) // neighbor B is in the frame + { + x_dest = cx+xblk; + y_dest = cy-1; + // get the block mode for neighbor B (first part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0 ); + x_dest = cx+xblk+4; + y_dest = cy-1; + // get the block mode for neighbor B (second part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode2, &propagate_iblk2, 0); + if ( block_mode1 != UNDEFINED && block_mode2 != UNDEFINED && + (block_mode1==DIRECTIONAL_IBLOCK || block_mode2==DIRECTIONAL_IBLOCK) ) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if ( propagate_iblk1 || propagate_iblk2 ) + *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + // neighbor B has been visited before current block + if ( block_mode1 != UNDEFINED && block_mode2 != UNDEFINED) + for (i=0; i=0) // neighbor G + { + x_dest = cx-1; + y_dest = cy; + // get the block mode for neighbor B (first part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + x_dest = cx-1; + y_dest = cy+4; + // get the block mode for neighbor B (second part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode2, &propagate_iblk2, 0); + assert( block_mode1!= UNDEFINED && block_mode2!= UNDEFINED ); + if (block_mode1==DIRECTIONAL_IBLOCK || block_mode2==DIRECTIONAL_IBLOCK) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if ( propagate_iblk1 || propagate_iblk2 ) + *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + for (i=0; i=0 && cx-1>=0) // neighbor H + { + neighborH = fr_cur[(start_y-1)*s_yhor+(start_x-1)]; + x_dest = cx-1; + y_dest = cy-1; + // get the block mode for neighbor H + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + if (block_mode1==DIRECTIONAL_IBLOCK) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if ( propagate_iblk1) + *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + if (fr_curU!=NULL && fr_curV!=NULL) + { + neighborUH = (float)fr_curU[(start_uvy-1)*s_chor+(start_uvx-1)]; + neighborVH = (float)fr_curV[(start_uvy-1)*s_chor+(start_uvx-1)]; + } + } + return; +} + + +void GetSpaitialNeighborPixels4x4(videoinfo info, float *fadditional_penalty, vector_ptr fmv, + float *fr_cur, int cx, int cy, int xblk, int yblk, int yhor, int yver, + int t_level, float *fr_curU, float *fr_curV) +{ + int i, chor, cver, uvx, uvy, uvblk, x_dest, y_dest; + float mvx_d, mvy_d; + enum BiMode block_mode1; + enum FLAG is_pred; + int s_level, spatial_scale, blksize, uvblksize, start_x, start_y, s_yhor, s_yver; + int s_chor, s_cver, start_uvx, start_uvy; + int propagate_iblk1=0; + + // the dimensions and starting positions for Y U V at full resolution + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + if( s_level > 0 ) { + info.ywidth <<= s_level; + info.yheight <<= s_level; + info.cwidth <<= s_level; + info.cheight <<= s_level; + spatial_scale = 1<>s_level; + uvblksize = blksize/2; + if (uvblksize==0) // for the subsampling effect in spatial scalability + // ( more the one leve resolution reduction ) + { + if ( uvx%spatial_scale==0 && uvy%spatial_scale==0 ) + uvblksize = 1; + } + start_x = cx>>s_level; + start_y = cy>>s_level; + s_yhor = yhor>>s_level; + s_yver = yver>>s_level; + s_chor = chor>>s_level; + s_cver = cver>>s_level; + start_uvx = uvx>>s_level; + start_uvy = uvy>>s_level; + + if (cy-1>=0) // neighbor A is valid + { + x_dest = cx; + y_dest = cy-1; + // get the block mode for neighbor A (first part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + assert( block_mode1!= UNDEFINED ); + if (block_mode1==DIRECTIONAL_IBLOCK ) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if (propagate_iblk1) *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + for (i=0; i=0 && cx+xblk+xblk-1<=yhor-1) // neighbor B is in the frame + { + x_dest = cx+xblk; + y_dest = cy-1; + // get the block mode for neighbor B (first part) + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + if ( block_mode1 != UNDEFINED && block_mode1==DIRECTIONAL_IBLOCK ) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if (propagate_iblk1) *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + + // neighbor B has been visited before current block + if ( block_mode1 != UNDEFINED ) + for (i=0; i=0) // neighbor G + { + x_dest = cx-1; + y_dest = cy; + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + assert( block_mode1!= UNDEFINED ); + if (block_mode1==DIRECTIONAL_IBLOCK ) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if (propagate_iblk1) *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + for (i=0; i=0 && cx-1>=0) // neighbor H + { + neighborH = fr_cur[(start_y-1)*s_yhor+(start_x-1)]; + x_dest = cx-1; + y_dest = cy-1; + // get the block mode for neighbor H + get_predictor(&mvx_d, &mvy_d, &is_pred, fmv, x_dest, y_dest, info, t_level, + &block_mode1, &propagate_iblk1, 0); + if (block_mode1==DIRECTIONAL_IBLOCK) + { + *fadditional_penalty += DRIFT_PENALTY_IBLOCK; + if (propagate_iblk1) *fadditional_penalty += PROPAGATION_PENALTY_IBLOCK; + } + if (fr_curU!=NULL && fr_curV!=NULL && uvblksize!=0) + { + neighborUH = (float)fr_curU[(start_uvy-1)*s_chor+(start_uvx-1)]; + neighborVH = (float)fr_curV[(start_uvy-1)*s_chor+(start_uvx-1)]; + } + } + + return; +} + + +void Spatial_prediction_Decision(videoinfo info, float *fadditional_penalty, vector_ptr fmv, + float *fr_cur, int cx, int cy, int xblk, int yblk, int yhor, int yver, + int t_level, float *fr_curU, float *fr_curV, vector *tmv1) +{ + + int spatial_mode; + int x, y, blkthresh; + char pre_sign; + float pre_sum, pre_mse, diff; + + tmv1->total_cost = tmv1->sad_cost = (float)HUGE_VAL; + blkthresh = xblk; + for (spatial_mode=0; spatial_modesad_cost) + { + tmv1->bi_mode = DIRECTIONAL_IBLOCK; + tmv1->iblock_spatial_mode = (spatialMODE)spatial_mode; + tmv1->sad_cost = pre_sum; + tmv1->bit_cost = (*fadditional_penalty+DIRECTIONAL_IBLOCK_BIAS)*info.lambda[t_level]*3; + tmv1->total_cost = tmv1->sad_cost+tmv1->bit_cost; + } + } //for modes +} + + +void directional_iblock_detection(videoinfo info, vector_ptr fmv1_array, float *fr_cur, + int cx, int cy, int xblock, int yblock, int hor, int ver, int t_level, + vector *tmv1, float *fadditional_penalty) +{ + int x, y, xblk, yblk, n_index; + + xblk = ( cx + xblock <= hor ) ? xblock : hor - cx; + yblk = ( cy + yblock <= ver ) ? yblock : ver - cy; + + if (xblk!=yblk || ( xblk!=8 && xblk!=4) ) + return; // we skip IBLOCK detection for non-squred blocks + + // initialize all the neighbors to be HUGE_VAL + neighborH = (float)HUGE_VAL; + for ( n_index=0; n_index> 1)) { // top neighbor is effective + // the position of top neighbor at full resolution + pos = (topy-3)*( hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + { + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->Y, fr3->Y, &neighbor_valueY, + &self_weightY, ver_weightY, col, row, info, hor, ver, + 0, level); + if (i%2==0 && j%2==0 && uvblksize) + { + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->U, fr3->U, &neighbor_valueU, + &self_weightU, ver_weightU, col/2, row/2, info, hor/2, ver/2, + 1, level); + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->V, fr3->V, &neighbor_valueV, + &self_weightV, ver_weightV, col/2, row/2, info, hor/2, ver/2, + 1, level); + } + } + } else if (disy >= (yblk >> 1)) { // bottom neighbor is effective + pos = (topy+yblk+2)*( hor<Y, fr3->Y, &neighbor_valueY, + &self_weightY, ver_weightY, col, row, info, hor, ver, + 0, level); + if (i%2==0 && j%2==0 && uvblksize) + { + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->U, fr3->U, &neighbor_valueU, + &self_weightU, ver_weightU, col/2, row/2, info, hor/2, ver/2, + 1, level); + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->V, fr3->V, &neighbor_valueV, + &self_weightV, ver_weightV, col/2, row/2, info, hor/2, ver/2, + 1, level); + } + } + } + + // contribution from horizontal neighbor motion vectors + if (disx < (xblk >> 1)) { // left neighbor is effective + pos = ( row< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + { + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->Y, fr3->Y, &neighbor_valueY, + &self_weightY, hor_weightY, col, row, info, hor, ver, + 0, level); + if (i%2==0 && j%2==0 && uvblksize) + { + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->U, fr3->U, &neighbor_valueU, + &self_weightU, hor_weightU, col/2, row/2, info, hor/2, ver/2, + 1, level); + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->V, fr3->V, &neighbor_valueV, + &self_weightV, hor_weightV, col/2, row/2, info, hor/2, ver/2, + 1, level); + } + } + }else if (disx >= (xblk >> 1)) { // right neighbor is effective + pos = ( row<Y, fr3->Y, &neighbor_valueY, + &self_weightY, hor_weightY, col, row, info, hor, ver, + 0, level); + if (i%2==0 && j%2==0 && uvblksize) + { + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->U, fr3->U, &neighbor_valueU, + &self_weightU, hor_weightU, col/2, row/2, info, hor/2, ver/2, + 1, level); + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1->V, fr3->V, &neighbor_valueV, + &self_weightV, hor_weightV, col/2, row/2, info, hor/2, ver/2, + 1, level); + } + } + } + + // neighbor_valueY, neighbor_valueU and neighbor_valueV have already been weighted by alpha + // and neighbor weighting coefficients ( the set of neighbor values are negative! ) + neighbor_predictY[i*xblock+j] = neighbor_valueY; + self_weight_matrix[i*xblock+j]= self_weightY; + if ( i%2==0 && j%2==0 && uvblksize) + { + assert( self_weightU==self_weightV ); + self_weight_matrixUV[i/2*xblock/2+j/2] = self_weightV; + neighbor_predictU[i/2*xblock/2+j/2] = neighbor_valueU; + neighbor_predictV[i/2*xblock/2+j/2] = neighbor_valueV; + } + col++; + } + row++; + } + + +} + + + +// the set of analysis functions is always working in full resolution (original resolution ) +void Spatial_prediction_analysis_with_OBMC(vector_ptr fmv, int cx, int cy, int xblk, int yblk, int hor, int ver, + YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int t_level, int remaining_frs, videoinfo info, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) +{ + enum spatialMODE spatial_mode; + int x, y, blkthresh; + char pre_sign, pre_signU, pre_signV; + float diffY, diffU, diffV; + int chor, cver; + + chor = hor/2; cver = ver/2; + spatial_mode = fmv->iblock_spatial_mode; // encoder side + blkthresh = xblk; + assert( spatial_mode>=0 && spatial_mode<=8 ); + switch (spatial_mode) + { + case SPATIAL_VERTICAL: // interpolate/predict vertically + // we only need neighbor A and neighbor E for spatial vertical prediction + pre_sign = spatial_ver_pre(predict_blkY, neighborA, neighborE, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_ver_pre(predict_blkU, neighborUA, neighborUE, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_ver_pre(predict_blkV, neighborVA, neighborVE, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_HORIZONTAL: // interpolate/predict horizontally + // we only need neighbor G and neighbor C for spatial horizontal prediction + pre_sign = spatial_hor_pre(predict_blkY, neighborG, neighborC, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_hor_pre(predict_blkU, neighborUG, neighborUC, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_hor_pre(predict_blkV, neighborVG, neighborVC, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_DC: + // we need neighbor A, C, G and E for spatial DC prediction + pre_sign = spatial_dc_pre(predict_blkY, neighborA, neighborC, neighborE, neighborG, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_dc_pre(predict_blkU, neighborUA, neighborUC, neighborUE, neighborUG, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_dc_pre(predict_blkV, neighborVA, neighborVC, neighborVE, neighborVG, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_DOWN_LEFT: + // we need neighbor A, G, B, F, C, E for spatial down-left prediction + // the block is divided into 3 parts + // each part has 4 cases, so totally there are 12 cases for their existence + pre_sign = spatial_downleft_pre(predict_blkY, neighborA, neighborG, + neighborB, neighborF, neighborC, neighborE, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_downleft_pre(predict_blkU, neighborUA, neighborUG, + neighborUB, neighborUF, neighborUC, neighborUE, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_downleft_pre(predict_blkV, neighborVA, neighborVG, + neighborVB, neighborVF, neighborVC, neighborVE, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_DOWN_RIGHT: + // we need neighbor A, C, G, E, and H, D for spatial down-right prediction + // the block is divided into 3 parts + // each part has 4 cases, so totally there are 12 cases for their existence + pre_sign = spatial_downright_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborH, neighborD, neighborD1, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_downright_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUH, neighborUD, neighborUD1, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_downright_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVH, neighborVD, neighborVD1, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_VERTICAL_RIGHT: + // we need neighbor A, C, G, E, and H, D for spatial vertical-right prediction + // for 2x2 block, there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_verright_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborH, neighborD, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_verright_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUH, neighborUD, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_verright_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVH, neighborVD, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_HORIZONTAL_DOWN: + // we need neighbor A, C, G, E, and H, D for spatial horizontal prediction + // for 2x2 block, there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_hordown_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborH, neighborD[0], neighborD1, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_hordown_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUH, neighborUD[0], neighborUD1, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_hordown_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVH, neighborVD[0], neighborVD1, xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_VERTICAL_LEFT: + // we need neighbor A, C, G, E, B, F for spatial vertical-left prediction + // for 2x2 block there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_verleft_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborB, neighborF[0], xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_verleft_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUB, neighborUF[0], xblk/2, xblk/2, blkthresh); + pre_signV = spatial_verleft_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVB, neighborVF[0], xblk/2, xblk/2, blkthresh); + break; + + case SPATIAL_HORIZANTAL_UP: + // we need neighbor A, C, G, E, B, F for spatial vertical-left prediction + // for 2x2 block there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_horup_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborB[0], neighborF, xblk, xblk, blkthresh); + blkthresh = xblk/2; // this is for format 4:2:0 + pre_signU = spatial_horup_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUB[0], neighborUF, xblk/2, xblk/2, blkthresh); + pre_signV = spatial_horup_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVB[0], neighborVF, xblk/2, xblk/2, blkthresh); + break; + } // switch (spatial_mode) + + if ( pre_sign ) + { + diffY = diffU = diffV = 0; + + + // for IBLOCK in OBMC framework + get_neighbor_predict_values( fmv, cx, cy, xblk, yblk, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, + frameMEinfo, varblkarray, xblk/2); + + for (y=0; yY[(cy+y)*hor+(cx+x)] = alpha* ( fr2->Y[(cy+y)*hor+(cx+x)] + - predict_blkY[y*xblk+x]*self_weight_matrix[y*xblk+x] ) + + neighbor_predictY[y*xblk+x]; + diffY += (float)fabs(H1->Y[(cy+y)*hor+(cx+x)]); + assert( pre_signU && pre_signV ); + if ( x%2==0 && y%2==0 ) + { // Note: we use sub-sampled version of self_weight_matrix, i.e. [y*xblk+x] + H1->U[(cy+y)/2*chor+(cx+x)/2] = alpha * ( fr2->U[(cy+y)/2*chor+(cx+x)/2] + -predict_blkU[y/2*xblk/2+x/2]*self_weight_matrixUV[y/2*xblk/2+x/2] ) + +neighbor_predictU[y/2*xblk/2+x/2] ; + diffU += (float)fabs(H1->U[(cy+y)/2*chor+(cx+x)/2]); + H1->V[(cy+y)/2*chor+(cx+x)/2] = alpha * ( fr2->V[(cy+y)/2*chor+(cx+x)/2] + -predict_blkV[y/2*xblk/2+x/2]*self_weight_matrixUV[y/2*xblk/2+x/2] ) + +neighbor_predictV[y/2*xblk/2+x/2] ; + diffV += (float)fabs(H1->V[(cy+y)/2*chor+(cx+x)/2]); + } + } + +#ifdef DEGUB_DIRECTIONAL_IBLOCK_OBMC + FILE *fiblk = fopen("iblock_info_encoder.txt", "at"); + fprintf(fiblk, "x=%03d\t y=%03d\t blk=%02d\t %.2f\t %.2f\t %.2f\n", cx, cy, xblk, diffY, diffU, diffV); + fclose(fiblk); +#endif + + + }else + assert(0); // in this function pre_sign must be valid + +} + + +void diretional_iblock_spatial_interpolation_with_OBMC(vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int t_level, int remaining_frs, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) +{ + int x, y, n_index; + float fadditional_penalty=0; + + // initialize all the neighbors to be HUGE_VAL + neighborH = neighborUH = neighborVH = (float)HUGE_VAL; + for ( n_index=0; n_indexY, + cx, cy, xblk, yblk, hor, ver, t_level, fr2->U, fr2->V); + + Spatial_prediction_analysis_with_OBMC( fmv, cx, cy, xblk, yblk, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, + frameMEinfo, varblkarray); + } + else if (xblk==4) + { + GetSpaitialNeighborPixels4x4(info, &fadditional_penalty, fmv_root, fr2->Y, + cx, cy, xblk, yblk, hor, ver, t_level, fr2->U, fr2->V); + Spatial_prediction_analysis_with_OBMC( fmv, cx, cy, xblk, yblk, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, + frameMEinfo, varblkarray); + } + else + { + assert(0); + printf("Error in diretional_iblock_spatial_interpolation()!\n"); + } +} + + +// this function is always working in full resolution ( original video resolution ) +// fmv2 is the root of the non-NULL motion vector quad-tree (fmv) 递归调用,划分成最小的块 +void rec_directional_iblock_analysis_with_OBMC(vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr L1, YUVimage_ptr H1, YUVimage_ptr H0, + YUVimage_ptr fr1, YUVimage_ptr fr2, YUVimage_ptr fr3, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref1, vector_ptr mv_ref2, vector_ptr mv_ref3, + int t_level, int remaining_frs, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) +{ + int xblock, yblock; + + if( fmv->child ) { + rec_directional_iblock_analysis_with_OBMC( fmv->child0, cx, cy, xblk/2, yblk/2, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, fmv_root, + frameMEinfo, varblkarray); + rec_directional_iblock_analysis_with_OBMC( fmv->child1, cx + xblk / 2, cy, xblk/2, yblk/2, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, fmv_root, + frameMEinfo, varblkarray); + rec_directional_iblock_analysis_with_OBMC( fmv->child2, cx , cy+ yblk / 2, xblk/2, yblk/2, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, fmv_root, + frameMEinfo, varblkarray); + rec_directional_iblock_analysis_with_OBMC( fmv->child3, cx + xblk / 2, cy+ yblk / 2, xblk/2, yblk/2, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, info, fmv_root, + frameMEinfo, varblkarray); + } else { // 最小的块 + /* consider the small block around the boundaries */ + xblock = ( cx + xblk <= hor ) ? xblk : hor - cx; + yblock = ( cy + yblk <= ver ) ? yblk : ver - cy; + + if( xblock <= 0 || yblock <= 0 ) return; + + if (fmv->bi_mode != DIRECTIONAL_IBLOCK) return; + + // double check the validity of this directional IBLOCK + assert(fmv->lifting_mode == SPATIAL_PREDICTED ); + assert(xblock==yblock && (xblock==8 || xblock==4)); + + // do the iblock spatial interpolation for this block 为这个块进行空间插值 + diretional_iblock_spatial_interpolation_with_OBMC( fmv, cx, cy, xblock, yblock, hor, ver, + L1, H1, H0, fr1, fr2, fr3, fmv1, fmv2, fmv3, + mv_ref1, mv_ref2, mv_ref3, t_level, remaining_frs, + info, fmv_root, frameMEinfo, varblkarray); + } +} + + +void Spatial_prediction_synthesis_with_OBMC( vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int level, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) +{ + enum spatialMODE spatial_mode; + int x, y, blkthresh; + char pre_sign, pre_signU, pre_signV; + float diffY, diffU, diffV; + int chor, cver, s_level, uvx, uvy, uvblk, spatial_scale; + int blksize, uvblksize; + + uvx = cx/2; + uvy = cy/2; + uvblk = xblk/2; + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + spatial_scale =1<>s_level; + uvblksize = blksize/2; + if (uvblksize==0) // for the subsampling effect in spatial scalability + { + if ( uvx%spatial_scale==0 && uvy%spatial_scale==0 ) + uvblksize = 1; + } + // the starting position, block size and dimension size at specific resolution + cx >>= s_level; + cy >>= s_level; + hor >>= s_level; + ver >>= s_level; + chor = hor/2; cver = ver/2; + + spatial_mode = fmv->iblock_spatial_mode; // encoder side + blkthresh = blksize; + assert( spatial_mode>=0 && spatial_mode<=8 && blksize<=8 ); + switch (spatial_mode) + { + case SPATIAL_VERTICAL: // interpolate/predict vertically + // we only need neighbor A and neighbor E for spatial vertical prediction + pre_sign = spatial_ver_pre(predict_blkY, neighborA, neighborE, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_ver_pre(predict_blkU, neighborUA, neighborUE, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_ver_pre(predict_blkV, neighborVA, neighborVE, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_HORIZONTAL: // interpolate/predict horizontally + // we only need neighbor G and neighbor C for spatial horizontal prediction + pre_sign = spatial_hor_pre(predict_blkY, neighborG, neighborC, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_hor_pre(predict_blkU, neighborUG, neighborUC, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_hor_pre(predict_blkV, neighborVG, neighborVC, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_DC: + // we need neighbor A, C, G and E for spatial DC prediction + pre_sign = spatial_dc_pre(predict_blkY, neighborA, neighborC, neighborE, neighborG, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_dc_pre(predict_blkU, neighborUA, neighborUC, neighborUE, neighborUG, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_dc_pre(predict_blkV, neighborVA, neighborVC, neighborVE, neighborVG, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_DOWN_LEFT: + // we need neighbor A, G, B, F, C, E for spatial down-left prediction + // the block is divided into 3 parts + // each part has 4 cases, so totally there are 12 cases for their existence + pre_sign = spatial_downleft_pre(predict_blkY, neighborA, neighborG, + neighborB, neighborF, neighborC, neighborE, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_downleft_pre(predict_blkU, neighborUA, neighborUG, + neighborUB, neighborUF, neighborUC, neighborUE, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_downleft_pre(predict_blkV, neighborVA, neighborVG, + neighborVB, neighborVF, neighborVC, neighborVE, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_DOWN_RIGHT: + // we need neighbor A, C, G, E, and H, D for spatial down-right prediction + // the block is divided into 3 parts + // each part has 4 cases, so totally there are 12 cases for their existence + pre_sign = spatial_downright_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborH, neighborD, neighborD1, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_downright_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUH, neighborUD, neighborUD1, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_downright_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVH, neighborVD, neighborVD1, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_VERTICAL_RIGHT: + // we need neighbor A, C, G, E, and H, D for spatial vertical-right prediction + // for 2x2 block, there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_verright_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborH, neighborD, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_verright_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUH, neighborUD, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_verright_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVH, neighborVD, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_HORIZONTAL_DOWN: + // we need neighbor A, C, G, E, and H, D for spatial horizontal prediction + // for 2x2 block, there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_hordown_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborH, neighborD[0], neighborD1, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_hordown_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUH, neighborUD[0], neighborUD1, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_hordown_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVH, neighborVD[0], neighborVD1, uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_VERTICAL_LEFT: + // we need neighbor A, C, G, E, B, F for spatial vertical-left prediction + // for 2x2 block there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_verleft_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborB, neighborF[0], blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_verleft_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUB, neighborUF[0], uvblksize, uvblksize, blkthresh); + pre_signV = spatial_verleft_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVB, neighborVF[0], uvblksize, uvblksize, blkthresh); + break; + + case SPATIAL_HORIZANTAL_UP: + // we need neighbor A, C, G, E, B, F for spatial vertical-left prediction + // for 2x2 block there are only 2 parts: 8 cases + // for 4x4 and 8x8 blocks, there are 5 parts: 20 cases + pre_sign = spatial_horup_pre(predict_blkY, neighborA, neighborC, neighborG, neighborE, + neighborB[0], neighborF, blksize, blksize, blkthresh); + blkthresh = uvblksize; // this is for format 4:2:0 + pre_signU = spatial_horup_pre(predict_blkU, neighborUA, neighborUC, neighborUG, neighborUE, + neighborUB[0], neighborUF, uvblksize, uvblksize, blkthresh); + pre_signV = spatial_horup_pre(predict_blkV, neighborVA, neighborVC, neighborVG, neighborVE, + neighborVB[0], neighborVF, uvblksize, uvblksize, blkthresh); + break; + } // switch (spatial_mode) + + if ( pre_sign ) + { + diffY = diffU = diffV = 0; + + + // for IBLOCK in OBMC framework + get_neighbor_predict_values( fmv, cx, cy, blksize, blksize, hor, ver, + &L1, &H1, &H0, &frp, fr0, fr1, fmv0, fmv1, fmv2, + mv_ref0, mv_ref1, mv_ref2, level, 0, info, + frameMEinfo, varblkarray, uvblksize); + + for (y=0; yY[(cy+y)*hor+(cx+x)] = 1/alpha* ( H0.Y[(cy+y)*hor+(cx+x)]- neighbor_predictY[y*blksize+x] ) + +predict_blkY[y*blksize+x]*self_weight_matrix[y*blksize+x] ; + diffY += (float)fabs(H0.Y[(cy+y)*hor+(cx+x)]); + if ( x%2==0 && y%2==0 && pre_signU && pre_signV && uvblksize ) + { + fr0->U[(cy+y)/2*chor+(cx+x)/2] = 1/alpha * ( H0.U[(cy+y)/2*chor+(cx+x)/2]-neighbor_predictU[y/2*uvblksize+x/2]) + +predict_blkU[y/2*uvblksize+x/2]* self_weight_matrixUV[y/2*uvblksize+x/2]; + diffU += (float)fabs(H0.U[(cy+y)/2*chor+(cx+x)/2]); + fr0->V[(cy+y)/2*chor+(cx+x)/2] = 1/alpha * ( H0.V[(cy+y)/2*chor+(cx+x)/2]-neighbor_predictV[y/2*uvblksize+x/2]) + +predict_blkV[y/2*uvblksize+x/2]* self_weight_matrixUV[y/2*uvblksize+x/2]; + diffV += (float)fabs(H1.V[(cy+y)/2*chor+(cx+x)/2]); + } + } + +// printf("x=%03d\t y=%03d\t blk=%02d\t %.2f\t %.2f\t %.2f\n", cx, cy, xblk, diffY, diffU, diffV); + }else + assert(0); // in this function pre_sign must be valid + +} + + +void diretional_iblock_spatial_synthesis_with_OBMC( vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int level, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) +{ + int x, y, n_index; + float fadditional_penalty=0; + + // initialize all the neighbors to be HUGE_VAL + neighborH = neighborUH = neighborVH = (float)HUGE_VAL; + for ( n_index=0; n_indexY, + cx, cy, xblk, yblk, hor, ver, level, fr0->U, fr0->V); + Spatial_prediction_synthesis_with_OBMC( fmv, cx, cy, xblk, yblk, + hor, ver, fr0, fr1, H0, L1, H1, frp, fmv0, fmv1, fmv2, + mv_ref0, mv_ref1, mv_ref2, level, info, fmv_root, + frameMEinfo, varblkarray); + + } + else if (xblk==4) + { + GetSpaitialNeighborPixels4x4(info, &fadditional_penalty, fmv_root, fr0->Y, + cx, cy, xblk, yblk, hor, ver, level, fr0->U, fr0->V); + Spatial_prediction_synthesis_with_OBMC( fmv, cx, cy, xblk, yblk, + hor, ver, fr0, fr1, H0, L1, H1, frp, fmv0, fmv1, fmv2, + mv_ref0, mv_ref1, mv_ref2, level, info, fmv_root, + frameMEinfo, varblkarray); + } + else + { + assert(0); + printf("Error in diretional_iblock_spatial_interpolation()!\n"); + } +} + + +void rec_directional_iblock_synthesis_with_OBMC( vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, + YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int level, videoinfo info, + vector_ptr fmv_root, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) +{ + int xblock, yblock; + + if( fmv->child ) { + rec_directional_iblock_synthesis_with_OBMC( fmv->child0, cx, cy , xblk/2, yblk/2, hor, ver, + fr0, fr1, H0, L1, H1, frp, + fmv0, fmv1, fmv2, mv_ref0, mv_ref1, mv_ref2, + level, info, fmv_root, + frameMEinfo, varblkarray); + rec_directional_iblock_synthesis_with_OBMC( fmv->child1, cx+xblk/2, cy , xblk/2, yblk/2, hor, ver, + fr0, fr1, H0, L1, H1, frp, + fmv0, fmv1, fmv2, mv_ref0, mv_ref1, mv_ref2, + level, info, fmv_root, + frameMEinfo, varblkarray); + rec_directional_iblock_synthesis_with_OBMC( fmv->child2, cx , cy+yblk/2, xblk/2, yblk/2, hor, ver, + fr0, fr1, H0, L1, H1, frp, + fmv0, fmv1, fmv2, mv_ref0, mv_ref1, mv_ref2, + level, info, fmv_root, + frameMEinfo, varblkarray); + rec_directional_iblock_synthesis_with_OBMC( fmv->child3, cx+xblk/2 , cy+yblk/2, xblk/2, yblk/2, hor, ver, + fr0, fr1, H0, L1, H1, frp, + fmv0, fmv1, fmv2, mv_ref0, mv_ref1, mv_ref2, + level, info, fmv_root, + frameMEinfo, varblkarray); + } else { + /* consider the small block around the boundaries */ + xblock = ( cx + xblk <= hor ) ? xblk : hor - cx; + yblock = ( cy + yblk <= ver ) ? yblk : ver - cy; + + if( xblock <= 0 || yblock <= 0 ) return; + + if (fmv->bi_mode != DIRECTIONAL_IBLOCK) return; + + // double check the validity of this directional IBLOCK + assert(fmv->lifting_mode == SPATIAL_PREDICTED ); + assert(xblock==yblock && (xblock==8 || xblock==4)); + + // do the iblock spatial synthesis for this block + diretional_iblock_spatial_synthesis_with_OBMC( fmv, cx, cy, xblk, yblk, + hor, ver, fr0, fr1, H0, L1, H1, frp, fmv0, fmv1, fmv2, + mv_ref0, mv_ref1, mv_ref2, level, info, fmv_root, + frameMEinfo, varblkarray); + } + + +} + diff --git a/Interframe EZBC/TempSub/src/display.c b/Interframe EZBC/TempSub/src/display.c new file mode 100644 index 0000000..48b641e --- /dev/null +++ b/Interframe EZBC/TempSub/src/display.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#define EXTERN extern +#include "rasterfile.h" +#include "basic.h" +#include "structN.h" +#include "coderN.h" +#include "bmeN.h" +#include "memoryN.h" +#include "miscN.h" +#include "dpx.h" +#include "unix_pc.h" +#include "ioN.h" +#include "analsyn.h" +#include "util_filtering.h" +#include + +#define OUTPUT_RAS + +void copyframe( YUVimage * source, YUVimage * dest, videoinfo info ); +void snr_frame( float *ysnr, float *usnr, float *vsnr, YUVimage_ptr codeframe, + YUVimage_ptr inframe, videoinfo info ); +void write_frame( YUVimage frame, videoinfo info, char *inname, int index, + enum FORMAT format ); +void yuv2RGB( unsigned char *RGBframe, int yhor, int yver, float *Yframe, + int chor, int cver, float *Uframe, float *Vframe ); +struct rasterfile *exchange_rasheader( struct rasterfile *rhead ); +struct rasterfile make_header( int hor, int ver, int depth ); +void write_ras( char *filename, struct rasterfile header, + unsigned char *frame ); + + +void +writefloatimg4( char *name, struct rasterfile *rhead, float *data ) +{ + FILE *fp; + int i, nn; + U32 *p; + struct rasterfile temphead; + + rhead->ras_depth = 32; + rhead->ras_length = rhead->ras_height * rhead->ras_width * sizeof( float ); + rhead->ras_maptype = RMT_NONE; + rhead->ras_maplength = 0; + + if( !name ) { + fp = stdout; + } else if( ( fp = fopen( name, "wb" ) ) == NULL ) { + ( void )fprintf( stderr, "write_floatimg4: can't open %s for write\n", + name ); + exit( -1 ); + } + nn = rhead->ras_width * rhead->ras_height; + + + /* write the file header */ + temphead = *rhead; + p = ( U32 * ) & temphead; + for( i = 0; i < 8; i++ ) { + p[i] = exchange_4byte_order( p[i] ); + } + if( fwrite( p, sizeof( U32 ), 8, fp ) != 8 ) { + printf( "write_ras: can't write header to %s\n", name ); + exit( 1 ); + } + + p = ( U32 * ) data; + for( i = 0; i < nn; i++ ) { + p[i] = exchange_4byte_order( p[i] ); + } + + if( fwrite( p, sizeof( U32 ), nn, fp ) != ( unsigned )nn ) { + printf( "write_ras: can't write header to %s\n", name ); + exit( 1 ); + } + + ( void )fclose( fp ); + return; +} + + +void +block2pixel( float *mvx, float *mvy, vector_ptr fmv, int cx, int cy, int xblk, + int yblk, int hor, int ver ) +{ + int i, j, xblock, yblock, pos; + + /* change the structure of motion vectors */ + /* from the block-based to the pixel-based */ + /* write the motion vector of the block recursively */ + + if( fmv->child ) { + block2pixel( mvx, mvy, fmv->child0, cx, cy, xblk / 2, yblk / 2, hor, + ver ); + block2pixel( mvx, mvy, fmv->child1, cx + xblk / 2, cy, xblk / 2, yblk / 2, + hor, ver ); + block2pixel( mvx, mvy, fmv->child2, cx, cy + yblk / 2, xblk / 2, yblk / 2, + hor, ver ); + block2pixel( mvx, mvy, fmv->child3, cx + xblk / 2, cy + yblk / 2, + xblk / 2, yblk / 2, hor, ver ); + } else { + /* consider the small block around the boundaries */ + xblock = ( cx + xblk <= hor ) ? xblk : hor - cx; + yblock = ( cy + yblk <= ver ) ? yblk : ver - cy; + + if( xblock <= 0 || yblock <= 0 ) { + /* printf("xblock<=0 || yblock<=0 in block2pixel2() !\n");*/ + return; + } + + for( i = cy; i < cy + yblock; i++ ) { + for( j = cx; j < cx + xblock; j++ ) { + pos = i * hor + j; + mvx[pos] = fmv->mvx; + mvy[pos] = fmv->mvy; + } + } + } +} + + + +void write_highband(YUVimage frame, int GOPIndex, int level, int index, + videoinfo info) +{ + int ysize, pos; + float weight, *data; + char name[512]; + unsigned char *char_data = NULL; + struct rasterfile rhead; + + ysize = info.ywidth * info.yheight; + + temporal_filter(); + weight = (float) pow( HPW1[1], (float) level); + + data = + (float *) getarray ( ysize, sizeof(float), "data_write_highband" ); + char_data = + (unsigned char *) getarray ( ysize, sizeof(unsigned char), "char_data" ); + + for( pos = 0; pos < ysize; pos++ ) { + data[pos] = frame.Y[pos] / weight; + } + + rhead = make_header(info.ywidth, info.yheight, GRAYDATA); + cnv_data_4_1(data, char_data, ysize); + + sprintf( name, "%s_statistics/GOP%02d_%s%01d_fr%03d.ras", + info.bitname, GOPIndex, "H", level, index ); + write_ras(name, rhead, char_data); + + free(char_data); + free(data); +} + + +void +write_lowband( YUVimage frame, int GOPIndex, int level, int index, + videoinfo info ) +{ + int ysize, csize, pos; + float weight; + char name[512]; + YUVimage temp; + + ysize = info.ywidth * info.yheight; + csize = info.cwidth * info.cheight; + + temporal_filter(); + weight = (float) pow( LPW4[1], (float) level); + + frame_alloc( &temp, info ); + + for( pos = 0; pos < ysize; pos++ ) { + temp.Y[pos] = frame.Y[pos] / weight; + } + + for( pos = 0; pos < csize; pos++ ) { + temp.U[pos] = frame.U[pos] / weight; + temp.V[pos] = frame.V[pos] / weight; + } + +#ifdef OUTPUT_RAS + sprintf( name, "%s_statistics/GOP%02d_%s%01d_fr%03d.ras", + info.bitname, GOPIndex, "L", level, index ); + write_frame(temp, info, name, index, RAS); +#else + sprintf( name, "%s_statistics/GOP%02d_%s%01d_fr%03d.yuv", + info.bitname, GOPIndex, "L", level, index ); + write_frame(temp, info, name, index, YUV); +#endif + + free_frame( temp ); +} + diff --git a/Interframe EZBC/TempSub/src/dpxio.c b/Interframe EZBC/TempSub/src/dpxio.c new file mode 100644 index 0000000..550bb46 --- /dev/null +++ b/Interframe EZBC/TempSub/src/dpxio.c @@ -0,0 +1,609 @@ +#include "basic.h" +#include +#include +#include +#include +#include +#include "rasterfile.h" +#include "structN.h" +#include "dpx.h" +#include "unix_pc.h" +#include "chrom.h" +#include "memoryN.h" + +#define Detector 0xffc00000 +float clipping2( float ipix ); + +void dpx2ras( char *dpxname, char *outname ); +U16 colorLUT[1024]; + + +U16 +Release( U32 * data, U8 bitdepth ) +{ + U32 temp; + U16 outdata; + + outdata = 0; + + temp = ( *data ) & Detector; + outdata = temp >> ( 32 - bitdepth ); + ( *data ) = ( *data ) << bitdepth; + + return outdata; +} + + +void +Pack( U32 * data, int comp, U8 bitdepth ) +{ + ( *data ) <<= bitdepth; + comp = comp & 0x3ff; + ( *data ) = ( *data ) | comp; +} + + + +U16 * +read_dpx( char *dpxname, struct dpx **dpxheader, int *nr, int *nc ) +{ + int nn; + int i, j, pos; + FILE *fp = NULL; + U32 *data = NULL, rgbU32, offset; + U16 *RGBframe; + U8 bitdepth; + + if( ( fp = fopen( dpxname, "rb" ) ) == NULL ) { + fprintf( stderr, "Can't open %s for read\n", dpxname ); + exit( 1 ); + } + + *dpxheader = + ( struct dpx * )getarray( 1, sizeof( struct dpx ), "*dpxheader" ); + + if( fread( *dpxheader, sizeof( struct dpx ), 1, fp ) != 1 ) { + printf( "read dpx file header error \n" ); + exit( 1 ); + } + + *nc = exchange_4byte_order( ( *dpxheader )->imageinfo.pixels_per_line ); + *nr = exchange_4byte_order( ( *dpxheader )->imageinfo.lines_per_image_ele ); + + offset = exchange_4byte_order( ( *dpxheader )->fileinfo.offset ); + printf( "offset = %d\n", offset ); + //total = exchange_4byte_order((*dpxheader)->fileinfo.file_size); printf("total file size= %d\n", total); +/* + if( (nr!=1080) || (nc!=1920) ){ + printf("the height of image %d and the width of image are error\n", nr, nc); + exit(0); + } +*/ + //*nr = 540; *nc = 960; + nn = ( *nr ) * ( *nc ); + //printf("row %d col %d pixels %d\n", *nr, *nc, nn); + + + fseek( fp, offset, SEEK_SET ); + + + data = ( U32 * ) getarray( nn, sizeof( U32 ), "data" ); + if( fread( data, sizeof( U32 ), nn, fp ) != ( unsigned )nn ) { + printf( "read image data error\n" ); + exit( 1 ); + } + fclose( fp ); + + for( i = 0; i < nn; i++ ) { + data[i] = exchange_4byte_order( data[i] ); + } + + /* seperate 4 byte data into R, G, B */ + bitdepth = ( *dpxheader )->imageinfo.bit_size; + RGBframe = ( U16 * ) getarray( nn * 3, sizeof( U16 ), "RGBframe" ); + + for( i = 0; i < ( *nr ); i++ ) { + for( j = 0; j < ( *nc ); j++ ) { + pos = i * ( *nc ) + j; + + rgbU32 = data[pos]; + + RGBframe[i * 3 * ( *nc ) + 3 * j + 2] = Release( &rgbU32, bitdepth ); + + RGBframe[i * 3 * ( *nc ) + 3 * j + 1] = Release( &rgbU32, bitdepth ); + + RGBframe[i * 3 * ( *nc ) + 3 * j] = Release( &rgbU32, bitdepth ); + } + } + free( data ); + return RGBframe; +} + + + + +struct dpx * +make_dpxheader( videoinfo info ) +{ + struct dpx *dpxheader; + + dpxheader = read_dpx_header( "dpxheader" ); + + dpxheader->imageinfo.pixels_per_line = exchange_4byte_order( info.ywidth ); + dpxheader->imageinfo.lines_per_image_ele = + exchange_4byte_order( info.yheight ); + //dpxheader->imageinfo.bit_size = 10; + return ( dpxheader ); +} + +#ifdef DPX_SUPPORT +void +write_dpx( char *dpxname, float *LRGB, videoinfo info ) +{ + int i, j, pos; + int temp; + U8 bitdepth; + int hor, ver, nn; + FILE *fp = NULL; + U32 *data = NULL; + struct dpx *dpxheader; + //*RGBframe, + + + ver = info.yheight; + hor = info.ywidth; + nn = ver * hor; + + dpxheader = make_dpxheader( info ); + + data = ( U32 * ) getarray( nn, sizeof( U32 ), "data" ); + + if( !( fp = fopen( dpxname, "wb" ) ) ) { + printf( "write_frame: %s\n", dpxname ); + exit( 1 ); + } +// RGBframe = Nonlinearize(LRGB, ver, hor, info); + + for( i = 0; i < ver; i++ ) { + for( j = 0; j < hor; j++ ) { + pos = i * hor + j; + + bitdepth = dpxheader->imageinfo.bit_size; // no need to exchange order. it is U8 data + data[pos] = 0; + + temp = nint( LRGB[pos * 3 + 2] ); // R + if( temp > info.max ) + temp = info.max; + if( temp < info.min ) + temp = info.min; + Pack( &data[pos], temp, bitdepth ); + + temp = nint( LRGB[pos * 3 + 1] ); // G + if( temp > info.max ) + temp = info.max; + if( temp < info.min ) + temp = info.min; + Pack( &data[pos], temp, bitdepth ); + + temp = nint( LRGB[pos * 3] ); // B + if( temp > info.max ) + temp = info.max; + if( temp < info.min ) + temp = info.min; + Pack( &data[pos], temp, bitdepth ); + + data[pos] <<= 2; + + data[pos] = exchange_4byte_order( data[pos] ); + } + } + + + + if( fwrite( dpxheader, sizeof( struct dpx ), 1, fp ) != 1 ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + + if( fwrite( data, sizeof( U32 ), nn, fp ) != ( unsigned )nn ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + + fclose( fp ); + free( data ); //free(RGBframe); + free( dpxheader ); +} +#endif + + +void +dpx2ras( char *dpxname, char *outname, enum CODING_DOMAIN coding_domain ) +{ + int nr, nc, pos, downnr, downnc, downpos, t; + int i, j, k, r; + U8 *temp; + U16 *RGBframe; + U16 Bmin, Bmax, Gmin, Gmax, Rmin, Rmax; + struct dpx *dpxheader; + struct rasterfile rhead; + + RGBframe = read_dpx( dpxname, &dpxheader, &nr, &nc ); + + + //printf("%d %d\n", nr, nc); + + + dpxrange( RGBframe, nr, nc, &Bmin, &Bmax, &Gmin, &Gmax, &Rmin, &Rmax ); + printf( "image min(R %d G %d B %d), image max(R %d G %d B %d) \n", Rmin, + Gmin, Bmin, Rmax, Gmax, Bmax ); + + + r = 1; + downnr = nr / r; + downnc = nc / r; + temp = ( U8 * ) getarray( downnr * downnc * 3, sizeof( U8 ), "temp" ); + for( i = 0; i < downnr; i++ ) { + for( j = 0; j < downnc; j++ ) { + pos = ( i * r ) * ( nc * 3 ) + ( j * r ) * 3; /* 3 comes from R, G, B */ + downpos = i * ( downnc * 3 ) + j * 3; + for( k = 0; k < 3; k++ ) { + + if( coding_domain != LOG ) + t = colorLUT[RGBframe[pos + k]]; + else + t = ( RGBframe[pos + k] + 2 ) >> 2; + + if( t > 255 ) + temp[downpos + k] = 255; + else if( t < 0 ) + temp[downpos + k] = 0; + else + temp[downpos + k] = ( U8 ) t; + } + } + } + + rhead = make_header( downnc, downnr, RGBDATA ); + write_ras( outname, rhead, temp ); + + free( temp ); + free( dpxheader ); + free( RGBframe ); + return; +} + +#ifdef DPX_SUPPORT +void +dpx2dpx( char *dpxname, char *outname ) +{ + int nr, nc, pos, pos2; + int i, j; + U16 *RGBframe; + float Ydata, Udata, Vdata; + struct dpx *dpxheader; + YUVimage YUV; + float *LRGB; //*RGBframe, + + videoinfo info; + + RGBframe = read_dpx( dpxname, &dpxheader, &nr, &nc ); + + + info.ywidth = nc; + info.yheight = nr; + info.cwidth = nc; + info.cheight = nr; + + frame_alloc( &YUV, info ); + + for( i = 0; i < nr; i++ ) { + for( j = 0; j < nc; j++ ) { + pos = i * ( nc * 3 ) + j * 3; /* 3 comes from R, G, B */ + pos2 = i * nc + j; + RGB2YUV( ( float )RGBframe[pos + 2], ( float )RGBframe[pos + 1], + ( float )RGBframe[pos], &( YUV.Y[pos2] ), &( YUV.V[pos2] ), + &( YUV.U[pos2] ) ); + YUV.U[pos2] += 512.; + YUV.V[pos2] += 512.; + } + } + + + info.coding_domain = LOG; + info.max = 1023; + info.min = 0; + + + + LRGB = + ( float * )getarray( info.ywidth * info.yheight * 3, sizeof( float ), + "LRGB" ); + + for( i = 0; i < info.yheight; i++ ) { + for( j = 0; j < info.ywidth; j++ ) { + pos = i * info.ywidth + j; + Ydata = YUV.Y[pos]; + Udata = YUV.U[pos]; + Vdata = YUV.V[pos]; + /* YUV -> RGB */ + Udata -= 1024 / 2.; + Vdata -= 1024 / 2.; + YUV2RGB( Ydata, Udata, Vdata, &( LRGB[pos * 3 + 2] ), + &( LRGB[pos * 3 + 1] ), &( LRGB[pos * 3] ) ); + } + } + + + + write_dpx( outname, LRGB, info ); + + + + free_frame( YUV ); + free( LRGB ); + free( dpxheader ); + free( RGBframe ); + return; +} +#endif + +void +dpxrange( U16 * RGBframe, int row, int col, U16 * Bmin, U16 * Bmax, + U16 * Gmin, U16 * Gmax, U16 * Rmin, U16 * Rmax ) +{ + int i; + + *Bmax = 0; + *Bmin = 1024; + + *Gmax = 0; + *Gmin = 1024; + + *Rmax = 0; + *Rmin = 1024; + + for( i = 0; i < row * col; i++ ) { + + if( RGBframe[i * 3] < ( *Bmin ) ) { + *Bmin = RGBframe[i * 3]; + } + if( RGBframe[i * 3] > ( *Bmax ) ) { + *Bmax = RGBframe[i * 3]; + } + + if( RGBframe[i * 3 + 1] < ( *Gmin ) ) { + *Gmin = RGBframe[i * 3 + 1]; + } + if( RGBframe[i * 3 + 1] > ( *Gmax ) ) { + *Gmax = RGBframe[i * 3 + 1]; + } + if( RGBframe[i * 3 + 2] < ( *Rmin ) ) { + *Rmin = RGBframe[i * 3 + 2]; + } + if( RGBframe[i * 3 + 2] > ( *Rmax ) ) { + *Rmax = RGBframe[i * 3 + 2]; + } + } +// printf("min = %d, max = %d (dpxio.c)\n", *min, *max); +} + +/* + * convert 10 bits LOG data to "coding_domain" + * #define Gamma 2.2 + * #define Refblack 95 + * #define Refwhite 685 + * #define KODAK + */ +float +convertLOG( int peak, float data, enum CODING_DOMAIN coding_domain ) +{ + float newdata; + //int i; + double linear; //, shift, gain + +#ifdef KODAK + k = 0.002 / 0.6; + + if( data <= Refblack ) + newdata = 0; + else if( data >= Refwhite ) + newdata = peak; + else { + + range = pow( 10, Refwhite * k ) - pow( 10, Refblack * k ); + + /* direct from The Cineon Digital Film System + shift = data-Refwhite; + shift *= k; + shift = pow(10, shift); + gain = 1/(1-pow(10, (Refblack-Refwhite)*k)); + + linear = shift*gain-(gain-1); + */ + linear = ( pow( 10, data * k ) - pow( 10, Refblack * k ) ) / range; // equivalent to the upper one, but easy to understand + + if( coding_domain == LINEAR ) + newdata = peak * linear; + else if( coding_domain == VIDEO ) + newdata = peak * pow( linear, 1. / Gamma ); + else { + printf( "coding_domain error (dpxio.c)\n" ); + exit( 1 ); + } + + } + + return newdata; + +#else //cintel + double black, white; + + black = pow( 2., Refblack / 102.4 ) / 1024; + white = pow( 2., Refwhite / 102.4 ) / 1024; + + linear = ( pow( 2., data / 102.4 ) / 1024 - black ) / ( white - black ); + if( linear > 1 ) + linear = 1.; + if( linear < 0 ) + linear = 0; + + if( coding_domain == LINEAR ) + newdata = ( float )( peak * linear ); + else if( coding_domain == VIDEO ) + newdata = ( float )( peak * pow( linear, 1. / Gamma ) ); + else { + printf( "coding_domain error (dpxio.c)\n" ); + exit( 1 ); + } + + return newdata; + +#endif + + +} + +void +compute_colorLUT( int bits, enum CODING_DOMAIN coding_domain ) +{ + int i; + int peak; + + peak = ( 1 << bits ) - 1; //printf("peak = %d \n", peak); + + if( coding_domain == LOG ) + return; + + for( i = 0; i < 1024; i++ ) { + colorLUT[i] = nint( convertLOG( peak, ( float )i, coding_domain ) ); + //printf("i %d, LUT %d\n", i, colorLUT[i]); getchar(); + } +} + +/*float *linearize(U16 *RGBframe, int row, int col, videoinfo info) +{ + int i; + U16 Bmin, Bmax, Gmin, Gmax, Rmin, Rmax; + float *LRGB; + + LRGB = (float *)getarray(row*col*3, sizeof(float), "LRGB"); + + if( (info.log == YES) && (info.linear ==YES) ){ + dpxrange(RGBframe, row, col, &Bmin, &Bmax, &Gmin, &Gmax, &Rmin, &Rmax); + if( (Rmin < info.min) || (Rmax > info.max) ||(Gmin < info.min) || (Gmax > info.max) + ||(Bmin < info.min) || (Bmax > info.max)){ + printf("image min(R%d G%d B%d) != info.min(%d), image max(R%d G%d B%d) != info.max(%d)\n", Rmin, Gmin, Bmin, info.min, Rmax, Gmin, Bmin, info.max); + exit(1); + } + } + else{ + for(i=0; i 0){ + shift = log10(tmp+1); + } + else{ + shift = 0; + } + RGBframe[i] = (float)(shift/k + info.min); + } + } + else{ + for(i=0; i +#include +#include +#include +#include +#define EXTERN +#include "structN.h" +#include "basic.h" +#include "coderN.h" +#include "init_encN.h" +#include "memoryN.h" +#include "analsyn.h" +#include "ioN.h" +#include "pstatN.h" +#include "miscN.h" +#include "ezbc_enc_3d.h" +#include "mv_statistics.h" +#include "hvsbm_fullres.h" +#include "bmeN.h" + +#include "layer_mv.h" + +#define EXTERN extern +#define LAMBDA_ADAPT_RATIO_THRES 0.6 +#define INIT_RANGE 7 +#define LAMBDA_LOWER_LMT 3 + +#define THEO_LENGTH 48 +#define THEO_COUNT 6 +#define ADAPT_LEVEL 5 +//#define THEO_MODEL + +//#define LAMBDA_CTRL + +//Added on 02.05.2018 +EXTERN int SIMUL_START; +EXTERN int SIMUL_POINT; +EXTERN int SIMUL_LIMIT; +EXTERN int SIMUL_LEVEL; +EXTERN int SIMUL_RANGE; + +EXTERN int SIMUL_ROUND; + +unsigned long int *gop_mv; + +float global_motion_active; + +void read_command( int argc, char **argv, videoinfo * info ); + +int bit_alloc_CBR( videoinfo info, unsigned char *qp, + long int overhead, unsigned long *gop_sum_mv, int curr_last ); + + +typedef struct lambda_rate{ + int bitrate; + float lambda; + float bst_psnr; + char bitfile[256]; + char dec_video[256]; + long int total_bytes_past; + long int total_bytes_past_buffer; +}; + +typedef struct lambda_buff{ + float buff_lambda[ADAPT_LEVEL]; + lambda_buff *next; +}; + +void linear_fitting(int maxn, float *a0, float *a1, double *x, double *y){ + +// double x[maxn] = {-0.693,-0.511,-0.357,-0.223,-0.105}; +// double y[maxn] = {2.565, 2.485, 2.302, 2.197, 2.197}; + double xi = 0, x2 = 0, yi = 0, xy = 0; + + for(int i = 0; i < maxn; i++){ + xi += x[i], x2 += x[i] * x[i], yi += y[i], xy += x[i] * y[i]; + } + *a0 = (yi * x2 - xy * xi) / (x2 * maxn - xi * xi); + *a1 = (yi * xi - xy * maxn) / (xi * xi - x2 * maxn); + printf("P(x) = %f%+fx\n", *a0, *a1); + +} + +void file_copy(char *dest_name, char *source_name){ + + FILE * file1,*file2; + + file1 = fopen(source_name,"rb"); + file2 = fopen(dest_name,"wb"); + if(!file1) + { + printf("File open failed!",source_name); + return; + } + char c; + long int index = 0; + fseek(file1,0,SEEK_END); + long int length = ftell(file1); + //printf("%d\n",length); + if(!length) + return; + while(!fseek(file1,index,SEEK_SET)) + { + fread(&c,1,1,file1); + fwrite(&c,1,1,file2); + if(index == length - 1) + { + break; + } + index++; + } + fclose(file1); + fclose(file2); +} + +int compare_lambda_vector(lambda_buff *buff, float *lambda_vector){ + int i,j; + int getnum = 0; + int judge; + lambda_buff *root, *create; + + assert(buff != NULL); + root = buff; + + printf("\nCompare lambda vector:\n"); + + while(root != NULL){ + judge = YES; + + for(i = 0; i < ADAPT_LEVEL; i ++) + printf("%f\t",root->buff_lambda[i]); + printf("\n"); + + for(i = 0; i < ADAPT_LEVEL; i ++){ + if(root->buff_lambda[i] != lambda_vector[i]){ + judge = NO; + break; + } + } + if(judge == YES)//find a match in the queue! + return 1; + + root = root->next; + } + + assert(root == NULL);//if we arrive at this point, a new vector has been detected. + + root = buff; + while(root->next != NULL){ + root = root->next; + } + + assert(root->next == NULL); + + create = new lambda_buff; + for(i = 0; i < ADAPT_LEVEL; i ++) + create->buff_lambda[i] = lambda_vector[i]; + create->next = NULL; + root->next = create; + + return 0; +} + +void destroy_lambda_buff(lambda_buff *buff){ + lambda_buff *create; + + if(buff != NULL){ + do{ + create = buff; + buff = create->next; + delete(create); + }while(buff->next != NULL); + + delete(buff); + } +} + + +/* + * main() + */ +int +main( int argc, char **argv ) +{ + int curr, curr_disp, last, i, j, remaining_frs, header_bytes; + long int num_of_GOP, *output_GOP_bytes, *dec_output_GOP_bytes; + int GOP_counter, VBR_GOP_counter; + long mark, elp; // initial and elapsed time + double duration; + enum FLAG first_GOP; + enum FLAG Level_change; + FILE *fpio, *fplmbd; + char mvstatname[512]; + char post_stream[256], seq_name[256], raw_buffer[256], enc_buff[256], dec_buff[256]; //Added on 01.14.2018 + + char rd_name[256], rd_buff[256], mvst_buff[256]; + + int estimated_overhead = 0, FAT_bytes, GOPheader_bytes = 2; + long int sum_mv; + +//for simul dec, added on 01.04.2018 + long int total_bytes_past = 0, total_bytes_past_buffer, vbr_total_bytes_past; + long int *read_GOP_bytes; +//for simul dec + + + float best_lambda[ADAPT_LEVEL]; + float curr_lambda[ADAPT_LEVEL]; + + float buff_best_lambda[ADAPT_LEVEL]; + + int simul_count = 0; + int round = 0; + int simul_enc = NO; + + int simul_alert = NO, in_simul = NO; + int segment_init = YES; + + float simul_psnr; + + float best_simul_psnr[3]; + float theo_simul_psnr[THEO_COUNT]; + double theo_simul_psnr1[THEO_COUNT][INIT_RANGE], theo_simul_psnr2[THEO_COUNT][INIT_RANGE], theo_simul_psnr3[THEO_COUNT][INIT_RANGE+2]; + int getnum; + + enum FLAG VBR_first_GOP, VBR_Level_change; + int VBR_remaining_frs, vbr_curr, vbr_remaining_frs; + + int BOTTOM_BITRATE; + double theo_a[3], theo_b[3], theo_log_a[3], theo_log_b[3];//Added on 05.20.2019, lambda = a * R^b + int maxn = 5; + +//Added on 04.07.2019 + lambda_rate lr_record[6]; + + lambda_buff *lmda_buff; + lmda_buff = NULL; + + for(i = 0; i < THEO_COUNT; i ++){ + lr_record[i].total_bytes_past = 0; + lr_record[i].total_bytes_past_buffer = 0; + } + +//Added on 03.26.2018 + int uphor, upver, scale; + float *upframe1, *upframe2, *upsamp_x; + + int BUFF_SIMUL_POINT, BUFF_SIMUL_START; + + int cx, cy, cpos; + float block_diff, block_ratio; //Added on 06.29.2018 + float buff_gop_block, last_gop_diff; + simul_skip = NO; + skip_frame = NO; + + int gop_end = NO; + + for(i = 0;i < 3;i ++) + best_simul_psnr[i] = 0; + + float buffer_active = 0; + int SIMUL_ADD; + + printf("Built on %s at %s.\n", __DATE__, __TIME__); + + videoinfo info; + // videoinfo info2; // only used in info.denoise_flag == YES this case + + mark = clock( ); + read_command( argc, argv, &info ); // 读命令行 + + SIMUL_START = 4 * info.GOPsz; + SIMUL_POINT = info.GOPsz; + SIMUL_LIMIT = INIT_RANGE; + SIMUL_LEVEL = 0; + SIMUL_ROUND = 2; + SIMUL_RANGE = SIMUL_LIMIT / 2; + + printf("Simulative bitrate = %d\n",info.simul_rate); + + /* open MV statistics file */ + strcpy(mvstatname, info.bitname); + strcat(mvstatname, "_mvstatistics.log"); + mvStat_open(mvstatname); + + buff_frameMEinfo = (ImageMEinfo *)getarray( info.yheight * info.ywidth, sizeof( ImageMEinfo ), "buff_frameMEinfo" ); + + for( cy = 0; cy < info.yheight; cy++ ){ + for( cx = 0; cx < info.ywidth; cx++ ){ + cpos = cy * info.ywidth + cx; + buff_frameMEinfo[cpos].left_mvx = 0; + buff_frameMEinfo[cpos].left_mvy = 0; + buff_frameMEinfo[cpos].right_mvx = 0; + buff_frameMEinfo[cpos].right_mvy = 0; + } + } + +//bit file buffer + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); + seq_name[strlen( info.bitname ) - 4] = '\0'; + sprintf( enc_buff, "%s_%d.bit", seq_name, 2 ); + +//subband sample file buffer + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); // Hanke, 16.09.02 + seq_name[strlen( info.bitname ) - 4] = '\0'; // + sprintf( rd_name, "%s.rd_sample_dat", seq_name ); + sprintf( rd_buff, "%s_buff.rd_sample_dat", seq_name ); + +//mvby file buffer + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); + seq_name[strlen( info.bitname ) - 4] = '\0'; + sprintf( mvst_buff, "%s_buff.mvby", seq_name ); //info.mvstatname is the file! + + if( info.denoise_flag == YES ) { + info.ywidth /= 2; + info.yheight /= 2; + info.cwidth /= 2; + info.cheight /= 2; + } + + init_enc( &info ); // in init_encN.c + + initialize_spiral_search(get_searchrange(1 << (info.tPyrLev-1), info)); + + write_header( info.bitname, info ); + header_bytes = sizeof( videoheader ); + + num_of_GOP = get_GOP_num( info ); + + total_bytes_past += sizeof( videoheader ); + total_bytes_past += num_of_GOP * sizeof( long int ); + + for(i = 0; i < THEO_COUNT; i ++){ + lr_record[i].total_bytes_past += sizeof( videoheader ); + lr_record[i].total_bytes_past += num_of_GOP * sizeof( long int ); + } + + read_GOP_bytes = + ( long int * )getarray( num_of_GOP, sizeof( long int ), + "read_GOP_bytes" ); + + //Added on 11.12.2017 + gop_mv = ( unsigned long * )getarray( num_of_GOP, sizeof( unsigned long ), "gop_mv" ); + + output_GOP_bytes = + ( long int * )getarray( num_of_GOP, sizeof( long int ), + "output_GOP_bytes" ); + for( i = 0; i < num_of_GOP; i++ ) + output_GOP_bytes[i] = 0; + + dec_output_GOP_bytes = + ( long int * )getarray( num_of_GOP, sizeof( long int ), + "dec_output_GOP_bytes" ); + for( i = 0; i < num_of_GOP; i++ ) + dec_output_GOP_bytes[i] = 0; + + + if( !( fpio = fopen( info.bitname, "a+b" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + +// printf("Enc num_of_GOP = %d\n",num_of_GOP); + + // leave some space for keeping the GOP byte size + fwrite( output_GOP_bytes, sizeof( long int ), num_of_GOP, fpio ); + fclose( fpio ); + header_bytes += num_of_GOP * sizeof( long int ); +/* + orig_lambda[0] = info.lambda[0]; + orig_lambda[1] = info.lambda[1]; + orig_lambda[2] = info.lambda[2]; + + best_lambda[0] = orig_lambda[0]; + best_lambda[1] = orig_lambda[1]; + best_lambda[2] = orig_lambda[2]; + + curr_lambda[0] = orig_lambda[0]; + curr_lambda[1] = orig_lambda[1]; + curr_lambda[2] = orig_lambda[2]; + + buff_best_lambda[0] = orig_lambda[0]; + buff_best_lambda[1] = orig_lambda[1]; + buff_best_lambda[2] = orig_lambda[2]; +*/ + for(i = 0; i < ADAPT_LEVEL; i ++){ + orig_lambda[i] = info.lambda[i]; + best_lambda[i] = orig_lambda[i]; + curr_lambda[i] = orig_lambda[i]; + buff_best_lambda[i] = orig_lambda[i]; + } + + first_GOP = YES; + curr = info.start; + last = info.last; + GOP_counter = 0; + +//Added on 03.26.2018 + scale = 1 << info.subpel[0]; + assert(info.subpel[0] > 0 && info.subpel[0] == info.subpel[1]); + scale = scale << ADD_SUB; + uphor = ( info.ywidth - 1 ) * scale + 1; + upver = ( info.yheight - 1 ) * scale + 1; + + upsamp_x = ( float * )getarray( uphor * info.yheight, sizeof( float ), "upsamp_x" ); + upframe1 = ( float * )getarray( uphor * upver, sizeof( float ), "upframe1" ); + upframe2 = ( float * )getarray( uphor * upver, sizeof( float ), "upframe2" ); + +#ifdef VBR_DEC + vbr_total_bytes_past = total_bytes_past; + printf("\nVBR_DEC, copy file to buffer!\n"); + file_copy(enc_buff, info.bitname); + file_copy(rd_buff, rd_name); + file_copy(mvst_buff, info.mvstatname); + save_enc_status( &info ); + + info.lambda_adapt_thres = 100000; + SIMUL_POINT = 0; +#endif + + while( curr <= last ) { // 逐GOP + +// fscanf(fplmbd,"%f %f %f\n",&info.lambda[0],&info.lambda[1],&info.lambda[2]); + + remaining_frs = last - curr + 1; // 剩余帧 + // 下面检测剩余帧是否还够一个gop 正常情况下,eff_GOPsz等于bigGOP,但是在最后不够一个GOP时,等于剩余帧 + if ( remaining_frs < info.bigGOP ){ + Level_change = YES; // last bigGOP detected + info.eff_GOPsz = remaining_frs; // effective GOP size + curr_disp = curr + info.GOPsz - 1; + if (curr_disp > last) curr_disp = last; + }else{ + Level_change = NO; // full GOP + info.eff_GOPsz = info.bigGOP; + curr_disp = curr + info.GOPsz - 1; + } + + gop_block = 0; frame_cnt = 0; + +#ifdef INTRA_SUPPORT + switch ( info.intra ) { + + case YES: + + if( info.denoise_flag == YES ) { + printf( "can not handle this case\n" ); + exit( 1 ); + } + +#ifdef THREE_D + output_GOP_bytes[GOP_counter] = three_D_anal( curr, GOP_counter, info ); +#else + output_GOP_bytes[GOP_counter] = intra_encode( curr, GOP_counter, info ); +#endif + + break; + + case NO: +#endif + +//Added new +#ifdef TEST_LAMBDA + if( (info.GOPsz * GOP_counter) == SIMUL_START && simul_count < SIMUL_LIMIT ){ //simul cycle + + GOP_counter = GOP_counter - ( (SIMUL_START - SIMUL_POINT)/info.GOPsz ); + curr = info.start + SIMUL_POINT; + if( curr == info.start )first_GOP = YES; + curr_disp = curr + info.GOPsz - 1; + remaining_frs = last - curr + 1; + +reselect_sign: ; + if( simul_count < (SIMUL_LIMIT-1) ){ //Simul enc + + for(i = 2;i >= 0;i --){ + if(i != SIMUL_LEVEL){ + if(i <= 1){ + info.lambda[i] = best_lambda[i]; + assert(best_lambda[i] > 0); + }else{ + assert(i == 2); + for(j = ADAPT_LEVEL-1;j >= i;j --){ + info.lambda[j] = best_lambda[j]; + assert(best_lambda[j] > 0); + } + } + } + } + + if( simul_count == 0 ){ + if(round == 0) + SIMUL_ADD = 1; + else + SIMUL_ADD = 1; + + info.lambda[SIMUL_LEVEL] = curr_lambda[SIMUL_LEVEL] - SIMUL_RANGE * SIMUL_ADD; + if(SIMUL_LEVEL == 2){ + for(j = ADAPT_LEVEL-1;j > SIMUL_LEVEL;j --){ + info.lambda[j] = curr_lambda[j] - SIMUL_RANGE * SIMUL_ADD; + } + } + + if(info.lambda[SIMUL_LEVEL] < LAMBDA_LOWER_LMT){ + info.lambda[SIMUL_LEVEL] = LAMBDA_LOWER_LMT; + if(SIMUL_LEVEL == 2){ + for(j = ADAPT_LEVEL-1;j > SIMUL_LEVEL;j --){ + info.lambda[j] = LAMBDA_LOWER_LMT; + } + } + } + if(SIMUL_LEVEL >= 1 && info.lambda[SIMUL_LEVEL] < info.lambda[SIMUL_LEVEL-1]){ +#ifdef LAMBDA_CTRL + info.lambda[SIMUL_LEVEL] = info.lambda[SIMUL_LEVEL-1]; +#endif + } + + }else{ + info.lambda[SIMUL_LEVEL] = curr_lambda[SIMUL_LEVEL] + SIMUL_ADD; + if(SIMUL_LEVEL == 2){ + for(j = ADAPT_LEVEL-1;j > SIMUL_LEVEL;j --){ + info.lambda[j] = curr_lambda[j] + SIMUL_ADD; + } + } + + if( info.lambda[SIMUL_LEVEL] == buff_best_lambda[SIMUL_LEVEL] ){ + info.lambda[SIMUL_LEVEL] = info.lambda[SIMUL_LEVEL] + SIMUL_ADD; + if(SIMUL_LEVEL == 2){ + for(j = ADAPT_LEVEL-1;j > SIMUL_LEVEL;j --){ + info.lambda[j] = info.lambda[j] + SIMUL_ADD; + } + } + } + + for( i = SIMUL_LEVEL+1; i <= 2; i ++ ){ +#ifdef LAMBDA_CTRL + if(info.lambda[i] < info.lambda[i-1]) + info.lambda[i] = info.lambda[i-1]; +#endif + } + } + + printf("\nlambda revised! lambda0 = %f, lambda1 = %f, lambda2 = %f, lambda3 = %f\n", info.lambda[0], info.lambda[1], info.lambda[2], info.lambda[3]); + + for(i = ADAPT_LEVEL-1;i >= 0;i --) + curr_lambda[i] = info.lambda[i]; + +//Added on 05.04.2019 + if(lmda_buff != NULL){ + getnum = compare_lambda_vector(lmda_buff,info.lambda); + if( getnum == 0 ){ + printf("\nLambda vector not tried, try it.\n"); + }else{ + assert(getnum == 1); + printf("\nLambda vector already tried, skip it.\n"); + simul_count ++; + goto reselect_sign; + } + }else{ + assert(lmda_buff == NULL); + segment_init = NO; + printf("\nLambda vector not tried, try it.\n"); + lmda_buff = new lambda_buff; + lmda_buff->next = NULL; + for(i = 0;i < ADAPT_LEVEL;i ++) + lmda_buff->buff_lambda[i] = info.lambda[i]; + } +//Added on 05.04.2019 + }else{ //Encode with the best choice, when simul_count == (SIMUL_LIMIT-1) + assert(simul_count == (SIMUL_LIMIT-1)); + for(i = 0; i <= 2; i ++){ + info.lambda[i] = best_lambda[i]; + assert(best_lambda[i] > 0); + if(i == 2){ + for(j = ADAPT_LEVEL-1;j > i;j --){ + info.lambda[j] = best_lambda[j]; + } + } + } + printf("\nfinal best lambda0 = %f, lambda1 = %f, lambda2 = %f, lambda3 = %f\n", info.lambda[0], info.lambda[1], info.lambda[2], info.lambda[3]); + } + + simul_count ++; + + if(simul_count == SIMUL_LIMIT && SIMUL_START < (info.last - 0 * info.GOPsz) ){ + if(SIMUL_LEVEL == 2){ + if( (round == SIMUL_ROUND) || + ( (buff_best_lambda[0] == best_lambda[0]) && + (buff_best_lambda[1] == best_lambda[1]) && + (buff_best_lambda[2] == best_lambda[2]) ) ){//Has done three rounds + + printf("Overall end of current GOP simulation reached!\n"); + destroy_lambda_buff(lmda_buff); + lmda_buff = NULL; + + if( (buff_best_lambda[0] == best_lambda[0]) && + (buff_best_lambda[1] == best_lambda[1]) && + (buff_best_lambda[2] == best_lambda[2]) ) + printf("Obtained same lambda group.\n"); + + round = 0; + simul_count = 0; + + SIMUL_START = BUFF_SIMUL_START; + SIMUL_POINT = BUFF_SIMUL_POINT; + in_simul = NO;//move forward to search for the next segment with similar feature; + + SIMUL_LEVEL = 0; + + gop_end = YES; + }else{ + printf("Current round end reached!\n"); +#ifdef THEO_MODEL + if(round == 0){ + printf("SIMUL LEVEL 1:\n"); + for(i = 0; i < THEO_COUNT; i ++){ + for(j = 0; j < INIT_RANGE; j ++){ + printf("theo point = %d, lambda point = %d, YPSNR = %f\n",i,j,theo_simul_psnr1[i][j]); + } + printf("\n\n"); + } + printf("SIMUL LEVEL 2:\n"); + for(i = 0; i < THEO_COUNT; i ++){ + for(j = 0; j < INIT_RANGE; j ++){ + printf("theo point = %d, lambda point = %d, YPSNR = %f\n",i,j,theo_simul_psnr2[i][j]); + } + printf("\n\n"); + } + printf("SIMUL LEVEL 3:\n"); + for(i = 0; i < THEO_COUNT; i ++){ + for(j = 0; j < INIT_RANGE+2; j ++){ + printf("theo point = %d, lambda point = %d, YPSNR = %f\n",i,j,theo_simul_psnr3[i][j]); + } + printf("\n\n"); + } + } +#endif + round ++; + simul_count = 0; + SIMUL_LEVEL = 0; +// best_simul_psnr = 0; + for(i = 0;i < ADAPT_LEVEL;i ++){ + curr_lambda[i] = best_lambda[i]; + buff_best_lambda[i] = best_lambda[i]; + } + } + + SIMUL_LIMIT = INIT_RANGE; + SIMUL_RANGE = SIMUL_LIMIT / 2; + + }else{//Do it for higher/lower temporal level + assert(SIMUL_LEVEL == 0 || SIMUL_LEVEL == 1); + for(i = 0;i < ADAPT_LEVEL;i ++) + curr_lambda[i] = best_lambda[i]; + + SIMUL_LEVEL ++; + printf("SIMUL_LEVEL changed! SIMUL_LEVEL = %d\n",SIMUL_LEVEL); + simul_count = 0; + + if(SIMUL_LEVEL == 1) + SIMUL_LIMIT += 0; + else{ + assert(SIMUL_LEVEL == 2); + SIMUL_LIMIT += 2; + } + + SIMUL_RANGE = SIMUL_LIMIT / 2; + } + } + + if ( remaining_frs < info.bigGOP ){ + Level_change = YES; // last bigGOP detected + info.eff_GOPsz = remaining_frs; // effective GOP size + curr_disp = curr + info.GOPsz - 1; + if (curr_disp > last) curr_disp = last; + }else{ + Level_change = NO; // full GOP + info.eff_GOPsz = info.bigGOP; + curr_disp = curr + info.GOPsz - 1; + } + +//copy related files back from buffer + file_copy(info.bitname, enc_buff); + file_copy(rd_name, rd_buff); + file_copy(info.mvstatname, mvst_buff); + + printf( "******************************************************\n"); + printf( "* frame %.3d ~ frame %.3d (%.3d) (remaining_frs: %.3d) *\n", + curr, curr_disp, curr + info.eff_GOPsz-1, remaining_frs ); + printf( "******************************************************\n"); + + resume_enc_status( &info ); + + simul_skip = YES; + + output_GOP_bytes[GOP_counter] = + mctf_anal_ezbc( curr, GOP_counter, info, first_GOP, + Level_change, remaining_frs, &sum_mv, YES, upframe1, upframe2, upsamp_x); + + simul_skip = NO; + + if( gop_end == YES ){ + for(i = 0;i < ADAPT_LEVEL;i ++){ + orig_lambda[i] = best_lambda[i]; + } + + for(i = 0;i <= 2;i ++) + best_simul_psnr[i] = 0; + + for(i = 0;i < ADAPT_LEVEL;i ++){ + curr_lambda[i] = orig_lambda[i]; + best_lambda[i] = orig_lambda[i]; + buff_best_lambda[i] = orig_lambda[i]; + } + + gop_end = NO; + } + + simul_alert = YES; + + total_bytes_past = total_bytes_past_buffer; + for(i = 0; i < THEO_COUNT; i ++){ + lr_record[i].total_bytes_past = lr_record[i].total_bytes_past_buffer; + } + }else{ //if non-simul +#endif +//Added new + printf( "******************************************************\n"); + printf( "* frame %.3d ~ frame %.3d (%.3d) (remaining_frs: %.3d) *\n", + curr, curr_disp, curr + info.eff_GOPsz-1, remaining_frs ); // 当前gop要编码的帧的范围:curr起始,curr_disp结束 + printf( "******************************************************\n"); + +#ifdef TEST_LAMBDA + if( (info.GOPsz * GOP_counter) == info.start + SIMUL_POINT){ +//copy related files into buffer +#ifndef VBR_DEC + printf("\ncopy file to buffer!\n"); + file_copy(enc_buff, info.bitname); + file_copy(rd_buff, rd_name); + file_copy(mvst_buff, info.mvstatname); + save_enc_status( &info ); +#else + printf("\nVBR_DEC, file is ready in the buffer!\n"); +#endif + + total_bytes_past_buffer = total_bytes_past; + for(i = 0; i < THEO_COUNT; i ++){ + lr_record[i].total_bytes_past_buffer = lr_record[i].total_bytes_past; + } + + printf("\nlambda revised! lambda0 = %f, lambda1 = %f, lambda2 = %f, lambda3 = %f\n", info.lambda[0], info.lambda[1], info.lambda[2], info.lambda[3]); + } + gop_block = 0; frame_cnt = 0; + printf("simul_alert = %d\n",simul_alert); + +// if(curr == (SIMUL_START - info.GOPsz) ) +// simul_skip = YES; +#endif + if( info.denoise_flag == YES ) { + + output_GOP_bytes[GOP_counter] = + denoise_mctf_anal_ezbc( curr, GOP_counter, info, first_GOP, + Level_change, remaining_frs ); + } else { + output_GOP_bytes[GOP_counter] = + // 起始帧,第几个gop,视频信息,是否为第一个gop,是不是不足一个gop,剩余帧,mv和,NO, + mctf_anal_ezbc( curr, GOP_counter, info, first_GOP, + Level_change, remaining_frs, &sum_mv, NO, upframe1, upframe2, upsamp_x); // 真正编码GOP的入口 + } +#ifdef TEST_LAMBDA + gop_block = gop_block / frame_cnt; + printf("Current avg frame block number: %f\n",gop_block); + + if(first_GOP == YES){ + buff_gop_block = gop_block; +/* SIMUL_POINT = info.GOPsz; + SIMUL_START = 4 * info.GOPsz; +*/ + in_simul = NO; + printf("Initial state! New buff_gop_block = %f\n",gop_block); + printf("buff_gop_block = %f\n", buff_gop_block); + }else{ + assert(first_GOP == NO); + if( curr == (info.start + SIMUL_POINT) && in_simul == NO ){ + buff_gop_block = gop_block; + printf("New buff_gop_block start! Buff_gop_block = %f\n",buff_gop_block); + } + + if( curr == (info.start + SIMUL_START - 3 * info.GOPsz) && in_simul == NO ){ +#ifndef VBR_DEC + buff_gop_block = gop_block; + printf("Updated buff_gop_block for new segment = %f\n", buff_gop_block); +#endif + } + + if( curr == (info.start + SIMUL_START - 2 * info.GOPsz) && in_simul == NO ){ + if( fabs(gop_block - buff_gop_block) > info.lambda_adapt_thres || curr >= (info.last + 1 - 3 * info.GOPsz) ){ + printf("gop_block = %f, buff_gop_block = %f\n", gop_block, buff_gop_block); + buff_gop_block = gop_block; + BUFF_SIMUL_POINT = curr; + BUFF_SIMUL_START = curr + 3 * info.GOPsz; + in_simul = YES; + printf("Feature change detected! SIMUL_START = %d\n",SIMUL_START); + printf("Updated buff_gop_block = %f\n", buff_gop_block); + }else{ + SIMUL_START += info.GOPsz; + in_simul = NO; + printf("Feature continued! SIMUL_POINT = %d, increased SIMUL_START = %d\n",SIMUL_POINT, SIMUL_START); + printf("gop_block = %f, buff_gop_block = %f\n", gop_block, buff_gop_block); + } + }//when curr == (SIMUL_START - info.GOPsz) + }//not first GOP + + }//if non-simul +#endif +#ifdef INTRA_SUPPORT + break; + + default: + + printf( "error (encoderN.c)\n" ); + exit( 1 ); + + } +#endif + gop_mv[GOP_counter] = sum_mv; + +#ifdef TEST_LAMBDA + +////////////////////////////////////////////////// +#ifdef THEO_MODEL + BOTTOM_BITRATE = info.simul_rate - 200; + + if( curr < (info.last - info.GOPsz) && round == 0 ){ + info.bitrate = BOTTOM_BITRATE; + for(i = 0; i < THEO_COUNT; i ++){ + + FAT_bytes = num_of_GOP * sizeof( long int ); + GOPheader_bytes = 2 * num_of_GOP; + + sprintf( post_stream, "%s_%d.bit", seq_name, info.bitrate ); + estimated_overhead = sizeof( videoheader ) + GOPheader_bytes + FAT_bytes; + +#ifdef VBR_DEC + test( info, &info.qp, estimated_overhead, gop_mv, curr + info.GOPsz - 1, 1 ); +//simul decoding +//info.bitname + strcpy(raw_buffer,info.bitname); + strcpy(info.bitname,post_stream); +///////////////////////////////////////// + + if( curr == (info.start + SIMUL_START - info.GOPsz) ){ + lr_record[i].total_bytes_past = vbr_total_bytes_past; + VBR_GOP_counter = 0; + VBR_first_GOP = YES; + vbr_curr = info.start; + VBR_Level_change = NO; + + while( VBR_GOP_counter <= GOP_counter ){ + vbr_remaining_frs = info.last - vbr_curr + 1; + + if( !( fpio = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, sizeof( videoheader ) + VBR_GOP_counter * sizeof( long int ), SEEK_SET ); + + fread( &dec_output_GOP_bytes[VBR_GOP_counter], sizeof( long int ), 1, fpio ); + + printf("dec_output_GOP_bytes[VBR_GOP_counter] = %d\n",dec_output_GOP_bytes[VBR_GOP_counter]); + printf("Current total_bytes_past = %d\n",lr_record[i].total_bytes_past); + + fclose( fpio ); + + info.GOPbytes = dec_output_GOP_bytes[VBR_GOP_counter]; + + if( simul_alert == YES ){ + mctf_syn_ezbc( vbr_curr, VBR_GOP_counter, &lr_record[i].total_bytes_past, info, + VBR_first_GOP, Level_change, vbr_remaining_frs, YES, NO ); + + simul_alert = NO; + }else{ + mctf_syn_ezbc( vbr_curr, VBR_GOP_counter, &lr_record[i].total_bytes_past, info, + VBR_first_GOP, Level_change, vbr_remaining_frs, NO, NO ); + } + + lr_record[i].total_bytes_past += info.GOPbytes; + VBR_GOP_counter ++; + VBR_first_GOP = NO; + vbr_curr += info.GOPsz; + }//end while + }//end if curr + + if( curr == (info.start + SIMUL_START - info.GOPsz) ){ + printf("\nCalculate PSNR info! Obtained by lambda0 = %f, lambda1 = %f, lambda2 = %f\n", curr_lambda[0],curr_lambda[1],curr_lambda[2]); + + if(curr - info.GOPsz < info.start) + assert(0); + else{ + if(SIMUL_LEVEL == 0){ + theo_simul_psnr1[i][simul_count] = calsnr(SIMUL_POINT, curr-1, info);//frame 12-24 + printf("Theo simul_count = %d, THEO_COUNT = %d, YPSNR = %f\n\n",simul_count, i, theo_simul_psnr1[i][simul_count]); + }else if(SIMUL_LEVEL == 1){ + theo_simul_psnr2[i][simul_count] = calsnr(SIMUL_POINT, curr-1, info);//frame 8-22 + printf("Theo simul_count = %d, THEO_COUNT = %d, YPSNR = %f\n\n",simul_count, i, theo_simul_psnr2[i][simul_count]); + }else{ + assert(SIMUL_LEVEL == 2); + theo_simul_psnr3[i][simul_count] = calsnr(SIMUL_POINT, curr-1, info);//frame 4-20 + printf("Theo simul_count = %d, THEO_COUNT = %d, YPSNR = %f\n\n",simul_count, i, theo_simul_psnr3[i][simul_count]); + } + } + } + +//simul decoding ends for certain bitrate + strcpy(info.decname, dec_buff); + info.bitrate += 200; + strcpy(info.bitname, raw_buffer); +#else + test( info, &info.qp, estimated_overhead, gop_mv, curr + info.GOPsz - 1, 0 ); +//simul decoding +//info.bitname + strcpy(raw_buffer,info.bitname); + strcpy(info.bitname,post_stream); + + if( !( fpio = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, sizeof( videoheader ) + GOP_counter * sizeof( long int ), SEEK_SET ); + + fread( &dec_output_GOP_bytes[GOP_counter], sizeof( long int ), 1, fpio ); + + printf("dec_output_GOP_bytes[GOP_counter] = %d\n",dec_output_GOP_bytes[GOP_counter]); + printf("Current theo total_bytes_past = %d\n",lr_record[i].total_bytes_past); + + fclose( fpio ); + +//decoding start + strcpy(dec_buff, info.decname); + sprintf( info.decname, "%s_%d.yuv", seq_name, info.bitrate ); + + info.GOPbytes = dec_output_GOP_bytes[GOP_counter]; + + mctf_syn_ezbc( curr, GOP_counter, &(lr_record[i].total_bytes_past), info, + first_GOP, Level_change, remaining_frs, simul_alert, YES ); + + lr_record[i].total_bytes_past += info.GOPbytes; + + if( curr == (info.start + SIMUL_START - info.GOPsz) ){ + printf("\nCalculate PSNR info! Obtained by lambda0 = %f, lambda1 = %f, lambda2 = %f\n", curr_lambda[0],curr_lambda[1],curr_lambda[2]); + + if(curr - info.GOPsz < info.start) + assert(0); + else{ + if(SIMUL_LEVEL == 0) + theo_simul_psnr[i] = calsnr(SIMUL_POINT, curr, info);//frame 12-24 + else if(SIMUL_LEVEL == 1) + theo_simul_psnr[i] = calsnr(SIMUL_POINT, curr, info);//frame 8-22 + else{ + assert(SIMUL_LEVEL == 2); + theo_simul_psnr[i] = calsnr(SIMUL_POINT, curr, info);//frame 4-20 + } + } + + } +//simul decoding ends for certain bitrate + strcpy(info.decname, dec_buff); + info.bitrate += 100; + strcpy(info.bitname, raw_buffer); +#endif + }//THEO_COUNT +/* + printf("PSNR values for theoretical model:\n"); + getnum = BOTTOM_BITRATE; + for(i = 0; i < THEO_COUNT; i ++){ + printf("Bitrate: %d, PSNR: %f\n", getnum,theo_simul_psnr[i]); + getnum += 100; + } +*/ + }//end if +#endif +////////////////////////////////////////////////// + + info.bitrate = info.simul_rate; + FAT_bytes = num_of_GOP * sizeof( long int ); + GOPheader_bytes = 2 * num_of_GOP; + + sprintf( post_stream, "%s_%d.bit", seq_name, info.bitrate ); + + estimated_overhead = sizeof( videoheader ) + GOPheader_bytes + FAT_bytes; + +#ifdef VBR_DEC + test( info, &info.qp, estimated_overhead, gop_mv, curr + info.GOPsz - 1, 1 ); +#else + test( info, &info.qp, estimated_overhead, gop_mv, curr + info.GOPsz - 1, 0 ); +#endif +//simul decoding +// info.bitname + strcpy(raw_buffer,info.bitname); + strcpy(info.bitname,post_stream); + +#ifdef VBR_DEC + if( curr == (info.start + SIMUL_START - info.GOPsz) ){ + total_bytes_past = vbr_total_bytes_past; + VBR_GOP_counter = 0; + VBR_first_GOP = YES; + vbr_curr = info.start; + VBR_Level_change = NO; + + while( VBR_GOP_counter <= GOP_counter ){ + vbr_remaining_frs = info.last - vbr_curr + 1; + + if( !( fpio = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, sizeof( videoheader ) + VBR_GOP_counter * sizeof( long int ), SEEK_SET ); + + fread( &dec_output_GOP_bytes[VBR_GOP_counter], sizeof( long int ), 1, fpio ); + + printf("dec_output_GOP_bytes[VBR_GOP_counter] = %d\n",dec_output_GOP_bytes[VBR_GOP_counter]); + printf("Current total_bytes_past = %d\n",total_bytes_past); + + fclose( fpio ); + + info.GOPbytes = dec_output_GOP_bytes[VBR_GOP_counter]; + + if( simul_alert == YES ){ + mctf_syn_ezbc( vbr_curr, VBR_GOP_counter, &total_bytes_past, info, + VBR_first_GOP, Level_change, vbr_remaining_frs, YES, NO ); + + simul_alert = NO; + }else{ + mctf_syn_ezbc( vbr_curr, VBR_GOP_counter, &total_bytes_past, info, + VBR_first_GOP, Level_change, vbr_remaining_frs, NO, NO ); + } + + total_bytes_past += info.GOPbytes; + VBR_GOP_counter ++; + VBR_first_GOP = NO; + vbr_curr += info.GOPsz; + }//end while + }//end if +#else + if( !( fpio = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, sizeof( videoheader ) + GOP_counter * sizeof( long int ), SEEK_SET ); + + fread( &dec_output_GOP_bytes[GOP_counter], sizeof( long int ), 1, fpio ); + + printf("dec_output_GOP_bytes[GOP_counter] = %d\n",dec_output_GOP_bytes[GOP_counter]); + printf("Current total_bytes_past = %d\n",total_bytes_past); + + fclose( fpio ); + + info.GOPbytes = dec_output_GOP_bytes[GOP_counter]; + + if( simul_alert == YES ){ + mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs, YES, NO ); + + simul_alert = NO; + }else{ + mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs, NO, NO ); + } + + total_bytes_past += info.GOPbytes; +#endif + strcpy(info.bitname,raw_buffer); + + if( curr == (info.start + SIMUL_START - info.GOPsz) ){ + printf("\nCalculate PSNR info! Obtained by lambda0 = %f, lambda1 = %f, lambda2 = %f, lambda3 = %f\n", curr_lambda[0],curr_lambda[1],curr_lambda[2],curr_lambda[3]); +#ifndef VBR_DEC + if(curr - info.GOPsz < info.start) + assert(0); + else{ + if(SIMUL_LEVEL == 0) + simul_psnr = calsnr(SIMUL_POINT, curr-1, info);//frame 12-24 + else if(SIMUL_LEVEL == 1) + simul_psnr = calsnr(SIMUL_POINT, curr-1, info);//frame 8-22 + else{ + assert(SIMUL_LEVEL == 2); + simul_psnr = calsnr(SIMUL_POINT, curr-1, info);//frame 4-20 + } + } +#else + if(curr - info.GOPsz < info.start) + assert(0); + else{ + if(SIMUL_LEVEL == 0) + simul_psnr = calsnr(SIMUL_POINT, info.act_last, info); + else if(SIMUL_LEVEL == 1) + simul_psnr = calsnr(SIMUL_POINT, info.act_last, info); + else{ + assert(SIMUL_LEVEL == 2); + simul_psnr = calsnr(SIMUL_POINT, info.act_last, info); + } + } +#endif + + if( simul_psnr > (best_simul_psnr[SIMUL_LEVEL]) ){ + best_simul_psnr[SIMUL_LEVEL] = simul_psnr; + for(i = 0;i < ADAPT_LEVEL;i ++) + best_lambda[i] = curr_lambda[i]; + } + printf("\nBest PSNR current level = %f, lambda0 = %f, lambda1 = %f, lambda2 = %f, lambda3 = %f\n",best_simul_psnr[SIMUL_LEVEL], best_lambda[0], best_lambda[1], best_lambda[2], best_lambda[3]); + for(i = 0;i <= 2;i ++) + printf("TEMP level %d, best_simul_psnr = %f\n",i,best_simul_psnr[i]); + } +#endif + + first_GOP = NO; + GOP_counter++; + curr += info.GOPsz; + + } /* while */ + +#ifdef TEST_LAMBDA + + // decode LAST GOP + { + info.eff_GOPsz = remaining_frs; + remaining_frs = 0; // no bitstream extraction of last GOP, only temporal filtering + + printf( " decoding frame %d - %d (last_GOP) .....\n", curr - info.GOPsz + 1, last ); + +// info.bitname + strcpy(raw_buffer,info.bitname); + strcpy(info.bitname,post_stream); + + if( !( fpio = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, sizeof( videoheader ) + GOP_counter * sizeof( long int ), SEEK_SET ); + + fread( &dec_output_GOP_bytes[GOP_counter], sizeof( long int ), 1, fpio ); + + printf("dec_output_GOP_bytes[GOP_counter] = %d\n",dec_output_GOP_bytes[GOP_counter]); + + fclose( fpio ); + + info.GOPbytes = dec_output_GOP_bytes[GOP_counter]; + + mctf_syn_ezbc( curr, GOP_counter, &total_bytes_past, info, + first_GOP, Level_change, remaining_frs, NO, NO ); + +// total_bytes_past += info.GOPbytes; + + strcpy(info.bitname,raw_buffer); + } + +#endif + + /* pstatN.c *//* cfr and pfr are just used as the memory in calsnr, and the data in cfr and pfr is not used in calsnr */ + + if( !( fpio = fopen( info.bitname, "r+b" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + fseek( fpio, sizeof( videoheader ), SEEK_SET ); + fwrite( output_GOP_bytes, sizeof( long int ), num_of_GOP, fpio ); + fclose( fpio ); + +// fclose(fplmbd); + + clean_up_spiral_search(get_searchrange(1 << (info.tPyrLev-1), info)); + + elp = clock( ) - mark; + duration = ( double )elp / CLOCKS_PER_SEC; + print_time( duration ); + + mvStat_close(); + + free(gop_mv); //Added on 11.12.2017 + free(dec_output_GOP_bytes); + free(output_GOP_bytes); + + free(upsamp_x); + free(upframe1); + free(upframe2); + +// enc_destructor( info ); + free(buff_frameMEinfo); + + printf( "finished.\n" ); + return 0; +} + + +/* + * usage() + */ +void +usage( ) +{ + printf( "3DSBCen parameter_file \n" ); +} + +/* + * error_check() + */ +void +error_check( videoinfo info ) +{ + int i; + + if( !strcmp( info.inname, "NULL" ) ) { + printf( "error in read_command(): specify -inname input\n" ); + exit( 1 ); + } + if( !strcmp( info.bitname, "NULL" ) ) { + printf( "error in read_command(): specify -bitname bitfile\n" ); + exit( 1 ); + } + if( !strcmp( info.statname, "NULL" ) ) { + printf( "error in read_command(): specify -statname statusfile\n" ); + exit( 1 ); + } + for (i = 0; i < MAX_TLEVELS; i++) { + if( info.level[i] == -1 ) { + printf( "error in read_command(): specify -MBlevel\n" ); + exit( 1 ); + } + } + if( info.start < 0 || info.start > info.last ) { + printf( "error in read_command(): start %d last %d\n", info.start, + info.last ); + printf( "0<= start, last <1000 and start<=last\n" ); + exit( 1 ); + } + if( info.ywidth < 0 || info.yheight < 0 || info.cwidth < 0 + || info.cheight < 0 ) { + printf( "error in read_command(): image size\n" ); + printf( " Y: %d x %d, C: %d x %d\n", info.ywidth, info.yheight, + info.cwidth, info.cheight ); + exit( 1 ); + } + if( info.start < 0 ) { + printf( "can not handle this case (encoderN.c)\n" ); + exit( 1 ); + } + + if( info.ywidth % 8 ) { + printf( "error: Y width %d should be multiple of 8.(encoderN.c)\n", + info.ywidth ); + exit( 1 ); + } + if( info.yheight % 8 ) { + printf( "error: Y height %d should be multiple of 8.(encoderN.c)\n", + info.yheight ); + exit( 1 ); + } + if( info.cwidth % 8 ) { + printf( "C width %d should be multiple of 8.\n", info.cwidth ); //exit(1); + } + if( info.cheight % 8 ) { + printf( "C height %d should be multiple of 8.\n", info.cheight ); // exit(1); + } + if( info.bitrate < 0 ) { + printf( "error in read_command(): rate %d\n", info.bitrate ); + exit( 1 ); + } +#ifdef INTRA_SUPPORT + if( info.intra == YES && info.denoise_flag == YES ) { + printf + ( "error in read_command(): both info.intra == YES && info.denoise_flag == YES \n" ); + exit( 1 ); + } +#endif + for (i = 0; i < MAX_TLEVELS; i++) { + if (info.xblk[i] < (1 << (info.level[i] - 1)) || + info.yblk[i] < (1 << (info.level[i] - 1))) { + printf("error in read_command(): too many block splitting levels (%d) " + "for macroblock size (%dx%d) in t-level %d\n", + info.level[i], info.xblk[i], info.yblk[i], i); + exit(1); + } + } +} + + /* quad tree structured should be cleaned before starting the next */ + /* so, clean the structure except 1st layer */ + /* fmv->child and fmv->lifting_mode should be initialized to 0 */ + +/* + * read_command() + */ +void +read_command( int argc, char **argv, videoinfo * info ) +{ + int i, j, k, argnum = 1, tpyr, range = 0; + char iline[256], token[80], istring[80], strtmp[256]; + FILE *fppar; + /********** setting the initial or default values ************/ + strcpy( info->inname, "NULL" ); + strcpy( info->bitname, "NULL" ); + strcpy( info->statname, "NULL" ); + strcpy( info->tmpname, "mvbit.tmp" ); + strcpy( info->jp2kname, "NULL" ); + strcpy( info->jp2k_decname, "NULL" ); + + for (i = 0; i < MAX_TLEVELS; i++) {// 最大做MAX_TLEVELS次时域滤波 + info->level[i] = -1; + info->lambda[i] = 24.; + info->subpel[i] = 2; + info->AGP_level[i] = 0; + info->bi_mv[i] = 1; // indicate the existence of RIGHT_CONNECTED mode + info->bi_exist[i] = 1; // indicate the existence of mv on RIGHT side + // bi_mv[]==1 RIGHT_CONNECTED mode exists: + // mv must be bi-directional and bi_exist[] must be 1 + // bi_mv[]==0 RIGHT_CONNECTED mode is prevented: + // mv on RIGHT side can be discarded and bi_exist[] can be 0 or 1. + + info->layer_mv[i] = 0; // no layer structure for motion vector coding in each temporal level + info->layer_exist[i] = 0; + } + info->ME = 3; /* ???? not output to bitstream */ + info->start = -1; + info->last = -1; + info->act_last = -1; + info->ywidth = 352; + info->yheight = 240; + info->cwidth = 176; + info->cheight = 120; + info->framerate = 24; + info->bitrate = 0; + info->verbose = 0; + info->tPyrLev = 3; + info->GOPsz = 0x1 << info->tPyrLev; + info->bigGOP = ( 0x1 << ( info->tPyrLev + 1 ) ) - 1;// gop size * 2 - 1 + info->eff_GOPsz = info->bigGOP; + info->GOPbytes = MAX_STD_INT; + info->t_level = 0; + info->s_level = 0; + info->searchrange = -1; + info->maxsearchrange = info->ywidth; + info->format = YUV; + info->pixeldepth = 8; + info->maxMBnum = -1; + + info->denoise_flag = NO; + + info->SLTF_range = 0; + info->SHTF_range = 0; + + + + /************* read the argument and set the value ********/ + + if( argc == 1 ) { + usage( ); + exit( 1 ); + } + + for( i = 1; i < argc; i++ ) { // 打开配置文件,放在fppar上 + if( *( argv[i] ) == '-' ) { + + switch ( *( ++argv[i] ) ) { + default: + printf( "-%c such an option is not available\n", *( argv[i] ) ); + usage( ); + exit( 1 ); + case 'h': + usage( ); + exit( 1 ); + break; + } + } else { + switch ( argnum ) { + default: + printf( "more parameters are specified\n" ); + usage( ); + exit( 1 ); + case 1: + fppar = fopen( argv[i], "rt" ); + if( fppar == NULL ) { + printf( "can not open file %s\n", argv[i] ); + usage( ); + exit( 1 ); + } + argnum++; + break; + } + } + } + + while( fgets( iline, 254, fppar ) ) { /* read one line */ + sscanf( iline, "%s", token ); + + if( !strcmp( token, "-inname" ) ) { + sscanf( iline, "%s%s", token, info->inname ); + }else if( !strcmp( token, "-jp2kname" ) ) { + sscanf( iline, "%s%s", token, info->jp2kname ); + } else if( !strcmp( token, "-jp2k_decname" ) ) { + sscanf( iline, "%s%s", token, info->jp2k_decname ); + } else if( !strcmp( token, "-decname" ) ) { + sscanf( iline, "%s%s", token, info->decname ); + } else if( !strcmp( token, "-bitname" ) ) { + sscanf( iline, "%s%s", token, info->bitname ); + strncpy( strtmp, info->bitname, strlen( info->bitname ) - 4 ); // Hanke, 16.09.02 + strtmp[strlen( info->bitname ) - 4] = '\0'; // + sprintf( info->mvstatname, "%s%s", strtmp, ".mvby" ); // + sprintf( info->tsubname, "%s%s", strtmp, ".t" ); // + } else if( !strcmp( token, "-statname" ) ) { + sscanf( iline, "%s%s", token, info->statname ); + } else if( !strcmp( token, "-simulrate" ) ) { + sscanf( iline, "%s%d", token, &( info->simul_rate) ); + } else if( !strcmp( token, "-lambdathres" ) ) { + sscanf( iline, "%s%d", token, &( info->lambda_adapt_thres) ); + } else if( !strcmp( token, "-start" ) ) { + sscanf( iline, "%s%d", token, &( info->start ) ); + } else if( !strcmp( token, "-last" ) ) { + sscanf( iline, "%s%d", token, &( info->last ) ); + } else if( !strcmp( token, "-act_last" ) ) { + sscanf( iline, "%s%d", token, &( info->act_last ) ); + }else if( !strcmp( token, "-size" ) ) { + sscanf( iline, "%s%d%d%d%d", token, &( info->ywidth ), + &( info->yheight ), &( info->cwidth ), &( info->cheight ) ); + // save the original resolution for frequency roll-off + info->org_yheight = info->yheight; + info->org_ywidth = info->ywidth; + + } else if( !strcmp( token, "-framerate" ) ) { + sscanf( iline, "%s%d", token, &( info->framerate ) ); + } else if( !strcmp( token, "-searchrange" ) ) { + sscanf( iline, "%s%d", token, &( info->searchrange ) ); + } else if( !strcmp( token, "-maxsearchrange" ) ) { + sscanf( iline, "%s%d", token, &( info->maxsearchrange ) ); + } +#ifdef SUPPORT_INTRA + else if( !strcmp( token, "-intra" ) ) { + sscanf( iline, "%s%s", token, istring ); + if( !strcmp( istring, "YES" ) ) { + info->intra = YES; + } else if( !strcmp( istring, "NO" ) ) { + info->intra = NO; + } else { + printf( "-intra options error\n" ); + exit( 1 ); + } + } +#endif + else if( !strcmp( token, "-denoise" ) ) { + sscanf( iline, "%s%s", token, istring ); + if( !strcmp( istring, "YES" ) ) { + info->denoise_flag = YES; + } else if( !strcmp( istring, "NO" ) ) { + info->denoise_flag = NO; + } else { + printf( "-denoise options error\n" ); + exit( 1 ); + } + } + + else if( !strcmp( token, "-motion" ) ) { + sscanf( iline, "%s%s", token, istring ); + if( (!strcmp(istring, "hvsbm")) || + (!strcmp(istring, "hvsbm_fullres")) ) { + for (i = 0; i < MAX_TLEVELS; i++) { + info->xblk[i] = 64; + info->yblk[i] = 64; + info->level[i] = 5; + } + info->ME = 3; + } else { + printf( "-motion options error (hvsbm)\n" ); + exit( 1 ); + } + } else if( !strcmp( token, "-lambda" ) ) { + sscanf(iline, "%s", token); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%f", &(info->lambda[j])); + // switch the ' ' back and forth to get the number for lambda by Yongjun Wu + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No lambda value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of lambda values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->lambda[k] = info->lambda[k-1]; + } + } else if( !strcmp( token, "-afflambda" ) ) { + sscanf(iline, "%s", token); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%f", &(info->aff_lambda[j])); + // switch the ' ' back and forth to get the number for lambda by Yongjun Wu + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No lambda value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of lambda values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->aff_lambda[k] = info->aff_lambda[k-1]; + } + }else if( !strcmp( token, "-AGP_level" ) ) { // the sign for AGP of motion vector coding + sscanf(iline, "%s", token); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%d", &(info->AGP_level[j])); + // switch the ' ' back and forth to get the number for lambda by Yongjun Wu + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No AGP_level value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of AGP_level values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->AGP_level[k] = info->AGP_level[k-1]; + } + } else if( !strcmp( token, "-bi_mv" ) ) { // the sign for alternative Haar reconstruction in decoder + sscanf(iline, "%s", token); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%d", &(info->bi_mv[j])); + // switch the ' ' back and forth to get the number for lambda by Yongjun Wu + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No bi_mv value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of bi_mv values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->bi_mv[k] = info->bi_mv[k-1]; + } + } else if( !strcmp( token, "-layer_mv" ) ) { // the layerd structure for motion vector coding + sscanf(iline, "%s", token); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%d", &(info->layer_mv[j])); + // switch the ' ' back and forth to get the number for lambda by Yongjun Wu + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No layer_mv value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of layer_mv values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->layer_mv[k] = info->layer_mv[k-1]; + } + }else if( !strcmp( token, "-MVaccuracy" ) ) { + sscanf(iline, "%s", token); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%d", &(info->subpel[j])); + // switch the ' ' back and forth to get the number for MVaccuracy by Yongjun Wu + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No subpel value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of subpel values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->subpel[k] = info->subpel[k-1]; + } + } else if( !strcmp( token, "-SLTF_range" ) ) { + sscanf( iline, "%s%d", token, &range ); + if( range < 0 || range > 10 ) { + printf( "illegal SLTF transition range\n" ); + exit( 1 ); + } else { + info->SLTF_range = range; + } + } else if( !strcmp( token, "-SHTF_range" ) ) { + sscanf( iline, "%s%d", token, &range ); + if( range < 0 || range > 10 ) { + printf( "illegal SHTF transition range\n" ); + exit( 1 ); + } else { + info->SHTF_range = range; + } + } else if( !strcmp( token, "-tPyrLev" ) ) { + sscanf( iline, "%s%d", token, &tpyr ); // &( info->tPyrLev ) ); + info->tPyrLev = (short int) tpyr; + + if( info->tPyrLev < 1 || info->tPyrLev > MAX_TLEVELS ) { + printf( "illegal temporal pyr. layer number(1 - %d)\n", + MAX_TLEVELS); + exit( 1 ); + } else { + // nFrsPyr = (int)pow(2.0, (double)info->tPyrLev); + info->GOPsz = 0x1 << info->tPyrLev; + info->bigGOP = ( 0x1 << ( info->tPyrLev + 1 ) ) - 1; + } + } else if( !strcmp( token, "-MBsize" ) ) { + sscanf( iline, "%s", token ); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++); + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%d", &(info->xblk[j])); + info->yblk[j] = info->xblk[j]; + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No MBsize value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of MBsize values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->xblk[k] = info->xblk[k-1]; + info->yblk[k] = info->xblk[k]; + } + } else if( !strcmp( token, "-MBlevel" ) ) { + sscanf( iline, "%s", token ); + j = 0; + for (k = strlen(token); iline[k] == ' '; k++);// 把空格读掉 + while (j < MAX_TLEVELS && k < (int)strlen(iline) && iline[k] != '#') { + sscanf(&(iline[k]), "%d", &(info->level[j]));// 赋值到level中,有几个赋几个,剩下的用前面的赋值 + for (; iline[k] != ' '; k++); + for (; iline[k] == ' '; k++); + j++; + } + if (j == 0) { + printf("ERROR: No MBlevel value given!\n"); + exit(1); + } else if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of MBlevel values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + info->level[k] = info->level[k-1]; + } + } else if( token[0] == '-' ) { + printf( "%s such a token is not available\n", token ); + usage( ); + exit( 1 ); + } else { + } + } + fclose( fppar ); + + if(info->act_last == -1){ + assert(info->last >= 0); + info->act_last = info->last; + } + + // how many sub-symbols exist + for (k = 0; k < MAX_TLEVELS; k++) { + info->AGP_exist[k] = info->AGP_level[k]; + info->layer_exist[k] = info->layer_mv[k]; + } + + strncpy( strtmp, info->bitname, strlen( info->bitname ) - 4 ); // Hanke, 16.09.02 + strtmp[strlen( info->bitname ) - 4] = '\0'; // + sprintf( info->mvname, "%s.mv", strtmp ); // + + error_check( *info ); +} diff --git a/Interframe EZBC/TempSub/src/golomb.cpp b/Interframe EZBC/TempSub/src/golomb.cpp new file mode 100644 index 0000000..02742d2 --- /dev/null +++ b/Interframe EZBC/TempSub/src/golomb.cpp @@ -0,0 +1,76 @@ +#include "golomb.h" +#include "mv_ec.h" +#include + +int theGrad0; +int theMaxLevels; + +void golomb_init(int grad0, int maxLevels) +{ + theGrad0 = grad0; + theMaxLevels = maxLevels; +} + +int golomb_encode_word(int word, int write) +{ + int level, res, numbits; + int i; + + assert(word >= 0); + // if (word < 0) { + // printf("illegal word in golomb_encode_word (%d)\n", word); + // } + + res = 1 << theGrad0; + level = 1; + numbits = 1 + theGrad0; + + while (word >= res && level < theMaxLevels) { + word -= res; + res <<= 1; + level++; + numbits += 2; + } + + if (level >= theMaxLevels) { + if (word >= res) { + word = res - 1; // crop if too large + } + res = 0; + numbits -= 1; + } + + if (write) { + // data bits + res |= word; + + // write bits + for (i = numbits - 1; i >= 0; i--) { + output_bit((res >> i) & 1); + } + } + + return numbits; +} + +int golomb_decode_word() +{ + int level; + int bit, databits; + int i; + + level = 0; + while (level + 1 < theMaxLevels) { + input_bit(bit); + if (bit) break; + level++; + } + + databits = 0; + for (i = 0; i < theGrad0 + level; i++) { + input_bit(bit); + databits = (databits << 1) | bit; + } + + return (((1 << level) - 1 << theGrad0) + databits); +} diff --git a/Interframe EZBC/TempSub/src/hvsbm_fullres.c b/Interframe EZBC/TempSub/src/hvsbm_fullres.c new file mode 100644 index 0000000..c9d24c7 --- /dev/null +++ b/Interframe EZBC/TempSub/src/hvsbm_fullres.c @@ -0,0 +1,843 @@ +#include "hvsbm_fullres.h" +#include "mode_decision.h" +#include "mv_ec.h" +#include "basic.h" +#include "bmeN.h" +#include "bme_tools.h" +#include "util_filtering.h" +#include "memoryN.h" +#include "mvcodingN.h" +#include "miscN.h" +#define EXTERN extern + +#define ANCHOR_LAMBDA 10 + + + +#include "coderN.h" +#include + +float ratio0 = -1, ratio1 = -1; +float rate0 = -1, rate1 = -1, rate2 = -1; +float new_lambda[LAMBDA_ADPT_LEVEL]; +int revise0 = 0, revise1 = 0, revise2 = 0; + + +//Added on 09.10.2017 +void lambda_revise(float *lambda, int t_level, float add_num){ + *lambda += add_num; + + if( *lambda <= 1 ) + *lambda -= add_num; +} + + + +void print_info(vector_ptr fmv1, vector_ptr fmv2, int xblock, int yblock, int x, int y){ + + if(fmv1->child){ + if(fmv2){ + print_info(fmv1->child0,fmv2->child0,xblock/2,yblock/2,x,y); + print_info(fmv1->child1,fmv2->child1,xblock/2,yblock/2,x+xblock /2,y); + print_info(fmv1->child2,fmv2->child2,xblock/2,yblock/2,x,y+yblock /2); + print_info(fmv1->child3,fmv2->child3,xblock/2,yblock/2,x+xblock /2,y+yblock /2); + } + else{ + print_info(fmv1->child0,NULL,xblock/2,yblock/2,x,y); + print_info(fmv1->child1,NULL,xblock/2,yblock/2,x+xblock /2,y); + print_info(fmv1->child2,NULL,xblock/2,yblock/2,x,y+yblock /2); + print_info(fmv1->child3,NULL,xblock/2,yblock/2,x+xblock /2,y+yblock /2); + } + } + else{ + if(fmv1->bi_mode == DIRECTIONAL_IBLOCK)printf("amigo! "); + printf("x = %d, y = %d, blkx = %d, blky = %d, fmv1_x = %1.2f, fmv1_y = %1.2f\n",x, y, xblock, yblock, fmv1->mvx,fmv1->mvy); + if(fmv2!=NULL){ + if(fmv2->bi_mode == DIRECTIONAL_IBLOCK)printf("amigo! "); + printf("x = %d, y = %d, blkx = %d, blky = %d, fmv2_x = %1.2f, fmv2_y = %1.2f\n",x, y, xblock, yblock, fmv2->mvx,fmv2->mvy); + } + } + +} + +void create_children(vector_ptr fmv) +{ + int i; + + assert(fmv->child == 0); + + fmv->child=1; + + fmv->child0 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child0" ); + fmv->child1 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child1" ); + fmv->child2 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child2" ); + fmv->child3 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv->child3" ); + + fmv->child0->parent = fmv; + fmv->child1->parent = fmv; + fmv->child2->parent = fmv; + fmv->child3->parent = fmv; + + fmv->child0->child = 0; + fmv->child0->bi_mode = UNDEFINED; + fmv->child0->lifting_mode = IGNORED; + fmv->child0->is_predictor = NO; + fmv->child0->propagate_iblk = 0; + + fmv->child1->child = 0; + fmv->child1->bi_mode = UNDEFINED; + fmv->child1->lifting_mode = IGNORED; + fmv->child1->is_predictor = NO; + fmv->child1->propagate_iblk = 0; + + fmv->child2->child = 0; + fmv->child2->bi_mode = UNDEFINED; + fmv->child2->lifting_mode = IGNORED; + fmv->child2->is_predictor = NO; + fmv->child2->propagate_iblk = 0; + + fmv->child3->child = 0; + fmv->child3->bi_mode = UNDEFINED; + fmv->child3->lifting_mode = IGNORED; + fmv->child3->is_predictor = NO; + fmv->child3->propagate_iblk = 0; + + for (i = 0; i < NUMBER_OF_BI_MODES; i++) { + fmv->child0->mode_info[i] = invalid_mode_info; + fmv->child1->mode_info[i] = invalid_mode_info; + fmv->child2->mode_info[i] = invalid_mode_info; + fmv->child3->mode_info[i] = invalid_mode_info; + } +} + +void kill_children(vector_ptr fmv) +{ + if(fmv->child) { + kill_children(fmv->child0); + kill_children(fmv->child1); + kill_children(fmv->child2); + kill_children(fmv->child3); + + free(fmv->child0); + free(fmv->child1); + free(fmv->child2); + free(fmv->child3); + + fmv->child = 0; + } +} + +// 向fmv1和fmv2写东西,来表示这个块的运动信息 +void rec_hvsbm_fullres(vector_ptr fmv1_array, vector_ptr fmv2_array, + vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3_array, vector_ptr fmv4_array, + float *fr_cur, float *fr_ref1, float *fr_ref2, + float *upframe1, float *upframe2, + float *pmv1x, float *pmv1y, float *pmv2x, float *pmv2y, + int x, int y, int xblock, int yblock, + int maxx, int maxy, int hor, int ver, + int block_level, int t_level, videoinfo info, int dec) +{ + int i; + float split_sad_cost, split_bit_cost, split_total_cost; + int cx, cy,xblk,yblk; + int ctx1x, ctx1y, ctx2x, ctx2y; + float mvpred1x[4], mvpred1y[4], mvpred2x[4], mvpred2y[4]; +#ifndef MEDIAN_PREDICTION + int xblk, yblk; +#endif + + if(block_level == 1 && (t_level == 0 || t_level == 1 || t_level == 2) && (x == 0 && y == 0) ) + printf("lambda = %f\n",info.lambda[t_level]); + +/////////////////// Added by Yuan Liu on 01.18.2016 ///////////////// + for(i=0;i<=3;i++){ + mvpred1x[i] = (float)HUGE_VAL; + mvpred1y[i] = (float)HUGE_VAL; + mvpred2x[i] = (float)HUGE_VAL; + mvpred2y[i] = (float)HUGE_VAL; + } +////////////////////////////////////////////////////////////////////// + + assert((fmv2_array == NULL && fmv2 == NULL) || + (fmv2_array != NULL && fmv2 != NULL)); + + // initialization + fmv1->is_predictor = NO; + if (fmv2 != NULL) fmv2->is_predictor = NO; + +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",x,y,xblock,yblock); + + // block validity check + if (x >= hor || y >= ver) { + // fmv1->mad = 0.; + fmv1->sad_cost = 0.; + fmv1->bit_cost = 0.; + fmv1->total_cost = 0.; + + if (fmv2 != NULL) { + // fmv2->mad = 0.; + fmv2->sad_cost = 0.; + fmv2->bit_cost = 0.; + fmv2->total_cost = 0.; + } + + return; + } + + // update contexts and predictors +#ifdef ECSIM_USE_CONTEXTS + ec_get_contexts(&ctx1x, &ctx1y, fmv1_array, x, y, info, t_level, 0); + if (fmv2_array != NULL) { + ec_get_contexts(&ctx2x, &ctx2y, fmv2_array, x, y, info, t_level, 0); + } +#else + ctx1x = ctx1y = 0; + ctx2x = ctx2y = 0; +#endif + +#ifdef MEDIAN_PREDICTION + get_median_predictor(mvpred1x, mvpred1y, fmv1_array, fmv3_array, fmv4_array, + x, y, xblock, yblock, info, t_level, 0); + if (fmv2 != NULL) { + get_median_predictor(mvpred2x, mvpred2y, fmv2_array, fmv4_array, NULL, + x, y, xblock, yblock, info, t_level, 0); + } +#else + xblk = ( x + xblock <= hor ) ? xblock : hor - x; + yblk = ( y + yblock <= ver ) ? yblock : ver - y; + + // store zig-zag predictors if pointing inside reference frame + if (x - (*pmv1x) < 0 || x - (*pmv1x) + xblk > hor || + y - (*pmv1y) < 0 || y - (*pmv1y) + yblk > ver) { + mvpred1x = 0.; + mvpred1y = 0.; + } else { + mvpred1x = *pmv1x; + mvpred1y = *pmv1y; + } + if (x - (*pmv2x) < 0 || x - (*pmv2x) + xblk > hor || + y - (*pmv2y) < 0 || y - (*pmv2y) + yblk > ver) { + mvpred2x = 0.; + mvpred2y = 0.; + } else { + mvpred2x = *pmv2x; + mvpred2y = *pmv2y; + } +#endif + + // motion estimation and mode decision + // note that block size decision starts with smallest block size + find_best_mode(fmv1_array, fmv2_array, fmv1, fmv2, fmv3_array, fmv4_array, fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + x, y, xblock, yblock, maxx, maxy, hor, ver, t_level, info, + ctx1x, ctx1y, ctx2x, ctx2y, + mvpred1x, mvpred1y, mvpred2x, mvpred2y, dec); + +#ifdef ECSIM_USE_CONTEXTS + // update coding engine + // note that in mvcoding.c, the MCFs are encoded separately!!! + // solution: increase the number of contexts and use different contexts + // for fmv1 and fmv2, which may be problematic with mv_ec! + assert(EC_SIM_TYPE != AR_NARY); + if (fmv1->lifting_mode != IGNORED) { + fmv1->dmvx = fmv1->mvx - (fmv1->med_idx >= 0)? mvpred1x[fmv1->med_idx] : 0.0; + fmv1->dmvy = fmv1->mvy - (fmv1->med_idx >= 0)? mvpred1y[fmv1->med_idx] : 0.0; + ec_update_model((int)((1 << info.subpel[t_level]) * fmv1->dmvx), ctx1x); + ec_update_model((int)((1 << info.subpel[t_level]) * fmv1->dmvy), ctx1y); + } + if (fmv2 != NULL && fmv2->lifting_mode != IGNORED) { + fmv2->dmvx = fmv2->mvx - (fmv2->med_idx >= 0)? mvpred2x[fmv2->med_idx] : 0.0; + fmv2->dmvy = fmv2->mvy - (fmv2->med_idx >= 0)? mvpred2y[fmv2->med_idx] : 0.0; + ec_update_model((int)((1 << info.subpel[t_level]) * fmv2->dmvx), ctx2x); + ec_update_model((int)((1 << info.subpel[t_level]) * fmv2->dmvy), ctx2y); + } +#endif + + // minimum block size (e.g. 4x4) still not reached? + if (block_level < info.level[t_level]) { + // create children + create_children(fmv1); + if (fmv2 != NULL) create_children(fmv2); + + // freeze coder state + ec_freeze(); + + // find block sizes, vectors and modes for children + cx = x; + cy = y; + rec_hvsbm_fullres(fmv1_array, fmv2_array, + fmv1->child0, fmv2 ? fmv2->child0 : NULL, fmv3_array, fmv4_array, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + pmv1x, pmv1y, pmv2x, pmv2y, + cx, cy, xblock / 2, yblock / 2, maxx, maxy, + hor, ver, block_level + 1, t_level, info, dec); + cx = x + xblock / 2; + cy = y; + rec_hvsbm_fullres(fmv1_array, fmv2_array, + fmv1->child1, fmv2 ? fmv2->child1 : NULL, fmv3_array, fmv4_array, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + pmv1x, pmv1y, pmv2x, pmv2y, + cx, cy, xblock / 2, yblock / 2, maxx, maxy, + hor, ver, block_level + 1, t_level, info, dec); + cx = x; + cy = y + yblock / 2; + rec_hvsbm_fullres(fmv1_array, fmv2_array, + fmv1->child2, fmv2 ? fmv2->child2 : NULL, fmv3_array, fmv4_array, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + pmv1x, pmv1y, pmv2x, pmv2y, + cx, cy, xblock / 2, yblock / 2, maxx, maxy, + hor, ver, block_level + 1, t_level, info, dec); + cx = x + xblock / 2; + cy = y + yblock / 2; + rec_hvsbm_fullres(fmv1_array, fmv2_array, + fmv1->child3, fmv2 ? fmv2->child3 : NULL, fmv3_array, fmv4_array, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + pmv1x, pmv1y, pmv2x, pmv2y, + cx, cy, xblock / 2, yblock / 2, maxx, maxy, + hor, ver, block_level + 1, t_level, info, dec); + + // compute splitting costs + // fmv1 costs and fmv2 costs are synonym + split_sad_cost = fmv1->child0->sad_cost + fmv1->child1->sad_cost + + fmv1->child2->sad_cost + fmv1->child3->sad_cost; + split_bit_cost = fmv1->child0->bit_cost + fmv1->child1->bit_cost + + fmv1->child2->bit_cost + fmv1->child3->bit_cost; + // after directional IBLOCK is added in this assertion is not valid any more + // assert(split_bit_cost / info.lambda[t_level] == float(int(split_bit_cost / info.lambda[t_level]))); + + if(fmv1->bi_mode >= 9 && fmv1->bi_mode <= 11){ +// printf("\nx = %d, y = %d, xblk = %d, yblk = %d",x,y,xblock,yblock); +// printf("\nsplit_sad_cost = %f, split_bit_cost = %f\n",split_sad_cost,split_bit_cost); +// printf("fmv1->sad_cost = %f, fmv1->bit_cost = %f\n",fmv1->sad_cost,fmv1->bit_cost); + } + + split_total_cost = split_sad_cost + split_bit_cost; + + // are you sure you like your children? + if (split_total_cost > fmv1->total_cost) { + // if not -> kill them ;-) + kill_children(fmv1); + if (fmv2 != NULL) kill_children(fmv2); + + // get previous states (without splitting) + ec_unfreeze(0); + +#ifndef MEDIAN_PREDICTION + // get new zig-zag predictor + if (fmv1->is_predictor == YES) { + *pmv1x = fmv1->mvx; + *pmv1y = fmv1->mvy; + } else { + *pmv1x = mvpred1x; + *pmv1y = mvpred1y; + } + if (fmv2 != NULL && fmv2->is_predictor == YES) { + *pmv2x = fmv2->mvx; + *pmv2y = fmv2->mvy; + } else { + *pmv2x = mvpred2x; + *pmv2y = mvpred2y; + } +#endif + } else { + // you like your children + // current node will not be coded, update cost + fmv1->is_predictor = NO; + fmv1->sad_cost = split_sad_cost; + fmv1->bit_cost = split_bit_cost; + // after directional IBLOCK is added in this assertion is not valid any more + // assert(fmv1->bit_cost / info.lambda[t_level] == float(int(fmv1->bit_cost / info.lambda[t_level]))); + if (fmv2 != NULL) { + fmv2->is_predictor = NO; + fmv2->sad_cost = split_sad_cost; + fmv2->bit_cost = split_bit_cost; + } + + // remove state from stack but keep current states (with splitting) + ec_unfreeze(1); + } + + // compute real cost for current block (consider splitting decision bit) + fmv1->bit_cost += 1.0f * info.lambda[t_level]; + // after directional IBLOCK is added in this assertion is not valid any more + // assert(fmv1->bit_cost / info.lambda[t_level] == float(int(fmv1->bit_cost / info.lambda[t_level]))); + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + if (fmv2 != NULL) { + fmv2->bit_cost = fmv1->bit_cost; + fmv2->total_cost = fmv1->total_cost; + } + + } +#ifndef MEDIAN_PREDICTION + else { + // leaf node: get zig-zag predictor + if (fmv1->is_predictor == YES) { + *pmv1x = fmv1->mvx; + *pmv1y = fmv1->mvy; + } + if (fmv2 != NULL && fmv2->is_predictor == YES) { + *pmv2x = fmv2->mvx; + *pmv2y = fmv2->mvy; + } + } +#else + assert((*pmv1x) == 0. && (*pmv1y) == 0. && (*pmv2x) == 0. && (*pmv2y) == 0.); +#endif +} + +/* + * hvsbm_fullres + * hiearchical variable size block matching on full resolution 挑选出最好的mv,此函数内部会进行rd计算 + */ +float hvsbm_fullres(vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, vector_ptr fmv4, + float *fr_cur, float *fr_ref1, float *fr_ref2, + float *upframe1, float *upframe2, + int t_level, int dist, videoinfo info, int dec) +{ + int hor, ver, xnum, ynum, xblk, yblk, maxx, maxy; + int x, y, X, Y, pos; + float pmv1x, pmv1y, pmv2x, pmv2y; + float bit_sum, sad_sum, total_sum; + float lambda_cost[4], best_cost; + int best_add_count; + + float new_ratio, new_rate; + + FILE *p_r, *p_sad, *p_lambda, *p_ratio; + int i,j; + + assert(fmv1 && fr_cur && fr_ref1); + assert((fmv2 && fr_ref2) || (!fmv2 && !fr_ref2)); + + // 全是注释 + if(fmv2 != NULL && t_level == 0){ +// p_r = fopen("rate_cost0.txt","at"); +// p_sad = fopen("sad_cost0.txt","at"); + +// p_ratio = fopen("RD_ratio0.txt","at"); +// p_lambda = fopen("lambda_value0.txt","at"); +/* + if(rate0 != -1){ + assert(rate0 > 0 && new_lambda[t_level] > 0 ); + info.lambda[t_level] = new_lambda[t_level]; + } +*/ + } + else if(fmv2 != NULL && t_level == 1) + { +// p_r = fopen("rate_cost1.txt","at"); +// p_sad = fopen("sad_cost1.txt","at"); + +// p_ratio = fopen("RD_ratio1.txt","at"); +// p_lambda = fopen("lambda_value1.txt","at"); +/* + if(rate1 != -1){ + assert(rate1 > 0 && new_lambda[t_level] > 0 ); + info.lambda[t_level] = new_lambda[t_level]; + } +*/ + } + else if(fmv2 != NULL && t_level == 2){ +// p_r = fopen("rate_cost2.txt","at"); +// p_sad = fopen("sad_cost2.txt","at"); +/* + if(rate2 != -1){ + assert(rate2 > 0 && new_lambda[t_level] > 0 ); + info.lambda[t_level] = new_lambda[t_level]; + } +*/ + } + else if(fmv2 != NULL && t_level == 3) + { +// p_r = fopen("rate_cost3.txt","at"); +// p_sad = fopen("sad_cost3.txt","at"); + } + + // initialization + hor = info.ywidth; + ver = info.yheight; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + + maxx = maxy = get_searchrange(dist, info); + printf("t_level = %d: block sizes = %dx%d - %dx%d, accuracy = %d, " + "search range = %d, lambda = %f, xnum = %d, ynum = %d\n", t_level, xblk, yblk, + xblk >> (info.level[t_level] - 1), yblk >> (info.level[t_level] - 1), + info.subpel[t_level], maxx, info.lambda[t_level], xnum, ynum); + + // initialize entropy coding +#ifdef ECSIM_USE_CONTEXTS + ec_enc_init(info, ECSIM_TYPE, 0, 3, 0); +#else + ec_enc_init(info, ECSIM_TYPE, 0, 1, 0); +#endif + +/////////////////////////////////////////////////// +/* + if(t_level == 0 && fmv2 != NULL){ + for(i = 0; i <= 3; i ++){ + lambda_revise(&info.lambda[t_level],t_level,1); + + // perform ME + MD + bit_sum = 0.; + sad_sum = 0.; + total_sum = 0.; + for(y = 0, Y = 0; Y < ynum; y += yblk, Y++) { + // initialize zig-zag predictors per row + pmv1x = 0.; + pmv1y = 0.; + pmv2x = 0.; + pmv2y = 0.; + + for(x = 0, X = 0; X < xnum; x += xblk, X++) { + pos = Y * xnum + X; + rec_hvsbm_fullres(fmv1, fmv2, &fmv1[pos], fmv2 ? (&fmv2[pos]) : NULL, fmv3, fmv4, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + &pmv1x, &pmv1y, &pmv2x, &pmv2y, + x, y, xblk, yblk, maxx, maxy, + hor, ver, 1, t_level, info, dec); + assert(fmv2 == NULL || (fmv1[pos].bit_cost == fmv2[pos].bit_cost && + fmv1[pos].total_cost == fmv2[pos].total_cost)); + bit_sum += fmv1[pos].bit_cost; + sad_sum += fmv1[pos].sad_cost; + total_sum += fmv1[pos].total_cost; + } + } + + lambda_cost[i] = sad_sum + bit_sum/info.lambda[t_level]*ANCHOR_LAMBDA ; + printf("total_sum = %f\n",lambda_cost[i]); + + free_vector(fmv1, info); + free_vector(fmv2, info); + }//for i + + best_cost = (float)HUGE_VAL; + + for(i = 0; i <= 3; i ++){ + if( lambda_cost[i] < best_cost ){ + best_cost = lambda_cost[i]; + best_add_count = i; + } + } + + lambda_revise(&info.lambda[t_level], t_level, best_add_count-3); + printf("best_lambda = %f\n", info.lambda[t_level]); + } +/////////////////////////////////////////////////// +*/ + + // perform ME + MD + bit_sum = 0.; + sad_sum = 0.; + total_sum = 0.; + for(y = 0, Y = 0; Y < ynum; y += yblk, Y++) { + // initialize zig-zag predictors per row + pmv1x = 0.; + pmv1y = 0.; + pmv2x = 0.; + pmv2y = 0.; + + for(x = 0, X = 0; X < xnum; x += xblk, X++) { // 按块进行 + pos = Y * xnum + X; + rec_hvsbm_fullres(fmv1, fmv2, &fmv1[pos], fmv2 ? (&fmv2[pos]) : NULL, fmv3, fmv4, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + &pmv1x, &pmv1y, &pmv2x, &pmv2y, + x, y, xblk, yblk, maxx, maxy, + hor, ver, 1, t_level, info, dec); + assert(fmv2 == NULL || (fmv1[pos].bit_cost == fmv2[pos].bit_cost && + fmv1[pos].total_cost == fmv2[pos].total_cost)); + bit_sum += fmv1[pos].bit_cost; + sad_sum += fmv1[pos].sad_cost; + total_sum += fmv1[pos].total_cost; + } + } + // printf("total mv bits expected = %f\n", bit_sum / info.lambda[t_level]); + + +/* + new_ratio = bit_sum / sad_sum; + new_rate = bit_sum / info.lambda[t_level]; + + if(fmv2 != NULL){ + if(t_level == 0){ + if(rate0 == -1){ + rate0 = bit_sum / info.lambda[t_level]; + }else{ + if( (new_rate/rate0) < THRES_RATIO ){ + lambda_revise(&info.lambda[t_level],t_level,2); + + free_vector(fmv1, info); + free_vector(fmv2, info); + + bit_sum = 0.; + sad_sum = 0.; + total_sum = 0.; + for(y = 0, Y = 0; Y < ynum; y += yblk, Y++) { + // initialize zig-zag predictors per row + pmv1x = 0.; + pmv1y = 0.; + pmv2x = 0.; + pmv2y = 0.; + + for(x = 0, X = 0; X < xnum; x += xblk, X++) { + pos = Y * xnum + X; + rec_hvsbm_fullres(fmv1, fmv2, &fmv1[pos], fmv2 ? (&fmv2[pos]) : NULL, fmv3, fmv4, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + &pmv1x, &pmv1y, &pmv2x, &pmv2y, + x, y, xblk, yblk, maxx, maxy, + hor, ver, 1, t_level, info, dec); + assert(fmv2 == NULL || (fmv1[pos].bit_cost == fmv2[pos].bit_cost && + fmv1[pos].total_cost == fmv2[pos].total_cost)); + bit_sum += fmv1[pos].bit_cost; + sad_sum += fmv1[pos].sad_cost; + total_sum += fmv1[pos].total_cost; + } + } + } + + }//else + new_lambda[t_level] = info.lambda[t_level]; + + }else if(t_level == 1){ + if(rate1 == -1){ + rate1 = bit_sum / info.lambda[t_level]; + }else{ + if( (new_rate/rate1) < THRES_RATIO ){ + lambda_revise(&info.lambda[t_level],t_level,3); + + free_vector(fmv1, info); + free_vector(fmv2, info); + + bit_sum = 0.; + sad_sum = 0.; + total_sum = 0.; + for(y = 0, Y = 0; Y < ynum; y += yblk, Y++) { + // initialize zig-zag predictors per row + pmv1x = 0.; + pmv1y = 0.; + pmv2x = 0.; + pmv2y = 0.; + + for(x = 0, X = 0; X < xnum; x += xblk, X++) { + pos = Y * xnum + X; + rec_hvsbm_fullres(fmv1, fmv2, &fmv1[pos], fmv2 ? (&fmv2[pos]) : NULL, fmv3, fmv4, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + &pmv1x, &pmv1y, &pmv2x, &pmv2y, + x, y, xblk, yblk, maxx, maxy, + hor, ver, 1, t_level, info, dec); + assert(fmv2 == NULL || (fmv1[pos].bit_cost == fmv2[pos].bit_cost && + fmv1[pos].total_cost == fmv2[pos].total_cost)); + bit_sum += fmv1[pos].bit_cost; + sad_sum += fmv1[pos].sad_cost; + total_sum += fmv1[pos].total_cost; + } + } + } + }//else + new_lambda[t_level] = info.lambda[t_level]; + + }else if(t_level == 2){ + if(rate2 == -1){ + rate2 = bit_sum / info.lambda[t_level]; + }else{ + if( (new_rate/rate2) < THRES_RATIO ){ + lambda_revise(&info.lambda[t_level],t_level,4); + + free_vector(fmv1, info); + free_vector(fmv2, info); + + bit_sum = 0.; + sad_sum = 0.; + total_sum = 0.; + for(y = 0, Y = 0; Y < ynum; y += yblk, Y++) { + // initialize zig-zag predictors per row + pmv1x = 0.; + pmv1y = 0.; + pmv2x = 0.; + pmv2y = 0.; + + for(x = 0, X = 0; X < xnum; x += xblk, X++) { + pos = Y * xnum + X; + rec_hvsbm_fullres(fmv1, fmv2, &fmv1[pos], fmv2 ? (&fmv2[pos]) : NULL, fmv3, fmv4, + fr_cur, fr_ref1, fr_ref2, upframe1, upframe2, + &pmv1x, &pmv1y, &pmv2x, &pmv2y, + x, y, xblk, yblk, maxx, maxy, + hor, ver, 1, t_level, info, dec); + assert(fmv2 == NULL || (fmv1[pos].bit_cost == fmv2[pos].bit_cost && + fmv1[pos].total_cost == fmv2[pos].total_cost)); + bit_sum += fmv1[pos].bit_cost; + sad_sum += fmv1[pos].sad_cost; + total_sum += fmv1[pos].total_cost; + } + } + } + } + new_lambda[t_level] = info.lambda[t_level]; + } + } + +*/ + + // terminate entropy coding + ec_enc_end1(); + ec_enc_end2(); + +/* for(x=0 ; x <= info.tPyrLev - 1 ; x++){ + printf("layer mv = %d\n",info.layer_mv[x]); + printf("AGP level = %d\n",info.AGP_level[x]); + }*/ + + if(fmv2 != NULL){ + + if(t_level <= 2){ +// fclose(p_r); +// fclose(p_sad); + } + } + + return total_sum; +} + + + +void rdme(vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3, vector_ptr fmv4, + YUVimage *fr_cur, YUVimage *fr_ref1, YUVimage *fr_ref2, + enum FLAG *sc1, enum FLAG *sc2, + int t_level, int dist, videoinfo info, float *upframe1, float *upframe2, float *upsamp_x ) +{ + int hor, ver, xnum, ynum; + float cost, min_cost; + vector_ptr tmp_fmv1, tmp_fmv2; + + int dec; + + hor = info.ywidth;// 图像宽度 + ver = info.yheight; // 图像高度 + xnum = info.xnum[t_level]; // x方向块的数量 + ynum = info.ynum[t_level];// y 方向块的数量 + + assert(fmv1 && fr_cur && fr_ref1 && sc1 && (*sc1 == NO)); + assert((fmv2 && fr_ref2 && sc2 && (*sc2 == NO)) || + (!fmv2 && !fr_ref2 && !sc2)); + +#ifdef PRE_INTERPOL + // generate interpolated reference frames + Interpolate_frame2(fr_ref1->Y, hor, ver, &upframe1, upsamp_x, + MY_MIN(PRE_INTERPOL, info.subpel[t_level])); +#else + upframe1 = NULL; +#endif + + //////////////////////// + if(fmv2 != NULL) + dec = 1; + else + dec = 0; + //////////////////////// + + tmp_fmv1 = (vector*)getarray(info.maxMBnum, sizeof(vector), "tmp_fmv1"); + alloc_vector(tmp_fmv1, info); + + // generate intra satd + temporal_filter(); + min_cost = RDMD_INTRA_FACTOR * getFrameSATD(fr_cur->Y, hor, ver); + assert(*sc1 == NO); + *sc1 = YES; + free_vector(fmv1, info); + if (fmv2 != NULL) { + assert(*sc2 == NO); + *sc2 = YES; + free_vector(fmv2, info); + } + + // perform left search + free_vector(tmp_fmv1, info); + cost = hvsbm_fullres(tmp_fmv1, NULL, fmv3, NULL, fr_cur->Y, fr_ref1->Y, NULL, + upframe1, NULL, t_level, dist, info, dec); + // printf("left pred cost = %f\n", cost); + if (cost < min_cost) { + min_cost = cost; + free_vector(fmv1, info); + mv_copy(tmp_fmv1, fmv1, info); + *sc1 = NO; + if (fmv2 != NULL) { + free_vector(fmv2, info); + *sc2 = YES; + } + } + + + + // bi-directional case? + if (fmv2 != NULL +// && (simul_skip == NO || skip_frame == NO ) + ) { + +#ifdef PRE_INTERPOL + Interpolate_frame2(fr_ref2->Y, hor, ver, &upframe2, upsamp_x, + MY_MIN(PRE_INTERPOL, info.subpel[t_level])); +#else + upframe2 = NULL; +#endif + + tmp_fmv2 = (vector*)getarray(info.maxMBnum, sizeof(vector), "tmp_fmv2"); + alloc_vector(tmp_fmv2, info); + + // right search + free_vector(tmp_fmv2, info); + cost = hvsbm_fullres(tmp_fmv2, NULL, fmv4, NULL, fr_cur->Y, fr_ref2->Y, NULL, + upframe2, NULL, t_level, dist, info, dec); + // printf("right pred cost = %f\n", cost); + if (cost < min_cost) { + min_cost = cost; + free_vector(fmv1, info); + free_vector(fmv2, info); + mv_copy(tmp_fmv2, fmv2, info); + *sc1 = YES; + *sc2 = NO; + } + + // bi-directional search + free_vector(tmp_fmv1, info); + free_vector(tmp_fmv2, info); + cost = hvsbm_fullres(tmp_fmv1, tmp_fmv2, fmv3, fmv4, fr_cur->Y, fr_ref1->Y, fr_ref2->Y, + upframe1, upframe2, t_level, dist, info, 0); + // printf("bi pred cost = %f\n", cost); + if (cost < min_cost) { + min_cost = cost; + free_vector(fmv1, info); + free_vector(fmv2, info); + mv_copy(tmp_fmv1, fmv1, info); + mv_copy(tmp_fmv2, fmv2, info); + *sc1 = NO; + *sc2 = NO; + } + + // tidy up + free_vector(tmp_fmv2, info); + free(tmp_fmv2); +#ifdef PRE_INTERPOL +// free(upframe2); +#endif + } + free_vector(tmp_fmv1, info); + free(tmp_fmv1); + +#ifdef PRE_INTERPOL +// free(upframe1); +#endif + + printf("=> sc1 = %d, sc2 = %d\n", *sc1, sc2 ? *sc2 : 0); +} + +int get_searchrange(int dist, videoinfo info) +{ + int sr; + + assert(info.searchrange >= 0); + + sr = dist * info.searchrange; + + return (sr < info.maxsearchrange) ? sr : info.maxsearchrange; +} diff --git a/Interframe EZBC/TempSub/src/init_decN.c b/Interframe EZBC/TempSub/src/init_decN.c new file mode 100644 index 0000000..b82ccb4 --- /dev/null +++ b/Interframe EZBC/TempSub/src/init_decN.c @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#define EXTERN extern +#include "structN.h" +#include "coderN.h" +#include "basic.h" +#include "util_filtering.h" +#include "memoryN.h" +#include "general.h" +#include + +/*****************************************************************************/ +/* init_dec() */ +/*****************************************************************************/ +void +init_dec( videoinfo info ) +{ + int i, j, /*xnum, ynum, xblk, yblk, hor, ver,*/ GOPsz; + int num_mv_GOP, num_pyrFrs_bigGOP, rel_s_level; + /*int picture_rate, totalrate, illbit, pllbit, lhbit, hbit; */ + +//#ifdef MCTF_WITH_OBMC + int hor, ver, s_level; + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + hor = info.ywidth<> (info.level[i] - 1), info.yblk[i] >> (info.level[i] - 1)); + + if( info.subpel[i] == 4 ) + printf( "1/16-pixel accuracy\n" ); + else if( info.subpel[i] == 3 ) + printf( "1/8-pixel accuracy\n" ); + else if( info.subpel[i] == 2 ) + printf( "quarter-pixel accuracy\n" ); + else if( info.subpel[i] == 1 ) + printf( "half-pixel accuracy\n" ); + else + printf( "full-pixel accuracy\n" ); + } + printf( " Frame rate : %0.2f frames/sec (t_level %d)\n", + ((double)(info.framerate) / pow( (float)2, (int)info.t_level)), info.t_level ); + printf( " Frame size : (Y) %d x %d (C) %d x %d (s_level %d)\n", + info.ywidth << rel_s_level, info.yheight << rel_s_level, + info.cwidth << rel_s_level, info.cheight << rel_s_level, + info.s_level ); + if ( info.denoise_flag == YES ) + printf( " Denoise : YES\n"); +#ifdef MY_SCALE + printf( " MY_SCALE : %d (%d extra bits)\n", MY_SCALE, (int)log2(MY_SCALE)); +#endif + printf( "---------------------------------------------------------------\n" ); + /****************** initialize the sequence information ****************/ + GOPsz = info.GOPsz; + + // same number of MVs for GOP and bigGOP ! + num_mv_GOP = 1; // 4, 9, 18, 35, ... + num_pyrFrs_bigGOP = 1; // 3, 6, 11, 20, ... + + // calculation of base indices for MV-sets and frames + for( i = info.tPyrLev-1; i >= 0; i-- ){ + num_mv_GOP += info.GOPsz / (int)( pow( (float)2, (int)i)) + 1; + } + num_pyrFrs_bigGOP = info.GOPsz + info.tPyrLev + 1; // 为什么这样??????? + + printf("num_pyrFrs_bigGOP = %d, num_mv_GOP = %d\n", num_pyrFrs_bigGOP, num_mv_GOP); + + /***************** allocate the 1st layer motion vectors ***************/ + dec_yfmv_bigGOP = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "dec_yfmv_bigGOP_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ){ + dec_yfmv_bigGOP[j] = + ( vector_ptr ) getarray( info.maxMBnum, sizeof( vector ), "dec_yfmv_bigGOP" ); + alloc_vector( dec_yfmv_bigGOP[j], info ); + } + + dec_yfmv = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "dec_yfmv_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ) { + dec_yfmv[j] = + ( vector_ptr ) getarray( info.maxMBnum, sizeof( vector ), "dec_yfmv" ); + alloc_vector( dec_yfmv[j], info ); + } + + dec_mv_ref_bigGOP = + ( vector_ptr * ) getarray( num_mv_GOP, sizeof( vector_ptr ), + "dec_mv_ref_bigGOP" ); + mv_ref = + ( vector_ptr * ) getarray( num_mv_GOP, sizeof( vector_ptr ), + "mv_ref" ); + + /************ allocate the frame *************/ + frame_alloc( &end_of_lastGOP, info ); + + if( info.tPyrLev >= 1 ) { + dec_pyrFrs_bigGOP = + ( YUVimage_ptr ) getarray( num_pyrFrs_bigGOP, sizeof( YUVimage ), + "dec_pyrFrs_bigGOP_ptr" ); + for(i = 0; i < num_pyrFrs_bigGOP; i++){ + frame_alloc( &dec_pyrFrs_bigGOP[i], info ); + } + + dec_pyrFrs = + ( YUVimage_ptr ) getarray( info.GOPsz, sizeof( YUVimage ), + "dec_pyrFrs_ptr" ); + + if( info.denoise_flag == NO ) { + for(i = 0; i < info.GOPsz; i++){ + frame_alloc( &dec_pyrFrs[i], info ); + } + } + + dec_pyrFrs_first = + ( YUVimage_ptr ) getarray( info.tPyrLev, sizeof( YUVimage ), + "dec_pyrFrs_first_ptr" ); + for( i = 0; i < info.tPyrLev; i++ ){ + frame_alloc( &dec_pyrFrs_first[i], info ); + } + + dec_pyrTemp = + ( YUVimage_ptr * ) getarray( info.tPyrLev, sizeof( YUVimage_ptr ), + "dec_pyrTemp" ); + + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + dec_pyrTemp[i] = ( YUVimage_ptr ) getarray( GOPsz, sizeof( YUVimage ), + "dec_pyrTemp[]" ); + for(j = 0; j < GOPsz; j++){ + frame_alloc( &dec_pyrTemp[i][j], info ); + } + GOPsz /= 2; + } + + } else { + assert(0); + } + + if( info.denoise_flag == YES ) { + Four_bigGOP = + ( YUVimage * ) getarray( ((YUV420 == 1) ? 2 : 4) * info.GOPsz, + sizeof( YUVimage ), "Four_bigGOP" ); + for( j = 0; j < ((YUV420 == 1) ? 2 : 4) * info.GOPsz; j++ ) { + frame_alloc( &Four_bigGOP[j], info ); + } + + Four_GOP = + ( YUVimage * ) getarray( ((YUV420 == 1) ? 2 : 4) * info.GOPsz, + sizeof( YUVimage ), "Four_GOP" ); + for( j = 0; j < ((YUV420 == 1) ? 2 : 4) * info.GOPsz; j++ ) { + frame_alloc( &Four_GOP[j], info ); + } + + for( i = 0; i < ((YUV420 == 1) ? 1 : 3); i++ ) { + spatial_high[i] = + ( YUVimage * ) getarray( info.GOPsz, sizeof( YUVimage ), + "spatial_high[i]" ); + } + + } + + frY = ( float ** )getarray( info.GOPsz, sizeof( float * ), "*frY" ); + frU = ( float ** )getarray( info.GOPsz, sizeof( float * ), "*frU" ); + frV = ( float ** )getarray( info.GOPsz, sizeof( float * ), "*frV" ); + + dec_scene_change = + ( enum FLAG ** )getarray( info.tPyrLev, sizeof( enum FLAG * ), + "dec_scene_change_ptr" ); + + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + GOPsz += 1; + dec_scene_change[i] = + ( enum FLAG * )getarray( GOPsz, sizeof( enum FLAG ), "dec_scene_change" ); + GOPsz /= 2; + } + + + + +} diff --git a/Interframe EZBC/TempSub/src/init_encN.c b/Interframe EZBC/TempSub/src/init_encN.c new file mode 100644 index 0000000..c9a8980 --- /dev/null +++ b/Interframe EZBC/TempSub/src/init_encN.c @@ -0,0 +1,517 @@ +#include +#include +#include +#include +#include +#define EXTERN extern +#include "basic.h" +#include "structN.h" +#include "coderN.h" +#include "init_encN.h" +#include "memoryN.h" +#include "dpx.h" +#include "util_filtering.h" +#include "structN.h" +#include "general.h" +#include + +extern U16 colorLUT[1024]; + +#define Yes 1 +#define No 0 + +extern long int totalY[5], totalU[5], totalV[5], totalmap[5], totalMV[5]; +int rateAlloc( Rate_ptr FrsRate, int nfrs, videoinfo * info ); + +/*****************************************************************************/ +/* init() */ +/*****************************************************************************/ +void +init_enc( videoinfo * info ) +{ + int i, j, xblk, yblk, hor, ver, bigGOP, rel_s_level; + int num_mv_bigGOP, num_mv_GOP, num_pyrFrs_bigGOP;//, num_scene_change; + char name[512], strtmp[512]; + FILE *fpstat, *fpbit, *fp, *fp_mv; + + int GOPsz; + + interpolate_filter( ); + temporal_filter( ); + rel_s_level = (info->denoise_flag == YES); + + for( i = 0; i < 5; i++ ) { + totalY[i] = 0; + totalU[i] = 0; + totalV[i] = 0; + totalmap[i] = 0; + totalMV[i] = 0; + } + + /************ initialize the sequence information ***************/ + hor = info->ywidth; + ver = info->yheight; + info->maxMBnum = 0; + for (i = 0; i < info->tPyrLev; i++) { + xblk = info->xblk[i]; + yblk = info->yblk[i]; + info->xnum[i] = ( !( hor % xblk ) ) ? hor / xblk : hor / xblk + 1; + info->ynum[i] = ( !( ver % yblk ) ) ? ver / yblk : ver / yblk + 1; + + if(info->xnum[i] * info->ynum[i] > info->maxMBnum) { + info->maxMBnum = info->xnum[i] * info->ynum[i]; + } + } + + num_mv_bigGOP = 1; // 4, 11, 26, 57, ... + num_mv_GOP = 1; // 4, 9, 18, 35, ... + num_pyrFrs_bigGOP = 1; // 2, 4, 12, 27, ... + + // calculation of base indices for MV-sets and frames + for( i = info->tPyrLev-1; i >= 0; i-- ){ + num_pyrFrs_bigGOP += info->bigGOP / (int)(pow ( (float)2, (int)(i + 1))); + num_mv_bigGOP += info->bigGOP / (int)(pow ( (float)2, (int)i)); + num_mv_GOP += info->GOPsz / (int)(pow ( (float)2, (int)i)) + 1; + } + + printf("num_pyrFrs_bigGOP = %d, num_mv_GOP = %d, num_mv_bigGOP = %d\n", num_pyrFrs_bigGOP, num_mv_GOP, num_mv_bigGOP); + /************ allocate the 1st layer motion vectors *************/ + yfmv_bigGOP = + ( vector_ptr * ) getarray( num_mv_bigGOP + 1, sizeof( vector_ptr ), + "yfmv_bigGOP_ptr" ); + for( j = 1; j <= num_mv_bigGOP; j++ ){ + yfmv_bigGOP[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "yfmv_bigGOP" ); + alloc_vector( yfmv_bigGOP[j], *info ); + } +//Shadow + buff_yfmv_bigGOP = + ( vector_ptr * ) getarray( num_mv_bigGOP + 1, sizeof( vector_ptr ), + "buff_yfmv_bigGOP_ptr" ); + for( j = 1; j <= num_mv_bigGOP; j++ ){ + buff_yfmv_bigGOP[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "buff_yfmv_bigGOP" ); + alloc_vector( buff_yfmv_bigGOP[j], *info ); + } + + yfmv = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "yfmv_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ) { + yfmv[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "yfmv" ); + alloc_vector( yfmv[j], *info ); + } +//Shadow + buff_yfmv = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "buff_yfmv_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ) { + buff_yfmv[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "buff_yfmv" ); + alloc_vector( buff_yfmv[j], *info ); + } + + tmp_yfmv = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "tmp_yfmv" ); + alloc_vector( tmp_yfmv, *info ); +//Shadow + buff_tmp_yfmv = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "buff_tmp_yfmv" ); + alloc_vector( buff_tmp_yfmv, *info ); + + mv_ref_bigGOP = + ( vector_ptr * ) getarray( num_mv_bigGOP, sizeof( vector_ptr ), + "mv_ref_bigGOP" ); +//Shadow + buff_mv_ref_bigGOP = + ( vector_ptr * ) getarray( num_mv_bigGOP, sizeof( vector_ptr ), + "buff_mv_ref_bigGOP" ); + +// for simul decoding 01.09.2018 + mv_ref = + ( vector_ptr * ) getarray( num_mv_GOP, sizeof( vector_ptr ), + "mv_ref" ); +//Shadow + buff_mv_ref = + ( vector_ptr * ) getarray( num_mv_GOP, sizeof( vector_ptr ), + "buff_mv_ref" ); + + dec_yfmv_bigGOP = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "dec_yfmv_bigGOP_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ){ + dec_yfmv_bigGOP[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "dec_yfmv_bigGOP" ); + alloc_vector( dec_yfmv_bigGOP[j], *info ); + } +//Shadow + buff_dec_yfmv_bigGOP = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "buff_dec_yfmv_bigGOP_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ){ + buff_dec_yfmv_bigGOP[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "buff_dec_yfmv_bigGOP" ); + alloc_vector( buff_dec_yfmv_bigGOP[j], *info ); + } + + dec_yfmv = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "dec_yfmv_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ) { + dec_yfmv[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "dec_yfmv" ); + alloc_vector( dec_yfmv[j], *info ); + } +//Shadow + buff_dec_yfmv = + ( vector_ptr * ) getarray( num_mv_GOP + 1, sizeof( vector_ptr ), + "buff_dec_yfmv_ptr" ); + for( j = 1; j <= num_mv_GOP; j++ ) { + buff_dec_yfmv[j] = + ( vector_ptr ) getarray( info->maxMBnum, sizeof( vector ), "buff_dec_yfmv" ); + alloc_vector( buff_dec_yfmv[j], *info ); + } + + dec_mv_ref_bigGOP = + ( vector_ptr * ) getarray( num_mv_GOP, sizeof( vector_ptr ), + "dec_mv_ref_bigGOP" ); +//Shadow + buff_dec_mv_ref_bigGOP = + ( vector_ptr * ) getarray( num_mv_GOP, sizeof( vector_ptr ), + "buff_dec_mv_ref_bigGOP" ); + +// for simul decoding 01.09.2018 + +//#ifdef MCTF_WITH_OBMC + // allocate memory for frameMEinfo, varblkarray + // pixel based motion vector side information, and side information for each block + frameMEinfo = (ImageMEinfo*) getarray(hor*ver, sizeof(ImageMEinfo), "frameMEinfo"); + varblkarray = (Varblkarrayinfo*) getarray(hor/SMALLEST_BLKSIZE*ver/SMALLEST_BLKSIZE, + sizeof(Varblkarrayinfo), "varblkarray"); +//#endif + + + + + /*********************** allocate the frames *********************/ + frame_alloc( &end_of_lastGOP, *info ); +//Shadow + frame_alloc( &buff_end_of_lastGOP, *info ); + + if( info->tPyrLev >= 1 ){ + + pyrFrs_bigGOP = + ( YUVimage_ptr ) getarray( num_pyrFrs_bigGOP, sizeof( YUVimage ), + "pyrFrs_bigGOP__ptr" ); + for(i = 0; i < num_pyrFrs_bigGOP; i++){ + frame_alloc( &pyrFrs_bigGOP[i], *info ); + } +//Shadow + buff_pyrFrs_bigGOP = + ( YUVimage_ptr ) getarray( num_pyrFrs_bigGOP, sizeof( YUVimage ), + "buff_pyrFrs_bigGOP_ptr" ); + for(i = 0; i < num_pyrFrs_bigGOP; i++){ + frame_alloc( &buff_pyrFrs_bigGOP[i], *info ); + } + + pyrFrs = + ( YUVimage_ptr ) getarray( info->GOPsz, sizeof( YUVimage ), + "pyrFrs_ptr" ); + for(i = 0; i < info->GOPsz; i++){ + frame_alloc( &pyrFrs[i], *info ); + } +//Shadow + buff_pyrFrs = + ( YUVimage_ptr ) getarray( info->GOPsz, sizeof( YUVimage ), + "buff_pyrFrs_ptr" ); + for(i = 0; i < info->GOPsz; i++){ + frame_alloc( &buff_pyrFrs[i], *info ); + } + + pyrFrs_first = + ( YUVimage_ptr ) getarray( info->tPyrLev, sizeof( YUVimage ), + "pyrFrs_first_ptr" ); + for( i = 0; i < info->tPyrLev; i++ ){ + frame_alloc( &pyrFrs_first[i], *info ); + } +//Shadow + buff_pyrFrs_first = + ( YUVimage_ptr ) getarray( info->tPyrLev, sizeof( YUVimage ), + "buff_pyrFrs_first_ptr" ); + for( i = 0; i < info->tPyrLev; i++ ){ + frame_alloc( &buff_pyrFrs_first[i], *info ); + } + + pyrTemp = + ( YUVimage_ptr * ) getarray( info->tPyrLev, sizeof( YUVimage_ptr ), + "pyrTemp" ); + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + pyrTemp[i] = ( YUVimage_ptr ) getarray( bigGOP, sizeof( YUVimage ), + "pyrTemp[]" ); + for(j = 0; j < bigGOP; j++){ + frame_alloc( &pyrTemp[i][j], *info ); + } + bigGOP /= 2; + } +//Shadow + buff_pyrTemp = + ( YUVimage_ptr * ) getarray( info->tPyrLev, sizeof( YUVimage_ptr ), + "buff_pyrTemp" ); + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + buff_pyrTemp[i] = ( YUVimage_ptr ) getarray( bigGOP, sizeof( YUVimage ), + "buff_pyrTemp[]" ); + for(j = 0; j < bigGOP; j++){ + frame_alloc( &buff_pyrTemp[i][j], *info ); + } + bigGOP /= 2; + } +// For simul decoding ************************************************* + dec_pyrFrs_bigGOP = + ( YUVimage_ptr ) getarray( num_pyrFrs_bigGOP, sizeof( YUVimage ), + "dec_pyrFrs_bigGOP_ptr" ); + for(i = 0; i < num_pyrFrs_bigGOP; i++){ + frame_alloc( &dec_pyrFrs_bigGOP[i], *info ); + } +//Shadow + buff_dec_pyrFrs_bigGOP = + ( YUVimage_ptr ) getarray( num_pyrFrs_bigGOP, sizeof( YUVimage ), + "buff_dec_pyrFrs_bigGOP_ptr" ); + for(i = 0; i < num_pyrFrs_bigGOP; i++){ + frame_alloc( &buff_dec_pyrFrs_bigGOP[i], *info ); + } + + dec_pyrFrs = + ( YUVimage_ptr ) getarray( info->GOPsz, sizeof( YUVimage ), + "dec_pyrFrs_ptr" ); + if( info->denoise_flag == NO ) { + for(i = 0; i < info->GOPsz; i++){ + frame_alloc( &dec_pyrFrs[i], *info ); + } + } +//Shadow + buff_dec_pyrFrs = + ( YUVimage_ptr ) getarray( info->GOPsz, sizeof( YUVimage ), + "buff_dec_pyrFrs_ptr" ); + if( info->denoise_flag == NO ) { + for(i = 0; i < info->GOPsz; i++){ + frame_alloc( &buff_dec_pyrFrs[i], *info ); + } + } + + dec_pyrFrs_first = + ( YUVimage_ptr ) getarray( info->tPyrLev, sizeof( YUVimage ), + "dec_pyrFrs_first_ptr" ); + for( i = 0; i < info->tPyrLev; i++ ){ + frame_alloc( &dec_pyrFrs_first[i], *info ); + } +//Shadow + buff_dec_pyrFrs_first = + ( YUVimage_ptr ) getarray( info->tPyrLev, sizeof( YUVimage ), + "buff_dec_pyrFrs_first_ptr" ); + for( i = 0; i < info->tPyrLev; i++ ){ + frame_alloc( &buff_dec_pyrFrs_first[i], *info ); + } + + dec_pyrTemp = + ( YUVimage_ptr * ) getarray( info->tPyrLev, sizeof( YUVimage_ptr ), + "dec_pyrTemp" ); + GOPsz = info->GOPsz; + for( i = 0; i < info->tPyrLev; i++ ) { + dec_pyrTemp[i] = ( YUVimage_ptr ) getarray( GOPsz, sizeof( YUVimage ), + "dec_pyrTemp[]" ); + for(j = 0; j < GOPsz; j++){ + frame_alloc( &dec_pyrTemp[i][j], *info ); + } + GOPsz /= 2; + } +//Shadow + buff_dec_pyrTemp = + ( YUVimage_ptr * ) getarray( info->tPyrLev, sizeof( YUVimage_ptr ), + "buff_dec_pyrTemp" ); + GOPsz = info->GOPsz; + for( i = 0; i < info->tPyrLev; i++ ) { + buff_dec_pyrTemp[i] = ( YUVimage_ptr ) getarray( GOPsz, sizeof( YUVimage ), + "buff_dec_pyrTemp[]" ); + for(j = 0; j < GOPsz; j++){ + frame_alloc( &buff_dec_pyrTemp[i][j], *info ); + } + GOPsz /= 2; + } + + } else { // info->tPyrLev == 0; relevant? + assert(0); + } + + if( info->denoise_flag == YES ) { + Four_GOP = + ( YUVimage * ) getarray( 4 * info->GOPsz, sizeof( YUVimage ), + "Four_GOP" ); + + for( i = 0; i < ((YUV420 == 1) ? 1 : 3); i++ ) { + spatial_high[i] = + ( YUVimage * ) getarray( info->bigGOP, sizeof( YUVimage ), + "spatial_high[i]" ); + for( j = 0; j < info->bigGOP; j++ ) { + frame_alloc( &spatial_high[i][j], *info ); + } + } + + } + + /********************* rate allocation **********************/ + rateAlloc( &FrsRate, num_mv_GOP + 1, info ); + + frY = ( float ** )getarray( info->GOPsz, sizeof( float * ), "*frY" ); + frU = ( float ** )getarray( info->GOPsz, sizeof( float * ), "*frU" ); + frV = ( float ** )getarray( info->GOPsz, sizeof( float * ), "*frV" ); + + + /**************** output encoder information **************/ + printf( "---------------------------------------------------------------\n" ); + printf( " Input sequence : %s\n", info->inname ); + // printf( " Coded sequence : %s\n", info->decname); + printf( " Motion vectors : %s\n", info->mvname ); + printf( " Bit file : %s\n", info->bitname ); + printf( " Status log : %s\n", info->statname ); + printf( " Sequence length : %03d frames ( %03d - %03d )\n", + info->last - info->start + 1, info->start, info->last ); + printf( " Frame rate : %0.2f frames/sec\n", + (double)(info->framerate)); + printf( " Frame size : (Y) %d x %d (C) %d x %d\n", + info->ywidth << rel_s_level, info->yheight << rel_s_level, + info->cwidth << rel_s_level, info->cheight << rel_s_level); + if ( info->denoise_flag == YES ) + printf( " Denoise : YES\n"); + if( info->ME == 3 ){ + for (i = 0; i < info->tPyrLev; i++) { + printf( " Motion Level %d : HVSBM with Bx %d By %d ... Bx %d By %d / ", + i, info->xblk[i], info->yblk[i], + info->xblk[i] >> (info->level[i] - 1), info->yblk[i] >> (info->level[i] - 1)); + if( info->subpel[i] == 4 ) + printf( "1/16-pixel accuracy\n" ); + else if( info->subpel[i] == 3 ) + printf( "1/8-pixel accuracy\n" ); + else if( info->subpel[i] == 2 ) + printf( "quarter-pixel accuracy\n" ); + else if( info->subpel[i] == 1 ) + printf( "half-pixel accuracy\n" ); + else + printf( "full-pixel accuracy\n" ); + } + } else { + printf( " Motion : unknown / " ); + } + printf( " Searchrange : %d\n", info->searchrange ); + printf( " Max Searchrange : %d\n", info->maxsearchrange ); + printf( " Lambda : "); + for (i = 0; i < info->tPyrLev; i++) printf("%.1f ", info->lambda[i]); + printf("\n"); +#ifdef MY_SCALE + printf( " MY_SCALE : %d (%d extra bits)\n", MY_SCALE, (int)log2(MY_SCALE)); +#endif + // printf( " initial bits for GOP = %d bits\n", info->GOPbit); + printf( "---------------------------------------------------------------\n" ); + + /******************** initialize the statefile **************/ + if( !( fpstat = fopen( info->statname, "wb" ) ) ) { + printf( "init: %s\n", info->statname ); + exit( 1 ); + } + fprintf( fpstat, "---------------------------------------------------------------\n" ); + fprintf( fpstat, " Input sequence : %s\n", info->inname ); + fprintf( fpstat, " Motion vectors : %s\n", info->mvname ); + fprintf( fpstat, " Bit file : %s\n", info->bitname ); + fprintf( fpstat, " Status log : %s\n", info->statname ); + fprintf( fpstat, " Sequence length : %03d frames ( %03d - %03d )\n", + info->last - info->start + 1, info->start, info->last ); + fprintf( fpstat, " Frame rate : %0.2f frames/sec\n", + (double)(info->framerate)); + fprintf( fpstat, " Frame size : (Y) %d x %d (C) %d x %d\n", + info->ywidth << rel_s_level, info->yheight << rel_s_level, + info->cwidth << rel_s_level, info->cheight << rel_s_level); + if ( info->denoise_flag == YES ) + fprintf( fpstat, " Denoise : YES\n"); + fprintf( fpstat, " Searchrange : %d\n", info->searchrange ); + fprintf( fpstat, " Max searchrange : %d\n", info->maxsearchrange ); + fprintf( fpstat, " Lambda : "); + for (i = 0; i < info->tPyrLev; i++) + fprintf(fpstat, "%.1f ", info->lambda[i]); + fprintf(fpstat, "\n"); +#ifdef MY_SCALE + fprintf( fpstat, " MY_SCALE : %d (%d extra bits)\n", MY_SCALE, (int)log2(MY_SCALE)); +#endif + // fprintf( fpstat, " initial bits for GOP = %d bits\n", info->GOPbit); + fprintf( fpstat, "---------------------------------------------------------------\n" ); + fclose( fpstat ); + + /******************* newly open the bitfile ******************/ + if( !( fpbit = fopen( info->bitname, "wb" ) ) ) { + printf( "init: %s\n", info->bitname ); + exit( 1 ); + } + fclose( fpbit ); + + if( !( fp_mv = fopen( info->mvstatname, "wb" ) ) ) { + printf( "can not open %s\n", info->mvstatname ); + exit( 1 ); + } + fclose( fp_mv ); + + strncpy( strtmp, info->bitname, strlen( info->bitname ) - 4 ); // Hanke, 16.09.02 + strtmp[strlen( info->bitname ) - 4] = '\0'; // + sprintf( name, "%s.rd_sample_dat", strtmp ); // + if( !( fp = fopen( name, "wb" ) ) ) { + printf( "init: can not open %s\n", name ); + exit( 1 ); + } + fclose( fp ); + + /******************* allocation of scene changes ******************/ + // scene change description: + scene_change = + ( enum FLAG ** )getarray( info->tPyrLev, sizeof( enum FLAG * ), + "scene_change" ); + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + scene_change[i] = + ( enum FLAG * )getarray( bigGOP + 1, sizeof( enum FLAG ), "scene_change" ); + bigGOP /= 2; + } +//Shadow + buff_scene_change = + ( enum FLAG ** )getarray( info->tPyrLev, sizeof( enum FLAG * ), + "buff_scene_change" ); + bigGOP = info->bigGOP; + for( i = 0; i < info->tPyrLev; i++ ) { + buff_scene_change[i] = + ( enum FLAG * )getarray( bigGOP + 1, sizeof( enum FLAG ), "buff_scene_change" ); + bigGOP /= 2; + } + +//For simul decoding + dec_scene_change = + ( enum FLAG ** )getarray( info->tPyrLev, sizeof( enum FLAG * ), + "dec_scene_change_ptr" ); + GOPsz = info->GOPsz; + for( i = 0; i < info->tPyrLev; i++ ) { + GOPsz += 1; + dec_scene_change[i] = + ( enum FLAG * )getarray( GOPsz, sizeof( enum FLAG ), "dec_scene_change" ); + GOPsz /= 2; + } +//Shadow + buff_dec_scene_change = + ( enum FLAG ** )getarray( info->tPyrLev, sizeof( enum FLAG * ), + "buff_dec_scene_change_ptr" ); + GOPsz = info->GOPsz; + for( i = 0; i < info->tPyrLev; i++ ) { + GOPsz += 1; + buff_dec_scene_change[i] = + ( enum FLAG * )getarray( GOPsz, sizeof( enum FLAG ), "buff_dec_scene_change" ); + GOPsz /= 2; + } + +} diff --git a/Interframe EZBC/TempSub/src/intra_dec.c b/Interframe EZBC/TempSub/src/intra_dec.c new file mode 100644 index 0000000..59e9def --- /dev/null +++ b/Interframe EZBC/TempSub/src/intra_dec.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#define EXTERN extern +#include "basic.h" +#include "rasterfile.h" +#include "structN.h" +#include "coderN.h" +#include "analsyn.h" +#include "ioN.h" +#include "miscN.h" +#include "memoryN.h" +#include "chrom.h" +#include "mvcodingN.h" +#include "ezbc_dec_3d.h" +#include "bmeN.h" +#include "pstatN.h" + + +void ezbc3d_dec_GOP( YUVimage * pyrFrs, videoinfo info, long total_bytes_past, + long int GOP_counter, int curr ); + + +void +intra_decode( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info ) +{ + int i; + + ezbc3d_dec_GOP( dec_pyrFrs, info, *total_bytes_past, GOP_counter, curr ); + + for( i = 0; i < info.GOPsz; i++ ) { + write_frame( dec_pyrFrs[i], info, info.decname, curr + i, info.format ); + } + + /* + for( i = 0; i < info.GOPsz; i++ ) { + free_frame( dec_pyrFrs[i] ); + } + */ +} diff --git a/Interframe EZBC/TempSub/src/intra_enc.c b/Interframe EZBC/TempSub/src/intra_enc.c new file mode 100644 index 0000000..e3310cc --- /dev/null +++ b/Interframe EZBC/TempSub/src/intra_enc.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#define EXTERN extern +#include "basic.h" +#include "rasterfile.h" +#include "structN.h" +#include "coderN.h" +#include "analsyn.h" +#include "ioN.h" +#include "miscN.h" +#include "memoryN.h" +#include "chrom.h" +#include "mvcodingN.h" +#include "ezbc_dec_3d.h" +#include "bmeN.h" +#include "pstatN.h" +#include "ezbc_enc_3d.h" + + +long int +intra_encode( int curr, int GOP_counter, videoinfo info ) +{ + int i; + long int output_GOP_bytes; + + for( i = 0; i < info.GOPsz; i++ ) { + read_frame( &pyrFrs[i], info, info.inname, curr + i, info.format ); /*ioN.c */ + } + output_GOP_bytes = ezbc3d_enc_GOP( curr, pyrFrs, info, GOP_counter ); + return output_GOP_bytes; + +} diff --git a/Interframe EZBC/TempSub/src/ioN.c b/Interframe EZBC/TempSub/src/ioN.c new file mode 100644 index 0000000..bae0eb6 --- /dev/null +++ b/Interframe EZBC/TempSub/src/ioN.c @@ -0,0 +1,1437 @@ +#include +#include +#include +#include +#include +#include "structN.h" +#include "rasterfile.h" +#include "basic.h" +#include "dpx.h" +#include "unix_pc.h" +#include "chrom.h" +#include "miscN.h" +#define EXTERN extern +#include "coderN.h" +#include "util_filtering.h" +extern enum FLAG **scene_change; +extern enum FLAG **dec_scene_change; + +#define RGBYUV //do RGB to YUV conversion +//#define OUTPUT_RAS + + +/*****************************************************************************/ +/* clipping() */ +/*****************************************************************************/ +int +clipping( float ipix ) +{ + int opix; + + if( ipix > 255.0 ) + opix = 255; + else if( ipix < 0.0 ) + opix = 0; + else + opix = nint( ipix ); + + return ( opix ); +} + +/*****************************************************************************/ +/* clipping2() */ +/*****************************************************************************/ +float +clipping2( float ipix ) +{ + float opix; + + if( ipix > 255.0 ) + opix = 255.; + else if( ipix < 0.0 ) + opix = 0.; + else + opix = ipix; + + return ( opix ); +} + + +/*****************************************************************************/ +/* read_child() */ +/*****************************************************************************/ +void +read_child( vector_ptr fmv, FILE * fpio ) +{ + /* if child is NULL, then there is nothing to do */ + /* else, allocate the memory */ + /* and read the 4 child motion vectors */ + /* and call again */ + + if( fmv->child ) { + fmv->child0 = ( vector_ptr ) calloc( 1, sizeof( vector ) ); + fmv->child1 = ( vector_ptr ) calloc( 1, sizeof( vector ) ); + fmv->child2 = ( vector_ptr ) calloc( 1, sizeof( vector ) ); + fmv->child3 = ( vector_ptr ) calloc( 1, sizeof( vector ) ); + + fread( fmv->child0, sizeof( vector ), 1, fpio ); + fread( fmv->child1, sizeof( vector ), 1, fpio ); + fread( fmv->child2, sizeof( vector ), 1, fpio ); + fread( fmv->child3, sizeof( vector ), 1, fpio ); + + fmv->child0->parent = fmv; + fmv->child1->parent = fmv; + fmv->child2->parent = fmv; + fmv->child3->parent = fmv; + + read_child( fmv->child0, fpio ); + read_child( fmv->child1, fpio ); + read_child( fmv->child2, fpio ); + read_child( fmv->child3, fpio ); + } else { + } +} + + +/*****************************************************************************/ +/* write_child() */ +/*****************************************************************************/ +void +write_child( vector_ptr fmv, FILE * fpio ) +{ + /* if child is NULL, then there is nothing to do */ + /* else, write the 4 child motion vectors and call again */ + + if( fmv->child ) { + fwrite( fmv->child0, sizeof( vector ), 1, fpio ); + fwrite( fmv->child1, sizeof( vector ), 1, fpio ); + fwrite( fmv->child2, sizeof( vector ), 1, fpio ); + fwrite( fmv->child3, sizeof( vector ), 1, fpio ); + + write_child( fmv->child0, fpio ); + write_child( fmv->child1, fpio ); + write_child( fmv->child2, fpio ); + write_child( fmv->child3, fpio ); + } else { + } +} + + +/*****************************************************************************/ +/* print_mv() */ +/*****************************************************************************/ +void +print_mv( vector_ptr fmv, int cx, int cy, int xblk, int yblk, int hor, + int ver ) +{ + float mvx, mvy, mad; + + /* this routine draws the variable block motion vectors */ + + if( fmv->child ) { + + if( xblk >= 32 ) { + mvx = fmv->mvx; + mvy = fmv->mvy; + mad = fmv->mad; + printf( "x %d y %d xblk %d yblk %d mvx %.1f mvy %.1f mad %.1f\n", cx, + cy, xblk, yblk, mvx, mvy, mad ); + } + print_mv( fmv->child0, cx, cy, xblk / 2, yblk / 2, hor, ver ); + print_mv( fmv->child1, cx + xblk / 2, cy, xblk / 2, yblk / 2, hor, ver ); + print_mv( fmv->child2, cx, cy + yblk / 2, xblk / 2, yblk / 2, hor, ver ); + print_mv( fmv->child3, cx + xblk / 2, cy + yblk / 2, xblk / 2, yblk / 2, + hor, ver ); + } else { + if( cx < hor && cy < ver && xblk >= 32 ) { + mvx = fmv->mvx; + mvy = fmv->mvy; + mad = fmv->mad; + printf( "x %d y %d xblk %d yblk %d mvx %.1f mvy %.1f mad %.1f\n", cx, cy, + xblk, yblk, mvx, mvy, mad ); + } + + return; + } +} + + + + +/***************************************************************************** + ** ** + ** ras2yuv ** + ** ** + ** -. convert the sun rasterfile to YUV file (YUV with 4:1:1 or 4:2:2) ** + ** ** + ** author : Seung-Jong Choi ** + ** ** + *****************************************************************************/ + +/* sub422=0; *//* 4:1:1 subsampling */ +/*sub422=1; *//* 4:2:2 subsampling */ +void +ras2yuv( char *rasname, int yhor, int yver, float *Yfr, int chor, int cver, + float *Ufr, float *Vfr ) +{ + unsigned char *RGBfr, *temp, map[768]; + FILE *fpin; + int i, j, hor, ver, mapsize, sub422; + float Ydata, Udata, Vdata, Rdata, Gdata, Bdata; + struct rasterfile *header; + U32 *p; + + if( !( fpin = fopen( rasname, "rb" ) ) ) { + printf( "ras2yuv: can't open rasterfile %s.\n", rasname ); + exit( 1 ); + } + + header = + ( struct rasterfile * )getarray( 1, sizeof( struct rasterfile ), + "header" ); + /* read the header of rasterfile */ + if( fread( header, sizeof( struct rasterfile ), 1, fpin ) != 1 ) { + printf( "\n" ); + printf( "ras2yuv: can't read header from %s.\n", rasname ); + exit( 1 ); + } + + p = ( U32 * ) header; + for( i = 0; i < 8; i++ ) { + p[i] = exchange_4byte_order( p[i] ); + } + + header = ( struct rasterfile * )p; + + + + hor = header->ras_width; + ver = header->ras_height; + if( ( yhor != hor ) || ( yver != ver ) ) { + printf + ( "size of image error info.width %d, info.height %d, header->ras_width %d, header->ras_height %d (ioN.c)!\n", + yhor, yver, hor, ver ); + header->ras_depth = 24; + hor = yhor; + ver = yver; + /*exit(0); */ + } + + + /************ allocate memory and read the data of rasterfile **********/ + /* + if(sub422){ + RGBfr = (unsigned char*) calloc(ver*hor*3, sizeof(unsigned char)); + Yfr = (float*) calloc(hor*ver, sizeof(float)); + Ufr = (float*) calloc((hor/2)*ver, sizeof(float)); + Vfr = (float*) calloc((hor/2)*ver, sizeof(float)); + } + else { + RGBfr = (unsigned char*) calloc(ver*hor*3, sizeof(unsigned char)); + Yfr = (float*) calloc(hor*ver, sizeof(float)); + Ufr = (float*) calloc(hor*ver/4, sizeof(float)); + Vfr = (float*) calloc(hor*ver/4, sizeof(float)); + } + */ + + /* read the map */ + mapsize = header->ras_maplength; + if( ( mapsize != 768 ) && ( mapsize != 0 ) ) { + printf( "the size of maplength %d is not 768(ioN.c)\n", mapsize ); + exit( 0 ); + } + + if( mapsize ) { + if( fread( map, sizeof( unsigned char ), mapsize, fpin ) != + ( unsigned )mapsize ) { + printf( "ras2yuv: error in reading of map from %s.\n", rasname ); + exit( 1 ); + } + } + + /********************* read the data *****************/ + if( header->ras_depth == GRAYDATA ) { + if( ( chor != 0 ) || ( cver != 0 ) ) { + printf( " the size of chrom component error(ras2yuv.c)!\n" ); + exit( 0 ); + } + temp = ( unsigned char * )calloc( hor * ver, sizeof( unsigned char ) ); + if( fread( temp, sizeof( unsigned char ), hor * ver, fpin ) != + ( unsigned )( hor * ver ) ) { + printf( "ras2yuv: can't read the Y data from %s.\n", rasname ); + exit( 1 ); + } + for( i = 0; i < hor * ver; i++ ) + Yfr[i] = ( float )temp[i]; + free( temp ); + } else if( header->ras_depth == RGBDATA ) { + + if( ( yhor == 2 * chor ) && ( yver == 2 * cver ) ) + sub422 = 0; + else if( ( yhor == 2 * chor ) && ( yver == cver ) ) + sub422 = 1; + else if( ( yhor == chor ) && ( yver == cver ) ) + sub422 = 2; + else { + printf( "size of image error(ras2yuv.c)\n" ); + exit( 0 ); + } + + RGBfr = + ( unsigned char * )calloc( ver * hor * 3, sizeof( unsigned char ) ); + if( fread( RGBfr, sizeof( unsigned char ), 3 * hor * ver, fpin ) != + ( unsigned )( 3 * hor * ver ) ) { + printf( "ras2yuv: can't read the RGB data from %s.\n", rasname ); + exit( 1 ); + } + for( i = 0; i < ver; i++ ) { + for( j = 0; j < hor; j++ ) { + /* read the data and change to the float */ + Bdata = ( float )RGBfr[i * ( 3 * hor ) + 3 * j]; + Gdata = ( float )RGBfr[i * ( 3 * hor ) + 3 * j + 1]; + Rdata = ( float )RGBfr[i * ( 3 * hor ) + 3 * j + 2]; + + RGB2YUV( Rdata, Gdata, Bdata, &Ydata, &Udata, &Vdata ); + Udata += 128.; + Vdata += 128.; + + if( sub422 == 2 ) { + Yfr[i * hor + j] = Ydata; + Ufr[i * hor + j] = Udata; + Vfr[i * hor + j] = Vdata; + } else if( sub422 == 1 ) { + Yfr[i * hor + j] = Ydata; + if( !( j % 2 ) ) { + Ufr[i * ( hor / 2 ) + ( j / 2 )] = Udata; + Vfr[i * ( hor / 2 ) + ( j / 2 )] = Vdata; + } + } else { + Yfr[i * hor + j] = Ydata; + if( !( j % 2 ) && !( i % 2 ) ) { + Ufr[( i / 2 ) * ( hor / 2 ) + j / 2] = Udata; + Vfr[( i / 2 ) * ( hor / 2 ) + j / 2] = Vdata; + } + } + } /* for j */ + } /* for i */ + free( RGBfr ); + + } else { + printf( "ras2yuv: %s is not supported.\n", rasname ); + exit( 1 ); + } + + + fclose( fpin ); + + free( header ); + +} + + + +/***************************************************************************** + ** ** + ** yuv2ras ** + ** ** + ** -. convert the YUV file to sun rasterfile (YUV with 4:1:1 or 4:2:2) ** + ** ** + ** author : Seung-Jong Choi ** + ** ** + *****************************************************************************/ + +void +yuv2ras( char *rasname, int yhor, int yver, float *Yframe, int chor, int cver, + float *Uframe, float *Vframe ) +{ + int i, j, ci, cj; + float Ydata, Udata, Vdata, Rdata, Gdata, Bdata; + struct rasterfile header; + unsigned char *RGBframe, *temp; + + ci = ( cver ) ? yver / cver : 0; + cj = ( chor ) ? yhor / chor : 0; + + /* allocate memory */ + + /* + Yframe = (unsigned char*) calloc(yhor*yver, sizeof(unsigned char)); + Uframe = (unsigned char*) calloc(chor*cver, sizeof(unsigned char)); + Vframe = (unsigned char*) calloc(chor*cver, sizeof(unsigned char)); + */ + + /* read the data from SIF or CCIR */ + /* + if(!(fpin = fopen(yuvname, "rb"))){ + printf("yuv2ras: can't open %s for reading.\n", yuvname); + exit(1); + } + + if(fread(Yframe, sizeof(unsigned char), yhor*yver, fpin) != yhor*yver){ + printf("yuv2ras: can't read Y from %s\n", yuvname); + exit(1); + } + if(fread(Uframe, sizeof(unsigned char), chor*cver, fpin) != chor*cver){ + printf("yuv2ras: can't read U from %s\n", yuvname); + exit(1); + } + if(fread(Vframe, sizeof(unsigned char), chor*cver, fpin) != chor*cver){ + printf("yuv2ras: can't read V from %s\n", yuvname); + exit(1); + } + fclose(fpin); + */ + + /* convert YUV to BGR */ + if( chor * cver ) { + RGBframe = + ( unsigned char * )calloc( yhor * yver * 3, sizeof( unsigned char ) ); + for( i = 0; i < yver; i++ ) { + for( j = 0; j < yhor; j++ ) { + Ydata = clipping2( Yframe[i * yhor + j] ); + Udata = clipping2( Uframe[( i / ci ) * chor + ( j / cj )] ); + Vdata = clipping2( Vframe[( i / ci ) * chor + ( j / cj )] ); + + /* YUV -> RGB */ + Udata -= 128.; + Vdata -= 128.; + YUV2RGB( Ydata, Udata, Vdata, &Rdata, &Gdata, &Bdata ); + + /* clipping */ + if( Rdata >= 255. ) + Rdata = 255.; + if( Rdata <= 0. ) + Rdata = 0.; + if( Gdata >= 255. ) + Gdata = 255.; + if( Gdata <= 0. ) + Gdata = 0.; + if( Bdata >= 255. ) + Bdata = 255.; + if( Bdata <= 0. ) + Bdata = 0.; + + /* formatting */ + RGBframe[i * 3 * yhor + 3 * j] = ( unsigned char )nint( Bdata ); + RGBframe[i * 3 * yhor + 3 * j + 1] = ( unsigned char )nint( Gdata ); + RGBframe[i * 3 * yhor + 3 * j + 2] = ( unsigned char )nint( Rdata ); + } + } + header = make_header( yhor, yver, RGBDATA ); + + write_ras( rasname, header, RGBframe ); + free( RGBframe ); + } else { /* gray file */ + temp = ( unsigned char * )calloc( yhor * yver, sizeof( unsigned char ) ); + header = make_header( yhor, yver, GRAYDATA ); + for( i = 0; i < yhor * yver; i++ ) { + if( Yframe[i] >= 255. ) + temp[i] = 255; + else if( Yframe[i] <= 0. ) + temp[i] = 0; + else + temp[i] = ( unsigned char )Yframe[i]; + } + write_ras( rasname, header, temp ); + free( temp ); + } + + + +} + + + + +/***************************************************************************** + ** ** + ** yuv2RGB ** + ** ** + ** -. convert the YUV file to RGB (YUV with 4:1:1 or 4:2:2) ** + ** ** + ** ** + ** ** + *****************************************************************************/ + +void +yuv2RGB( unsigned char *RGBframe, int yhor, int yver, float *Yframe, int chor, + int cver, float *Uframe, float *Vframe ) +{ + int i, j, ci, cj; + float Ydata, Udata, Vdata, Rdata, Gdata, Bdata; + + ci = ( cver ) ? yver / cver : 0; + cj = ( chor ) ? yhor / chor : 0; + + /* allocate memory */ + + /* convert YUV to BGR */ + if( chor * cver ) { + /* RGBframe = (unsigned char*) calloc(yhor*yver*3, sizeof(unsigned char));*/ + for( i = 0; i < yver; i++ ) { + for( j = 0; j < yhor; j++ ) { + Ydata = clipping2( Yframe[i * yhor + j] ); /* QUEST */ + Udata = clipping2( Uframe[( i / ci ) * chor + ( j / cj )] ); + Vdata = clipping2( Vframe[( i / ci ) * chor + ( j / cj )] ); + + /* YUV -> RGB */ + Udata -= 128.; + Vdata -= 128.; + YUV2RGB( Ydata, Udata, Vdata, &Rdata, &Gdata, &Bdata ); + + /* clipping */ + if( Rdata >= 255. ) + Rdata = 255.; + if( Rdata <= 0. ) + Rdata = 0.; + if( Gdata >= 255. ) + Gdata = 255.; + if( Gdata <= 0. ) + Gdata = 0.; + if( Bdata >= 255. ) + Bdata = 255.; + if( Bdata <= 0. ) + Bdata = 0.; + + /* formatting */ + RGBframe[i * 3 * yhor + 3 * j] = ( unsigned char )nint( Bdata ); + RGBframe[i * 3 * yhor + 3 * j + 1] = ( unsigned char )nint( Gdata ); + RGBframe[i * 3 * yhor + 3 * j + 2] = ( unsigned char )nint( Rdata ); + } + } + + } else { /* gray file */ + + for( i = 0; i < yhor * yver; i++ ) { + if( Yframe[i] >= 255. ) + RGBframe[i] = 255; + else if( Yframe[i] <= 0. ) + RGBframe[i] = 0; + else + RGBframe[i] = ( unsigned char )Yframe[i]; + } + } + +} + + +/*****************************************************************************/ +/* read_frame() */ +/*****************************************************************************/ +void +read_frame( YUVimage_ptr frame, videoinfo info, char *inname, int index, + enum FORMAT format ) +{ + int i, size, ret; +#ifdef SUPPORT_DPX + int j, row, col, pos; + float Rdata, Gdata, Bdata; + U16 *RGBframe; + struct dpx *dpxheader; +#endif + int frameskip = 0; + _int64 offset; + unsigned char *temp; + char frame_name[250]; + //float *LRGB; + FILE *fpio; + + offset = ( frameskip + 1 ) * index * ( info.ywidth*info.yheight + 2 * info.cwidth*info.cheight ); +// printf("\noffset = %ld\n",offset); + + switch ( format ) { + case RAS: + sprintf( frame_name, inname, index ); + ras2yuv( frame_name, info.ywidth, info.yheight, frame->Y, info.cwidth, + info.cheight, frame->U, frame->V ); + break; + case YUV: + /* assume that the order of data file is Y[total], U[total], V[total] */ + + if ((strchr (inname, '%'))!=0) //check the filename for frame or video mode + { + sprintf(frame_name, inname, index); // for frame-mode only + if (!(fpio = fopen(frame_name, "rb"))) + { + printf("read_frame: %s\n", frame_name); + exit(1); + } + } + else + { // for container-mode (video) + sprintf(frame_name, inname); + if (!(fpio = fopen(inname, "rb"))) + { + printf("read_Video: %s\n", inname); + exit(1); + } +// fseek (fpio, offset, SEEK_SET); //seek to the picture in the file + _fseeki64(fpio, offset, SEEK_SET); + /* if ( fseek (fpio, offset, SEEK_SET)); //seek to the picture in the file with error check + { + printf("Error while seeking to picture"); + exit (1); + } */ + } + + size = ( info.ywidth ) * ( info.yheight ); + temp = + ( unsigned char * )getarray( size, sizeof( unsigned char ), "temp" ); + if( ( ret = fread( temp, sizeof( unsigned char ), size, fpio ) ) != size ) { + + printf + ( "error for reading file %s.Y in read_frame(): return size %d, target size %d\n", + frame_name, ret, size ); + exit( 1 ); + } + for( i = 0; i < size; i++ ) + frame->Y[i] = ( float )temp[i]; + + size = ( info.cwidth ) * ( info.cheight ); + if( fread( temp, sizeof( unsigned char ), size, fpio ) != + ( unsigned )( size ) ) { + printf( "error for reading file %s.U in read_frame()\n", frame_name ); + exit( 1 ); + } + for( i = 0; i < size; i++ ) + frame->U[i] = ( float )temp[i]; + + if( fread( temp, sizeof( unsigned char ), size, fpio ) != + ( unsigned )( size ) ) { + printf( "error for reading file %s.V in read_frame()\n", frame_name ); + exit( 1 ); + } + for( i = 0; i < size; i++ ) + frame->V[i] = ( float )temp[i]; + + free( temp ); + fclose( fpio ); + break; +#ifdef SUPPORT_DPX + case DPX: + //printf("index %d %d\n", index, 0); + sprintf( frame_name, inname, index ); + RGBframe = read_dpx( frame_name, &dpxheader, &row, &col ); + + if( ( row != info.yheight ) || ( col != info.ywidth ) ) { + printf( " the size of image does not match with the info\n" ); + exit( 1 ); + } + + + for( i = 0; i < info.yheight; i++ ) { + for( j = 0; j < info.ywidth; j++ ) { + Bdata = RGBframe[i * ( 3 * info.ywidth ) + 3 * j]; + Gdata = RGBframe[i * ( 3 * info.ywidth ) + 3 * j + 1]; + Rdata = RGBframe[i * ( 3 * info.ywidth ) + 3 * j + 2]; + + if( info.coding_domain != LOG ) { + Bdata = convertLOG( PEAK, Bdata, info.coding_domain ); + Gdata = convertLOG( PEAK, Gdata, info.coding_domain ); + Rdata = convertLOG( PEAK, Rdata, info.coding_domain ); + } + /* convert RGB to YUV */ + pos = i * info.ywidth + j; + +#ifdef RGBYUV + RGB2YUV( Rdata, Gdata, Bdata, &( frame->Y[pos] ), &( frame->U[pos] ), + &( frame->V[pos] ) ); + + if( info.coding_domain != LOG ) { + frame->U[pos] += ( PEAK + 1 ) / 2; + frame->V[pos] += ( PEAK + 1 ) / 2; + } else { + frame->U[pos] += 1024 / 2; + frame->V[pos] += 1024 / 2; + } +#else + frame->Y[pos] = Rdata; + frame->U[pos] = Gdata; + frame->V[pos] = Bdata; +#endif + } + } + + + // sprintf(dpxname, "%s%04d%s", "temp", index, ".dpx"); + // write_dpx(dpxname, *frame, info); + + free( RGBframe ); + free( dpxheader ); + + break; +#endif + default: + printf( "image format error format = %d(ioN.c)\n", format ); + exit( 0 ); + + } + + +} + +/*****************************************************************************/ +/* read_jp2k_frame() */ +/*****************************************************************************/ +void +read_jp2k_frame( YUVimage_ptr frame, videoinfo info, char *inname, int index, + enum FORMAT format ) +{ + int i, size, ret; +#ifdef SUPPORT_DPX + int j, row, col, pos; + float Rdata, Gdata, Bdata; + U16 *RGBframe; + struct dpx *dpxheader; +#endif + int frameskip = 0; + long offset; + float *temp; + char frame_name[250]; + //float *LRGB; + FILE *fpio; + + offset = ( sizeof( float ) / sizeof( unsigned char ) ) * ( frameskip + 1 ) * index * ( info.ywidth*info.yheight + 2 * info.cwidth*info.cheight ); + + switch ( format ) { + case RAS: + sprintf( frame_name, inname, index ); + ras2yuv( frame_name, info.ywidth, info.yheight, frame->Y, info.cwidth, + info.cheight, frame->U, frame->V ); + break; + case YUV: + /* assume that the order of data file is Y[total], U[total], V[total] */ + + if ((strchr (inname, '%'))!=0) //check the filename for frame or video mode + { + sprintf(frame_name, inname, index); // for frame-mode only + if (!(fpio = fopen(frame_name, "rb"))) + { + printf("read_frame: %s\n", frame_name); + exit(1); + } + } + else + { // for container-mode (video) + sprintf(frame_name, inname); + if (!(fpio = fopen(inname, "rb"))) + { + printf("read_Video: %s\n", inname); + exit(1); + } + fseek (fpio, offset, SEEK_SET); //seek to the picture in the file + /* if ( fseek (fpio, offset, SEEK_SET)); //seek to the picture in the file with error check + { + printf("Error while seeking to picture"); + exit (1); + } */ + } + + size = ( info.ywidth ) * ( info.yheight ); + temp = + ( float * )getarray( size, sizeof( float ), "temp" ); + if( ( ret = fread( temp, sizeof( float ), size, fpio ) ) != size ) { + + printf + ( "error for reading file %s.Y in read_frame(): return size %d, target size %d\n", + frame_name, ret, size ); + exit( 1 ); + } + for( i = 0; i < size; i++ ) + frame->Y[i] = ( float )temp[i]; + + size = ( info.cwidth ) * ( info.cheight ); + if( fread( temp, sizeof( float ), size, fpio ) != + ( size ) ) { + printf( "error for reading file %s.U in read_frame()\n", frame_name ); + exit( 1 ); + } + for( i = 0; i < size; i++ ) + frame->U[i] = ( float )temp[i]; + + if( fread( temp, sizeof( float ), size, fpio ) != + ( size ) ) { + printf( "error for reading file %s.V in read_frame()\n", frame_name ); + exit( 1 ); + } + for( i = 0; i < size; i++ ) + frame->V[i] = ( float )temp[i]; + + free( temp ); + fclose( fpio ); + break; +#ifdef SUPPORT_DPX + case DPX: + //printf("index %d %d\n", index, 0); + sprintf( frame_name, inname, index ); + RGBframe = read_dpx( frame_name, &dpxheader, &row, &col ); + + if( ( row != info.yheight ) || ( col != info.ywidth ) ) { + printf( " the size of image does not match with the info\n" ); + exit( 1 ); + } + + + for( i = 0; i < info.yheight; i++ ) { + for( j = 0; j < info.ywidth; j++ ) { + Bdata = RGBframe[i * ( 3 * info.ywidth ) + 3 * j]; + Gdata = RGBframe[i * ( 3 * info.ywidth ) + 3 * j + 1]; + Rdata = RGBframe[i * ( 3 * info.ywidth ) + 3 * j + 2]; + + if( info.coding_domain != LOG ) { + Bdata = convertLOG( PEAK, Bdata, info.coding_domain ); + Gdata = convertLOG( PEAK, Gdata, info.coding_domain ); + Rdata = convertLOG( PEAK, Rdata, info.coding_domain ); + } + /* convert RGB to YUV */ + pos = i * info.ywidth + j; + +#ifdef RGBYUV + RGB2YUV( Rdata, Gdata, Bdata, &( frame->Y[pos] ), &( frame->U[pos] ), + &( frame->V[pos] ) ); + + if( info.coding_domain != LOG ) { + frame->U[pos] += ( PEAK + 1 ) / 2; + frame->V[pos] += ( PEAK + 1 ) / 2; + } else { + frame->U[pos] += 1024 / 2; + frame->V[pos] += 1024 / 2; + } +#else + frame->Y[pos] = Rdata; + frame->U[pos] = Gdata; + frame->V[pos] = Bdata; +#endif + } + } + + + // sprintf(dpxname, "%s%04d%s", "temp", index, ".dpx"); + // write_dpx(dpxname, *frame, info); + + free( RGBframe ); + free( dpxheader ); + + break; +#endif + default: + printf( "image format error format = %d(ioN.c)\n", format ); + exit( 0 ); + + } + + +} + +/*****************************************************************************/ +/* write_frame() */ +/*****************************************************************************/ +void +write_frame( YUVimage frame, videoinfo info, char *inname, int index, + enum FORMAT format ) +{ + FILE *fpio; + int i, size; + char frame_name[250]; + unsigned char *temp; + long int offset; +#ifdef SUPPORT_DPX + int j, pos; + float Ydata, Udata, Vdata; +#endif + float *LRGB = 0; + int frameskip = 0; + +// printf("Enter write frame!\n"); + + offset = ( frameskip + 1 ) * index * ( info.ywidth*info.yheight + 2 * info.cwidth*info.cheight ); + + switch ( format ) { + case RAS: + sprintf( frame_name, inname, index ); + yuv2ras( frame_name, info.ywidth, info.yheight, frame.Y, info.cwidth, + info.cheight, frame.U, frame.V ); + break; + + case YUV: + /* assume that the order of data file is Y[total], U[total], V[total] */ + if ((strchr (inname, '%'))!=0) + { + assert(0); + sprintf(frame_name, inname, index); + + if (!(fpio = fopen(frame_name, "wb"))) // open a new frame file + { + printf("write_frame: %s\n", frame_name); + exit(1); + } + } + else + { + if ( index == info.start ) // open new video file + { + if (!(fpio = fopen(inname, "wb"))) + { + printf("write_Video: %s\n", inname); + exit(1); + } + } + else // append new frame to existing video file + { + if (!(fpio = fopen(inname, "r+b"))) + { + printf("write_Video: %s\n", inname); + exit(1); + } + } + fseek (fpio, offset, SEEK_SET); + } + + size = ( info.ywidth ) * ( info.yheight ); + temp = ( unsigned char * )calloc( size, sizeof( unsigned char ) ); + for( i = 0; i < size; i++ ) + temp[i] = ( unsigned char )clipping( frame.Y[i] ); + if( fwrite( temp, sizeof( unsigned char ), size, fpio ) != + ( unsigned )( size ) ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + + size = ( info.cwidth ) * ( info.cheight ); /* QUEST */ + for( i = 0; i < size; i++ ) + temp[i] = ( unsigned char )clipping( frame.U[i] ); + if( fwrite( temp, sizeof( unsigned char ), size, fpio ) != + ( unsigned )( size ) ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + + for( i = 0; i < size; i++ ) + temp[i] = ( unsigned char )clipping( frame.V[i] ); + if( fwrite( temp, sizeof( unsigned char ), size, fpio ) != + ( unsigned )( size ) ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + free( temp ); + fclose( fpio ); + + break; + + case DPX: + +#ifdef DPX_SUPPORT + LRGB = + ( float * )getarray( info.ywidth * info.yheight * 3, sizeof( float ), + "LRGB" ); + + for( i = 0; i < info.yheight; i++ ) { + for( j = 0; j < info.ywidth; j++ ) { + pos = i * info.ywidth + j; + Ydata = frame.Y[pos]; + Udata = frame.U[pos]; + Vdata = frame.V[pos]; + /* YUV -> RGB */ + if( info.coding_domain != LOG ) { + Udata -= ( PEAK + 1 ) / 2.; + Vdata -= ( PEAK + 1 ) / 2.; + } else { + Udata -= 1024 / 2.; + Vdata -= 1024 / 2.; + } + YUV2RGB( Ydata, Udata, Vdata, &( LRGB[pos * 3 + 2] ), + &( LRGB[pos * 3 + 1] ), &( LRGB[pos * 3] ) ); + } + } + //printf("Check the DPX header (ioN.c) \n"); getchar(); + + sprintf( frame_name, inname, index ); + + save_dpx_header( info, index ); // save the header from the original dpx file for the reconstructed frame + + write_dpx( frame_name, LRGB, info ); +#else + assert(0); +#endif + +#ifdef OUTPUT_RAS + unsigned char *RGBframe; + int data; + struct rasterfile header; + char rasname[250]; + + RGBframe = + ( unsigned char * )getarray( info.ywidth * info.yheight * 3, + sizeof( unsigned char ), "LRGB" ); + + strcpy( rasname, frame_name ); + strcat( rasname, ".ras" ); + + header = make_header( info.ywidth, info.yheight, RGBDATA ); + + switch ( info.coding_domain ) { + case VIDEO: + for( i = 0; i < info.ywidth * info.yheight * 3; i++ ) { + + data = nint( LRGB[i] * 255. / PEAK ); + if( data < 0 ) + RGBframe[i] = 0; + else if( data > 255 ) + RGBframe[i] = 255; + else + RGBframe[i] = data; + } + break; + + case LINEAR: // so we need to do Gamma correction + for( i = 0; i < info.ywidth * info.yheight * 3; i++ ) { + + LRGB[i] = LRGB[i] / PEAK; + if( LRGB[i] > 1 ) + LRGB[i] = 1; + else if( LRGB[i] < 0 ) + LRGB[i] = 0; + + data = nint( 255 * pow( LRGB[i], 1. / Gamma ) ); + if( data < 0 ) + RGBframe[i] = 0; + else if( data > 255 ) + RGBframe[i] = 255; + else + RGBframe[i] = data; + } + break; + + case LOG: + for( i = 0; i < info.ywidth * info.yheight * 3; i++ ) { + + //LRGB[i] = LRGB[i]*1023/PEAK; + + if( LRGB[i] < 0 ) + LRGB[i] = 0; + else if( LRGB[i] > 1023 ) + LRGB[i] = 1023; + + RGBframe[i] = nint( convertLOG( 255, LRGB[i], VIDEO ) ); + } + break; + + default: + printf( "coding_domain error (ioN.c)\n" ); + exit( 1 ); + } + + write_ras( rasname, header, RGBframe ); + + free( RGBframe ); +#endif + + free( LRGB ); + break; + + default: + printf( "image format error format = %d(ioN.c)\n", format ); + exit( 0 ); + + } + +} + +/*****************************************************************************/ +/* write_jp2k_frame() */ +/*****************************************************************************/ +void +write_jp2k_frame( YUVimage frame, videoinfo info, char *inname, int index, + enum FORMAT format ) +{ + FILE *fpio; + int i, size; + char frame_name[250]; + float *temp; +#ifdef SUPPORT_DPX + int j, pos; + float Ydata, Udata, Vdata; +#endif + float *LRGB = 0; + + switch ( format ) { + case RAS: + sprintf( frame_name, inname, index ); + yuv2ras( frame_name, info.ywidth, info.yheight, frame.Y, info.cwidth, + info.cheight, frame.U, frame.V ); + break; + + case YUV: + /* assume that the order of data file is Y[total], U[total], V[total] */ + if ((strchr (inname, '%'))!=0) + { + sprintf(frame_name, inname, index); + + if (!(fpio = fopen(frame_name, "wb"))) // open a new frame file + { + printf("write_frame: %s\n", frame_name); + exit(1); + } + } + else + { + if ( index == info.start ) // open new video file + { + if (!(fpio = fopen(inname, "wb"))) + { + printf("write_Video: %s\n", inname); + exit(1); + } + } + else // append new frame to existing video file + { + if (!(fpio = fopen(inname, "ab"))) + { + printf("write_Video: %s\n", inname); + exit(1); + } + } + } + + size = ( info.ywidth ) * ( info.yheight ); + temp = ( float * )calloc( size, sizeof( float ) ); + for( i = 0; i < size; i++ ) + temp[i] = ( frame.Y[i] ); + if( fwrite( temp, sizeof( float ), size, fpio ) != + ( size ) ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + + size = ( info.cwidth ) * ( info.cheight ); /* QUEST */ + for( i = 0; i < size; i++ ) + temp[i] = ( frame.U[i] ); + if( fwrite( temp, sizeof( float ), size, fpio ) != + ( size ) ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + + for( i = 0; i < size; i++ ) + temp[i] = ( frame.V[i] ); + if( fwrite( temp, sizeof( float ), size, fpio ) != + ( size ) ) { + printf( "error in write_frame()\n" ); + exit( 1 ); + } + free( temp ); + fclose( fpio ); + + break; + + case DPX: + +#ifdef DPX_SUPPORT + LRGB = + ( float * )getarray( info.ywidth * info.yheight * 3, sizeof( float ), + "LRGB" ); + + for( i = 0; i < info.yheight; i++ ) { + for( j = 0; j < info.ywidth; j++ ) { + pos = i * info.ywidth + j; + Ydata = frame.Y[pos]; + Udata = frame.U[pos]; + Vdata = frame.V[pos]; + /* YUV -> RGB */ + if( info.coding_domain != LOG ) { + Udata -= ( PEAK + 1 ) / 2.; + Vdata -= ( PEAK + 1 ) / 2.; + } else { + Udata -= 1024 / 2.; + Vdata -= 1024 / 2.; + } + YUV2RGB( Ydata, Udata, Vdata, &( LRGB[pos * 3 + 2] ), + &( LRGB[pos * 3 + 1] ), &( LRGB[pos * 3] ) ); + } + } + //printf("Check the DPX header (ioN.c) \n"); getchar(); + + sprintf( frame_name, inname, index ); + + save_dpx_header( info, index ); // save the header from the original dpx file for the reconstructed frame + + write_dpx( frame_name, LRGB, info ); +#else + assert(0); +#endif + +#ifdef OUTPUT_RAS + unsigned char *RGBframe; + int data; + struct rasterfile header; + char rasname[250]; + + RGBframe = + ( unsigned char * )getarray( info.ywidth * info.yheight * 3, + sizeof( unsigned char ), "LRGB" ); + + strcpy( rasname, frame_name ); + strcat( rasname, ".ras" ); + + header = make_header( info.ywidth, info.yheight, RGBDATA ); + + switch ( info.coding_domain ) { + case VIDEO: + for( i = 0; i < info.ywidth * info.yheight * 3; i++ ) { + + data = nint( LRGB[i] * 255. / PEAK ); + if( data < 0 ) + RGBframe[i] = 0; + else if( data > 255 ) + RGBframe[i] = 255; + else + RGBframe[i] = data; + } + break; + + case LINEAR: // so we need to do Gamma correction + for( i = 0; i < info.ywidth * info.yheight * 3; i++ ) { + + LRGB[i] = LRGB[i] / PEAK; + if( LRGB[i] > 1 ) + LRGB[i] = 1; + else if( LRGB[i] < 0 ) + LRGB[i] = 0; + + data = nint( 255 * pow( LRGB[i], 1. / Gamma ) ); + if( data < 0 ) + RGBframe[i] = 0; + else if( data > 255 ) + RGBframe[i] = 255; + else + RGBframe[i] = data; + } + break; + + case LOG: + for( i = 0; i < info.ywidth * info.yheight * 3; i++ ) { + + //LRGB[i] = LRGB[i]*1023/PEAK; + + if( LRGB[i] < 0 ) + LRGB[i] = 0; + else if( LRGB[i] > 1023 ) + LRGB[i] = 1023; + + RGBframe[i] = nint( convertLOG( 255, LRGB[i], VIDEO ) ); + } + break; + + default: + printf( "coding_domain error (ioN.c)\n" ); + exit( 1 ); + } + + write_ras( rasname, header, RGBframe ); + + free( RGBframe ); +#endif + + free( LRGB ); + break; + + default: + printf( "image format error format = %d(ioN.c)\n", format ); + exit( 0 ); + + } + +} + +void +scaling( int curr, YUVimage ** pyrTemp, YUVimage * pyrFrs, videoinfo info, + enum FLAG first_GOP, int remaining_frs ) +{ + int i, nfrs, t_level; + float weight; + + temporal_filter (); + t_level = MY_MIN (info.t_level, info.tPyrLev); + + if ( remaining_frs != 0 ){ + nfrs = info.GOPsz; + } else { + nfrs = info.eff_GOPsz; + } + nfrs = nfrs >> t_level; + if ( first_GOP == YES ) nfrs = 1; + + weight = ( float )pow( 1 / LPW4[1], t_level ); + + if( t_level < info.tPyrLev ) { + for( i = 0; i < nfrs; i++ ) { + wcopyframe( &pyrTemp[t_level][i], &pyrTemp[t_level][i], weight, info ); + } + } else { // t_level = info.tPyrLev + wcopyframe( &pyrFrs[0], &pyrFrs[0], weight, info ); + } +} + +void +write_GOP( int curr, YUVimage ** pyrTemp, YUVimage * pyrFrs, videoinfo info, + enum FLAG first_GOP, int remaining_frs ) +{ + int i, nfrs, dist, t_level; + + // assert (info.t_level <= info.tPyrLev); + + t_level = MY_MIN (info.t_level, info.tPyrLev); + dist = 1 << ( t_level ); + + if( info.tPyrLev > 0 && info.t_level > 0 ) + scaling( curr, pyrTemp, pyrFrs, info, first_GOP, remaining_frs ); + + if( t_level < info.tPyrLev ) { // default case + + if( first_GOP == YES ){ + write_frame( pyrTemp[t_level][0], info, info.decname, curr, info.format ); + } else { + if ( remaining_frs != 0 ){ + nfrs = info.GOPsz; + } else { + nfrs = info.eff_GOPsz; + } + + for( i = 0; i < nfrs >> t_level; i++ ) { + if ( (curr - info.GOPsz + (i+1) * dist) <= info.last ){ + write_frame( pyrTemp[t_level][i], info, info.decname, curr - info.GOPsz + (i+1) * dist, info.format ); + // printf(" write_frame( pyrTemp[%d][%d], curr - info.GOPsz + (i+1) * dist %d );\n", + // t_level, i, curr - info.GOPsz + (i+1) * dist ); + } + } + } + + } else { + if ( curr <= info.last ){ + write_frame( pyrFrs[0], info, info.decname, curr, info.format ); + } + } + +} + + +void rec_write_block_mode_motion_vector( vector_ptr fmv, int cx, int cy, + int xblk, int yblk, int hor, int ver, + int t_level, videoinfo info, FILE *fpmvio, int frame_type ) +{ + int xblock, yblock; + + if( fmv->child ) { + rec_write_block_mode_motion_vector( fmv->child0, cx, cy, + xblk/2, yblk/2, hor, ver, t_level, info, fpmvio, frame_type ); + + rec_write_block_mode_motion_vector( fmv->child1, cx+xblk/2, cy, + xblk/2, yblk/2, hor, ver, t_level, info, fpmvio, frame_type ); + + rec_write_block_mode_motion_vector( fmv->child2, cx, cy+yblk/2, + xblk/2, yblk/2, hor, ver, t_level, info, fpmvio, frame_type ); + + rec_write_block_mode_motion_vector( fmv->child3, cx+xblk/2, cy+yblk/2, + xblk/2, yblk/2, hor, ver, t_level, info, fpmvio, frame_type ); + + } else { + /* consider the small block around the boundaries */ + xblock = ( cx + xblk <= hor ) ? xblk : hor - cx; + yblock = ( cy + yblk <= ver ) ? yblk : ver - cy; + + if( xblock <= 0 || yblock <= 0 ) return; + + // the format of block_mode_motion_info file + fprintf(fpmvio, "%d\t %d\t %d\t %d\t %d\t", cx, cy, xblock, yblock, fmv->bi_mode); + if (frame_type==1 || frame_type==2) // uni-left or uni-right + { + if ( fmv->bi_mode != DIRECTIONAL_IBLOCK ) + // indicator of mv, mvx, mvy + fprintf(fpmvio, "%d\t %f\t %f\n", 1, fmv->mvx, fmv->mvy); + else + fprintf(fpmvio, "%d\t %f\t %f\n", 0, fmv->iblock_spatial_mode*1.0, 0); + } + + if (frame_type==0) // bi-directional + { + if ( fmv->lifting_mode==CONNECTED || fmv->lifting_mode==PREDICTED ) + fprintf(fpmvio, "%d\t %f\t %f\n", 1, fmv->mvx, fmv->mvy); + else if ( fmv->lifting_mode==SPATIAL_PREDICTED) + fprintf(fpmvio, "%d\t %f\t %f\n", 0, fmv->iblock_spatial_mode*1.0, 0); + else + fprintf(fpmvio, "%d\t %f\t %f\n", 0, 0, 0); + } + + } +} + + +void write_block_mode_motion_vector(char *direction, int GOP_counter, int count, int frame_type, + vector_ptr fmv, videoinfo info, int t_level) +{ + + int x, y, X, Y, yhor, yver; + int xnum, ynum, xblk, yblk; + char file_name[80]; + FILE *fpmvio; + + sprintf(file_name, "%s_block_mode_mv_GOP%03d_count%03d_frametype%1d.txt", + direction, GOP_counter, count, frame_type); + fpmvio = fopen(file_name, "wt"); + yhor = info.ywidth; + yver = info.yheight; + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) { + rec_write_block_mode_motion_vector( &fmv[Y * xnum + X], x, y, xblk, yblk, yhor, yver, + t_level, info, fpmvio, frame_type ); + } + } + fclose(fpmvio); + +} + + + +// write high temporal frames into files +void write_frame_into_file(YUVimage frame, videoinfo info, int index, int GOP_counter) +{ + char framenameY[80], framenameU[80], framenameV[80]; + int x, y, yhor, yver; + FILE *fpimgY, *fpimgU, *fpimgV; + + yhor = info.ywidth; yver = info.yheight; + + // write high temporal frame into text file to have a look + sprintf(framenameY, "highframeY_GOP%03d_index%d.txt", GOP_counter, index); + sprintf(framenameU, "highframeU_GOP%03d_index%d.txt", GOP_counter, index); + sprintf(framenameV, "highframeV_GOP%03d_index%d.txt", GOP_counter, index); + fpimgY = fopen( framenameY, "wt"); + fpimgU = fopen( framenameU, "wt"); + fpimgV = fopen( framenameV, "wt"); + for (y=0; y + +#define SELECT_MERGE_BLOCK 32 +#define MV_MERGE_THRESH 7 +#define MERGENCE_DEBUG + +inline float median(float a, float b, float c) +{ + return ((a>b) ? ((a>c) ? ((b>c) ? b : c) : a) : + ((b>c) ? ((a>c) ? a : c) : b)); +} + + +void +replace_enhancement_mv_subtree( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count, float sample_mvx, float sample_mvy ) +{ + int cx, cy; + + if (!fmv1->child) + { + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + fmv1->mvx = sample_mvx; fmv1->mvy = sample_mvy; + }else + { + cx = x; + cy = y; + replace_enhancement_mv_subtree( fmv1_array, fmv2_array, fmv1->child0, fmv2? fmv2->child0:NULL, + pmvx, pmvy, num_symbol, subpel, + cx, cy, xblk/2, yblk/2, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, + blk_thresh, count, sample_mvx, sample_mvy ); + cx = x + xblk / 2; + cy = y; + replace_enhancement_mv_subtree( fmv1_array, fmv2_array, fmv1->child1, fmv2? fmv2->child1:NULL, + pmvx, pmvy, num_symbol, subpel, + cx, cy, xblk/2, yblk/2, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, + blk_thresh, count, sample_mvx, sample_mvy ); + cx = x; + cy = y + yblk / 2; + replace_enhancement_mv_subtree( fmv1_array, fmv2_array, fmv1->child2, fmv2? fmv2->child2:NULL, + pmvx, pmvy, num_symbol, subpel, + cx, cy, xblk/2, yblk/2, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, + blk_thresh, count, sample_mvx, sample_mvy ); + cx = x + xblk / 2; + cy = y + yblk / 2; + replace_enhancement_mv_subtree( fmv1_array, fmv2_array, fmv1->child3, fmv2? fmv2->child3:NULL, + pmvx, pmvy, num_symbol, subpel, + cx, cy, xblk/2, yblk/2, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, + blk_thresh, count, sample_mvx, sample_mvy ); + } +} + + +void +replace_enhancement_mv_further( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int cx, cy; + + if( fmv1->child && xblk>blk_thresh ) { + cx = x; + cy = y; + replace_enhancement_mv_further(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + replace_enhancement_mv_further(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + replace_enhancement_mv_further(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + replace_enhancement_mv_further(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) return; + + if (!fmv1->mv_exist) return; + + // irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child) + return; + + if ( fmv1->child && fmv1->mv_exist && fmv1->merge_sign ) + replace_enhancement_mv_subtree(fmv1_array, fmv2_array, fmv1, fmv2 , + pmvx, pmvy, num_symbol, subpel, x, y, xblk, yblk, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count, + fmv1->sample_mvx, fmv1->sample_mvy); + + } +} + + +void +replace_enhancement_mv( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int cx, cy; + + if( fmv1->child && xblk>blk_thresh ) { + cx = x; + cy = y; + replace_enhancement_mv(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + replace_enhancement_mv(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + replace_enhancement_mv(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + replace_enhancement_mv(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) return; + + if (!fmv1->mv_exist) return; + + if ( fmv1->child && fmv1->mv_exist && fmv1->merge_sign ) + replace_enhancement_mv_subtree(fmv1_array, fmv2_array, fmv1, fmv2 , + pmvx, pmvy, num_symbol, subpel, x, y, xblk, yblk, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count, + fmv1->sample_mvx, fmv1->sample_mvy); + + if (fmv1->child && fmv1->mv_exist && !fmv1->merge_sign) + { + replace_enhancement_mv_further( fmv1_array, fmv2_array, fmv1, fmv2, + pmvx, pmvy, num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, blk_thresh/2, count ); + + } + + } + +} + + +// 就是进行了一些设置fmv->mv_exist、 fmv->sample_mvx、 fmv->sample_mvy +// recursively visit the child, do the subsampling 递归访问孩子,做下采样 +// we subsmaple for blocks with size ( blk_thresh x blk_thresh ) +void scalable_quad_tree_child(vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, int blk_thresh) +{ + // blkszie>blk_thresh and have children 有孩子且块大于阈值 + if(fmv->child && yblk>blk_thresh && xblk>blk_thresh){ // there are children and blksize>blk_thresh + scalable_quad_tree_child(fmv->child0, cx, cy, xblk/2, yblk/2, hor, ver, blk_thresh); + scalable_quad_tree_child(fmv->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, ver, blk_thresh); + scalable_quad_tree_child(fmv->child2, cx, cy+yblk/2, xblk/2, yblk/2, hor, ver, blk_thresh); + scalable_quad_tree_child(fmv->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, ver, blk_thresh); + } + else{ + if (cx >= hor || cy >= ver) return; // boundary check 边界返回 + + // blksize>blk_thresh and have no children 块大但是没有孩子,返回 + if (!(fmv->child) && yblk>blk_thresh && xblk>blk_thresh ) return; + + // blksize==blk_thresh and no children 相同大小但是没有孩子 + if (!(fmv->child) && yblk==blk_thresh && xblk==blk_thresh ){ + fmv->mv_exist = 0; + // there is motion vector for this block on this side + if ( fmv->lifting_mode != IGNORED && fmv->bi_mode != DIRECTIONAL_IBLOCK) + { + fmv->mv_exist = 1; + fmv->sample_mvx = fmv->mvx; + fmv->sample_mvy = fmv->mvy; + } + return; + } + + // blksize==blk_thresh and have children 剩下的最后一种情况 块大小相同但是有孩子 + fmv->mv_exist = 0; + // child0: + if ( !(cx >= hor || cy >= ver) ) // boundary check for the child0 + { + // there is motion vector on this side for child0 + if ( fmv->child0->mv_exist ) + { + fmv->mv_exist = 1; + fmv->sample_mvx = fmv->child0->sample_mvx; + fmv->sample_mvy = fmv->child0->sample_mvy; + return; + } + + } + + // child1: + if ( !(cx+xblk/2>=hor || cy >=ver) ) // boundary check for the child1 + { + // there is motion vector on this side for child1 + if ( fmv->child1->mv_exist ) + { + fmv->mv_exist = 1; + fmv->sample_mvx = fmv->child1->sample_mvx; + fmv->sample_mvy = fmv->child1->sample_mvy; + return; + } + } + + // child2: + if ( !(cx >= hor || cy+yblk/2>ver) ) // boundary check for the child2 + { + // there is motion vector on this side for child0 + if ( fmv->child2->mv_exist ) + { + fmv->mv_exist = 1; + fmv->sample_mvx = fmv->child2->sample_mvx; + fmv->sample_mvy = fmv->child2->sample_mvy; + return; + } + } + + // child3: + if ( !(cx+xblk/2>=hor || cy+yblk/2>=ver) ) // boundary check for the child3 + { + // there is motion vector on this side for child0 + if ( fmv->child3->mv_exist ) + { + fmv->mv_exist = 1; + fmv->sample_mvx = fmv->child3->sample_mvx; + fmv->sample_mvy = fmv->child3->sample_mvy; + return; + } + } + } +} + + +void whether_merge_this_sub_tree(vector_ptr fmv, int cx, int cy, int xblk, int yblk, int hor, int ver, + int *merge_sign, float sample_mvx, float sample_mvy, + int *sub_blocks, float scale_factor, + int tlevel, int tindex, int blk_thresh) +{ + if (fmv->child) + { + whether_merge_this_sub_tree(fmv->child0, cx, cy, xblk/2, yblk/2, hor, ver, merge_sign, + sample_mvx, sample_mvy, sub_blocks, scale_factor, + tlevel, tindex, blk_thresh); + whether_merge_this_sub_tree(fmv->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, ver, merge_sign, + sample_mvx, sample_mvy, sub_blocks, scale_factor, + tlevel, tindex, blk_thresh); + whether_merge_this_sub_tree(fmv->child2, cx , cy+yblk/2, xblk/2, yblk/2, hor, ver, merge_sign, + sample_mvx, sample_mvy, sub_blocks, scale_factor, + tlevel, tindex, blk_thresh); + whether_merge_this_sub_tree(fmv->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, ver, merge_sign, + sample_mvx, sample_mvy, sub_blocks, scale_factor, + tlevel, tindex, blk_thresh); + } + else + { + if (cx>=hor || cy>=ver) return; + + (*sub_blocks)++; + + if ((fmv->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + +#ifdef MERGENCE_DEBUG + FILE *fsub_tree; + char subtree_file[80]; + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, tlevel, tindex); + fsub_tree = fopen(subtree_file, "at"); + fprintf(fsub_tree, "x=%d\t y=%d blk=%d\t mvx=%.2f\t mvy=%.2f\n", + cx, cy, xblk, fmv->mvx, fmv->mvy); + fclose(fsub_tree); +#endif + + if (fabs(fmv->mvx - sample_mvx)>MV_MERGE_THRESH*scale_factor || + fabs(fmv->mvy - sample_mvy)>MV_MERGE_THRESH*scale_factor ) + *merge_sign = 0; + return; + } +} + +// selectively merge quad-treee +void select_merge_quad_tree_child_further(vector_ptr fmv, int cx, int cy, int xblk, int yblk, + int hor, int ver, int *merge_block_num2, int *checked_block2, + int blk_thresh, int tlevel, int tindex) +{ + int merge_sign, sub_blocks; + + // if a child is NULL, then there is nothing to do + // there is children and blksize>blk_thresh + if(fmv->child && yblk>blk_thresh && xblk>blk_thresh){ + select_merge_quad_tree_child_further(fmv->child0, cx, cy, xblk/2, yblk/2, hor, ver, + merge_block_num2, checked_block2, blk_thresh, tlevel, tindex); + select_merge_quad_tree_child_further(fmv->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, ver, + merge_block_num2, checked_block2, blk_thresh, tlevel, tindex); + select_merge_quad_tree_child_further(fmv->child2, cx, cy+yblk/2, xblk/2, yblk/2, hor, ver, + merge_block_num2, checked_block2, blk_thresh, tlevel, tindex); + select_merge_quad_tree_child_further(fmv->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, ver, + merge_block_num2, checked_block2, blk_thresh, tlevel, tindex); + } + else{ + if (cx >= hor || cy >= ver) return; + + // blksize>=blk_threh but no children + if (!(fmv->child)) return; // motion vectors in base layer + +#ifdef MERGENCE_DEBUG + FILE *fsub_tree; + char subtree_file[80]; + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, tlevel, tindex); + fsub_tree = fopen(subtree_file, "at"); + fprintf(fsub_tree, "checking subtree x=%d\t y=%d blk=%d\n", cx, cy, xblk); + fclose(fsub_tree); +#endif + + // irregular motion area + if ( fmv->child0->child || fmv->child1->child || + fmv->child2->child || fmv->child3->child) + return; + + (*checked_block2)++; + merge_sign = 1; + if (fmv->mv_exist) // check whether the block is allowed to do subsampling for motion vectors + { + sub_blocks = 0; + whether_merge_this_sub_tree(fmv, cx, cy, xblk, yblk, hor, ver, &merge_sign, + fmv->sample_mvx, fmv->sample_mvy, &sub_blocks, 1.5, + tlevel, tindex, blk_thresh); + }else + { +#ifdef MERGENCE_DEBUG + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, tlevel, tindex); + fsub_tree = fopen(subtree_file, "at"); + fprintf(fsub_tree, "NO motion vector in this subtree\n\n\n"); + fclose(fsub_tree); +#endif + fmv->merge_sign = 0; + return; + } + +#ifdef MERGENCE_DEBUG + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, tlevel, tindex); + fsub_tree = fopen(subtree_file, "at"); + if (merge_sign) + fprintf(fsub_tree, "subtree MERGED\n"); + else + fprintf(fsub_tree, "subtree NOT MERGED\n"); + fprintf(fsub_tree, "\n\n"); + fclose(fsub_tree); +#endif + + fmv->merge_sign = merge_sign; // the final decision whether merge this sub-tree + if (merge_sign) + (*merge_block_num2)++; + + } +} + + +// selectively merge quad treee +void select_merge_quad_tree_child(vector_ptr fmv, int cx, int cy, int xblk, int yblk, int hor, int ver, + int *merge_block_num, int *merge_block_num2,int *checked_block1, + int *checked_block2, int blk_thresh, int t_level, int tindex) +{ + int merge_sign, sub_blocks; + + // there is children and blksize>blk_thresh + if(fmv->child && yblk>blk_thresh && xblk>blk_thresh){ + select_merge_quad_tree_child(fmv->child0, cx, cy, xblk/2, yblk/2, hor, ver, + merge_block_num, merge_block_num2, checked_block1, checked_block2, + blk_thresh, t_level, tindex); + select_merge_quad_tree_child(fmv->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, ver, + merge_block_num, merge_block_num2, checked_block1, checked_block2, + blk_thresh, t_level, tindex); + select_merge_quad_tree_child(fmv->child2, cx, cy+yblk/2, xblk/2, yblk/2, hor, ver, + merge_block_num, merge_block_num2, checked_block1, checked_block2, + blk_thresh, t_level, tindex); + select_merge_quad_tree_child(fmv->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, ver, + merge_block_num, merge_block_num2, checked_block1, checked_block2, + blk_thresh, t_level, tindex); + } + else{ + if (cx >= hor || cy >= ver) return; + + // blksize>=blk_threh but no children + if (!(fmv->child)) return; // motion vectors in base layer + +#ifdef MERGENCE_DEBUG + FILE *fsub_tree; + char subtree_file[80]; + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, t_level, tindex); + fsub_tree = fopen(subtree_file, "at"); + fprintf(fsub_tree, "checking subtree x=%d\t y=%d blk=%d\n", cx, cy, xblk); + fclose(fsub_tree); +#endif + + merge_sign = 1; + if (fmv->mv_exist) // check whether the block is allowed to do subsampling + { + sub_blocks = 0; + whether_merge_this_sub_tree(fmv, cx, cy, xblk, yblk, hor, ver, &merge_sign, + fmv->sample_mvx, fmv->sample_mvy, &sub_blocks, 1.0, + t_level, tindex, blk_thresh); + }else + { +#ifdef MERGENCE_DEBUG + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, t_level, tindex); + fsub_tree = fopen(subtree_file, "at"); + fprintf(fsub_tree, "NO motion vector in this subtree\n\n\n"); + fclose(fsub_tree); +#endif + fmv->merge_sign = 0; + return; + } + +#ifdef MERGENCE_DEBUG + sprintf(subtree_file, "subtree%d_i%d_j%d.txt", blk_thresh, t_level, tindex); + fsub_tree = fopen(subtree_file, "at"); + if (merge_sign) + fprintf(fsub_tree, "subtree MERGED\n"); + else + fprintf(fsub_tree, "subtree NOT MERGED\n"); + fprintf(fsub_tree, "\n\n"); + fclose(fsub_tree); +#endif + + fmv->merge_sign = merge_sign; // the final decision whether merge this sub-tree + if (merge_sign) + { // for statistical use + *merge_block_num += sub_blocks; + (*checked_block1)++; // merged blk_thresh x blk_thresh blocks + }else + { + select_merge_quad_tree_child_further(fmv, cx, cy, xblk, yblk, hor, ver, + merge_block_num2, checked_block2, blk_thresh/2, t_level, tindex); + + } + + } +} + + +// motion vector subsample from 4x4->8x8->16x16->32x32 +// there is no redundunt motion vector for coding 编码不需要冗余的运动向量 就是设置了一些变量 +void layer_structure_mv_subsample(videoinfo info, int t_level, int tindex, vector_ptr fmv, int encoder_side) +{ + + int i, x, y, X, Y, xnum, ynum, xblk, yblk, hor, ver, blk_thresh; + int merge_block_num, merge_block_num2, checked_block1, checked_block2, total_blk_thresh; + + if (!info.layer_mv[t_level]) return; // no layer structure for this temporal level + + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + hor = info.ywidth; + ver = info.yheight; + + // recursively subsample motion vectors from bottom to top, i.e. 4x4->8x8->16x16->32x32 递归的 + for (i=0; i<4; i++) + { + blk_thresh = 4*(1<blk_thresh and have children + if(fmv->child){ // there are children and blksize>blk_thresh + recursive_layer_structure_mv_trim(fmv->child0, cx, cy, xblk/2, yblk/2, hor, ver); + recursive_layer_structure_mv_trim(fmv->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, ver); + recursive_layer_structure_mv_trim(fmv->child2, cx, cy+yblk/2, xblk/2, yblk/2, hor, ver); + recursive_layer_structure_mv_trim(fmv->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, ver); + } + else{ + if (cx >= hor || cy >= ver) return; // boundary check + + if ((fmv->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + + // trim the replaced motion vector, and make it in the frame boundary + xblk2 = ( cx + xblk <= hor ) ? xblk : hor - cx; + yblk2 = ( cy + yblk <= ver ) ? yblk : ver - cy; + if (cx + xblk2 - fmv->mvx > hor ) + fmv->mvx = (float) ( hor - (cx+xblk2)); + if ( cx-fmv->mvx<0) + fmv->mvx = (float) cx; + if ( cy+yblk2-fmv->mvy > ver ) + fmv->mvy = (float) (ver- (cy+yblk2)); + if ( cy-fmv->mvy<0) + fmv->mvy = (float) cy; + + } +} + + +void layer_structure_mv_trim(videoinfo info, int t_level, int tindex, vector_ptr fmv, int count) +{ + + int x, y, X, Y, xnum, ynum, xblk, yblk, hor, ver; + + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + hor = info.ywidth; + ver = info.yheight; + + // recursively trim the replaced motion vectors + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) { + recursive_layer_structure_mv_trim(fmv+Y*xnum+X, x, y, xblk, yblk, hor, ver); + } + } +} + + +void clear_frame_motion_field(FRAME_MOTION_FIELD *frame_motion_field, videoinfo info) +{ + int i, j; + for (i=0; ibi_mode <= 6 && fmv->bi_mode >= 0) || fmv->bi_mode == 8 || (fmv->bi_mode == 7 && fmv->aff_mrg == NO) ){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].available = 1; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = dmvx; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = dmvy; + frame_motion_field[(y+j)*info.ywidth+(x+i)].mvx = mvx; + frame_motion_field[(y+j)*info.ywidth+(x+i)].mvy = mvy; + } + else if( (fmv->bi_mode <= 11 && fmv->bi_mode >= 9) || (fmv->bi_mode == 7 && fmv->aff_mrg == YES) ){ + + if( (i+1)/xblk2 == 1 ) + addx = 1; + else + addx = 0; + + if( (j+1)/yblk2 == 1 ) + addy = 1; + else + addy = 0; + + frame_motion_field[(y+j)*info.ywidth+(x+i)].available = 1; + frame_motion_field[(y+j)*info.ywidth+(x+i)].mvx = (fmv->aff2_mvx - fmv->aff1_mvx)*(i + addx)/xblk2 + (fmv->aff3_mvx - fmv->aff1_mvx)*(j + addy)/yblk2 + fmv->aff1_mvx; + frame_motion_field[(y+j)*info.ywidth+(x+i)].mvy = (fmv->aff2_mvy - fmv->aff1_mvy)*(i + addx)/xblk2 + (fmv->aff3_mvy - fmv->aff1_mvy)*(j + addy)/yblk2 + fmv->aff1_mvy; + + if(fmv->bi_mode == 7 && fmv->aff_mrg == YES){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = 0; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = 0; + }else if(fmv->direct_idx == DIRECT ){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = 0; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = 0; + } + else if(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE && fmv->merge_dir == UP){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = (0 - 0)*((float)i)/((float)xblk2) + (fmv->aff3_dmvx - 0)*((float)j)/((float)yblk2) + 0; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = (0 - 0)*((float)i)/((float)xblk2) + (fmv->aff3_dmvy - 0)*((float)j)/((float)yblk2) + 0; + } + else if(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE && fmv->merge_dir == LEFT){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = (fmv->aff2_dmvx - 0)*((float)i)/((float)xblk2) + (0 - 0)*((float)j)/((float)yblk2) + 0; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = (fmv->aff2_dmvy - 0)*((float)i)/((float)xblk2) + (0 - 0)*((float)j)/((float)yblk2) + 0; + } + else if(fmv->direct_idx == INDIRECT && fmv->merge_idx == INTER){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = (fmv->aff2_dmvx - fmv->aff1_dmvx)*((float)i)/((float)xblk2) + (fmv->aff3_dmvx - fmv->aff1_dmvx)*((float)j)/((float)yblk2) + fmv->aff1_dmvx; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = (fmv->aff2_dmvy - fmv->aff1_dmvy)*((float)i)/((float)xblk2) + (fmv->aff3_dmvy - fmv->aff1_dmvy)*((float)j)/((float)yblk2) + fmv->aff1_dmvy; + } + else if(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE && fmv->merge_dir == PAL_L ){ + if(fmv->aff_idx >= 0){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = (fmv->aff2_dmvx - fmv->aff1_dmvx)*((float)i)/((float)xblk2) + (fmv->aff3_dmvx - fmv->aff1_dmvx)*((float)j)/((float)yblk2) + fmv->aff1_dmvx; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = (fmv->aff2_dmvy - fmv->aff1_dmvy)*((float)i)/((float)xblk2) + (fmv->aff3_dmvy - fmv->aff1_dmvy)*((float)j)/((float)yblk2) + fmv->aff1_dmvy; + }else{ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = 0; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = 0; + } + } + else if(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE && fmv->merge_dir == TRAN_P ){ + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvx = (fmv->aff2_dmvx - fmv->aff1_dmvx)*((float)i)/((float)xblk2) + (fmv->aff3_dmvx - fmv->aff1_dmvx)*((float)j)/((float)yblk2) + fmv->aff1_dmvx; + frame_motion_field[(y+j)*info.ywidth+(x+i)].dmvy = (fmv->aff2_dmvy - fmv->aff1_dmvy)*((float)i)/((float)xblk2) + (fmv->aff3_dmvy - fmv->aff1_dmvy)*((float)j)/((float)yblk2) + fmv->aff1_dmvy; + }else + assert(0); + }else + assert(0); + } +} + +///////////// Added on 02.20.2016 //////////////////// +void copy_frame_motion_field( FRAME_MOTION_FIELD *src_frame_motion_field, SIMP_FRAME_MOTION_FIELD *dest_frame_motion_field, videoinfo info ){ + int i,j; + + for (i=0; i= 0 && x_pos < hor && y_pos >= 0 && y_pos < ver); + + //Modified by Yuan Liu on 01.12.2016 regarding the subpel accuracy part of median prediction + + // try to get predictors for blocks A, B, and C + // A + x_dest = x_pos - 1; + y_dest = y_pos + yblock - 1; + if (x_dest < 0 || y_dest >= ver) { + is_pred_a = 0; + } else { + is_pred_a = frame_motion_field[y_dest*hor+x_dest].available; + if ( is_pred_a ) + { + mvx_a = frame_motion_field[y_dest*hor+x_dest].mvx; + mvy_a = frame_motion_field[y_dest*hor+x_dest].mvy; + + mvx_a = mvx_a * (1 << subpel); + mvy_a = mvy_a * (1 << subpel); + + it_mvx = (int)(mvx_a); + it_mvy = (int)(mvy_a); + + mvx_a = (float)(it_mvx); + mvy_a = (float)(it_mvy); + + mvx_a = mvx_a / (1 << subpel); + mvy_a = mvy_a / (1 << subpel); + + } + } + + // B + y_dest = y_pos - 1; + x_dest = x_pos + xblock - 1; + if (y_dest < 0 || x_dest >= hor) { + is_pred_b = 0; + } else { + is_pred_b = frame_motion_field[y_dest*hor+x_dest].available; + if ( is_pred_b ) + { + mvx_b = frame_motion_field[y_dest*hor+x_dest].mvx; + mvy_b = frame_motion_field[y_dest*hor+x_dest].mvy; + + mvx_b = mvx_b * (1 << subpel); + mvy_b = mvy_b * (1 << subpel); + + it_mvx = (int)(mvx_b); + it_mvy = (int)(mvy_b); + + mvx_b = (float)(it_mvx); + mvy_b = (float)(it_mvy); + + mvx_b = mvx_b / (1 << subpel); + mvy_b = mvy_b / (1 << subpel); + + } + } + + // C + x_dest = x_pos - 1; + y_dest = y_pos - 1; + if (x_dest < 0 || y_dest < 0) { + is_pred_c = 0; + } else { + is_pred_c = frame_motion_field[y_dest*hor+x_dest].available; + if ( is_pred_c ) + { + mvx_c = frame_motion_field[y_dest*hor+x_dest].mvx; + mvy_c = frame_motion_field[y_dest*hor+x_dest].mvy; + + mvx_c = mvx_c * (1 << subpel); + mvy_c = mvy_c * (1 << subpel); + + it_mvx = (int)(mvx_c); + it_mvy = (int)(mvy_c); + + mvx_c = (float)(it_mvx); + mvy_c = (float)(it_mvy); + + mvx_c = mvx_c / (1 << subpel); + mvy_c = mvy_c / (1 << subpel); + } + } + + // blocks A, B, and C available? + if (is_pred_a == 1 && is_pred_b == 1 && is_pred_c == 1) { + pmvx[0] = mvx_a; + pmvy[0] = mvy_a; + pmvx[1] = mvx_b; + pmvy[1] = mvy_b; + pmvx[2] = mvx_c; + pmvy[2] = mvy_c; + } else { +// try to get predictor for block D +// D + x_dest = x_pos + xblock; + y_dest = y_pos - 1; + if (x_dest >= hor || y_dest < 0) { + is_pred_d = 0; + } else { + is_pred_d = frame_motion_field[y_dest*hor+x_dest].available; + if ( is_pred_d ) + { + mvx_d = frame_motion_field[y_dest*hor+x_dest].mvx; + mvy_d = frame_motion_field[y_dest*hor+x_dest].mvy; + + mvx_d = mvx_d * (1 << subpel); + mvy_d = mvy_d * (1 << subpel); + + it_mvx = (int)(mvx_d); + it_mvy = (int)(mvy_d); + + mvx_d = (float)(it_mvx); + mvy_d = (float)(it_mvy); + + mvx_d = mvx_d / (1 << subpel); + mvy_d = mvy_d / (1 << subpel); + + } + } + +//////////////////// Added by Yuan Liu //////////////////// + if(is_pred_a == 1){ + pmvx[0] = mvx_a; + pmvy[0] = mvy_a; + } + if(is_pred_b == 1){ + pmvx[1] = mvx_b; + pmvy[1] = mvy_b; + } + if(is_pred_c == 1){ + pmvx[2] = mvx_c; + pmvy[2] = mvy_c; + } + if(is_pred_d == 1){ + pmvx[3] = mvx_d; + pmvy[3] = mvy_d; + } +//////////////////////////////////////////////////////////////// + } + + // check if predictor points outside the reference frame + // only use integer part of the prediction motion vector for checking + // which means sub-pixel distance such as 0.25, 0.50 and 0.75 beyond the + // boundary is allowed. + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + + ////////////// Added on 02.02.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 3); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + assert(pmvx[3] == (float)HUGE_VAL && pmvy[3] == (float)HUGE_VAL); +////////////////////////////////////////////////////////////// + //Set median prediction candidate if available + if(pmvx[0] != (float)HUGE_VAL && pmvy[0] != (float)HUGE_VAL && pmvx[1] != (float)HUGE_VAL && pmvy[1] != (float)HUGE_VAL + && pmvx[2] != (float)HUGE_VAL && pmvy[2] != (float)HUGE_VAL){ + pmvx[3] = median( pmvx[0],pmvx[1],pmvx[2]); + pmvy[3] = median( pmvy[0],pmvy[1],pmvy[2]); + } + + ////////////////////////////////////////////////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + + ////////////// Added on 02.21.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + +// if(pmvx[3]==(float)HUGE_VAL && pmvy[3]==(float)HUGE_VAL && pmvx[2]!=(float)HUGE_VAL && pmvy[2]!=(float)HUGE_VAL){ +// assert( pmvx[0]!=(float)HUGE_VAL && pmvy[0]!=(float)HUGE_VAL && pmvx[1]!=(float)HUGE_VAL && pmvy[1]!=(float)HUGE_VAL ); + for(count = 0; count <= 3; count++){ + if(pmvx[count] == (float)HUGE_VAL && pmvy[count] == (float)HUGE_VAL){ + x_dest = x_pos; + y_dest = y_pos; + if (x_dest < 0 || y_dest < 0) { + assert(0); + } else { + is_pred_tmp = prev_frame_motion_field[y_dest*hor+x_dest].available; + if(is_pred_tmp == 1){ + mvx_tmp = prev_frame_motion_field[y_dest*hor+x_dest].mvx; + mvy_tmp = prev_frame_motion_field[y_dest*hor+x_dest].mvy; + + mvx_tmp = mvx_tmp * (1 << subpel); + mvy_tmp = mvy_tmp * (1 << subpel); + + it_mvx = (int)(mvx_tmp); + it_mvy = (int)(mvy_tmp); + + mvx_tmp = (float)(it_mvx); + mvy_tmp = (float)(it_mvy); + + mvx_tmp = mvx_tmp / (1 << subpel); + mvy_tmp = mvy_tmp / (1 << subpel); + + if(mvx_tmp != (float)HUGE_VAL && mvy_tmp != (float)HUGE_VAL){ + pmvx[count] = mvx_tmp; + pmvy[count] = mvy_tmp; + } + } + } + break; + } + } + +//////////////////////////////////////////////////////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + + ////////////// Added on 02.27.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } +////////////////////////////////////////////////////////////// + for(count = 0; count <= 3; count++){ + if(pmvx[count] == (float)HUGE_VAL && pmvy[count] == (float)HUGE_VAL){ + x_dest = x_pos - 1; + y_dest = y_pos + yblock; + if (x_dest < 0 || y_dest >= ver) { + is_pred_e = 0; + } else { + is_pred_e = frame_motion_field[y_dest*hor+x_dest].available; + if ( is_pred_e == 1 ) + { + mvx_e = frame_motion_field[y_dest*hor+x_dest].mvx; + mvy_e = frame_motion_field[y_dest*hor+x_dest].mvy; + + mvx_e = mvx_e * (1 << subpel); + mvy_e = mvy_e * (1 << subpel); + + it_mvx = (int)(mvx_e); + it_mvy = (int)(mvy_e); + + mvx_e = (float)(it_mvx); + mvy_e = (float)(it_mvy); + + mvx_e = mvx_e / (1 << subpel); + mvy_e = mvy_e / (1 << subpel); + + if(mvx_e != (float)HUGE_VAL && mvy_e != (float)HUGE_VAL){ + pmvx[count] = mvx_e; + pmvy[count] = mvy_e; + } + } + } + break; + } + } + +//////////////////////////////////////////////////////////////////// + for(i = 0; i <= 3; i++){ + if (x_pos - (int)(pmvx[i]) < 0 || x_pos - (int)(pmvx[i]) + xblock > hor || + y_pos - (int)(pmvy[i]) < 0 || y_pos - (int)(pmvy[i]) + yblock > ver) { + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + + ////////////// Added on 02.27.2016 ///////////////////////// + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if(pmvx[i] == pmvx[k] && pmvy[i] == pmvy[k] && pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + pmvx[i] = (float)HUGE_VAL; + pmvy[i] = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if(pmvx[i] != (float)HUGE_VAL && pmvy[i] != (float)HUGE_VAL){ + med_px[k] = pmvx[i]; + med_py[k] = pmvy[i]; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + pmvx[i] = med_px[i]; + pmvy[i] = med_py[i]; + } + for(i=0;i<=3;i++){ + med_px[i] = (float)HUGE_VAL; + med_py[i] = (float)HUGE_VAL; + } + +} + + +void ec_get_contexts_motion_field(int *ctx_x, int *ctx_y, FRAME_MOTION_FIELD *frame_motion_field, + int x, int y, videoinfo info, int t_level, int blk_thresh) +{ + float dmvx_hor, dmvy_hor, dmvx_ver, dmvy_ver, dmvx_dia, dmvy_dia; + int ispred_hor, ispred_ver, ispred_dia; + float e_x, e_y; + + if (x-1>=0) + { + ispred_hor = frame_motion_field[y*info.ywidth+(x-1)].available; + if ( ispred_hor ) + { + dmvx_hor = frame_motion_field[y*info.ywidth+(x-1)].dmvx; + dmvy_hor = frame_motion_field[y*info.ywidth+(x-1)].dmvy; + } + }else + ispred_hor = 0; + + if (y-1>=0) + { + ispred_ver = frame_motion_field[(y-1)*info.ywidth+x].available; + if ( ispred_ver ) + { + dmvx_ver = frame_motion_field[(y-1)*info.ywidth+x].dmvx; + dmvy_ver = frame_motion_field[(y-1)*info.ywidth+x].dmvy; + } + }else + ispred_ver = 0; + + if ( x-1>=0 && y-1>=0) + { + ispred_dia = frame_motion_field[(y-1)*info.ywidth+(x-1)].available; + if ( ispred_dia ) + { + dmvx_dia = frame_motion_field[(y-1)*info.ywidth+(x-1)].dmvx; + dmvy_dia = frame_motion_field[(y-1)*info.ywidth+(x-1)].dmvy; + } + }else + ispred_dia = 0; + + if(ispred_hor == 0) dmvx_hor = dmvy_hor = 0.; + if(ispred_ver == 0) dmvx_ver = dmvy_ver = 0.; + if(ispred_dia == 0) dmvx_dia = dmvy_dia = 0.; + + e_x = float(fabs(dmvx_hor) + fabs(dmvx_ver)); + e_y = float(fabs(dmvy_hor) + fabs(dmvy_ver)); + + if (e_x < 3) { + *ctx_x = 0; + } else if (e_x > 15) { + *ctx_x = 1; + } else { + *ctx_x = 2; + } + + if (e_y < 3) { + *ctx_y = 0; + } else if (e_y > 15) { + *ctx_y = 1; + } else { + *ctx_y = 2; + } + + // mvStat_setCTX(dmvx_hor, dmvy_hor, + // dmvx_ver, dmvy_ver, + // dmvx_dia, dmvy_dia); +} diff --git a/Interframe EZBC/TempSub/src/lifting-only write Y.c b/Interframe EZBC/TempSub/src/lifting-only write Y.c new file mode 100644 index 0000000..b37d6aa --- /dev/null +++ b/Interframe EZBC/TempSub/src/lifting-only write Y.c @@ -0,0 +1,2214 @@ +#include +#include +#include +#include +#include "basic.h" +#define EXTERN extern +#include "encoderN.h" +#include "bmeN.h" +#include "analsyn.h" +#include "structN.h" +#include "coderN.h" +#include "memoryN.h" +#include "util_filtering.h" +#include "iostream" +#include "fstream" +EXTERN float global_motion_active; + + +/*****************************************************************************/ +/* determine_min_distance() */ +/* determines minimal distance to nearest unconnected pixel Hanke 03/03/12 */ +/*****************************************************************************/ + +int +determine_min_distance(unsigned char *pused0, unsigned char *pused1, int px, + int py, int hor, int ver, int SLTF_range, int *tpos) +{ + int tx, ty, t, xmin, ymin, xmax, ymax, ppos; + + *tpos = 0; + ppos = py * hor + px; + + assert( pused0[ppos] == USED || pused1[ppos] == USED ); + + for (t = 1; t <= SLTF_range; t++){ + // test boundaries + xmin = (px - t <= 0) ? 0 : px - t; + ymin = (py - t <= 0) ? 0 : py - t; + xmax = (px + t >= hor - 1) ? hor - 1 : px + t; + ymax = (py + t >= ver - 1) ? ver - 1 : py + t; + + for (ty = ymin; ty <= ymax; ty++){ + for (tx = xmin; tx <= xmax; tx++){ + *tpos = ty * hor + tx; + if ((tx == xmin) || (tx == xmax) || (ty == ymin) || (ty == ymax)){ + if( pused0[*tpos] == UNUSED && pused1[*tpos] == UNUSED ){ + return t; // unconnected pixel found + } + } + } + } + } + + // no match + return (SLTF_range + 1); +} + + +/*****************************************************************************/ +/* lowpass_transition_weight() */ +/* weights connected pixels in the neighborhood of unconnected pixels (SLTF) */ +/*****************************************************************************/ + +float +lowpass_transition_weight(unsigned char *pused0, unsigned char *pused1, int px, + int py, int hor, int ver, int SLTF_range, int *tpos) +{ + int t = 0; + float SLTF_weight; + + if( SLTF_range > 0 ){ + t = determine_min_distance (pused0, pused1, px, py, hor, ver, SLTF_range, tpos); + assert (t > 0 && t <= SLTF_range + 1); + SLTF_weight = (float)t / (float)(SLTF_range + 1); + } else { + SLTF_weight = 1.0; + } + + return SLTF_weight; +} + + +/*****************************************************************************/ +/* mc_analysis() */ +/* */ +/* mv1 mv2 mv3 */ +/* <--- ---> <--- */ +/* | | */ +/* frp fr0 | fr1 fr2| fr3 */ +/* . . . |/ | \ | |/ */ +/* . . . / | \ | / */ +/* . . ./| | \ |/| */ +/* . H0 | | H1 | */ +/* . .\ | | / | */ +/* . . \| | / | */ +/* . . | | / | */ +/* . . |\ | / | */ +/* .. | \|/ | */ +/* L0 | L1 | */ +/* | | */ +/* */ +/* INPUT: H0, fr1, fr2, fr3, mv1, mv2, mv3 */ +/* OUTPUT: L1, H1 */ +/* */ +/*****************************************************************************/ +void +mc_analysis( float *L1, float *H1, float *H0, float *fr1, float *fr2, float *fr3, + float *mvx1, float *mvy1, float *mvx2, float *mvy2, float *mvx3, float *mvy3, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + float *mvx3_int, float *mvy3_int, vector_ptr mv_ref1, vector_ptr mv_ref2, + vector_ptr mv_ref3, int hor, int ver, int level, int remaining_frs, + videoinfo info ) +{ + int i; + int cx, cy, px, py, cpos, ppos, case1, case2; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *hweight, *lweight, *fweight, fweight_sum; + float *ltmp0, *ltmp1, *ptmp0, *ptmp1, ptmp0_sum, ptmp1_sum; + unsigned char *pused0, *pused1; + + int SLTF_range, SHTF_x_range, SHTF_y_range, SHTF_filter_size; + int tx, ty, tpos, tcase, tx_min, ty_min, tx_max, ty_max; + int fx, fy, fpos; + float SLTF_weight = 1.0, *SHTF_filter; + + float sad=0; + + int case_biCon, case_leftCon, case_rightCon; + int case_biPred, case_leftPred, case_rightPred, case_intra; +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + + float max=0.0,min=0.0; + + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + + + for( i = 0; i < hor * ver; i++ ){ + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } + + case_biCon = case_leftCon = case_rightCon = 0; + case_biPred = case_leftPred = case_rightPred = case_intra = 0; + + SLTF_range = info.SLTF_range; + SHTF_x_range = info.SHTF_range; + SHTF_y_range = info.SHTF_range; + + assert( SLTF_range >= 0 && SLTF_range < 10 ); + assert( SHTF_x_range >= 0 && SHTF_x_range < 10 ); + assert( SHTF_y_range >= 0 && SHTF_y_range < 10 ); + + // initialize SHTF_filter + SHTF_filter_size = (2 * SHTF_x_range + 1) * (2 * SHTF_y_range + 1) ; + + SHTF_filter = ( float * )getarray( SHTF_filter_size, sizeof( float ), "SHTF_filter" ); + fweight = ( float * )getarray( SHTF_filter_size, sizeof( float ), "fweight" ); + ptmp0 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp0" ); + ptmp1 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp1" ); + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + SHTF_filter[fpos] = 1.0f / SHTF_filter_size; + } + + /* generate temporal high subband H1 */ + + if( mv_ref2 != NULL || mv_ref3 != NULL ){ + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { // 逐像素处理 + cpos = cy * hor + cx; + +#ifdef COPYCOMPENSATION_WEIGHTING + // assert(SHTF_filter_size == 1); // commented out by Yongjun Wu + comp_weight = 1.0f; +#endif + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // when the pixel is in directional IBLOCK, continue + if ( mv_ref2 != NULL && mv_ref3 != NULL ) + { + if ( mvx2[cpos] == (float)HUGE_VAL && mvy2[cpos] == (float)HUGE_VAL && + mvx3[cpos] == (float)HUGE_VAL && mvy3[cpos] == (float)HUGE_VAL && + mvx2_int[cpos] == (float)HUGE_VAL && mvy2_int[cpos] == (float)HUGE_VAL && + mvx3_int[cpos] == (float)HUGE_VAL && mvy3_int[cpos] == (float)HUGE_VAL ) + { + case_intra++; + continue; + } + } else if ( mv_ref2 != NULL && mv_ref3 == NULL) + { + if ( mvx2[cpos] == (float)HUGE_VAL && mvy2[cpos] == (float)HUGE_VAL && + mvx2_int[cpos] == (float)HUGE_VAL && mvy2_int[cpos] == (float)HUGE_VAL ) + { + case_intra++; + continue; + } + } else if ( mv_ref2 == NULL && mv_ref3 != NULL ) + { + if ( mvx3[cpos] == (float)HUGE_VAL && mvy3[cpos] == (float)HUGE_VAL && + mvx3_int[cpos] == (float)HUGE_VAL && mvy3_int[cpos] == (float)HUGE_VAL ) + { + case_intra++; + continue; + } + } +#endif + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + fweight[fpos] = 0.0; + ptmp0[fpos] = 0.0; + ptmp1[fpos] = 0.0; + } + fweight_sum = ptmp0_sum = ptmp1_sum = 0.0; + pfx0 = pfy0 = pfx1 = pfy1 = 0.0; + + // get nearest inbound position + tx_min = (cx - SHTF_x_range <= 0) ? 0 : cx - SHTF_x_range; + ty_min = (cy - SHTF_y_range <= 0) ? 0 : cy - SHTF_y_range; + tx_max = (cx + SHTF_x_range >= hor - 1) ? hor - 1 : cx + SHTF_x_range; + ty_max = (cy + SHTF_y_range >= ver - 1) ? ver - 1 : cy + SHTF_y_range; + + + for (ty = ty_min, fy = 0; ty <= ty_max; ty++, fy++){ + for (tx = tx_min, fx = 0; tx <= tx_max; tx++, fx++){ + + tpos = ty * hor + tx; // absolute position in MV / image arrays + fpos = fy * (2 * SHTF_x_range + 1) + fx; // relative position in SHTF_filter array + assert( fpos >= 0 && fpos < SHTF_filter_size ); + + if( mvx2[tpos] != (float)HUGE_VAL && mvy2[tpos] != (float)HUGE_VAL && + mvx3[tpos] != (float)HUGE_VAL && mvy3[tpos] != (float)HUGE_VAL ){ + hweight = HPW1; // default mode (bi-directional) + pfx0 = cx - mvx2[tpos]; + pfy0 = cy - mvy2[tpos]; + pfx1 = cx - mvx3[tpos]; + pfy1 = cy - mvy3[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + ptmp1[fpos] = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case_biCon++; + } + else if ( mvx3[tpos] != (float)HUGE_VAL && mvy3[tpos] != (float)HUGE_VAL ){ + hweight = HPW2; // forward mode + pfx1 = cx - mvx3[tpos]; + pfy1 = cy - mvy3[tpos]; + if( inbound( pfx1, pfy1, hor, ver ) ){ + ptmp1[fpos] = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case_rightCon++; + } + else if ( mvx2[tpos] != (float)HUGE_VAL && mvy2[tpos] != (float)HUGE_VAL ){ + hweight = HPW3; // backward mode + pfx0 = cx - mvx2[tpos]; + pfy0 = cy - mvy2[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case_leftCon++; + } + else{ + if( mvx2_int[tpos] != (float)HUGE_VAL && mvy2_int[tpos] != (float)HUGE_VAL && + mvx3_int[tpos] != (float)HUGE_VAL && mvy3_int[tpos] != (float)HUGE_VAL ){ +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW1_pred; // bi-predicted + pfx0 = cx - mvx2_int[tpos]; + pfy0 = cy - mvy2_int[tpos]; + pfx1 = cx - mvx3_int[tpos]; + pfy1 = cy - mvy3_int[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + ptmp1[fpos] = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case_biPred++; + } + else if ( mvx3_int[tpos] != (float)HUGE_VAL && mvy3_int[tpos] != (float)HUGE_VAL ){ +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW2_pred; // fwd-predicted + pfx1 = cx - mvx3_int[tpos]; + pfy1 = cy - mvy3_int[tpos]; + if ( inbound( pfx1, pfy1, hor, ver ) ){ + ptmp1[fpos] = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case_rightPred++; + } + else if ( mvx2_int[tpos] != (float)HUGE_VAL && mvy2_int[tpos] != (float)HUGE_VAL ){ +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW3_pred; // bwd-predicted + pfx0 = cx - mvx2_int[tpos]; + pfy0 = cy - mvy2_int[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case_leftPred++; + } + else{ // intra mode (scene changes at both sides) +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW4_pred; + + if (tpos == cpos) case_intra++; + } + } + + assert( fweight[fpos] >= 0. && fweight[fpos] <= 1. ); + fweight_sum += fweight[fpos]; + ptmp0_sum += hweight[0] * fweight[fpos] * ptmp0[fpos]; + ptmp1_sum += hweight[2] * fweight[fpos] * ptmp1[fpos]; + + } // tx + } // ty + + //////////////////////////////////// + if(pfx0 < 0 || pfx0 >= hor) + printf("error in pfx0 = %f\n",pfx0); + if(pfx1 < 0 || pfx1 >= hor) + printf("error in pfx1 = %f\n",pfx1); + if(pfy0 < 0 || pfy0 >= ver) + printf("error in pfy0 = %f\n",pfy0); + if(pfy1 < 0 || pfy1 >= ver) + printf("error in pfy1 = %f\n",pfy1); + //////////////////////////////////// + + + // transition filtering + ptmp0_sum = (fweight_sum == 0) ? 0.0f : (ptmp0_sum / fweight_sum); + ptmp1_sum = (fweight_sum == 0) ? 0.0f : (ptmp1_sum / fweight_sum); + +#ifdef COPYCOMPENSATION_WEIGHTING + H1[cpos] = comp_weight * ( ptmp0_sum + hweight[1] * fr2[cpos] + ptmp1_sum ); +#else + H1[cpos] = ( ptmp0_sum + hweight[1] * fr2[cpos] + ptmp1_sum ); +#endif +// if(cx >= 240 && cx < 256 && cy >= 192 && cy < 208 && hor == 352) + if(hor == 352) + sad += fabs(H1[cpos]); + +// printf("%f\t",fabs(H1[cpos])); + + } +// printf("\n"); + } + +// printf("max = %f, min = %f\n",max,min); + + if( SHTF_x_range > 0) + printf("SHTF (%d pixels)\n", SHTF_x_range ); + assert(case_biCon + case_leftCon + case_rightCon + case_biPred + + case_leftPred + case_rightPred + case_intra == hor * ver); + + }else{ // copy frame component + for( cpos = 0; cpos < hor * ver; cpos++ ) { +#ifdef COPYCOMPENSATION_WEIGHTING + H1[cpos] = copycomp_weight_high[level] * HPW4[1] * fr2[cpos]; +#else + H1[cpos] = HPW4[1] * fr2[cpos]; +#endif + } + case_intra = hor * ver; + } + +// if(hor == 352) +// printf("sad = %f\n",sad); + + /* generate temporal low subband L1 */ + + // step 1 - motion compensation of H0 and H1 + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { + cpos = cy * hor + cx; + + if ( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ){ + pfx0 = cx - mvx1[cpos]; + pfy0 = cy - mvy1[cpos]; + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver ); + ppos = py * hor + px; + assert((ppos >= 0) && ppos < (hor * ver)); + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; + + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); + pused0[ppos] = USED; + } + } + } + } + + + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { + cpos = cy * hor + cx; + + if ( mvx2[cpos] != (float)HUGE_VAL && mvy2[cpos] != (float)HUGE_VAL ){ + pfx1 = cx - mvx2[cpos]; + pfy1 = cy - mvy2[cpos]; + position( &px, &py, pfx1, pfy1, mvx2[cpos], mvy2[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx2[cpos]; + cfy = py + mvy2[cpos]; + + if( pused1[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp1[ppos] = interpolate( cfx, cfy, H1, hor, ver, TYPE ); + pused1[ppos] = USED; + } + } + } + } + + + case1 = 0; + case2 = 0; + tcase = 0; + + // step 2 - calculation of L1 + if( mv_ref1 != NULL || mv_ref2 != NULL ){ + for( py = 0; py < ver; py++ ) { + for( px = 0; px < hor; px++ ) { + ppos = py * hor + px; + + if( pused0[ppos] == USED && pused1[ppos] == USED ){ + lweight = LPW1; // default mode (bi-directional) + case1++; + } + else if( pused0[ppos] == UNUSED && pused1[ppos] == USED ){ + lweight = LPW2; // forward mode + case1++; + } + else if( pused0[ppos] == USED && pused1[ppos] == UNUSED ){ + lweight = LPW3; // backward mode + case1++; + } + else{ + lweight = LPW4; // unconnected pixels + case2++; + } + + // lowpass transition filtering + if( pused0[ppos] == USED || pused1[ppos] == USED ){ + SLTF_weight = lowpass_transition_weight(pused0, pused1, px, py, hor, ver, SLTF_range, &tpos); + assert (SLTF_weight > 0.0 && SLTF_weight <= 1.0); + if( SLTF_weight != 1.0 ) tcase++; + } + + assert( ppos >= 0 && ppos < hor * ver ); + L1[ppos] = SLTF_weight * ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] ) + lweight[1] * fr1[ppos]; + } + } + + if( SLTF_range > 0) + printf("SLTF (%d pixels) -- connected %d, transitions %d, unconnected %d\n", SLTF_range, case1-tcase, tcase, case2 ); + + /* checking */ + if (case1 + case2 != hor * ver) { + printf( "error in lifting.c -- connected: %d, unconnected: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ) { +#ifdef COPYCOMPENSATION_WEIGHTING + L1[ppos] = copycomp_weight_low[level] * LPW4[1] * fr1[ppos]; +#else + L1[ppos] = LPW4[1] * fr1[ppos]; +#endif + } + } + + free( SHTF_filter ); + free( fweight ); + free( ptmp0 ); + free( ptmp1 ); + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + + +// scale down the motion vectors by 2 for U V components +void +scale_down_mv_by_scale( float *mvx, float *mvy, videoinfo info, int t_level, int shift ) +{ + float dx, dy; + int t, precision, scale; + + if ( *mvx==(float)HUGE_VAL && *mvy==(float)HUGE_VAL ) + return; + + scale = 1<0) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, s_level ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, s_level ); + } + + ptmp0 = ptmp1 = (float)0.0; + if( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL && + right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL) // 双向预测 + { + hweight = HPW1; // default mode (bi-directional) + if (UVcom) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + } + pfx0 = cx - left_mvx; // 在参考帧的位置 + pfy0 = cy - left_mvy; + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + if( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ){ + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + *neighbor_value += (ptmp0*hweight[0]+ptmp1*hweight[2])*neighbor_weight; + } + else // raise self weight to compensate for invalid neighbor motion vector 提高自身的权重来补偿邻居的权重 + *self_weight += neighbor_weight; + } + else if ( right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL ) // 前向预测 + { + hweight = HPW2; // forward mode + if (UVcom) + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + if( inbound( pfx1, pfy1, hor, ver ) ){ + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + *neighbor_value += ptmp1*hweight[2]*neighbor_weight; + }else + *self_weight += neighbor_weight; + }else if ( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL){ + hweight = HPW3; // backward mode + if (UVcom) + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + pfx0 = cx - left_mvx; + pfy0 = cy - left_mvy; + if( inbound( pfx0, pfy0, hor, ver ) ){ + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + *neighbor_value += ptmp0*hweight[0]*neighbor_weight; + }else + *self_weight += neighbor_weight; + }else + assert(0); +} + + +// 通过自身mv获得预测值 +void get_value_for_self_mv(int pos, ImageMEinfo *imagemeinfo, float *fr1, float *fr3, + float *self_value, float self_weight, + int cx, int cy, videoinfo info, int hor, int ver, + int *case_bi, int *case_left, int *case_right, + int UVcom, int t_level) +{ + float *hweight; + float ptmp0, ptmp1; + float pfx0, pfy0, pfx1, pfy1; + float left_mvx, left_mvy, right_mvx, right_mvy; + int s_level; + + // here the set of motion vectors are for Y component + left_mvx = imagemeinfo[pos].left_mvx; // 左侧mv的x信息 + left_mvy = imagemeinfo[pos].left_mvy; + right_mvx = imagemeinfo[pos].right_mvx; + right_mvy = imagemeinfo[pos].right_mvy; + // scale down the self motion vector by corresponding resolution reduction + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + if (s_level>0) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, s_level ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, s_level ); + } + ptmp0 = ptmp1 = (float)0.0; + if( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL && + right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL) // 两个参考帧都可以参考 + { + hweight = HPW1; // default mode (bi-directional) + if (UVcom) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + } + pfx0 = cx - left_mvx; // 获取参考像素的位置 + pfy0 = cy - left_mvy; + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + if ( ! ( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ) ) + printf("Error here\n"); + assert( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ); + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); +// 块级写出 +// // information for current block in Y coordinate with full resolution +// if (!UVcom) +// { +// int leftx = imagemeinfo[pos].leftx; +// int topy = imagemeinfo[pos].topy; // 这个块上边界在图像中的位置 +// int xblk = imagemeinfo[pos].blksize; +// int yblk = imagemeinfo[pos].blksize; +// //printf("%d, %d, %d, %d\n", cx, cy, topy, leftx); +// if (leftx == cx && topy == cy) +// { +// //std::ofstream myfile("interpolate fream.txt", std::ios::app); +// for (int block_h = cy; block_h < topy + yblk; block_h++) +// { +// for (int block_w = cx; block_w < leftx + xblk; block_w++) +// { +// int count = (block_w - cx) + (block_h - cy) * yblk; +// int cnn_pos = block_h * hor + block_w; +// //printf("%d, %d, %d\n", cnn_pos, block_h, block_w); +// float cnn_pfx0 = block_w - left_mvx; // 获取参考像素的位置 +// float cnn_pfy0 = block_h - left_mvy; +// float cnn_pfx1 = block_w - right_mvx; +// float cnn_pfy1 = block_h - right_mvy; +// if (!(inbound(cnn_pfx0, cnn_pfy0, hor, ver) && +// inbound(cnn_pfx1, cnn_pfy1, hor, ver))) +// continue; +// //if (!(inbound(cnn_pfx0, cnn_pfy0, hor, ver) && +// // inbound(cnn_pfx1, cnn_pfy1, hor, ver))) +// // printf("Error here\n"); +// //assert(inbound(cnn_pfx0, cnn_pfy0, hor, ver) && +// // inbound(cnn_pfx1, cnn_pfy1, hor, ver)); +// imagemeinfo[cnn_pos].cnn_ptmp0 = interpolate(cnn_pfx0, cnn_pfy0, fr1, hor, ver, TYPE); +// imagemeinfo[cnn_pos].cnn_ptmp1 = interpolate(cnn_pfx1, cnn_pfy1, fr3, hor, ver, TYPE); +// //myfile << cnn_pos << " " << imagemeinfo[cnn_pos].cnn_ptmp0 << " " << imagemeinfo[cnn_pos].cnn_ptmp1 << "\n"; +// } +// } +// //myfile.close(); +// } + + *self_value = (ptmp0*hweight[0] + ptmp1 * hweight[2])*self_weight; // 通过mv自身权重获得的补偿值 + (*case_bi)++; +#ifdef CNN_TEMPORAL_WAVELET + /*******写出*****/ + if (!UVcom) + { + //std::cout<< "mv*** " <<"0 "<< pos << " " << ptmp0 << " " << ptmp1 <<"\n"; + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 9); + //name[strlen(info.bitname) - 9] = '\0'; + //sprintf(data_file_name, "%s_enc_mv_org.txt", name); + //std::ofstream myfile(data_file_name, std::ios::app); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file_y failed" << std::endl; + // exit(0); + //} + //myfile << "0" << " " << left_mvx << " " << left_mvy << " " << right_mvx << " " << right_mvy << " "; + //myfile.close(); + + //// 解码端 + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 14); + //name[strlen(info.bitname) - 14] = '\0'; + //sprintf(data_file_name, "%s_dec_5_3_predict.txt", name); + //std::ofstream myfile(data_file_name, std::ios::app); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file_y failed" << std::endl; + // exit(0); + //} + //myfile << pos << " " << ptmp0 << " " << ptmp1 << " "; + //myfile.close(); + } + /*******写出*****/ +#endif + + + } + else if ( right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL){ // 右侧有参考帧 + hweight = HPW2; // forward mode + if (UVcom) + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + assert( inbound( pfx1, pfy1, hor, ver ) ); + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + *self_value = ptmp1*hweight[2]*self_weight; + (*case_right)++; +#ifdef CNN_TEMPORAL_WAVELET + /*******写出*****/ + if (!UVcom) + { + //std::cout << "mv*** " << "1 " << pos << " " << ptmp1 << "\n"; + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 9); + //name[strlen(info.bitname) - 9] = '\0'; + //sprintf(data_file_name, "%s_enc_mv_org.txt", name); + //std::ofstream myfile(data_file_name, std::ios::app); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file_y failed" << std::endl; + // exit(0); + //} + //myfile <<"1"<<" "<< right_mvx<< " "<< right_mvy<<" "; + //myfile.close(); + + //// 解码端 + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 14); + //name[strlen(info.bitname) - 14] = '\0'; + //sprintf(data_file_name, "%s_dec_5_3_predict.txt", name); + //std::ofstream myfile(data_file_name, std::ios::app); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file_y failed" << std::endl; + // exit(0); + //} + //myfile << pos << " " << ptmp0 << " " << ptmp1 << " "; + //myfile.close(); + } + /*******写出*****/ +#endif + } + else if ( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL ){ + hweight = HPW3; // backward mode + if (UVcom) + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + pfx0 = cx - left_mvx; + pfy0 = cy - left_mvy; + assert( inbound( pfx0, pfy0, hor, ver ) ); + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + *self_value = ptmp0*hweight[0]*self_weight; + (*case_left)++; +#ifdef CNN_TEMPORAL_WAVELET + /*******写出*****/ + if (!UVcom) + { + //std::cout << "mv*** " << "2 " << pos << " " << ptmp0 << "\n"; + //char name[256], data_file_name[256], start[10]; + //strncpy(name, info.bitname, strlen(info.bitname) - 9); + //name[strlen(info.bitname) - 9] = '\0'; + //sprintf(data_file_name, "%s_enc_mv_org.txt", name); + //std::ofstream myfile(data_file_name, std::ios::app); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file_y failed" << std::endl; + // exit(0); + //} + //myfile <<"2"<<" "<< left_mvx<< " " < <--- */ +/* | | */ +/* frp fr0 | fr1 fr2| fr3 */ +/* . . . |/ | \ | |/ */ +/* . . . / | \ | / */ +/* . . ./| | \ |/| */ +/* . H0 | | H1 | */ +/* . .\ | | / | */ +/* . . \| | / | */ +/* . . | | / | */ +/* . . |\ | / | */ +/* .. | \|/ | */ +/* L0 | L1 | */ +/* | | */ +/* */ +/* INPUT: H0, fr1, fr2, fr3, mv1, mv2, mv3 */ +/* OUTPUT: L1, H1 */ +/* 输出高频帧和低频帧 */ +/*****************************************************************************/ + +int count = 0; + +void +mc_analysis_with_OBMC( float *L1, float *H1, float *H0, float *fr1, float *fr2, float *fr3, + float *mvx1, float *mvy1, float *mvx2, float *mvy2, float *mvx3, float *mvy3, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + float *mvx3_int, float *mvy3_int, vector_ptr mv_ref1, vector_ptr mv_ref2, + vector_ptr mv_ref3, int hor, int ver, int level, int remaining_frs, + videoinfo info, ImageMEinfo *imagemeinfo, Varblkarrayinfo *varblkarray, int UVcom, + enum FLAG left_scene, enum FLAG right_scene, int type) +{ + int i; + int cx, cy, px, py, cpos, com_pos, ppos, case1, case2; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *lweight; + float *ltmp0, *ltmp1; + unsigned char *pused0, *pused1; + int leftx, topy, xblk, yblk, disx, disy, col, row, pos; + float self_weight, ver_weight, hor_weight; + float self_value, neighbor_value; + int case_bi, case_left, case_right, case_intra; // 用于记录采用这四种预测模式的像素的个数 + float sad = 0; + + float getnum, diff; + int pixel_count; + FILE *pc; + + // UVcom: indication for U V component + // for U V components we use the sub-sampled weighting coefficients + +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + + // the variables for update step in MCTF 用于update的变量 整帧处理 + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + for( i = 0; i < hor * ver; i++ ) + { + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } +#ifdef CNN_TEMPORAL_WAVELET + char name[256], data_file_name[256], start[10]; + strncpy(name, info.bitname, strlen(info.bitname) - 9); + name[strlen(info.bitname) - 9] = '\0'; + sprintf(data_file_name, "%s_enc_mv_org_yuv.txt", name); + std::ofstream myfile(data_file_name, std::ios::app); + if (myfile.is_open() == NULL) + { + std::cout << "open file_y failed" << std::endl; + exit(0); + } + if (!UVcom) + { + myfile << "new frame!\n"; + } +#endif + case_bi = case_left = case_right = case_intra= 0; + + /* generate temporal high subband H1 生成高频子带 */ + if( left_scene == NO || right_scene == NO )// 两边存在可以参考 + { + for( cy = 0; cy < ver; cy++ ) + { + for( cx = 0; cx < hor; cx++ ) // 像素级滤波,为什么不进行块级滤波 + { + cpos = (cy<> 1)) { // top neighbor is effective 当前像素到哪边更近,这里是到上面更近 + pos = (topy-3)*(hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1, fr3, &neighbor_value, + &self_weight, ver_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disy >= (yblk >> 1)) { // bottom neighbor is effective + pos = (topy+yblk+2)*(hor<> 1)) { // left neighbor is effective + pos = row*(hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1, fr3, &neighbor_value, + &self_weight, hor_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disx >= (xblk >> 1)) { // right neighbor is effective + pos = row*(hor<= 9 || (imagemeinfo[cpos].bi_mode == 7 && ) ) + fr2[com_pos] = fr2[com_pos] / 0.4; + } + + if(UVcom == 0 && level == 0){ + if(imagemeinfo[cpos].mrg_blk_bdr == 1) + fr2[cpos] = 255; + } +*/ //////////////////////////////////////////////////// +/* //MARK TWO COMP + if( type == 1 && level == 0 ){ + if(imagemeinfo[cpos].two_comp_src == 1) + fr2[com_pos] = fr2[com_pos] / 0.4; + } + + if(UVcom == 0 && level == 0){ + if(imagemeinfo[cpos].two_comp_bdr == 1) + fr2[cpos] = 255; + } +*/ //////////////////////////////////////////////////// + if(imagemeinfo[cpos].skip_sign == YES){ + H1[com_pos] = 0; + }else + H1[com_pos] = comp_weight * ( HPW1[1] * fr2[com_pos] + self_value + neighbor_value );// 计算出来H1 +#ifdef CNN_TEMPORAL_WAVELET + if (!UVcom) + { + + myfile << cpos <<"\n"; + //myfile << cpos << " " << H1[cpos] << " " << fr1[cpos] << " " << fr2[cpos] << " " << fr3[cpos] << "\n"; + } +#endif + } + } + +} + else // if( left_scene == NO || right_scene == NO ) + { // copy frame component + for( cpos = 0; cpos < hor * ver; cpos++ ) { // 逐个像素去做,使用的是帧内模式 +#ifdef COPYCOMPENSATION_WEIGHTING + H1[cpos] = copycomp_weight_high[level] * HPW4[1] * fr2[cpos]; +#else + H1[cpos] = HPW4[1] * fr2[cpos]; +#endif + } + case_intra = hor * ver; + } +#ifdef CNN_TEMPORAL_WAVELET + myfile.close(); +#endif + assert(case_intra + case_bi + case_left + case_right == hor*ver ); + /* generate temporal low subband L1 生成低频帧*/ + // step 1 - motion compensation of H0 and H1 运动补偿 + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { + cpos = cy * hor + cx; // 当前位置 + if ( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ) // 是否接受左边高频帧的更新 + { + pfx0 = cx - mvx1[cpos]; + pfy0 = cy - mvy1[cpos]; // 在参考图像中的位置 + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver ); + ppos = py * hor + px; // 取整之后的位置 + assert((ppos >= 0) && ppos < (hor * ver)); + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; // 当前位置的浮点位置 + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); + pused0[ppos] = USED; + } + } + } + } + + + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { + cpos = cy * hor + cx; + if ( mvx2[cpos] != (float)HUGE_VAL && mvy2[cpos] != (float)HUGE_VAL ){ + pfx1 = cx - mvx2[cpos]; + pfy1 = cy - mvy2[cpos]; + position( &px, &py, pfx1, pfy1, mvx2[cpos], mvy2[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx2[cpos]; + cfy = py + mvy2[cpos]; + if( pused1[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp1[ppos] = interpolate( cfx, cfy, H1, hor, ver, TYPE ); + pused1[ppos] = USED; + } + } + } + } + + + case1 = 0; + case2 = 0; + // step 2 - calculation of L1 + //mv_ref1 = NULL; + //mv_ref2 = NULL; + + if (mv_ref1 != NULL || mv_ref2 != NULL) // 有参考 + //if (0) // 有参考 + { + for( py = 0; py < ver; py++ ) { + for (px = 0; px < hor; px++) { + ppos = py * hor + px; + + if( pused0[ppos] == USED && pused1[ppos] == USED ){ + lweight = LPW1; // default mode (bi-directional) + case1++; + } + else if( pused0[ppos] == UNUSED && pused1[ppos] == USED ){ + lweight = LPW2; // forward mode + case1++; + } + else if( pused0[ppos] == USED && pused1[ppos] == UNUSED ){ + lweight = LPW3; // backward mode + case1++; + } + else{ + lweight = LPW4; // unconnected pixels + case2++; + } + assert( ppos >= 0 && ppos < hor * ver ); +#ifdef NO_UPDATE + //lweight[1] = LPW4[1] * copycomp_weight_low[level]; + //lweight[0] = 0; + //lweight[2] = 0; + //printf("%f, %f, %f\n", lweight[0], lweight[1], lweight[2]); + //L1[ppos] = LPW4[1] * copycomp_weight_low[level] * fr1[ppos]; // 计算出L1 + lweight = LPW4; + L1[ppos] = (lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos]) + lweight[1] * fr1[ppos]; // 计算出L1 +#else + L1[ppos] = ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] ) + lweight[1] * fr1[ppos]; // 计算出L1 +#endif + + /**************写出**********/ + //{ + // char name[256], data_file_name[256], start[10]; + // strncpy(name, info.bitname, strlen(info.bitname) - 9); + // name[strlen(info.bitname) - 9] = '\0'; + // sprintf(data_file_name, "%s_L.txt", name); + // std::ofstream myfile(data_file_name, std::ios::app); + // if (myfile.is_open() == NULL) + // { + // std::cout << "open file_y failed" << std::endl; + // exit(0); + // } + // myfile << ppos << " " << L1[ppos] << "\n"; + // myfile.close(); + //} + /**************写出**********/ + } + } +/* + if(UVcom == 0 && level == 0){ + diff = 0; pixel_count = 0; +// printf("MV matrix:\n\n"); + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = ( cy<= 0 ); + if(diff > global_motion_active) + global_motion_active = diff; + + pc = fopen("enc_block.txt","at"); + fprintf(pc,"%f\n",diff); + fclose(pc); + }//if UVcom = 0 +*/ + // checking + if (case1 + case2 != hor * ver) { + printf( "error in lifting.c -- connected: %d, unconnected: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ) { +#ifdef COPYCOMPENSATION_WEIGHTING + L1[ppos] = copycomp_weight_low[level] * LPW4[1] * fr1[ppos]; // 计算出L1 +#else + L1[ppos] = LPW4[1] * fr1[ppos]; +#endif + } + } + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + +/*****************************************************************************/ +/* mc_analysis() */ +/* */ +/* mv1 mv2 mv3 */ +/* <--- ---> <--- */ +/* | | */ +/* frp fr0 | fr1 fr2| fr3 */ +/* . . . |/ | \ | |/ */ +/* . . . / | \ | / */ +/* . . ./| | \ |/| */ +/* . H0 | | H1 | */ +/* . .\ | | / | */ +/* . . \| | / | */ +/* . . | | / | */ +/* . . |\ | / | */ +/* .. | \|/ | */ +/* L0 | L1 | */ +/* | | */ +/* */ +/* INPUT: H0, fr1, fr2, fr3, mv1, mv2, mv3 */ +/* OUTPUT: L1, H1 */ +/* */ +/*****************************************************************************/ + + +/*****************************************************************************/ +/* mc_synthesis() */ +/* */ +/* mv0 mv1 mv2 */ +/* ---> <--- ---> */ +/* | | | */ +/* frp | fr0 fr1 | fr2 fr3 | */ +/* . \| | / | \| . . . .| */ +/* . \ | / | \ . . . . */ +/* . |\ | / | |\ . . . |. */ +/* . | H0 | | H1 . | H2 */ +/* . | | | . | */ +/* . | | | . | */ +/* . | | | . | */ +/* L0 | L1 | L2 | */ +/* | | | */ +/* */ +/* INPUT: H0, L1, H1, frp, mv0, mv1, mv2 */ +/* OUTPUT: fr0, fr1 */ +/* */ +/*****************************************************************************/ +void +mc_synthesis( float *fr0, float *fr1, float *H0, float *L1, float *H1, float *frp, + float *mvx0, float *mvy0, float *mvx1, float *mvy1, + float *mvx2, float *mvy2, float *mvx0_int, float *mvy0_int, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + vector_ptr mv_ref0, vector_ptr mv_ref1, vector_ptr mv_ref2, + int hor, int ver, int level, videoinfo info ) +{ + int i; + int cx, cy, px, py, cpos, ppos, case1, case2, case3; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *hweight, *lweight, *fweight, fweight_sum; + float *ltmp0, *ltmp1, *ptmp0, *ptmp1, ptmp0_sum, ptmp1_sum; + unsigned char *pused0, *pused1; + + int SLTF_range, SHTF_x_range, SHTF_y_range, SHTF_filter_size; + int tx, ty, tpos, tcase, tx_min, ty_min, tx_max, ty_max; + int fx, fy, fpos; + float SLTF_weight = 1.0, *SHTF_filter; + + +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + + // step 0 - calculation of fr1 (A) / scene_change propagation + if (level < info.t_level) + { + if( mv_ref1 != NULL || mv_ref2 != NULL ) + { + for( ppos = 0; ppos < hor * ver; ppos++ ) + { + fr1[ppos] = L1[ppos] / LPW4[1]; // 第一次合成 + } + } + else + { + for( ppos = 0; ppos < hor * ver; ppos++ ) + { +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + return; + } + + + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + + for( i = 0; i < hor * ver; i++ ){ + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } + + SLTF_range = info.SLTF_range; + SHTF_x_range = info.SHTF_range; + SHTF_y_range = info.SHTF_range; + + assert( SLTF_range >= 0 && SLTF_range < 10 ); + assert( SHTF_x_range >= 0 && SHTF_x_range < 10 ); + assert( SHTF_y_range >= 0 && SHTF_y_range < 10 ); + + // initialize SHTF_filter + SHTF_filter_size = (2 * SHTF_x_range + 1) * (2 * SHTF_y_range + 1) ; + + SHTF_filter = ( float * )getarray( SHTF_filter_size, sizeof( float ), "SHTF_filter" ); + fweight = ( float * )getarray( SHTF_filter_size, sizeof( float ), "fweight" ); + ptmp0 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp0" ); + ptmp1 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp1" ); + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + SHTF_filter[fpos] = 1.0f / SHTF_filter_size; + } + + /* reconstruction of fr1 (A) */ + + // step 1 - motion compensation of H0 and H1 + // MC of H0 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ) { + pfx0 = cx - mvx1[cpos]; + pfy0 = cy - mvy1[cpos]; + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; + + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ){ + pused0[ppos] = USED; + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); + } + } + } + } + + // MC of H1 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx2[cpos] != (float)HUGE_VAL && mvy2[cpos] != (float)HUGE_VAL ) { + pfx1 = cx - mvx2[cpos]; + pfy1 = cy - mvy2[cpos]; + + position( &px, &py, pfx1, pfy1, mvx2[cpos], mvy2[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx2[cpos]; + cfy = py + mvy2[cpos]; + + if( pused1[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + pused1[ppos] = USED; + ltmp1[ppos] = interpolate( cfx, cfy, H1, hor, ver, TYPE ); + } + } + } + } + + case1 = case2 = tcase = 0; + + // step 2 - calculation of fr1 (A) + if( mv_ref1 != NULL || mv_ref2 != NULL ){ + for( py = 0; py < ver; py++ ) { + for( px = 0; px < hor; px++ ) { + ppos = py * hor + px; + + if( pused0[ppos] == USED && pused1[ppos] == USED ){ + lweight = LPW1; // default mode (bi-directional) + case1++; + } + else if( pused0[ppos] == UNUSED && pused1[ppos] == USED ){ + lweight = LPW2; // forward mode + case1++; + } + else if( pused0[ppos] == USED && pused1[ppos] == UNUSED ){ + lweight = LPW3; // backward mode + case1++; + } + else{ + lweight = LPW4; // intra mode (unconnected pixels) + case2++; + } + + // lowpass transition filtering + if( pused0[ppos] == USED || pused1[ppos] == USED ){ + SLTF_weight = lowpass_transition_weight(pused0, pused1, px, py, hor, ver, SLTF_range, &tpos); + assert (SLTF_weight > 0.0 && SLTF_weight <= 1.0); + if( SLTF_weight != 1.0 ) tcase++; + } + + assert( ppos >= 0 && ppos < hor * ver ); + fr1[ppos] = 1 / lweight[1] * ( L1[ppos] - SLTF_weight * ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] )); + } + } + + if( SLTF_range > 0) + printf("SLTF (%d pixels) -- connected %d, transitions %d, unconnected %d\n", SLTF_range, case1-tcase, tcase, case2 ); + + /* checking */ + if( case1 + case2 != hor * ver ){ + printf( "error in mctf() covered: %d, uncovered: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ){ + // fr1[ppos] = 1 / LPW4[1] * L1[ppos]; +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + + case1 = case2 = case3 = 0; + + /* reconstruction of fr0 (B) */ + + if( mv_ref0 != NULL || mv_ref1 != NULL ){ + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + +#ifdef COPYCOMPENSATION_WEIGHTING + // assert(SHTF_filter_size == 1); // commented by Yongjun Wu + comp_weight = 1.0f; +#endif + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // when the pixel is in directional IBLOCK, continue + if ( mv_ref0 != NULL && mv_ref1 != NULL ) + { + if ( mvx0[cpos] == (float)HUGE_VAL && mvy0[cpos] == (float)HUGE_VAL && + mvx1[cpos] == (float)HUGE_VAL && mvy1[cpos] == (float)HUGE_VAL && + mvx0_int[cpos] == (float)HUGE_VAL && mvy0_int[cpos] == (float)HUGE_VAL && + mvx1_int[cpos] == (float)HUGE_VAL && mvy1_int[cpos] == (float)HUGE_VAL ) + { + case3++; + continue; + } + } else if ( mv_ref0 != NULL && mv_ref1 == NULL) + { + if ( mvx0[cpos] == (float)HUGE_VAL && mvy0[cpos] == (float)HUGE_VAL && + mvx0_int[cpos] == (float)HUGE_VAL && mvy0_int[cpos] == (float)HUGE_VAL ) + { + case3++; + continue; + } + + } else if ( mv_ref0 == NULL && mv_ref1 != NULL ) + { + if ( mvx1[cpos] == (float)HUGE_VAL && mvy1[cpos] == (float)HUGE_VAL && + mvx1_int[cpos] == (float)HUGE_VAL && mvy1_int[cpos] == (float)HUGE_VAL ) + { + case3++; + continue; + } + } +#endif + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + fweight[fpos] = 0.0; + ptmp0[fpos] = 0.0; + ptmp1[fpos] = 0.0; + } + + // get nearest inbound position + tx_min = (cx - SHTF_x_range <= 0) ? 0 : cx - SHTF_x_range; + ty_min = (cy - SHTF_y_range <= 0) ? 0 : cy - SHTF_y_range; + tx_max = (cx + SHTF_x_range >= hor - 1) ? hor - 1 : cx + SHTF_x_range; + ty_max = (cy + SHTF_y_range >= ver - 1) ? ver - 1 : cy + SHTF_y_range; + + fweight_sum = ptmp0_sum = ptmp1_sum = 0.0; + pfx0 = pfy0 = pfx1 = pfy1 = 0.0; + + for (ty = ty_min, fy = 0; ty <= ty_max; ty++, fy++){ + for (tx = tx_min, fx = 0; tx <= tx_max; tx++, fx++){ + + tpos = ty * hor + tx; // absolute position in MV / image arrays + fpos = fy * (2 * SHTF_x_range + 1) + fx; // relative position in SHTF_filter array + assert( fpos >= 0 && fpos < SHTF_filter_size ); + + if( mvx0[tpos] != (float)HUGE_VAL && mvy0[tpos] != (float)HUGE_VAL && + mvx1[tpos] != (float)HUGE_VAL && mvy1[tpos] != (float)HUGE_VAL ){ + hweight = HPW1; // default mode (bi-directional) + pfx0 = cx - mvx0[tpos]; + pfy0 = cy - mvy0[tpos]; + pfx1 = cx - mvx1[tpos]; + pfy1 = cy - mvy1[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, frp, hor, ver, TYPE ); + ptmp1[fpos] = interpolate( pfx1, pfy1, fr1, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case1++; + } + else if( mvx1[tpos] != (float)HUGE_VAL && mvy1[tpos] != (float)HUGE_VAL ){ + hweight = HPW2; // forward mode + pfx1 = cx - mvx1[tpos]; + pfy1 = cy - mvy1[tpos]; + if( inbound( pfx1, pfy1, hor, ver ) ){ + ptmp1[fpos] = interpolate( pfx1, pfy1, fr1, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case1++; + } + else if( mvx0[tpos] != (float)HUGE_VAL && mvy0[tpos] != (float)HUGE_VAL ){ + hweight = HPW3; // backward mode + pfx0 = cx - mvx0[tpos]; + pfy0 = cy - mvy0[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, frp, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + if ( tpos == cpos ) case1++; + } + else{ // predicted modes + if ( tpos == cpos ) case2++; + + if( mvx0_int[tpos] != (float)HUGE_VAL && mvy0_int[tpos] != (float)HUGE_VAL && + mvx1_int[tpos] != (float)HUGE_VAL && mvy1_int[tpos] != (float)HUGE_VAL ){ +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW1_pred; // bi-directional + pfx0 = cx - mvx0_int[tpos]; + pfy0 = cy - mvy0_int[tpos]; + pfx1 = cx - mvx1_int[tpos]; + pfy1 = cy - mvy1_int[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, frp, hor, ver, TYPE ); + ptmp1[fpos] = interpolate( pfx1, pfy1, fr1, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + } + else if( mvx1_int[tpos] != (float)HUGE_VAL && mvy1_int[tpos] != (float)HUGE_VAL ){ +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW2_pred; // predicted - forward mode + pfx1 = cx - mvx1_int[tpos]; + pfy1 = cy - mvy1_int[tpos]; + if( inbound( pfx1, pfy1, hor, ver ) ){ + ptmp1[fpos] = interpolate( pfx1, pfy1, fr1, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + } + else if( mvx0_int[tpos] != (float)HUGE_VAL && mvy0_int[tpos] != (float)HUGE_VAL ){ +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW3_pred; // predicted - backward mode + pfx0 = cx - mvx0_int[tpos]; + pfy0 = cy - mvy0_int[tpos]; + if( inbound( pfx0, pfy0, hor, ver ) ){ + ptmp0[fpos] = interpolate( pfx0, pfy0, frp, hor, ver, TYPE ); + assert( fweight[fpos] == 0.0 ); + fweight[fpos] = SHTF_filter[fpos]; // set filter postion + } + } + else{ // intra - intra mode (scene changes at both sides) +#ifdef COPYCOMPENSATION_WEIGHTING_FORPREDICTED + comp_weight = copycomp_weight_high[level]; +#endif + hweight = HPW4_pred; + + } + } + + assert( fweight[fpos] >= 0. && fweight[fpos] <= 1. ); + fweight_sum += fweight[fpos]; + ptmp0_sum += hweight[0] * fweight[fpos] * ptmp0[fpos]; + ptmp1_sum += hweight[2] * fweight[fpos] * ptmp1[fpos]; + + } // tx + } // ty + + // transition filtering + ptmp0_sum = (fweight_sum == 0) ? 0.0f : (ptmp0_sum / fweight_sum); + ptmp1_sum = (fweight_sum == 0) ? 0.0f : (ptmp1_sum / fweight_sum); + +// printf("%f\t",fabs(H0[cpos])); + +#ifdef COPYCOMPENSATION_WEIGHTING + fr0[cpos] = 1 / hweight[1] * ( - ptmp0_sum + H0[cpos] / comp_weight - ptmp1_sum ); +#else + fr0[cpos] = 1 / hweight[1] * ( - ptmp0_sum + H0[cpos] - ptmp1_sum ); +#endif + } +// printf("\n"); + } + + if( SHTF_x_range > 0) + printf("SHTF (%d pixels)\n", SHTF_x_range ); + + /* checking */ + if( case1 + case2 + case3 != hor * ver ){ + printf( "error in lifting.c -- default: %d, intra: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( cpos = 0; cpos < hor * ver; cpos++ ){ + // fr0[cpos] = 1 / HPW4[1] * H0[cpos]; +#ifdef COPYCOMPENSATION_WEIGHTING + fr0[cpos] = H0[cpos] / (HPW4[1] * copycomp_weight_high[level]); +#else + fr0[cpos] = H0[cpos]; +#endif + } + } + + free( SHTF_filter ); + free( fweight ); + free( ptmp0 ); + free( ptmp1 ); + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + + +/*****************************************************************************/ +/* mc_synthesis() */ +/* */ +/* mv0 mv1 mv2 */ +/* ---> <--- ---> */ +/* | | | */ +/* frp | fr0 fr1 | fr2 fr3 | */ +/* . \| | / | \| . . . .| */ +/* . \ | / | \ . . . . */ +/* . |\ | / | |\ . . . |. */ +/* . | H0 | | H1 . | H2 */ +/* . | | | . | */ +/* . | | | . | */ +/* . | | | . | */ +/* L0 | L1 | L2 | */ +/* | | | */ +/* */ +/* INPUT: H0, L1, H1, frp, mv0, mv1, mv2 */ +/* OUTPUT: fr0, fr1 */ +/* */ +/*****************************************************************************/ +// here hor, ver are the dimension for specific component and specific resolution +// fr0[com_pos] = 1 / HPW1[1] * ( - self_value + H0[com_pos] / comp_weight - neighbor_value ); +void +mc_synthesis_with_OBMC( float *fr0, float *fr1, float *H0, float *L1, float *H1, float *frp, + float *mvx0, float *mvy0, float *mvx1, float *mvy1, + float *mvx2, float *mvy2, float *mvx0_int, float *mvy0_int, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + vector_ptr mv_ref0, vector_ptr mv_ref1, vector_ptr mv_ref2, + int hor, int ver, int level, videoinfo info, + ImageMEinfo *imagemeinfo, Varblkarrayinfo *varblkarray, int UVcom, int type ) +{ + //count += 1; + //printf("%d\n", count); + int i, case1, case2; + int cx, cy, px, py, cpos, ppos, com_pos; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *lweight; + float *ltmp0, *ltmp1; // 两个补偿完的帧 + unsigned char *pused0, *pused1; + int leftx, topy, xblk, yblk, disx, disy, col, row, pos; + float self_weight, ver_weight, hor_weight; + float self_value, neighbor_value; + int case_bi, case_left, case_right, case_intra ; + int s_level; + float sad; + + float getnum, getnum2, diff; + int pixel_count; + FILE *pc; + float avg_mv; + + // the spatial resolution reduction in decoder + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + + // step 0 - calculation of fr1 (A) / scene_change propagation// 进不来 + if (level < info.t_level) + { + if( mv_ref1 != NULL || mv_ref2 != NULL ) + { + for( ppos = 0; ppos < hor * ver; ppos++ ){ + fr1[ppos] = L1[ppos] / LPW4[1]; + } + } + else + { + for( ppos = 0; ppos < hor * ver; ppos++ ){ +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + return; + } + + // variables for update step in MCTF + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + for( i = 0; i < hor * ver; i++ ){ // 初始化 + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } + + // reconstruction of fr1 (A) 根据L1,使用update,重建fr1 + // step 1 - motion compensation of H0 and H1 为H0 H1做运动补偿 但是只做了双向预测的,其他三种模式是什么情况,为啥没有做??? + // MC of H0 为H0做运动补偿 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ) { // 有参考mv + pfx0 = cx - mvx1[cpos]; // 参考像素的x位置 + pfy0 = cy - mvy1[cpos]; // 参考像素的y位置 + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver );// 返回整数位置,放在px, py + ppos = py * hor + px; // 整数位置 + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; + + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ){ // 如果之前没有被使用 + pused0[ppos] = USED; + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); // 根据运动补偿插出帧 + } + } + } + } + + // MC of H1 为H1做运动补偿 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx2[cpos] != (float)HUGE_VAL && mvy2[cpos] != (float)HUGE_VAL ) { + pfx1 = cx - mvx2[cpos]; + pfy1 = cy - mvy2[cpos]; + + position( &px, &py, pfx1, pfy1, mvx2[cpos], mvy2[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx2[cpos]; + cfy = py + mvy2[cpos]; + + if( pused1[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + pused1[ppos] = USED; + ltmp1[ppos] = interpolate( cfx, cfy, H1, hor, ver, TYPE ); + } + } + } + } + + case1 = case2 = 0; + // step 2 - calculation of fr1 (A) 重建fr1,一共有四种模式,双向预测、前向预测、后向预测、帧内预测 + //mv_ref1 = NULL; + //mv_ref2 = NULL; + //if (0) { + //count++; + + if (mv_ref1 != NULL || mv_ref2 != NULL) { + for( py = 0; py < ver; py++ ) { + for( px = 0; px < hor; px++ ) { + ppos = py * hor + px; + + if( pused0[ppos] == USED && pused1[ppos] == USED ){ // 表示是双向的预测 + lweight = LPW1; // default mode (bi-directional) + case1++; + } + else if( pused0[ppos] == UNUSED && pused1[ppos] == USED ){ + lweight = LPW2; // forward mode + case1++; + } + else if( pused0[ppos] == USED && pused1[ppos] == UNUSED ){ + // for this case info.bi_mv[level] must be 1 + // if info.bi_mv[level]==0, this case is impossible, + // because RIGHT_CONNECTED becomes LEFT_PREDICTED + lweight = LPW3; // backward mode + case1++; + } + else{ + lweight = LPW4; // intra mode (unconnected pixels) intra 模式 + case2++; + } + assert( ppos >= 0 && ppos < hor * ver ); +#ifdef NO_UPDATE + //lweight = LPW4; + //lweight[1] = LPW4[1] * copycomp_weight_low[level]; + //lweight[0] = 0; + //lweight[2] = 0; + //fr1[ppos] = 1 / ( LPW4[1] * copycomp_weight_low[level]) * (L1[ppos]); // 重建出的帧 + lweight = LPW4; + fr1[ppos] = 1 / lweight[1] * (L1[ppos] - (lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos])); // 重建出的帧 +#else + fr1[ppos] = 1 / lweight[1] * ( L1[ppos] - ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] )); // 重建出的帧 +#endif + } + } + + assert( case1 + case2 == hor * ver ); + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ){ +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + + sad = 0; + + // the OBMC weighting coefficients for U V are sub-sampled version of those for Y + // the OBMC weighting coefficients for low resolution frame are + // sub-sampled version of those in full resolution + // reconstruction of fr0 (B) 重建fr0 + case_bi = case_left = case_right = case_intra = 0; + if( mv_ref0 != NULL || mv_ref1 != NULL ){ // + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = ( (cy<> 1)) { // top neighbor is effective 离上面近 + pos = (topy-3)*( (hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) // 不是最上面一行且上面的块不是帧内块 + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, frp, fr1, &neighbor_value, + &self_weight, ver_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disy >= (yblk >> 1)) { // bottom neighbor is effective 离下面近 + pos = (topy+yblk+2)*( (hor<> 1)) { // left neighbor is effective + pos = row*( (hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, frp, fr1, &neighbor_value, + &self_weight, hor_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disx >= (xblk >> 1)) { // right neighbor is effective + pos = row*( (hor<= 9 || (imagemeinfo[cpos].bi_mode == 7 && imagemeinfo[cpos].aff_mrg == YES) ) + fr0[com_pos] = fr0[com_pos] / 0.4; + } +*/ +/* if(UVcom == 0 && level == 0){ + if(imagemeinfo[cpos].mrg_blk_bdr == 1) + fr0[cpos] = 255; + } +*/ //////////////////////////////////////////////////// + + } + } +/* + if(UVcom == 0 && level == 0){ + diff = 0; pixel_count = 0; avg_mv = 0; +// printf("MV matrix:\n\n"); + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = ( (cy<= 0 ); + if(diff > global_motion_active) + global_motion_active = diff; + + fclose(pc); + }//if UVcom = 0 +*/ + assert( case_bi + case_left + case_right + case_intra == hor * ver ); + }//if mv + else{ // copy frame component 直接就是整帧复制 + for( cpos = 0; cpos < hor * ver; cpos++ ){ +#ifdef COPYCOMPENSATION_WEIGHTING + fr0[cpos] = H0[cpos] / (HPW4[1] * copycomp_weight_high[level]); +#else + fr0[cpos] = H0[cpos]; +#endif + } + } + + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + diff --git a/Interframe EZBC/TempSub/src/lifting.c b/Interframe EZBC/TempSub/src/lifting.c new file mode 100644 index 0000000..c4547b1 --- /dev/null +++ b/Interframe EZBC/TempSub/src/lifting.c @@ -0,0 +1,2426 @@ +#include +#include +#include +#include +#include "basic.h" +#define EXTERN extern +#include "encoderN.h" +#include "bmeN.h" +#include "analsyn.h" +#include "structN.h" +#include "coderN.h" +#include "memoryN.h" +#include "util_filtering.h" +#include "iostream" +#include "fstream" +EXTERN float global_motion_active; + + +/*****************************************************************************/ +/* determine_min_distance() */ +/* determines minimal distance to nearest unconnected pixel Hanke 03/03/12 */ +/*****************************************************************************/ + +int +determine_min_distance(unsigned char *pused0, unsigned char *pused1, int px, + int py, int hor, int ver, int SLTF_range, int *tpos) +{ + int tx, ty, t, xmin, ymin, xmax, ymax, ppos; + + *tpos = 0; + ppos = py * hor + px; + + assert( pused0[ppos] == USED || pused1[ppos] == USED ); + + for (t = 1; t <= SLTF_range; t++){ + // test boundaries + xmin = (px - t <= 0) ? 0 : px - t; + ymin = (py - t <= 0) ? 0 : py - t; + xmax = (px + t >= hor - 1) ? hor - 1 : px + t; + ymax = (py + t >= ver - 1) ? ver - 1 : py + t; + + for (ty = ymin; ty <= ymax; ty++){ + for (tx = xmin; tx <= xmax; tx++){ + *tpos = ty * hor + tx; + if ((tx == xmin) || (tx == xmax) || (ty == ymin) || (ty == ymax)){ + if( pused0[*tpos] == UNUSED && pused1[*tpos] == UNUSED ){ + return t; // unconnected pixel found + } + } + } + } + } + + // no match + return (SLTF_range + 1); +} + + +/*****************************************************************************/ +/* lowpass_transition_weight() */ +/* weights connected pixels in the neighborhood of unconnected pixels (SLTF) */ +/*****************************************************************************/ + +float +lowpass_transition_weight(unsigned char *pused0, unsigned char *pused1, int px, + int py, int hor, int ver, int SLTF_range, int *tpos) +{ + int t = 0; + float SLTF_weight; + + if( SLTF_range > 0 ){ + t = determine_min_distance (pused0, pused1, px, py, hor, ver, SLTF_range, tpos); + assert (t > 0 && t <= SLTF_range + 1); + SLTF_weight = (float)t / (float)(SLTF_range + 1); + } else { + SLTF_weight = 1.0; + } + + return SLTF_weight; +} + + +/*****************************************************************************/ +/* mc_analysis() */ +/* */ +/* mv1 mv2 mv3 */ +/* <--- ---> <--- */ +/* | | */ +/* frp fr0 | fr1 fr2| fr3 */ +/* . . . |/ | \ | |/ */ +/* . . . / | \ | / */ +/* . . ./| | \ |/| */ +/* . H0 | | H1 | */ +/* . .\ | | / | */ +/* . . \| | / | */ +/* . . | | / | */ +/* . . |\ | / | */ +/* .. | \|/ | */ +/* L0 | L1 | */ +/* | | */ +/* */ +/* INPUT: H0, fr1, fr2, fr3, mv1, mv2, mv3 */ +/* OUTPUT: L1, H1 */ +/* */ +/*****************************************************************************/ +void +mc_analysis( float *L1, float *H1, float *H0, float *fr1, float *fr2, float *fr3, + float *mvx1, float *mvy1, float *mvx2, float *mvy2, float *mvx3, float *mvy3, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + float *mvx3_int, float *mvy3_int, vector_ptr mv_ref1, vector_ptr mv_ref2, + vector_ptr mv_ref3, int hor, int ver, int level, int remaining_frs, + videoinfo info ) +{ + int i; + int cx, cy, px, py, cpos, ppos, case1, case2; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *hweight, *lweight, *fweight, fweight_sum; + float *ltmp0, *ltmp1, *ptmp0, *ptmp1, ptmp0_sum, ptmp1_sum; + unsigned char *pused0, *pused1; + + //std::cout << level << ((mv_ref1==NULL)?0:1) <<" "<< ((mv_ref2==NULL)?0:1)<< " " << ((mv_ref3==NULL)?0:1)<< " " <= 0 && SLTF_range < 10 ); + assert( SHTF_x_range >= 0 && SHTF_x_range < 10 ); + assert( SHTF_y_range >= 0 && SHTF_y_range < 10 ); + + // initialize SHTF_filter + SHTF_filter_size = (2 * SHTF_x_range + 1) * (2 * SHTF_y_range + 1) ; // 默认算出为1 + + SHTF_filter = ( float * )getarray( SHTF_filter_size, sizeof( float ), "SHTF_filter" ); + fweight = ( float * )getarray( SHTF_filter_size, sizeof( float ), "fweight" ); + ptmp0 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp0" ); + ptmp1 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp1" ); + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + SHTF_filter[fpos] = 1.0f / SHTF_filter_size; + } + + /* generate temporal high subband H1 */ +#ifdef COUT_MV_UPDATE + int UVcom = 0; + if (info.ywidth != hor) { + UVcom = 1; + } + char name[256], data_file_name[256], start[10]; + strncpy(name, info.bitname, strlen(info.bitname) - 4); + name[strlen(info.bitname) - 4] = '\0'; + sprintf(data_file_name, "%s_enc_mv_update_test_yuv.txt", name); + std::ofstream myfile(data_file_name, std::ios::app); + if (myfile.is_open() == NULL) + { + std::cout << "open file_y failed" << std::endl; + exit(0); + } + //if(UVcom==0) + myfile << "new frame! It is UV " << UVcom << "\n"; + +#endif + + if( mv_ref2 != NULL || mv_ref3 != NULL ){ + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { // 逐像素处理 + cpos = cy * hor + cx; // 第几个像素点 + +#ifdef COPYCOMPENSATION_WEIGHTING + // assert(SHTF_filter_size == 1); // commented out by Yongjun Wu + comp_weight = 1.0f; +#endif + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // when the pixel is in directional IBLOCK, continue + if ( mv_ref2 != NULL && mv_ref3 != NULL ) + { + if ( mvx2[cpos] == (float)HUGE_VAL && mvy2[cpos] == (float)HUGE_VAL && + mvx3[cpos] == (float)HUGE_VAL && mvy3[cpos] == (float)HUGE_VAL && + mvx2_int[cpos] == (float)HUGE_VAL && mvy2_int[cpos] == (float)HUGE_VAL && + mvx3_int[cpos] == (float)HUGE_VAL && mvy3_int[cpos] == (float)HUGE_VAL ) + { + case_intra++; + continue; + } + } else if ( mv_ref2 != NULL && mv_ref3 == NULL) + { + if ( mvx2[cpos] == (float)HUGE_VAL && mvy2[cpos] == (float)HUGE_VAL && + mvx2_int[cpos] == (float)HUGE_VAL && mvy2_int[cpos] == (float)HUGE_VAL ) + { + case_intra++; + continue; + } + } else if ( mv_ref2 == NULL && mv_ref3 != NULL ) + { + if ( mvx3[cpos] == (float)HUGE_VAL && mvy3[cpos] == (float)HUGE_VAL && + mvx3_int[cpos] == (float)HUGE_VAL && mvy3_int[cpos] == (float)HUGE_VAL ) + { + case_intra++; + continue; + } + } +#endif + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + fweight[fpos] = 0.0; + ptmp0[fpos] = 0.0; + ptmp1[fpos] = 0.0; + } + fweight_sum = ptmp0_sum = ptmp1_sum = 0.0; + pfx0 = pfy0 = pfx1 = pfy1 = 0.0; + + // get nearest inbound position 防止出界,但是默认情况下,不会出界 + tx_min = (cx - SHTF_x_range <= 0) ? 0 : cx - SHTF_x_range; + ty_min = (cy - SHTF_y_range <= 0) ? 0 : cy - SHTF_y_range; + tx_max = (cx + SHTF_x_range >= hor - 1) ? hor - 1 : cx + SHTF_x_range; + ty_max = (cy + SHTF_y_range >= ver - 1) ? ver - 1 : cy + SHTF_y_range; + + for (ty = ty_min, fy = 0; ty <= ty_max; ty++, fy++){ + for (tx = tx_min, fx = 0; tx <= tx_max; tx++, fx++){ // SHTF_range大于0时才会多次执行,否则仅仅一次 + tpos = ty * hor + tx; // absolute position in MV / image arrays + fpos = fy * (2 * SHTF_x_range + 1) + fx; // relative position in SHTF_filter array + assert( fpos >= 0 && fpos < SHTF_filter_size ); +#ifdef COUT_MV_UPDATE + //if (UVcom == 0) + { + if (ty % 4 == 0 && tx % 4 == 0) + { + float left_mvx, left_mvy, right_mvx, right_mvy; + // here the set of motion vectors are for Y component + left_mvx = (mvx2[tpos] == (float)HUGE_VAL) ? mvx2_int[tpos] : mvx2[tpos]; + left_mvy = (mvy2[tpos] == (float)HUGE_VAL) ? mvy2_int[tpos] : mvy2[tpos]; + right_mvx = (mvx3[tpos] == (float)HUGE_VAL) ? mvx3_int[tpos] : mvx3[tpos]; + right_mvy = (mvy3[tpos] == (float)HUGE_VAL) ? mvy3_int[tpos] : mvy3[tpos]; + if (left_mvx != (float)HUGE_VAL && left_mvy != (float)HUGE_VAL && right_mvx != (float)HUGE_VAL && right_mvy != (float)HUGE_VAL) // 两个参考帧都可以参考 + { + myfile << "0p " << " "<< ty/4 <<" "<= 0. && fweight[fpos] <= 1. ); + fweight_sum += fweight[fpos]; + ptmp0_sum += hweight[0] * fweight[fpos] * ptmp0[fpos]; + ptmp1_sum += hweight[2] * fweight[fpos] * ptmp1[fpos]; + + } // tx + } // ty + + //////////////////////////////////// + if(pfx0 < 0 || pfx0 >= hor) + printf("error in pfx0 = %f\n",pfx0); + if(pfx1 < 0 || pfx1 >= hor) + printf("error in pfx1 = %f\n",pfx1); + if(pfy0 < 0 || pfy0 >= ver) + printf("error in pfy0 = %f\n",pfy0); + if(pfy1 < 0 || pfy1 >= ver) + printf("error in pfy1 = %f\n",pfy1); + //////////////////////////////////// + + + // transition filtering + ptmp0_sum = (fweight_sum == 0) ? 0.0f : (ptmp0_sum / fweight_sum); + ptmp1_sum = (fweight_sum == 0) ? 0.0f : (ptmp1_sum / fweight_sum); + +#ifdef COPYCOMPENSATION_WEIGHTING + H1[cpos] = comp_weight * ( ptmp0_sum + hweight[1] * fr2[cpos] + ptmp1_sum ); +#ifdef COUT_MV_UPDATE + //myfile << H1[cpos]<< " " << fr2[cpos]<< " "<= 240 && cx < 256 && cy >= 192 && cy < 208 && hor == 352) + if(hor == 352) + sad += fabs(H1[cpos]); + +// printf("%f\t",fabs(H1[cpos])); + + } +// printf("\n"); + } + +// printf("max = %f, min = %f\n",max,min); + + if( SHTF_x_range > 0) + printf("SHTF (%d pixels)\n", SHTF_x_range ); + assert(case_biCon + case_leftCon + case_rightCon + case_biPred + + case_leftPred + case_rightPred + case_intra == hor * ver); + + }else{ // copy frame component + for( cpos = 0; cpos < hor * ver; cpos++ ) { +#ifdef COPYCOMPENSATION_WEIGHTING + H1[cpos] = copycomp_weight_high[level] * HPW4[1] * fr2[cpos]; +#else + H1[cpos] = HPW4[1] * fr2[cpos]; +#endif + } + case_intra = hor * ver; + } + +// if(hor == 352) +// printf("sad = %f\n",sad); + + /* generate temporal low subband L1 */ + + // step 1 - motion compensation of H0 and H1 + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { // 遍历H0 + cpos = cy * hor + cx; + + if ( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ){ + pfx0 = cx - mvx1[cpos]; //低频帧中对应的位置 + pfy0 = cy - mvy1[cpos];//低频帧中对应的位置 + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver ); // 返回整数位置 + ppos = py * hor + px; + assert((ppos >= 0) && ppos < (hor * ver)); + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; + + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); + pused0[ppos] = USED; +#ifdef COUT_MV_UPDATE + //if (UVcom == 0) + { + //if (py % 4 == 0 && px % 4 == 0) // 4倍下采样 + //{ + // float left_mvx, left_mvy, right_mvx, right_mvy; + // // here the set of motion vectors are for Y component + // left_mvx = mvx1[cpos]; + // left_mvy = mvy1[cpos]; + // myfile << "1u " << py/4 <<" "<< px/4 << " " << left_mvx << " " << left_mvy << "\n"; + // //myfile << "1u " < 0.0 && SLTF_weight <= 1.0); + if( SLTF_weight != 1.0 ) tcase++; + } + + assert( ppos >= 0 && ppos < hor * ver ); + L1[ppos] = SLTF_weight * ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] ) + lweight[1] * fr1[ppos]; +#ifdef COUT_MV_UPDATE + //myfile <<"u "< 0) + printf("SLTF (%d pixels) -- connected %d, transitions %d, unconnected %d\n", SLTF_range, case1-tcase, tcase, case2 ); + + /* checking */ + if (case1 + case2 != hor * ver) { + printf( "error in lifting.c -- connected: %d, unconnected: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ) { +#ifdef COPYCOMPENSATION_WEIGHTING + L1[ppos] = copycomp_weight_low[level] * LPW4[1] * fr1[ppos]; +#else + L1[ppos] = LPW4[1] * fr1[ppos]; +#endif + } + } +#ifdef COUT_MV_UPDATE + myfile.close(); +#endif + + free( SHTF_filter ); + free( fweight ); + free( ptmp0 ); + free( ptmp1 ); + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + + +// scale down the motion vectors by 2 for U V components +void +scale_down_mv_by_scale( float *mvx, float *mvy, videoinfo info, int t_level, int shift ) +{ + float dx, dy; + int t, precision, scale; + + if ( *mvx==(float)HUGE_VAL && *mvy==(float)HUGE_VAL ) + return; + + scale = 1<0) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, s_level ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, s_level ); + } + + ptmp0 = ptmp1 = (float)0.0; + if( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL && + right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL) // 双向预测 + { + hweight = HPW1; // default mode (bi-directional) + if (UVcom) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + } + pfx0 = cx - left_mvx; // 在参考帧的位置 + pfy0 = cy - left_mvy; + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + if( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ){ + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + *neighbor_value += (ptmp0*hweight[0]+ptmp1*hweight[2])*neighbor_weight; + } + else // raise self weight to compensate for invalid neighbor motion vector 提高自身的权重来补偿邻居的权重 + *self_weight += neighbor_weight; + } + else if ( right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL ) // 前向预测 + { + hweight = HPW2; // forward mode + if (UVcom) + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + if( inbound( pfx1, pfy1, hor, ver ) ){ + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); + *neighbor_value += ptmp1*hweight[2]*neighbor_weight; + }else + *self_weight += neighbor_weight; + }else if ( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL){ + hweight = HPW3; // backward mode + if (UVcom) + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + pfx0 = cx - left_mvx; + pfy0 = cy - left_mvy; + if( inbound( pfx0, pfy0, hor, ver ) ){ + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + *neighbor_value += ptmp0*hweight[0]*neighbor_weight; + }else + *self_weight += neighbor_weight; + }else + assert(0); +} + + +// 通过自身mv获得预测值 +void get_value_for_self_mv(int pos, ImageMEinfo *imagemeinfo, float *fr1, float *fr3, + float *self_value, float self_weight, + int cx, int cy, videoinfo info, int hor, int ver, + int *case_bi, int *case_left, int *case_right, + int UVcom, int t_level) +{ + float *hweight; + float ptmp0, ptmp1; + float pfx0, pfy0, pfx1, pfy1; + float left_mvx, left_mvy, right_mvx, right_mvy; + int s_level; + + // here the set of motion vectors are for Y component + left_mvx = imagemeinfo[pos].left_mvx; // 左侧mv的x信息 + left_mvy = imagemeinfo[pos].left_mvy; + right_mvx = imagemeinfo[pos].right_mvx; + right_mvy = imagemeinfo[pos].right_mvy; + // scale down the self motion vector by corresponding resolution reduction + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + if (s_level>0) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, s_level ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, s_level ); + } + ptmp0 = ptmp1 = (float)0.0; + if( left_mvx != (float)HUGE_VAL && + left_mvy != (float)HUGE_VAL && + right_mvx!= (float)HUGE_VAL && + right_mvy!= (float)HUGE_VAL) // 两个参考帧都可以参考 + { + hweight = HPW1; // default mode (bi-directional) + if (UVcom) + { + scale_down_mv_by_scale( &left_mvx, &left_mvy, info, t_level, 1 ); + scale_down_mv_by_scale( &right_mvx, &right_mvy, info, t_level, 1 ); + } + pfx0 = cx - left_mvx; // 获取参考像素的位置 + pfy0 = cy - left_mvy; + pfx1 = cx - right_mvx; + pfy1 = cy - right_mvy; + if ( ! ( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ) ) + printf("Error here\n"); + assert( inbound( pfx0, pfy0, hor, ver ) && + inbound( pfx1, pfy1, hor, ver ) ); + ptmp0 = interpolate( pfx0, pfy0, fr1, hor, ver, TYPE ); + ptmp1 = interpolate( pfx1, pfy1, fr3, hor, ver, TYPE ); +// 块级写出 + // information for current block in Y coordinate with full resolution +// if (!UVcom) +// { +// int leftx = imagemeinfo[pos].leftx; +// int topy = imagemeinfo[pos].topy; // 这个块上边界在图像中的位置 +// int xblk = imagemeinfo[pos].blksize; +// int yblk = imagemeinfo[pos].blksize; +// //printf("%d, %d, %d, %d\n", cx, cy, topy, leftx); +// if (leftx == cx && topy == cy) +// { +// //std::ofstream myfile("interpolate fream.txt", std::ios::app); +// for (int block_h = cy; block_h < topy + yblk; block_h++) +// { +// for (int block_w = cx; block_w < leftx + xblk; block_w++) +// { +// int count = (block_w - cx) + (block_h - cy) * yblk; +// int cnn_pos = block_h * hor + block_w; +// //printf("%d, %d, %d\n", cnn_pos, block_h, block_w); +// float cnn_pfx0 = block_w - left_mvx; // 获取参考像素的位置 +// float cnn_pfy0 = block_h - left_mvy; +// float cnn_pfx1 = block_w - right_mvx; +// float cnn_pfy1 = block_h - right_mvy; +// if (!(inbound(cnn_pfx0, cnn_pfy0, hor, ver) && +// inbound(cnn_pfx1, cnn_pfy1, hor, ver))) +// continue; +// //if (!(inbound(cnn_pfx0, cnn_pfy0, hor, ver) && +// // inbound(cnn_pfx1, cnn_pfy1, hor, ver))) +// // printf("Error here\n"); +// //assert(inbound(cnn_pfx0, cnn_pfy0, hor, ver) && +// // inbound(cnn_pfx1, cnn_pfy1, hor, ver)); +// imagemeinfo[cnn_pos].cnn_ptmp0 = interpolate(cnn_pfx0, cnn_pfy0, fr1, hor, ver, TYPE); +// imagemeinfo[cnn_pos].cnn_ptmp1 = interpolate(cnn_pfx1, cnn_pfy1, fr3, hor, ver, TYPE); +// //myfile << cnn_pos << " " << imagemeinfo[cnn_pos].cnn_ptmp0 << " " << imagemeinfo[cnn_pos].cnn_ptmp1 << "\n"; +// } +// } +// //myfile.close(); +// } + + *self_value = (ptmp0*hweight[0] + ptmp1 * hweight[2])*self_weight; // 通过mv自身权重获得的补偿值 + (*case_bi)++; +#ifdef CNN_TEMPORAL_WAVELET + /*******写出*****/ + //std::cout<< "mv*** "< <--- */ +/* | | */ +/* frp fr0 | fr1 fr2| fr3 */ +/* . . . |/ | \ | |/ */ +/* . . . / | \ | / */ +/* . . ./| | \ |/| */ +/* . H0 | | H1 | */ +/* . .\ | | / | */ +/* . . \| | / | */ +/* . . | | / | */ +/* . . |\ | / | */ +/* .. | \|/ | */ +/* L0 | L1 | */ +/* | | */ +/* */ +/* INPUT: H0, fr1, fr2, fr3, mv1, mv2, mv3 */ +/* OUTPUT: L1, H1 */ +/* 输出高频帧和低频帧 */ +/*****************************************************************************/ + +int count = 0; + +void +mc_analysis_with_OBMC( float *L1, float *H1, float *H0, float *fr1, float *fr2, float *fr3, + float *mvx1, float *mvy1, float *mvx2, float *mvy2, float *mvx3, float *mvy3, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + float *mvx3_int, float *mvy3_int, vector_ptr mv_ref1, vector_ptr mv_ref2, + vector_ptr mv_ref3, int hor, int ver, int level, int remaining_frs, + videoinfo info, ImageMEinfo *imagemeinfo, Varblkarrayinfo *varblkarray, int UVcom, + enum FLAG left_scene, enum FLAG right_scene, int type) +{ + int i; + int cx, cy, px, py, cpos, com_pos, ppos, case1, case2; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *lweight; + float *ltmp0, *ltmp1; + unsigned char *pused0, *pused1; + int leftx, topy, xblk, yblk, disx, disy, col, row, pos; + float self_weight, ver_weight, hor_weight; + float self_value, neighbor_value; + int case_bi, case_left, case_right, case_intra; // 用于记录采用这四种预测模式的像素的个数 + float sad = 0; + + float getnum, diff; + int pixel_count; + FILE *pc; + + // UVcom: indication for U V component + // for U V components we use the sub-sampled weighting coefficients + +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + //float comp_weight = 1; + // the variables for update step in MCTF 用于update的变量 整帧处理 + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + for( i = 0; i < hor * ver; i++ ) + { + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } +#ifdef CNN_TEMPORAL_WAVELET + char name[256], data_file_name[256], start[10]; + strncpy(name, info.bitname, strlen(info.bitname) - 9); + name[strlen(info.bitname) - 9] = '\0'; + sprintf(data_file_name, "%s_enc_mv_org_yuv.txt", name); + std::ofstream myfile(data_file_name, std::ios::app); + if (myfile.is_open() == NULL) + { + std::cout << "open file_y failed" << std::endl; + exit(0); + } + myfile << "new frame! It is UV "<> 1)) { // top neighbor is effective 当前像素到哪边更近,这里是到上面更近 + pos = (topy-3)*(hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1, fr3, &neighbor_value, + &self_weight, ver_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disy >= (yblk >> 1)) { // bottom neighbor is effective + pos = (topy+yblk+2)*(hor<> 1)) { // left neighbor is effective + pos = row*(hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, fr1, fr3, &neighbor_value, + &self_weight, hor_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disx >= (xblk >> 1)) { // right neighbor is effective + pos = row*(hor<= 9 || (imagemeinfo[cpos].bi_mode == 7 && ) ) + fr2[com_pos] = fr2[com_pos] / 0.4; + } + + if(UVcom == 0 && level == 0){ + if(imagemeinfo[cpos].mrg_blk_bdr == 1) + fr2[cpos] = 255; + } +*/ //////////////////////////////////////////////////// +/* //MARK TWO COMP + if( type == 1 && level == 0 ){ + if(imagemeinfo[cpos].two_comp_src == 1) + fr2[com_pos] = fr2[com_pos] / 0.4; + } + + if(UVcom == 0 && level == 0){ + if(imagemeinfo[cpos].two_comp_bdr == 1) + fr2[cpos] = 255; + } +*/ //////////////////////////////////////////////////// + if(imagemeinfo[cpos].skip_sign == YES){ + H1[com_pos] = 0; + }else + H1[com_pos] = comp_weight * ( HPW1[1] * fr2[com_pos] + self_value + neighbor_value );// 计算出来H1 +#ifdef CNN_TEMPORAL_WAVELET + //myfile << cpos <<"\n"; + myfile << com_pos << " " << H1[com_pos] << " " << fr1[com_pos] << " " << fr2[com_pos] << " " << fr3[com_pos] << "\n"; +#endif + } + } + +} + else // if( left_scene == NO || right_scene == NO ) + { // copy frame component + for( cpos = 0; cpos < hor * ver; cpos++ ) { // 逐个像素去做,使用的是帧内模式 +#ifdef COPYCOMPENSATION_WEIGHTING + H1[cpos] = copycomp_weight_high[level] * HPW4[1] * fr2[cpos]; +#else + H1[cpos] = HPW4[1] * fr2[cpos]; +#endif + } + case_intra = hor * ver; + } +#ifdef CNN_TEMPORAL_WAVELET + myfile.close(); +#endif + assert(case_intra + case_bi + case_left + case_right == hor*ver ); + /* generate temporal low subband L1 生成低频帧*/ + // step 1 - motion compensation of H0 and H1 运动补偿 + for( cy = 0; cy < ver; cy++ ) { + for( cx = 0; cx < hor; cx++ ) { + cpos = cy * hor + cx; // 当前位置 + if ( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ) // 是否接受左边高频帧的更新 + { + pfx0 = cx - mvx1[cpos]; + pfy0 = cy - mvy1[cpos]; // 在参考图像中的位置 + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver ); + ppos = py * hor + px; // 取整之后的位置 + assert((ppos >= 0) && ppos < (hor * ver)); + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; // 当前位置的浮点位置 + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); + pused0[ppos] = USED; + } + } + } + } + + + for( cy = 0; cy < ver; cy++ ) { // 右侧高频帧更新 + for( cx = 0; cx < hor; cx++ ) { + cpos = cy * hor + cx; + if ( mvx2[cpos] != (float)HUGE_VAL && mvy2[cpos] != (float)HUGE_VAL ){ + pfx1 = cx - mvx2[cpos]; + pfy1 = cy - mvy2[cpos]; + position( &px, &py, pfx1, pfy1, mvx2[cpos], mvy2[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx2[cpos]; + cfy = py + mvy2[cpos]; + if( pused1[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + ltmp1[ppos] = interpolate( cfx, cfy, H1, hor, ver, TYPE ); + pused1[ppos] = USED; + } + } + } + } + + + case1 = 0; + case2 = 0; + // step 2 - calculation of L1 + //mv_ref1 = NULL; + //mv_ref2 = NULL; + + if (mv_ref1 != NULL || mv_ref2 != NULL) // 有参考 + //if (0) // 有参考 + { + for( py = 0; py < ver; py++ ) { + for (px = 0; px < hor; px++) { + ppos = py * hor + px; + + if( pused0[ppos] == USED && pused1[ppos] == USED ){ + lweight = LPW1; // default mode (bi-directional) + case1++; + } + else if( pused0[ppos] == UNUSED && pused1[ppos] == USED ){ + lweight = LPW2; // forward mode + case1++; + } + else if( pused0[ppos] == USED && pused1[ppos] == UNUSED ){ + lweight = LPW3; // backward mode + case1++; + } + else{ + lweight = LPW4; // unconnected pixels + case2++; + } + assert( ppos >= 0 && ppos < hor * ver ); +#ifdef NO_UPDATE + //lweight[1] = LPW4[1] * copycomp_weight_low[level]; + //lweight[0] = 0; + //lweight[2] = 0; + //printf("%f, %f, %f\n", lweight[0], lweight[1], lweight[2]); + //L1[ppos] = LPW4[1] * copycomp_weight_low[level] * fr1[ppos]; // 计算出L1 + lweight = LPW4; + L1[ppos] = (lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos]) + lweight[1] * fr1[ppos]; // 计算出L1 +#else + L1[ppos] = ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] ) + lweight[1] * fr1[ppos]; // 计算出L1 +#endif + + /**************写出**********/ + //{ + // char name[256], data_file_name[256], start[10]; + // strncpy(name, info.bitname, strlen(info.bitname) - 9); + // name[strlen(info.bitname) - 9] = '\0'; + // sprintf(data_file_name, "%s_L.txt", name); + // std::ofstream myfile(data_file_name, std::ios::app); + // if (myfile.is_open() == NULL) + // { + // std::cout << "open file_y failed" << std::endl; + // exit(0); + // } + // myfile << ppos << " " << L1[ppos] << "\n"; + // myfile.close(); + //} + /**************写出**********/ + } + } +/* + if(UVcom == 0 && level == 0){ + diff = 0; pixel_count = 0; +// printf("MV matrix:\n\n"); + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = ( cy<= 0 ); + if(diff > global_motion_active) + global_motion_active = diff; + + pc = fopen("enc_block.txt","at"); + fprintf(pc,"%f\n",diff); + fclose(pc); + }//if UVcom = 0 +*/ + // checking + if (case1 + case2 != hor * ver) { + printf( "error in lifting.c -- connected: %d, unconnected: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ) { +#ifdef COPYCOMPENSATION_WEIGHTING + L1[ppos] = copycomp_weight_low[level] * LPW4[1] * fr1[ppos]; // 计算出L1 +#else + L1[ppos] = LPW4[1] * fr1[ppos]; +#endif + } + } + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + +/*****************************************************************************/ +/* mc_analysis() */ +/* */ +/* mv1 mv2 mv3 */ +/* <--- ---> <--- */ +/* | | */ +/* frp fr0 | fr1 fr2| fr3 */ +/* . . . |/ | \ | |/ */ +/* . . . / | \ | / */ +/* . . ./| | \ |/| */ +/* . H0 | | H1 | */ +/* . .\ | | / | */ +/* . . \| | / | */ +/* . . | | / | */ +/* . . |\ | / | */ +/* .. | \|/ | */ +/* L0 | L1 | */ +/* | | */ +/* */ +/* INPUT: H0, fr1, fr2, fr3, mv1, mv2, mv3 */ +/* OUTPUT: L1, H1 */ +/* */ +/*****************************************************************************/ + + +/*****************************************************************************/ +/* mc_synthesis() */ +/* */ +/* mv0 mv1 mv2 */ +/* ---> <--- ---> */ +/* | | | */ +/* frp | fr0 fr1 | fr2 fr3 | */ +/* . \| | / | \| . . . .| */ +/* . \ | / | \ . . . . */ +/* . |\ | / | |\ . . . |. */ +/* . | H0 | | H1 . | H2 */ +/* . | | | . | */ +/* . | | | . | */ +/* . | | | . | */ +/* L0 | L1 | L2 | */ +/* | | | */ +/* */ +/* INPUT: H0, L1, H1, frp, mv0, mv1, mv2 */ +/* OUTPUT: fr0, fr1 */ +/* */ +/*****************************************************************************/ +void +mc_synthesis( float *fr0, float *fr1, float *H0, float *L1, float *H1, float *frp, + float *mvx0, float *mvy0, float *mvx1, float *mvy1, + float *mvx2, float *mvy2, float *mvx0_int, float *mvy0_int, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + vector_ptr mv_ref0, vector_ptr mv_ref1, vector_ptr mv_ref2, + int hor, int ver, int level, videoinfo info ) +{ + int i; + int cx, cy, px, py, cpos, ppos, case1, case2, case3; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *hweight, *lweight, *fweight, fweight_sum; + float *ltmp0, *ltmp1, *ptmp0, *ptmp1, ptmp0_sum, ptmp1_sum; + unsigned char *pused0, *pused1; + + int SLTF_range, SHTF_x_range, SHTF_y_range, SHTF_filter_size; + int tx, ty, tpos, tcase, tx_min, ty_min, tx_max, ty_max; + int fx, fy, fpos; + float SLTF_weight = 1.0, *SHTF_filter; +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + + // step 0 - calculation of fr1 (A) / scene_change propagation + if (level < info.t_level) + { + if( mv_ref1 != NULL || mv_ref2 != NULL ) + { + for( ppos = 0; ppos < hor * ver; ppos++ ) + { + fr1[ppos] = L1[ppos] / LPW4[1]; // 第一次合成 + } + } + else + { + for( ppos = 0; ppos < hor * ver; ppos++ ) + { +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + return; + } + + + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + + for( i = 0; i < hor * ver; i++ ){ + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } + + SLTF_range = info.SLTF_range; + SHTF_x_range = info.SHTF_range; + SHTF_y_range = info.SHTF_range; + + assert( SLTF_range >= 0 && SLTF_range < 10 ); + assert( SHTF_x_range >= 0 && SHTF_x_range < 10 ); + assert( SHTF_y_range >= 0 && SHTF_y_range < 10 ); + + // initialize SHTF_filter + SHTF_filter_size = (2 * SHTF_x_range + 1) * (2 * SHTF_y_range + 1) ; + + SHTF_filter = ( float * )getarray( SHTF_filter_size, sizeof( float ), "SHTF_filter" ); + fweight = ( float * )getarray( SHTF_filter_size, sizeof( float ), "fweight" ); + ptmp0 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp0" ); + ptmp1 = ( float * )getarray( SHTF_filter_size, sizeof( float ), "ptmp1" ); + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + SHTF_filter[fpos] = 1.0f / SHTF_filter_size; + } +#ifdef COUT_MV_UPDATE + + int UVcom = 0; + if (info.ywidth != hor) { + UVcom = 1; + } + bool new_file = 0; + char name[256], data_file_name[256], start[10]; + strncpy(name, info.bitname, strlen(info.bitname) - 4); + name[strlen(info.bitname) - 4] = '\0'; + sprintf(data_file_name, "%s_dec_mv_update_test_yuv.txt", name); + + { // 判断是否为新创建的文件 + std::ifstream fin(data_file_name); + if (!fin) + new_file = 1; + else + fin.close(); + } + + std::ofstream myfile(data_file_name, std::ios::app); + if (myfile.is_open() == NULL) + { + std::cout << "open file_y failed" << std::endl; + exit(0); + } + if (new_file) + { + myfile << "frame number: " << info.last - info.start + 1 << "\n"; + myfile << "width height: " << info.ywidth <<" "<< info.yheight << "\n"; + } + myfile << "new frame! It is UV " << UVcom << "\n"; +#endif + /* reconstruction of fr1 (A) */ + + // step 1 - motion compensation of H0 and H1 + // MC of H0 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ) { + pfx0 = cx - mvx1[cpos]; + pfy0 = cy - mvy1[cpos]; + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; + + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ){ + pused0[ppos] = USED; + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); +#ifdef COUT_MV_UPDATE + { + //if (py % 4 == 0 && px % 4 == 0) { // 4倍下采样 + // float left_mvx, left_mvy, right_mvx, right_mvy; + // // here the set of motion vectors are for Y component + // left_mvx = mvx1[cpos]; + // left_mvy = mvy1[cpos]; + // myfile << "1u " << py / 4 << " " << px / 4 << " " << left_mvx << " " << left_mvy << "\n"; + // //myfile << "1u " < 0.0 && SLTF_weight <= 1.0); + if( SLTF_weight != 1.0 ) tcase++; + } + + assert( ppos >= 0 && ppos < hor * ver ); + fr1[ppos] = 1 / lweight[1] * ( L1[ppos] - SLTF_weight * ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] )); + //std::cout << lweight[1] <<" "< 0) + printf("SLTF (%d pixels) -- connected %d, transitions %d, unconnected %d\n", SLTF_range, case1-tcase, tcase, case2 ); + + /* checking */ + if( case1 + case2 != hor * ver ){ + printf( "error in mctf() covered: %d, uncovered: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ){ + // fr1[ppos] = 1 / LPW4[1] * L1[ppos]; +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + + case1 = case2 = case3 = 0; + + /* reconstruction of fr0 (B) */ + //double sum_predict = 0; + //double sum_predict_H = 0; + //double sum_predict_pre = 0; + if( mv_ref0 != NULL || mv_ref1 != NULL ){ + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + +#ifdef COPYCOMPENSATION_WEIGHTING + // assert(SHTF_filter_size == 1); // commented by Yongjun Wu + comp_weight = 1.0f; +#endif + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // when the pixel is in directional IBLOCK, continue + if ( mv_ref0 != NULL && mv_ref1 != NULL ) + { + if ( mvx0[cpos] == (float)HUGE_VAL && mvy0[cpos] == (float)HUGE_VAL && + mvx1[cpos] == (float)HUGE_VAL && mvy1[cpos] == (float)HUGE_VAL && + mvx0_int[cpos] == (float)HUGE_VAL && mvy0_int[cpos] == (float)HUGE_VAL && + mvx1_int[cpos] == (float)HUGE_VAL && mvy1_int[cpos] == (float)HUGE_VAL ) + { + case3++; + continue; + } + } else if ( mv_ref0 != NULL && mv_ref1 == NULL) + { + if ( mvx0[cpos] == (float)HUGE_VAL && mvy0[cpos] == (float)HUGE_VAL && + mvx0_int[cpos] == (float)HUGE_VAL && mvy0_int[cpos] == (float)HUGE_VAL ) + { + case3++; + continue; + } + + } else if ( mv_ref0 == NULL && mv_ref1 != NULL ) + { + if ( mvx1[cpos] == (float)HUGE_VAL && mvy1[cpos] == (float)HUGE_VAL && + mvx1_int[cpos] == (float)HUGE_VAL && mvy1_int[cpos] == (float)HUGE_VAL ) + { + case3++; + continue; + } + } +#endif + + for( fpos = 0; fpos < SHTF_filter_size; fpos++ ){ + fweight[fpos] = 0.0; + ptmp0[fpos] = 0.0; + ptmp1[fpos] = 0.0; + } + + // get nearest inbound position + tx_min = (cx - SHTF_x_range <= 0) ? 0 : cx - SHTF_x_range; + ty_min = (cy - SHTF_y_range <= 0) ? 0 : cy - SHTF_y_range; + tx_max = (cx + SHTF_x_range >= hor - 1) ? hor - 1 : cx + SHTF_x_range; + ty_max = (cy + SHTF_y_range >= ver - 1) ? ver - 1 : cy + SHTF_y_range; + + fweight_sum = ptmp0_sum = ptmp1_sum = 0.0; + pfx0 = pfy0 = pfx1 = pfy1 = 0.0; + + for (ty = ty_min, fy = 0; ty <= ty_max; ty++, fy++){ + for (tx = tx_min, fx = 0; tx <= tx_max; tx++, fx++){ + + tpos = ty * hor + tx; // absolute position in MV / image arrays + fpos = fy * (2 * SHTF_x_range + 1) + fx; // relative position in SHTF_filter array + assert( fpos >= 0 && fpos < SHTF_filter_size ); +#ifdef COUT_MV_UPDATE + if (ty % 4 == 0 && tx % 4 == 0) + { + float left_mvx, left_mvy, right_mvx, right_mvy; + // here the set of motion vectors are for Y component + left_mvx = (mvx0[tpos] == (float)HUGE_VAL) ? mvx0_int[tpos] : mvx0[tpos]; + left_mvy = (mvy0[tpos] == (float)HUGE_VAL) ? mvy0_int[tpos] : mvy0[tpos]; + right_mvx = (mvx1[tpos] == (float)HUGE_VAL) ? mvx1_int[tpos] : mvx1[tpos]; + right_mvy = (mvy1[tpos] == (float)HUGE_VAL) ? mvy1_int[tpos] : mvy1[tpos]; + if (left_mvx != (float)HUGE_VAL && left_mvy != (float)HUGE_VAL && right_mvx != (float)HUGE_VAL && right_mvy != (float)HUGE_VAL) // 两个参考帧都可以参考 + { + myfile << "0p " << " "<< ty/4 <<" "<= 0. && fweight[fpos] <= 1. ); + fweight_sum += fweight[fpos]; + ptmp0_sum += hweight[0] * fweight[fpos] * ptmp0[fpos]; + ptmp1_sum += hweight[2] * fweight[fpos] * ptmp1[fpos]; + + } // tx + } // ty + + // transition filtering + ptmp0_sum = (fweight_sum == 0) ? 0.0f : (ptmp0_sum / fweight_sum); + ptmp1_sum = (fweight_sum == 0) ? 0.0f : (ptmp1_sum / fweight_sum); + +// printf("%f\t",fabs(H0[cpos])); + +#ifdef COPYCOMPENSATION_WEIGHTING + fr0[cpos] = 1 / hweight[1] * ( - ptmp0_sum + H0[cpos] / comp_weight - ptmp1_sum ); + //sum_predict += (fr0[cpos]); + //sum_predict_H += (H0[cpos])/ hweight[1]; + //sum_predict_pre += ( - ptmp0_sum - ptmp1_sum)/ hweight[1]; +#else + fr0[cpos] = 1 / hweight[1] * ( - ptmp0_sum + H0[cpos] - ptmp1_sum ); +#endif + } +// printf("\n"); + } + //if (hor == 832) + //{ + // std::cout.precision(10); + // std::cout << "predict " << sum_predict << std::endl; + // std::cout << "predict_H " << sum_predict_H << std::endl; + // std::cout << "predict_pre " << sum_predict_pre << std::endl; + //} + + if( SHTF_x_range > 0) + printf("SHTF (%d pixels)\n", SHTF_x_range ); + + /* checking */ + if( case1 + case2 + case3 != hor * ver ){ + printf( "error in lifting.c -- default: %d, intra: %d\n", case1, case2 ); + exit( 1 ); + } + } + else{ // copy frame component + for( cpos = 0; cpos < hor * ver; cpos++ ){ + // fr0[cpos] = 1 / HPW4[1] * H0[cpos]; +#ifdef COPYCOMPENSATION_WEIGHTING + fr0[cpos] = H0[cpos] / (HPW4[1] * copycomp_weight_high[level]); +#else + fr0[cpos] = H0[cpos]; +#endif + } + } +#ifdef COUT_MV_UPDATE + myfile.close(); +#endif + free( SHTF_filter ); + free( fweight ); + free( ptmp0 ); + free( ptmp1 ); + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + + +/*****************************************************************************/ +/* mc_synthesis() */ +/* */ +/* mv0 mv1 mv2 */ +/* ---> <--- ---> */ +/* | | | */ +/* frp | fr0 fr1 | fr2 fr3 | */ +/* . \| | / | \| . . . .| */ +/* . \ | / | \ . . . . */ +/* . |\ | / | |\ . . . |. */ +/* . | H0 | | H1 . | H2 */ +/* . | | | . | */ +/* . | | | . | */ +/* . | | | . | */ +/* L0 | L1 | L2 | */ +/* | | | */ +/* */ +/* INPUT: H0, L1, H1, frp, mv0, mv1, mv2 */ +/* OUTPUT: fr0, fr1 */ +/* */ +/*****************************************************************************/ +// here hor, ver are the dimension for specific component and specific resolution +// fr0[com_pos] = 1 / HPW1[1] * ( - self_value + H0[com_pos] / comp_weight - neighbor_value ); +void +mc_synthesis_with_OBMC( float *fr0, float *fr1, float *H0, float *L1, float *H1, float *frp, + float *mvx0, float *mvy0, float *mvx1, float *mvy1, + float *mvx2, float *mvy2, float *mvx0_int, float *mvy0_int, + float *mvx1_int, float *mvy1_int, float *mvx2_int, float *mvy2_int, + vector_ptr mv_ref0, vector_ptr mv_ref1, vector_ptr mv_ref2, + int hor, int ver, int level, videoinfo info, + ImageMEinfo *imagemeinfo, Varblkarrayinfo *varblkarray, int UVcom, int type ) +{ + //count += 1; + //printf("%d\n", count); + int i, case1, case2; + int cx, cy, px, py, cpos, ppos, com_pos; + float cfx, cfy, pfx0, pfy0, pfx1, pfy1; + float *lweight; + float *ltmp0, *ltmp1; // 两个补偿完的帧 + unsigned char *pused0, *pused1; + int leftx, topy, xblk, yblk, disx, disy, col, row, pos; + float self_weight, ver_weight, hor_weight; + float self_value, neighbor_value; + int case_bi, case_left, case_right, case_intra ; + int s_level; + float sad; + + float getnum, getnum2, diff; + int pixel_count; + FILE *pc; + float avg_mv; + + // the spatial resolution reduction in decoder + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + +#ifdef COPYCOMPENSATION_WEIGHTING + float comp_weight; +#endif + //float comp_weight = 1; + + // step 0 - calculation of fr1 (A) / scene_change propagation// 进不来 + if (level < info.t_level) + { + if( mv_ref1 != NULL || mv_ref2 != NULL ) + { + for( ppos = 0; ppos < hor * ver; ppos++ ){ + fr1[ppos] = L1[ppos] / LPW4[1]; + } + } + else + { + for( ppos = 0; ppos < hor * ver; ppos++ ){ +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + return; + } + + // variables for update step in MCTF + pused0 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused0" ); + pused1 = ( unsigned char * )getarray( hor * ver, sizeof( unsigned char ), "pused1" ); + ltmp0 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp0" ); + ltmp1 = ( float * )getarray( hor * ver, sizeof( float ), "ltmp1" ); + for( i = 0; i < hor * ver; i++ ){ // 初始化 + pused0[i] = UNUSED; + pused1[i] = UNUSED; + ltmp0[i] = 0.0; + ltmp1[i] = 0.0; + } + + // reconstruction of fr1 (A) 根据L1,使用update,重建fr1 + // step 1 - motion compensation of H0 and H1 为H0 H1做运动补偿 但是只做了双向预测的,其他三种模式是什么情况,为啥没有做??? + // MC of H0 为H0做运动补偿 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx1[cpos] != (float)HUGE_VAL && mvy1[cpos] != (float)HUGE_VAL ) { // 有参考mv + pfx0 = cx - mvx1[cpos]; // 参考像素的x位置 + pfy0 = cy - mvy1[cpos]; // 参考像素的y位置 + position( &px, &py, pfx0, pfy0, mvx1[cpos], mvy1[cpos], hor, ver );// 返回整数位置,放在px, py + ppos = py * hor + px; // 整数位置 + cfx = px + mvx1[cpos]; + cfy = py + mvy1[cpos]; + + if( pused0[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ){ // 如果之前没有被使用 + pused0[ppos] = USED; + ltmp0[ppos] = interpolate( cfx, cfy, H0, hor, ver, TYPE ); // 根据运动补偿插出帧 + } + } + } + } + + // MC of H1 为H1做运动补偿 + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = cy * hor + cx; + + if( mvx2[cpos] != (float)HUGE_VAL && mvy2[cpos] != (float)HUGE_VAL ) { + pfx1 = cx - mvx2[cpos]; + pfy1 = cy - mvy2[cpos]; + + position( &px, &py, pfx1, pfy1, mvx2[cpos], mvy2[cpos], hor, ver ); + ppos = py * hor + px; + cfx = px + mvx2[cpos]; + cfy = py + mvy2[cpos]; + + if( pused1[ppos] == UNUSED && inbound( cfx, cfy, hor, ver ) ) { + pused1[ppos] = USED; + ltmp1[ppos] = interpolate( cfx, cfy, H1, hor, ver, TYPE ); + } + } + } + } + + case1 = case2 = 0; + // step 2 - calculation of fr1 (A) 重建fr1,一共有四种模式,双向预测、前向预测、后向预测、帧内预测 + //mv_ref1 = NULL; + //mv_ref2 = NULL; + //if (0) { + //count++; + + if (mv_ref1 != NULL || mv_ref2 != NULL) { + for( py = 0; py < ver; py++ ) { + for( px = 0; px < hor; px++ ) { + ppos = py * hor + px; + + if( pused0[ppos] == USED && pused1[ppos] == USED ){ // 表示是双向的预测 + lweight = LPW1; // default mode (bi-directional) + case1++; + } + else if( pused0[ppos] == UNUSED && pused1[ppos] == USED ){ + lweight = LPW2; // forward mode + case1++; + } + else if( pused0[ppos] == USED && pused1[ppos] == UNUSED ){ + // for this case info.bi_mv[level] must be 1 + // if info.bi_mv[level]==0, this case is impossible, + // because RIGHT_CONNECTED becomes LEFT_PREDICTED + lweight = LPW3; // backward mode + case1++; + } + else{ + lweight = LPW4; // intra mode (unconnected pixels) intra 模式 + case2++; + } + assert( ppos >= 0 && ppos < hor * ver ); +#ifdef NO_UPDATE + //lweight = LPW4; + //lweight[1] = LPW4[1] * copycomp_weight_low[level]; + //lweight[0] = 0; + //lweight[2] = 0; + //fr1[ppos] = 1 / ( LPW4[1] * copycomp_weight_low[level]) * (L1[ppos]); // 重建出的帧 + lweight = LPW4; + fr1[ppos] = 1 / lweight[1] * (L1[ppos] - (lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos])); // 重建出的帧 +#else + fr1[ppos] = 1 / lweight[1] * ( L1[ppos] - ( lweight[0] * ltmp0[ppos] + lweight[2] * ltmp1[ppos] )); // 重建出的帧 +#endif + } + } + + assert( case1 + case2 == hor * ver ); + } + else{ // copy frame component + for( ppos = 0; ppos < hor * ver; ppos++ ){ +#ifdef COPYCOMPENSATION_WEIGHTING + fr1[ppos] = L1[ppos] / (LPW4[1] * copycomp_weight_low[level]); +#else + fr1[ppos] = L1[ppos]; +#endif + } + } + + sad = 0; + + // the OBMC weighting coefficients for U V are sub-sampled version of those for Y + // the OBMC weighting coefficients for low resolution frame are + // sub-sampled version of those in full resolution + // reconstruction of fr0 (B) 重建fr0 + case_bi = case_left = case_right = case_intra = 0; + if( mv_ref0 != NULL || mv_ref1 != NULL ){ // + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = ( (cy<> 1)) { // top neighbor is effective 离上面近 + pos = (topy-3)*( (hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) // 不是最上面一行且上面的块不是帧内块 + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, frp, fr1, &neighbor_value, + &self_weight, ver_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disy >= (yblk >> 1)) { // bottom neighbor is effective 离下面近 + pos = (topy+yblk+2)*( (hor<> 1)) { // left neighbor is effective + pos = row*( (hor< 0) && imagemeinfo[pos].bi_mode != DIRECTIONAL_IBLOCK ) + get_value_for_neighbor_mv(cpos, pos, imagemeinfo, frp, fr1, &neighbor_value, + &self_weight, hor_weight, cx, cy, info, hor, ver, + UVcom, level); + } + else if (disx >= (xblk >> 1)) { // right neighbor is effective + pos = row*( (hor<= 9 || (imagemeinfo[cpos].bi_mode == 7 && imagemeinfo[cpos].aff_mrg == YES) ) + fr0[com_pos] = fr0[com_pos] / 0.4; + } +*/ +/* if(UVcom == 0 && level == 0){ + if(imagemeinfo[cpos].mrg_blk_bdr == 1) + fr0[cpos] = 255; + } +*/ //////////////////////////////////////////////////// + + } + } +/* + if(UVcom == 0 && level == 0){ + diff = 0; pixel_count = 0; avg_mv = 0; +// printf("MV matrix:\n\n"); + for( cy = 0; cy < ver; cy++ ){ + for( cx = 0; cx < hor; cx++ ){ + cpos = ( (cy<= 0 ); + if(diff > global_motion_active) + global_motion_active = diff; + + fclose(pc); + }//if UVcom = 0 +*/ + assert( case_bi + case_left + case_right + case_intra == hor * ver ); + }//if mv + else{ // copy frame component 直接就是整帧复制 + for( cpos = 0; cpos < hor * ver; cpos++ ){ +#ifdef COPYCOMPENSATION_WEIGHTING + fr0[cpos] = H0[cpos] / (HPW4[1] * copycomp_weight_high[level]); +#else + fr0[cpos] = H0[cpos]; +#endif + } + } + + + free( pused0 ); + free( pused1 ); + free( ltmp0 ); + free( ltmp1 ); + +} + diff --git a/Interframe EZBC/TempSub/src/memoryN.c b/Interframe EZBC/TempSub/src/memoryN.c new file mode 100644 index 0000000..c8d9806 --- /dev/null +++ b/Interframe EZBC/TempSub/src/memoryN.c @@ -0,0 +1,414 @@ +#include +#include +#include +#include +#include +#define EXTERN extern +#include "basic.h" +#include "structN.h" +#include "coderN.h" +#include "memoryN.h" +#include + +/****************************************************************************/ +/* file: getarray.c */ +/****************************************************************************/ +char * +getarray( int num, int siz, char *name ) +{ + char *ptr; + //printf("allocating %d bytes for %s (%d pieces of %d bytes).\n", num * siz, name, num, siz); + + ptr = ( char * )calloc( num, siz ); + + //printf("get_array! num = %d, siz = %d, %s \n",num,siz,name); + + if( ptr == NULL ) { + std::cout<< "num:"<\n", name ); + exit( 1 ); + } + return ( ptr ); +} + +int +rateAlloc( Rate_ptr FrsRate, int nfrs, videoinfo * info ) +{ + int layer_num; + + FrsRate->map = ( int * )getarray( nfrs, sizeof( int ), "FrsR.map" ); + + FrsRate->mv = (int **)getarray(LAYER_NUM, sizeof(int **), "FrsRate->mv"); + for (layer_num=0; layer_nummv[layer_num] = (int *)getarray(nfrs, sizeof(int *), "FrsRate->mv[]"); + + FrsRate->ybit = ( int * )getarray( nfrs, sizeof( int ), "FrsR.ybit" ); + FrsRate->ubit = ( int * )getarray( nfrs, sizeof( int ), "FrsR.ubit" ); + FrsRate->vbit = ( int * )getarray( nfrs, sizeof( int ), "FrsR.vbit" ); + FrsRate->yvar = ( float * )getarray( nfrs, sizeof( float ), "FrsR.yvar" ); + FrsRate->uvar = ( float * )getarray( nfrs, sizeof( float ), "FrsR.uvar" ); + FrsRate->vvar = ( float * )getarray( nfrs, sizeof( float ), "FrsR.vvar" ); + + + // for scalable motion vector coding: AGP + FrsRate->submv = (int ***)getarray(LAYER_NUM, sizeof(int **), "FrsRate->submv"); + for (layer_num=0; layer_numsubmv[layer_num] = (int **)getarray(MAX_AGP_LEVEL, sizeof(int *), "FrsRate->submv[]"); + for (layer_num=0; layer_numsubmv[layer_num][i] = (int *)getarray(nfrs, sizeof(int), "FrsRate->submv[][]"); + + + return ( 0 ); +} + +int +free_rate( Rate_ptr FrsRate ) +{ + free( FrsRate->map ); + free( FrsRate->mv ); + free( FrsRate->ybit ); + free( FrsRate->ubit ); + free( FrsRate->vbit ); + free( FrsRate->yvar ); + free( FrsRate->uvar ); + free( FrsRate->vvar ); + return ( 0 ); +} + +/*****************************************************************************/ +/* transition filtering */ +/*****************************************************************************/ +void +alloc_transmap( transmap ** map, int hor, int ver ) +{ + *map = ( transmap * )getarray( 1 , sizeof( transmap ), "transmap" ); + (*map)->cmode = + ( int * )getarray( hor * ver, sizeof( int ), "transmap_cmode" ); + (*map)->dist = + ( int * )getarray( hor * ver, sizeof( int ), "transmap_dist" ); + (*map)->tmode = + ( int * )getarray( hor * ver, sizeof( int ), "transmap_tmode" ); +} + +void +free_transmap( transmap * map ) +{ + free ( map->cmode ); + free ( map->dist ); + free ( map->tmode ); + free ( map ); +} + + +/*****************************************************************************/ +/* motion vectors */ +/*****************************************************************************/ +void +alloc_vector( vector_ptr fmv, videoinfo info ) +{ + int i, j, size; + + // size = ( info.xnum ) * ( info.ynum ); + size = info.maxMBnum; + for( i = 0; i < size; i++ ) { + fmv[i].child = 0; + fmv[i].parent = NULL; + fmv[i].bi_mode = UNDEFINED; + fmv[i].lifting_mode = IGNORED; + fmv[i].is_predictor = NO; + fmv[i].merge = YES; + fmv[i].merge_sign = 0; + for (j = 0; j < NUMBER_OF_BI_MODES; j++) { + fmv[i].mode_info[j] = invalid_mode_info; + } + } +} + +void +free_child( vector_ptr fmv ) +{ + // if there is no child, then cut itself + // otherwise cut the children first and parent + + if( fmv->child == 1 ) { /* having children */ + + /* move to free_vector() */ + free_child( fmv->child0 ); + free_child( fmv->child1 ); + free_child( fmv->child2 ); + free_child( fmv->child3 ); + + free( fmv->child0 ); + free( fmv->child1 ); + free( fmv->child2 ); + free( fmv->child3 ); + } +} + +void +free_vector( vector_ptr fmv, videoinfo info ) +{ + int i, j, size; + + /* quad tree structured should be cleaned before starting the next */ + /* so, clean the structure except 1st layer */ + /* fmv->child and fmv->lifting_mode should be initialized to CONNECTED */ + + // size = ( info.xnum ) * ( info.ynum ); + size = info.maxMBnum; + for( i = 0; i < size; i++ ) { + free_child( &fmv[i] ); + + fmv[i].child = 0; // reset after free_child not before + fmv[i].merge = YES; + fmv[i].merge_sign = 0; + fmv[i].mvx = (float)HUGE_VAL; // free_vector also used in case of + fmv[i].mvy = (float)HUGE_VAL; // scene_changes (cmp. anal.c) + fmv[i].lifting_mode = IGNORED; + fmv[i].is_predictor = NO; + fmv[i].bi_mode = UNDEFINED; // added by Yongjun Wu, June 8, 2005 + for (j = 0; j < NUMBER_OF_BI_MODES; j++) { + fmv[i].mode_info[j] = invalid_mode_info; + } + + fmv[i].med_idx = -1; //Added on 01.17.2016 + /////////// Added by Yuan Liu ///////////// + fmv[i].direct_idx = NONAFF; + fmv[i].aff_idx = -1; + fmv[i].merge_idx = INEFFECTIVE; + fmv[i].merge_dir = MUDA; + fmv[i].trans_pred_idx = MUDA; + + fmv[i].aff_mrg = NO; + fmv[i].two_comp_src = 0; + fmv[i].skip_sign = NO; + + fmv[i].aff1_mvx = (float)HUGE_VAL; + fmv[i].aff1_mvy = (float)HUGE_VAL; + fmv[i].aff2_mvx = (float)HUGE_VAL; + fmv[i].aff2_mvy = (float)HUGE_VAL; + fmv[i].aff3_mvx = (float)HUGE_VAL; + fmv[i].aff3_mvy = (float)HUGE_VAL; + + fmv[i].aff1_dmvx = (float)HUGE_VAL; + fmv[i].aff1_dmvy = (float)HUGE_VAL; + fmv[i].aff2_dmvx = (float)HUGE_VAL; + fmv[i].aff2_dmvy = (float)HUGE_VAL; + fmv[i].aff3_dmvx = (float)HUGE_VAL; + fmv[i].aff3_dmvy = (float)HUGE_VAL; + + ////////////////////////////////////////////// + } +} + +void +free_mvs( vector_ptr * yfmv, videoinfo info ) +{ + int j, num_mv_GOP; + + num_mv_GOP = 1; // 4, 9, 19, 35, ... + + for( j = info.tPyrLev-1; j >= 0; j-- ) + num_mv_GOP += info.GOPsz / (int)(pow ( (float)2, (int)j)) + 1; + + for( j = 1; j <= num_mv_GOP; j++ ) + free_vector( yfmv[j], info ); +} + + +/*****************************************************************************/ +/* frames */ +/*****************************************************************************/ +void +frame_alloc( YUVimage_ptr frame, videoinfo info ) +{ + int i, ysize, csize; + + ysize = info.ywidth * info.yheight; + csize = info.cwidth * info.cheight; + + frame->Y = ( float * )getarray( ysize, sizeof( float ), "frame" ); + frame->U = ( float * )getarray( csize, sizeof( float ), "frame" ); + frame->V = ( float * )getarray( csize, sizeof( float ), "frame" ); + + for( i = 0; i < ysize; i++ ) frame->Y[i] = 0.; + for( i = 0; i < csize; i++ ) frame->U[i] = 0.; + for( i = 0; i < csize; i++ ) frame->V[i] = 0.; +} + +void +free_frame( YUVimage frame ) +{ + free( frame.Y ); + free( frame.U ); + free( frame.V ); +} + + +/*****************************************************************************/ +/* destructors */ +/*****************************************************************************/ +void +enc_destructor( videoinfo info ) +{ + int i, j, num_mv_bigGOP, num_mv_GOP, num_pyrFrs_bigGOP; + + num_mv_bigGOP = 1; // 4, 11, 26, 57, ... + num_mv_GOP = 1; // 4, 9, 19, 35, ... + num_pyrFrs_bigGOP = 1; // 2, 4, 12, 27, ... + + // calculation of base indices for MV-sets and frames + for( i = info.tPyrLev-1; i >= 0; i-- ){ + num_pyrFrs_bigGOP += info.bigGOP / (int)(pow ( (float)2, (int)(i + 1) )); + num_mv_bigGOP += info.bigGOP / (int)(pow ( (float)2, (int)i)); + num_mv_GOP += info.GOPsz / (int)(pow ( (float)2, (int)i)) + 1; + } + + // printf("num_mv_bigGOP %d, num_mv_GOP %d, num_pyrFrs_bigGOP %d, num_pyrFrs %d\n", + // num_mv_bigGOP, num_mv_GOP, num_pyrFrs_bigGOP, info.GOPsz); + + /******************** free the motion vectors ********************/ + + for( j = 1; j <= num_mv_bigGOP; j++ ){ + free_vector( yfmv_bigGOP[j], info ); + free( yfmv_bigGOP[j] ); + } +//Shadow + for( j = 1; j <= num_mv_bigGOP; j++ ){ + free_vector( buff_yfmv_bigGOP[j], info ); + free( buff_yfmv_bigGOP[j] ); + } + + for( j = 1; j <= num_mv_GOP; j++ ){ + free_vector( yfmv[j], info ); + free( yfmv[j] ); + } +//Shadow + for( j = 1; j <= num_mv_GOP; j++ ){ + free_vector( buff_yfmv[j], info ); + free( buff_yfmv[j] ); + } + + free_vector( tmp_yfmv, info ); +//Shadow + free_vector( buff_tmp_yfmv, info ); + + /************************* free the frames ***********************/ + free_frame( end_of_lastGOP ); +//Shadow + free_frame( buff_end_of_lastGOP ); + + if( info.tPyrLev >= 1 ){ + + for(i = 0; i < num_pyrFrs_bigGOP; i++) + free_frame( pyrFrs_bigGOP[i] ); + free( pyrFrs_bigGOP ); +//Shadow + for(i = 0; i < num_pyrFrs_bigGOP; i++) + free_frame( buff_pyrFrs_bigGOP[i] ); + free( buff_pyrFrs_bigGOP ); + + for(i = 0; i < info.GOPsz; i++) + free_frame( pyrFrs[i] ); + free( pyrFrs ); +//Shadow + for(i = 0; i < info.GOPsz; i++) + free_frame( buff_pyrFrs[i] ); + free( buff_pyrFrs ); + + for( i = 0; i < info.tPyrLev; i++ ) + free_frame( pyrFrs_first[i] ); + free( pyrFrs_first ); +//Shadow + for( i = 0; i < info.tPyrLev; i++ ) + free_frame( buff_pyrFrs_first[i] ); + free( buff_pyrFrs_first ); + + } else { } // info->tPyrLev == 0, nie verwendet (hoffentlich!) + + if( info.denoise_flag == YES ) { + for( i = 0; i < ((YUV420 == 1) ? 1 : 3); i++ ) + free( spatial_high[i] ); + } + + /************************* free scene changes *********************/ + for( i = 0; i < info.tPyrLev; i++ ) { + free ( scene_change[i] ); + } + free ( scene_change ); +//Shadow + for( i = 0; i < info.tPyrLev; i++ ) { + free ( buff_scene_change[i] ); + } + free ( buff_scene_change ); + +} + +void +dec_destructor( videoinfo info ) +{ + int i, j, num_mv_GOP, num_pyrFrs_bigGOP; + + // same number of MVs for GOP and bigGOP ! + num_mv_GOP = 1; // 4, 9, 18, 35, ... + num_pyrFrs_bigGOP = 1; // 3, 6, 11, 20, ... + + // calculation of base indices for MV-sets and frames + for( i = info.tPyrLev-1; i >= 0; i-- ){ + num_mv_GOP += info.GOPsz / (int)(pow ( (float)2, (int)i)) + 1; + } + num_pyrFrs_bigGOP = info.GOPsz + info.tPyrLev; + + /******************** free the motion vectors ********************/ + + for( j = 1; j <= num_mv_GOP; j++ ){ + free_vector( dec_yfmv_bigGOP[j], info ); + free( dec_yfmv_bigGOP[j] ); + free_vector( dec_yfmv[j], info ); + free( dec_yfmv[j] ); + } + + /************************* free the frames ***********************/ + free_frame( end_of_lastGOP ); + + if( info.tPyrLev >= 1 ){ + + for(i = 0; i < num_pyrFrs_bigGOP; i++) + free_frame( dec_pyrFrs_bigGOP[i] ); + free( dec_pyrFrs_bigGOP ); + + for(i = 0; i < info.GOPsz; i++) + free_frame( dec_pyrFrs[i] ); + free( dec_pyrFrs ); + + for( i = 0; i < info.tPyrLev; i++ ) + free_frame( dec_pyrFrs_first[i] ); + free( dec_pyrFrs_first ); + + for( i = info.tPyrLev - 1; i >= 0; i-- ) { + for(j = 0; j < (info.GOPsz / (int)pow( (float)2, (int)i)); j++){ + free_frame( dec_pyrTemp[i][j] ); + } + free( dec_pyrTemp[i] ); + } + free( dec_pyrTemp ); + + } + + if( info.denoise_flag == YES ) { + for( i = 0; i < ((YUV420 == 1) ? 1 : 3); i++ ) + free( spatial_high[i] ); + free( Four_GOP ); + } + + /************************* free scene changes *********************/ + for( i = 0; i < info.tPyrLev; i++ ) { + free ( dec_scene_change[i] ); + } + free ( dec_scene_change ); + +} + + + diff --git a/Interframe EZBC/TempSub/src/miscN.c b/Interframe EZBC/TempSub/src/miscN.c new file mode 100644 index 0000000..6db3553 --- /dev/null +++ b/Interframe EZBC/TempSub/src/miscN.c @@ -0,0 +1,557 @@ +#include +#include +#include +#include +#include +#include "structN.h" +#include "basic.h" +#include + +#define CLOCKS 1e6 /* for CPU time */ + +long clock( ); + + + +/* + * variance() + * calculate variance of a sub_block inside an frame. + * frame : a pointer pointing the upper-left corner of this block + * lenx : width of sub_block. + * leny : height of sub_block. + * hor : width of the original frame + */ +float +variance( float *frame, int lenx, int leny, int hor ) +{ + int x, y; //, pos + double mean, mean2; //data, + float *iptr; + + if( !( lenx * leny ) ) + return 0.; + iptr = frame; + + mean = mean2 = 0.; + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + mean += *iptr; + mean2 += ( *iptr ) * ( *iptr ); + iptr++; + } + iptr += hor - lenx; + } + mean /= lenx * leny; + mean2 /= lenx * leny; + + mean2 -= mean * mean; + + return ( ( float )mean2 ); + +} + +/* + * get_mean() + * calculate mean of a sub_block inside a frame. + * frame : a pointer pointing the upper-left corner of this block + * lenx : width of sub_block. + * leny : height of sub_block. + * hor : width of the original frame + */ + +float +get_mean( float *frame, int lenx, int leny, int hor ) +{ + int x, y; //, pos + double mean; + float *iptr; + + if( !( lenx * leny ) ) + return 0.; + iptr = frame; + + mean = 0.; + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + mean += *iptr; + iptr++; + } + iptr += hor - lenx; + } + mean /= lenx * leny; + return ( ( float )mean ); +} + + +double +variance_mean( float *frame, int lenx, int leny, float *mean ) +{ + int x, y, pos; + double data, sum, sum2; + + if( !( lenx * leny ) ) + return 0.; + sum = sum2 = 0.; + for( y = 0; y < leny; y++ ) { + pos = y * lenx; + for( x = 0; x < lenx; x++ ) { + data = frame[pos + x]; + sum += data; + sum2 += data * data; + } + } + *mean = ( float )( sum / ( lenx * leny ) ); + sum2 /= lenx * leny; + sum2 -= ( *mean ) * ( *mean ); + + return ( sum2 ); +} + + +void +varianceGOP( YUVimage_ptr frames, videoinfo info, Rate_ptr alloc ) +{ + int i, yhor, yver, chor, cver; + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + for( i = 0; i < info.GOPsz; i++ ) { + alloc->yvar[i] = variance( frames[i].Y, yhor, yver, yhor ); + alloc->uvar[i] = variance( frames[i].U, chor, cver, chor ); + alloc->vvar[i] = variance( frames[i].V, chor, cver, chor ); + } + + return; +} + + +long int +get_GOP_num( videoinfo info ) +{ + long int num; + + num = (long int) ( (info.last - info.start + info.GOPsz) / info.GOPsz ); + + return num; +} +/*****************************************************************************/ +/* header2info() */ +/*****************************************************************************/ +void +header2info( videoinfo_ptr info, videoheader header ) +{ + int hor, ver, xblk, yblk, i; + + info->framerate = header.framerate; + info->format = YUV; + + info->ywidth = header.ywidth; + info->yheight = header.yheight; + info->cwidth = header.cwidth; + info->cheight = header.cheight; + info->start = header.start; + info->last = header.last; + + hor = info->ywidth; + ver = info->yheight; + info->maxMBnum = 0; + for (i = 0; i < MAX_TLEVELS; i++) { + info->level[i] = header.level[i] & 0x0f ; // bit: 0-3 for level + info->AGP_exist[i] = ( header.level[i] & 0xf0 )>>4; // bit: 4-7 for AGP_exist + + info->subpel[i] = header.subpel[i] & 0x03; // bit: 0-1 for subpel + info->AGP_level[i] = (header.subpel[i] & 0x0C )>>2; // bit: 2-3 for AGP_level + info->bi_mv[i] = (header.subpel[i] & 0x10 )>>4; // bit: 4 for bi_mv + info->bi_exist[i] = (header.subpel[i] & 0x20 )>>5; // bit: 5 for bi_exist + info->layer_mv[i] = (header.subpel[i] & 0x40 )>>6; // bit: 6 for layer_mv + info->layer_exist[i] = (header.subpel[i] & 0x80 )>>7; // bit: 7 for layer_exist + info->xblk[i] = header.xblk[i]; + info->yblk[i] = header.yblk[i]; + xblk = info->xblk[i]; + yblk = info->yblk[i]; + info->xnum[i] = ( !( hor % xblk ) ) ? hor / xblk : hor / xblk + 1; + info->ynum[i] = ( !( ver % yblk ) ) ? ver / yblk : ver / yblk + 1; + + if(info->xnum[i] * info->ynum[i] > info->maxMBnum) { + info->maxMBnum = info->xnum[i] * info->ynum[i]; + } + } + + info->bitrate = header.bitrate; + + info->t_level = header.t_level; + info->s_level = header.s_level; + info->tPyrLev = header.tPyrLev; + info->GOPsz = 0x1 << header.tPyrLev; + info->bigGOP = ( 0x1 << ( header.tPyrLev + 1 ) ) - 1; + info->denoise_flag = header.denoise_flag; + + info->SLTF_range = header.SLTF_range; + info->SHTF_range = header.SHTF_range; + +} + +/*****************************************************************************/ +/* info2header() */ +/*****************************************************************************/ +void +info2header( videoheader_ptr header, videoinfo info ) +{ + int i; + + header->framerate = ( short int )info.framerate; + + header->ywidth = ( short int )info.ywidth; + header->yheight = ( short int )info.yheight; + header->cwidth = ( short int )info.cwidth; + header->cheight = ( short int )info.cheight; + header->start = ( short int )info.start; + header->last = ( short int )info.last; + + for (i = 0; i < MAX_TLEVELS; i++) { + header->level[i] = ( short int ) ( info.level[i] + // bit: 0-3 for level + (info.AGP_exist[i]<<4) ); // bit: 4-7 for AGP_exist + header->subpel[i] = ( short int )( (info.subpel[i]<<0)+ // bit: 0-1 for subpel + (info.AGP_level[i]<<2) + // bit: 2-3 for AGP_level + (info.bi_mv[i]<<4)+ // bit: 4 for bi_mv + (info.bi_exist[i]<<5)+ // bit: 5 for bi_exist + (info.layer_mv[i]<<6)+ // bit: 6 for layer_mv + (info.layer_exist[i]<<7)); // bit: 7 for layer_exist + header->xblk[i] = ( short int )info.xblk[i]; + header->yblk[i] = ( short int )info.yblk[i]; + } + + header->bitrate = info.bitrate; + + header->t_level = info.t_level ; + + + header->s_level = info.s_level; + header->tPyrLev = ( unsigned char )info.tPyrLev; + header->denoise_flag = info.denoise_flag; + + header->SLTF_range = info.SLTF_range; + header->SHTF_range = info.SHTF_range; + +} + +/*****************************************************************************/ +/* read_header() */ +/*****************************************************************************/ +void +read_header( char *name, videoinfo * info ) +{ + FILE *fpio; + videoheader header; + + if( !( fpio = fopen( name, "rb" ) ) ) { + printf( "read_header: %s\n", name ); + exit( 1 ); + } + fread( &header, sizeof( videoheader ), 1, fpio ); + fclose( fpio ); + header2info( info, header );// 头信息转换为info + +} + +/*****************************************************************************/ +/* write_header() */ +/*****************************************************************************/ +void +write_header( char *name, videoinfo info ) +{ + FILE *fpio; + videoheader header; + + info2header( &header, info ); + + if( !( fpio = fopen( name, "wb" ) ) ) { + printf( "write_header: %s\n", name ); + exit( 1 ); + } + fwrite( &header, sizeof( videoheader ), 1, fpio ); + fclose( fpio ); +} + +/*****************************************************************************/ +/* get_mvBytes() */ +/*****************************************************************************/ + +int +get_mvBytes( FILE * fp_mv ) +{ + int bytes; + char iline[80]; + + fgets( iline, 78, fp_mv ); + sscanf( iline, "%d", &bytes ); + return bytes; +} + +/*****************************************************************************/ +/* timecheck() */ +/*****************************************************************************/ +void +timecheck( long *pmark, int mode ) +{ + double sec; + long cmark; + + cmark = clock( ); /* current clock */ + sec = ( cmark - *pmark ) / CLOCKS; + *pmark = cmark; + + switch ( mode ) { + default: + printf( "error in timecheck()\n" ); + exit( 1 ); + case 0: + printf( "ME = %5.2f seconds.\n", sec ); + break; + case 1: + printf( "MCTF = %5.2f seconds.\n", sec ); + break; + case 2: + printf( "WAVE = %5.2f seconds.\n", sec ); + break; + case 3: + printf( "FSSQ = %5.2f seconds.\n", sec ); + break; + } +} + +/*****************************************************************************/ +/* showtime() */ +/*****************************************************************************/ +void +showtime( long pmark ) +{ + int hour, min; + double sec; + long cmark; + + cmark = clock( ); /* current clock */ + sec = ( cmark - pmark ) / CLOCKS; + hour = ( int )( sec / 3600.0 ); + sec -= 3600.0 * hour; + min = ( int )( sec / 60.0 ); + sec -= 60.0 * min; + + printf( "%d hour %d min %5.2f seconds.\n", hour, min, sec ); +} + + +void +computegain( YUVimage lowband, YUVimage highband, videoinfo info ) +{ + int yhor, yver, chor, cver; + double var0, var1, gain; + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + var0 = variance( lowband.Y, yhor, yver, yhor ); + var1 = variance( highband.Y, yhor, yver, yhor ); + gain = ( var0 + var1 ) / 2.0; + gain /= sqrt( var0 * var1 ); + fprintf( stdout, "lowband yvar = %f highband yvar = %f coding gain = %f\n", + ( float )var0, ( float )var1, ( float )gain ); + + if( chor ) { + var0 = variance( lowband.U, chor, cver, chor ); + var1 = variance( highband.U, chor, cver, chor ); + gain = ( var0 + var1 ) / 2.0; + gain /= sqrt( var0 * var1 ); + fprintf( stdout, + "lowband uvar = %f highband uvar = %f coding gain = %f\n", + ( float )var0, ( float )var1, ( float )gain ); + + var0 = variance( lowband.V, chor, cver, chor ); + var1 = variance( highband.V, chor, cver, chor ); + gain = ( var0 + var1 ) / 2.0; + gain /= sqrt( var0 * var1 ); + fprintf( stdout, + "lowband vvar = %f highband vvar = %f coding gain = %f\n", + ( float )var0, ( float )var1, ( float )gain ); + } + +} + + +void +copyframe( YUVimage * source, YUVimage * dest, videoinfo info ) +{ + int i; + + for( i = 0; i < info.ywidth * info.yheight; i++ ) { + dest->Y[i] = source->Y[i]; + } + if( info.cwidth && info.cheight ) { + for( i = 0; i < info.cwidth * info.cheight; i++ ) { + dest->U[i] = source->U[i]; + dest->V[i] = source->V[i]; + } + } + +} + + +void +wcopyframe( YUVimage * source, YUVimage * dest, float weight, videoinfo info ) +{ + int i; + + for( i = 0; i < info.ywidth * info.yheight; i++ ) { + dest->Y[i] = source->Y[i] * weight; + } + if( info.cwidth && info.cheight ) { + for( i = 0; i < info.cwidth * info.cheight; i++ ) { + dest->U[i] = source->U[i] * weight; + dest->V[i] = source->V[i] * weight; + } + } + +} + + +void +child_mv_copy(vector_ptr source, vector_ptr dest, videoinfo info) +{ + int i; + + assert( dest->child == 0 ); + + if( source->child ) { + dest->child = 1; + + // create empty children + dest->child0 = ( vector_ptr ) getarray( 1, sizeof( vector ), "dest->child0" ); + dest->child1 = ( vector_ptr ) getarray( 1, sizeof( vector ), "dest->child1" ); + dest->child2 = ( vector_ptr ) getarray( 1, sizeof( vector ), "dest->child2" ); + dest->child3 = ( vector_ptr ) getarray( 1, sizeof( vector ), "dest->child3" ); + + dest->child0->child = 0; + dest->child1->child = 0; + dest->child2->child = 0; + dest->child3->child = 0; + + dest->child0->parent = dest; + dest->child1->parent = dest; + dest->child2->parent = dest; + dest->child3->parent = dest; + + // go through the tree + child_mv_copy( source->child0, dest->child0, info ); + child_mv_copy( source->child1, dest->child1, info ); + child_mv_copy( source->child2, dest->child2, info ); + child_mv_copy( source->child3, dest->child3, info ); + } else { + // fill nodes + dest->child = source->child; + dest->bi_mode = source->bi_mode; + dest->lifting_mode = source->lifting_mode; +// dest->Ymean = source->Ymean; +// dest->Umean = source->Umean; +// dest->Vmean = source->Vmean; + dest->meandepth = source->meandepth; + dest->mvx = source->mvx; + dest->mvy = source->mvy; + dest->mad = source->mad; +// dest->bi_mvx = source->bi_mvx; +// dest->bi_mvy = source->bi_mvy; +// dest->bi_mad = source->bi_mad; + dest->is_predictor = source->is_predictor; + dest->sad_cost = source->sad_cost; + dest->bit_cost = source->bit_cost; + dest->total_cost = source->total_cost; + dest->mse = source->mse; + dest->var = source->var; +// dest->dL = source->dL; +// dest->dMAP = source->dMAP; +// dest->dMV = source->dMV; +// dest->dD = source->dD; +// dest->slope = source->slope; +// dest->mslope = source->mslope; + dest->merge = source->merge; + + dest->med_idx = source->med_idx; //Added by Yuan Liu on 01.23.2016 + dest->aff_mrg = source->aff_mrg; + + dest->two_comp_src = source->two_comp_src; + dest->skip_sign = source->skip_sign; //Added on 08.12.2018 +/* + for(i=0;i<=3;i++){ + dest->mrg_mvx[i] = source->mrg_mvx[i]; + dest->mrg_mvy[i] = source->mrg_mvy[i]; + + dest->mrg_aff_mvx1[i] = source->mrg_aff_mvx1[i]; + dest->mrg_aff_mvy1[i] = source->mrg_aff_mvy1[i]; + dest->mrg_aff_mvx2[i] = source->mrg_aff_mvx2[i]; + dest->mrg_aff_mvy2[i] = source->mrg_aff_mvy2[i]; + dest->mrg_aff_mvx3[i] = source->mrg_aff_mvx3[i]; + dest->mrg_aff_mvy3[i] = source->mrg_aff_mvy3[i]; + } +*/ + for(i=0;i<3;i++){ + dest->aff1_pred_mvx[i] = source->aff1_pred_mvx[i]; + dest->aff1_pred_mvy[i] = source->aff1_pred_mvy[i]; + dest->aff2_pred_mvx[i] = source->aff2_pred_mvx[i]; + dest->aff2_pred_mvy[i] = source->aff2_pred_mvy[i]; + dest->aff3_pred_mvx[i] = source->aff3_pred_mvx[i]; + dest->aff3_pred_mvy[i] = source->aff3_pred_mvy[i]; + } + //////// Added by Yuan Liu /////////// + if( (source->bi_mode >= 9 && source->bi_mode <=11) || (source->bi_mode == 7 && source->aff_mrg == YES) ){ + + dest->direct_idx = source->direct_idx; + dest->aff_idx = source->aff_idx; +// printf("\naff1x = %f, aff1y = %f \n aff2x = %f, aff2y = %f \n aff3x = %f, aff3y = %f\n",source->aff1_mvx,source->aff1_mvy,source->aff2_mvx,source->aff2_mvy,source->aff3_mvx,source->aff3_mvy); + + dest->aff1_mvx = source->aff1_mvx; + dest->aff1_mvy = source->aff1_mvy; + dest->aff2_mvx = source->aff2_mvx; + dest->aff2_mvy = source->aff2_mvy; + dest->aff3_mvx = source->aff3_mvx; + dest->aff3_mvy = source->aff3_mvy; + + dest->merge_idx = source->merge_idx; + dest->merge_dir = source->merge_dir; + dest->trans_pred_idx = source->trans_pred_idx; //Added on 01.16.2017 + + dest->aff1_dmvx = source->aff1_dmvx; + dest->aff1_dmvy = source->aff1_dmvy; + dest->aff2_dmvx = source->aff2_dmvx; + dest->aff2_dmvy = source->aff2_dmvy; + dest->aff3_dmvx = source->aff3_dmvx; + dest->aff3_dmvy = source->aff3_dmvy; + + dest->dmvx = source->dmvx; + dest->dmvy = source->dmvy; + + } + /////////////////////////////////////////// + + dest->iblock_spatial_mode = source->iblock_spatial_mode; // for spatial prediction mode + + for (i = 0; i < NUMBER_OF_BI_MODES; i++) { + dest->mode_info[i] = source->mode_info[i]; + } + } +} + +void +mv_copy( vector_ptr source, vector_ptr dest, videoinfo info ) +{ + int i, size; + + size = info.maxMBnum; + for( i = 0; i < size; i++ ) { + child_mv_copy( &source[i], &dest[i], info ); + } +} + diff --git a/Interframe EZBC/TempSub/src/mode_decision.c b/Interframe EZBC/TempSub/src/mode_decision.c new file mode 100644 index 0000000..00dda8d --- /dev/null +++ b/Interframe EZBC/TempSub/src/mode_decision.c @@ -0,0 +1,5993 @@ +#include +#include +#include +#include + +#define EXTERN extern + +#include "directional_iblock.h" +#include "mode_decision.h" +#include "bmeN.h" +#include "mvcodingN.h" +#include "basic.h" +#include "structN.h" +#include "util_filtering.h" +#include "bme_tools.h" +#include "coderN.h" +#include "mv_ec.h" +#include "miscN.h" + +#define DIRECT_LEN 1 +#define MERGE_LEN 1 +#define MERGE_DIR_UP_LEN 1 +#define MERGE_DIR_LEN 2 +#define AFF_IDX_OFFSET 3 +#define MRG_RANGE 10 +#define ITR_RANGE 6 +#define BI_RANGE 3 +#define PRL_RANGE 4 + +#define SMALL_AFF_BLK_COEF 0.90 +#define AFF_BLK_COEF_32 0.94 +#define AFF_BLK_COEF_64 0.94 + + +ModeInfo *tv11; +ModeInfo *tv12; +ModeInfo *tv13; + +ModeInfo *tv21; +ModeInfo *tv22; +ModeInfo *tv23; + +float *block_buff1; +float *block_buff2; + +int get_idx_length( int aff_num ){ + int i,j; + int getnum, val; + int length = 0; + + if(aff_num >= 9){ + getnum = (aff_num + 1); + while(getnum >= 4){ + getnum -= 4; + length += 1; + } + length += 1; + assert(getnum <= 3 && getnum >= 0); + length += 2; + }else if(aff_num >= 5 && aff_num <= 8){ + length = 3; + }else if(aff_num >= 2 && aff_num <= 4){ + length = 2; + }else if(aff_num == 1){ + length = 1; + }else + assert(0); + + return length; +} + + +//Added on 08.15.2016 //////////////////////////// + +int compare_mv(vector_ptr left1, vector_ptr right1, vector_ptr left2, vector_ptr right2){ + int eql; + int diff_l = 1, diff_r = 1; + + assert(left1->bi_mode == right1->bi_mode && left2->bi_mode == right2->bi_mode); + + if(left1->bi_mode >= 9 || left2->bi_mode >= 9){ + diff_l = 1; + diff_r = 1; + }else{ + if(left1 != NULL && left2 != NULL){ + if(left1->mvx == left2->mvx && left1->mvy == left2->mvy) + diff_l = 0; + }else if(left1 == NULL && right1 == NULL){ + diff_l = 0; + } + + if(right1 != NULL && right2 != NULL){ + if(right1->mvx == right2->mvx && right1->mvy == right2->mvy) + diff_r = 0; + }else if(right1 == NULL && right1 == NULL){ + diff_r = 0; + } + } + + return (diff_l + diff_r); +} + +//cx,cy - the coordinate of current block's upper-left corner +//x_pos,y_pos the merge reference point +void get_aff_mrg_mv( vector_ptr fmv, int cx, int cy, int x_pos, int y_pos, int xblk, int yblk, float dx1, float dy1, + float dx2, float dy2, float pmvx, float pmvy ){ + int i,j,k; + float mvx1, mvy1, mvx2, mvy2, mvx3, mvy3; + + mvx1 = pmvx - (x_pos - cx) * dx1 - (y_pos - cy) * dx2; + mvy1 = pmvy - (x_pos - cx) * dy1 - (y_pos - cy) * dy2; + + mvx2 = pmvx - (x_pos - cx - xblk) * dx1 - (y_pos - cy) * dx2; + mvy2 = pmvy - (x_pos - cx - xblk) * dy1 - (y_pos - cy) * dy2; + + mvx3 = pmvx - (x_pos - cx) * dx1 - (y_pos - cy - yblk) * dx2; + mvy3 = pmvy - (x_pos - cx) * dy1 - (y_pos - cy - yblk) * dy2; + + fmv->aff1_mvx = mvx1; + fmv->aff1_mvy = mvy1; + fmv->aff2_mvx = mvx2; + fmv->aff2_mvy = mvy2; + fmv->aff3_mvx = mvx3; + fmv->aff3_mvy = mvy3; +} + +/* + CBD + AZ + E +*/ +void get_merge_mv_info(vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv3_array, vector_ptr fmv4_array, vector_ptr *mrg_left, + vector_ptr *mrg_right, int x_pos, int y_pos, int hor, int ver, int xblk, int yblk, videoinfo info, int t_level){ + int i,j,k; + int get_xblk, get_yblk; + vector_ptr left_mva = NULL, left_mvb = NULL, left_mvc = NULL, left_mvd = NULL, left_mv_tmp = NULL, left_mve = NULL; + vector_ptr right_mva = NULL, right_mvb = NULL, right_mvc = NULL, right_mvd = NULL, right_mv_tmp = NULL, right_mve = NULL; + + float ula11,ula12,ulb11,ulb12,ulc11,ulc12,uld11,uld12,ult11,ult12,ule11,ule12; + float ula21,ula22,ulb21,ulb22,ulc21,ulc22,uld21,uld22,ult21,ult22,ule21,ule22; + + float left_affx1, left_affy1, left_affx2, left_affy2, left_affx3, left_affy3, left_affx4, left_affy4; + float right_affx1, right_affy1, right_affx2, right_affy2, right_affx3, right_affy3, right_affx4, right_affy4; + float aff_dmvx1,aff_dmvx2,aff_dmvy1,aff_dmvy2; + + float med_l_px[4], med_l_py[4], med_r_px[4], med_r_py[4]; + float med_l_aff1x[4],med_l_aff1y[4],med_l_aff2x[4],med_l_aff2y[4],med_l_aff3x[4],med_l_aff3y[4]; + float med_r_aff1x[4],med_r_aff1y[4],med_r_aff2x[4],med_r_aff2y[4],med_r_aff3x[4],med_r_aff3y[4]; + + int aff_blk; //Added on 03.14.2017 + + for(i=0;i<=3;i++){ + med_l_px[i] = (float)HUGE_VAL; + med_l_py[i] = (float)HUGE_VAL; + med_l_aff1x[i] = (float)HUGE_VAL; + med_l_aff1y[i] = (float)HUGE_VAL; + med_l_aff2x[i] = (float)HUGE_VAL; + med_l_aff2y[i] = (float)HUGE_VAL; + med_l_aff3x[i] = (float)HUGE_VAL; + med_l_aff3y[i] = (float)HUGE_VAL; + + med_r_px[i] = (float)HUGE_VAL; + med_r_py[i] = (float)HUGE_VAL; + med_r_aff1x[i] = (float)HUGE_VAL; + med_r_aff1y[i] = (float)HUGE_VAL; + med_r_aff2x[i] = (float)HUGE_VAL; + med_r_aff2y[i] = (float)HUGE_VAL; + med_r_aff3x[i] = (float)HUGE_VAL; + med_r_aff3y[i] = (float)HUGE_VAL; + } + +//A + aff_blk = 0; + + left_mva = find_block(x_pos-1,y_pos+yblk-1,fmv1_array,info,t_level,&ula11,&ula12,&get_xblk,&get_yblk,0,0); + + find_block(x_pos-3,y_pos+yblk-3,fmv1_array,info,t_level,&left_affx1,&left_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos-2,y_pos+yblk-3,fmv1_array,info,t_level,&left_affx2,&left_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos-3,y_pos+yblk-2,fmv1_array,info,t_level,&left_affx3,&left_affy3,&get_xblk,&get_yblk,0,0); + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + + assert(left_mva->bi_mode>=9 || (left_mva->bi_mode == 7 && left_mva->aff_mrg == YES) ); + + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[0], x_pos, y_pos, x_pos-3, y_pos+yblk-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + + if(fmv2_array != NULL){ + right_mva = find_block(x_pos-1,y_pos+yblk-1,fmv2_array,info,t_level,&ula21,&ula22,&get_xblk,&get_yblk,0,0); + + find_block(x_pos-3,y_pos+yblk-3,fmv2_array,info,t_level,&right_affx1,&right_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos-2,y_pos+yblk-3,fmv2_array,info,t_level,&right_affx2,&right_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos-3,y_pos+yblk-2,fmv2_array,info,t_level,&right_affx3,&right_affy3,&get_xblk,&get_yblk,0,0); + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + + assert(right_mva->bi_mode>=9 || (right_mva->bi_mode == 7 && right_mva->aff_mrg == YES) ); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[0], x_pos, y_pos, x_pos-3, y_pos+yblk-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + if(aff_blk == 1){ + if( left_mva != NULL && left_mva->is_predictor == YES ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[0], x_pos, y_pos, x_pos-3, y_pos+yblk-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + } + + if( right_mva != NULL && right_mva->is_predictor == YES ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[0], x_pos, y_pos, x_pos-3, y_pos+yblk-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } + } +//B + aff_blk = 0; + left_mvb = find_block(x_pos+xblk-1,y_pos-1,fmv1_array,info,t_level,&ulb11,&ulb12,&get_xblk,&get_yblk,0,0); + + find_block(x_pos+xblk-3,y_pos-3,fmv1_array,info,t_level,&left_affx1,&left_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk-2,y_pos-3,fmv1_array,info,t_level,&left_affx2,&left_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk-3,y_pos-2,fmv1_array,info,t_level,&left_affx3,&left_affy3,&get_xblk,&get_yblk,0,0); + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + + assert( left_mvb->bi_mode>=9 || (left_mvb->bi_mode == 7 && left_mvb->aff_mrg == YES) ); + + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[1], x_pos, y_pos, x_pos+xblk-3,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + + if(fmv2_array != NULL){ + right_mvb = find_block(x_pos+xblk-1,y_pos-1,fmv2_array,info,t_level,&ulb21,&ulb22,&get_xblk,&get_yblk,0,0); + + find_block(x_pos+xblk-3,y_pos-3,fmv2_array,info,t_level,&right_affx1,&right_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk-2,y_pos-3,fmv2_array,info,t_level,&right_affx2,&right_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk-3,y_pos-2,fmv2_array,info,t_level,&right_affx3,&right_affy3,&get_xblk,&get_yblk,0,0); + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + + assert(right_mvb->bi_mode>=9 || (right_mvb->bi_mode == 7 && right_mvb->aff_mrg == YES) ); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[1], x_pos, y_pos,x_pos+xblk-3,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + if(aff_blk == 1){ + if( left_mvb != NULL && left_mvb->is_predictor == YES ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[1], x_pos, y_pos, x_pos+xblk-3,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + } + if( right_mvb != NULL && right_mvb->is_predictor == YES ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[1], x_pos, y_pos,x_pos+xblk-3,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } + + } +//C + aff_blk = 0; + left_mvc = find_block(x_pos-1,y_pos-1,fmv1_array,info,t_level,&ulc11,&ulc12,&get_xblk,&get_yblk,0,0); + + find_block(x_pos-3,y_pos-3,fmv1_array,info,t_level,&left_affx1,&left_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos-2,y_pos-3,fmv1_array,info,t_level,&left_affx2,&left_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos-3,y_pos-2,fmv1_array,info,t_level,&left_affx3,&left_affy3,&get_xblk,&get_yblk,0,0); + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + + assert(left_mvc->bi_mode>=9 || (left_mvc->bi_mode == 7 && left_mvc->aff_mrg == YES) ); + + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[2], x_pos, y_pos, x_pos-3, y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + + if(fmv2_array != NULL){ + right_mvc = find_block(x_pos-1,y_pos-1,fmv2_array,info,t_level,&ulc21,&ulc22,&get_xblk,&get_yblk,0,0); + + find_block(x_pos-3,y_pos-3,fmv2_array,info,t_level,&right_affx1,&right_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos-2,y_pos-3,fmv2_array,info,t_level,&right_affx2,&right_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos-3,y_pos-2,fmv2_array,info,t_level,&right_affx3,&right_affy3,&get_xblk,&get_yblk,0,0); + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + + assert(right_mvc->bi_mode>=9 || (right_mvc->bi_mode == 7 && right_mvc->aff_mrg == YES) ); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[2], x_pos, y_pos, x_pos-3, y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + if(aff_blk == 1){ + if(left_mvc != NULL && left_mvc->is_predictor == YES ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[2], x_pos, y_pos, x_pos-3, y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + } + if(right_mvc != NULL && right_mvc->is_predictor == YES ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[2], x_pos, y_pos, x_pos-3, y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } + } + + aff_blk = 0; + + if( (left_mva != NULL || right_mva != NULL) && (left_mvb != NULL || right_mvb != NULL) && (left_mvc != NULL || right_mvc != NULL) ); + else{ +//D + left_mvd = find_block(x_pos+xblk,y_pos-1,fmv1_array,info,t_level,&uld11,&uld12,&get_xblk,&get_yblk,0,0); + + find_block(x_pos+xblk+1,y_pos-3,fmv1_array,info,t_level,&left_affx1,&left_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk+2,y_pos-3,fmv1_array,info,t_level,&left_affx2,&left_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk+1,y_pos-2,fmv1_array,info,t_level,&left_affx3,&left_affy3,&get_xblk,&get_yblk,0,0); + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + + assert(left_mvd->bi_mode>=9 || (left_mvd->bi_mode == 7 && left_mvd->aff_mrg == YES) ); + + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[3], x_pos, y_pos, x_pos+xblk+1,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + aff_blk = 1; + } + + if(fmv2_array != NULL){ + right_mvd = find_block(x_pos+xblk,y_pos-1,fmv2_array,info,t_level,&uld21,&uld22,&get_xblk,&get_yblk,0,0); + + find_block(x_pos+xblk+1,y_pos-3,fmv2_array,info,t_level,&right_affx1,&right_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk+2,y_pos-3,fmv2_array,info,t_level,&right_affx2,&right_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos+xblk+1,y_pos-2,fmv2_array,info,t_level,&right_affx3,&right_affy3,&get_xblk,&get_yblk,0,0); + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + + assert(right_mvd->bi_mode>=9 || (right_mvd->bi_mode == 7 && right_mvd->aff_mrg == YES) ); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[3], x_pos, y_pos, x_pos+xblk+1,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + aff_blk = 1; + } + + if(aff_blk == 1){ + if(left_mvd != NULL && left_mvd->is_predictor == YES ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[3], x_pos, y_pos, x_pos+xblk+1,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + } + if(right_mvd != NULL && right_mvd->is_predictor == YES ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[3], x_pos, y_pos, x_pos+xblk+1,y_pos-3,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } + } + } + + if(left_mva != NULL){ + if( left_mva->bi_mode <= 6 || left_mva->bi_mode == 8 || (left_mva->bi_mode == 7 && left_mva->aff_mrg == NO) ){ + mrg_left[0]->mvx = left_mva->mvx; mrg_left[0]->mvy = left_mva->mvy; mrg_left[0]->lifting_mode = CONNECTED; + }else{ + mrg_left[0]->mvx = ula11; mrg_left[0]->mvy = ula12; mrg_left[0]->lifting_mode = CONNECTED; + } + } + if(right_mva != NULL){ + if( right_mva->bi_mode <= 6 || right_mva->bi_mode == 8 || (right_mva->bi_mode == 7 && right_mva->aff_mrg == NO) ){ + mrg_right[0]->mvx = right_mva->mvx; mrg_right[0]->mvy = right_mva->mvy; mrg_right[0]->lifting_mode = CONNECTED; + }else{ + mrg_right[0]->mvx = ula21; mrg_right[0]->mvy = ula22; mrg_right[0]->lifting_mode = CONNECTED; + } + } + if(left_mvb != NULL){ + if(left_mvb->bi_mode <= 6 || left_mvb->bi_mode == 8 || (left_mvb->bi_mode == 7 && left_mvb->aff_mrg == NO) ){ + mrg_left[1]->mvx = left_mvb->mvx; mrg_left[1]->mvy = left_mvb->mvy; mrg_left[1]->lifting_mode = CONNECTED; + }else{ + mrg_left[1]->mvx = ulb11; mrg_left[1]->mvy = ulb12; mrg_left[1]->lifting_mode = CONNECTED; + } + } + if(right_mvb != NULL){ + if( right_mvb->bi_mode <= 6 || right_mvb->bi_mode == 8 || (right_mvb->bi_mode == 7 && right_mvb->aff_mrg == NO) ){ + mrg_right[1]->mvx = right_mvb->mvx; mrg_right[1]->mvy = right_mvb->mvy; mrg_right[1]->lifting_mode = CONNECTED; + }else{ + mrg_right[1]->mvx = ulb21; mrg_right[1]->mvy = ulb22; mrg_right[1]->lifting_mode = CONNECTED; + } + } + if(left_mvc != NULL){ + if( left_mvc->bi_mode <= 6 || left_mvc->bi_mode == 8 || (left_mvc->bi_mode == 7 && left_mvc->aff_mrg == NO) ){ + mrg_left[2]->mvx = left_mvc->mvx; mrg_left[2]->mvy = left_mvc->mvy; mrg_left[2]->lifting_mode = CONNECTED; + }else{ + mrg_left[2]->mvx = ulc11; mrg_left[2]->mvy = ulc12; mrg_left[2]->lifting_mode = CONNECTED; + } + } + if(right_mvc != NULL){ + if( right_mvc->bi_mode <= 6 || right_mvc->bi_mode == 8 || (right_mvc->bi_mode == 7 && right_mvc->aff_mrg == NO) ){ + mrg_right[2]->mvx = right_mvc->mvx; mrg_right[2]->mvy = right_mvc->mvy; mrg_right[2]->lifting_mode = CONNECTED; + }else{ + mrg_right[2]->mvx = ulc21; mrg_right[2]->mvy = ulc22; mrg_right[2]->lifting_mode = CONNECTED; + } + } + if(left_mvd != NULL){ + if( left_mvd->bi_mode <= 6 || left_mvd->bi_mode == 8 || (left_mvd->bi_mode == 7 && left_mvd->aff_mrg == NO) ){ + mrg_left[3]->mvx = left_mvd->mvx; mrg_left[3]->mvy = left_mvd->mvy; mrg_left[3]->lifting_mode = CONNECTED; + }else{ + mrg_left[3]->mvx = uld11; mrg_left[3]->mvy = uld12; mrg_left[3]->lifting_mode = CONNECTED; + } + } + if(right_mvd != NULL){ + if( right_mvd->bi_mode <= 6 || right_mvd->bi_mode == 8 || (right_mvd->bi_mode == 7 && right_mvd->aff_mrg == NO) ){ + mrg_right[3]->mvx = right_mvd->mvx; mrg_right[3]->mvy = right_mvd->mvy; mrg_right[3]->lifting_mode = CONNECTED; + }else{ + mrg_right[3]->mvx = uld21; mrg_right[3]->mvy = uld22; mrg_right[3]->lifting_mode = CONNECTED; + } + } + + //////////////////////// + for(i = 0;i <= 3;i ++){ + if( (x_pos-(mrg_left[i]->mvx)<0||x_pos-(mrg_left[i]->mvx)+xblk>hor||y_pos-(mrg_left[i]->mvy)<0|| + y_pos-(mrg_left[i]->mvy)+yblk>ver) && (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + if( (x_pos-(mrg_right[i]->mvx)<0||x_pos-(mrg_right[i]->mvx)+xblk>hor||y_pos-(mrg_right[i]->mvy)<0|| + y_pos-(mrg_right[i]->mvy)+yblk>ver) && (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if( (mrg_left[i]->mvx == mrg_left[k]->mvx && mrg_left[i]->mvy == mrg_left[k]->mvy) && + (mrg_right[i]->mvx == mrg_right[k]->mvx && mrg_right[i]->mvy == mrg_right[k]->mvy) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + med_l_px[k] = mrg_left[i]->mvx; + med_l_py[k] = mrg_left[i]->mvy; + med_l_aff1x[k] = mrg_left[i]->aff1_mvx; + med_l_aff1y[k] = mrg_left[i]->aff1_mvy; + med_l_aff2x[k] = mrg_left[i]->aff2_mvx; + med_l_aff2y[k] = mrg_left[i]->aff2_mvy; + med_l_aff3x[k] = mrg_left[i]->aff3_mvx; + med_l_aff3y[k] = mrg_left[i]->aff3_mvy; + + med_r_px[k] = mrg_right[i]->mvx; + med_r_py[k] = mrg_right[i]->mvy; + med_r_aff1x[k] = mrg_right[i]->aff1_mvx; + med_r_aff1y[k] = mrg_right[i]->aff1_mvy; + med_r_aff2x[k] = mrg_right[i]->aff2_mvx; + med_r_aff2y[k] = mrg_right[i]->aff2_mvy; + med_r_aff3x[k] = mrg_right[i]->aff3_mvx; + med_r_aff3y[k] = mrg_right[i]->aff3_mvy; + + k++; + } + } + assert(k <= 3); + for(i = 0;i <= 3;i++){ + mrg_left[i]->mvx = med_l_px[i]; + mrg_left[i]->mvy = med_l_py[i]; + mrg_left[i]->aff1_mvx = med_l_aff1x[i]; + mrg_left[i]->aff1_mvy = med_l_aff1y[i]; + mrg_left[i]->aff2_mvx = med_l_aff2x[i]; + mrg_left[i]->aff2_mvy = med_l_aff2y[i]; + mrg_left[i]->aff3_mvx = med_l_aff3x[i]; + mrg_left[i]->aff3_mvy = med_l_aff3y[i]; + + mrg_right[i]->mvx = med_r_px[i]; + mrg_right[i]->mvy = med_r_py[i]; + mrg_right[i]->aff1_mvx = med_r_aff1x[i]; + mrg_right[i]->aff1_mvy = med_r_aff1y[i]; + mrg_right[i]->aff2_mvx = med_r_aff2x[i]; + mrg_right[i]->aff2_mvy = med_r_aff2y[i]; + mrg_right[i]->aff3_mvx = med_r_aff3x[i]; + mrg_right[i]->aff3_mvy = med_r_aff3y[i]; + + } + for(i=0;i<=3;i++){ + med_l_px[i] = (float)HUGE_VAL; + med_l_py[i] = (float)HUGE_VAL; + med_l_aff1x[i] = (float)HUGE_VAL; + med_l_aff1y[i] = (float)HUGE_VAL; + med_l_aff2x[i] = (float)HUGE_VAL; + med_l_aff2y[i] = (float)HUGE_VAL; + med_l_aff3x[i] = (float)HUGE_VAL; + med_l_aff3y[i] = (float)HUGE_VAL; + + med_r_px[i] = (float)HUGE_VAL; + med_r_py[i] = (float)HUGE_VAL; + med_r_aff1x[i] = (float)HUGE_VAL; + med_r_aff1y[i] = (float)HUGE_VAL; + med_r_aff2x[i] = (float)HUGE_VAL; + med_r_aff2y[i] = (float)HUGE_VAL; + med_r_aff3x[i] = (float)HUGE_VAL; + med_r_aff3y[i] = (float)HUGE_VAL; + } + + assert(mrg_left[3]->mvx == (float)HUGE_VAL && mrg_left[3]->mvy == (float)HUGE_VAL + && mrg_right[3]->mvx == (float)HUGE_VAL && mrg_right[3]->mvy == (float)HUGE_VAL); + +//TMP merge candidate + aff_blk = 0; + + for(i = 0; i <= 3; i++){ + if( (mrg_left[i]->mvx == (float)HUGE_VAL && mrg_left[i]->mvy == (float)HUGE_VAL) && + (mrg_right[i]->mvx == (float)HUGE_VAL && mrg_right[i]->mvy == (float)HUGE_VAL) ){ + if(fmv3_array != NULL) + left_mv_tmp = find_block(x_pos,y_pos,fmv3_array,info,t_level,&ult11,&ult12,&get_xblk,&get_yblk,0,0); + + if(fmv2_array != NULL && fmv4_array != NULL) + right_mv_tmp = find_block(x_pos,y_pos,fmv4_array,info,t_level,&ult21,&ult22,&get_xblk,&get_yblk,0,0); + + if(left_mv_tmp != NULL){ + if( left_mv_tmp->bi_mode <= 6 || left_mv_tmp->bi_mode == 8 || (left_mv_tmp->bi_mode == 7 && left_mv_tmp->aff_mrg == NO) ){ + mrg_left[i]->mvx = left_mv_tmp->mvx; mrg_left[i]->mvy = left_mv_tmp->mvy; mrg_left[i]->lifting_mode = CONNECTED; + }else{ + mrg_left[i]->mvx = ult11; mrg_left[i]->mvy = ult12; mrg_left[i]->lifting_mode = CONNECTED; + } + } + if(right_mv_tmp != NULL){ + if( right_mv_tmp->bi_mode <= 6 || right_mv_tmp->bi_mode == 8 || (right_mv_tmp->bi_mode == 7 && right_mv_tmp->aff_mrg == NO) ){ + mrg_right[i]->mvx = right_mv_tmp->mvx; mrg_right[i]->mvy = right_mv_tmp->mvy; mrg_right[i]->lifting_mode = CONNECTED; + }else{ + mrg_right[i]->mvx = ult21; mrg_right[i]->mvy = ult22; mrg_right[i]->lifting_mode = CONNECTED; + } + } +//Additional TMP merge candidate + if( (mrg_left[i]->mvx == (float)HUGE_VAL && mrg_left[i]->mvy == (float)HUGE_VAL) && + (mrg_right[i]->mvx == (float)HUGE_VAL && mrg_right[i]->mvy == (float)HUGE_VAL) ){ + if(fmv3_array != NULL) + left_mv_tmp = find_block(x_pos-xblk,y_pos-yblk,fmv3_array,info,t_level,&ult11,&ult12,&get_xblk,&get_yblk,0,0); + + if(fmv2_array != NULL && fmv4_array != NULL) + right_mv_tmp = find_block(x_pos-xblk,y_pos-yblk,fmv4_array,info,t_level,&ult21,&ult22,&get_xblk,&get_yblk,0,0); + + if(left_mv_tmp != NULL){ + if( left_mv_tmp->bi_mode <= 6 || left_mv_tmp->bi_mode == 8 || (left_mv_tmp->bi_mode == 7 && left_mv_tmp->aff_mrg == NO) ){ + mrg_left[i]->mvx = left_mv_tmp->mvx; mrg_left[i]->mvy = left_mv_tmp->mvy; mrg_left[i]->lifting_mode = CONNECTED; + }else{ + mrg_left[i]->mvx = ult11; mrg_left[i]->mvy = ult12; mrg_left[i]->lifting_mode = CONNECTED; + } + } + if(right_mv_tmp != NULL){ + if( right_mv_tmp->bi_mode <= 6 || right_mv_tmp->bi_mode == 8 || (right_mv_tmp->bi_mode == 7 && right_mv_tmp->aff_mrg == NO) ){ + mrg_right[i]->mvx = right_mv_tmp->mvx; mrg_right[i]->mvy = right_mv_tmp->mvy; mrg_right[i]->lifting_mode = CONNECTED; + }else{ + mrg_right[i]->mvx = ult21; mrg_right[i]->mvy = ult22; mrg_right[i]->lifting_mode = CONNECTED; + } + } + } +//Additional TMP merge candidate + break; + } + } + //////////////////////// + for(i = 0;i <= 3;i ++){ + if( (x_pos-(mrg_left[i]->mvx)<0||x_pos-(mrg_left[i]->mvx)+xblk>hor||y_pos-(mrg_left[i]->mvy)<0|| + y_pos-(mrg_left[i]->mvy)+yblk>ver) && (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + if( (x_pos-(mrg_right[i]->mvx)<0||x_pos-(mrg_right[i]->mvx)+xblk>hor||y_pos-(mrg_right[i]->mvy)<0|| + y_pos-(mrg_right[i]->mvy)+yblk>ver) && (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if( (mrg_left[i]->mvx == mrg_left[k]->mvx && mrg_left[i]->mvy == mrg_left[k]->mvy ) && + (mrg_right[i]->mvx == mrg_right[k]->mvx && mrg_right[i]->mvy == mrg_right[k]->mvy ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + med_l_px[k] = mrg_left[i]->mvx; + med_l_py[k] = mrg_left[i]->mvy; + med_l_aff1x[k] = mrg_left[i]->aff1_mvx; + med_l_aff1y[k] = mrg_left[i]->aff1_mvy; + med_l_aff2x[k] = mrg_left[i]->aff2_mvx; + med_l_aff2y[k] = mrg_left[i]->aff2_mvy; + med_l_aff3x[k] = mrg_left[i]->aff3_mvx; + med_l_aff3y[k] = mrg_left[i]->aff3_mvy; + + med_r_px[k] = mrg_right[i]->mvx; + med_r_py[k] = mrg_right[i]->mvy; + med_r_aff1x[k] = mrg_right[i]->aff1_mvx; + med_r_aff1y[k] = mrg_right[i]->aff1_mvy; + med_r_aff2x[k] = mrg_right[i]->aff2_mvx; + med_r_aff2y[k] = mrg_right[i]->aff2_mvy; + med_r_aff3x[k] = mrg_right[i]->aff3_mvx; + med_r_aff3y[k] = mrg_right[i]->aff3_mvy; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + mrg_left[i]->mvx = med_l_px[i]; + mrg_left[i]->mvy = med_l_py[i]; + mrg_left[i]->aff1_mvx = med_l_aff1x[i]; + mrg_left[i]->aff1_mvy = med_l_aff1y[i]; + mrg_left[i]->aff2_mvx = med_l_aff2x[i]; + mrg_left[i]->aff2_mvy = med_l_aff2y[i]; + mrg_left[i]->aff3_mvx = med_l_aff3x[i]; + mrg_left[i]->aff3_mvy = med_l_aff3y[i]; + + mrg_right[i]->mvx = med_r_px[i]; + mrg_right[i]->mvy = med_r_py[i]; + mrg_right[i]->aff1_mvx = med_r_aff1x[i]; + mrg_right[i]->aff1_mvy = med_r_aff1y[i]; + mrg_right[i]->aff2_mvx = med_r_aff2x[i]; + mrg_right[i]->aff2_mvy = med_r_aff2y[i]; + mrg_right[i]->aff3_mvx = med_r_aff3x[i]; + mrg_right[i]->aff3_mvy = med_r_aff3y[i]; + + } + for(i=0;i<=3;i++){ + med_l_px[i] = (float)HUGE_VAL; + med_l_py[i] = (float)HUGE_VAL; + med_l_aff1x[i] = (float)HUGE_VAL; + med_l_aff1y[i] = (float)HUGE_VAL; + med_l_aff2x[i] = (float)HUGE_VAL; + med_l_aff2y[i] = (float)HUGE_VAL; + med_l_aff3x[i] = (float)HUGE_VAL; + med_l_aff3y[i] = (float)HUGE_VAL; + + med_r_px[i] = (float)HUGE_VAL; + med_r_py[i] = (float)HUGE_VAL; + med_r_aff1x[i] = (float)HUGE_VAL; + med_r_aff1y[i] = (float)HUGE_VAL; + med_r_aff2x[i] = (float)HUGE_VAL; + med_r_aff2y[i] = (float)HUGE_VAL; + med_r_aff3x[i] = (float)HUGE_VAL; + med_r_aff3y[i] = (float)HUGE_VAL; + } +//E + aff_blk = 0; + + for(i = 0; i <= 3; i++){ + if( (mrg_left[i]->mvx == (float)HUGE_VAL && mrg_left[i]->mvy == (float)HUGE_VAL) && + (mrg_right[i]->mvx == (float)HUGE_VAL && mrg_right[i]->mvy == (float)HUGE_VAL) ){ + + left_mve = find_block(x_pos-1,y_pos+yblk,fmv1_array,info,t_level,&ule11,&ule12,&get_xblk,&get_yblk,0,0); + + find_block(x_pos-3,y_pos+yblk+1,fmv1_array,info,t_level,&left_affx1,&left_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos-2,y_pos+yblk+1,fmv1_array,info,t_level,&left_affx2,&left_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos-3,y_pos+yblk+2,fmv1_array,info,t_level,&left_affx3,&left_affy3,&get_xblk,&get_yblk,0,0); + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + + assert(left_mve->bi_mode>=9 || (left_mve->bi_mode == 7 && left_mve->aff_mrg == YES) ); + + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[i], x_pos, y_pos, x_pos-3,y_pos+yblk+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + aff_blk = 1; + } + + if(fmv2_array != NULL){ + right_mve = find_block(x_pos-1,y_pos+yblk,fmv2_array,info,t_level,&ule21,&ule22,&get_xblk,&get_yblk,0,0); + + find_block(x_pos-3,y_pos+yblk+1,fmv2_array,info,t_level,&right_affx1,&right_affy1,&get_xblk,&get_yblk,0,0); + find_block(x_pos-2,y_pos+yblk+1,fmv2_array,info,t_level,&right_affx2,&right_affy2,&get_xblk,&get_yblk,0,0); + find_block(x_pos-3,y_pos+yblk+2,fmv2_array,info,t_level,&right_affx3,&right_affy3,&get_xblk,&get_yblk,0,0); + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + + assert(right_mve->bi_mode>=9 || (right_mve->bi_mode == 7 && right_mve->aff_mrg == YES) ); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[i], x_pos, y_pos, x_pos-3,y_pos+yblk+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + aff_blk = 1; + } + + if(aff_blk == 1){ + if(left_mve != NULL && left_mve->is_predictor == YES){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_aff_mrg_mv(mrg_left[i], x_pos, y_pos, x_pos-3,y_pos+yblk+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + } + if(right_mve != NULL && right_mve->is_predictor == YES){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_aff_mrg_mv(mrg_right[i], x_pos, y_pos, x_pos-3,y_pos+yblk+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } + + } + + if(left_mve != NULL){ + if( left_mve->bi_mode <= 6 || left_mve->bi_mode == 8 || (left_mve->bi_mode == 7 && left_mve->aff_mrg == NO) ){ + mrg_left[i]->mvx = left_mve->mvx; mrg_left[i]->mvy = left_mve->mvy; mrg_left[i]->lifting_mode = CONNECTED; + }else{ + mrg_left[i]->mvx = ule11; mrg_left[i]->mvy = ule12; mrg_left[i]->lifting_mode = CONNECTED; + } + } + if(right_mve != NULL){ + if( right_mve->bi_mode <= 6 || right_mve->bi_mode == 8 || (right_mve->bi_mode == 7 && right_mve->aff_mrg == NO) ){ + mrg_right[i]->mvx = right_mve->mvx; mrg_right[i]->mvy = right_mve->mvy; mrg_right[i]->lifting_mode = CONNECTED; + }else{ + mrg_right[i]->mvx = ule21; mrg_right[i]->mvy = ule22; mrg_right[i]->lifting_mode = CONNECTED; + } + } + break; + } + } + + aff_blk = 0; + //////////////////////// + for(i = 0;i <= 3;i ++){ + if( (x_pos-(mrg_left[i]->mvx)<0||x_pos-(mrg_left[i]->mvx)+xblk>hor||y_pos-(mrg_left[i]->mvy)<0|| + y_pos-(mrg_left[i]->mvy)+yblk>ver) && (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + if( (x_pos-(mrg_right[i]->mvx)<0||x_pos-(mrg_right[i]->mvx)+xblk>hor||y_pos-(mrg_right[i]->mvy)<0|| + y_pos-(mrg_right[i]->mvy)+yblk>ver) && (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if( (mrg_left[i]->mvx == mrg_left[k]->mvx && mrg_left[i]->mvy == mrg_left[k]->mvy ) && + (mrg_right[i]->mvx == mrg_right[k]->mvx && mrg_right[i]->mvy == mrg_right[k]->mvy ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + med_l_px[k] = mrg_left[i]->mvx; + med_l_py[k] = mrg_left[i]->mvy; + med_l_aff1x[k] = mrg_left[i]->aff1_mvx; + med_l_aff1y[k] = mrg_left[i]->aff1_mvy; + med_l_aff2x[k] = mrg_left[i]->aff2_mvx; + med_l_aff2y[k] = mrg_left[i]->aff2_mvy; + med_l_aff3x[k] = mrg_left[i]->aff3_mvx; + med_l_aff3y[k] = mrg_left[i]->aff3_mvy; + + med_r_px[k] = mrg_right[i]->mvx; + med_r_py[k] = mrg_right[i]->mvy; + med_r_aff1x[k] = mrg_right[i]->aff1_mvx; + med_r_aff1y[k] = mrg_right[i]->aff1_mvy; + med_r_aff2x[k] = mrg_right[i]->aff2_mvx; + med_r_aff2y[k] = mrg_right[i]->aff2_mvy; + med_r_aff3x[k] = mrg_right[i]->aff3_mvx; + med_r_aff3y[k] = mrg_right[i]->aff3_mvy; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + mrg_left[i]->mvx = med_l_px[i]; + mrg_left[i]->mvy = med_l_py[i]; + mrg_left[i]->aff1_mvx = med_l_aff1x[i]; + mrg_left[i]->aff1_mvy = med_l_aff1y[i]; + mrg_left[i]->aff2_mvx = med_l_aff2x[i]; + mrg_left[i]->aff2_mvy = med_l_aff2y[i]; + mrg_left[i]->aff3_mvx = med_l_aff3x[i]; + mrg_left[i]->aff3_mvy = med_l_aff3y[i]; + + mrg_right[i]->mvx = med_r_px[i]; + mrg_right[i]->mvy = med_r_py[i]; + mrg_right[i]->aff1_mvx = med_r_aff1x[i]; + mrg_right[i]->aff1_mvy = med_r_aff1y[i]; + mrg_right[i]->aff2_mvx = med_r_aff2x[i]; + mrg_right[i]->aff2_mvy = med_r_aff2y[i]; + mrg_right[i]->aff3_mvx = med_r_aff3x[i]; + mrg_right[i]->aff3_mvy = med_r_aff3y[i]; + + } +} +//////////////////////////////////////////////////// + +//Added on 01.17.2016 +float med(float a, float b, float c) +{ + return ((a>b) ? ((a>c) ? ((b>c) ? b : c) : a) : + ((b>c) ? ((a>c) ? a : c) : b)); +} + +vector_ptr find_block(int x, int y, vector_ptr root, videoinfo info, int t_level, float *mvx, float *mvy, + int *get_xblk, int *get_yblk, int get_addx, int get_addy){ //Find the + int i,j,k,sum; + int pos; + int x0,y0; + vector_ptr v1; + int xblk = info.xblk[t_level],yblk = info.yblk[t_level]; + int xblk2, yblk2; + + int addx,addy; + int int_mvx,int_mvy; + float fmvx1,fmvy1,fmvx2,fmvy2,fmvx3,fmvy3,fmvx4,fmvy4; + + sum = 0; + pos = 0; + + if(x < 0 || x >= info.ywidth || y < 0 || y >= info.yheight){ + v1 = NULL; + *mvx = (float)HUGE_VAL; + *mvy = (float)HUGE_VAL; + return v1; + } + + while(y >= sum){ + sum += info.yblk[t_level]; + pos += info.xnum[t_level]; + } + pos -= info.xnum[t_level]; + + sum = 0; + while(x >= sum){ + sum += info.xblk[t_level]; + pos ++; + } + pos --; + + v1 = &root[pos]; + x0 = info.xblk[t_level] * ( pos % info.xnum[t_level]); + y0 = info.yblk[t_level] * (int)(pos / info.xnum[t_level]); + +// printf("Original position: x0 = %d, y0 = %d\n",x0,y0); + + while(v1->child){ + if( (y0 + yblk/2) > y){ + if( (x0 + xblk/2) > x){ + v1 = v1->child0; + xblk/=2; + yblk/=2; + } + else{ + v1 = v1->child1; + x0 = x0 + xblk/2; + xblk/=2; + yblk/=2; + } + } + else{ + if( (x0 + xblk/2) > x){ + v1 = v1->child2; + y0 = y0 + yblk/2; + xblk/=2; + yblk/=2; + } + else{ + v1 = v1->child3; + x0 = x0 + xblk/2; + y0 = y0 + yblk/2; + xblk/=2; + yblk/=2; + } + } + } + + ////////// Added on 04.03.2016 ////////// + xblk2 = ( x0 + xblk <= info.ywidth ) ? xblk : info.ywidth - x0; + yblk2 = ( y0 + yblk <= info.yheight ) ? yblk : info.yheight - y0; + ////////////////////////////////////////////// + + if(get_addx == 0 && get_addy == 0){ + if( (x-x0+1)/xblk2 == 1 ) + addx = 1; + else + addx = 0; + + if( (y-y0+1)/yblk2 == 1 ) + addy = 1; + else + addy = 0; + }else{ + addx = get_addx; + addy = get_addy; + } + + ////////// Modified on 01.05.2016 ////////// + if( (v1->bi_mode >= 0 && v1->bi_mode <= 6) || v1->bi_mode == 8 || (v1->bi_mode == 7 && v1->aff_mrg == NO) ){ + *mvx = v1->mvx; + *mvy = v1->mvy; + } + else if( (v1->bi_mode >= 9 && v1->bi_mode <= 11) || (v1->bi_mode == 7 && v1->aff_mrg == YES) ){ +// *mvx = (v1->aff2_mvx - v1->aff1_mvx)*(x-x0 + addx)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-y0 + addy)/yblk2 + v1->aff1_mvx; +// *mvy = (v1->aff2_mvy - v1->aff1_mvy)*(x-x0 + addx)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-y0 + addy)/yblk2 + v1->aff1_mvy; +//Added on 01.24.2019 + if(get_addx == 0 && get_addy == 0){ + *mvx = (v1->aff2_mvx - v1->aff1_mvx)*(x-x0 + addx)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-y0 + addy)/yblk2 + v1->aff1_mvx; + *mvy = (v1->aff2_mvy - v1->aff1_mvy)*(x-x0 + addx)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-y0 + addy)/yblk2 + v1->aff1_mvy; + }else if(get_addx == 0 && get_addy == 1){ + fmvx3 = (v1->aff2_mvx - v1->aff1_mvx)*(x-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-1-y0)/yblk2 + v1->aff1_mvx; + fmvy3 = (v1->aff2_mvy - v1->aff1_mvy)*(x-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-1-y0)/yblk2 + v1->aff1_mvy; + + fmvx4 = (v1->aff2_mvx - v1->aff1_mvx)*(x-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-2-y0)/yblk2 + v1->aff1_mvx; + fmvy4 = (v1->aff2_mvy - v1->aff1_mvy)*(x-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-2-y0)/yblk2 + v1->aff1_mvy; + + *mvx = fmvx3 + 2 * (fmvx3 - fmvx4); + *mvy = fmvy3 + 2 * (fmvy3 - fmvy4); + }else if(get_addx == 1 && get_addy == 0){ + fmvx1 = (v1->aff2_mvx - v1->aff1_mvx)*(x-1-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-y0)/yblk2 + v1->aff1_mvx; + fmvy1 = (v1->aff2_mvy - v1->aff1_mvy)*(x-1-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-y0)/yblk2 + v1->aff1_mvy; + + fmvx2 = (v1->aff2_mvx - v1->aff1_mvx)*(x-2-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-y0)/yblk2 + v1->aff1_mvx; + fmvy2 = (v1->aff2_mvy - v1->aff1_mvy)*(x-2-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-y0)/yblk2 + v1->aff1_mvy; + + *mvx = fmvx1 + 2 * (fmvx1 - fmvx2); + *mvy = fmvy1 + 2 * (fmvy1 - fmvy2); + }else if(get_addx == 1 && get_addy == 1){ + fmvx1 = (v1->aff2_mvx - v1->aff1_mvx)*(x-1-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-1-y0)/yblk2 + v1->aff1_mvx; + fmvy1 = (v1->aff2_mvy - v1->aff1_mvy)*(x-1-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-1-y0)/yblk2 + v1->aff1_mvy; + + fmvx2 = (v1->aff2_mvx - v1->aff1_mvx)*(x-2-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-1-y0)/yblk2 + v1->aff1_mvx; + fmvy2 = (v1->aff2_mvy - v1->aff1_mvy)*(x-2-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-1-y0)/yblk2 + v1->aff1_mvy; + + fmvx3 = (v1->aff2_mvx - v1->aff1_mvx)*(x-1-x0)/xblk2 + (v1->aff3_mvx - v1->aff1_mvx)*(y-2-y0)/yblk2 + v1->aff1_mvx; + fmvy3 = (v1->aff2_mvy - v1->aff1_mvy)*(x-1-x0)/xblk2 + (v1->aff3_mvy - v1->aff1_mvy)*(y-2-y0)/yblk2 + v1->aff1_mvy; + + *mvx = fmvx1 + 2 * (fmvx1 - fmvx3) + 2 * (fmvx1 - fmvx2); + *mvy = fmvy1 + 2 * (fmvy1 - fmvy3) + 2 * (fmvy1 - fmvy2); + }else + assert(0); +/////////////////////////////////////////////////////////////// + } + + if(get_addx == 1 || get_addy == 1){ + (*mvx) = (*mvx) * AFF_SUBPEL; + (*mvy) = (*mvy) * AFF_SUBPEL; + int_mvx = (int)(*mvx); + int_mvy = (int)(*mvy); + (*mvx) = (float)(int_mvx); + (*mvy) = (float)(int_mvy); + (*mvx) = (*mvx) / AFF_SUBPEL; + (*mvy) = (*mvy) / AFF_SUBPEL; + } +////////////////////////////////////////////// + + if(v1->bi_mode == UNDEFINED || v1->bi_mode == DIRECTIONAL_IBLOCK || v1->is_predictor == NO){ + v1 = NULL; + *mvx = (float)HUGE_VAL; + *mvy = (float)HUGE_VAL; + } + +// printf("mvx = %f, mvy = %f\n",*mvx,*mvy); + + *get_xblk = xblk2; + *get_yblk = yblk2; + + return v1; +} + +float find_affine_SAD(float *frame_cur, float *frame_ref1, float *frame_ref2, float *upframe1, float *upframe2, ModeInfo v11, ModeInfo v12, ModeInfo v13, + ModeInfo v21, ModeInfo v22, ModeInfo v23, int xblk, int yblk, int cx, int cy, int hor, int ver, + int best_mode, int subpel, int type){ +//type 0: interpolation in both left and right +//type 1: interpolation in left only +//type 2: interpolation in right only + + float mse,fx1,fy1,fx2,fy2; + float px1,py1,px2,py2; + float ptemp,diff,sum; + float mvx1,mvy1,mvx2,mvy2; + float ptemp1,ptemp2; + + float dhorx1,dverx1,dhory1,dvery1,dhorx2,dverx2,dhory2,dvery2; //Added by Yuan Liu on 04.23.2016 + float mvx1_int, mvx2_int, mvy1_int, mvy2_int; //Added by Yuan Liu on 04.23.2016 + + int x,y,m,m0; + int uphor,upver; + int upx11,upx12,upy11,upy12;// + int upx21,upx22,upy21,upy22; + int pos1,pos2; + + int scale = 1 << subpel; + scale = scale << ADD_SUB; //Added on 03.13.2017 + + float accu = 1/((float)scale); + + int x1,x2,y1,y2; + float dX,dY; + +// printf("Enter affine SAD!\n"); + + uphor = ( hor - 1 ) * scale + 1; + upver = ( ver - 1 ) * scale + 1; + + dhorx1 = (v12.mvx - v11.mvx)/xblk; + dhory1 = (v12.mvy - v11.mvy)/xblk; + + dverx1 = (v13.mvx - v11.mvx)/yblk; + dvery1 = (v13.mvy - v11.mvy)/yblk; + + dhorx2 = (v22.mvx - v21.mvx)/xblk; + dhory2 = (v22.mvy - v21.mvy)/xblk; + + dverx2 = (v23.mvx - v21.mvx)/yblk; + dvery2 = (v23.mvy - v21.mvy)/yblk; + + m = cy * hor + cx; + m0 = 0; + sum = 0; + + mvx1 = v11.mvx; + mvy1 = v11.mvy; + + mvx1_int = mvx1; + mvy1_int = mvy1; + + mvx2 = v21.mvx; + mvy2 = v21.mvy; + + mvx2_int = mvx2; + mvy2_int = mvy2; + + for( y = 0; y < yblk; y++ ) { + for( x = 0; x < xblk; x++ ) { + +// mvx1 = (v12.mvx - v11.mvx)*x/xblk + (v13.mvx - v11.mvx)*y/yblk + v11.mvx; +// mvy1 = (v12.mvy - v11.mvy)*x/xblk + (v13.mvy - v11.mvy)*y/yblk + v11.mvy; + + px1 = (float)cx - mvx1; + py1 = (float)cy - mvy1; + + fx1 = px1 + (float)x; + fy1 = py1 + (float)y; + +// if( ( ( int )( fx1 * 16 ) ) % 16 == 0 )fx1 = floor(fx1); +// if( ( ( int )( fy1 * 16 ) ) % 16 == 0 )fy1 = floor(fy1); + + if(best_mode == RIGHT_CONNECTED_AFF){//If RIGHT_CONNECTED + + x2 = ( int )ceil( fx1 ); + x1 = ( int )floor( fx1 ); + y2 = ( int )ceil( fy1 ); + y1 = ( int )floor( fy1 ); + + if( x2 >= (hor-1) || x1 < 0 || y2 >= (ver-1) || y1 < 0 ){ +// assert(fx1 > (hor-1) || fx1 < 0 || fy1 > (ver-1) || fy1 < 0); + ptemp = (float)HUGE_VAL; + } + else{ + upx11 = (int)(fx1/accu); + upy11 = (int)(fy1/accu); + + pos1 = upy11*uphor + upx11; + + dX = fx1 * scale - upx11; + dY = fy1 * scale - upy11; + + if(x1 == x2 && y1 == y2) + ptemp = upframe2[pos1]; + else if(x1 == x2) + ptemp = (1 - dY) * upframe2[pos1] + dY * upframe2[pos1 + uphor]; + else if(y1 == y2) + ptemp = (1 - dX) * upframe2[pos1] + dX * upframe2[pos1 + 1]; + else + ptemp = ( 1 - dY ) * ( ( 1 - dX ) * upframe2[pos1] + dX * upframe2[pos1 + 1] ) + dY * ( ( 1 - dX ) * upframe2[pos1 + uphor] + dX * upframe2[pos1 + uphor + 1] ); + } + + mvx1 += dhorx1; + mvy1 += dhory1; + + }else if(best_mode == LEFT_CONNECTED_AFF){//If LEFT_CONNECTED + x2 = ( int )ceil( fx1 ); + x1 = ( int )floor( fx1 ); + y2 = ( int )ceil( fy1 ); + y1 = ( int )floor( fy1 ); + + if( x2 >= (hor-1) || x1 < 0 || y2 >= (ver-1) || y1 < 0 ){ + ptemp = (float)HUGE_VAL; + } + else{ + upx11 = (int)(fx1/accu); + upy11 = (int)(fy1/accu); + + pos1 = upy11*uphor + upx11; + + dX = fx1 * scale - upx11; + dY = fy1 * scale - upy11; + + if(x1 == x2 && y1 == y2) + ptemp = upframe1[pos1]; + else if(x1 == x2) + ptemp = (1 - dY) * upframe1[pos1] + dY * upframe1[pos1 + uphor]; + else if(y1 == y2) + ptemp = (1 - dX) * upframe1[pos1] + dX * upframe1[pos1 + 1]; + else + ptemp = ( 1 - dY ) * ( ( 1 - dX ) * upframe1[pos1] + dX * upframe1[pos1 + 1] ) + dY * ( ( 1 - dX ) * upframe1[pos1 + uphor] + dX * upframe1[pos1 + uphor + 1] ); + } + + mvx1 += dhorx1; + mvy1 += dhory1; + } + else if(best_mode == BI_CONNECTED_AFF){//If BI_CONNECTED +//LEFT MV + if(type==0 || type==1 || type==3 || type == 4){ + x2 = ( int )ceil( fx1 ); + x1 = ( int )floor( fx1 ); + y2 = ( int )ceil( fy1 ); + y1 = ( int )floor( fy1 ); + + if( x2 >= (hor-1) || x1 < 0 || y2 >= (ver-1) || y1 < 0 ){ +// assert(fx1 > (hor-1) || fx1 < 0 || fy1 > (ver-1) || fy1 < 0); + ptemp1 = (float)HUGE_VAL; + } + else{ + upx11 = (int)(fx1/accu); + upy11 = (int)(fy1/accu); + + pos1 = upy11*uphor + upx11; + + dX = fx1 * scale - upx11; + dY = fy1 * scale - upy11; + + if(x1 == x2 && y1 == y2) + ptemp1 = upframe1[pos1]; + else if(x1 == x2) + ptemp1 = (1 - dY) * upframe1[pos1] + dY * upframe1[pos1 + uphor]; + else if(y1 == y2) + ptemp1 = (1 - dX) * upframe1[pos1] + dX * upframe1[pos1 + 1]; + else + ptemp1 = ( 1 - dY ) * ( ( 1 - dX ) * upframe1[pos1] + dX * upframe1[pos1 + 1] ) + dY * ( ( 1 - dX ) * upframe1[pos1 + uphor] + dX * upframe1[pos1 + uphor + 1] ); + + if(type==0 || type==1) + block_buff1[m0] = ptemp1; + + mvx1 += dhorx1; + mvy1 += dhory1; + } + }//if type = 0 or 1 + else + ptemp1 = block_buff1[m0]; + +//RIGHT MV + if(type==0 || type==2 || type==3 || type == 4){ +// mvx2 = (v22.mvx - v21.mvx)*x/xblk + (v23.mvx - v21.mvx)*y/yblk + v21.mvx; +// mvy2 = (v22.mvy - v21.mvy)*x/xblk + (v23.mvy - v21.mvy)*y/yblk + v21.mvy; + + px2 = (float)cx - mvx2; + py2 = (float)cy - mvy2; + + fx2 = px2 + (float)x; + fy2 = py2 + (float)y; + + x2 = ( int )ceil( fx2 ); + x1 = ( int )floor( fx2 ); + y2 = ( int )ceil( fy2 ); + y1 = ( int )floor( fy2 ); + + if( x2 >= (hor-1) || x1 < 0 || y2 >= (ver-1) || y1 < 0 ){ +// assert(fx2 > (hor-1) || fx2 < 0 || fy2 > (ver-1) || fy2 < 0); + ptemp2 = (float)HUGE_VAL; + } + else{ + upx21 = (int)(fx2/accu); + upy21 = (int)(fy2/accu); + + pos2 = upy21*uphor + upx21; + + dX = fx2 * scale - upx21; + dY = fy2 * scale - upy21; + + if(x1 == x2 && y1 == y2) + ptemp2 = upframe2[pos2]; + else if(x1 == x2) + ptemp2 = (1 - dY) * upframe2[pos2] + dY * upframe2[pos2 + uphor]; + else if(y1 == y2) + ptemp2 = (1 - dX) * upframe2[pos2] + dX * upframe2[pos2 + 1]; + else + ptemp2 = ( 1 - dY ) * ( ( 1 - dX ) * upframe2[pos2] + dX * upframe2[pos2 + 1] ) + dY * ( ( 1 - dX ) * upframe2[pos2 + uphor] + dX * upframe2[pos2 + uphor + 1] ); + + if(type==0 || type==2) + block_buff2[m0] = ptemp2; + } + mvx2 += dhorx2; + mvy2 += dhory2; + }//type = 0 or 2 + else + ptemp2 = block_buff2[m0]; + + if(ptemp1 == (float)HUGE_VAL || ptemp2 == (float)HUGE_VAL) + ptemp = (float)HUGE_VAL; + else + ptemp = 0.5f * ( ptemp1 + ptemp2 ); + + m0++; + }//if BI_AFF + else + assert(0); + + if(ptemp == (float)HUGE_VAL){ +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); + return ptemp; + break; + } + + diff = frame_cur[m] - ptemp; + sum = ( diff < 0 ) ? (sum - diff) : (sum + diff); + m++; + + if(type == 4) + printf("%d\t",(int)fabs(diff) ); + + }// x + if(ptemp == (float)HUGE_VAL)break; + m += hor - xblk; + + mvx1 = mvx1_int + dverx1; + mvy1 = mvy1_int + dvery1; + + mvx1_int = mvx1; + mvy1_int = mvy1; + + if(best_mode == BI_CONNECTED_AFF){ + mvx2 = mvx2_int + dverx2; + mvy2 = mvy2_int + dvery2; + + mvx2_int = mvx2; + mvy2_int = mvy2; + } + + if(type == 4) + printf("\n"); + + }// y + +// printf("affine SAD sum: %f\n",sum); +// sum /= xblk * yblk; + +// printf("Exit affine SAD!\n"); + +/* if(type == 4) + printf("\n\n"); +*/ + return sum; +} + +float find_affine_MSE(float *frame_cur, float *frame_ref1, float *frame_ref2, float *aff_ref_var, ModeInfo v11, ModeInfo v12, ModeInfo v13, ModeInfo v21, ModeInfo v22, ModeInfo v23, int xblk, int yblk, int cx, int cy, int hor, int ver, int best_mode){ + float mse,fx1,fy1,fx2,fy2; + float px1,py1,px2,py2; + float ptemp,diff,sum; + float mvx1,mvy1,mvx2,mvy2; + + int x,y,m; + + int ref_x1,ref_y1,ref_x2,ref_y2; + + float aff_ref_mean1, aff_ref_mean2; + + m = cy * hor + cx; + sum = 0; + + *aff_ref_var = 0; + aff_ref_mean1 = 0; + aff_ref_mean2 = 0; + + for( y = 0; y < yblk; y++ ) { + for( x = 0; x < xblk; x++ ) { + + mvx1 = (v12.mvx - v11.mvx)*x/xblk + (v13.mvx - v11.mvx)*y/yblk + v11.mvx; + mvy1 = (v12.mvy - v11.mvy)*x/xblk + (v13.mvy - v11.mvy)*y/yblk + v11.mvy; + + px1 = cx - mvx1; + py1 = cy - mvy1; + + fx1 = px1 + x; + fy1 = py1 + y; + + position( &ref_x1, &ref_y1, fx1, fy1, mvx1, mvy1, hor, ver ); + + if(best_mode == RIGHT_CONNECTED_AFF){ + ptemp = interpolate( fx1, fy1, frame_ref2, hor, ver, TYPE ); + *aff_ref_var += frame_ref2[ref_y1 * hor + ref_x1] * frame_ref2[ref_y1 * hor + ref_x1]; + aff_ref_mean1 += frame_ref2[ref_y1 * hor + ref_x1]; + + }else if(best_mode == LEFT_CONNECTED_AFF){ + ptemp = interpolate( fx1, fy1, frame_ref1, hor, ver, TYPE ); + *aff_ref_var += frame_ref1[ref_y1 * hor + ref_x1] * frame_ref1[ref_y1 * hor + ref_x1]; + aff_ref_mean1 += frame_ref1[ref_y1 * hor + ref_x1]; + } + else if(best_mode == BI_CONNECTED_AFF){ + mvx2 = (v22.mvx - v21.mvx)*x/xblk + (v23.mvx - v21.mvx)*y/yblk + v21.mvx; + mvy2 = (v22.mvy - v21.mvy)*x/xblk + (v23.mvy - v21.mvy)*y/yblk + v21.mvy; + + px2 = cx - mvx2; + py2 = cy - mvy2; + + fx2 = px2 + x; + fy2 = py2 + y; + + ptemp = 0.5f * ( interpolate( fx1, fy1, frame_ref1, hor, ver, TYPE ) + interpolate(fx2, fy2, frame_ref2, hor, ver, TYPE ) ); + + position( &ref_x2, &ref_y2, fx2, fy2, mvx2, mvy2, hor, ver ); + + *aff_ref_var += 0.5f * ( frame_ref1[ref_y1 * hor + ref_x1] * frame_ref1[ref_y1 * hor + ref_x1] + + frame_ref2[ref_y2 * hor + ref_x2] * frame_ref2[ref_y2 * hor + ref_x2] ); + aff_ref_mean1 += frame_ref1[ref_y1 * hor + ref_x1]; + aff_ref_mean2 += frame_ref2[ref_y2 * hor + ref_x2]; + } + + if(ptemp == (float)HUGE_VAL){ +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); + return ptemp; + break; + } + + diff = frame_cur[m] - ptemp; + sum += diff * diff; + m++; + } + if(ptemp == (float)HUGE_VAL)break; + m += hor - xblk; + } + +// printf("affine SSE sum: %f\n",sum); + sum /= xblk * yblk; + + (*aff_ref_var) /= xblk * yblk; + aff_ref_mean1 /= xblk * yblk; + aff_ref_mean2 /= xblk * yblk; + + if(best_mode == LEFT_CONNECTED_AFF || best_mode == RIGHT_CONNECTED_AFF){ + (*aff_ref_var) -= aff_ref_mean1 * aff_ref_mean1; + }else{ + assert(best_mode == BI_CONNECTED_AFF); + (*aff_ref_var) -= 0.5f * (aff_ref_mean1 * aff_ref_mean1 + aff_ref_mean2 * aff_ref_mean2); + } + +// printf("affine_ref_var = %f\n",*aff_ref_var); + + return sum; +} + +float delta_v_search_bi(float *frame_cur, float *frame_ref1, float *frame_ref2,float *upframe1, float *upframe2, int ct1x, int ct1y, int ct2x, int ct2y, ModeInfo *v11, + ModeInfo *v12, ModeInfo *v13, ModeInfo *v21, ModeInfo *v22, ModeInfo *v23, ModeInfo *dv11, + ModeInfo *dv12, ModeInfo *dv13, ModeInfo *dv21, ModeInfo *dv22, ModeInfo *dv23, int xblk, + int yblk, int cx, int cy, int hor, int ver, int best_mode, int lambda, int subpel, int t_level, int type){ + // type 0: INTER + // type 2: MERGE UP + // type 3: MERGE INTER + float i,j; + int k = 0; + float tx1,ty1,tx2,ty2,tx3,ty3; + int max; + float accu = 0.25, range; + + float min_j, get_sad, code_v11,code_v12,code_v13, code_v21,code_v22,code_v23, get_bit, get_mvx, get_mvy, best_sad; + float min_j_lst; + + if(type == 2 || type == 3){ + max = 3; + range = accu * BI_RANGE; + }else{ + assert(type == 0); + max = 3; + range = accu * BI_RANGE; + } + + range = range + t_level * 0.25; + + dv11->mvx = v11->mvx; + dv11->mvy = v11->mvy; + dv12->mvx = v12->mvx; + dv12->mvy = v12->mvy; + dv13->mvx = v13->mvx; + dv13->mvy = v13->mvy; + + dv21->mvx = v21->mvx; + dv21->mvy = v21->mvy; + dv22->mvx = v22->mvx; + dv22->mvy = v22->mvy; + dv23->mvx = v23->mvx; + dv23->mvy = v23->mvy; + + tv11->mvx = v11->mvx; + tv11->mvy = v11->mvy; + tv12->mvx = v12->mvx; + tv12->mvy = v12->mvy; + tv13->mvx = v13->mvx; + tv13->mvy = v13->mvy; + + tv21->mvx = v21->mvx; + tv21->mvy = v21->mvy; + tv22->mvx = v22->mvx; + tv22->mvy = v22->mvy; + tv23->mvx = v23->mvx; + tv23->mvy = v23->mvy; + +// code_v1 = get_bit_cost(lambda,dv1->mvx + 0.5,dv1->mvy,v1->mvx,v1->mvy,0,0,subpel); +// printf("code v1 = %f\n",code_v1); + + code_v11 = 0; + code_v12 = 0; + code_v13 = 0; + + code_v21 = 0; + code_v22 = 0; + code_v23 = 0; + + min_j = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + best_sad = min_j; + +// if(type == 0) +// assert(min_j != (float)HUGE_VAL); + + ////////////// INITIALIZATION ///////////// + if(type == 2){ + code_v12 = get_bit_cost(lambda,dv12->mvx,dv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel); + code_v22 = get_bit_cost(lambda,dv22->mvx,dv22->mvy,v22->mvx,v22->mvy,ct2x,ct2y,subpel); + }else if(type == 3){ + code_v13 = get_bit_cost(lambda,dv13->mvx,dv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel); + code_v23 = get_bit_cost(lambda,dv23->mvx,dv23->mvy,v23->mvx,v23->mvy,ct2x,ct2y,subpel); + }else{ + assert(type == 0); + code_v11 = get_bit_cost(lambda,dv11->mvx,dv11->mvy,v11->mvx,v11->mvy,ct1x,ct1y,subpel); + code_v12 = get_bit_cost(lambda,dv12->mvx,dv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel); + code_v13 = get_bit_cost(lambda,dv13->mvx,dv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel); + + code_v21 = get_bit_cost(lambda,dv21->mvx,dv21->mvy,v21->mvx,v21->mvy,ct2x,ct2y,subpel); + code_v22 = get_bit_cost(lambda,dv22->mvx,dv22->mvy,v22->mvx,v22->mvy,ct2x,ct2y,subpel); + code_v23 = get_bit_cost(lambda,dv23->mvx,dv23->mvy,v23->mvx,v23->mvy,ct2x,ct2y,subpel); + } + min_j = min_j + code_v11 + code_v12 + code_v13 + code_v21 + code_v22 + code_v23; + min_j_lst = min_j; + /////////////////////////////////////////////// + + while(k < max){ +//V11 + if(type == 0 || type == 1){ + tx1 = cx - dv11->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty1 = cy - dv11->mvy; + +// if(type == 0) +// assert(tx1 >= 0 && tx1 < hor && ty1 >= 0 && ty1 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx1 - i >= 0 && tx1 - i < hor && ty1 - j >= 0 && ty1 - j < ver && (i!=0 || j!=0) ){ + tv11->mvx = dv11->mvx + i; + tv11->mvy = dv11->mvy + j; + + if(i == (-1)*range && j == (-1)*range && type == 0 ) + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*tv11,*dv12,*dv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + else + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*tv11,*dv12,*dv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,1); + + get_bit = get_bit_cost(lambda,tv11->mvx,tv11->mvy,v11->mvx,v11->mvy,ct1x,ct1y,subpel); + + if( (get_sad + get_bit + code_v12 + code_v13 + code_v21 + code_v22 + code_v23) < min_j ){ + min_j = get_sad + get_bit + code_v12 + code_v13 + code_v21 + code_v22 + code_v23; + code_v11 = get_bit; + best_sad = get_sad; + + get_mvx = tv11->mvx - dv11->mvx; + get_mvy = tv11->mvy - dv11->mvy; + } + } + } + } + dv11->mvx = dv11->mvx + get_mvx; + dv11->mvy = dv11->mvy + get_mvy; + + assert( code_v11 == get_bit_cost(lambda,dv11->mvx,dv11->mvy,v11->mvx,v11->mvy,ct1x,ct1y,subpel) ); + + }//type 0 or 1 + +//V12 + if(type == 0 || type == 2){ + tx2 = cx + xblk - dv12->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty2 = cy - dv12->mvy; + +// if(type == 0) +// assert(tx2 >= 0 && tx2 < hor && ty2 >= 0 && ty2 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx2 - i >= 0 && tx2 - i < hor && ty2 - j >= 0 && ty2 - j < ver && (i!=0 || j!=0) ){ + tv12->mvx = dv12->mvx + i; + tv12->mvy = dv12->mvy + j; + + if(i == (-1)*range && j == (-1)*range && type == 2 ) + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*tv12,*dv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + else + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*tv12,*dv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,1); + + get_bit = get_bit_cost(lambda,tv12->mvx,tv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel); + + if( (get_sad + code_v11 + get_bit + code_v13 + code_v21 + code_v22 + code_v23) < min_j ){ + min_j = get_sad + code_v11 + get_bit + code_v13 + code_v21 + code_v22 + code_v23; + code_v12 = get_bit; + best_sad = get_sad; + + get_mvx = tv12->mvx - dv12->mvx; + get_mvy = tv12->mvy - dv12->mvy; + } + } + } + } + dv12->mvx = dv12->mvx + get_mvx; + dv12->mvy = dv12->mvy + get_mvy; + + assert( code_v12 == get_bit_cost(lambda,dv12->mvx,dv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel) ); + + }//type 0 or 2 + +//V13 + if(type == 0 || type == 3){ + tx3 = cx - dv13->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty3 = cy + yblk - dv13->mvy; + +// if(type == 0) +// assert(tx3 >= 0 && tx3 < hor && ty3 >= 0 && ty3 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu ){ + for(j = (-1)*range;j <= range; j+= accu ){ + if(tx3 - i >= 0 && tx3 - i < hor && ty3 - j >= 0 && ty3 - j < ver && (i!=0 || j!=0) ){ + tv13->mvx = dv13->mvx + i; + tv13->mvy = dv13->mvy + j; + + if(i == (-1)*range && j == (-1)*range && type == 3 ) + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*tv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + else + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*tv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,1); + + get_bit = get_bit_cost(lambda,tv13->mvx,tv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel); + + if( (get_sad + code_v11 + code_v12 + get_bit + code_v21 + code_v22 + code_v23) < min_j ){ + min_j = get_sad + code_v11 + code_v12 + get_bit + code_v21 + code_v22 + code_v23; + code_v13 = get_bit; + best_sad = get_sad; + + get_mvx = tv13->mvx - dv13->mvx; + get_mvy = tv13->mvy - dv13->mvy; + } + } + } + } + dv13->mvx = dv13->mvx + get_mvx; + dv13->mvy = dv13->mvy + get_mvy; + + assert( code_v13 == get_bit_cost(lambda,dv13->mvx,dv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel) ); + + }//type 0 or 3 + +//////// +//RIGHT SEARCH +//V21 + if(type == 0 || type == 1){ + tx1 = cx - dv21->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty1 = cy - dv21->mvy; + +// if(type == 0) +// assert(tx1 >= 0 && tx1 < hor && ty1 >= 0 && ty1 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx1 - i >= 0 && tx1 - i < hor && ty1 - j >= 0 && ty1 - j < ver && (i!=0 || j!=0) ){ + tv21->mvx = dv21->mvx + i; + tv21->mvy = dv21->mvy + j; + + if(i == (-1)*range && j == (-1)*range ) + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*tv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + else + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*tv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,2); + + get_bit = get_bit_cost(lambda,tv21->mvx,tv21->mvy,v21->mvx,v21->mvy,ct2x,ct2y,subpel); + + if( (get_sad + code_v11 + code_v12 + code_v13 + get_bit + code_v22 + code_v23) < min_j ){ + min_j = get_sad + code_v11 + code_v12 + code_v13 + get_bit + code_v22 + code_v23; + code_v21 = get_bit; + best_sad = get_sad; + + get_mvx = tv21->mvx - dv21->mvx; + get_mvy = tv21->mvy - dv21->mvy; + } + } + } + } + dv21->mvx = dv21->mvx + get_mvx; + dv21->mvy = dv21->mvy + get_mvy; + + assert( code_v21 == get_bit_cost(lambda,dv21->mvx,dv21->mvy,v21->mvx,v21->mvy,ct2x,ct2y,subpel) ); + + }//type 0 or 1 + +//V22 + if(type == 0 || type == 2){ + tx2 = cx + xblk - dv22->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty2 = cy - dv22->mvy; + +// if(type == 0) +// assert(tx2 >= 0 && tx2 < hor && ty2 >= 0 && ty2 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx2 - i >= 0 && tx2 - i < hor && ty2 - j >= 0 && ty2 - j < ver && (i!=0 || j!=0) ){ + tv22->mvx = dv22->mvx + i; + tv22->mvy = dv22->mvy + j; + + if(i == (-1)*range && j == (-1)*range && type == 2 ) + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*dv21,*tv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + else + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*dv21,*tv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,2); + + get_bit = get_bit_cost(lambda,tv22->mvx,tv22->mvy,v22->mvx,v22->mvy,ct2x,ct2y,subpel); + + if( (get_sad + code_v11 + code_v12 + code_v13 + code_v21 + get_bit + code_v23) < min_j ){ + min_j = get_sad + code_v11 + code_v12 + code_v13 + code_v21 + get_bit + code_v23; + code_v22 = get_bit; + best_sad = get_sad; + + get_mvx = tv22->mvx - dv22->mvx; + get_mvy = tv22->mvy - dv22->mvy; + } + } + } + } + dv22->mvx = dv22->mvx + get_mvx; + dv22->mvy = dv22->mvy + get_mvy; + + assert( code_v22 == get_bit_cost(lambda,dv22->mvx,dv22->mvy,v22->mvx,v22->mvy,ct2x,ct2y,subpel) ); + + }//type 0 or 2 + +//V23 + if(type == 0 || type == 3){ + tx3 = cx - dv23->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty3 = cy + yblk - dv23->mvy; + +// if(type == 0) +// assert(tx3 >= 0 && tx3 < hor && ty3 >= 0 && ty3 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu ){ + for(j = (-1)*range;j <= range; j+= accu ){ + if(tx3 - i >= 0 && tx3 - i < hor && ty3 - j >= 0 && ty3 - j < ver && (i!=0 || j!=0) ){ + tv23->mvx = dv23->mvx + i; + tv23->mvy = dv23->mvy + j; + + + if(i == (-1)*range && j == (-1)*range && type == 3 ) + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*dv21,*dv22,*tv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + else + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*dv21,*dv22,*tv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,2); + + get_bit = get_bit_cost(lambda,tv23->mvx,tv23->mvy,v23->mvx,v23->mvy,ct2x,ct2y,subpel); + + if( (get_sad + code_v11 + code_v12 + code_v13 + code_v21 + code_v22 + get_bit) < min_j ){ + min_j = get_sad + code_v11 + code_v12 + code_v13 + code_v21 + code_v22 + get_bit; + code_v23 = get_bit; + best_sad = get_sad; + + get_mvx = tv23->mvx - dv23->mvx; + get_mvy = tv23->mvy - dv23->mvy; + } + } + } + } + dv23->mvx = dv23->mvx + get_mvx; + dv23->mvy = dv23->mvy + get_mvy; + + assert( code_v23 == get_bit_cost(lambda,dv23->mvx,dv23->mvy,v23->mvx,v23->mvy,ct2x,ct2y,subpel) ); + + }//type 0 or 3 + +//////// + k++; + assert(min_j <= min_j_lst); + + if( min_j == min_j_lst ){ + k = max + 1; + break; + }else{ + min_j_lst = min_j; + } + + }//if k < max + + return best_sad; +} + +float delta_v_search_prl(float *frame_cur, float *frame_ref1, float *frame_ref2, float *upframe1, float *upframe2, int ct1x, int ct1y, int ct2x, int ct2y, ModeInfo *v11, + ModeInfo *v12, ModeInfo *v13, ModeInfo *dv11, ModeInfo *dv12, ModeInfo *dv13, ModeInfo *dv21, ModeInfo *dv22, + ModeInfo *dv23, int xblk, int yblk, int cx, int cy, int hor, int ver, int best_mode, int lambda, int subpel, + int t_level, int type){ + // type 0: INTER + // type 2: MERGE UP + // type 3: MERGE INTER + float i,j; + int k = 0; + float tx11,ty11,tx12,ty12,tx13,ty13,tx21,ty21,tx22,ty22,tx23,ty23; + int max; + float get, accu = 0.25, range; + + float min_j, get_sad, code_v11,code_v12,code_v13, code_v21,code_v22,code_v23, get_bit, get_mvx, get_mvy, best_sad; + float min_j_lst; + + if(type == 2 || type == 3){ + max = 3; + range = MRG_RANGE * accu; + }else{ + assert(type == 0); + max = 3; + range = PRL_RANGE * accu; + } + + range = range + t_level * 0.25; + + dv11->mvx = v11->mvx; + dv11->mvy = v11->mvy; + dv12->mvx = v12->mvx; + dv12->mvy = v12->mvy; + dv13->mvx = v13->mvx; + dv13->mvy = v13->mvy; + + dv21->mvx = (-1)*v11->mvx; + dv21->mvy = (-1)*v11->mvy; + dv22->mvx = (-1)*v12->mvx; + dv22->mvy = (-1)*v12->mvy; + dv23->mvx = (-1)*v13->mvx; + dv23->mvy = (-1)*v13->mvy; + + tv11->mvx = v11->mvx; + tv11->mvy = v11->mvy; + tv12->mvx = v12->mvx; + tv12->mvy = v12->mvy; + tv13->mvx = v13->mvx; + tv13->mvy = v13->mvy; + + code_v11 = 0; + code_v12 = 0; + code_v13 = 0; + + min_j = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*dv13,*dv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + best_sad = min_j; + + ////////////// INITIALIZATION ///////////// + if(type == 2){ + code_v12 = get_bit_cost(lambda,dv12->mvx,dv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel); + }else if(type == 3){ + code_v13 = get_bit_cost(lambda,dv13->mvx,dv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel); + }else{ + assert(type == 0); + code_v11 = get_bit_cost(lambda,dv11->mvx,dv11->mvy,v11->mvx,v11->mvy,ct1x,ct1y,subpel); + code_v12 = get_bit_cost(lambda,dv12->mvx,dv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel); + code_v13 = get_bit_cost(lambda,dv13->mvx,dv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel); + } + min_j = min_j + code_v11 + code_v12 + code_v13; + min_j_lst = min_j; + /////////////////////////////////////////////// + + while(k < max){ +//V11 + if(type == 0 || type == 1){ + tx11 = cx - dv11->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty11 = cy - dv11->mvy; + + tx21 = cx - dv21->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty21 = cy - dv21->mvy; + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx11 - i >= 0 && tx11 - i < hor && ty11 - j >= 0 && ty11 - j < ver && + tx21 + i >= 0 && tx21 + i < hor && ty21 + j >= 0 && ty21 + j < ver && (i!=0 || j!=0) ){ + + tv11->mvx = dv11->mvx + i; + tv11->mvy = dv11->mvy + j; + + tv21->mvx = (-1)*tv11->mvx; + tv21->mvy = (-1)*tv11->mvy; + + + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*tv11,*dv12,*dv13,*tv21,*dv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + + get_bit = get_bit_cost(lambda,tv11->mvx,tv11->mvy,v11->mvx,v11->mvy,ct1x,ct1y,subpel); + + if( (get_sad + get_bit + code_v12 + code_v13) < min_j ){ + min_j = get_sad + get_bit + code_v12 + code_v13; + code_v11 = get_bit; + best_sad = get_sad; + + get_mvx = tv11->mvx - dv11->mvx; + get_mvy = tv11->mvy - dv11->mvy; + } + } + } + } + dv11->mvx = dv11->mvx + get_mvx; + dv11->mvy = dv11->mvy + get_mvy; + + dv21->mvx = (-1)*dv11->mvx; + dv21->mvy = (-1)*dv11->mvy; + + assert( code_v11 == get_bit_cost(lambda,dv11->mvx,dv11->mvy,v11->mvx,v11->mvy,ct1x,ct1y,subpel) ); + + }//type 0 or 1 + +//V12 + if(type == 0 || type == 2){ + tx12 = cx + xblk - dv12->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty12 = cy - dv12->mvy; + + tx22 = cx + xblk - dv22->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty22 = cy - dv22->mvy; + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx12 - i >= 0 && tx12 - i < hor && ty12 - j >= 0 && ty12 - j < ver && + tx22 + i >= 0 && tx22 + i < hor && ty22 + j >= 0 && ty22 + j < ver && (i!=0 || j!=0) ){ + + tv12->mvx = dv12->mvx + i; + tv12->mvy = dv12->mvy + j; + + tv22->mvx = (-1)*tv12->mvx; + tv22->mvy = (-1)*tv12->mvy; + + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*tv12,*dv13,*dv21,*tv22,*dv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + + get_bit = get_bit_cost(lambda,tv12->mvx,tv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel); + + if( (get_sad + code_v11 + get_bit + code_v13) < min_j ){ + min_j = get_sad + code_v11 + get_bit + code_v13; + code_v12 = get_bit; + best_sad = get_sad; + + get_mvx = tv12->mvx - dv12->mvx; + get_mvy = tv12->mvy - dv12->mvy; + } + } + } + } + dv12->mvx = dv12->mvx + get_mvx; + dv12->mvy = dv12->mvy + get_mvy; + + dv22->mvx = (-1)*dv12->mvx; + dv22->mvy = (-1)*dv12->mvy; + + assert( code_v12 == get_bit_cost(lambda,dv12->mvx,dv12->mvy,v12->mvx,v12->mvy,ct1x,ct1y,subpel) ); + + }//type 0 or 2 + +//V13 + if(type == 0 || type == 3){ + tx13 = cx - dv13->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty13 = cy + yblk - dv13->mvy; + + tx23 = cx - dv23->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty23 = cy + yblk - dv23->mvy; + +// if(type == 0) +// assert(tx3 >= 0 && tx3 < hor && ty3 >= 0 && ty3 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu ){ + for(j = (-1)*range;j <= range; j+= accu ){ + if(tx13 - i >= 0 && tx13 - i < hor && ty13 - j >= 0 && ty13 - j < ver && + tx23 + i >= 0 && tx23 + i < hor && ty23 + j >= 0 && ty23 + j < ver && (i!=0 || j!=0) ){ + + tv13->mvx = dv13->mvx + i; + tv13->mvy = dv13->mvy + j; + + tv23->mvx = (-1)*tv13->mvx; + tv23->mvy = (-1)*tv13->mvy; + + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv11,*dv12,*tv13,*dv21,*dv22,*tv23,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + + get_bit = get_bit_cost(lambda,tv13->mvx,tv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel); + + if( (get_sad + code_v11 + code_v12 + get_bit) < min_j ){ + min_j = get_sad + code_v11 + code_v12 + get_bit; + code_v13 = get_bit; + best_sad = get_sad; + + get_mvx = tv13->mvx - dv13->mvx; + get_mvy = tv13->mvy - dv13->mvy; + } + } + } + } + dv13->mvx = dv13->mvx + get_mvx; + dv13->mvy = dv13->mvy + get_mvy; + + dv23->mvx = (-1)*dv13->mvx; + dv23->mvy = (-1)*dv13->mvy; + + assert( code_v13 == get_bit_cost(lambda,dv13->mvx,dv13->mvy,v13->mvx,v13->mvy,ct1x,ct1y,subpel) ); + + }//type 0 or 3 + + k++; + assert(min_j <= min_j_lst); + + if( min_j == min_j_lst ){ + k = max + 1; + break; + } + else{ + min_j_lst = min_j; + } + + }//if k < max + + return best_sad; + +} + +float delta_v_search(float *frame_cur, float *frame_ref1, float *frame_ref2, float *upframe1, float *upframe2, int ctx, int cty, ModeInfo *v11, + ModeInfo *v12, ModeInfo *v13, ModeInfo *dv1, ModeInfo *dv2, ModeInfo *dv3, int xblk, + int yblk, int cx, int cy, int hor, int ver, int best_mode, int lambda, int subpel, int t_level, int type){ + // type 0: INTER + // type 2: MERGE UP + // type 3: MERGE INTER + float i,j; + int k = 0; + float tx1,ty1,tx2,ty2,tx3,ty3; + int max; + float get, accu = 0.25, range; + + float min_j, get_sad, code_v1,code_v2,code_v3, get_bit, get_mvx, get_mvy, best_sad; + float min_j_lst; + +// range = range * (t_level + 1); + + if(type == 2 || type == 3){ + max = 3; + range = accu * MRG_RANGE; + }else{ + assert(type == 0); + max = 3; + range = accu * ITR_RANGE; + } + + range = range + t_level * 0.25; + + dv1->mvx = v11->mvx; + dv1->mvy = v11->mvy; + dv2->mvx = v12->mvx; + dv2->mvy = v12->mvy; + dv3->mvx = v13->mvx; + dv3->mvy = v13->mvy; + + tv11->mvx = v11->mvx; + tv11->mvy = v11->mvy; + tv12->mvx = v12->mvx; + tv12->mvy = v12->mvy; + tv13->mvx = v13->mvx; + tv13->mvy = v13->mvy; + + code_v1 = 0; + code_v2 = 0; + code_v3 = 0; + + min_j = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv1,*dv2,*dv3,*dv1,*dv2,*dv3,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + best_sad = min_j; + +// if(type == 0) +// assert(min_j != (float)HUGE_VAL); + + ////////////// INITIALIZATION ///////////// + if(type == 2){ + code_v2 = get_bit_cost(lambda,dv2->mvx,dv2->mvy,v12->mvx,v12->mvy,ctx,cty,subpel); + }else if(type == 3){ + code_v3 = get_bit_cost(lambda,dv3->mvx,dv3->mvy,v13->mvx,v13->mvy,ctx,cty,subpel); + }else{ + assert(type == 0); + code_v1 = get_bit_cost(lambda,dv1->mvx,dv1->mvy,v11->mvx,v11->mvy,ctx,cty,subpel); + code_v2 = get_bit_cost(lambda,dv2->mvx,dv2->mvy,v12->mvx,v12->mvy,ctx,cty,subpel); + code_v3 = get_bit_cost(lambda,dv3->mvx,dv3->mvy,v13->mvx,v13->mvy,ctx,cty,subpel); + } + min_j = min_j + code_v1 + code_v2 + code_v3; + min_j_lst = min_j; + /////////////////////////////////////////////// + + while(k < max){ +//V1 + if(type == 0 || type == 1){ + tx1 = cx - dv1->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty1 = cy - dv1->mvy; + +// if(type == 0) +// assert(tx1 >= 0 && tx1 < hor && ty1 >= 0 && ty1 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx1 - i >= 0 && tx1 - i < hor && ty1 - j >= 0 && ty1 - j < ver && (i!=0 || j!=0) ){ + tv11->mvx = dv1->mvx + i; + tv11->mvy = dv1->mvy + j; + + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*tv11,*dv2,*dv3,*tv11,*dv2,*dv3,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + + get_bit = get_bit_cost(lambda,tv11->mvx,tv11->mvy,v11->mvx,v11->mvy,ctx,cty,subpel); + + if( (get_sad + get_bit + code_v2 + code_v3) < min_j ){ + min_j = get_sad + get_bit + code_v2 + code_v3; + code_v1 = get_bit; + best_sad = get_sad; + + get_mvx = tv11->mvx - dv1->mvx; + get_mvy = tv11->mvy - dv1->mvy; + } + } + } + } + dv1->mvx = dv1->mvx + get_mvx; + dv1->mvy = dv1->mvy + get_mvy; + + assert( code_v1 == get_bit_cost(lambda,dv1->mvx,dv1->mvy,v11->mvx,v11->mvy,ctx,cty,subpel) ); + + }//type 0 or 1 + +//V2 + if(type == 0 || type == 2){ + tx2 = cx + xblk - dv2->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty2 = cy - dv2->mvy; + +// if(type == 0) +// assert(tx2 >= 0 && tx2 < hor && ty2 >= 0 && ty2 < ver); + + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu){ + for(j = (-1)*range;j <= range; j+= accu){ + if(tx2 - i >= 0 && tx2 - i < hor && ty2 - j >= 0 && ty2 - j < ver && (i!=0 || j!=0) ){ + tv12->mvx = dv2->mvx + i; + tv12->mvy = dv2->mvy + j; + + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv1,*tv12,*dv3,*dv1,*tv12,*dv3,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + + get_bit = get_bit_cost(lambda,tv12->mvx,tv12->mvy,v12->mvx,v12->mvy,ctx,cty,subpel); + + if( (get_sad + code_v1 + get_bit + code_v3) < min_j ){ + min_j = get_sad + code_v1 + get_bit + code_v3; + code_v2 = get_bit; + best_sad = get_sad; + + get_mvx = tv12->mvx - dv2->mvx; + get_mvy = tv12->mvy - dv2->mvy; + } + } + } + } + dv2->mvx = dv2->mvx + get_mvx; + dv2->mvy = dv2->mvy + get_mvy; + + assert( code_v2 == get_bit_cost(lambda,dv2->mvx,dv2->mvy,v12->mvx,v12->mvy,ctx,cty,subpel) ); + + }//type 0 or 2 + +//V3 + if(type == 0 || type == 3){ + tx3 = cx - dv3->mvx;//This is employed to confirm that searched pixel position is within the frame boundary + ty3 = cy + yblk - dv3->mvy; + +/* if(type == 0){ + if(!(tx3 >= 0 && tx3 < hor && ty3 >= 0 && ty3 < ver)){ + printf("tx3 = %f, ty3 = %f\n",tx3,ty3); + assert(0); + } + } +*/ + get_mvx = 0; + get_mvy = 0; + + for(i = (-1)*range;i <= range; i += accu ){ + for(j = (-1)*range;j <= range; j+= accu ){ + if(tx3 - i >= 0 && tx3 - i < hor && ty3 - j >= 0 && ty3 - j < ver && (i!=0 || j!=0) ){ + tv13->mvx = dv3->mvx + i; + tv13->mvy = dv3->mvy + j; + + get_sad = find_affine_SAD(frame_cur, frame_ref1, frame_ref2,upframe1,upframe2,*dv1,*dv2,*tv13,*dv1,*dv2,*tv13,xblk,yblk,cx,cy,hor,ver,best_mode,subpel,0); + + get_bit = get_bit_cost(lambda,tv13->mvx,tv13->mvy,v13->mvx,v13->mvy,ctx,cty,subpel); + + if( (get_sad + code_v1 + code_v2 + get_bit) < min_j ){ + min_j = get_sad + code_v1 + code_v2 + get_bit; + code_v3 = get_bit; + best_sad = get_sad; + + get_mvx = tv13->mvx - dv3->mvx; + get_mvy = tv13->mvy - dv3->mvy; + } + } + } + } + dv3->mvx = dv3->mvx + get_mvx; + dv3->mvy = dv3->mvy + get_mvy; + + assert( code_v3 == get_bit_cost(lambda,dv3->mvx,dv3->mvy,v13->mvx,v13->mvy,ctx,cty,subpel) ); + + }//type 0 or 3 + +//////// + k++; + + assert(min_j <= min_j_lst); + + if( min_j == min_j_lst ){ + k = max + 1; + break; + } + else{ + min_j_lst = min_j; + } + + }//if k < max + + return best_sad; +} + +// 决策对于当前块,找到最好的块模式 +void find_best_mode(vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, vector_ptr fmv3_array, vector_ptr fmv4_array, + float *fr_cur, float *fr_ref1, float *fr_ref2, + float *upframe1, float *upframe2, + int x, int y, int xblk, int yblk, int maxx, int maxy, + int hor, int ver, int t_level, videoinfo info, + int ctx1x, int ctx1y, int ctx2x, int ctx2y, + float *pmv1x, float *pmv1y, float *pmv2x, float *pmv2y, int dec) +{ + vector tmv1, tmv2; + float min_cost, mode_coding_cost; + int i,j,k, mode_cnt, best_mode, bst_idx1, bst_idx2,bst_aff_idx, getnum; + int pos1, pos2; + float px1, py1, px2, py2; + ModeInfo *v1, *v2; + +// ModeInfo mrg11,mrg12,mrg13,mrg21,mrg22,mrg23; + + //Added on 02.02.2016 + float min1_total_cost, min1_bit_cost, min1_sad_cost, min2_total_cost, min2_bit_cost, min2_sad_cost; + float bst_mv1x = (float)HUGE_VAL, bst_mv1y = (float)HUGE_VAL,bst_mv2x = (float)HUGE_VAL, bst_mv2y = (float)HUGE_VAL; + float getval, bst_mse,bst_sad,bst_aff_sad; + float mvx_buff, mvy_buff; + + float pre_pmv1x = (float)HUGE_VAL, pre_pmv1y = (float)HUGE_VAL, pre_pmv2x = (float)HUGE_VAL, pre_pmv2y = (float)HUGE_VAL; + int xblk2, yblk2,get_xblk,get_yblk; + + float aff_coef; //added on 11.24.2016 + + float best_trans_sad, two_comp_sad; //added on 11.10.2016 + int best_trans_mode; //added on 11.10.2016 + float best_trans_bit_cost; + ModeInfo trans_mvl, trans_mvr; + float aff_sad_cache; + + vector two_comp_tmv; //added on 11.13.2016 + float *D1, *D2; + int *Dx; + int range = 5; + float get_mvx,get_mvy; + float dis_x,dis_y; + + float t_coef = 1; + + int do_two_comp = 0; + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + + tv11 = new ModeInfo; + tv12 = new ModeInfo; + tv13 = new ModeInfo; + + tv21 = new ModeInfo; + tv22 = new ModeInfo; + tv23 = new ModeInfo; + + vector_ptr mrg_left[4], mrg_right[4]; + + //Added by Yuan Liu on 01.23.2016 + + float get_aff_bit_cost, get_aff_sad_cost, get_aff_total_cost, best_aff_bit_cost, best_aff_sad_cost, best_aff_total_cost; + + float mvx, mvy; + + //Added on 01.18.2016 + float aff_mse,aff_ref_var,aff_var; + int med_cnt1, med_cnt2; + +#ifdef AFFINE_APPLY + //Added by Yuan Liu + int size; + float level; + float *get1x = new float; + float *get1y = new float; + float *get2x = new float; + float *get2y = new float; + float *get3x = new float; + float *get3y = new float; + + float do_affine, do_inter; + float best_sad, bili_sad; + + ModeInfo merg_aff_v1,merg_aff_v2; + ModeInfo merg_aff2_v1,merg_aff2_v2; + ModeInfo get_v1[4],get_v2[4],get_v3[4]; //Save reference information for generating affine MV + ModeInfo get2_v1[4],get2_v2[4],get2_v3[4]; //Save reference information for generating affine MV + + int aff_idx1, aff_idx2; + int pred11 = -1,pred12 = -1,pred13 = -1; + int pred21 = -1,pred22 = -1,pred23 = -1; + int best_idx1, best_idx2; + int count, round, mrg_cnt1, mrg_cnt2; + + float left_dmvx, left_dmvy, right_dmvx, right_dmvy; + + ModeInfo *dv11 = new ModeInfo; + ModeInfo *dv12 = new ModeInfo; + ModeInfo *dv13 = new ModeInfo; + + ModeInfo *dv21 = new ModeInfo; + ModeInfo *dv22 = new ModeInfo; + ModeInfo *dv23 = new ModeInfo; + + int aff_num1,aff_num2; + +#endif + + if(xblk >= 64) + aff_coef = AFF_BLK_COEF_64; + else if(xblk == 32) + aff_coef = AFF_BLK_COEF_32; + else + aff_coef = SMALL_AFF_BLK_COEF; + + /////////////// Added on 01.18.2016 ///////////////// +/* + for(i = 0;i <= 3;i ++){ + fmv1->mrg_mvx[i] = (float)HUGE_VAL; + fmv1->mrg_mvy[i] = (float)HUGE_VAL; + if(fmv2 != NULL){ + fmv2->mrg_mvx[i] = (float)HUGE_VAL; + fmv2->mrg_mvy[i] = (float)HUGE_VAL; + } + } +*/ + + for(i = 0;i <= 3;i ++){ + mrg_left[i] = NULL; + mrg_right[i] = NULL; + } + + med_cnt1 = 0; + for(i=0;i<=3;i++){ + if(pmv1x[i] != (float)HUGE_VAL && pmv1y[i] != (float)HUGE_VAL) + med_cnt1++; + } +// printf("med_cnt1 = %d\n",med_cnt1); + + switch(med_cnt1){ + case 0: + pre_pmv1x = 0.0; + pre_pmv1y = 0.0; + break; + + case 1: + case 2: + assert(pmv1x[3] == (float)HUGE_VAL && pmv1y[3] == (float)HUGE_VAL); + if(pmv1x[0] != (float)HUGE_VAL && pmv1y[0] != (float)HUGE_VAL){ + pre_pmv1x = pmv1x[0]; + pre_pmv1y = pmv1y[0]; + } + else if(pmv1x[1] != (float)HUGE_VAL && pmv1y[1] != (float)HUGE_VAL){ + pre_pmv1x = pmv1x[1]; + pre_pmv1y = pmv1y[1]; + } + else if(pmv1x[2] != (float)HUGE_VAL && pmv1y[2] != (float)HUGE_VAL){ + pre_pmv1x = pmv1x[2]; + pre_pmv1y = pmv1y[2]; + } + break; + + case 3: + assert(pmv1x[3] == (float)HUGE_VAL && pmv1y[3] == (float)HUGE_VAL); + assert(pmv1x[0] != (float)HUGE_VAL && pmv1y[0] != (float)HUGE_VAL + && pmv1x[1] != (float)HUGE_VAL && pmv1y[1] != (float)HUGE_VAL + && pmv1x[2] != (float)HUGE_VAL && pmv1y[2] != (float)HUGE_VAL); + pre_pmv1x = med(pmv1x[0], pmv1x[1], pmv1x[2]); + pre_pmv1y = med(pmv1y[0], pmv1y[1], pmv1y[2]); + break; + + case 4: + assert(pmv1x[3] != (float)HUGE_VAL && pmv1y[3] != (float)HUGE_VAL); + pre_pmv1x = pmv1x[3]; + pre_pmv1y = pmv1y[3]; + break; + + default: + assert(0); + } + + if(fmv2 != NULL){ + + med_cnt2 = 0; + for(i=0;i<=3;i++){ + if(pmv2x[i] != (float)HUGE_VAL && pmv2y[i] != (float)HUGE_VAL) + med_cnt2++; + } + +// printf("med_cnt2 = %d\n",med_cnt1); + + switch(med_cnt2){ + case 0: + pre_pmv2x = 0.0; + pre_pmv2y = 0.0; + break; + + case 1: + case 2: + assert(pmv2x[3] == (float)HUGE_VAL && pmv2y[3] == (float)HUGE_VAL); + if(pmv2x[0] != (float)HUGE_VAL && pmv2y[0] != (float)HUGE_VAL){ + pre_pmv2x = pmv2x[0]; + pre_pmv2y = pmv2y[0]; + } + else if(pmv2x[1] != (float)HUGE_VAL && pmv2y[1] != (float)HUGE_VAL){ + pre_pmv2x = pmv2x[1]; + pre_pmv2y = pmv2y[1]; + } + else if(pmv2x[2] != (float)HUGE_VAL && pmv2y[2] != (float)HUGE_VAL){ + pre_pmv2x = pmv2x[2]; + pre_pmv2y = pmv2y[2]; + } + break; + + case 3: + assert(pmv2x[3] == (float)HUGE_VAL && pmv2y[3] == (float)HUGE_VAL); + assert(pmv2x[0] != (float)HUGE_VAL && pmv2y[0] != (float)HUGE_VAL + && pmv2x[1] != (float)HUGE_VAL && pmv2y[1] != (float)HUGE_VAL + && pmv2x[2] != (float)HUGE_VAL && pmv2y[2] != (float)HUGE_VAL); + pre_pmv2x = med(pmv2x[0], pmv2x[1], pmv2x[2]); + pre_pmv2y = med(pmv2y[0], pmv2y[1], pmv2y[2]); + break; + + case 4: + assert(pmv2x[3] != (float)HUGE_VAL && pmv2y[3] != (float)HUGE_VAL); + pre_pmv2x = pmv2x[3]; + pre_pmv2y = pmv2y[3]; + break; + + default: + assert(0); + } + } + /////////////////////////////////////////////////////// + + /************************************************************************ + **************************** LEFT CONNECTED **************************** + ************************************************************************/ + // mode has not been tested before + assert(fmv1->mode_info[LEFT_CONNECTED].is_valid == NO && + (fmv2 == NULL || fmv2->mode_info[LEFT_CONNECTED].is_valid == NO)); + + min1_sad_cost = (float)HUGE_VAL; + min1_bit_cost = (float)HUGE_VAL; + min1_total_cost = (float)HUGE_VAL; + tmv1.med_idx = -1; + bst_mv1x = (float)HUGE_VAL, bst_mv1y = (float)HUGE_VAL, bst_idx1 = -1; + + + for(i=0;i<=3;i++){ + if(pmv1x[i] != (float)HUGE_VAL && pmv1y[i] != (float)HUGE_VAL ){ + // MV search + full_search_fast(&tmv1.mvx, &tmv1.mvy, fr_cur, fr_ref1, NULL, + upframe1, NULL, + 0., 0., x, y, xblk, yblk, maxx, maxy, hor, ver, + info.subpel[t_level], info.lambda[t_level], + pmv1x[i], pmv1y[i], ctx1x, ctx1y, + &tmv1.sad_cost, &tmv1.bit_cost, &tmv1.total_cost, NO); // add parallel mode. mwi + + tmv1.med_idx = i; + + if(min1_total_cost > tmv1.total_cost){ + min1_total_cost = tmv1.total_cost; + min1_bit_cost = tmv1.bit_cost; + min1_sad_cost = tmv1.sad_cost; + bst_idx1 = tmv1.med_idx; + bst_mv1x = tmv1.mvx; + bst_mv1y = tmv1.mvy; + } + } + } + + if(min1_total_cost != (float)HUGE_VAL){ + assert(bst_idx1 >= 0 && bst_idx1 <= 3); + assert(tmv1.med_idx >= 0 && bst_mv1x!= (float)HUGE_VAL && bst_mv1y!= (float)HUGE_VAL); + tmv1.mvx = bst_mv1x; + tmv1.mvy = bst_mv1y; + tmv1.total_cost = min1_total_cost; + tmv1.bit_cost = min1_bit_cost; + tmv1.sad_cost = min1_sad_cost; + tmv1.med_idx = bst_idx1; + } + + if(med_cnt1 == 0){ + assert(tmv1.med_idx == -1 && bst_mv1x == (float)HUGE_VAL && bst_mv1y == (float)HUGE_VAL); + // MV search + full_search_fast(&tmv1.mvx, &tmv1.mvy, fr_cur, fr_ref1, NULL, + upframe1, NULL, + 0., 0., x, y, xblk, yblk, maxx, maxy, hor, ver, + info.subpel[t_level], info.lambda[t_level], + 0, 0, ctx1x, ctx1y, + &tmv1.sad_cost, &tmv1.bit_cost, &tmv1.total_cost, NO); // add parallel mode. mwi + assert(tmv1.total_cost < min1_total_cost); + } + // check for validity + find_MSE(&tmv1, NULL, fr_cur, fr_ref1, NULL, x, y, xblk, yblk, hor, ver, + t_level); + + for(i=0;i<=3;i++){ + if(pmv1x[i] != (float)HUGE_VAL && pmv1y[i] != (float)HUGE_VAL){ + getval = get_bit_cost(info.lambda[t_level], tmv1.mvx,tmv1.mvy,pmv1x[i],pmv1y[i], ctx1x, ctx1y, info.subpel[t_level]); + if(getval < tmv1.bit_cost){ + tmv1.med_idx = i; + tmv1.bit_cost = getval; + tmv1.total_cost = tmv1.bit_cost + tmv1.sad_cost; + } + } + } + + if (tmv1.lifting_mode == CONNECTED) { + + v1 = &fmv1->mode_info[LEFT_CONNECTED]; + v1->is_valid = YES; + v1->is_predictor = YES; + v1->mvx = tmv1.mvx; + v1->mvy = tmv1.mvy; + v1->sad_cost = tmv1.sad_cost; + v1->mse = tmv1.mse; + v1->bit_cost = tmv1.bit_cost; + v1->total_cost = tmv1.total_cost; + v1->med_idx = tmv1.med_idx; + + if (fmv2 != NULL) { + v2 = &fmv2->mode_info[LEFT_CONNECTED]; + v2->is_valid = YES; + v2->is_predictor = NO; + v2->sad_cost = v1->sad_cost; + v2->mse = v1->mse; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + } + } + + /************************************************************************ + **************************** LEFT PREDICTED **************************** + ************************************************************************/ + + // mode has not been tested before + assert(fmv1->mode_info[LEFT_PREDICTED].is_valid == NO && + (fmv2 == NULL || fmv2->mode_info[LEFT_PREDICTED].is_valid == NO)); + + v1 = &fmv1->mode_info[LEFT_PREDICTED]; + v1->is_valid = YES; + v1->is_predictor = YES; + v1->mvx = tmv1.mvx; + v1->mvy = tmv1.mvy; + v1->sad_cost = tmv1.sad_cost; + v1->mse = tmv1.mse; + v1->bit_cost = tmv1.bit_cost; + v1->total_cost = tmv1.total_cost; + v1->med_idx = tmv1.med_idx; + + if (fmv2 != NULL) { + v2 = &fmv2->mode_info[LEFT_PREDICTED]; + v2->is_valid = YES; + v2->is_predictor = NO; + v2->sad_cost = v1->sad_cost; + v2->mse = tmv1.mse; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + } + + // the following modes are possible in bi-directional case (2 MVFs) only + if (fmv2 != NULL) { + + /************************************************************************ + **************************** RIGHT CONNECTED *************************** + ************************************************************************/ + + // mode has not been tested before + assert(fmv1->mode_info[RIGHT_CONNECTED].is_valid == NO && + fmv2->mode_info[RIGHT_CONNECTED].is_valid == NO); + + min2_sad_cost = (float)HUGE_VAL; + min2_bit_cost = (float)HUGE_VAL; + min2_total_cost = (float)HUGE_VAL; + tmv2.med_idx = -1; + bst_mv2x = (float)HUGE_VAL, bst_mv2y = (float)HUGE_VAL, bst_idx2 = -1; + + for(i=0;i<=3;i++){ + if(pmv2x[i] != (float)HUGE_VAL && pmv2y[i] != (float)HUGE_VAL ){ + // MV search + full_search_fast(&tmv2.mvx, &tmv2.mvy, fr_cur, fr_ref2, NULL, + upframe2, NULL, + 0., 0., x, y, xblk, yblk, maxx, maxy, hor, ver, + info.subpel[t_level], info.lambda[t_level], + pmv2x[i], pmv2y[i], ctx2x, ctx2y, + &tmv2.sad_cost, &tmv2.bit_cost, &tmv2.total_cost, NO); // add parallel mode. mwi + + tmv2.med_idx = i; + + if(min2_total_cost > tmv2.total_cost){ + min2_total_cost = tmv2.total_cost; + min2_bit_cost = tmv2.bit_cost; + min2_sad_cost = tmv2.sad_cost; + bst_idx2 = tmv2.med_idx; + bst_mv2x = tmv2.mvx; + bst_mv2y = tmv2.mvy; + } + } + } + + if(min2_total_cost != (float)HUGE_VAL){ + assert(bst_idx2 >= 0 && bst_idx2 <= 3); + assert(tmv2.med_idx >= 0 && bst_mv2x!= (float)HUGE_VAL && bst_mv2y!= (float)HUGE_VAL); + tmv2.mvx = bst_mv2x; + tmv2.mvy = bst_mv2y; + tmv2.total_cost = min2_total_cost; + tmv2.bit_cost = min2_bit_cost; + tmv2.sad_cost = min2_sad_cost; + tmv2.med_idx = bst_idx2; + } + + if(med_cnt2 == 0){ + assert(tmv2.med_idx == -1 && bst_mv2x == (float)HUGE_VAL && bst_mv2y == (float)HUGE_VAL); + // MV search + full_search_fast(&tmv2.mvx, &tmv2.mvy, fr_cur, fr_ref2, NULL, + upframe2, NULL, + 0., 0., x, y, xblk, yblk, maxx, maxy, hor, ver, + info.subpel[t_level], info.lambda[t_level], + 0, 0, ctx2x, ctx2y, + &tmv2.sad_cost, &tmv2.bit_cost, &tmv2.total_cost, NO); // add parallel mode. mwi + assert(tmv2.total_cost < min2_total_cost); + } + + // check for validity + find_MSE(&tmv2, NULL, fr_cur, fr_ref2, NULL, x, y, xblk, yblk, hor, ver, + t_level); + + for(i=0;i<=3;i++){ + if(pmv2x[i] != (float)HUGE_VAL && pmv2y[i] != (float)HUGE_VAL){ + getval = get_bit_cost(info.lambda[t_level], tmv2.mvx,tmv2.mvy,pmv2x[i],pmv2y[i], ctx2x, ctx2y, info.subpel[t_level]); + if(getval < tmv2.bit_cost){ + tmv2.med_idx = i; + tmv2.bit_cost = getval; + tmv2.total_cost = tmv2.bit_cost + tmv2.sad_cost; + } + } + } + + if (tmv2.lifting_mode == CONNECTED) { + + v2 = &fmv2->mode_info[RIGHT_CONNECTED]; + v2->is_valid = YES; + v2->is_predictor = YES; + v2->mvx = tmv2.mvx; + v2->mvy = tmv2.mvy; + v2->sad_cost = tmv2.sad_cost; + v2->mse = tmv2.mse; + v2->bit_cost = tmv2.bit_cost; + v2->total_cost = tmv2.total_cost; + v2->med_idx = tmv2.med_idx; + + v1 = &fmv1->mode_info[RIGHT_CONNECTED]; + v1->is_valid = YES; + v1->is_predictor = NO; + v1->sad_cost = v2->sad_cost; + v1->mse = tmv2.mse; + v1->bit_cost = v2->bit_cost; + v1->total_cost = v2->total_cost; + } + + + /************************************************************************ + *************************** RIGHT PREDICTED **************************** + ************************************************************************/ + + // mode has not been tested before + assert(fmv1->mode_info[RIGHT_PREDICTED].is_valid == NO && + fmv2->mode_info[RIGHT_PREDICTED].is_valid == NO); + + v2 = &fmv2->mode_info[RIGHT_PREDICTED]; + v2->is_valid = YES; + v2->is_predictor = YES; + v2->mvx = tmv2.mvx; + v2->mvy = tmv2.mvy; + v2->sad_cost = tmv2.sad_cost; + v2->mse = tmv2.mse; + v2->bit_cost = tmv2.bit_cost; + v2->total_cost = tmv2.total_cost; + v2->med_idx = tmv2.med_idx; + + v1 = &fmv1->mode_info[RIGHT_PREDICTED]; + v1->is_valid = YES; + v1->is_predictor = NO; + v1->sad_cost = v2->sad_cost; + v1->mse = tmv2.mse; + v1->bit_cost = v2->bit_cost; + v1->total_cost = v2->total_cost; + + + /************************************************************************ + ****************************** BI CONNECTED **************************** + ************************************************************************/ + + // mode has not been tested before + assert(fmv1->mode_info[BI_CONNECTED].is_valid == NO && + fmv2->mode_info[BI_CONNECTED].is_valid == NO); + + // left vector has already been estimated, so start with right side +/* + min2_sad_cost = (float)HUGE_VAL; + min2_bit_cost = (float)HUGE_VAL; + min2_total_cost = (float)HUGE_VAL; + tmv2.med_idx = -1; + bst_mv2x = (float)HUGE_VAL, bst_mv2y = (float)HUGE_VAL; +*/ + + assert(tmv1.mvx != (float)HUGE_VAL && tmv1.mvy != (float)HUGE_VAL && tmv2.mvx != (float)HUGE_VAL && tmv2.mvy != (float)HUGE_VAL); + + for(k=0;k<=3;k++){ + if(pmv2x[k] != (float)HUGE_VAL && pmv2y[k] != (float)HUGE_VAL ){ + // MV search + full_search_fast(&tmv2.mvx, &tmv2.mvy, fr_cur, fr_ref2, fr_ref1, + upframe2, upframe1, + tmv1.mvx, tmv1.mvy, x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + pmv2x[k], pmv2y[k], ctx2x, ctx2y, + &tmv2.sad_cost, &tmv2.bit_cost, &tmv2.total_cost, NO); // add parallel mode. mwi + if(min2_total_cost > tmv2.total_cost){ + min2_total_cost = tmv2.total_cost; + min2_bit_cost = tmv2.bit_cost; + min2_sad_cost = tmv2.sad_cost; + tmv2.med_idx = k; + bst_mv2x = tmv2.mvx; + bst_mv2y = tmv2.mvy; + } + } + } + + if(min2_total_cost != (float)HUGE_VAL){ + assert(tmv2.med_idx >= 0 && bst_mv2x!= (float)HUGE_VAL && bst_mv2y!= (float)HUGE_VAL); + tmv2.mvx = bst_mv2x; + tmv2.mvy = bst_mv2y; + tmv2.total_cost = min2_total_cost; + tmv2.bit_cost = min2_bit_cost; + tmv2.sad_cost = min2_sad_cost; + } + + if(med_cnt2 == 0){ + assert(tmv2.med_idx == -1 && bst_mv2x == (float)HUGE_VAL && bst_mv2y == (float)HUGE_VAL); + // MV search + full_search_fast(&tmv2.mvx, &tmv2.mvy, fr_cur, fr_ref2, fr_ref1, + upframe2, upframe1, + tmv1.mvx, tmv1.mvy, x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + 0, 0, ctx2x, ctx2y, + &tmv2.sad_cost, &tmv2.bit_cost, &tmv2.total_cost, NO); // add parallel mode. mwi + assert(tmv2.total_cost < min2_total_cost); + } + + for (i = 1; i < BIME_ITERATIONS + 1; i++) { + + if (i % 2) { + +// re-estimate left vector +/* min1_sad_cost = (float)HUGE_VAL; + min1_bit_cost = (float)HUGE_VAL; + min1_total_cost = (float)HUGE_VAL; + tmv1.med_idx = -1; + bst_mv1x = (float)HUGE_VAL, bst_mv1y = (float)HUGE_VAL; +*/ + + for(k=0;k<=3;k++){ + if(pmv1x[k] != (float)HUGE_VAL && pmv1y[k] != (float)HUGE_VAL ){ + // MV search + full_search_fast(&tmv1.mvx, &tmv1.mvy, fr_cur, fr_ref1, fr_ref2, + upframe1, upframe2, + tmv2.mvx, tmv2.mvy, x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + pmv1x[k], pmv1y[k], ctx1x, ctx1y, + &tmv1.sad_cost, &tmv1.bit_cost, &tmv1.total_cost, NO); // add parallel mode. mwi + if(min1_total_cost > tmv1.total_cost){ + min1_total_cost = tmv1.total_cost; + min1_bit_cost = tmv1.bit_cost; + min1_sad_cost = tmv1.sad_cost; + tmv1.med_idx = k; + bst_mv1x = tmv1.mvx; + bst_mv1y = tmv1.mvy; + } + } + } + + if(min1_total_cost != (float)HUGE_VAL){ + assert(tmv1.med_idx >= 0 && bst_mv1x!= (float)HUGE_VAL && bst_mv1y!= (float)HUGE_VAL); + tmv1.mvx = bst_mv1x; + tmv1.mvy = bst_mv1y; + tmv1.total_cost = min1_total_cost; + tmv1.bit_cost = min1_bit_cost; + tmv1.sad_cost = min1_sad_cost; + } + + if(med_cnt1 == 0){ + assert(tmv1.med_idx == -1 && bst_mv1x == (float)HUGE_VAL && bst_mv1y == (float)HUGE_VAL); + // MV search + full_search_fast(&tmv1.mvx, &tmv1.mvy, fr_cur, fr_ref1, fr_ref2, + upframe1, upframe2, + tmv2.mvx, tmv2.mvy, x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + 0, 0, ctx1x, ctx1y, + &tmv1.sad_cost, &tmv1.bit_cost, &tmv1.total_cost, NO);// add parallel mode. mwi + assert(tmv1.total_cost < min1_total_cost); + } + } else { + +// re-estimate right vector +/* min2_sad_cost = (float)HUGE_VAL; + min2_bit_cost = (float)HUGE_VAL; + min2_total_cost = (float)HUGE_VAL; + tmv2.med_idx = -1; + bst_mv2x = (float)HUGE_VAL, bst_mv2y = (float)HUGE_VAL; +*/ + + for(k=0;k<=3;k++){ + if(pmv2x[k] != (float)HUGE_VAL && pmv2y[k] != (float)HUGE_VAL ){ + // MV search + full_search_fast(&tmv2.mvx, &tmv2.mvy, fr_cur, fr_ref2, fr_ref1, + upframe2, upframe1, + tmv1.mvx, tmv1.mvy, x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + pmv2x[k], pmv2y[k], ctx2x, ctx2y, + &tmv2.sad_cost, &tmv2.bit_cost, &tmv2.total_cost, NO); // add parallel mode. mwi + if(min2_total_cost > tmv2.total_cost){ + min2_total_cost = tmv2.total_cost; + min2_bit_cost = tmv2.bit_cost; + min2_sad_cost = tmv2.sad_cost; + tmv2.med_idx = k; + bst_mv2x = tmv2.mvx; + bst_mv2y = tmv2.mvy; + } + } + } + + if(min2_total_cost != (float)HUGE_VAL){ + assert(tmv2.med_idx >= 0 && bst_mv2x!= (float)HUGE_VAL && bst_mv2y!= (float)HUGE_VAL); + tmv2.mvx = bst_mv2x; + tmv2.mvy = bst_mv2y; + tmv2.total_cost = min2_total_cost; + tmv2.bit_cost = min2_bit_cost; + tmv2.sad_cost = min2_sad_cost; + } + + if(med_cnt2 == 0){ + assert(tmv2.med_idx == -1 && bst_mv2x == (float)HUGE_VAL && bst_mv2y == (float)HUGE_VAL); + // MV search + full_search_fast(&tmv2.mvx, &tmv2.mvy, fr_cur, fr_ref2, fr_ref1, + upframe2, upframe1, + tmv1.mvx, tmv1.mvy, x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + 0, 0, ctx2x, ctx2y, + &tmv2.sad_cost, &tmv2.bit_cost, &tmv2.total_cost, NO); // add parallel mode. mwi + assert(tmv2.total_cost < min2_total_cost); + } + } + } + + // check for validity + find_MSE(&tmv1, &tmv2, fr_cur, fr_ref1, fr_ref2, x, y, xblk, yblk, + hor, ver, t_level); + + ///////////// Added on 02.06.2016 ///////////////////////// + for(i=0;i<=3;i++){ + if(pmv1x[i] != (float)HUGE_VAL && pmv1y[i] != (float)HUGE_VAL){ + getval = get_bit_cost(info.lambda[t_level], tmv1.mvx,tmv1.mvy,pmv1x[i],pmv1y[i], ctx1x, ctx1y, info.subpel[t_level]); + if(getval < tmv1.bit_cost){ + tmv1.med_idx = i; + tmv1.bit_cost = getval; + tmv1.total_cost = tmv1.bit_cost + tmv1.sad_cost; + } + } + } + + for(i=0;i<=3;i++){ + if(pmv2x[i] != (float)HUGE_VAL && pmv2y[i] != (float)HUGE_VAL){ + getval = get_bit_cost(info.lambda[t_level], tmv2.mvx,tmv2.mvy,pmv2x[i],pmv2y[i], ctx2x, ctx2y, info.subpel[t_level]); + if(getval < tmv2.bit_cost){ + tmv2.med_idx = i; + tmv2.bit_cost = getval; + tmv2.total_cost = tmv2.bit_cost + tmv2.sad_cost; + } + } + } + + assert(tmv1.lifting_mode == tmv2.lifting_mode); + if (tmv1.lifting_mode == CONNECTED) { + + v1 = &fmv1->mode_info[BI_CONNECTED]; + v1->is_valid = YES; + v1->is_predictor = YES; + v1->mvx = tmv1.mvx; + v1->mvy = tmv1.mvy; + v1->sad_cost = tmv2.sad_cost; // right ME was last => get right side SAD + v1->mse = tmv1.mse; + v1->bit_cost = tmv1.bit_cost + tmv2.bit_cost; + v1->total_cost = v1->sad_cost + v1->bit_cost; + v1->med_idx = tmv1.med_idx; + + v2 = &fmv2->mode_info[BI_CONNECTED]; + v2->is_valid = YES; + v2->is_predictor = YES; + v2->mvx = tmv2.mvx; + v2->mvy = tmv2.mvy; + v2->sad_cost = v1->sad_cost; + v2->mse = tmv1.mse; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + v2->med_idx = tmv2.med_idx; + } + + + /************************************************************************ + ****************************** BI PREDICTED **************************** + ************************************************************************/ + + v1 = &fmv1->mode_info[BI_PREDICTED]; + v1->is_valid = YES; + v1->is_predictor = YES; + v1->mvx = tmv1.mvx; + v1->mvy = tmv1.mvy; + v1->sad_cost = tmv2.sad_cost; // right ME was last => get right side SAD + v1->mse = tmv1.mse; + v1->bit_cost = tmv1.bit_cost + tmv2.bit_cost; + v1->total_cost = v1->sad_cost + v1->bit_cost; + v1->med_idx = tmv1.med_idx; + + v2 = &fmv2->mode_info[BI_PREDICTED]; + v2->is_valid = YES; + v2->is_predictor = YES; + v2->mvx = tmv2.mvx; + v2->mvy = tmv2.mvy; + v2->sad_cost = v1->sad_cost; + v2->mse = tmv1.mse; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + v2->med_idx = tmv2.med_idx; + + /************************************************************************ + ******************************* PARALLEL ******************************* + ************************************************************************/ + + // mode has not been tested before + assert(fmv1->mode_info[PARALLEL].is_valid == NO && + fmv2->mode_info[PARALLEL].is_valid == NO); + + // MV search + min1_sad_cost = (float)HUGE_VAL; + min1_bit_cost = (float)HUGE_VAL; + min1_total_cost = (float)HUGE_VAL; + tmv1.med_idx = -1; + bst_mv1x = (float)HUGE_VAL, bst_mv1y = (float)HUGE_VAL; + + + for(i=0;i<=3;i++){ + if(pmv1x[i] != (float)HUGE_VAL && pmv1y[i] != (float)HUGE_VAL ){ + // MV search + full_search_fast(&tmv1.mvx, &tmv1.mvy, fr_cur, fr_ref1, fr_ref2, + upframe1, upframe2, + 0., 0., x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + pmv1x[i], pmv1y[i], ctx1x, ctx1y, + &tmv1.sad_cost, &tmv1.bit_cost, &tmv1.total_cost, YES); // add parallel mode. mwi + if(min1_total_cost > tmv1.total_cost){ + min1_total_cost = tmv1.total_cost; + min1_bit_cost = tmv1.bit_cost; + min1_sad_cost = tmv1.sad_cost; + tmv1.med_idx = i; + bst_mv1x = tmv1.mvx; + bst_mv1y = tmv1.mvy; + } + } + } + + if(min1_total_cost != (float)HUGE_VAL){ + assert(tmv1.med_idx >= 0 && bst_mv1x!= (float)HUGE_VAL && bst_mv1y!= (float)HUGE_VAL); + tmv1.mvx = bst_mv1x; + tmv1.mvy = bst_mv1y; + tmv1.total_cost = min1_total_cost; + tmv1.bit_cost = min1_bit_cost; + tmv1.sad_cost = min1_sad_cost; + } + + if(med_cnt1 == 0){ + assert(tmv1.med_idx == -1 && bst_mv1x == (float)HUGE_VAL && bst_mv1y == (float)HUGE_VAL); + // MV search + full_search_fast(&tmv1.mvx, &tmv1.mvy, fr_cur, fr_ref1, fr_ref2, + upframe1, upframe2, + 0., 0., x, y, xblk, yblk, maxx, maxy, + hor, ver, info.subpel[t_level], info.lambda[t_level], + 0, 0, ctx1x, ctx1y, + &tmv1.sad_cost, &tmv1.bit_cost, &tmv1.total_cost, YES);// add parallel mode. mwi + assert(tmv1.total_cost < min1_total_cost); + } + + // parallel mode: backward mv = -forward mv + tmv2.mvx = -tmv1.mvx; + tmv2.mvy = -tmv1.mvy; + + // check for validity + find_MSE(&tmv1, &tmv2, fr_cur, fr_ref1, fr_ref2, x, y, xblk, yblk, + hor, ver, t_level); + + for(i=0;i<=3;i++){ + if(pmv1x[i] != (float)HUGE_VAL && pmv1y[i] != (float)HUGE_VAL){ + getval = get_bit_cost(info.lambda[t_level], tmv1.mvx,tmv1.mvy,pmv1x[i],pmv1y[i], ctx1x, ctx1y, info.subpel[t_level]); + if(getval < tmv1.bit_cost){ + tmv1.med_idx = i; + tmv1.bit_cost = getval; + tmv1.total_cost = tmv1.bit_cost + tmv1.sad_cost; + } + } + } + + assert(tmv1.lifting_mode == tmv2.lifting_mode); + if (tmv1.lifting_mode == CONNECTED) { + + v1 = &fmv1->mode_info[PARALLEL]; + v1->is_valid = YES; + v1->is_predictor = YES; + v1->mvx = tmv1.mvx; + v1->mvy = tmv1.mvy; + v1->sad_cost = tmv1.sad_cost; + v1->mse = tmv1.mse; + v1->bit_cost = tmv1.bit_cost; + v1->total_cost = tmv1.total_cost; + v1->med_idx = tmv1.med_idx; + + v2 = &fmv2->mode_info[PARALLEL]; + v2->is_valid = YES; + v2->is_predictor = YES; + v2->mvx = tmv2.mvx; + v2->mvy = tmv2.mvy; + v2->sad_cost = v1->sad_cost; + v2->mse = tmv1.mse; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + } + ////////////////////////////////// + + } // end of: the following modes are possible in bi-directional case (2 MVFs) only + + /************************************************************************ + **************************** BLOCK MERGING **************************** + ************************************************************************/ + + assert( (x >= 0) && (x <= (hor - xblk2)) && (y >= 0) && (y <= (ver - yblk2)) ); + + aff_var = variance(fr_cur + y * hor + x, xblk2, yblk2, hor); + +// mode has not been tested before +// assert(fmv1->mode_info[BLOCK_MERGING].is_valid == NO && +// (fmv2 == NULL || fmv2->mode_info[BLOCK_MERGING].is_valid == NO)); + +// no MV search +// spatial mode is bidirectional: mv = pmv + + for(i=0;i<=3;i++){ + mrg_left[i] = new vector; + mrg_right[i] = new vector; + + clean_mrg_mv(mrg_left[i]); + clean_mrg_mv(mrg_right[i]); + } + + get_merge_mv_info(fmv1_array,fmv2_array,fmv3_array,fmv4_array,mrg_left,mrg_right,x,y, hor, ver, xblk2,yblk2,info,t_level); + + for(i=0;i<=3;i++){ + if(mrg_left[i] != NULL){ + if( mrg_left[i]->mvx != (float)HUGE_VAL ){ + assert(mrg_left[i]->mvy != (float)HUGE_VAL); + assert( (float(x)-mrg_left[i]->mvx >= 0) && (float(x)-mrg_left[i]->mvx<= (hor - xblk2)) + && (float(y)-mrg_left[i]->mvy >= 0) && (float(y)-mrg_left[i]->mvy <= (ver - yblk2)) ); + } +/* + fmv1->mrg_mvx[i] = mrg_left[i]->mvx; + fmv1->mrg_mvy[i] = mrg_left[i]->mvy; + + fmv1->mrg_aff_mvx1[i] = mrg_left[i]->aff1_mvx; + fmv1->mrg_aff_mvy1[i] = mrg_left[i]->aff1_mvy; + fmv1->mrg_aff_mvx2[i] = mrg_left[i]->aff2_mvx; + fmv1->mrg_aff_mvy2[i] = mrg_left[i]->aff2_mvy; + fmv1->mrg_aff_mvx3[i] = mrg_left[i]->aff3_mvx; + fmv1->mrg_aff_mvy3[i] = mrg_left[i]->aff3_mvy; +*/ + } + + if(mrg_right[i] != NULL){ + if( mrg_right[i]->mvx != (float)HUGE_VAL ){ + assert(mrg_right[i]->mvy != (float)HUGE_VAL); + assert( (float(x)-mrg_right[i]->mvx >= 0) && (float(x)-mrg_right[i]->mvx<= (hor - xblk2)) + && (float(y)-mrg_right[i]->mvy >= 0) && (float(y)-mrg_right[i]->mvy <= (ver - yblk2)) ); + } + if(fmv2 != NULL){ +/* + fmv2->mrg_mvx[i] = mrg_right[i]->mvx; + fmv2->mrg_mvy[i] = mrg_right[i]->mvy; + + fmv2->mrg_aff_mvx1[i] = mrg_right[i]->aff1_mvx; + fmv2->mrg_aff_mvy1[i] = mrg_right[i]->aff1_mvy; + fmv2->mrg_aff_mvx2[i] = mrg_right[i]->aff2_mvx; + fmv2->mrg_aff_mvy2[i] = mrg_right[i]->aff2_mvy; + fmv2->mrg_aff_mvx3[i] = mrg_right[i]->aff3_mvx; + fmv2->mrg_aff_mvy3[i] = mrg_right[i]->aff3_mvy; +*/ + } + } + } + +////////////// BLK MRG //////////////////// + bst_sad = (float)HUGE_VAL; + bst_mse = (float)HUGE_VAL; + bst_aff_sad = (float)HUGE_VAL; + + bst_idx1 = -1; + tmv1.med_idx = -1; + tmv2.med_idx = -1; + tmv1.aff_mrg = NO; + tmv2.aff_mrg = NO; + + tmv1.mvx = (float)HUGE_VAL; + tmv1.mvy = (float)HUGE_VAL; + tmv2.mvx = (float)HUGE_VAL; + tmv2.mvy = (float)HUGE_VAL; + + tmv1.aff1_mvx = (float)HUGE_VAL;tmv1.aff1_mvy = (float)HUGE_VAL; + tmv1.aff2_mvx = (float)HUGE_VAL;tmv1.aff2_mvy = (float)HUGE_VAL; + tmv1.aff3_mvx = (float)HUGE_VAL;tmv1.aff3_mvy = (float)HUGE_VAL; + tmv2.aff1_mvx = (float)HUGE_VAL;tmv2.aff1_mvy = (float)HUGE_VAL; + tmv2.aff2_mvx = (float)HUGE_VAL;tmv2.aff2_mvy = (float)HUGE_VAL; + tmv2.aff3_mvx = (float)HUGE_VAL;tmv2.aff3_mvy = (float)HUGE_VAL; + + for( i = 0; i <= 3; i++ ){ + + getval = (float)HUGE_VAL; + + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL)){ + tmv1.mvx = mrg_left[i]->mvx; + tmv1.mvy = mrg_left[i]->mvy; + tmv2.mvx = mrg_right[i]->mvx; + tmv2.mvy = mrg_right[i]->mvy; + + tmv1.aff1_mvx = mrg_left[i]->aff1_mvx;tmv1.aff1_mvy = mrg_left[i]->aff1_mvy; + tmv1.aff2_mvx = mrg_left[i]->aff2_mvx;tmv1.aff2_mvy = mrg_left[i]->aff2_mvy; + tmv1.aff3_mvx = mrg_left[i]->aff3_mvx;tmv1.aff3_mvy = mrg_left[i]->aff3_mvy; + tmv2.aff1_mvx = mrg_right[i]->aff1_mvx;tmv2.aff1_mvy = mrg_right[i]->aff1_mvy; + tmv2.aff2_mvx = mrg_right[i]->aff2_mvx;tmv2.aff2_mvy = mrg_right[i]->aff2_mvy; + tmv2.aff3_mvx = mrg_right[i]->aff3_mvx;tmv2.aff3_mvy = mrg_right[i]->aff3_mvy; + + if( (tmv1.mvx != (float)HUGE_VAL && tmv1.mvy != (float)HUGE_VAL && tmv2.mvx != (float)HUGE_VAL && tmv2.mvy != (float)HUGE_VAL) ){ + tmv1.sad_cost = Subpel_MCP_Error4(fr_cur, x, y, xblk, yblk, + fr_ref1, upframe1, tmv1.mvx, tmv1.mvy, + fr_ref2, upframe2, tmv2.mvx, tmv2.mvy, + hor, ver, info.subpel[t_level]); + tmv2.sad_cost = tmv1.sad_cost; + }else if( tmv1.mvx != (float)HUGE_VAL && tmv1.mvx != (float)HUGE_VAL ){ + tmv1.sad_cost = Subpel_MCP_Error4(fr_cur, x, y, xblk, yblk, + fr_ref1, upframe1, tmv1.mvx, tmv1.mvy, + NULL, NULL, tmv2.mvx, tmv2.mvy, + hor, ver, info.subpel[t_level]); + + tmv2.sad_cost = tmv1.sad_cost; + }else if( tmv2.mvx != (float)HUGE_VAL && tmv2.mvx != (float)HUGE_VAL ){ + tmv2.sad_cost = Subpel_MCP_Error4(fr_cur, x, y, xblk, yblk, + fr_ref2, upframe2, tmv2.mvx, tmv2.mvy, + NULL, NULL, tmv1.mvx, tmv1.mvx, + hor, ver, info.subpel[t_level]); + + tmv1.sad_cost = tmv2.sad_cost; + }else + assert(0); + + getval = (float)HUGE_VAL; + +// if(fmv2 != NULL){ + if( (mrg_left[i]->aff1_mvx != (float)HUGE_VAL && mrg_left[i]->aff1_mvy != (float)HUGE_VAL && mrg_left[i]->aff2_mvx != (float)HUGE_VAL && + mrg_left[i]->aff2_mvy != (float)HUGE_VAL && mrg_left[i]->aff3_mvx != (float)HUGE_VAL && mrg_left[i]->aff3_mvy != (float)HUGE_VAL) && + (mrg_right[i]->aff1_mvx != (float)HUGE_VAL && mrg_right[i]->aff1_mvy != (float)HUGE_VAL && mrg_right[i]->aff2_mvx != (float)HUGE_VAL && + mrg_right[i]->aff2_mvy != (float)HUGE_VAL && mrg_right[i]->aff3_mvx != (float)HUGE_VAL && mrg_right[i]->aff3_mvy != (float)HUGE_VAL) ){ + tv11->mvx = mrg_left[i]->aff1_mvx; + tv11->mvy = mrg_left[i]->aff1_mvy; + tv12->mvx = mrg_left[i]->aff2_mvx; + tv12->mvy = mrg_left[i]->aff2_mvy; + tv13->mvx = mrg_left[i]->aff3_mvx; + tv13->mvy = mrg_left[i]->aff3_mvy; + + tv21->mvx = mrg_right[i]->aff1_mvx; + tv21->mvy = mrg_right[i]->aff1_mvy; + tv22->mvx = mrg_right[i]->aff2_mvx; + tv22->mvy = mrg_right[i]->aff2_mvy; + tv23->mvx = mrg_right[i]->aff3_mvx; + tv23->mvy = mrg_right[i]->aff3_mvy; + + getval = find_affine_SAD(fr_cur,fr_ref1,fr_ref2,upframe1,upframe2,*tv11,*tv12,*tv13,*tv21,*tv22,*tv23,xblk2,yblk2,x,y, + hor,ver,BI_CONNECTED_AFF,info.subpel[t_level],3); + + }else if(mrg_left[i]->aff1_mvx != (float)HUGE_VAL && mrg_left[i]->aff1_mvy != (float)HUGE_VAL && mrg_left[i]->aff2_mvx != (float)HUGE_VAL && + mrg_left[i]->aff2_mvy != (float)HUGE_VAL && mrg_left[i]->aff3_mvx != (float)HUGE_VAL && mrg_left[i]->aff3_mvy != (float)HUGE_VAL){ + tv11->mvx = mrg_left[i]->aff1_mvx; + tv11->mvy = mrg_left[i]->aff1_mvy; + tv12->mvx = mrg_left[i]->aff2_mvx; + tv12->mvy = mrg_left[i]->aff2_mvy; + tv13->mvx = mrg_left[i]->aff3_mvx; + tv13->mvy = mrg_left[i]->aff3_mvy; + + getval = find_affine_SAD(fr_cur,fr_ref1,fr_ref2,upframe1,upframe2,*tv11,*tv12,*tv13,*tv11,*tv12,*tv13,xblk2,yblk2,x,y, + hor,ver,LEFT_CONNECTED_AFF,info.subpel[t_level],3); + }else if(mrg_right[i]->aff1_mvx != (float)HUGE_VAL && mrg_right[i]->aff1_mvy != (float)HUGE_VAL && mrg_right[i]->aff2_mvx != (float)HUGE_VAL && + mrg_right[i]->aff2_mvy != (float)HUGE_VAL && mrg_right[i]->aff3_mvx != (float)HUGE_VAL && mrg_right[i]->aff3_mvy != (float)HUGE_VAL){ + tv21->mvx = mrg_right[i]->aff1_mvx; + tv21->mvy = mrg_right[i]->aff1_mvy; + tv22->mvx = mrg_right[i]->aff2_mvx; + tv22->mvy = mrg_right[i]->aff2_mvy; + tv23->mvx = mrg_right[i]->aff3_mvx; + tv23->mvy = mrg_right[i]->aff3_mvy; + + getval = find_affine_SAD(fr_cur,fr_ref1,fr_ref2,upframe1,upframe2,*tv21,*tv22,*tv23,*tv21,*tv22,*tv23,xblk2,yblk2,x,y, + hor,ver,RIGHT_CONNECTED_AFF,info.subpel[t_level],3); + } +// }//if fmv2 != NULL + + if(getval < bst_aff_sad){ + bst_aff_sad = getval; + bst_idx1 = i; + } + + if(tmv1.sad_cost < bst_sad){ + bst_sad = tmv1.sad_cost; + tmv1.med_idx = i; + tmv2.med_idx = i; + } + + }//if effective MRG target + }// i + + if(bst_aff_sad < (bst_sad * aff_coef) ){ + assert(bst_idx1 >= 0); +/* printf("cx = %d, cy = %d, xblk = %d, yblk = %d, bst_aff_sad = %f, bst_sad = %f\n",x,y,xblk2,yblk2,bst_aff_sad,bst_sad); + + if(mrg_left[bst_idx1]->aff1_mvx != (float)HUGE_VAL) + printf("LEFT\naff1_mvx = %f, aff1_mvy = %f\naff2_mvx = %f, aff2_mvy = %f\naff3_mvx = %f, aff3_mvy = %f\n\n", + mrg_left[bst_idx1]->aff1_mvx,mrg_left[bst_idx1]->aff1_mvy,mrg_left[bst_idx1]->aff2_mvx, + mrg_left[bst_idx1]->aff2_mvy,mrg_left[bst_idx1]->aff3_mvx,mrg_left[bst_idx1]->aff3_mvy); + + if(mrg_right[bst_idx1]->aff1_mvx != (float)HUGE_VAL) + printf("RIGHT\naff1_mvx = %f, aff1_mvy = %f\naff2_mvx = %f, aff2_mvy = %f\naff3_mvx = %f, aff3_mvy = %f\n\n", + mrg_right[bst_idx1]->aff1_mvx,mrg_right[bst_idx1]->aff1_mvy,mrg_right[bst_idx1]->aff2_mvx, + mrg_right[bst_idx1]->aff2_mvy,mrg_right[bst_idx1]->aff3_mvx,mrg_right[bst_idx1]->aff3_mvy); +*/ + tmv1.med_idx = bst_idx1; + tmv2.med_idx = bst_idx1; + tmv1.aff_mrg = YES; + tmv2.aff_mrg = YES; + tmv1.sad_cost = bst_aff_sad; + tmv2.sad_cost = bst_aff_sad; + }else{ + tmv1.aff_mrg = NO; + tmv2.aff_mrg = NO; + } + + if(tmv1.med_idx >= 0){ + + if(tmv1.aff_mrg == YES){ + tmv1.mvx = mrg_left[tmv1.med_idx]->mvx; + tmv1.mvy = mrg_left[tmv1.med_idx]->mvy; + tmv2.mvx = mrg_right[tmv2.med_idx]->mvx; + tmv2.mvy = mrg_right[tmv2.med_idx]->mvy; + + tmv1.aff1_mvx = mrg_left[tmv1.med_idx]->aff1_mvx;tmv1.aff1_mvy = mrg_left[tmv1.med_idx]->aff1_mvy; + tmv1.aff2_mvx = mrg_left[tmv1.med_idx]->aff2_mvx;tmv1.aff2_mvy = mrg_left[tmv1.med_idx]->aff2_mvy; + tmv1.aff3_mvx = mrg_left[tmv1.med_idx]->aff3_mvx;tmv1.aff3_mvy = mrg_left[tmv1.med_idx]->aff3_mvy; + tmv2.aff1_mvx = mrg_right[tmv2.med_idx]->aff1_mvx;tmv2.aff1_mvy = mrg_right[tmv2.med_idx]->aff1_mvy; + tmv2.aff2_mvx = mrg_right[tmv2.med_idx]->aff2_mvx;tmv2.aff2_mvy = mrg_right[tmv2.med_idx]->aff2_mvy; + tmv2.aff3_mvx = mrg_right[tmv2.med_idx]->aff3_mvx;tmv2.aff3_mvy = mrg_right[tmv2.med_idx]->aff3_mvy; + + tv11->mvx = mrg_left[tmv1.med_idx]->aff1_mvx; tv21->mvx = mrg_right[tmv1.med_idx]->aff1_mvx; + tv11->mvy = mrg_left[tmv1.med_idx]->aff1_mvy; tv21->mvy = mrg_right[tmv1.med_idx]->aff1_mvy; + tv12->mvx = mrg_left[tmv1.med_idx]->aff2_mvx; tv22->mvx = mrg_right[tmv1.med_idx]->aff2_mvx; + tv12->mvy = mrg_left[tmv2.med_idx]->aff2_mvy; tv22->mvy = mrg_right[tmv2.med_idx]->aff2_mvy; + tv13->mvx = mrg_left[tmv2.med_idx]->aff3_mvx; tv23->mvx = mrg_right[tmv2.med_idx]->aff3_mvx; + tv13->mvy = mrg_left[tmv2.med_idx]->aff3_mvy; tv23->mvy = mrg_right[tmv2.med_idx]->aff3_mvy; + }else{ + tmv1.mvx = mrg_left[tmv1.med_idx]->mvx; + tmv1.mvy = mrg_left[tmv1.med_idx]->mvy; + tmv2.mvx = mrg_right[tmv2.med_idx]->mvx; + tmv2.mvy = mrg_right[tmv2.med_idx]->mvy; + + tmv1.aff1_mvx = (float)HUGE_VAL;tmv1.aff1_mvy = (float)HUGE_VAL; + tmv1.aff2_mvx = (float)HUGE_VAL;tmv1.aff2_mvy = (float)HUGE_VAL; + tmv1.aff3_mvx = (float)HUGE_VAL;tmv1.aff3_mvy = (float)HUGE_VAL; + tmv2.aff1_mvx = (float)HUGE_VAL;tmv2.aff1_mvy = (float)HUGE_VAL; + tmv2.aff2_mvx = (float)HUGE_VAL;tmv2.aff2_mvy = (float)HUGE_VAL; + tmv2.aff3_mvx = (float)HUGE_VAL;tmv2.aff3_mvy = (float)HUGE_VAL; + } + } +//////////////////////////////////////////////// + + for(i=0;i<=3;i++){ + delete(mrg_left[i]); + delete(mrg_right[i]); + } +///////////////////////////////////// + // check for validity + if(tmv1.aff_mrg == NO){ + if( (tmv1.mvx != (float)HUGE_VAL && tmv1.mvy != (float)HUGE_VAL) && + (tmv2.mvx != (float)HUGE_VAL && tmv2.mvy != (float)HUGE_VAL) ){ + find_MSE(&tmv1, &tmv2, fr_cur, fr_ref1, fr_ref2, x, y, xblk, yblk, hor, ver, t_level); + assert(tmv1.mse == tmv2.mse); + tmv1.is_predictor = YES; + tmv2.is_predictor = YES; + } + else if( tmv1.mvx != (float)HUGE_VAL && tmv1.mvy != (float)HUGE_VAL ){ + find_MSE(&tmv1, NULL, fr_cur, fr_ref1, NULL, x, y, xblk, yblk, hor, ver, t_level); + tmv2.mse = tmv1.mse; + tmv2.lifting_mode = IGNORED; + tmv1.is_predictor = YES; + tmv2.is_predictor = NO; + } + else if( tmv2.mvx != (float)HUGE_VAL && tmv2.mvy != (float)HUGE_VAL ){ + find_MSE(&tmv2, NULL, fr_cur, fr_ref2, NULL, x, y, xblk, yblk, hor, ver, t_level); + tmv1.mse = tmv2.mse; + tmv1.lifting_mode = IGNORED; + tmv1.is_predictor = NO; + tmv2.is_predictor = YES; + }else{ + tmv1.lifting_mode = IGNORED; + tmv2.lifting_mode = IGNORED; + tmv1.is_predictor = NO; + tmv2.is_predictor = NO; + } + }else{ + assert(tmv1.aff_mrg == YES); + tmv1.lifting_mode = IGNORED; + tmv2.lifting_mode = IGNORED; + tmv1.is_predictor = NO; + tmv2.is_predictor = NO; + } + +///////////////////////////////////////////////////////// + if( (tmv1.aff1_mvx != (float)HUGE_VAL && tmv1.aff1_mvy != (float)HUGE_VAL) && + (tmv2.aff1_mvx != (float)HUGE_VAL && tmv2.aff1_mvy != (float)HUGE_VAL) ){ + + assert(tmv1.lifting_mode == IGNORED && tmv2.lifting_mode == IGNORED && tmv1.aff_mrg == YES); + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*tv11,*tv12,*tv13, + *tv21,*tv22,*tv23,xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + assert(tmv1.mse == tmv2.mse); + tmv1.is_predictor = YES; + tmv2.is_predictor = YES; + tmv1.mse = aff_mse; + tmv2.mse = aff_mse; + tmv1.lifting_mode = CONNECTED; + tmv2.lifting_mode = CONNECTED; + } + } + else if( tmv1.aff1_mvx != (float)HUGE_VAL && tmv1.aff1_mvy != (float)HUGE_VAL ){ + + assert(tmv1.lifting_mode == IGNORED && tmv2.lifting_mode == IGNORED && tmv1.aff_mrg == YES); + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*tv11,*tv12,*tv13, + *tv11,*tv12,*tv13,xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + tmv2.lifting_mode = IGNORED; + tmv1.is_predictor = YES; + tmv2.is_predictor = NO; + tmv1.mse = aff_mse; + tmv2.mse = aff_mse; + tmv1.lifting_mode = CONNECTED; + } + } + else if( tmv2.aff1_mvx != (float)HUGE_VAL && tmv2.aff1_mvy != (float)HUGE_VAL ){ + + assert(tmv1.lifting_mode == IGNORED && tmv2.lifting_mode == IGNORED && tmv2.aff_mrg == YES); + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*tv21,*tv22,*tv23, + *tv21,*tv22,*tv23,xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + tmv1.lifting_mode = IGNORED; + tmv1.is_predictor = NO; + tmv2.is_predictor = YES; + tmv1.mse = aff_mse; + tmv2.mse = aff_mse; + tmv2.lifting_mode = CONNECTED; + } + } +///////////////////////////////////////////////////////// + + if ( (tmv1.lifting_mode == CONNECTED || tmv2.lifting_mode == CONNECTED) ) { + + assert(tmv1.med_idx >= 0 && tmv1.med_idx == tmv2.med_idx); + // generate SAD + + if( (tmv1.mvx != (float)HUGE_VAL && tmv1.mvy != (float)HUGE_VAL && tmv2.mvx != (float)HUGE_VAL && tmv2.mvy != (float)HUGE_VAL) ) + tmv1.sad_cost = Subpel_MCP_Error4(fr_cur, x, y, xblk, yblk, + fr_ref1, upframe1, tmv1.mvx, tmv1.mvy, + fr_ref2, upframe2, tmv2.mvx, tmv2.mvy, + hor, ver, info.subpel[t_level]); + else if( tmv1.mvx != (float)HUGE_VAL && tmv1.mvx != (float)HUGE_VAL ) + tmv1.sad_cost = Subpel_MCP_Error4(fr_cur, x, y, xblk, yblk, + fr_ref1, upframe1, tmv1.mvx, tmv1.mvy, + NULL, NULL, tmv2.mvx, tmv2.mvy, + hor, ver, info.subpel[t_level]); + else if( tmv2.mvx != (float)HUGE_VAL && tmv2.mvx != (float)HUGE_VAL ) + tmv1.sad_cost = Subpel_MCP_Error4(fr_cur, x, y, xblk, yblk, + fr_ref2, upframe2, tmv2.mvx, tmv2.mvy, + NULL, NULL, tmv1.mvx, tmv1.mvx, + hor, ver, info.subpel[t_level]); + else + assert(tmv1.aff1_mvx != (float)HUGE_VAL || tmv2.aff1_mvx != (float)HUGE_VAL); + + + v1 = &fmv1->mode_info[BLOCK_MERGING]; + v1->is_valid = YES; + v1->is_predictor = tmv1.is_predictor; + v1->lifting_mode = tmv1.lifting_mode; + v1->mvx = tmv1.mvx; + v1->mvy = tmv1.mvy; + v1->sad_cost = tmv1.sad_cost; + v1->mse = tmv1.mse; + v1->bit_cost = 0.; + v1->total_cost = tmv1.sad_cost; + v1->med_idx = tmv1.med_idx; + + v1->aff_mrg = tmv1.aff_mrg; + + if(v1->aff_mrg == YES){ + v1->aff1_mvx = tmv1.aff1_mvx; + v1->aff1_mvy = tmv1.aff1_mvy; + v1->aff2_mvx = tmv1.aff2_mvx; + v1->aff2_mvy = tmv1.aff2_mvy; + v1->aff3_mvx = tmv1.aff3_mvx; + v1->aff3_mvy = tmv1.aff3_mvy; + } + + if(fmv2 != NULL){ + v2 = &fmv2->mode_info[BLOCK_MERGING]; + v2->is_valid = YES; + v2->is_predictor = tmv2.is_predictor; + v2->lifting_mode = tmv2.lifting_mode; + v2->mvx = tmv2.mvx; + v2->mvy = tmv2.mvy; + v2->sad_cost = v1->sad_cost; + v2->mse = tmv1.mse; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + v2->med_idx = tmv2.med_idx; + + v2->aff_mrg = tmv2.aff_mrg; + + if(v2->aff_mrg == YES){ + v2->aff1_mvx = tmv2.aff1_mvx; + v2->aff1_mvy = tmv2.aff1_mvy; + v2->aff2_mvx = tmv2.aff2_mvx; + v2->aff2_mvy = tmv2.aff2_mvy; + v2->aff3_mvx = tmv2.aff3_mvx; + v2->aff3_mvy = tmv2.aff3_mvy; + } + } + } + + /************************************************************************* + >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DECISION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + *************************************************************************/ + + min_cost = (float)HUGE_VAL; + best_mode = -1; + + for (mode_cnt = 0; mode_cnt < NUMBER_OF_TRANS_MODES; mode_cnt++) { + + // prevent certain modes +#ifdef NO_CONNECT + if (get_mode_coding_cost((BiMode)mode_cnt, fmv2, info.bi_mv[t_level], t_level) > 0 && mode_cnt != BI_CONNECTED + && mode_cnt != LEFT_CONNECTED && mode_cnt != RIGHT_CONNECTED && mode_cnt != PARALLEL && mode_cnt != BLOCK_MERGING) { + //if (get_mode_coding_cost((BiMode)mode_cnt, fmv2, info.bi_mv[t_level], t_level) > 0) { +#else + if (get_mode_coding_cost((BiMode)mode_cnt, fmv2, info.bi_mv[t_level], t_level) > 0) { +#endif + + v1 = &fmv1->mode_info[mode_cnt]; + + if (v1->is_valid == YES) { + assert(fmv2 != NULL || (mode_cnt != BI_CONNECTED && + mode_cnt != BI_PREDICTED )); + + // add mode coding cost + mode_coding_cost = + info.lambda[t_level] * get_mode_coding_cost((BiMode)mode_cnt, + fmv2, info.bi_mv[t_level], t_level); + + assert(mode_coding_cost > 0); + + v1->bit_cost += mode_coding_cost; + v1->total_cost += mode_coding_cost; + + if (fmv2 != NULL) { + v2 = &fmv2->mode_info[mode_cnt]; + + assert(v2->is_valid == YES); + v2->bit_cost += mode_coding_cost; + v2->total_cost += mode_coding_cost; + } + + // what does it cost? + if (v1->total_cost < min_cost) { + // assert(fabs(v1->sad_cost + v1->bit_cost - v1->total_cost) < 1.0); + + best_mode = mode_cnt; + min_cost = v1->total_cost; + } + } + } + } + + assert(best_mode >= 0); + + // best mode was found + v1 = &fmv1->mode_info[best_mode]; + fmv1->bi_mode = (BiMode)best_mode; + if( fmv1->bi_mode == BLOCK_MERGING ){ + fmv1->lifting_mode = v1->lifting_mode; + fmv1->is_predictor = v1->is_predictor; + + fmv1->aff_mrg = v1->aff_mrg; + if(fmv1->aff_mrg == YES){ + fmv1->aff1_mvx = v1->aff1_mvx; fmv1->aff1_mvy = v1->aff1_mvy; + fmv1->aff2_mvx = v1->aff2_mvx; fmv1->aff2_mvy = v1->aff2_mvy; + fmv1->aff3_mvx = v1->aff3_mvx; fmv1->aff3_mvy = v1->aff3_mvy; + } + }else{ + fmv1->lifting_mode = left_mode[best_mode]; + fmv1->is_predictor = v1->is_predictor; + } + fmv1->mvx = v1->mvx; + fmv1->mvy = v1->mvy; + fmv1->sad_cost = v1->sad_cost; + fmv1->mse = v1->mse; + fmv1->bit_cost = v1->bit_cost; + fmv1->total_cost = v1->total_cost; + + fmv1->med_idx = v1->med_idx; //Added by Yuan Liu on 01.23.2016 + + assert(fmv1->total_cost == min_cost); + + if (fmv2 != NULL) { + v2 = &fmv2->mode_info[best_mode]; + assert(v2->is_valid == YES); + fmv2->bi_mode = (BiMode)best_mode; + if( fmv2->bi_mode == BLOCK_MERGING ){ + fmv2->lifting_mode = v2->lifting_mode; + fmv2->is_predictor = v2->is_predictor; + + fmv2->aff_mrg = v2->aff_mrg; + if(fmv2->aff_mrg == YES){ + fmv2->aff1_mvx = v2->aff1_mvx; fmv2->aff1_mvy = v2->aff1_mvy; + fmv2->aff2_mvx = v2->aff2_mvx; fmv2->aff2_mvy = v2->aff2_mvy; + fmv2->aff3_mvx = v2->aff3_mvx; fmv2->aff3_mvy = v2->aff3_mvy; + } + }else{ + fmv2->lifting_mode = right_mode[best_mode]; + fmv2->is_predictor = v2->is_predictor; + } + fmv2->mvx = v2->mvx; + fmv2->mvy = v2->mvy; + fmv2->sad_cost = v2->sad_cost; + fmv2->mse = fmv1->mse; + fmv2->bit_cost = v2->bit_cost; + fmv2->total_cost = v2->total_cost; + + fmv2->med_idx = v2->med_idx; //Added by Yuan Liu on 01.23.2016 + + } + + /****************查看是否还有connect模式******************/ + //if (fmv2 != NULL) + // printf("%d ", fmv2->lifting_mode); + //if (fmv1 != NULL) + // printf("%d ", fmv1->lifting_mode); + /**********************************/ + + /************************************************************************ + **************************** AFFINE MODES *************************** + ************************************************************************/ +#ifdef AFFINE_APPLY + +assert(dec == 1 || dec == 0); + +size = xblk2 * yblk2; +level = pow( (float)2, (int)t_level); + +do_affine = 0; +do_inter = 0; + +//Decide if we should do affine search +if(dec == 0){ + if( (fmv1->sad_cost > 1*size*(1 + t_level*0.25)) && fmv1->sad_cost > 160 ) + do_affine = 1; + + if(do_affine == 1){ + if(xblk == 8){ + if(fmv1->sad_cost > 300) + do_inter = 1; + + }else if(fmv1->sad_cost > 1.5*size*(1 + t_level*0.25)) + do_inter = 1; + } + +}else{ + assert(dec == 1); + if( fmv1->sad_cost > (4*size*level) ) + do_affine = 1; + + if(do_affine == 1){ + if( fmv1->sad_cost > (6*size*level) ) + do_inter = 1; + } +} +//Affine search decision + +if( (x + xblk < hor && y + yblk < ver && xblk >= 16) && do_affine == 1 && +(best_mode == BI_CONNECTED || best_mode == BLOCK_MERGING || best_mode == PARALLEL || best_mode == LEFT_CONNECTED || best_mode == RIGHT_CONNECTED) ){ + + + best_trans_sad = fmv1->sad_cost; + best_trans_mode = fmv1->bi_mode; + + aff_idx1 = fmv1->med_idx; + + if(fmv2 != NULL) + aff_idx2 = fmv2->med_idx; + + if(best_mode != BLOCK_MERGING){ + if(best_mode != RIGHT_CONNECTED){//for LEFT_CONNECTED, BI_CONNECTED, PARALLEL + if(fmv1->med_idx == -1){ + left_dmvx = fmv1->mvx; + left_dmvy = fmv1->mvy; + }else{ + left_dmvx = fmv1->mvx - pmv1x[fmv1->med_idx]; + left_dmvy = fmv1->mvy - pmv1y[fmv1->med_idx]; + } + } + + if(best_mode != LEFT_CONNECTED && best_mode != PARALLEL){//for RIGHT_CONNECTED, RIGHT_CONNECTED + if(fmv2->med_idx == -1){ + right_dmvx = fmv2->mvx; + right_dmvy = fmv2->mvy; + }else{ + right_dmvx = fmv2->mvx - pmv2x[fmv2->med_idx]; + right_dmvy = fmv2->mvy - pmv2y[fmv2->med_idx]; + } + } + }else{ + left_dmvx = 0; + left_dmvy = 0; + + right_dmvx = 0; + right_dmvy = 0; + } + + best_trans_bit_cost = fmv1->bit_cost - info.lambda[t_level] * get_mode_coding_cost((BiMode)best_trans_mode,fmv2,info.bi_mv[t_level], t_level); + + if(best_mode == BLOCK_MERGING){ + assert(best_trans_bit_cost == 0); + }else if(best_mode == LEFT_CONNECTED || best_mode == PARALLEL){ + getval = get_bit_cost(info.lambda[t_level],left_dmvx,left_dmvy,0,0,ctx1x,ctx1y,info.subpel[t_level]); + assert(best_trans_bit_cost == getval); + }else if(best_mode == RIGHT_CONNECTED){ + getval = get_bit_cost(info.lambda[t_level],right_dmvx,right_dmvy,0,0,ctx2x,ctx2y,info.subpel[t_level]); + assert(best_trans_bit_cost == getval); + }else{ + getval = get_bit_cost(info.lambda[t_level],left_dmvx,left_dmvy,0,0,ctx1x,ctx1y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],right_dmvx,right_dmvy,0,0,ctx2x,ctx2y,info.subpel[t_level]); + assert(best_trans_bit_cost == getval); + } + + trans_mvl.mvx = fmv1->mvx; + trans_mvl.mvy = fmv1->mvy; + + if(fmv2 != NULL){ + trans_mvr.mvx = fmv2->mvx; + trans_mvr.mvy = fmv2->mvy; + } + + if(fmv2 != NULL) + assert(fmv1->bi_mode == fmv2->bi_mode && fmv1->sad_cost == fmv2->sad_cost); + + +// printf("best_mode = %d, fmv1x = %f, fmv1y = %f, fmv2x = %f, fmv2y = %f, cx = %d, cy = %d, xblk2 = %d, yblk2 = %d, Translational SAD: %f\n",best_mode,fmv1->mvx,fmv1->mvy,fmv2->mvx,fmv2->mvy,x,y,xblk,yblk,fmv2->sad_cost); +// printf("Translational MV coding bits: %f\n",fmv1->bit_cost); + +// assert(fmv1->mode_info[AFFINE_MODE].is_valid == NO && +// (fmv2 == NULL || fmv2->mode_info[AFFINE_MODE].is_valid == NO)); + + get_v1[0].mvx = fmv1->mvx; + get_v1[0].mvy = fmv1->mvy; + get_v2[0].mvx = fmv1->mvx; + get_v2[0].mvy = fmv1->mvy; + get_v3[0].mvx = fmv1->mvx; + get_v3[0].mvy = fmv1->mvy; + + if(fmv2!=NULL){ + get2_v1[0].mvx = fmv2->mvx; + get2_v1[0].mvy = fmv2->mvy; + get2_v2[0].mvx = fmv2->mvx; + get2_v2[0].mvy = fmv2->mvy; + get2_v3[0].mvx = fmv2->mvx; + get2_v3[0].mvy = fmv2->mvy; + } + + if(fmv2!=NULL) + assert(fmv1->bi_mode == fmv2->bi_mode); + + for(i=0;i<4;i++){ + get_v1[i].mvx = (float)HUGE_VAL; + get_v1[i].mvy = (float)HUGE_VAL; + if(i<=3){ + get_v2[i].mvx = (float)HUGE_VAL; + get_v2[i].mvy = (float)HUGE_VAL; + get_v3[i].mvx = (float)HUGE_VAL; + get_v3[i].mvy = (float)HUGE_VAL; + } + } + +/////////// +//AFFINE V1 + i = 0; + +// printf("BLOCK B\n"); + find_block(x,y-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,1);if(*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL)i++; //BLOCK B +// printf("BLOCK C\n"); + find_block(x-1,y,fmv1_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,0);if(*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL)i++; //BLOCK C +// printf("BLOCK A\n"); + find_block(x-1,y-1,fmv1_array,info,t_level,get3x,get3y,&get_xblk,&get_yblk,1,1);if(*get3x != (float)HUGE_VAL && *get3y != (float)HUGE_VAL)i++; //BLOCK A + + if( (*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL) && ( fabs(*get2x - *get1x) < SMALL_DIFF && fabs(*get2y - *get1y) < SMALL_DIFF ) ){ + i--; + *get2x = (float)HUGE_VAL; + *get2y = (float)HUGE_VAL; + } + if( (*get3x != (float)HUGE_VAL && *get3y != (float)HUGE_VAL) && ( ( fabs(*get3x - *get1x) < SMALL_DIFF && fabs(*get3y - *get1y) < SMALL_DIFF) || ( fabs(*get3x - *get2x) < SMALL_DIFF && fabs(*get3y - *get2y) < SMALL_DIFF ) ) ){ + i--; + *get3x = (float)HUGE_VAL; + *get3y = (float)HUGE_VAL; + } + + get_v1[0].mvx = *get1x; + get_v1[0].mvy = *get1y; + + get_v1[1].mvx = *get2x; + get_v1[1].mvy = *get2y; + + get_v1[2].mvx = *get3x; + get_v1[2].mvy = *get3y; + +//TEMP Predictor + for(i = 0;i < 3; i ++){ + if( get_v1[i].mvx == (float)HUGE_VAL && get_v1[i].mvy == (float)HUGE_VAL && fmv3_array != NULL ){ + find_block(x,y,fmv3_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,0); + + for(j = 0; j < 3; j ++){ + if( (*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL) && ( fabs(*get1x - get_v1[j].mvx) < SMALL_DIFF && fabs(*get1y - get_v1[j].mvy) < SMALL_DIFF ) ){ + *get1x = (float)HUGE_VAL; + *get1y = (float)HUGE_VAL; + } + } + get_v1[i].mvx = *get1x; + get_v1[i].mvy = *get1y; + break; + } + } + + +//AFFINE V2 + i = 0; + +// printf("BLOCK D\n"); + find_block(x+xblk2-1,y-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);if(*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL)i++;//BLOCK D +// printf("BLOCK E\n"); + find_block(x+xblk2,y-1,fmv1_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,0,1);if(*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL)i++;//BLOCK E + + if( (*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL) && ( fabs(*get2x - *get1x) < SMALL_DIFF && fabs(*get2y - *get1y) < SMALL_DIFF ) ){ + i--; + *get2x = (float)HUGE_VAL; + *get2y = (float)HUGE_VAL; + } + + get_v2[0].mvx = *get1x; + get_v2[0].mvy = *get1y; + + get_v2[1].mvx = *get2x; + get_v2[1].mvy = *get2y; + + assert(i<=2); + + if(i >= 2){ + get_v2[2].mvx = ( ((*get1x!=(float)HUGE_VAL)?*get1x:0) + ((*get2x!=(float)HUGE_VAL)?*get2x:0) )/i; + get_v2[2].mvy = ( ((*get1y!=(float)HUGE_VAL)?*get1y:0) + ((*get2y!=(float)HUGE_VAL)?*get2y:0) )/i; + } + + if( (get_v2[2].mvx != (float)HUGE_VAL && get_v2[2].mvy != (float)HUGE_VAL) && ( ( fabs(get_v2[2].mvx - get_v2[0].mvx) < SMALL_DIFF && fabs(get_v2[2].mvy - get_v2[0].mvy) < SMALL_DIFF) || ( fabs(get_v2[2].mvx - get_v2[1].mvx) < SMALL_DIFF && fabs(get_v2[2].mvy - get_v2[1].mvy) < SMALL_DIFF ) ) ){ + get_v2[2].mvx = (float)HUGE_VAL; + get_v2[2].mvy = (float)HUGE_VAL; + } + +//TEMP Predictor + for(i = 0;i < 3; i ++){ + if( get_v2[i].mvx == (float)HUGE_VAL && get_v2[i].mvy == (float)HUGE_VAL && fmv3_array != NULL ){ + find_block(x+xblk2,y,fmv3_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,0); + + for(j = 0; j < 3; j ++){ + if( (*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL) && ( fabs(*get1x - get_v2[j].mvx) < SMALL_DIFF && fabs(*get1y - get_v2[j].mvy) < SMALL_DIFF ) ){ + *get1x = (float)HUGE_VAL; + *get1y = (float)HUGE_VAL; + } + } + get_v2[i].mvx = *get1x; + get_v2[i].mvy = *get1y; + break; + } + } + +//AFFINE V3 + i = 0; + +// printf("BLOCK F\n"); + find_block(x-1,y+yblk2-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);if(*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL)i++;//BLOCK F +// printf("BLOCK G\n"); + find_block(x-1,y+yblk2,fmv1_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,0);if(*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL)i++;//BLOCK G + + if( (*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL) && ( fabs(*get2x - *get1x) < SMALL_DIFF && fabs(*get2y - *get1y) < SMALL_DIFF) ){ + i--; + *get2x = (float)HUGE_VAL; + *get2y = (float)HUGE_VAL; + } + + get_v3[0].mvx = *get1x; + get_v3[0].mvy = *get1y; + + get_v3[1].mvx = *get2x; + get_v3[1].mvy = *get2y; + + assert(i<=2); + + if(i >= 2){ + get_v3[2].mvx = ( ((*get1x!=(float)HUGE_VAL)?*get1x:0) + ((*get2x!=(float)HUGE_VAL)?*get2x:0) )/i; + get_v3[2].mvy = ( ((*get1y!=(float)HUGE_VAL)?*get1y:0) + ((*get2y!=(float)HUGE_VAL)?*get2y:0) )/i; + } + + if( (get_v3[2].mvx != (float)HUGE_VAL && get_v3[2].mvy != (float)HUGE_VAL) && ( ( fabs(get_v3[2].mvx - get_v3[0].mvx) < SMALL_DIFF && fabs(get_v3[2].mvy - get_v3[0].mvy) < SMALL_DIFF) || ( fabs(get_v3[2].mvx - get_v3[1].mvx) < SMALL_DIFF && fabs(get_v3[2].mvy - get_v3[1].mvy) < SMALL_DIFF ) ) ){ + get_v3[2].mvx = (float)HUGE_VAL; + get_v3[2].mvy = (float)HUGE_VAL; + } + +//TEMP Predictor + for(i = 0;i < 3; i ++){ + if( get_v3[i].mvx == (float)HUGE_VAL && get_v3[i].mvy == (float)HUGE_VAL && fmv3_array != NULL ){ + find_block(x,y+yblk2,fmv3_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,0); + + for(j = 0; j < 3; j ++){ + if( (*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL) && ( fabs(*get1x - get_v3[j].mvx) < SMALL_DIFF && fabs(*get1y - get_v3[j].mvy) < SMALL_DIFF) ){ + *get1x = (float)HUGE_VAL; + *get1y = (float)HUGE_VAL; + } + } + + get_v3[i].mvx = *get1x; + get_v3[i].mvy = *get1y; + break; + } + } + + for(i=0;i<3;i++){ + fmv1->aff1_pred_mvx[i] = get_v1[i].mvx; + fmv1->aff1_pred_mvy[i] = get_v1[i].mvy; + fmv1->aff2_pred_mvx[i] = get_v2[i].mvx; + fmv1->aff2_pred_mvy[i] = get_v2[i].mvy; + fmv1->aff3_pred_mvx[i] = get_v3[i].mvx; + fmv1->aff3_pred_mvy[i] = get_v3[i].mvy; + } + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////// fmv2 ////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + + for(i=0;i<4;i++){ + get2_v1[i].mvx = (float)HUGE_VAL; + get2_v1[i].mvy = (float)HUGE_VAL; + if(i<=3){ + get2_v2[i].mvx = (float)HUGE_VAL; + get2_v2[i].mvy = (float)HUGE_VAL; + get2_v3[i].mvx = (float)HUGE_VAL; + get2_v3[i].mvy = (float)HUGE_VAL; + } + } + + if(fmv2 != NULL){ +/////////// +//AFFINE V1 + i = 0; + +// printf("BLOCK B\n"); + find_block(x,y-1,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,1);if(*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL)i++; //BLOCK B +// printf("BLOCK C\n"); + find_block(x-1,y,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,0);if(*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL)i++; //BLOCK C +// printf("BLOCK A\n"); + find_block(x-1,y-1,fmv2_array,info,t_level,get3x,get3y,&get_xblk,&get_yblk,1,1);if(*get3x != (float)HUGE_VAL && *get3y != (float)HUGE_VAL)i++; //BLOCK A + + if( (*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL) && ( fabs(*get2x - *get1x) < SMALL_DIFF && fabs(*get2y - *get1y) < SMALL_DIFF ) ){ + i--; + *get2x = (float)HUGE_VAL; + *get2y = (float)HUGE_VAL; + } + if( (*get3x != (float)HUGE_VAL && *get3y != (float)HUGE_VAL) && ( ( fabs(*get3x - *get1x) < SMALL_DIFF && fabs(*get3y - *get1y) < SMALL_DIFF ) || ( fabs(*get3x - *get2x) < SMALL_DIFF && fabs(*get3y - *get2y) < SMALL_DIFF) ) ){ + i--; + *get3x = (float)HUGE_VAL; + *get3y = (float)HUGE_VAL; + } + + get2_v1[0].mvx = *get1x; + get2_v1[0].mvy = *get1y; + + get2_v1[1].mvx = *get2x; + get2_v1[1].mvy = *get2y; + + get2_v1[2].mvx = *get3x; + get2_v1[2].mvy = *get3y; + +//TEMP Predictor + for(i = 0;i < 3; i ++){ + if( get2_v1[i].mvx == (float)HUGE_VAL && get2_v1[i].mvy == (float)HUGE_VAL && fmv4_array != NULL ){ + find_block(x,y,fmv4_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,0); + + for(j = 0; j < 3; j ++){ + if( (*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL) && ( fabs(*get1x - get2_v1[j].mvx) < SMALL_DIFF && fabs(*get1y - get2_v1[j].mvy) < SMALL_DIFF) ){ + *get1x = (float)HUGE_VAL; + *get1y = (float)HUGE_VAL; + } + } + get2_v1[i].mvx = *get1x; + get2_v1[i].mvy = *get1y; + break; + } + } + +//AFFINE V2 + i = 0; + +// printf("BLOCK D\n"); + find_block(x+xblk2-1,y-1,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);if(*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL)i++;//BLOCK D +// printf("BLOCK E\n"); + find_block(x+xblk2,y-1,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,0,1);if(*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL)i++;//BLOCK E + + if( (*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL) && ( fabs(*get2x - *get1x) < SMALL_DIFF && fabs(*get2y - *get1y) < SMALL_DIFF) ){ + i--; + *get2x = (float)HUGE_VAL; + *get2y = (float)HUGE_VAL; + } + + get2_v2[0].mvx = *get1x; + get2_v2[0].mvy = *get1y; + + get2_v2[1].mvx = *get2x; + get2_v2[1].mvy = *get2y; + + assert(i<=2); + + if(i >= 2){ + get2_v2[2].mvx = ( ((*get1x!=(float)HUGE_VAL)?*get1x:0) + ((*get2x!=(float)HUGE_VAL)?*get2x:0) )/i; + get2_v2[2].mvy = ( ((*get1y!=(float)HUGE_VAL)?*get1y:0) + ((*get2y!=(float)HUGE_VAL)?*get2y:0) )/i; + } + + if( (get2_v2[2].mvx != (float)HUGE_VAL && get2_v2[2].mvy != (float)HUGE_VAL) && ( ( fabs(get2_v2[2].mvx - get2_v2[0].mvx) < SMALL_DIFF && fabs(get2_v2[2].mvy - get2_v2[0].mvy) < SMALL_DIFF) || ( fabs(get2_v2[2].mvx - get2_v2[1].mvx) < SMALL_DIFF && fabs(get2_v2[2].mvy - get2_v2[1].mvy) < SMALL_DIFF ) ) ){ + get2_v2[2].mvx = (float)HUGE_VAL; + get2_v2[2].mvy = (float)HUGE_VAL; + } + +//TEMP Predictor + for(i = 0;i < 3; i ++){ + if( get2_v2[i].mvx == (float)HUGE_VAL && get2_v2[i].mvy == (float)HUGE_VAL && fmv4_array != NULL ){ + find_block(x+xblk2,y,fmv4_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,0); + + for(j = 0; j < 3; j ++){ + if( (*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL) && ( fabs(*get1x - get2_v2[j].mvx) < SMALL_DIFF && fabs(*get1y - get2_v2[j].mvy) < SMALL_DIFF) ){ + *get1x = (float)HUGE_VAL; + *get1y = (float)HUGE_VAL; + } + } + get2_v2[i].mvx = *get1x; + get2_v2[i].mvy = *get1y; + break; + } + } + +//AFFINE V3 + i = 0; + +// printf("BLOCK F\n"); + find_block(x-1,y+yblk2-1,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);if(*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL)i++;//BLOCK F +// printf("BLOCK G\n"); + find_block(x-1,y+yblk2,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,0);if(*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL)i++;//BLOCK G + + if( (*get2x != (float)HUGE_VAL && *get2y != (float)HUGE_VAL) && ( fabs(*get2x - *get1x) < SMALL_DIFF && fabs(*get2y - *get1y) < SMALL_DIFF) ){ + i--; + *get2x = (float)HUGE_VAL; + *get2y = (float)HUGE_VAL; + } + + get2_v3[0].mvx = *get1x; + get2_v3[0].mvy = *get1y; + + get2_v3[1].mvx = *get2x; + get2_v3[1].mvy = *get2y; + + assert(i<=2); + + if(i >= 2){ + get2_v3[2].mvx = ( ((*get1x!=(float)HUGE_VAL)?*get1x:0) + ((*get2x!=(float)HUGE_VAL)?*get2x:0) )/i; + get2_v3[2].mvy = ( ((*get1y!=(float)HUGE_VAL)?*get1y:0) + ((*get2y!=(float)HUGE_VAL)?*get2y:0) )/i; + } + + if( (get2_v3[2].mvx != (float)HUGE_VAL && get2_v3[2].mvy != (float)HUGE_VAL) && ( ( fabs(get2_v3[2].mvx - get2_v3[0].mvx) < SMALL_DIFF && fabs(get2_v3[2].mvy - get2_v3[0].mvy) < SMALL_DIFF) || ( fabs(get2_v3[2].mvx - get2_v3[1].mvx) < SMALL_DIFF && fabs(get2_v3[2].mvy - get2_v3[1].mvy) < SMALL_DIFF ) ) ){ + get2_v3[2].mvx = (float)HUGE_VAL; + get2_v3[2].mvy = (float)HUGE_VAL; + } + +//TEMP Predictor + for(i = 0;i < 3; i ++){ + if( get2_v3[i].mvx == (float)HUGE_VAL && get2_v3[i].mvy == (float)HUGE_VAL && fmv4_array != NULL ){ + find_block(x,y+yblk2,fmv4_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,0); + + for(j = 0; j < 3; j ++){ + if( (*get1x != (float)HUGE_VAL && *get1y != (float)HUGE_VAL) && ( fabs(*get1x - get2_v3[j].mvx) < SMALL_DIFF && fabs(*get1y - get2_v3[j].mvy) < SMALL_DIFF ) ){ + *get1x = (float)HUGE_VAL; + *get1y = (float)HUGE_VAL; + } + } + get2_v3[i].mvx = *get1x; + get2_v3[i].mvy = *get1y; + break; + } + } + + for(i=0;i<3;i++){ + fmv2->aff1_pred_mvx[i] = get2_v1[i].mvx; + fmv2->aff1_pred_mvy[i] = get2_v1[i].mvy; + fmv2->aff2_pred_mvx[i] = get2_v2[i].mvx; + fmv2->aff2_pred_mvy[i] = get2_v2[i].mvy; + fmv2->aff3_pred_mvx[i] = get2_v3[i].mvx; + fmv2->aff3_pred_mvy[i] = get2_v3[i].mvy; + } + + }//if fmv2 != NULL + + //////////////////// Added on 05.01.2016 //////////////////// + + aff_num1 = 0; + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( get_v1[i].mvx!=(float)HUGE_VAL && get_v2[j].mvx!=(float)HUGE_VAL && get_v3[k].mvx!=(float)HUGE_VAL ){ + assert(get_v1[i].mvy!=(float)HUGE_VAL && get_v2[j].mvy!=(float)HUGE_VAL && get_v3[k].mvy!=(float)HUGE_VAL); + aff_num1 ++; + } + } + } + } + +// if(aff_num1 == 0) +// printf("zero pred!\n"); + +// printf("aff_num1 = %d\n",aff_num1); + + aff_num2 = 0; + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( get2_v1[i].mvx!=(float)HUGE_VAL && get2_v2[j].mvx!=(float)HUGE_VAL && get2_v3[k].mvx!=(float)HUGE_VAL ){ + assert(get2_v1[i].mvy!=(float)HUGE_VAL && get2_v2[j].mvy!=(float)HUGE_VAL && get2_v3[k].mvy!=(float)HUGE_VAL); + aff_num2 ++; + } + } + } + } + +// if(aff_num2 == 0) +// printf("zero pred!\n"); + +// printf("aff_num2 = %d\n",aff_num2); + + assert(aff_num1 <= 27 && aff_num2 <= 27); + + if(fmv2 != NULL){ +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d, aff_num1 = %d, aff_num2 = %d\n",x,y,xblk2,yblk2,aff_num1,aff_num2); + } + ////////////////////////////////////////////////////////////// + + best_aff_bit_cost = (float)HUGE_VAL; + best_aff_sad_cost = (float)HUGE_VAL; + best_aff_total_cost = best_aff_sad_cost + best_aff_bit_cost; + best_idx1 = -1; + count = 0; + pos1 = -1; + +//LEFT SEARCH +//AFF_DIRECT MODE + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( get_v1[i].mvx!=(float)HUGE_VAL && get_v2[j].mvx!=(float)HUGE_VAL && get_v3[k].mvx!=(float)HUGE_VAL && + get_v1[i].mvy!=(float)HUGE_VAL && get_v2[j].mvy!=(float)HUGE_VAL && get_v3[k].mvy!=(float)HUGE_VAL ){ + get_aff_sad_cost = find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2,get_v1[i],get_v2[j],get_v3[k],get2_v1[i],get2_v2[j],get2_v3[k], + xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF,info.subpel[t_level],0); + get_aff_bit_cost = info.lambda[t_level] * get_mode_coding_cost(LEFT_CONNECTED_AFF, fmv2, + info.bi_mv[t_level], t_level) + info.lambda[t_level] * ( (int)(aff_num1/4) + AFF_IDX_OFFSET + DIRECT_LEN ); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + if( (get_aff_total_cost < best_aff_total_cost) ){ + assert(get_aff_total_cost != (float)HUGE_VAL); + + best_aff_bit_cost = get_aff_bit_cost; + best_aff_sad_cost = get_aff_sad_cost; + best_aff_total_cost = get_aff_total_cost; + best_idx1 = i * 9 + j * 3 + k; + pred11 = i; + pred12 = j; + pred13 = k; + pos1 = count; +// printf("count = %d, length = %d\n",count, (int)(count/4) ); + } + count++; + } + } + } + } + + if( ( (best_aff_total_cost < (fmv1->total_cost + 3 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + best_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (best_aff_total_cost < fmv1->total_cost ) && best_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,get_v1[pred11],get_v2[pred12],get_v3[pred13], + get2_v1[pred21],get2_v2[pred22],get2_v3[pred23],xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + if(fmv2 != NULL) + assert(fmv1->total_cost == fmv2->total_cost); + + assert(pos1 >= 0 && pos1 <= 26); + + assert(best_idx1 >= 0 && best_idx1 <= 26); + fmv1->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv1->sad_cost = best_aff_sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = best_aff_bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = pos1; + fmv1->direct_idx = DIRECT; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = get_v1[pred11].mvx;fmv1->aff1_mvy = get_v1[pred11].mvy; + fmv1->aff2_mvx = get_v2[pred12].mvx;fmv1->aff2_mvy = get_v2[pred12].mvy; + fmv1->aff3_mvx = get_v3[pred13].mvx;fmv1->aff3_mvy = get_v3[pred13].mvy; + + if(fmv2 != NULL){ + fmv2->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv2->sad_cost = fmv1->sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = fmv1->bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + fmv2->direct_idx = DIRECT; + fmv2->is_predictor = NO; + fmv2->lifting_mode = IGNORED; + fmv2->aff1_mvx = (float)HUGE_VAL;fmv2->aff1_mvy = (float)HUGE_VAL; + fmv2->aff2_mvx = (float)HUGE_VAL;fmv2->aff2_mvy = (float)HUGE_VAL; + fmv2->aff3_mvx = (float)HUGE_VAL;fmv2->aff3_mvy = (float)HUGE_VAL; + } + }//If MSE + } + +//AFF_INTER MODE + if(pred11 >= 0 && pred12 >= 0 && pred13 >= 0 && do_inter == 1){ + assert(pos1 >= 0); + + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, &get_v1[pred11], &get_v2[pred12], &get_v3[pred13],dv11,dv12,dv13,xblk2,yblk2,x,y,hor,ver, + LEFT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + + get_aff_sad_cost = find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, *dv11, *dv12, *dv13, *dv21, *dv22, + *dv23, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * ( (int)(pos1/4) + AFF_IDX_OFFSET + DIRECT_LEN + MERGE_LEN) + get_bit_cost(info.lambda[t_level],dv11->mvx, + dv11->mvy,get_v1[pred11].mvx,get_v1[pred11].mvy,ctx1x,ctx1y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy, + get_v2[pred12].mvx,get_v2[pred12].mvy,ctx1x,ctx1y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy, + get_v3[pred13].mvx,get_v3[pred13].mvy,ctx1x,ctx1y,info.subpel[t_level]) + info.lambda[t_level] * get_mode_coding_cost(LEFT_CONNECTED_AFF, + fmv2,info.bi_mv[t_level], t_level); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + aff_sad_cache = get_aff_sad_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*dv11, *dv12, *dv13, *dv21, *dv22, + *dv23, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv1->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv1->sad_cost = get_aff_sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = get_aff_bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = pos1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = INTER; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = dv11->mvx; fmv1->aff1_mvy = dv11->mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff1_dmvx = dv11->mvx - get_v1[pred11].mvx; + fmv1->aff1_dmvy = dv11->mvy - get_v1[pred11].mvy; + fmv1->aff2_dmvx = dv12->mvx - get_v2[pred12].mvx; + fmv1->aff2_dmvy = dv12->mvy - get_v2[pred12].mvy; + fmv1->aff3_dmvx = dv13->mvx - get_v3[pred13].mvx; + fmv1->aff3_dmvy = dv13->mvy - get_v3[pred13].mvy; + + // printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n",fmv1->aff2_dmvx,fmv1->aff2_dmvy); + + if(fmv2 != NULL){ + fmv2->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv2->sad_cost = fmv1->sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = fmv1->bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = INTER; + fmv2->is_predictor = NO; + fmv2->lifting_mode = IGNORED; + fmv2->aff1_mvx = (float)HUGE_VAL;fmv2->aff1_mvy = (float)HUGE_VAL; + fmv2->aff2_mvx = (float)HUGE_VAL;fmv2->aff2_mvy = (float)HUGE_VAL; + fmv2->aff3_mvx = (float)HUGE_VAL;fmv2->aff3_mvy = (float)HUGE_VAL; + } + }//If MSE + } + } +//INTER + +//AFF_MERGE MODE +//UP MERGE + // printf("BLOCK B\n"); + find_block(x,y-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,1);//BLOCK B + merg_aff_v1.mvx = *get1x; + merg_aff_v1.mvy = *get1y; + // printf("BLOCK D\n"); + find_block(x+xblk2-1,y-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);//BLOCK D + merg_aff_v2.mvx = *get1x; + merg_aff_v2.mvy = *get1y; + + if(merg_aff_v1.mvx != (float)HUGE_VAL && merg_aff_v1.mvy != (float)HUGE_VAL && + merg_aff_v2.mvx != (float)HUGE_VAL && merg_aff_v2.mvy != (float)HUGE_VAL){ + + mrg_cnt1 = 0; + + for(i = 0;i < 2; i++){ + if(get_v3[i].mvx != (float)HUGE_VAL && get_v3[i].mvy != (float)HUGE_VAL){ + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, &merg_aff_v1, &merg_aff_v2, &get_v3[i], dv11,dv12,dv13,xblk2,yblk2,x,y,hor,ver, + LEFT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,3); + + get_aff_sad_cost = best_sad; +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, merg_aff_v1, merg_aff_v2, *dv13, merg_aff_v1, merg_aff_v2, *dv13, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF,info.subpel[t_level],0); + get_aff_bit_cost = info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_UP_LEN + 1 ) + info.lambda[t_level] * get_mode_coding_cost(LEFT_CONNECTED_AFF,fmv2,info.bi_mv[t_level], + t_level) + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,get_v3[i].mvx,get_v3[i].mvy,ctx1x,ctx1y,info.subpel[t_level]); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, merg_aff_v1, merg_aff_v2, *dv13, + merg_aff_v1, merg_aff_v2, *dv13, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv1->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv1->sad_cost = get_aff_sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = get_aff_bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = mrg_cnt1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = UP; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = merg_aff_v1.mvx;fmv1->aff1_mvy = merg_aff_v1.mvy; + fmv1->aff2_mvx = merg_aff_v2.mvx;fmv1->aff2_mvy = merg_aff_v2.mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff3_dmvx = dv13->mvx - get_v3[i].mvx; + fmv1->aff3_dmvy = dv13->mvy - get_v3[i].mvy; + + // printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n",fmv1->aff3_dmvx,fmv1->aff3_dmvy); + + if(fmv2 != NULL){ + fmv2->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv2->sad_cost = fmv1->sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = fmv1->bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = UP; + fmv2->is_predictor = NO; + fmv2->lifting_mode = IGNORED; + fmv2->aff1_mvx = (float)HUGE_VAL;fmv2->aff1_mvy = (float)HUGE_VAL; + fmv2->aff2_mvx = (float)HUGE_VAL;fmv2->aff2_mvy = (float)HUGE_VAL; + fmv2->aff3_mvx = (float)HUGE_VAL;fmv2->aff3_mvy = (float)HUGE_VAL; + } + }//If MSE + } + + mrg_cnt1 ++; + }//IF get != HUGE_VAL + } + } + +//LEFT MERGE + // printf("BLOCK C\n"); + find_block(x-1,y,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,0);//BLOCK C + merg_aff_v1.mvx = *get1x; + merg_aff_v1.mvy = *get1y; + // printf("BLOCK F\n"); + find_block(x-1,y+yblk2-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);//BLOCK F + merg_aff_v2.mvx = *get1x; + merg_aff_v2.mvy = *get1y; + + if(merg_aff_v1.mvx != (float)HUGE_VAL && merg_aff_v1.mvy != (float)HUGE_VAL && + merg_aff_v2.mvx != (float)HUGE_VAL && merg_aff_v2.mvy != (float)HUGE_VAL){ + + mrg_cnt1 = 0; + + for(i = 0;i < 2; i++){ + if(get_v2[i].mvx != (float)HUGE_VAL && get_v2[i].mvy != (float)HUGE_VAL){ + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2, upframe1,upframe2,ctx1x, ctx1y, &merg_aff_v1, &get_v2[i], &merg_aff_v2, dv11,dv12,dv13,xblk2,yblk2,x,y,hor,ver, + LEFT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,2); + + get_aff_sad_cost = best_sad; +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, merg_aff_v1, *dv12, merg_aff_v2, merg_aff_v1, *dv12, merg_aff_v2, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF,info.subpel[t_level],0); + get_aff_bit_cost = info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + info.lambda[t_level] * get_mode_coding_cost(LEFT_CONNECTED_AFF, + fmv2,info.bi_mv[t_level], t_level) + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,get_v2[i].mvx,get_v2[i].mvy, + ctx1x,ctx1y,info.subpel[t_level]); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, merg_aff_v1, *dv12, merg_aff_v2, + merg_aff_v1, *dv12, merg_aff_v2, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv1->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv1->sad_cost = get_aff_sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = get_aff_bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = mrg_cnt1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = LEFT; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = merg_aff_v1.mvx;fmv1->aff1_mvy = merg_aff_v1.mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = merg_aff_v2.mvx;fmv1->aff3_mvy = merg_aff_v2.mvy; + + fmv1->aff2_dmvx = dv12->mvx - get_v2[i].mvx; + fmv1->aff2_dmvy = dv12->mvy - get_v2[i].mvy; + + // printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n",fmv1->aff2_dmvx,fmv1->aff2_dmvy); + + if(fmv2 != NULL){ + fmv2->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv2->sad_cost = fmv1->sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = fmv1->bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = LEFT; + fmv2->is_predictor = NO; + fmv2->lifting_mode = IGNORED; + fmv2->aff1_mvx = (float)HUGE_VAL;fmv2->aff1_mvy = (float)HUGE_VAL; + fmv2->aff2_mvx = (float)HUGE_VAL;fmv2->aff2_mvy = (float)HUGE_VAL; + fmv2->aff3_mvx = (float)HUGE_VAL;fmv2->aff3_mvy = (float)HUGE_VAL; + } + }//If MSE + } + + mrg_cnt1 ++; + } + }// i + } + +/* TEST */ + if(pred11 >= 0 && pred12 >= 0 && pred13 >= 0 && do_inter == 1){ + if( (best_trans_mode == LEFT_CONNECTED || best_trans_mode == LEFT_PREDICTED || + (best_trans_mode == BLOCK_MERGING && trans_mvl.mvx != (float)HUGE_VAL && trans_mvr.mvx == (float)HUGE_VAL) ) && fmv2 != NULL){ + if(best_trans_sad < best_aff_sad_cost){ +// printf("left trans better, bi_mode = %d, x = %d, y = %d, xblk = %d, yblk = %d\naff_sad = %f, trans_sad = %f\n\n", +// best_trans_mode,x,y,xblk2,yblk2,best_aff_sad_cost,best_trans_sad); + + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, &trans_mvl, &trans_mvl, &trans_mvl,dv11,dv12,dv13,xblk2,yblk2,x,y,hor,ver, + LEFT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + + get_aff_sad_cost = best_sad; + + get_aff_bit_cost = get_bit_cost(info.lambda[t_level],dv11->mvx,dv11->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]); + + dv11->dmvx = dv11->mvx - trans_mvl.mvx; dv11->dmvy = dv11->mvy - trans_mvl.mvy; + dv12->dmvx = dv12->mvx - trans_mvl.mvx; dv12->dmvy = dv12->mvy - trans_mvl.mvy; + dv13->dmvx = dv13->mvx - trans_mvl.mvx; dv13->dmvy = dv13->mvy - trans_mvl.mvy; + +//Apply trans-based aff result if better + if(best_trans_mode == BLOCK_MERGING){ + + get_aff_bit_cost = get_aff_bit_cost + info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + + info.lambda[t_level] * get_mode_coding_cost(LEFT_CONNECTED_AFF, fmv2,info.bi_mv[t_level], t_level); + + }else if(best_trans_mode == LEFT_CONNECTED || best_trans_mode == LEFT_PREDICTED){ + get_aff_bit_cost = get_aff_bit_cost + get_bit_cost(info.lambda[t_level],left_dmvx,left_dmvy,0,0,ctx1x,ctx1y,info.subpel[t_level]); + + get_aff_bit_cost = get_aff_bit_cost + info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + + info.lambda[t_level] * get_mode_coding_cost(LEFT_CONNECTED_AFF, fmv2,info.bi_mv[t_level], t_level); + + }else + assert(0); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + +//decision making + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef * t_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*dv11, *dv12, *dv13, *dv21, *dv22, + *dv23, xblk2,yblk2,x,y,hor,ver,LEFT_CONNECTED_AFF); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv1->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv1->sad_cost = get_aff_sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = get_aff_bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + + fmv1->aff_idx = -1; + + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = TRAN_P; + + if(best_trans_mode == BLOCK_MERGING) + fmv1->trans_pred_idx = DIR; + else{ + assert(best_trans_mode == LEFT_CONNECTED); + fmv1->trans_pred_idx = INDIR; + } + + + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + + fmv1->dmvx = left_dmvx; fmv1->dmvy = left_dmvy; + fmv1->aff1_mvx = dv11->mvx; fmv1->aff1_mvy = dv11->mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff1_dmvx = dv11->dmvx; fmv1->aff1_dmvy = dv11->dmvy; + fmv1->aff2_dmvx = dv12->dmvx; fmv1->aff2_dmvy = dv12->dmvy; + fmv1->aff3_dmvx = dv13->dmvx; fmv1->aff3_dmvy = dv13->dmvy; + + + if(fmv2 != NULL){ + fmv2->bi_mode = (BiMode)LEFT_CONNECTED_AFF; + + fmv2->sad_cost = fmv1->sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = fmv1->bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = TRAN_P; + + if(best_trans_mode == BLOCK_MERGING) + fmv2->trans_pred_idx = DIR; + else{ + assert(best_trans_mode == LEFT_CONNECTED); + fmv2->trans_pred_idx = INDIR; + } + + fmv2->is_predictor = NO; + fmv2->lifting_mode = IGNORED; + + fmv2->dmvx = (float)HUGE_VAL; fmv2->dmvy = (float)HUGE_VAL; + fmv2->aff1_mvx = (float)HUGE_VAL; fmv2->aff1_mvy = (float)HUGE_VAL; + fmv2->aff2_mvx = (float)HUGE_VAL; fmv2->aff2_mvy = (float)HUGE_VAL; + fmv2->aff3_mvx = (float)HUGE_VAL; fmv2->aff3_mvy = (float)HUGE_VAL; + } + }//If MSE + } + } + } + }//if pred +/* END OF TEST */ + + +//RIGHT SEARCH IF AVAILABLE + if( fmv2 != NULL ){ + block_buff1 = ( float * )getarray( xblk * yblk, sizeof( float ), "block_buff1" ); + block_buff2 = ( float * )getarray( xblk * yblk, sizeof( float ), "block_buff2" ); + +//DIRECT MODE + best_aff_bit_cost = (float)HUGE_VAL; + best_aff_sad_cost = (float)HUGE_VAL; + best_aff_total_cost = best_aff_sad_cost + best_aff_bit_cost; + best_idx2 = -1; + count = 0; + pos2 = -1; + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( get2_v1[i].mvx!=(float)HUGE_VAL && get2_v2[j].mvx!=(float)HUGE_VAL && get2_v3[k].mvx!=(float)HUGE_VAL && + get2_v1[i].mvy!=(float)HUGE_VAL && get2_v2[j].mvy!=(float)HUGE_VAL && get2_v3[k].mvy!=(float)HUGE_VAL ){ + get_aff_sad_cost = find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2,get2_v1[i],get2_v2[j],get2_v3[k],get_v1[i],get_v2[j],get_v3[k], + xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF,info.subpel[t_level],0); + get_aff_bit_cost = info.lambda[t_level] * get_mode_coding_cost(RIGHT_CONNECTED_AFF, fmv2, + info.bi_mv[t_level], t_level) + info.lambda[t_level] * ( (int)(aff_num2/4) + AFF_IDX_OFFSET + DIRECT_LEN ); + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + if( (get_aff_total_cost < best_aff_total_cost) ){ + assert(get_aff_total_cost != (float)HUGE_VAL); + + best_aff_bit_cost = get_aff_bit_cost; + best_aff_sad_cost = get_aff_sad_cost; + best_aff_total_cost = get_aff_total_cost; + best_idx2 = i * 9 + j * 3 + k; + pred21 = i; + pred22 = j; + pred23 = k; + pos2 = count; +// printf("count = %d, length = %d\n",count, (int)(count/4) ); + } + count++; + } + } + } + } + + if( ( (best_aff_total_cost < (fmv1->total_cost + 3 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + best_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (best_aff_total_cost < fmv1->total_cost ) && best_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, get2_v1[pred21],get2_v2[pred22],get2_v3[pred23], + get_v1[pred11],get_v2[pred12],get_v3[pred13], xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + assert(fmv1->total_cost == fmv2->total_cost); + assert(pos2 >= 0 && pos2 <= 26); + assert(best_idx2 >= 0 && best_idx2 <= 26); + fmv2->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv2->sad_cost = best_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = best_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = pos2; + fmv2->direct_idx = DIRECT; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = get2_v1[pred21].mvx;fmv2->aff1_mvy = get2_v1[pred21].mvy; + fmv2->aff2_mvx = get2_v2[pred22].mvx;fmv2->aff2_mvy = get2_v2[pred22].mvy; + fmv2->aff3_mvx = get2_v3[pred23].mvx;fmv2->aff3_mvy = get2_v3[pred23].mvy; + + fmv1->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = -1; + fmv1->direct_idx = DIRECT; + fmv1->is_predictor = NO; + fmv1->lifting_mode = IGNORED; + fmv1->aff1_mvx = (float)HUGE_VAL;fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL;fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL;fmv1->aff3_mvy = (float)HUGE_VAL; + }//If MSE + } + +//AFF_INTER MODE + if(pred21 >= 0 && pred22 >= 0 && pred23 >= 0 && do_inter == 1){ + assert(pos2 >= 0); + + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2, upframe1,upframe2,ctx2x, ctx2y, &get2_v1[pred21], &get2_v2[pred22], &get2_v3[pred23],dv21,dv22,dv23,xblk2,yblk2,x,y, + hor,ver,RIGHT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + + get_aff_sad_cost = best_sad; +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, *dv21, *dv22, *dv23, *dv11, *dv12,*dv13, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * ( (int)(pos2/4) + AFF_IDX_OFFSET + DIRECT_LEN + MERGE_LEN ) + get_bit_cost(info.lambda[t_level],dv21->mvx,dv21->mvy, + get2_v1[pred21].mvx,get2_v1[pred21].mvy,ctx2x,ctx2y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],dv22->mvx,dv22->mvy,get2_v2[pred22].mvx, + get2_v2[pred22].mvy,ctx2x,ctx2y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],dv23->mvx,dv23->mvy,get2_v3[pred23].mvx, + get2_v3[pred23].mvy,ctx2x,ctx2y,info.subpel[t_level]) + info.lambda[t_level] * get_mode_coding_cost(RIGHT_CONNECTED_AFF, + fmv2,info.bi_mv[t_level], t_level); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + aff_sad_cache = get_aff_sad_cost; + + if( ( (get_aff_total_cost < (fmv2->total_cost + 1 * info.lambda[t_level]) ) && fmv2->bi_mode <= 8 && + get_aff_sad_cost < (fmv2->sad_cost * aff_coef) ) || + (fmv2->bi_mode >= 9 && (get_aff_total_cost < fmv2->total_cost ) && get_aff_sad_cost < fmv2->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, *dv21, *dv22, *dv23, + *dv11, *dv12,*dv13, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + assert(fmv2->total_cost == fmv1->total_cost); + + fmv2->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = pos2; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = INTER; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = dv21->mvx; fmv2->aff1_mvy = dv21->mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + fmv2->aff1_dmvx = dv21->mvx - get2_v1[pred21].mvx; + fmv2->aff1_dmvy = dv21->mvy - get2_v1[pred21].mvy; + fmv2->aff2_dmvx = dv22->mvx - get2_v2[pred22].mvx; + fmv2->aff2_dmvy = dv22->mvy - get2_v2[pred22].mvy; + fmv2->aff3_dmvx = dv23->mvx - get2_v3[pred23].mvx; + fmv2->aff3_dmvy = dv23->mvy - get2_v3[pred23].mvy; + +// printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n",fmv1->aff2_dmvx,fmv1->aff2_dmvy); + + fmv1->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = -1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = INTER; + fmv1->is_predictor = NO; + fmv1->lifting_mode = IGNORED; + fmv1->aff1_mvx = (float)HUGE_VAL;fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL;fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL;fmv1->aff3_mvy = (float)HUGE_VAL; + }//If MSE + } + } +//INTER + +//AFF_MERGE MODE +//UP MERGE + // printf("BLOCK B\n"); + find_block(x,y-1,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,1);//BLOCK B + merg_aff_v1.mvx = *get1x; + merg_aff_v1.mvy = *get1y; + // printf("BLOCK D\n"); + find_block(x+xblk2-1,y-1,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);//BLOCK D + merg_aff_v2.mvx = *get1x; + merg_aff_v2.mvy = *get1y; + + if(merg_aff_v1.mvx != (float)HUGE_VAL && merg_aff_v1.mvy != (float)HUGE_VAL && + merg_aff_v2.mvx != (float)HUGE_VAL && merg_aff_v2.mvy != (float)HUGE_VAL){ + + mrg_cnt1 = 0; + + for(i = 0;i < 2; i++){ + if(get2_v3[i].mvx != (float)HUGE_VAL && get2_v3[i].mvy != (float)HUGE_VAL){ + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx2x, ctx2y, &merg_aff_v1, &merg_aff_v2, &get2_v3[i], dv21,dv22,dv23,xblk2, + yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,3); + + get_aff_sad_cost = best_sad; +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2,merg_aff_v1, merg_aff_v2, *dv23, merg_aff_v1, merg_aff_v2,*dv23, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_UP_LEN + 1 ) + info.lambda[t_level] * get_mode_coding_cost(RIGHT_CONNECTED_AFF,fmv2,info.bi_mv[t_level], + t_level) + get_bit_cost(info.lambda[t_level],dv23->mvx,dv23->mvy,get2_v3[i].mvx,get2_v3[i].mvy,ctx2x,ctx2y,info.subpel[t_level]); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + assert(fmv1->total_cost == fmv2->total_cost); + + if( ( (get_aff_total_cost < (fmv2->total_cost + 1 * info.lambda[t_level]) ) && fmv2->bi_mode <= 8 && + get_aff_sad_cost < (fmv2->sad_cost * aff_coef) ) || + (fmv2->bi_mode >= 9 && (get_aff_total_cost < fmv2->total_cost ) && get_aff_sad_cost < fmv2->sad_cost) ){ //affine decision + + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, merg_aff_v1, merg_aff_v2, *dv23, + merg_aff_v1, merg_aff_v2,*dv23, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + fmv2->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = mrg_cnt1; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = UP; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = merg_aff_v1.mvx;fmv2->aff1_mvy = merg_aff_v1.mvy; + fmv2->aff2_mvx = merg_aff_v2.mvx;fmv2->aff2_mvy = merg_aff_v2.mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + fmv2->aff3_dmvx = dv23->mvx - get2_v3[i].mvx; + fmv2->aff3_dmvy = dv23->mvy - get2_v3[i].mvy; + + // printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n",fmv2->aff3_dmvx,fmv2->aff3_dmvy); + + fmv1->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = -1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = UP; + fmv1->is_predictor = NO; + fmv1->lifting_mode = IGNORED; + fmv1->aff1_mvx = (float)HUGE_VAL;fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL;fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL;fmv1->aff3_mvy = (float)HUGE_VAL; + }//If MSE + } + + mrg_cnt1 ++; + } + } + } + +//LEFT MERGE + // printf("BLOCK C\n"); + find_block(x-1,y,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,0);//BLOCK C + merg_aff_v1.mvx = *get1x; + merg_aff_v1.mvy = *get1y; + // printf("BLOCK F\n"); + find_block(x-1,y+yblk2-1,fmv2_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);//BLOCK F + merg_aff_v2.mvx = *get1x; + merg_aff_v2.mvy = *get1y; + + if(merg_aff_v1.mvx != (float)HUGE_VAL && merg_aff_v1.mvy != (float)HUGE_VAL && + merg_aff_v2.mvx != (float)HUGE_VAL && merg_aff_v2.mvy != (float)HUGE_VAL){ + + mrg_cnt1 = 0; + + for(i = 0;i < 2; i++){ + if(get2_v2[i].mvx != (float)HUGE_VAL && get2_v2[i].mvy != (float)HUGE_VAL){ + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx2x, ctx2y, &merg_aff_v1, &get2_v2[i], &merg_aff_v2, dv21,dv22,dv23,xblk2,yblk2, + x,y,hor,ver,RIGHT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,2); + + get_aff_sad_cost = best_sad; +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, merg_aff_v1, *dv22, merg_aff_v2, merg_aff_v1, *dv22, merg_aff_v2, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + info.lambda[t_level] * get_mode_coding_cost(RIGHT_CONNECTED_AFF, + fmv2,info.bi_mv[t_level], t_level) + get_bit_cost(info.lambda[t_level],dv22->mvx,dv22->mvy,get2_v2[i].mvx,get2_v2[i].mvy, + ctx2x,ctx2y,info.subpel[t_level]); + + assert(fmv1->total_cost == fmv2->total_cost); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + if( ( (get_aff_total_cost < (fmv2->total_cost + 1 * info.lambda[t_level]) ) && fmv2->bi_mode <= 8 && + get_aff_sad_cost < (fmv2->sad_cost * aff_coef) ) || + (fmv2->bi_mode >= 9 && (get_aff_total_cost < fmv2->total_cost ) && get_aff_sad_cost < fmv2->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, merg_aff_v1, *dv22, merg_aff_v2, + merg_aff_v1, *dv22, merg_aff_v2, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + fmv2->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = mrg_cnt1; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = LEFT; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = merg_aff_v1.mvx;fmv2->aff1_mvy = merg_aff_v1.mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = merg_aff_v2.mvx;fmv2->aff3_mvy = merg_aff_v2.mvy; + + fmv2->aff2_dmvx = dv22->mvx - get2_v2[i].mvx; + fmv2->aff2_dmvy = dv22->mvy - get2_v2[i].mvy; + + // printf("fmv2->aff2_dmvx = %f, fmv2->aff2_dmvy = %f\n",fmv2->aff2_dmvx,fmv2->aff2_dmvy); + + fmv1->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = -1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = LEFT; + fmv1->is_predictor = NO; + fmv1->lifting_mode = IGNORED; + fmv1->aff1_mvx = (float)HUGE_VAL;fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL;fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL;fmv1->aff3_mvy = (float)HUGE_VAL; + }//If MSE + } + + mrg_cnt1 ++; + } + } + } +//MERGE mode + +/* TEST */ + if(pred21 >= 0 && pred22 >= 0 && pred23 >= 0 && do_inter == 1){ + if( (best_trans_mode == RIGHT_CONNECTED || best_trans_mode == RIGHT_PREDICTED || + (best_trans_mode == BLOCK_MERGING && trans_mvr.mvx != (float)HUGE_VAL && trans_mvl.mvx == (float)HUGE_VAL) ) && fmv2 != NULL){ + if(best_trans_sad < best_aff_sad_cost){ +// printf("right trans better, bi_mode = %d, x = %d, y = %d, xblk = %d, yblk = %d\naff_sad = %f, trans_sad = %f\n\n", +// best_trans_mode,x,y,xblk2,yblk2,best_aff_sad_cost,best_trans_sad); + + best_sad = delta_v_search(fr_cur, fr_ref1, fr_ref2, upframe1,upframe2,ctx2x, ctx2y, &trans_mvr, &trans_mvr, &trans_mvr, dv21,dv22,dv23,xblk2,yblk2,x,y, + hor,ver,RIGHT_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + + get_aff_sad_cost = best_sad; + + get_aff_bit_cost = get_bit_cost(info.lambda[t_level],dv21->mvx,dv21->mvy,trans_mvr.mvx,trans_mvr.mvy,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv22->mvx,dv22->mvy,trans_mvr.mvx,trans_mvr.mvy,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv23->mvx,dv23->mvy,trans_mvr.mvx,trans_mvr.mvy,ctx2x,ctx2y,info.subpel[t_level]); + + dv21->dmvx = dv21->mvx - trans_mvr.mvx; dv21->dmvy = dv21->mvy - trans_mvr.mvy; + dv22->dmvx = dv22->mvx - trans_mvr.mvx; dv22->dmvy = dv22->mvy - trans_mvr.mvy; + dv23->dmvx = dv23->mvx - trans_mvr.mvx; dv23->dmvy = dv23->mvy - trans_mvr.mvy; + +//Apply trans-based aff result if better + if(best_trans_mode == BLOCK_MERGING){ + + get_aff_bit_cost = get_aff_bit_cost + info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + + info.lambda[t_level] * get_mode_coding_cost(RIGHT_CONNECTED_AFF, fmv2,info.bi_mv[t_level], t_level); + + }else if(best_trans_mode == RIGHT_CONNECTED || best_trans_mode == RIGHT_PREDICTED){ + get_aff_bit_cost = get_aff_bit_cost + get_bit_cost(info.lambda[t_level],right_dmvx,right_dmvy,0,0,ctx2x,ctx2y,info.subpel[t_level]); + + get_aff_bit_cost = get_aff_bit_cost + info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + + info.lambda[t_level] * get_mode_coding_cost(RIGHT_CONNECTED_AFF, fmv2,info.bi_mv[t_level], t_level); + + }else + assert(0); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + +//decision making + if( ( (get_aff_total_cost < (fmv2->total_cost + 1 * info.lambda[t_level]) ) && fmv2->bi_mode <= 8 && + get_aff_sad_cost < (fmv2->sad_cost * aff_coef * t_coef) ) || + (fmv2->bi_mode >= 9 && (get_aff_total_cost < fmv2->total_cost ) && get_aff_sad_cost < fmv2->sad_cost) ){ + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*dv21, *dv22, *dv23, *dv11, *dv12, + *dv13, xblk2,yblk2,x,y,hor,ver,RIGHT_CONNECTED_AFF); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv2->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + + fmv2->aff_idx = -1; + + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = TRAN_P; + + if(best_trans_mode == BLOCK_MERGING) + fmv2->trans_pred_idx = DIR; + else{ + assert(best_trans_mode == RIGHT_CONNECTED); + fmv2->trans_pred_idx = INDIR; + } + + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + + fmv2->dmvx = right_dmvx; fmv2->dmvy = right_dmvy; + fmv2->aff1_mvx = dv21->mvx; fmv2->aff1_mvy = dv21->mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + fmv2->aff1_dmvx = dv21->dmvx; fmv2->aff1_dmvy = dv21->dmvy; + fmv2->aff2_dmvx = dv22->dmvx; fmv2->aff2_dmvy = dv22->dmvy; + fmv2->aff3_dmvx = dv23->dmvx; fmv2->aff3_dmvy = dv23->dmvy; + + + fmv1->bi_mode = (BiMode)RIGHT_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv1->aff_idx = -1; + + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = TRAN_P; + + if(best_trans_mode == BLOCK_MERGING) + fmv1->trans_pred_idx = DIR; + else{ + assert(best_trans_mode == RIGHT_CONNECTED); + fmv1->trans_pred_idx = INDIR; + } + + fmv1->is_predictor = NO; + fmv1->lifting_mode = IGNORED; + + fmv1->dmvx = (float)HUGE_VAL; fmv1->dmvy = (float)HUGE_VAL; + fmv1->aff1_mvx = (float)HUGE_VAL; fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL; fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL; fmv1->aff3_mvy = (float)HUGE_VAL; + }//If MSE + } + } + } + }//if pred +/* END OF TEST */ + + +//BI-DIRECTIONAL SEARCH +//AFF_DIRECT MODE + if(pos1 >= 0 && pos2 >= 0){ + best_aff_bit_cost = (float)HUGE_VAL; + best_aff_sad_cost = (float)HUGE_VAL; + best_aff_total_cost = best_aff_sad_cost + best_aff_bit_cost; + + for(round = 0;round < 3; round++){ + assert(get_v1[pred11].mvx != (float)HUGE_VAL && get_v1[pred11].mvy != (float)HUGE_VAL && get_v2[pred12].mvx != (float)HUGE_VAL && + get_v2[pred12].mvy != (float)HUGE_VAL && get_v3[pred13].mvx != (float)HUGE_VAL && get_v3[pred13].mvy != (float)HUGE_VAL); + + count = 0; + + //RIGHT SEARCH + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( get2_v1[i].mvx!=(float)HUGE_VAL && get2_v2[j].mvx!=(float)HUGE_VAL && get2_v3[k].mvx!=(float)HUGE_VAL && + get2_v1[i].mvy!=(float)HUGE_VAL && get2_v2[j].mvy!=(float)HUGE_VAL && get2_v3[k].mvy!=(float)HUGE_VAL ){ + get_aff_sad_cost = find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2,get_v1[pred11],get_v2[pred12],get_v3[pred13],get2_v1[i], + get2_v2[j],get2_v3[k],xblk2,yblk2,x,y,hor,ver, BI_CONNECTED_AFF,info.subpel[t_level],0); + get_aff_bit_cost = info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF, fmv2, info.bi_mv[t_level], t_level) + + info.lambda[t_level] * ((int)(aff_num1/4) + AFF_IDX_OFFSET) + info.lambda[t_level] * ((int)(aff_num2/4) + AFF_IDX_OFFSET) + info.lambda[t_level]*1; + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + if( (get_aff_total_cost < best_aff_total_cost) ){ + assert(get_aff_total_cost != (float)HUGE_VAL); + + best_aff_bit_cost = get_aff_bit_cost; + best_aff_sad_cost = get_aff_sad_cost; + best_aff_total_cost = get_aff_total_cost; + best_idx2 = i * 9 + j * 3 + k; + pred21 = i; + pred22 = j; + pred23 = k; + pos2 = count; +// printf("count = %d, length = %d\n",count, (int)(count/4) ); + } + count++; + } + } + } + } + + assert(get2_v1[pred21].mvx != (float)HUGE_VAL && get2_v1[pred21].mvy != (float)HUGE_VAL && get2_v2[pred22].mvx != (float)HUGE_VAL && + get2_v2[pred22].mvy != (float)HUGE_VAL && get2_v3[pred23].mvx != (float)HUGE_VAL && get2_v3[pred23].mvy != (float)HUGE_VAL); + + count = 0; + + //LEFT SEARCH + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( get_v1[i].mvx!=(float)HUGE_VAL && get_v2[j].mvx!=(float)HUGE_VAL && get_v3[k].mvx!=(float)HUGE_VAL && + get_v1[i].mvy!=(float)HUGE_VAL && get_v2[j].mvy!=(float)HUGE_VAL && get_v3[k].mvy!=(float)HUGE_VAL ){ + get_aff_sad_cost = find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2,get_v1[i],get_v2[j],get_v3[k],get2_v1[pred21], + get2_v2[pred22],get2_v3[pred23],xblk2,yblk2,x,y,hor,ver, BI_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF, fmv2, info.bi_mv[t_level], t_level) + + info.lambda[t_level] * ((int)(aff_num1/4) + AFF_IDX_OFFSET) + info.lambda[t_level] * ((int)(aff_num2/4) + AFF_IDX_OFFSET) + info.lambda[t_level]*1; + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + if( (get_aff_total_cost < best_aff_total_cost) ){ + assert(get_aff_total_cost != (float)HUGE_VAL); + + best_aff_bit_cost = get_aff_bit_cost; + best_aff_sad_cost = get_aff_sad_cost; + best_aff_total_cost = get_aff_total_cost; + best_idx1 = i * 9 + j * 3 + k; + pred11 = i; + pred12 = j; + pred13 = k; + pos1 = count; +// printf("count = %d, length = %d\n",count, (int)(count/4) ); + } + count++; + } + } + } + } + }//round + + if( ( (best_aff_total_cost < (fmv1->total_cost + 3 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + best_aff_sad_cost < (fmv1->sad_cost - 4 * info.lambda[t_level]) ) || + (fmv1->bi_mode >= 9 && (best_aff_total_cost < fmv1->total_cost ) && best_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var, get_v1[pred11],get_v2[pred12],get_v3[pred13],get2_v1[pred21], + get2_v2[pred22],get2_v3[pred23], xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + assert(fmv1->total_cost == fmv2->total_cost); + assert(pos1 >= 0 && pos1 <= 26); + assert(pos2 >= 0 && pos2 <= 26); + + assert(best_idx2 >= 0 && best_idx2 <= 26); + fmv2->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv2->sad_cost = best_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = best_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = pos2; + fmv2->direct_idx = DIRECT; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = get2_v1[pred21].mvx;fmv2->aff1_mvy = get2_v1[pred21].mvy; + fmv2->aff2_mvx = get2_v2[pred22].mvx;fmv2->aff2_mvy = get2_v2[pred22].mvy; + fmv2->aff3_mvx = get2_v3[pred23].mvx;fmv2->aff3_mvy = get2_v3[pred23].mvy; + + fmv1->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = pos1; + fmv1->direct_idx = DIRECT; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = get_v1[pred11].mvx;fmv1->aff1_mvy = get_v1[pred11].mvy; + fmv1->aff2_mvx = get_v2[pred12].mvx;fmv1->aff2_mvy = get_v2[pred12].mvy; + fmv1->aff3_mvx = get_v3[pred13].mvx;fmv1->aff3_mvy = get_v3[pred13].mvy; + }//If MSE + } + +//BI-DIRECTIONAL INTER + if(do_inter == 1){ + best_sad = delta_v_search_bi(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, ctx2x, ctx2y, &get_v1[pred11], &get_v2[pred12], &get_v3[pred13], + &get2_v1[pred21], &get2_v2[pred22], &get2_v3[pred23],dv11,dv12,dv13,dv21,dv22,dv23,xblk2,yblk2,x,y, + hor,ver,BI_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + + get_aff_sad_cost = best_sad; + +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, *dv11, *dv12, *dv13, *dv21, *dv22,*dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * ( (int)(pos1/4) + AFF_IDX_OFFSET ) + info.lambda[t_level] * ( (int)(pos2/4) + AFF_IDX_OFFSET )+ + get_bit_cost(info.lambda[t_level],dv11->mvx,dv11->mvy,get_v1[pred11].mvx,get_v1[pred11].mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,get_v2[pred12].mvx,get_v2[pred12].mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,get_v3[pred13].mvx,get_v3[pred13].mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv21->mvx,dv21->mvy,get2_v1[pred21].mvx,get2_v1[pred21].mvy,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv22->mvx,dv22->mvy,get2_v2[pred22].mvx,get2_v2[pred22].mvy,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv23->mvx,dv23->mvy,get2_v3[pred23].mvx,get2_v3[pred23].mvy,ctx2x,ctx2y,info.subpel[t_level]) + + info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF,fmv2,info.bi_mv[t_level], t_level) + (DIRECT_LEN + MERGE_LEN) * info.lambda[t_level]; + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + aff_sad_cache = get_aff_sad_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*dv11, *dv12, *dv13, + *dv21, *dv22, *dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + assert(fmv2->total_cost == fmv1->total_cost); + + fmv2->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = pos2; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = INTER; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = dv21->mvx; fmv2->aff1_mvy = dv21->mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + fmv2->aff1_dmvx = dv21->mvx - get2_v1[pred21].mvx; + fmv2->aff1_dmvy = dv21->mvy - get2_v1[pred21].mvy; + fmv2->aff2_dmvx = dv22->mvx - get2_v2[pred22].mvx; + fmv2->aff2_dmvy = dv22->mvy - get2_v2[pred22].mvy; + fmv2->aff3_dmvx = dv23->mvx - get2_v3[pred23].mvx; + fmv2->aff3_dmvy = dv23->mvy - get2_v3[pred23].mvy; + + // printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n",fmv1->aff2_dmvx,fmv1->aff2_dmvy); + + fmv1->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = pos1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = INTER; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = dv11->mvx; fmv1->aff1_mvy = dv11->mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff1_dmvx = dv11->mvx - get_v1[pred11].mvx; + fmv1->aff1_dmvy = dv11->mvy - get_v1[pred11].mvy; + fmv1->aff2_dmvx = dv12->mvx - get_v2[pred12].mvx; + fmv1->aff2_dmvy = dv12->mvy - get_v2[pred12].mvy; + fmv1->aff3_dmvx = dv13->mvx - get_v3[pred13].mvx; + fmv1->aff3_dmvy = dv13->mvy - get_v3[pred13].mvy; + }//If MSE + } + } +//INTER + +/* TEST */ + if(fmv2 != NULL){ + if( (best_trans_mode == BI_CONNECTED || +// best_trans_mode == PARALLEL || + (best_trans_mode == BLOCK_MERGING && trans_mvl.mvx != (float)HUGE_VAL && trans_mvr.mvx != (float)HUGE_VAL ) ) && do_inter == 1 ){ + if(best_trans_sad < best_aff_sad_cost){ +// printf("bi trans better, bi_mode = %d, x = %d, y = %d, xblk = %d, yblk = %d\naff_sad = %f, trans_sad = %f\n\n", +// best_trans_mode,x,y,xblk2,yblk2,best_aff_sad_cost,best_trans_sad); + + if(best_trans_mode == BI_CONNECTED || best_trans_mode == BLOCK_MERGING){ + best_sad = delta_v_search_bi(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, ctx2x, ctx2y, &trans_mvl, &trans_mvl, + &trans_mvl, &trans_mvr, &trans_mvr, &trans_mvr, dv11,dv12,dv13,dv21,dv22,dv23,xblk2,yblk2,x,y, + hor,ver,BI_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + }else{ + assert(best_trans_mode == PARALLEL); + + best_sad = delta_v_search_bi(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, ctx2x, ctx2y, &trans_mvl, &trans_mvl, &trans_mvl, + &trans_mvr, &trans_mvr, &trans_mvr, dv11,dv12,dv13,dv21,dv22,dv23,xblk2,yblk2,x,y, + hor,ver,BI_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + } + + get_aff_sad_cost = best_sad; + + if(1){ + get_aff_bit_cost = get_bit_cost(info.lambda[t_level],dv11->mvx,dv11->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv21->mvx,dv21->mvy,trans_mvr.mvx,trans_mvr.mvy,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv22->mvx,dv22->mvy,trans_mvr.mvx,trans_mvr.mvy,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv23->mvx,dv23->mvy,trans_mvr.mvx,trans_mvr.mvy,ctx2x,ctx2y,info.subpel[t_level]); + }else{ + assert(0); + get_aff_bit_cost = get_bit_cost(info.lambda[t_level],dv11->mvx,dv11->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,trans_mvl.mvx,trans_mvl.mvy,ctx1x,ctx1y,info.subpel[t_level]); + } + + dv11->dmvx = dv11->mvx - trans_mvl.mvx; dv11->dmvy = dv11->mvy - trans_mvl.mvy; + dv12->dmvx = dv12->mvx - trans_mvl.mvx; dv12->dmvy = dv12->mvy - trans_mvl.mvy; + dv13->dmvx = dv13->mvx - trans_mvl.mvx; dv13->dmvy = dv13->mvy - trans_mvl.mvy; + + dv21->dmvx = dv21->mvx - trans_mvr.mvx; dv21->dmvy = dv21->mvy - trans_mvr.mvy; + dv22->dmvx = dv22->mvx - trans_mvr.mvx; dv22->dmvy = dv22->mvy - trans_mvr.mvy; + dv23->dmvx = dv23->mvx - trans_mvr.mvx; dv23->dmvy = dv23->mvy - trans_mvr.mvy; + + if(best_trans_mode == BLOCK_MERGING){ + + get_aff_bit_cost = get_aff_bit_cost + info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + + info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF, fmv2,info.bi_mv[t_level], t_level); + + }else if(best_trans_mode == BI_CONNECTED){ + get_aff_bit_cost = get_aff_bit_cost + get_bit_cost(info.lambda[t_level],right_dmvx,right_dmvy,0,0,ctx2x,ctx2y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],left_dmvx,left_dmvy,0,0,ctx1x,ctx1y,info.subpel[t_level]); + + get_aff_bit_cost = get_aff_bit_cost + info.lambda[t_level] * ( DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 ) + + info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF, fmv2,info.bi_mv[t_level], t_level); + + }else + assert(0); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + +//decision making + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef * t_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*dv11, *dv12, *dv13, *dv21, *dv22, + *dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv2->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = TRAN_P; + + if(best_trans_mode == BLOCK_MERGING) + fmv2->trans_pred_idx = DIR; + else{ + assert(best_trans_mode == BI_CONNECTED || best_trans_mode == PARALLEL); + fmv2->trans_pred_idx = INDIR; + } + + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + + fmv2->dmvx = right_dmvx; fmv2->dmvy = right_dmvy; + fmv2->aff1_mvx = dv21->mvx; fmv2->aff1_mvy = dv21->mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + fmv2->aff1_dmvx = dv21->dmvx; fmv2->aff1_dmvy = dv21->dmvy; + fmv2->aff2_dmvx = dv22->dmvx; fmv2->aff2_dmvy = dv22->dmvy; + fmv2->aff3_dmvx = dv23->dmvx; fmv2->aff3_dmvy = dv23->dmvy; + + + + fmv1->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv1->aff_idx = -1; + + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = TRAN_P; + + if(best_trans_mode == BLOCK_MERGING) + fmv1->trans_pred_idx = DIR; + else{ + assert(best_trans_mode == BI_CONNECTED || best_trans_mode == PARALLEL); + fmv1->trans_pred_idx = INDIR; + } + + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + + fmv1->dmvx = left_dmvx; fmv1->dmvy = left_dmvy; + fmv1->aff1_mvx = dv11->mvx; fmv1->aff1_mvy = dv11->mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff1_dmvx = dv11->dmvx; fmv1->aff1_dmvy = dv11->dmvy; + fmv1->aff2_dmvx = dv12->dmvx; fmv1->aff2_dmvy = dv12->dmvy; + fmv1->aff3_dmvx = dv13->dmvx; fmv1->aff3_dmvy = dv13->dmvy; + }//If MSE + } + } + } + }//if fmv2 + +/* END OF TEST */ + + }// if(pos1 >= 0 && pos2 >= 0) + +//BI-DIRECTIONAL MERGE +//BI-DIRECTIONAL PARALLEL MERGE + if(pos1 >= 0){ + best_sad = delta_v_search_prl(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, ctx1x, ctx1y, ctx2x, ctx2y, &get_v1[pred11], &get_v2[pred12], &get_v3[pred13], + dv11,dv12,dv13,dv21,dv22,dv23,xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF,info.lambda[t_level],info.subpel[t_level],t_level,0); + + get_aff_sad_cost = best_sad; + +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, *dv11, *dv12, *dv13, *dv21, *dv22, *dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF, info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * ( (int)(pos1/4)+AFF_IDX_OFFSET ) + (DIRECT_LEN+MERGE_LEN+MERGE_DIR_LEN) * info.lambda[t_level] + + get_bit_cost(info.lambda[t_level],dv11->mvx,dv11->mvy,get_v1[pred11].mvx,get_v1[pred11].mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,get_v2[pred12].mvx,get_v2[pred12].mvy,ctx1x,ctx1y,info.subpel[t_level]) + + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,get_v3[pred13].mvx,get_v3[pred13].mvy,ctx1x,ctx1y,info.subpel[t_level]) + + info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF,fmv2,info.bi_mv[t_level], t_level); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,*dv11, *dv12, *dv13, + *dv21, *dv22, *dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + assert(dv11->mvx == (-1)*dv21->mvx && dv11->mvy == (-1)*dv21->mvy && + dv12->mvx == (-1)*dv22->mvx && dv12->mvy == (-1)*dv22->mvy && + dv13->mvx == (-1)*dv23->mvx && dv13->mvy == (-1)*dv23->mvy ); + + assert(fmv2->total_cost == fmv1->total_cost); + + fmv2->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = -1; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = PAL_L; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = dv21->mvx; fmv2->aff1_mvy = dv21->mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + // printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n",fmv1->aff2_dmvx,fmv1->aff2_dmvy); + + fmv1->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = pos1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = PAL_L; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = dv11->mvx; fmv1->aff1_mvy = dv11->mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff1_dmvx = dv11->mvx - get_v1[pred11].mvx; + fmv1->aff1_dmvy = dv11->mvy - get_v1[pred11].mvy; + fmv1->aff2_dmvx = dv12->mvx - get_v2[pred12].mvx; + fmv1->aff2_dmvy = dv12->mvy - get_v2[pred12].mvy; + fmv1->aff3_dmvx = dv13->mvx - get_v3[pred13].mvx; + fmv1->aff3_dmvy = dv13->mvy - get_v3[pred13].mvy; + }//If MSE + } + } +//BI-DIRECTIONAL PARALLEL MERGE + +//UP MERGE + // printf("BLOCK B\n"); + find_block(x,y-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,0,1);//BLOCK B + merg_aff_v1.mvx = *get1x; + merg_aff_v1.mvy = *get1y; + // printf("BLOCK D\n"); + find_block(x+xblk2-1,y-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);//BLOCK D + merg_aff_v2.mvx = *get1x; + merg_aff_v2.mvy = *get1y; + + // printf("BLOCK B\n"); + find_block(x,y-1,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,0,1);//BLOCK B + merg_aff2_v1.mvx = *get2x; + merg_aff2_v1.mvy = *get2y; + // printf("BLOCK D\n"); + find_block(x+xblk2-1,y-1,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,1);//BLOCK D + merg_aff2_v2.mvx = *get2x; + merg_aff2_v2.mvy = *get2y; + + if(merg_aff_v1.mvx != (float)HUGE_VAL && merg_aff_v1.mvy != (float)HUGE_VAL && merg_aff_v2.mvx != (float)HUGE_VAL && + merg_aff_v2.mvy != (float)HUGE_VAL && merg_aff2_v1.mvx != (float)HUGE_VAL && merg_aff2_v1.mvy != (float)HUGE_VAL && + merg_aff2_v2.mvx != (float)HUGE_VAL && merg_aff2_v2.mvy != (float)HUGE_VAL){ + + mrg_cnt1 = 0; + + for(i = 0;i < 2; i++){ + + mrg_cnt2 = 0; + + for(j = 0;j < 2; j++){ + if(get_v3[i].mvx != (float)HUGE_VAL && get_v3[i].mvy != (float)HUGE_VAL && + get2_v3[j].mvx != (float)HUGE_VAL && get2_v3[j].mvy != (float)HUGE_VAL){ + + best_sad = delta_v_search_bi(fr_cur,fr_ref1,fr_ref2,upframe1,upframe2, ctx1x, ctx1y, ctx2x, ctx2y, &merg_aff_v1, &merg_aff_v2, &get_v3[i], &merg_aff2_v1, + &merg_aff2_v2, &get2_v3[j], dv11,dv12,dv13,dv21,dv22,dv23,xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF,info.lambda[t_level], + info.subpel[t_level],t_level,3); + + get_aff_sad_cost = best_sad; + +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, merg_aff_v1, merg_aff_v2, *dv13, merg_aff2_v1, merg_aff2_v2,*dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * (DIRECT_LEN + MERGE_LEN + MERGE_DIR_UP_LEN + 1 + 1) + info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF, + fmv2,info.bi_mv[t_level],t_level) + get_bit_cost(info.lambda[t_level],dv13->mvx,dv13->mvy,get_v3[i].mvx,get_v3[i].mvy,ctx1x, + ctx1y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],dv23->mvx,dv23->mvy,get2_v3[j].mvx,get2_v3[j].mvy,ctx2x, + ctx2y,info.subpel[t_level]); + + assert(fmv1->total_cost == fmv2->total_cost); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,merg_aff_v1, merg_aff_v2, *dv13, + merg_aff2_v1, merg_aff2_v2,*dv23, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv2->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = mrg_cnt2; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = UP; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = merg_aff2_v1.mvx;fmv2->aff1_mvy = merg_aff2_v1.mvy; + fmv2->aff2_mvx = merg_aff2_v2.mvx;fmv2->aff2_mvy = merg_aff2_v2.mvy; + fmv2->aff3_mvx = dv23->mvx; fmv2->aff3_mvy = dv23->mvy; + + fmv2->aff3_dmvx = dv23->mvx - get2_v3[j].mvx; + fmv2->aff3_dmvy = dv23->mvy - get2_v3[j].mvy; + + // printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n",fmv2->aff3_dmvx,fmv2->aff3_dmvy); + + fmv1->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = mrg_cnt1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = UP; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = merg_aff_v1.mvx;fmv1->aff1_mvy = merg_aff_v1.mvy; + fmv1->aff2_mvx = merg_aff_v2.mvx;fmv1->aff2_mvy = merg_aff_v2.mvy; + fmv1->aff3_mvx = dv13->mvx; fmv1->aff3_mvy = dv13->mvy; + + fmv1->aff3_dmvx = dv13->mvx - get_v3[i].mvx; + fmv1->aff3_dmvy = dv13->mvy - get_v3[i].mvy; + }//If MSE + } + + mrg_cnt2 ++; + } + }//j + + if(get_v3[i].mvx != (float)HUGE_VAL && get_v3[i].mvy != (float)HUGE_VAL) + mrg_cnt1 ++; + }//i + } +//LEFT MERGE + // printf("BLOCK C\n"); + find_block(x-1,y,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,0);//BLOCK C + merg_aff_v1.mvx = *get1x; + merg_aff_v1.mvy = *get1y; + // printf("BLOCK F\n"); + find_block(x-1,y+yblk2-1,fmv1_array,info,t_level,get1x,get1y,&get_xblk,&get_yblk,1,1);//BLOCK F + merg_aff_v2.mvx = *get1x; + merg_aff_v2.mvy = *get1y; + + // printf("BLOCK C\n"); + find_block(x-1,y,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,0);//BLOCK C + merg_aff2_v1.mvx = *get2x; + merg_aff2_v1.mvy = *get2y; + // printf("BLOCK F\n"); + find_block(x-1,y+yblk2-1,fmv2_array,info,t_level,get2x,get2y,&get_xblk,&get_yblk,1,1);//BLOCK F + merg_aff2_v2.mvx = *get2x; + merg_aff2_v2.mvy = *get2y; + + if(merg_aff_v1.mvx != (float)HUGE_VAL && merg_aff_v1.mvy != (float)HUGE_VAL && merg_aff_v2.mvx != (float)HUGE_VAL && + merg_aff_v2.mvy != (float)HUGE_VAL && merg_aff2_v1.mvx != (float)HUGE_VAL && merg_aff2_v1.mvy != (float)HUGE_VAL && + merg_aff2_v2.mvx != (float)HUGE_VAL && merg_aff2_v2.mvy != (float)HUGE_VAL){ + + mrg_cnt1 = 0; + + for(i = 0;i < 2; i++){ + + mrg_cnt2 = 0; + + for(j = 0;j < 2; j++){ + if(get_v2[i].mvx != (float)HUGE_VAL && get_v2[i].mvy != (float)HUGE_VAL && + get2_v2[j].mvx != (float)HUGE_VAL && get2_v2[j].mvy != (float)HUGE_VAL){ + + best_sad = delta_v_search_bi(fr_cur,fr_ref1,fr_ref2,upframe1,upframe2, ctx1x, ctx1y, ctx2x, ctx2y, &merg_aff_v1, &get_v2[i], &merg_aff_v2, &merg_aff2_v1, + &get2_v2[j], &merg_aff2_v2, dv11,dv12,dv13,dv21,dv22,dv23,xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF,info.lambda[t_level], + info.subpel[t_level],t_level,2); + + get_aff_sad_cost = best_sad; + +// find_affine_SAD(fr_cur, fr_ref1, fr_ref2,upframe1,upframe2, merg_aff_v1, *dv12, merg_aff_v2, merg_aff2_v1, *dv22,merg_aff2_v2,xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF,info.subpel[t_level],0); + + get_aff_bit_cost = info.lambda[t_level] * (DIRECT_LEN + MERGE_LEN + MERGE_DIR_LEN + 1 + 1) + info.lambda[t_level] * get_mode_coding_cost(BI_CONNECTED_AFF, + fmv2,info.bi_mv[t_level],t_level) + get_bit_cost(info.lambda[t_level],dv12->mvx,dv12->mvy,get_v2[i].mvx,get_v2[i].mvy,ctx1x, + ctx1y,info.subpel[t_level]) + get_bit_cost(info.lambda[t_level],dv22->mvx,dv22->mvy,get2_v2[j].mvx,get2_v2[j].mvy,ctx2x, + ctx2y,info.subpel[t_level]); + + assert(fmv1->total_cost == fmv2->total_cost); + + get_aff_total_cost = get_aff_sad_cost + get_aff_bit_cost; + + if( ( (get_aff_total_cost < (fmv1->total_cost + 1 * info.lambda[t_level]) ) && fmv1->bi_mode <= 8 && + get_aff_sad_cost < (fmv1->sad_cost * aff_coef) ) || + (fmv1->bi_mode >= 9 && (get_aff_total_cost < fmv1->total_cost ) && get_aff_sad_cost < fmv1->sad_cost) ){ //affine decision + + aff_mse = find_affine_MSE(fr_cur,fr_ref1,fr_ref2,&aff_ref_var,merg_aff_v1, *dv12, merg_aff_v2, + merg_aff2_v1, *dv22, merg_aff2_v2, xblk2,yblk2,x,y,hor,ver,BI_CONNECTED_AFF); + +// printf("aff_mse = %f, aff_ref_var = %f, aff_var = %f\n",aff_mse,aff_ref_var,aff_var); + + if( ( aff_mse < IBLOCK_FACTOR * aff_var && + aff_mse < IBLOCK_FACTOR * aff_ref_var ) + || aff_mse < NOISE_VAR * pow( LPW4[1], ( float )t_level ) ){ + + fmv2->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv2->sad_cost = get_aff_sad_cost; + fmv2->mse = aff_mse; + fmv2->bit_cost = get_aff_bit_cost; + fmv2->total_cost = fmv2->sad_cost + fmv2->bit_cost; + fmv2->aff_idx = mrg_cnt2; + fmv2->direct_idx = INDIRECT; + fmv2->merge_idx = MERGE; + fmv2->merge_dir = LEFT; + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + fmv2->aff1_mvx = merg_aff2_v1.mvx;fmv2->aff1_mvy = merg_aff2_v1.mvy; + fmv2->aff2_mvx = dv22->mvx; fmv2->aff2_mvy = dv22->mvy; + fmv2->aff3_mvx = merg_aff2_v2.mvx;fmv2->aff3_mvy = merg_aff2_v2.mvy; + + + fmv2->aff2_dmvx = dv22->mvx - get2_v2[j].mvx; + fmv2->aff2_dmvy = dv22->mvy - get2_v2[j].mvy; + + // printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n",fmv2->aff3_dmvx,fmv2->aff3_dmvy); + + fmv1->bi_mode = (BiMode)BI_CONNECTED_AFF; + + fmv1->sad_cost = fmv2->sad_cost; + fmv1->mse = aff_mse; + fmv1->bit_cost = fmv2->bit_cost; + fmv1->total_cost = fmv1->sad_cost + fmv1->bit_cost; + fmv1->aff_idx = mrg_cnt1; + fmv1->direct_idx = INDIRECT; + fmv1->merge_idx = MERGE; + fmv1->merge_dir = LEFT; + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + fmv1->aff1_mvx = merg_aff_v1.mvx;fmv1->aff1_mvy = merg_aff_v1.mvy; + fmv1->aff2_mvx = dv12->mvx; fmv1->aff2_mvy = dv12->mvy; + fmv1->aff3_mvx = merg_aff_v2.mvx;fmv1->aff3_mvy = merg_aff_v2.mvy; + + + fmv1->aff2_dmvx = dv12->mvx - get_v2[i].mvx; + fmv1->aff2_dmvy = dv12->mvy - get_v2[i].mvy; + }//If MSE + } + + mrg_cnt2 ++; + } + }//j + + if(get_v2[i].mvx != (float)HUGE_VAL && get_v2[i].mvy != (float)HUGE_VAL) + mrg_cnt1 ++; + }//i + } + +//MERGE MODE + free(block_buff1); + free(block_buff2); + + }//if fmv2 != NULL + +}// if best mode + + delete dv11; + delete dv12; + delete dv13; + + delete dv21; + delete dv22; + delete dv23; + + delete get1x; + delete get1y; + delete get2x; + delete get2y; + delete get3x; + delete get3y; + +#endif + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + if (xblk==8 || xblk==4) // directional IBLOCK detection + { + float fadditional_penalty = 0; // to restrict the drift effect from directional IBLOCK + int mode_bits; + tmv1.mvx = tmv1.mvy = (float)HUGE_VAL; + tmv1.total_cost = tmv1.sad_cost = tmv1.bit_cost = (float)HUGE_VAL; + // fmv1_array the root of the mv quad-tree + directional_iblock_detection(info, fmv1_array, fr_cur, x, y, xblk, yblk, hor, ver, t_level, + &tmv1, &fadditional_penalty); + // the total cost has been updated, i.e. there is a valid spatial mode + // otherwise there does not exist a valid spatial mode + if (tmv1.total_cost!= (float)HUGE_VAL) + { + mode_bits = get_mode_coding_cost(DIRECTIONAL_IBLOCK, fmv2, info.bi_mv[t_level], t_level ); + assert(mode_bits>0); + mode_coding_cost = (DIRECTIONAL_IBLOCK_BIAS+fadditional_penalty)*info.lambda[t_level] * mode_bits; + tmv1.bit_cost += mode_coding_cost; + tmv1.total_cost += mode_coding_cost; + + // update the information in fmv1 and fmv2 + v1 = &fmv1->mode_info[DIRECTIONAL_IBLOCK]; + v1->is_valid = YES; + v1->is_predictor = NO; + v1->mvx = v1->mvy = (float)HUGE_VAL; + v1->iblock_spatial_mode = tmv1.iblock_spatial_mode; + v1->sad_cost = tmv1.sad_cost; + v1->bit_cost = tmv1.bit_cost; + v1->total_cost = tmv1.total_cost; + + if (fmv2 != NULL) { + v2 = &fmv2->mode_info[DIRECTIONAL_IBLOCK]; + v2->is_valid = YES; + v2->is_predictor = NO; + v2->mvx = v2->mvy = (float)HUGE_VAL; + v2->iblock_spatial_mode = tmv1.iblock_spatial_mode; + v2->sad_cost = v1->sad_cost; + v2->bit_cost = v1->bit_cost; + v2->total_cost = v1->total_cost; + } + // best mode is replaced by DIRECTIONAL_IBLOCK + if ( fmv1->mode_info[best_mode].total_cost>tmv1.total_cost) + { + fmv1->bi_mode = DIRECTIONAL_IBLOCK; + fmv1->lifting_mode = left_mode[DIRECTIONAL_IBLOCK]; + fmv1->is_predictor = NO; + fmv1->mvx = fmv1->mvy = (float)HUGE_VAL; + fmv1->iblock_spatial_mode = v1->iblock_spatial_mode; + fmv1->sad_cost = v1->sad_cost; + fmv1->bit_cost = v1->bit_cost; + fmv1->total_cost = v1->total_cost; + fmv1->propagate_iblk = (fadditional_penalty>0) ? 1: 0; + if (fmv2 != NULL) { + fmv2->bi_mode = DIRECTIONAL_IBLOCK; + fmv2->lifting_mode = right_mode[DIRECTIONAL_IBLOCK]; + fmv2->is_predictor = NO; + fmv2->mvx = fmv2->mvy = (float)HUGE_VAL; + fmv2->iblock_spatial_mode = v2->iblock_spatial_mode; + fmv2->sad_cost = v2->sad_cost; + fmv2->bit_cost = v2->bit_cost; + fmv2->total_cost = v2->total_cost; + fmv1->propagate_iblk = (fadditional_penalty>0) ? 1: 0; + } + } + } + } +#endif + + delete tv11; + delete tv12; + delete tv13; + + delete tv21; + delete tv22; + delete tv23; + +} \ No newline at end of file diff --git a/Interframe EZBC/TempSub/src/mv_ec.cpp b/Interframe EZBC/TempSub/src/mv_ec.cpp new file mode 100644 index 0000000..e0fec97 --- /dev/null +++ b/Interframe EZBC/TempSub/src/mv_ec.cpp @@ -0,0 +1,548 @@ +#include +#include +#include +#include +#include "mv_ec.h" +#include "golomb.h" +#include "binarcode.h" +#define EXTERN +#include "arcode.h" +#include "bme_tools.h" +#include "mv_statistics.h" + +int buffer, bits_to_go, garbage_bits, outbyte, inbyte; +FILE *fptmp; +extern FILE *fpbit; + +int numSymbols = -1; +coderType theCoder = coderType(-1); +videoinfo theInfo; +int theWrite = -1; +long int mvBytes; + +/************************************************************************** + * Initialization for context adaptive binary arithmetic coder * + **************************************************************************/ + +const int numSeparateBins = 3; // number of bins with own context models + // additional models for + // a) remaining bins + // b) sign bit +const int multiContexts[numSeparateBins + 2] = {1, 0, 0, 0, 0}; + +const int initFreqDef[2] = {1, 1}; +const int *initFreq[12] = {initFreqDef, initFreqDef, initFreqDef, + initFreqDef, initFreqDef, initFreqDef, + initFreqDef, initFreqDef, initFreqDef, + initFreqDef, initFreqDef, initFreqDef}; + +/****************************************************************************/ + +void write_number(); +long int read_number(int with); + +// save 2 bytes for the splitted motion vector bits +void write_splitted_number(int outputbyte, FILE *fp) +{ + int tmpbyte; + tmpbyte = (outputbyte & 0xff00) >>8; putc(tmpbyte, fp); + tmpbyte = outputbyte & 0x00ff; putc(tmpbyte, fp); + return; +} + + + + + +void done_splitted_bytes(unsigned char store_splitted_bytes[65535], + unsigned int splitted_byte_num, videoinfo info, + int t_level) +{ + int i; + FILE *fpbit_split; + + // open the bitfile and copy the number of data + bit data + if (!(fpbit_split = fopen(info.bitname, "a+b"))) + { + printf("append_bit: %s\n", info.bitname); + exit(1); + } + + if(splitted_byte_num<0 || splitted_byte_num>=0xffff){ + printf("splitted motion vector bits are not valid---%d!\n", splitted_byte_num); + getchar(); + exit(1); + } + + write_splitted_number(splitted_byte_num, fpbit_split); + + for(i=0 ; i<(int)splitted_byte_num ; i++) + putc(store_splitted_bytes[i], fpbit_split); + + fclose(fpbit_split); +} + +// 读取两个字节 +unsigned int read_splitted_number(FILE *fp) +{ + int tmpbyte; + unsigned int inputbyte; + + tmpbyte = getc( fp );// 获得一个字符 + inputbyte = tmpbyte & 0xff; + + inputbyte <<= 8; + inputbyte += getc( fp ); + + return inputbyte; +} + + +void get_splitted_bytes(unsigned char *store_splitted_bytes, + unsigned int *splitted_byte_num, videoinfo info, + int t_level, FILE *fpbit, long int starting_pos) +{ + int i; + + fseek(fpbit, starting_pos, SEEK_SET); + *splitted_byte_num = read_splitted_number(fpbit);// 数量 + for(i=0 ; i<(int)(*splitted_byte_num) ; i++) // + store_splitted_bytes[i] = getc(fpbit); +} + + +/****************************************************************************/ +/* append_bit() */ +/****************************************************************************/ +void append_bit(char *bitname, char *tmpname, int with) +{ + int i; + + /* open the bitfile and copy the number of data + bit data */ + if (!(fpbit = fopen(bitname, "a+b"))) + { + printf("append_bit: %s\n", bitname); + exit(1); + } + if (!(fptmp = fopen(tmpname, "rb"))) + { + printf("append_bit: %s\n", tmpname); + exit(1); + } + + /* write the number of byte and copy data */ + if (with) + write_number(); + + for (i = 0; i < outbyte; i++) + putc(getc(fptmp), fpbit); + + fclose(fpbit); + fclose(fptmp); + + if (with) + { + outbyte += 4; + } +} + +/****************************************************************************/ +/* arencode_init() */ +/****************************************************************************/ +void ec_enc_init(videoinfo info, coderType coder, int symbols, int contexts, + int write) +{ + assert(theWrite < 0 && theCoder < 0 && numSymbols < 0); + assert(write >= 0); + + numSymbols = symbols; + theCoder = coder; + theInfo = info; + theWrite = write; + + switch(theCoder) { + case AR_NARY: + arencode_init(symbols, contexts, NULL); + break; + case AR_BINARY: + binar_enc_init(contexts, numSeparateBins, multiContexts, initFreq); + break; + case GOLOMB: + golomb_init(); + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } + + /* open the bitfile */ + if (theWrite > 0) + { + if (!(fptmp = fopen(info.tmpname, "wb"))) + { + printf("ec_enc_init: %s\n", info.tmpname); + exit(1); + } + } + + /* initialize variables */ + buffer = 0; + bits_to_go = 8; + outbyte = 0; +} + +/****************************************************************************/ +/* arencode_end() */ +/****************************************************************************/ +void ec_enc_end1() +{ + assert(theWrite >= 0 && theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + arencode_end(); + break; + case AR_BINARY: + binar_enc_end(); + break; + case GOLOMB: + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} + +void ec_enc_end2() +{ + if (theWrite > 0) + { + if (bits_to_go < 8) + { + putc(buffer >> bits_to_go, fptmp); + outbyte++; +// mv_res_bits += (8 - bits_to_go); + } + fclose(fptmp); + + /* write to the bit file */ + append_bit(theInfo.bitname, theInfo.tmpname, 1); +// mv_res_bits += 32; + } + + theCoder = coderType(-1); + theWrite = -1; + numSymbols = -1; +} + +/****************************************************************************/ +/* ardecode_init() */ +/****************************************************************************/ +long int ec_dec_preinit(FILE *fp) +{ + assert(fp != NULL); + + fpbit = fp; + + mvBytes = read_number(1); + + /* initialize variables */ + // buffer = 0; + bits_to_go = 0; + garbage_bits = 0; + + return mvBytes; +} + + +void ec_dec_init(coderType coder, int symbols, int contexts) +{ + assert(theWrite < 0 && theCoder < 0 && numSymbols < 0); + + theCoder = coder; + numSymbols = symbols; + + switch(theCoder) { + case AR_NARY: + ardecode_init(symbols, contexts, NULL); + break; + case AR_BINARY: + binar_dec_init(contexts, numSeparateBins, multiContexts, initFreq); + break; + case GOLOMB: + golomb_init(); + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} + +/****************************************************************************/ +/* ardecode_end() */ +/****************************************************************************/ +void ec_dec_end1(){ + assert(theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + ardecode_end(); + break; + case AR_BINARY: + binar_dec_end(); + break; + case GOLOMB: + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} +long int ec_dec_end2() +{ + /* read if there is something left */ + while (inbyte > 0) + { + getc(fpbit); + inbyte--; + } + + theCoder = coderType(-1); + theWrite = -1; + numSymbols = -1; + + return mvBytes; +} + +void ec_encode_word(int word, int context) +{ + assert(theWrite >= 0 && theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + encode_word(word + numSymbols / 2, context); + break; + case AR_BINARY: + binar_encode_word(word, context); + break; + case GOLOMB: + mv_res_bits += golomb_encode_word((word > 0) ? (word * 2 - 1) : (-word * 2), 1); + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} + +int ec_decode_word(int context) +{ + int word; + + assert(theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + return decode_word(context) - numSymbols / 2; + break; + case AR_BINARY: + return binar_decode_word(context); + break; + case GOLOMB: + word = golomb_decode_word(); + return (word % 2) ? (word / 2 + 1) : (-word / 2); + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } + + return -1; +} + +/****************************************************************************/ +/* update_model() */ +/****************************************************************************/ +void ec_update_model(int word, int context) +{ + assert(theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + update_model(word + numSymbols / 2, context); + break; + case AR_BINARY: + binar_update_model(word, context); + break; + case GOLOMB: + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} + +float ec_get_expected_length(int word, int context) +{ + assert(theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + return get_expected_length(word + numSymbols / 2, context); + break; + case AR_BINARY: + return binar_get_expected_length(word, context); + break; + case GOLOMB: + return (float)golomb_encode_word((word > 0) ? (word * 2 - 1) : (-word * 2), 0); + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } + + return -1.; +} + +void ec_freeze() +{ + assert(theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + printf("freezing is not yet implemented for AR_NARY\n"); + exit(1); + break; + case AR_BINARY: + printf("freezing is not yet implemented for AR_BINARY\n"); + exit(1); + break; + case GOLOMB: + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} + +void ec_unfreeze(int keep_current_states) +{ + assert(theCoder >= 0 && numSymbols >= 0); + + switch(theCoder) { + case AR_NARY: + printf("unfreezing is not yet implemented for AR_NARY\n"); + exit(1); + break; + case AR_BINARY: + printf("unfreezing is not yet implemented for AR_BINARY\n"); + exit(1); + break; + case GOLOMB: + break; + default: + printf("illegal codec in ec_enc_init.\n"); + exit(1); + break; + } +} + +void ec_get_contexts(int *ctx_x, int *ctx_y, vector_ptr fmv, int x, int y, + videoinfo info, int t_level, int blk_thresh) +{ + float dmvx_hor, dmvy_hor, dmvx_ver, dmvy_ver, dmvx_dia, dmvy_dia; + enum FLAG ispred_hor, ispred_ver, ispred_dia; + float e_x, e_y; + + get_dmv(&dmvx_hor, &dmvy_hor, &ispred_hor, fmv, x - 1, y, info, t_level, blk_thresh); + get_dmv(&dmvx_ver, &dmvy_ver, &ispred_ver, fmv, x, y - 1, info, t_level, blk_thresh); + get_dmv(&dmvx_dia, &dmvy_dia, &ispred_dia, fmv, x - 1, y - 1, info, t_level, blk_thresh); + + if(ispred_hor == NO) dmvx_hor = dmvy_hor = 0.; + if(ispred_ver == NO) dmvx_ver = dmvy_ver = 0.; + if(ispred_dia == NO) dmvx_dia = dmvy_dia = 0.; + + e_x = float(fabs(dmvx_hor) + fabs(dmvx_ver)); + e_y = float(fabs(dmvy_hor) + fabs(dmvy_ver)); + + if (e_x < 3) { + *ctx_x = 0; + } else if (e_x > 15) { + *ctx_x = 1; + } else { + *ctx_x = 2; + } + + if (e_y < 3) { + *ctx_y = 0; + } else if (e_y > 15) { + *ctx_y = 1; + } else { + *ctx_y = 2; + } + + // mvStat_setCTX(dmvx_hor, dmvy_hor, + // dmvx_ver, dmvy_ver, + // dmvx_dia, dmvy_dia); +} + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +void encode_init(videoinfo info) +{ + /* open the bitfile */ + + if (!(fptmp = fopen(info.tmpname, "wb"))) + { + printf("can not open: %s\n", info.tmpname); + exit(1); + } + + /* initialize variables */ + buffer = 0; + bits_to_go = 8; + outbyte = 0; + +} + +void encode_end(int with, videoinfo info) +{ + if (bits_to_go < 8) + { + putc(buffer >> bits_to_go, fptmp); + outbyte++; + } + fclose(fptmp); + + /* write to the bit file */ + append_bit(info.bitname, info.tmpname, with); +} + +void decode_init() +{ +// int i, bit; + + garbage_bits = 0; + bits_to_go = 0; +} + +void decode_end() +{ + /* read if there is something left */ + while (inbyte > 0) + { + getc(fpbit); + inbyte--; + } +} diff --git a/Interframe EZBC/TempSub/src/mv_statistics.cpp b/Interframe EZBC/TempSub/src/mv_statistics.cpp new file mode 100644 index 0000000..04316b1 --- /dev/null +++ b/Interframe EZBC/TempSub/src/mv_statistics.cpp @@ -0,0 +1,172 @@ +#include "mv_statistics.h" +#include "basic.h" +#include "general.h" +#include +#include +#include + +const int lazy = 1; + +FILE *mvStat_fp = NULL; +int mvStat_GOP = -1; +int mvStat_level = -1; +int mvStat_frame = -1; +int mvStat_xPos = -1; +int mvStat_yPos = -1; +int mvStat_numFreq = -1; + +float mvStat_dmvx, mvStat_dmvy; +float mvStat_dmvx_hor, mvStat_dmvy_hor; +float mvStat_dmvx_ver, mvStat_dmvy_ver; +float mvStat_dmvx_dia, mvStat_dmvy_dia; + +void mvStat_open(char *filename) +{ + if (lazy) return; + + assert(mvStat_fp == NULL); + + mvStat_fp = fopen(filename, "w"); + + assert(mvStat_fp != NULL); + + fprintf(mvStat_fp, "dmv: GOP level frame xpos ypos dmvx dmvy " + "dmvx_hor dmvy_hor dmvx_ver dmvy_ver dmvx_dia dmvy_dia\n"); + fprintf(mvStat_fp, "frq: GOP level frame ctx elements freq0 ...\n"); +} + +void mvStat_setFrame(int GOP, int level, int frame) +{ + if (mvStat_fp == NULL) return; + + assert(GOP >= 0 && level >= 0 && frame >= 0); + + mvStat_GOP = GOP; + mvStat_level = level; + mvStat_frame = frame; +} + +void mvStat_setPos(int x, int y) +{ + if (mvStat_fp == NULL) return; + + assert(x >= 0 && y >= 0); + + mvStat_xPos = x; + mvStat_yPos = y; +} + +void mvStat_setDMV(float dmvx, float dmvy) +{ + mvStat_dmvx = dmvx; + mvStat_dmvy = dmvy; +} + +void mvStat_setCTX(float dmvx_hor, float dmvy_hor, + float dmvx_ver, float dmvy_ver, + float dmvx_dia, float dmvy_dia) +{ + mvStat_dmvx_hor = dmvx_hor; + mvStat_dmvy_hor = dmvy_hor; + mvStat_dmvx_ver = dmvx_ver; + mvStat_dmvy_ver = dmvy_ver; + mvStat_dmvx_dia = dmvx_dia; + mvStat_dmvy_dia = dmvy_dia; +} + +void mvStat_writeDMVCTX() +{ + if (mvStat_fp == NULL) return; + + fprintf(mvStat_fp, "dmv: %02d %02d %02d %03d %03d " + "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n", + mvStat_GOP, mvStat_level, mvStat_frame, + mvStat_xPos, mvStat_yPos, + mvStat_dmvx, mvStat_dmvy, mvStat_dmvx_hor, mvStat_dmvy_hor, + mvStat_dmvx_ver, mvStat_dmvy_ver, mvStat_dmvx_dia, mvStat_dmvy_dia); +} + +void mvStat_writeFreqNumber(int ctx, int cum, int number) +{ + if (mvStat_fp == NULL) return; + + fprintf(mvStat_fp, "frq: %02d %02d %02d %02d %4d ", + mvStat_GOP, mvStat_level, mvStat_frame, ctx, cum); + + mvStat_numFreq = number; +} + +void mvStat_writeFreq(int freq) +{ + if (mvStat_fp == NULL) return; + + assert(mvStat_numFreq > 0); + + fprintf(mvStat_fp, "%4d ", freq); + + mvStat_numFreq--; + + if (mvStat_numFreq == 0) { + fprintf(mvStat_fp, "\n"); + } +} + +void mvStat_close() +{ + if (mvStat_fp == NULL) return; + + fclose(mvStat_fp); + + mvStat_fp = NULL; +} + + +#ifdef BLOCKMODE_STATISTICS + +// block size histogram +// 0: 1x1, 1: 2x2, 2: 4x4, 3: 8x8, 4: 16x16, +// 5: 32x32, 6: 64x64, 7: 128x128, 8: 256x256 +#define NUMBER_OF_BLOCKSIZES 9 +long int block_count[NUMBER_OF_BLOCKSIZES] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + +// block mode histogram +long int mode_count[NUMBER_OF_BI_MODES] = {0, 0, 0, 0, 0, 0, 0, 0}; + +// total area of block modes +double mode_area[NUMBER_OF_BI_MODES] = {0., 0., 0., 0., 0., 0., 0., 0.}; + + +void record_blockmode_statistics(int xblk, int yblk, enum BiMode mode, + int bi, int hor, int ver) +{ + block_count[int(rint(log2(double(MY_MAX(xblk, yblk)))))]++; + if (bi) { + mode_count[mode]++; + mode_area[mode] += double(xblk * yblk) / double(hor * ver); + } +} + +void dump_blockmode_statistics(char *filename) +{ + FILE *outfile; + char tmpname[1024]; + int i; + + sprintf(tmpname, "%s-blocksizes", filename); + outfile = fopen(tmpname, "w"); + assert(outfile); + for (i = 0; i < NUMBER_OF_BLOCKSIZES; i++) { + fprintf(outfile, "%ld\n", block_count[i]); + } + fclose(outfile); + + sprintf(tmpname, "%s-blockmodes", filename); + outfile = fopen(tmpname, "w"); + assert(outfile); + for (i = 0; i < NUMBER_OF_BI_MODES; i++) { + fprintf(outfile, "%ld %lf\n", mode_count[i], mode_area[i]); + } + fclose(outfile); +} + +#endif diff --git a/Interframe EZBC/TempSub/src/mvcodingN.c b/Interframe EZBC/TempSub/src/mvcodingN.c new file mode 100644 index 0000000..d2583f7 --- /dev/null +++ b/Interframe EZBC/TempSub/src/mvcodingN.c @@ -0,0 +1,9006 @@ +#include +#include +#include +#include + +#include "structN.h" +#include "basic.h" +#include "bmeN.h" +#include "mv_ec.h" +#include "mv_statistics.h" +#include "bme_tools.h" +#include "mode_decision.h" + +#define EXTERN extern + +#include "layer_mv.h" + +#include "ioN.h" +#include "miscN.h" + +//#define EC_TYPE GOLOMB +#define EC_TYPE AR_BINARY +#define EC_USE_CONTEXTS /* use contexts */ + +#define Yes 1 +#define No 0 + +#define DIS1 1 /* frame distance for block matching */ +#define DIS2 2 +#define DIS4 4 + +//#define DEBUG_SCALABLE_MV // for debug use by Yongjun Wu +//#define DEBUG_BLOCK_MODE_MV_INFO // for debug use by Yongjun Wu +//#define DEBUG_LAYER_STRUCTURE // for debug use by Yongjun Wu +#define LAYER_BLOCK_SIZE 32 + +float avg_blk_size[4]; +int blk_num; + +int debug_counter=0; +FILE *fpAGP_debug; +FILE *fpsub_debug; +char decoder_AGPdebug[80]; +char decoder_subdebug[80]; +char encoder_AGPdebug[80]; + +//Added on 02.05.2018 +int SIMUL_START;// = 16 +int SIMUL_POINT;// = 0 +int SIMUL_LIMIT;// = 1 +int SIMUL_LEVEL;// = 0 + +int SIMUL_ROUND; +int SIMUL_RANGE; + + +VLCtable blockmodeVLC[2] = { + {0, 1}, //CONNECTED huffman code = 0 + {1, 1} //PREDICTED huffman code = 1 +}; + + + +FRAME_MOTION_FIELD *frame_motion_field; +FRAME_MOTION_FIELD *frame_motion_field2; + +SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field1; +SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field2; + +SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field_left1; +SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field_left2; + +SIMP_FRAME_MOTION_FIELD *buffer_frame_motion_field1[G_LEVEL]; +SIMP_FRAME_MOTION_FIELD *buffer_frame_motion_field2[G_LEVEL]; + +SIMP_FRAME_MOTION_FIELD *save_buffer_frame_motion_field1[G_LEVEL]; +SIMP_FRAME_MOTION_FIELD *save_buffer_frame_motion_field2[G_LEVEL]; + + +//Added on 01.10.2018, for simul decoding +SIMP_FRAME_MOTION_FIELD *buffer_frame_motion_field1_dec[G_LEVEL]; +SIMP_FRAME_MOTION_FIELD *buffer_frame_motion_field2_dec[G_LEVEL]; + +SIMP_FRAME_MOTION_FIELD *save_buffer_frame_motion_field1_dec[G_LEVEL]; +SIMP_FRAME_MOTION_FIELD *save_buffer_frame_motion_field2_dec[G_LEVEL]; + +int aff_cum_idx[27]; + +int mv_res_bits; + +int mv_bits; + +int use_huff; + +float calc_res_bits; +float calc_res_sad; + +extern enum FLAG **scene_change; +extern enum FLAG **dec_scene_change; + +int ctl_info; +int mv_info; +int idx_info; + +int aff_mrg_blk; + +int cnt_quad[4]; +int cnt_tri[3]; + +int bi_mode_num012[12]; +int bi_mode_num345[12]; + +float mean_mode_mse[NUMBER_OF_BI_MODES]; +int mean_mode_num[NUMBER_OF_BI_MODES]; + +void child_map_decode( vector_ptr fmv1, vector_ptr fmv2, + int meandepth, int x, int y, int xblk, int yblk, + int hor, int ver, int small, videoinfo info, int t_level ); + +int read_number_core( FILE * fp ); +void write_number_core( int outputbyte, FILE * fp ); + + +// the variables for the section of sub-symbol +unsigned char store_splitted_bytes_array[LAYER_NUM][MAX_AGP_LEVEL][65535]; +unsigned int splitted_mv_byte_num_array[LAYER_NUM][MAX_AGP_LEVEL]; // the number of bytes for a sub-symbol +unsigned char splitted_mv_byte_array[LAYER_NUM][MAX_AGP_LEVEL]; // a specific byte for some sub-symbol + char splitted_bit_num_array[LAYER_NUM][MAX_AGP_LEVEL]; // how many bits have been used + +// the variables for additional sign +unsigned char store_splitted_sign[LAYER_NUM][65535]; +unsigned int splitted_sign_byte_num[LAYER_NUM]; +unsigned char splitted_sign_byte[LAYER_NUM]; + char splitted_sign_bit_num[LAYER_NUM]; + + +int frame_mv_cnt; +float sum_mv2, sum_mv1; + +/* + * putbits() + * write rightmost n (0<=n<=32) bits of val to outfile + * val : value needs to be output. + * n : rightmost n bits of val + */ +void +putbits( int val, int n ) +{ + int i; + unsigned int mask; + + assert(n >= 0); + + mask = 1 << ( n - 1 ); /* selects first (leftmost) bit */ + + for( i = 0; i < n; i++ ) { + if( val & mask ) { + output_bit( 1 ); + } else { + output_bit( 0 ); + } + mask >>= 1; /* select next bit */ + } +} + + +int +getbits( int len ) +{ + int i, bit, val = 0; + + for( i = 0; i < len; i++ ) { + val <<= 1; + input_bit( bit ); + val |= bit; + } + return val; +} + +//cx,cy - the coordinate of current block's upper-left corner +//x_pos,y_pos the merge reference point +void get_field_aff_mrg_mv( vector_ptr fmv, int cx, int cy, int x_pos, int y_pos, int xblk, int yblk, float dx1, float dy1, + float dx2, float dy2, float pmvx, float pmvy ){ + int i,j,k; + float mvx1, mvy1, mvx2, mvy2, mvx3, mvy3; + + mvx1 = pmvx - (x_pos - cx) * dx1 - (y_pos - cy) * dx2; + mvy1 = pmvy - (x_pos - cx) * dy1 - (y_pos - cy) * dy2; + + mvx2 = pmvx - (x_pos - cx - xblk) * dx1 - (y_pos - cy) * dx2; + mvy2 = pmvy - (x_pos - cx - xblk) * dy1 - (y_pos - cy) * dy2; + + mvx3 = pmvx - (x_pos - cx) * dx1 - (y_pos - cy - yblk) * dx2; + mvy3 = pmvy - (x_pos - cx) * dy1 - (y_pos - cy - yblk) * dy2; + + fmv->aff1_mvx = mvx1; + fmv->aff1_mvy = mvy1; + fmv->aff2_mvx = mvx2; + fmv->aff2_mvy = mvy2; + fmv->aff3_mvx = mvx3; + fmv->aff3_mvy = mvy3; + +} + +int field_compare_mv(vector_ptr left1, vector_ptr right1, vector_ptr left2, vector_ptr right2){ + int eql; + int diff_l = 1, diff_r = 1; + + assert(left1->bi_mode == right1->bi_mode && left2->bi_mode == right2->bi_mode); + + if(left1->bi_mode >= 9 || left2->bi_mode >= 9){ + diff_l = 1; + diff_r = 1; + }else{ + if(left1 != NULL && left2 != NULL){ + if(left1->mvx == left2->mvx && left1->mvy == left2->mvy) + diff_l = 0; + }else if(left1 == NULL && right1 == NULL){ + diff_l = 0; + } + + if(right1 != NULL && right2 != NULL){ + if(right1->mvx == right2->mvx && right1->mvy == right2->mvy) + diff_r = 0; + }else if(right1 == NULL && right1 == NULL){ + diff_r = 0; + } + } + + return (diff_l + diff_r); +} + +///////// added by Yuan Liu //////// + +void clean_mrg_mv(vector_ptr fmv){ + + fmv->lifting_mode = IGNORED; + + fmv->mvx = (float)HUGE_VAL; + fmv->mvy = (float)HUGE_VAL; + + fmv->aff1_mvx = (float)HUGE_VAL; + fmv->aff1_mvy = (float)HUGE_VAL; + fmv->aff2_mvx = (float)HUGE_VAL; + fmv->aff2_mvy = (float)HUGE_VAL; + fmv->aff3_mvx = (float)HUGE_VAL; + fmv->aff3_mvy = (float)HUGE_VAL; + +} + +/* + CBD + AZ + E +*/ +void get_field_merge_mv_info(vector_ptr *mrg_left, vector_ptr *mrg_right, int x_pos, int y_pos, int xblk, int yblk, + int hor, int ver, videoinfo info, int t_level, FRAME_MOTION_FIELD *cur_frame_motion_field1, FRAME_MOTION_FIELD *cur_frame_motion_field2, + SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field1, SIMP_FRAME_MOTION_FIELD *prev_frame_motion_field2, int type){ + int i,j,k; + int x_dest, y_dest, x_dest2, y_dest2; + int get_xblk, get_yblk; + int is_predl_a, is_predl_b, is_predl_c, is_predl_d, is_predl_tmp, is_predl_e; + int is_predr_a, is_predr_b, is_predr_c, is_predr_d, is_predr_tmp, is_predr_e; + + int aff_blk; //Added on 09.23.2016 + + float ul1,ul2; + float med_l_px[4], med_l_py[4], med_r_px[4], med_r_py[4]; + float med_l_aff1x[4],med_l_aff1y[4],med_l_aff2x[4],med_l_aff2y[4],med_l_aff3x[4],med_l_aff3y[4]; + float med_r_aff1x[4],med_r_aff1y[4],med_r_aff2x[4],med_r_aff2y[4],med_r_aff3x[4],med_r_aff3y[4]; + + float left_affx1, left_affy1, left_affx2, left_affy2, left_affx3, left_affy3, left_affx4, left_affy4; + float right_affx1, right_affy1, right_affx2, right_affy2, right_affx3, right_affy3, right_affx4, right_affy4; + + float aff_dmvx1, aff_dmvy1;//x-directional affine dmv + float aff_dmvx2, aff_dmvy2;//y-directional affine dmv + + for(i=0;i<=3;i++){ + med_l_px[i] = (float)HUGE_VAL; + med_l_py[i] = (float)HUGE_VAL; + med_l_aff1x[i] = (float)HUGE_VAL; + med_l_aff1y[i] = (float)HUGE_VAL; + med_l_aff2x[i] = (float)HUGE_VAL; + med_l_aff2y[i] = (float)HUGE_VAL; + med_l_aff3x[i] = (float)HUGE_VAL; + med_l_aff3y[i] = (float)HUGE_VAL; + + med_r_px[i] = (float)HUGE_VAL; + med_r_py[i] = (float)HUGE_VAL; + med_r_aff1x[i] = (float)HUGE_VAL; + med_r_aff1y[i] = (float)HUGE_VAL; + med_r_aff2x[i] = (float)HUGE_VAL; + med_r_aff2y[i] = (float)HUGE_VAL; + med_r_aff3x[i] = (float)HUGE_VAL; + med_r_aff3y[i] = (float)HUGE_VAL; + } + +//A + aff_blk = 0; + x_dest = x_pos - 1; + y_dest = y_pos + yblk - 1; + + if(x_dest < 0 || y_dest >= ver){ + is_predl_a = 0; + is_predr_a = 0; + }else{ + is_predl_a = cur_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_a = cur_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_a = 0; + + if(is_predl_a == 1){ + mrg_left[0]->mvx = cur_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[0]->mvy = cur_frame_motion_field1[y_dest*hor+x_dest].mvy; + + left_affx1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-2)].mvx; + left_affy1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-2)].mvy; + + left_affx2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-1)].mvx; + left_affy2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-1)].mvy; + + left_affx3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest-2)].mvx; + left_affy3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest-2)].mvy; + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[0], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + + mrg_left[0]->lifting_mode = CONNECTED; + } + + if(is_predr_a == 1){ + mrg_right[0]->mvx = cur_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[0]->mvy = cur_frame_motion_field2[y_dest*hor+x_dest].mvy; + + right_affx1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-2)].mvx; + right_affy1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-2)].mvy; + + right_affx2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-1)].mvx; + right_affy2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-1)].mvy; + + right_affx3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest-2)].mvx; + right_affy3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest-2)].mvy; + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[0], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + mrg_right[0]->lifting_mode = CONNECTED; + } + + if(is_predl_a == 1 && is_predr_a == 1 && aff_blk == 1){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[0], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[0], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + + } + +//B + aff_blk = 0; + x_dest = x_pos + xblk - 1; + y_dest = y_pos - 1; + + if(y_dest < 0 || x_dest >= hor){ + is_predl_b = 0; + is_predr_b = 0; + }else{ + is_predl_b = cur_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_b = cur_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_b = 0; + + if(is_predl_b == 1){ + mrg_left[1]->mvx = cur_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[1]->mvy = cur_frame_motion_field1[y_dest*hor+x_dest].mvy; + + left_affx1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-2)].mvx; + left_affy1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-2)].mvy; + + left_affx2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-1)].mvx; + left_affy2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-1)].mvy; + + left_affx3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest-2)].mvx; + left_affy3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest-2)].mvy; + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[1], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + + mrg_left[1]->lifting_mode = CONNECTED; + } + + if(is_predr_b == 1){ + mrg_right[1]->mvx = cur_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[1]->mvy = cur_frame_motion_field2[y_dest*hor+x_dest].mvy; + + right_affx1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-2)].mvx; + right_affy1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-2)].mvy; + + right_affx2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-1)].mvx; + right_affy2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-1)].mvy; + + right_affx3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest-2)].mvx; + right_affy3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest-2)].mvy; + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[1], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + mrg_right[1]->lifting_mode = CONNECTED; + } + + if(is_predl_b == 1 && is_predr_b == 1 && aff_blk == 1){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[1], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[1], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + + } +//C + aff_blk = 0; + x_dest = x_pos - 1; + y_dest = y_pos - 1; + + if(x_dest < 0 || y_dest < 0){ + is_predl_c = 0; + is_predr_c = 0; + }else{ + is_predl_c = cur_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_c = cur_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_c = 0; + + if(is_predl_c == 1){ + mrg_left[2]->mvx = cur_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[2]->mvy = cur_frame_motion_field1[y_dest*hor+x_dest].mvy; + + left_affx1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-2)].mvx; + left_affy1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-2)].mvy; + + left_affx2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-1)].mvx; + left_affy2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest-1)].mvy; + + left_affx3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest-2)].mvx; + left_affy3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest-2)].mvy; + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[2], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + + mrg_left[2]->lifting_mode = CONNECTED; + } + + if(is_predr_c == 1){ + mrg_right[2]->mvx = cur_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[2]->mvy = cur_frame_motion_field2[y_dest*hor+x_dest].mvy; + + right_affx1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-2)].mvx; + right_affy1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-2)].mvy; + + right_affx2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-1)].mvx; + right_affy2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest-1)].mvy; + + right_affx3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest-2)].mvx; + right_affy3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest-2)].mvy; + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[2], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + mrg_right[2]->lifting_mode = CONNECTED; + } + + if(is_predl_c == 1 && is_predr_c == 1 && aff_blk == 1){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[2], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[2], x_pos, y_pos, x_dest-2, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } +//D + aff_blk = 0; + if( (is_predl_a == 1 || is_predr_a == 1) && (is_predl_b == 1 || is_predr_b == 1) && (is_predl_c == 1 || is_predr_c == 1) ); + else{ + x_dest = x_pos + xblk; + y_dest = y_pos - 1; + + if(x_dest >= hor || y_dest < 0){ + is_predl_d = 0; + is_predr_d = 0; + }else{ + is_predl_d = cur_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_d = cur_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_d = 0; + + if(is_predl_d == 1){ + mrg_left[3]->mvx = cur_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[3]->mvy = cur_frame_motion_field1[y_dest*hor+x_dest].mvy; + + left_affx1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest+1)].mvx; + left_affy1 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest+1)].mvy; + + left_affx2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest+2)].mvx; + left_affy2 = cur_frame_motion_field1[(y_dest-2)*hor+(x_dest+2)].mvy; + + left_affx3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest+1)].mvx; + left_affy3 = cur_frame_motion_field1[(y_dest-1)*hor+(x_dest+1)].mvy; + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[3], x_pos, y_pos, x_dest+1, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + mrg_left[3]->lifting_mode = CONNECTED; + } + + if(is_predr_d == 1){ + mrg_right[3]->mvx = cur_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[3]->mvy = cur_frame_motion_field2[y_dest*hor+x_dest].mvy; + + right_affx1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest+1)].mvx; + right_affy1 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest+1)].mvy; + + right_affx2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest+2)].mvx; + right_affy2 = cur_frame_motion_field2[(y_dest-2)*hor+(x_dest+2)].mvy; + + right_affx3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest+1)].mvx; + right_affy3 = cur_frame_motion_field2[(y_dest-1)*hor+(x_dest+1)].mvy; + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[3], x_pos, y_pos, x_dest+1, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + + mrg_right[3]->lifting_mode = CONNECTED; + } + + if(is_predl_d == 1 && is_predr_d == 1 && aff_blk == 1){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[3], x_pos, y_pos, x_dest+1, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[3], x_pos, y_pos, x_dest+1, y_dest-2,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + + } + } + //////////////////////// + for(i = 0;i <= 3;i ++){ + if( (x_pos-(mrg_left[i]->mvx)<0||x_pos-(mrg_left[i]->mvx)+xblk>hor||y_pos-(mrg_left[i]->mvy)<0|| + y_pos-(mrg_left[i]->mvy)+yblk>ver) && (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + if( (x_pos-(mrg_right[i]->mvx)<0||x_pos-(mrg_right[i]->mvx)+xblk>hor||y_pos-(mrg_right[i]->mvy)<0|| + y_pos-(mrg_right[i]->mvy)+yblk>ver) && (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if( (mrg_left[i]->mvx == mrg_left[k]->mvx && mrg_left[i]->mvy == mrg_left[k]->mvy) && + (mrg_right[i]->mvx == mrg_right[k]->mvx && mrg_right[i]->mvy == mrg_right[k]->mvy) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + med_l_px[k] = mrg_left[i]->mvx; + med_l_py[k] = mrg_left[i]->mvy; + med_l_aff1x[k] = mrg_left[i]->aff1_mvx; + med_l_aff1y[k] = mrg_left[i]->aff1_mvy; + med_l_aff2x[k] = mrg_left[i]->aff2_mvx; + med_l_aff2y[k] = mrg_left[i]->aff2_mvy; + med_l_aff3x[k] = mrg_left[i]->aff3_mvx; + med_l_aff3y[k] = mrg_left[i]->aff3_mvy; + + med_r_px[k] = mrg_right[i]->mvx; + med_r_py[k] = mrg_right[i]->mvy; + med_r_aff1x[k] = mrg_right[i]->aff1_mvx; + med_r_aff1y[k] = mrg_right[i]->aff1_mvy; + med_r_aff2x[k] = mrg_right[i]->aff2_mvx; + med_r_aff2y[k] = mrg_right[i]->aff2_mvy; + med_r_aff3x[k] = mrg_right[i]->aff3_mvx; + med_r_aff3y[k] = mrg_right[i]->aff3_mvy; + + k++; + } + } + assert(k <= 3); + for(i = 0;i <= 3;i++){ + mrg_left[i]->mvx = med_l_px[i]; + mrg_left[i]->mvy = med_l_py[i]; + mrg_left[i]->aff1_mvx = med_l_aff1x[i]; + mrg_left[i]->aff1_mvy = med_l_aff1y[i]; + mrg_left[i]->aff2_mvx = med_l_aff2x[i]; + mrg_left[i]->aff2_mvy = med_l_aff2y[i]; + mrg_left[i]->aff3_mvx = med_l_aff3x[i]; + mrg_left[i]->aff3_mvy = med_l_aff3y[i]; + + mrg_right[i]->mvx = med_r_px[i]; + mrg_right[i]->mvy = med_r_py[i]; + mrg_right[i]->aff1_mvx = med_r_aff1x[i]; + mrg_right[i]->aff1_mvy = med_r_aff1y[i]; + mrg_right[i]->aff2_mvx = med_r_aff2x[i]; + mrg_right[i]->aff2_mvy = med_r_aff2y[i]; + mrg_right[i]->aff3_mvx = med_r_aff3x[i]; + mrg_right[i]->aff3_mvy = med_r_aff3y[i]; + + } + for(i=0;i<=3;i++){ + med_l_px[i] = (float)HUGE_VAL; + med_l_py[i] = (float)HUGE_VAL; + med_l_aff1x[i] = (float)HUGE_VAL; + med_l_aff1y[i] = (float)HUGE_VAL; + med_l_aff2x[i] = (float)HUGE_VAL; + med_l_aff2y[i] = (float)HUGE_VAL; + med_l_aff3x[i] = (float)HUGE_VAL; + med_l_aff3y[i] = (float)HUGE_VAL; + + med_r_px[i] = (float)HUGE_VAL; + med_r_py[i] = (float)HUGE_VAL; + med_r_aff1x[i] = (float)HUGE_VAL; + med_r_aff1y[i] = (float)HUGE_VAL; + med_r_aff2x[i] = (float)HUGE_VAL; + med_r_aff2y[i] = (float)HUGE_VAL; + med_r_aff3x[i] = (float)HUGE_VAL; + med_r_aff3y[i] = (float)HUGE_VAL; + } + + assert(mrg_left[3]->mvx == (float)HUGE_VAL && mrg_left[3]->mvy == (float)HUGE_VAL + && mrg_right[3]->mvx == (float)HUGE_VAL && mrg_right[3]->mvy == (float)HUGE_VAL); + +//TMP merge candidate + for(i = 0; i <= 3; i++){ + if( (mrg_left[i]->mvx == (float)HUGE_VAL && mrg_left[i]->mvy == (float)HUGE_VAL) && + (mrg_right[i]->mvx == (float)HUGE_VAL && mrg_right[i]->mvy == (float)HUGE_VAL) ){ + x_dest = x_pos; + y_dest = y_pos; + if (x_dest < 0 || y_dest < 0) { + assert(0); + } else { + is_predl_tmp = prev_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_tmp = prev_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_tmp = 0; + + if(is_predl_tmp == 1){ + mrg_left[i]->mvx = prev_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[i]->mvy = prev_frame_motion_field1[y_dest*hor+x_dest].mvy; + mrg_left[i]->lifting_mode = CONNECTED; + } + if(is_predr_tmp == 1){ + mrg_right[i]->mvx = prev_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[i]->mvy = prev_frame_motion_field2[y_dest*hor+x_dest].mvy; + mrg_right[i]->lifting_mode = CONNECTED; + } + } +//Additional TMP merge candidate + if( is_predl_tmp == 0 && is_predr_tmp == 0 ){ + x_dest = x_pos - xblk; + y_dest = y_pos - yblk; + if (x_dest < 0 || y_dest < 0) { + is_predl_tmp = 0; + is_predr_tmp = 0; + } else { + is_predl_tmp = prev_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_tmp = prev_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_tmp = 0; + + if(is_predl_tmp == 1){ + mrg_left[i]->mvx = prev_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[i]->mvy = prev_frame_motion_field1[y_dest*hor+x_dest].mvy; + mrg_left[i]->lifting_mode = CONNECTED; + } + if(is_predr_tmp == 1){ + mrg_right[i]->mvx = prev_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[i]->mvy = prev_frame_motion_field2[y_dest*hor+x_dest].mvy; + mrg_right[i]->lifting_mode = CONNECTED; + } + } + } +//Additional TMP merge candidate + break; + } + } + + //////////////////////// + for(i = 0;i <= 3;i ++){ + if( (x_pos-(mrg_left[i]->mvx)<0||x_pos-(mrg_left[i]->mvx)+xblk>hor||y_pos-(mrg_left[i]->mvy)<0|| + y_pos-(mrg_left[i]->mvy)+yblk>ver) && (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + if( (x_pos-(mrg_right[i]->mvx)<0||x_pos-(mrg_right[i]->mvx)+xblk>hor||y_pos-(mrg_right[i]->mvy)<0|| + y_pos-(mrg_right[i]->mvy)+yblk>ver) && (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if( (mrg_left[i]->mvx == mrg_left[k]->mvx && mrg_left[i]->mvy == mrg_left[k]->mvy ) && + (mrg_right[i]->mvx == mrg_right[k]->mvx && mrg_right[i]->mvy == mrg_right[k]->mvy ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + med_l_px[k] = mrg_left[i]->mvx; + med_l_py[k] = mrg_left[i]->mvy; + med_l_aff1x[k] = mrg_left[i]->aff1_mvx; + med_l_aff1y[k] = mrg_left[i]->aff1_mvy; + med_l_aff2x[k] = mrg_left[i]->aff2_mvx; + med_l_aff2y[k] = mrg_left[i]->aff2_mvy; + med_l_aff3x[k] = mrg_left[i]->aff3_mvx; + med_l_aff3y[k] = mrg_left[i]->aff3_mvy; + + med_r_px[k] = mrg_right[i]->mvx; + med_r_py[k] = mrg_right[i]->mvy; + med_r_aff1x[k] = mrg_right[i]->aff1_mvx; + med_r_aff1y[k] = mrg_right[i]->aff1_mvy; + med_r_aff2x[k] = mrg_right[i]->aff2_mvx; + med_r_aff2y[k] = mrg_right[i]->aff2_mvy; + med_r_aff3x[k] = mrg_right[i]->aff3_mvx; + med_r_aff3y[k] = mrg_right[i]->aff3_mvy; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + mrg_left[i]->mvx = med_l_px[i]; + mrg_left[i]->mvy = med_l_py[i]; + mrg_left[i]->aff1_mvx = med_l_aff1x[i]; + mrg_left[i]->aff1_mvy = med_l_aff1y[i]; + mrg_left[i]->aff2_mvx = med_l_aff2x[i]; + mrg_left[i]->aff2_mvy = med_l_aff2y[i]; + mrg_left[i]->aff3_mvx = med_l_aff3x[i]; + mrg_left[i]->aff3_mvy = med_l_aff3y[i]; + + mrg_right[i]->mvx = med_r_px[i]; + mrg_right[i]->mvy = med_r_py[i]; + mrg_right[i]->aff1_mvx = med_r_aff1x[i]; + mrg_right[i]->aff1_mvy = med_r_aff1y[i]; + mrg_right[i]->aff2_mvx = med_r_aff2x[i]; + mrg_right[i]->aff2_mvy = med_r_aff2y[i]; + mrg_right[i]->aff3_mvx = med_r_aff3x[i]; + mrg_right[i]->aff3_mvy = med_r_aff3y[i]; + + } + for(i=0;i<=3;i++){ + med_l_px[i] = (float)HUGE_VAL; + med_l_py[i] = (float)HUGE_VAL; + med_l_aff1x[i] = (float)HUGE_VAL; + med_l_aff1y[i] = (float)HUGE_VAL; + med_l_aff2x[i] = (float)HUGE_VAL; + med_l_aff2y[i] = (float)HUGE_VAL; + med_l_aff3x[i] = (float)HUGE_VAL; + med_l_aff3y[i] = (float)HUGE_VAL; + + med_r_px[i] = (float)HUGE_VAL; + med_r_py[i] = (float)HUGE_VAL; + med_r_aff1x[i] = (float)HUGE_VAL; + med_r_aff1y[i] = (float)HUGE_VAL; + med_r_aff2x[i] = (float)HUGE_VAL; + med_r_aff2y[i] = (float)HUGE_VAL; + med_r_aff3x[i] = (float)HUGE_VAL; + med_r_aff3y[i] = (float)HUGE_VAL; + } +//E + aff_blk = 0; + + for(i = 0; i <= 3; i++){ + if( (mrg_left[i]->mvx == (float)HUGE_VAL && mrg_left[i]->mvy == (float)HUGE_VAL) && + (mrg_right[i]->mvx == (float)HUGE_VAL && mrg_right[i]->mvy == (float)HUGE_VAL) ){ + x_dest = x_pos - 1; + y_dest = y_pos + yblk; + if(x_dest < 0 || y_dest >= ver){ + is_predl_e = 0; + is_predr_e = 0; + }else{ + is_predl_e = cur_frame_motion_field1[y_dest*hor+x_dest].available; + + if(type == 0) + is_predr_e = cur_frame_motion_field2[y_dest*hor+x_dest].available; + else + is_predr_e = 0; + + if(is_predl_e == 1){ + mrg_left[i]->mvx = cur_frame_motion_field1[y_dest*hor+x_dest].mvx; + mrg_left[i]->mvy = cur_frame_motion_field1[y_dest*hor+x_dest].mvy; + + left_affx1 = cur_frame_motion_field1[(y_dest+1)*hor+(x_dest-2)].mvx; + left_affy1 = cur_frame_motion_field1[(y_dest+1)*hor+(x_dest-2)].mvy; + + left_affx2 = cur_frame_motion_field1[(y_dest+1)*hor+(x_dest-1)].mvx; + left_affy2 = cur_frame_motion_field1[(y_dest+1)*hor+(x_dest-1)].mvy; + + left_affx3 = cur_frame_motion_field1[(y_dest+2)*hor+(x_dest-2)].mvx; + left_affy3 = cur_frame_motion_field1[(y_dest+2)*hor+(x_dest-2)].mvy; + + if( (left_affx3 != left_affx1 || left_affy3 != left_affy1) || (left_affx2 != left_affx1 || left_affy2 != left_affy1) ){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[i], x_pos, y_pos, x_dest-2, y_dest+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_blk = 1; + } + mrg_left[i]->lifting_mode = CONNECTED; + } + + if(is_predr_e == 1){ + mrg_right[i]->mvx = cur_frame_motion_field2[y_dest*hor+x_dest].mvx; + mrg_right[i]->mvy = cur_frame_motion_field2[y_dest*hor+x_dest].mvy; + + right_affx1 = cur_frame_motion_field2[(y_dest+1)*hor+(x_dest-2)].mvx; + right_affy1 = cur_frame_motion_field2[(y_dest+1)*hor+(x_dest-2)].mvy; + + right_affx2 = cur_frame_motion_field2[(y_dest+1)*hor+(x_dest-1)].mvx; + right_affy2 = cur_frame_motion_field2[(y_dest+1)*hor+(x_dest-1)].mvy; + + right_affx3 = cur_frame_motion_field2[(y_dest+2)*hor+(x_dest-2)].mvx; + right_affy3 = cur_frame_motion_field2[(y_dest+2)*hor+(x_dest-2)].mvy; + + if( (right_affx3 != right_affx1 || right_affy3 != right_affy1) || (right_affx2 != right_affx1 || right_affy2 != right_affy1) ){ + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[i], x_pos, y_pos, x_dest-2, y_dest+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + + aff_blk = 1; + } + mrg_right[i]->lifting_mode = CONNECTED; + } + + if(is_predl_e == 1 && is_predr_e == 1 && aff_blk == 1){ + aff_dmvx1 = (left_affx2 - left_affx1); + aff_dmvy1 = (left_affy2 - left_affy1); + + aff_dmvx2 = (left_affx3 - left_affx1); + aff_dmvy2 = (left_affy3 - left_affy1); + + get_field_aff_mrg_mv(mrg_left[i], x_pos, y_pos, x_dest-2, y_dest+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,left_affx1,left_affy1); + + aff_dmvx1 = (right_affx2 - right_affx1); + aff_dmvy1 = (right_affy2 - right_affy1); + + aff_dmvx2 = (right_affx3 - right_affx1); + aff_dmvy2 = (right_affy3 - right_affy1); + + get_field_aff_mrg_mv(mrg_right[i], x_pos, y_pos, x_dest-2, y_dest+1,xblk,yblk,aff_dmvx1,aff_dmvy1,aff_dmvx2,aff_dmvy2,right_affx1,right_affy1); + } + } + break; + } + } + + //////////////////////// + for(i = 0;i <= 3;i ++){ + if( (x_pos-(mrg_left[i]->mvx)<0||x_pos-(mrg_left[i]->mvx)+xblk>hor||y_pos-(mrg_left[i]->mvy)<0|| + y_pos-(mrg_left[i]->mvy)+yblk>ver) && (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + if( (x_pos-(mrg_right[i]->mvx)<0||x_pos-(mrg_right[i]->mvx)+xblk>hor||y_pos-(mrg_right[i]->mvy)<0|| + y_pos-(mrg_right[i]->mvy)+yblk>ver) && (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + + //check for repeated candidates + for(i = 3;i >= 1;i --){ + for(k = i-1;k >= 0;k --){ + if( (mrg_left[i]->mvx == mrg_left[k]->mvx && mrg_left[i]->mvy == mrg_left[k]->mvy ) && + (mrg_right[i]->mvx == mrg_right[k]->mvx && mrg_right[i]->mvy == mrg_right[k]->mvy ) ){ + mrg_left[i]->mvx = (float)HUGE_VAL; + mrg_left[i]->mvy = (float)HUGE_VAL; + mrg_left[i]->aff1_mvx = (float)HUGE_VAL; + mrg_left[i]->aff1_mvy = (float)HUGE_VAL; + mrg_left[i]->aff2_mvx = (float)HUGE_VAL; + mrg_left[i]->aff2_mvy = (float)HUGE_VAL; + mrg_left[i]->aff3_mvx = (float)HUGE_VAL; + mrg_left[i]->aff3_mvy = (float)HUGE_VAL; + + mrg_right[i]->mvx = (float)HUGE_VAL; + mrg_right[i]->mvy = (float)HUGE_VAL; + mrg_right[i]->aff1_mvx = (float)HUGE_VAL; + mrg_right[i]->aff1_mvy = (float)HUGE_VAL; + mrg_right[i]->aff2_mvx = (float)HUGE_VAL; + mrg_right[i]->aff2_mvy = (float)HUGE_VAL; + mrg_right[i]->aff3_mvx = (float)HUGE_VAL; + mrg_right[i]->aff3_mvy = (float)HUGE_VAL; + } + } + } + //check for HUGE_VALs + k = 0; + for(i = 0;i <= 3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) || + (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + med_l_px[k] = mrg_left[i]->mvx; + med_l_py[k] = mrg_left[i]->mvy; + med_l_aff1x[k] = mrg_left[i]->aff1_mvx; + med_l_aff1y[k] = mrg_left[i]->aff1_mvy; + med_l_aff2x[k] = mrg_left[i]->aff2_mvx; + med_l_aff2y[k] = mrg_left[i]->aff2_mvy; + med_l_aff3x[k] = mrg_left[i]->aff3_mvx; + med_l_aff3y[k] = mrg_left[i]->aff3_mvy; + + med_r_px[k] = mrg_right[i]->mvx; + med_r_py[k] = mrg_right[i]->mvy; + med_r_aff1x[k] = mrg_right[i]->aff1_mvx; + med_r_aff1y[k] = mrg_right[i]->aff1_mvy; + med_r_aff2x[k] = mrg_right[i]->aff2_mvx; + med_r_aff2y[k] = mrg_right[i]->aff2_mvy; + med_r_aff3x[k] = mrg_right[i]->aff3_mvx; + med_r_aff3y[k] = mrg_right[i]->aff3_mvy; + k++; + } + } + assert(k <= 4); + for(i = 0;i <= 3;i++){ + mrg_left[i]->mvx = med_l_px[i]; + mrg_left[i]->mvy = med_l_py[i]; + mrg_left[i]->aff1_mvx = med_l_aff1x[i]; + mrg_left[i]->aff1_mvy = med_l_aff1y[i]; + mrg_left[i]->aff2_mvx = med_l_aff2x[i]; + mrg_left[i]->aff2_mvy = med_l_aff2y[i]; + mrg_left[i]->aff3_mvx = med_l_aff3x[i]; + mrg_left[i]->aff3_mvy = med_l_aff3y[i]; + + mrg_right[i]->mvx = med_r_px[i]; + mrg_right[i]->mvy = med_r_py[i]; + mrg_right[i]->aff1_mvx = med_r_aff1x[i]; + mrg_right[i]->aff1_mvy = med_r_aff1y[i]; + mrg_right[i]->aff2_mvx = med_r_aff2x[i]; + mrg_right[i]->aff2_mvy = med_r_aff2y[i]; + mrg_right[i]->aff3_mvx = med_r_aff3x[i]; + mrg_right[i]->aff3_mvy = med_r_aff3y[i]; + + } + +} + + +float medi(float a, float b, float c) +{ + return ((a>b) ? ((a>c) ? ((b>c) ? b : c) : a) : + ((b>c) ? ((a>c) ? a : c) : b)); +} + +int put_aff_mvs(vector_ptr fmv, int x, int y, int xblk, int yblk, int hor, int ver, FRAME_MOTION_FIELD* cur_frame_motion_field, SIMP_FRAME_MOTION_FIELD* prev_frame_motion_field, int enc_idx){ + int getnum, count = 0, length, aff_num = 0, left_num = 0, up_num = 0; + int i,j,k; + float aff1_mvx[3],aff1_mvy[3],aff2_mvx[3],aff2_mvy[3],aff3_mvx[3],aff3_mvy[3]; + float get1_mvx[3],get1_mvy[3],get2_mvx[3],get2_mvy[3],get3_mvx[3],get3_mvy[3]; + float tempx, tempy; + int int_mvx, int_mvy; + float sub = 0.25; + + length = 0; + + for(i=0;i<3;i++){ + aff1_mvx[i] = (float)HUGE_VAL;get1_mvx[i] = (float)HUGE_VAL; + aff1_mvy[i] = (float)HUGE_VAL;get1_mvy[i] = (float)HUGE_VAL; + aff2_mvx[i] = (float)HUGE_VAL;get2_mvx[i] = (float)HUGE_VAL; + aff2_mvy[i] = (float)HUGE_VAL;get2_mvy[i] = (float)HUGE_VAL; + aff3_mvx[i] = (float)HUGE_VAL;get3_mvx[i] = (float)HUGE_VAL; + aff3_mvy[i] = (float)HUGE_VAL;get3_mvy[i] = (float)HUGE_VAL; + } + +// MV1 + if(y-1>=0){ + aff1_mvx[0] = cur_frame_motion_field[(y-1)*hor + x].mvx; + aff1_mvy[0] = cur_frame_motion_field[(y-1)*hor + x].mvy; + + aff1_mvx[0] = cur_frame_motion_field[(y-2)*hor + x].mvx + 2 * (cur_frame_motion_field[(y-2)*hor + x].mvx - cur_frame_motion_field[(y-3)*hor + x].mvx); + aff1_mvy[0] = cur_frame_motion_field[(y-2)*hor + x].mvy + 2 * (cur_frame_motion_field[(y-2)*hor + x].mvy - cur_frame_motion_field[(y-3)*hor + x].mvy); + + aff1_mvx[0] = aff1_mvx[0] * AFF_SUBPEL; + aff1_mvy[0] = aff1_mvy[0] * AFF_SUBPEL; + int_mvx = (int)(aff1_mvx[0]); + int_mvy = (int)(aff1_mvy[0]); + aff1_mvx[0] = (float)(int_mvx); + aff1_mvy[0] = (float)(int_mvy); + aff1_mvx[0] = aff1_mvx[0] / AFF_SUBPEL; + aff1_mvy[0] = aff1_mvy[0] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y-2)*hor + x].mvx == (float)HUGE_VAL){ + aff1_mvx[0] = (float)HUGE_VAL; + aff1_mvy[0] = (float)HUGE_VAL; + } + +// if(aff1_mvx[0]!= get1_mvx[0] || aff1_mvy[0]!= get1_mvy[0]) +// printf("aff1_mvx0 = %f, aff1_mvy0 = %f, get1_mvx0 = %f, get1_mvy0 = %f\n\n",aff1_mvx[0],aff1_mvy[0],get1_mvx[0],get1_mvy[0]); + } + + if(x-1>=0){ + aff1_mvx[1] = cur_frame_motion_field[y*hor + (x-1)].mvx; + aff1_mvy[1] = cur_frame_motion_field[y*hor + (x-1)].mvy; + + aff1_mvx[1] = cur_frame_motion_field[y*hor + (x-2)].mvx + 2 * (cur_frame_motion_field[y*hor + (x-2)].mvx - cur_frame_motion_field[y*hor + (x-3)].mvx); + aff1_mvy[1] = cur_frame_motion_field[y*hor + (x-2)].mvy + 2 * (cur_frame_motion_field[y*hor + (x-2)].mvy - cur_frame_motion_field[y*hor + (x-3)].mvy); + + aff1_mvx[1] = aff1_mvx[1] * AFF_SUBPEL; + aff1_mvy[1] = aff1_mvy[1] * AFF_SUBPEL; + int_mvx = (int)(aff1_mvx[1]); + int_mvy = (int)(aff1_mvy[1]); + aff1_mvx[1] = (float)(int_mvx); + aff1_mvy[1] = (float)(int_mvy); + aff1_mvx[1] = aff1_mvx[1] / AFF_SUBPEL; + aff1_mvy[1] = aff1_mvy[1] / AFF_SUBPEL; + + if(cur_frame_motion_field[y*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff1_mvx[1] = (float)HUGE_VAL; + aff1_mvy[1] = (float)HUGE_VAL; + } + +// if(aff1_mvx[1] != get1_mvx[1] || aff1_mvy[1] != get1_mvy[1]) +// printf("aff1_mvx1 = %f, aff1_mvy1 = %f, get1_mvx1 = %f, get1_mvy1 = %f\n\n",aff1_mvx[1],aff1_mvy[1],get1_mvx[1],get1_mvy[1]); + } + + if(y-1>=0 && x-1>=0){ + aff1_mvx[2] = cur_frame_motion_field[(y-1)*hor + (x-1)].mvx; + aff1_mvy[2] = cur_frame_motion_field[(y-1)*hor + (x-1)].mvy; + + aff1_mvx[2] = cur_frame_motion_field[(y-2)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y-3)*hor + (x-2)].mvx) + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y-2)*hor + (x-3)].mvx); + aff1_mvy[2] = cur_frame_motion_field[(y-2)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y-3)*hor + (x-2)].mvy) + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y-2)*hor + (x-3)].mvy); + + aff1_mvx[2] = aff1_mvx[2] * AFF_SUBPEL; + aff1_mvy[2] = aff1_mvy[2] * AFF_SUBPEL; + int_mvx = (int)(aff1_mvx[2]); + int_mvy = (int)(aff1_mvy[2]); + aff1_mvx[2] = (float)(int_mvx); + aff1_mvy[2] = (float)(int_mvy); + aff1_mvx[2] = aff1_mvx[2] / AFF_SUBPEL; + aff1_mvy[2] = aff1_mvy[2] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y-2)*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff1_mvx[2] = (float)HUGE_VAL; + aff1_mvy[2] = (float)HUGE_VAL; + } + +// if(aff1_mvx[2] != get1_mvx[2] || aff1_mvy[2] != get1_mvy[2]) +// printf("aff1_mvx2 = %f, aff1_mvy2 = %f, get1_mvx2 = %f, get1_mvy2 = %f\n\n",aff1_mvx[2],aff1_mvy[2],get1_mvx[2],get1_mvy[2]); + } + + if( fabs(aff1_mvx[1] - aff1_mvx[0]) < SMALL_DIFF && fabs(aff1_mvy[1] - aff1_mvy[0]) < SMALL_DIFF && aff1_mvx[1] != (float)HUGE_VAL && aff1_mvy[1] != (float)HUGE_VAL){ + aff1_mvx[1] = (float)HUGE_VAL; + aff1_mvy[1] = (float)HUGE_VAL; + } + if( ( ( fabs(aff1_mvx[2] - aff1_mvx[0]) < SMALL_DIFF && fabs(aff1_mvy[2] - aff1_mvy[0]) < SMALL_DIFF) || ( fabs(aff1_mvx[2] - aff1_mvx[1]) < SMALL_DIFF && fabs(aff1_mvy[2] - aff1_mvy[1]) < SMALL_DIFF) ) + && (aff1_mvx[2] != (float)HUGE_VAL && aff1_mvy[2] != (float)HUGE_VAL) ){ + aff1_mvx[2] = (float)HUGE_VAL; + aff1_mvy[2] = (float)HUGE_VAL; + } + +//TEMP + for( i = 0; i < 3 ; i ++ ){ + if( aff1_mvx[i] == (float)HUGE_VAL && aff1_mvy[i] == (float)HUGE_VAL ){ + tempx = prev_frame_motion_field[y*hor + x].mvx; + tempy = prev_frame_motion_field[y*hor + x].mvy; + + for( j = 0; j < 3 ; j ++ ){ + if( tempx != (float)HUGE_VAL && tempy != (float)HUGE_VAL && (fabs(tempx - aff1_mvx[j]) < SMALL_DIFF && fabs(tempy - aff1_mvy[j]) < SMALL_DIFF) ){ + tempx = (float)HUGE_VAL; + tempy = (float)HUGE_VAL; + } + } + aff1_mvx[i] = tempx; + aff1_mvy[i] = tempy; + break; + } + } + +// MV2 + if(y-1>=0 && x+xblk-1=0 && x+xblk=0){ + aff3_mvx[0] = cur_frame_motion_field[(y+yblk-1)*hor + (x-1)].mvx; + aff3_mvy[0] = cur_frame_motion_field[(y+yblk-1)*hor + (x-1)].mvy; + + aff3_mvx[0] = cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk-3)*hor + (x-2)].mvx) + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk-2)*hor + (x-3)].mvx); + aff3_mvy[0] = cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk-3)*hor + (x-2)].mvy) + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk-2)*hor + (x-3)].mvy); + + aff3_mvx[0] = aff3_mvx[0] * AFF_SUBPEL; + aff3_mvy[0] = aff3_mvy[0] * AFF_SUBPEL; + int_mvx = (int)(aff3_mvx[0]); + int_mvy = (int)(aff3_mvy[0]); + aff3_mvx[0] = (float)(int_mvx); + aff3_mvy[0] = (float)(int_mvy); + aff3_mvx[0] = aff3_mvx[0] / AFF_SUBPEL; + aff3_mvy[0] = aff3_mvy[0] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff3_mvx[0] = (float)HUGE_VAL; + aff3_mvy[0] = (float)HUGE_VAL; + } + +// if(aff3_mvx[0]!=get3_mvx[0] || aff3_mvy[0]!=get3_mvy[0]) +// printf("aff3_mvx0 = %f, aff3_mvy0 = %f, get3_mvx0 = %f, get3_mvy0 = %f\n\n",aff3_mvx[0],aff3_mvy[0],get3_mvx[0],get3_mvy[0]); + } + if(y+yblk=0){ + aff3_mvx[1] = cur_frame_motion_field[(y+yblk)*hor + (x-1)].mvx; + aff3_mvy[1] = cur_frame_motion_field[(y+yblk)*hor + (x-1)].mvy; + + aff3_mvx[1] = cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk)*hor + (x-3)].mvx); + aff3_mvy[1] = cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk)*hor + (x-3)].mvy); + + aff3_mvx[1] = aff3_mvx[1] * AFF_SUBPEL; + aff3_mvy[1] = aff3_mvy[1] * AFF_SUBPEL; + int_mvx = (int)(aff3_mvx[1]); + int_mvy = (int)(aff3_mvy[1]); + aff3_mvx[1] = (float)(int_mvx); + aff3_mvy[1] = (float)(int_mvy); + aff3_mvx[1] = aff3_mvx[1] / AFF_SUBPEL; + aff3_mvy[1] = aff3_mvy[1] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff3_mvx[1] = (float)HUGE_VAL; + aff3_mvy[1] = (float)HUGE_VAL; + } + +// if(aff3_mvx[1]!=get3_mvx[1] || aff3_mvy[1]!=get3_mvy[1]) +// printf("aff3_mvx1 = %f, aff3_mvy1 = %f, get3_mvx1 = %f, get3_mvy1 = %f\n\n",aff3_mvx[1],aff3_mvy[1],get3_mvx[1],get3_mvy[1]); + } + + if( fabs(aff3_mvx[1] - aff3_mvx[0]) < SMALL_DIFF && fabs(aff3_mvy[1] - aff3_mvy[0]) < SMALL_DIFF && aff3_mvx[1] != (float)HUGE_VAL && aff3_mvy[1] != (float)HUGE_VAL){ + aff3_mvx[1] = (float)HUGE_VAL; + aff3_mvy[1] = (float)HUGE_VAL; + } + + if(aff3_mvx[0] != (float)HUGE_VAL && aff3_mvy[0] != (float)HUGE_VAL && aff3_mvx[1] != (float)HUGE_VAL && aff3_mvy[1] != (float)HUGE_VAL){ + aff3_mvx[2] = (aff3_mvx[0] + aff3_mvx[1])/2; + aff3_mvy[2] = (aff3_mvy[0] + aff3_mvy[1])/2; + } + + if( ( ( fabs(aff3_mvx[2] - aff3_mvx[0]) < SMALL_DIFF && fabs(aff3_mvy[2] - aff3_mvy[0]) < SMALL_DIFF) || ( fabs(aff3_mvx[2] - aff3_mvx[1]) < SMALL_DIFF && fabs(aff3_mvy[2] - aff3_mvy[1]) < SMALL_DIFF) ) + && (aff3_mvx[2] != (float)HUGE_VAL && aff3_mvy[2] != (float)HUGE_VAL) ){ + aff3_mvx[2] = (float)HUGE_VAL; + aff3_mvy[2] = (float)HUGE_VAL; + } + +//TEMP + for( i = 0; i < 3 ; i ++ ){ + if( aff3_mvx[i] == (float)HUGE_VAL && aff3_mvy[i] == (float)HUGE_VAL ){ + tempx = prev_frame_motion_field[(y+yblk)*hor + x].mvx; + tempy = prev_frame_motion_field[(y+yblk)*hor + x].mvy; + + for( j = 0; j < 3 ; j ++ ){ + if( tempx != (float)HUGE_VAL && tempy != (float)HUGE_VAL && (fabs(tempx - aff3_mvx[j]) < SMALL_DIFF && fabs(tempy - aff3_mvy[j]) < SMALL_DIFF) ){ + tempx = (float)HUGE_VAL; + tempy = (float)HUGE_VAL; + } + } + aff3_mvx[i] = tempx; + aff3_mvy[i] = tempy; + break; + } + } + +///////////////////////////// + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( aff1_mvx[i]!=(float)HUGE_VAL && aff2_mvx[j]!=(float)HUGE_VAL && aff3_mvx[k]!=(float)HUGE_VAL ){ + assert(aff1_mvy[i]!=(float)HUGE_VAL && aff2_mvy[j]!=(float)HUGE_VAL && aff3_mvy[k]!=(float)HUGE_VAL); + aff_num ++; + } + } + } + } + + for(i=0;i<2;i++){ + if( aff2_mvx[i]!=(float)HUGE_VAL){ + assert(aff2_mvy[i]!=(float)HUGE_VAL); + left_num ++; + } + } + for(i=0;i<2;i++){ + if( aff3_mvx[i]!=(float)HUGE_VAL){ + assert(aff3_mvy[i]!=(float)HUGE_VAL); + up_num ++; + } + } + + if(enc_idx == 1){ + assert(left_num >= 1 && up_num >= 1 && aff_num >= 1); + printf("aff_num = %d\n\n",aff_num); + } + + printf("Predictors:\n"); + for(i = 0; i < 3; i ++ ){ + printf("aff1_mvx[%d] = %f, aff1_mvy[%d] = %f\naff2_mvx[%d] = %f, aff2_mvy[%d] = %f\naff3_mvx[%d] = %f, aff3_mvy[%d] = %f\n", + i,aff1_mvx[i],i,aff1_mvy[i],i,aff2_mvx[i],i,aff2_mvy[i],i,aff3_mvx[i],i,aff3_mvy[i]); + } + printf("\n\n"); + + for(i = 0; i < 3; i ++ ){ + if( !(aff1_mvx[i] == fmv->aff1_pred_mvx[i] && aff1_mvy[i] == fmv->aff1_pred_mvy[i] && + aff2_mvx[i] == fmv->aff2_pred_mvx[i] && aff2_mvy[i] == fmv->aff2_pred_mvy[i] && + aff3_mvx[i] == fmv->aff3_pred_mvx[i] && aff3_mvy[i] == fmv->aff3_pred_mvy[i] ) ){ + printf("Aff Pred Error!\nx = %d, y = %d, xblk = %d, yblk = %d\n",x,y,xblk,yblk); + for(k = 0; k < 3; k ++ ){ + printf("aff1_mvx[%d] = %f, aff1_mvy[%d] = %f\naff2_mvx[%d] = %f, aff2_mvy[%d] = %f\naff3_mvx[%d] = %f, aff3_mvy[%d] = %f\n", + k,fmv->aff1_pred_mvx[k],k,fmv->aff1_pred_mvy[k],k,fmv->aff2_pred_mvx[k],k,fmv->aff2_pred_mvy[k],k,fmv->aff3_pred_mvx[k],k, + fmv->aff3_pred_mvy[k]); + } + assert(0); + } + + } + + if(enc_idx == 1){ + if( fmv->direct_idx == DIRECT || (fmv->direct_idx == INDIRECT && fmv->merge_idx == INTER) ){ + + if(aff_num >= 9){ + getnum = fmv->aff_idx; + while(getnum >= 4){ + getnum -= 4; + putbits(1,1); + length += 1; + } + putbits(0,1); + length += 1; + assert(getnum <= 3 && getnum >= 0); + putbits(getnum,2); + length += 2; + }else if(aff_num >= 5 && aff_num <= 8){ + putbits(fmv->aff_idx,3); + length += 3; + }else if(aff_num >= 3 && aff_num <= 4){ + putbits(fmv->aff_idx,2); + length += 2; + }else if(aff_num == 2){ + putbits(fmv->aff_idx,1); + length += 1; + }else + assert(fmv->aff_idx == 0); + + }else{ + assert(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE); + + if(fmv->merge_dir == UP){ //Merge to the left + if(up_num == 2){ + putbits(fmv->aff_idx,1); //1-bit index for affine matrix prediction + length+=1; + }else + assert(fmv->aff_idx == 0); + } + else if(fmv->merge_dir == LEFT){ //Merge to the up + if(left_num == 2){ + putbits(fmv->aff_idx,1); //1-bit index for affine matrix prediction + length+=1; + }else + assert(fmv->aff_idx == 0); + } + else if(fmv->merge_dir == PAL_L){ //Must be a parallel affine mode + getnum = fmv->aff_idx; + + if(aff_num >= 9){ + while(getnum >= 4){ + getnum -= 4; + putbits(1,1); + length += 1; + } + putbits(0,1); + length += 1; + assert(getnum <= 3 && getnum >= 0); + putbits(getnum,2); + length += 2; + }else if(aff_num >= 5 && aff_num <= 8){ + putbits(fmv->aff_idx,3); + length += 3; + }else if(aff_num >= 3 && aff_num <= 4){ + putbits(fmv->aff_idx,2); + length += 2; + } + else if(aff_num == 2){ + putbits(fmv->aff_idx,1); + length += 1; + }else + assert(fmv->aff_idx == 0); + }else + assert(fmv->merge_dir == TRAN_P); //the translational predictor index has been transmitted instead + + } + }//if enc_idx + + return length; +} + + +void get_aff_mvs(vector_ptr fmv, int x, int y, int xblk, int yblk, int hor, int ver, FRAME_MOTION_FIELD* cur_frame_motion_field, SIMP_FRAME_MOTION_FIELD* prev_frame_motion_field, int dec_idx){ + int getnum, count = 0, length, aff_num = 0, up_num = 0, left_num = 0; + int i,j,k; + float aff1_mvx[3],aff1_mvy[3],aff2_mvx[3],aff2_mvy[3],aff3_mvx[3],aff3_mvy[3]; + float get1_mvx[3],get1_mvy[3],get2_mvx[3],get2_mvy[3],get3_mvx[3],get3_mvy[3]; + float tempx,tempy; + int int_mvx, int_mvy; + + int val; + float sub = 0.25; + + int subpel = (int)(1/sub); + + for(i=0;i<3;i++){ + aff1_mvx[i] = (float)HUGE_VAL;get1_mvx[i] = (float)HUGE_VAL; + aff1_mvy[i] = (float)HUGE_VAL;get1_mvy[i] = (float)HUGE_VAL; + aff2_mvx[i] = (float)HUGE_VAL;get2_mvx[i] = (float)HUGE_VAL; + aff2_mvy[i] = (float)HUGE_VAL;get2_mvy[i] = (float)HUGE_VAL; + aff3_mvx[i] = (float)HUGE_VAL;get3_mvx[i] = (float)HUGE_VAL; + aff3_mvy[i] = (float)HUGE_VAL;get3_mvy[i] = (float)HUGE_VAL; + } + +// MV1 + if(y-1>=0){ + aff1_mvx[0] = cur_frame_motion_field[(y-1)*hor + x].mvx; + aff1_mvy[0] = cur_frame_motion_field[(y-1)*hor + x].mvy; + + aff1_mvx[0] = cur_frame_motion_field[(y-2)*hor + x].mvx + 2 * (cur_frame_motion_field[(y-2)*hor + x].mvx - cur_frame_motion_field[(y-3)*hor + x].mvx); + aff1_mvy[0] = cur_frame_motion_field[(y-2)*hor + x].mvy + 2 * (cur_frame_motion_field[(y-2)*hor + x].mvy - cur_frame_motion_field[(y-3)*hor + x].mvy); + + aff1_mvx[0] = aff1_mvx[0] * AFF_SUBPEL; + aff1_mvy[0] = aff1_mvy[0] * AFF_SUBPEL; + int_mvx = (int)(aff1_mvx[0]); + int_mvy = (int)(aff1_mvy[0]); + aff1_mvx[0] = (float)(int_mvx); + aff1_mvy[0] = (float)(int_mvy); + aff1_mvx[0] = aff1_mvx[0] / AFF_SUBPEL; + aff1_mvy[0] = aff1_mvy[0] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y-2)*hor + x].mvx == (float)HUGE_VAL){ + aff1_mvx[0] = (float)HUGE_VAL; + aff1_mvy[0] = (float)HUGE_VAL; + } + } + + if(x-1>=0){ + aff1_mvx[1] = cur_frame_motion_field[y*hor + (x-1)].mvx; + aff1_mvy[1] = cur_frame_motion_field[y*hor + (x-1)].mvy; + + aff1_mvx[1] = cur_frame_motion_field[y*hor + (x-2)].mvx + 2 * (cur_frame_motion_field[y*hor + (x-2)].mvx - cur_frame_motion_field[y*hor + (x-3)].mvx); + aff1_mvy[1] = cur_frame_motion_field[y*hor + (x-2)].mvy + 2 * (cur_frame_motion_field[y*hor + (x-2)].mvy - cur_frame_motion_field[y*hor + (x-3)].mvy); + + aff1_mvx[1] = aff1_mvx[1] * AFF_SUBPEL; + aff1_mvy[1] = aff1_mvy[1] * AFF_SUBPEL; + int_mvx = (int)(aff1_mvx[1]); + int_mvy = (int)(aff1_mvy[1]); + aff1_mvx[1] = (float)(int_mvx); + aff1_mvy[1] = (float)(int_mvy); + aff1_mvx[1] = aff1_mvx[1] / AFF_SUBPEL; + aff1_mvy[1] = aff1_mvy[1] / AFF_SUBPEL; + + if(cur_frame_motion_field[y*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff1_mvx[1] = (float)HUGE_VAL; + aff1_mvy[1] = (float)HUGE_VAL; + } + } + + if(y-1>=0 && x-1>=0){ + aff1_mvx[2] = cur_frame_motion_field[(y-1)*hor + (x-1)].mvx; + aff1_mvy[2] = cur_frame_motion_field[(y-1)*hor + (x-1)].mvy; + + aff1_mvx[2] = cur_frame_motion_field[(y-2)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y-3)*hor + (x-2)].mvx) + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y-2)*hor + (x-3)].mvx); + aff1_mvy[2] = cur_frame_motion_field[(y-2)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y-3)*hor + (x-2)].mvy) + 2*(cur_frame_motion_field[(y-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y-2)*hor + (x-3)].mvy); + + aff1_mvx[2] = aff1_mvx[2] * AFF_SUBPEL; + aff1_mvy[2] = aff1_mvy[2] * AFF_SUBPEL; + int_mvx = (int)(aff1_mvx[2]); + int_mvy = (int)(aff1_mvy[2]); + aff1_mvx[2] = (float)(int_mvx); + aff1_mvy[2] = (float)(int_mvy); + aff1_mvx[2] = aff1_mvx[2] / AFF_SUBPEL; + aff1_mvy[2] = aff1_mvy[2] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y-2)*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff1_mvx[2] = (float)HUGE_VAL; + aff1_mvy[2] = (float)HUGE_VAL; + } + } + + if( fabs(aff1_mvx[1] - aff1_mvx[0]) < SMALL_DIFF && fabs(aff1_mvy[1] - aff1_mvy[0]) < SMALL_DIFF && aff1_mvx[1] != (float)HUGE_VAL && aff1_mvy[1] != (float)HUGE_VAL){ + aff1_mvx[1] = (float)HUGE_VAL; + aff1_mvy[1] = (float)HUGE_VAL; + } + if( ( ( fabs(aff1_mvx[2] - aff1_mvx[0]) < SMALL_DIFF && fabs(aff1_mvy[2] - aff1_mvy[0]) < SMALL_DIFF) || ( fabs(aff1_mvx[2] - aff1_mvx[1]) < SMALL_DIFF && fabs(aff1_mvy[2] - aff1_mvy[1]) < SMALL_DIFF) ) + && (aff1_mvx[2] != (float)HUGE_VAL && aff1_mvy[2] != (float)HUGE_VAL) ){ + aff1_mvx[2] = (float)HUGE_VAL; + aff1_mvy[2] = (float)HUGE_VAL; + } + +//TEMP + for( i = 0; i < 3 ; i ++ ){ + if( aff1_mvx[i] == (float)HUGE_VAL && aff1_mvy[i] == (float)HUGE_VAL ){ + tempx = prev_frame_motion_field[y*hor + x].mvx; + tempy = prev_frame_motion_field[y*hor + x].mvy; + + for( j = 0; j < 3 ; j ++ ){ + if( tempx != (float)HUGE_VAL && tempy != (float)HUGE_VAL && (fabs(tempx - aff1_mvx[j]) < SMALL_DIFF && fabs(tempy - aff1_mvy[j]) < SMALL_DIFF) ){ + tempx = (float)HUGE_VAL; + tempy = (float)HUGE_VAL; + } + } + aff1_mvx[i] = tempx; + aff1_mvy[i] = tempy; + break; + } + } + +// MV2 + if(y-1>=0 && x+xblk-1=0 && x+xblk=0){ + aff3_mvx[0] = cur_frame_motion_field[(y+yblk-1)*hor + (x-1)].mvx; + aff3_mvy[0] = cur_frame_motion_field[(y+yblk-1)*hor + (x-1)].mvy; + + aff3_mvx[0] = cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk-3)*hor + (x-2)].mvx) + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk-2)*hor + (x-3)].mvx); + aff3_mvy[0] = cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk-3)*hor + (x-2)].mvy) + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk-2)*hor + (x-3)].mvy); + + aff3_mvx[0] = aff3_mvx[0] * AFF_SUBPEL; + aff3_mvy[0] = aff3_mvy[0] * AFF_SUBPEL; + int_mvx = (int)(aff3_mvx[0]); + int_mvy = (int)(aff3_mvy[0]); + aff3_mvx[0] = (float)(int_mvx); + aff3_mvy[0] = (float)(int_mvy); + aff3_mvx[0] = aff3_mvx[0] / AFF_SUBPEL; + aff3_mvy[0] = aff3_mvy[0] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff3_mvx[0] = (float)HUGE_VAL; + aff3_mvy[0] = (float)HUGE_VAL; + } + } + if(y+yblk=0){ + aff3_mvx[1] = cur_frame_motion_field[(y+yblk)*hor + (x-1)].mvx; + aff3_mvy[1] = cur_frame_motion_field[(y+yblk)*hor + (x-1)].mvy; + + aff3_mvx[1] = cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk)*hor + (x-3)].mvx); + aff3_mvy[1] = cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk)*hor + (x-3)].mvy); + + aff3_mvx[1] = aff3_mvx[1] * AFF_SUBPEL; + aff3_mvy[1] = aff3_mvy[1] * AFF_SUBPEL; + int_mvx = (int)(aff3_mvx[1]); + int_mvy = (int)(aff3_mvy[1]); + aff3_mvx[1] = (float)(int_mvx); + aff3_mvy[1] = (float)(int_mvy); + aff3_mvx[1] = aff3_mvx[1] / AFF_SUBPEL; + aff3_mvy[1] = aff3_mvy[1] / AFF_SUBPEL; + + if(cur_frame_motion_field[(y+yblk)*hor + (x-2)].mvx == (float)HUGE_VAL){ + aff3_mvx[1] = (float)HUGE_VAL; + aff3_mvy[1] = (float)HUGE_VAL; + } + } + + if( fabs(aff3_mvx[1] - aff3_mvx[0]) < SMALL_DIFF && fabs(aff3_mvy[1] - aff3_mvy[0]) < SMALL_DIFF && aff3_mvx[1] != (float)HUGE_VAL && aff3_mvy[1] != (float)HUGE_VAL){ + aff3_mvx[1] = (float)HUGE_VAL; + aff3_mvy[1] = (float)HUGE_VAL; + } + + if(aff3_mvx[0] != (float)HUGE_VAL && aff3_mvy[0] != (float)HUGE_VAL && aff3_mvx[1] != (float)HUGE_VAL && aff3_mvy[1] != (float)HUGE_VAL){ + aff3_mvx[2] = (aff3_mvx[0] + aff3_mvx[1])/2; + aff3_mvy[2] = (aff3_mvy[0] + aff3_mvy[1])/2; + } + + if( ( ( fabs(aff3_mvx[2] - aff3_mvx[0]) < SMALL_DIFF && fabs(aff3_mvy[2] - aff3_mvy[0]) < SMALL_DIFF) || ( fabs(aff3_mvx[2] - aff3_mvx[1]) < SMALL_DIFF && fabs(aff3_mvy[2] - aff3_mvy[1]) < SMALL_DIFF) ) + && (aff3_mvx[2] != (float)HUGE_VAL && aff3_mvy[2] != (float)HUGE_VAL) ){ + aff3_mvx[2] = (float)HUGE_VAL; + aff3_mvy[2] = (float)HUGE_VAL; + } + +//TEMP + for( i = 0; i < 3 ; i ++ ){ + if( aff3_mvx[i] == (float)HUGE_VAL && aff3_mvy[i] == (float)HUGE_VAL ){ + tempx = prev_frame_motion_field[(y+yblk)*hor + x].mvx; + tempy = prev_frame_motion_field[(y+yblk)*hor + x].mvy; + + for( j = 0; j < 3 ; j ++ ){ + if( tempx != (float)HUGE_VAL && tempy != (float)HUGE_VAL && (fabs(tempx - aff3_mvx[j]) < SMALL_DIFF && fabs(tempy - aff3_mvy[j]) < SMALL_DIFF) ){ + tempx = (float)HUGE_VAL; + tempy = (float)HUGE_VAL; + } + } + aff3_mvx[i] = tempx; + aff3_mvy[i] = tempy; + break; + } + } + +///////////////////////////// + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if( aff1_mvx[i]!=(float)HUGE_VAL && aff2_mvx[j]!=(float)HUGE_VAL && aff3_mvx[k]!=(float)HUGE_VAL ){ + assert(aff1_mvy[i]!=(float)HUGE_VAL && aff2_mvy[j]!=(float)HUGE_VAL && aff3_mvy[k]!=(float)HUGE_VAL); + aff_num ++; + } + } + } + } + + for(i=0;i<2;i++){ + if( aff2_mvx[i]!=(float)HUGE_VAL){ + assert(aff2_mvy[i]!=(float)HUGE_VAL); + left_num ++; + } + } + for(i=0;i<2;i++){ + if( aff3_mvx[i]!=(float)HUGE_VAL){ + assert(aff3_mvy[i]!=(float)HUGE_VAL); + up_num ++; + } + } + + if(dec_idx == 1){ + + if( !(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE && fmv->merge_dir == TRAN_P) ) + assert(left_num >= 1 && up_num >= 1 && aff_num >= 1); + + printf("aff_num = %d\n\n",aff_num); + } + + printf("Predictors:\n"); + for(i = 0; i < 3; i ++ ){ + printf("aff1_mvx[%d] = %f, aff1_mvy[%d] = %f\naff2_mvx[%d] = %f, aff2_mvy[%d] = %f\naff3_mvx[%d] = %f, aff3_mvy[%d] = %f\n", + i,aff1_mvx[i],i,aff1_mvy[i],i,aff2_mvx[i],i,aff2_mvy[i],i,aff3_mvx[i],i,aff3_mvy[i]); + } + printf("\n\n"); + //////////// Added on 09.10.16 ///////////////// + if(dec_idx == 1){ + if(fmv->direct_idx == DIRECT || (fmv->direct_idx == INDIRECT && fmv->merge_idx == INTER) ){ + + if(aff_num >= 9){ + val = 0; + getnum = getbits(1); + while(getnum == 1){ + val += 4; + getnum = getbits(1); + } + + assert(getnum == 0); + getnum = getbits(2); + val += getnum; + fmv->aff_idx = val; + + }else if(aff_num >= 5 && aff_num <= 8){ + val = getbits(3); + fmv->aff_idx = val; + }else if(aff_num >= 3 && aff_num <= 4){ + val = getbits(2); + fmv->aff_idx = val; + }else if(aff_num == 2){ + val = getbits(1); + fmv->aff_idx = val; + }else + fmv->aff_idx = 0; + + }else{ + assert(fmv->direct_idx == INDIRECT && fmv->merge_idx == MERGE); + + if(fmv->merge_dir == UP){ + if(up_num == 2){ + val = getbits(1); + fmv->aff_idx = val; + }else + fmv->aff_idx = 0; + }else if(fmv->merge_dir == LEFT){ + if(left_num == 2){ + val = getbits(1); + fmv->aff_idx = val; + }else + fmv->aff_idx = 0; + }else if(fmv->merge_dir == PAL_L){ + + if(aff_num >= 9){ + val = 0; + getnum = getbits(1); + while(getnum == 1){ + val += 4; + getnum = getbits(1); + } + + assert(getnum == 0); + getnum = getbits(2); + val += getnum; + fmv->aff_idx = val; + + }else if(aff_num >= 5 && aff_num <= 8){ + val = getbits(3); + fmv->aff_idx = val; + }else if(aff_num >= 3 && aff_num <= 4){ + val = getbits(2); + fmv->aff_idx = val; + }else if(aff_num == 2){ + val = getbits(1); + fmv->aff_idx = val; + }else + fmv->aff_idx = 0; + }else + assert(fmv->merge_dir == TRAN_P); //predictors are left/right translational MVs that have been decoded. + } + }//if dec_idx + else{ + fmv->aff_idx = -1; + } + ///////////////////////////////////////////////////// + + assert(fmv->aff_idx == -1 || (fmv->aff_idx >= 0 && fmv->aff_idx <= 26) ); + + if(fmv->aff_idx >= 0) + aff_cum_idx[fmv->aff_idx]++; + + if(fmv->direct_idx == DIRECT){ + +// printf("fmv->aff_idx = %d\n",fmv->aff_idx); + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if(aff1_mvx[i]!=(float)HUGE_VAL && aff1_mvy[i]!=(float)HUGE_VAL && aff2_mvx[j]!=(float)HUGE_VAL && aff2_mvy[j]!=(float)HUGE_VAL && + aff3_mvx[k]!=(float)HUGE_VAL && aff3_mvy[k]!=(float)HUGE_VAL){ + if(count == fmv->aff_idx){ + fmv->aff1_mvx = aff1_mvx[i]; + fmv->aff1_mvy = aff1_mvy[i]; + fmv->aff2_mvx = aff2_mvx[j]; + fmv->aff2_mvy = aff2_mvy[j]; + fmv->aff3_mvx = aff3_mvx[k]; + fmv->aff3_mvy = aff3_mvy[k]; + goto sign1; + } + count++; + } + } + } + } +sign1: ; + }else if(fmv->direct_idx == INDIRECT){ + count = 0; + + if(fmv->merge_idx == MERGE){ + + if(fmv->merge_dir == UP){ + assert(fmv->aff_idx == 0 || fmv->aff_idx == 1); + fmv->aff1_mvx = cur_frame_motion_field[(y-1)*hor + x].mvx; + fmv->aff1_mvy = cur_frame_motion_field[(y-1)*hor + x].mvy; + + fmv->aff1_mvx = cur_frame_motion_field[(y-2)*hor + x].mvx + 2*(cur_frame_motion_field[(y-2)*hor + x].mvx - cur_frame_motion_field[(y-3)*hor + x].mvx); + fmv->aff1_mvy = cur_frame_motion_field[(y-2)*hor + x].mvy + 2*(cur_frame_motion_field[(y-2)*hor + x].mvy - cur_frame_motion_field[(y-3)*hor + x].mvy); + + fmv->aff1_mvx = fmv->aff1_mvx * AFF_SUBPEL; + fmv->aff1_mvy = fmv->aff1_mvy * AFF_SUBPEL; + int_mvx = (int)(fmv->aff1_mvx); + int_mvy = (int)(fmv->aff1_mvy); + fmv->aff1_mvx = (float)(int_mvx); + fmv->aff1_mvy = (float)(int_mvy); + fmv->aff1_mvx = fmv->aff1_mvx / AFF_SUBPEL; + fmv->aff1_mvy = fmv->aff1_mvy / AFF_SUBPEL; + + if(cur_frame_motion_field[(y-2)*hor + x].mvx == (float)HUGE_VAL){ + fmv->aff1_mvx = (float)HUGE_VAL; + fmv->aff1_mvy = (float)HUGE_VAL; + } + + ////////////////////////////// + fmv->aff2_mvx = cur_frame_motion_field[(y-1)*hor + (x+xblk-1)].mvx; + fmv->aff2_mvy = cur_frame_motion_field[(y-1)*hor + (x+xblk-1)].mvy; + + fmv->aff2_mvx = cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvx + 2*(cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvx - cur_frame_motion_field[(y-3)*hor + (x+xblk-2)].mvx) + 2*(cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvx - cur_frame_motion_field[(y-2)*hor + (x+xblk-3)].mvx); + fmv->aff2_mvy = cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvy + 2*(cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvy - cur_frame_motion_field[(y-3)*hor + (x+xblk-2)].mvy) + 2*(cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvy - cur_frame_motion_field[(y-2)*hor + (x+xblk-3)].mvy); + + fmv->aff2_mvx = fmv->aff2_mvx * AFF_SUBPEL; + fmv->aff2_mvy = fmv->aff2_mvy * AFF_SUBPEL; + int_mvx = (int)(fmv->aff2_mvx); + int_mvy = (int)(fmv->aff2_mvy); + fmv->aff2_mvx = (float)(int_mvx); + fmv->aff2_mvy = (float)(int_mvy); + fmv->aff2_mvx = fmv->aff2_mvx / AFF_SUBPEL; + fmv->aff2_mvy = fmv->aff2_mvy / AFF_SUBPEL; + + if(cur_frame_motion_field[(y-2)*hor + (x+xblk-2)].mvx == (float)HUGE_VAL){ + fmv->aff2_mvx = (float)HUGE_VAL; + fmv->aff2_mvy = (float)HUGE_VAL; + } + + for(i=0;i<2;i++){ + if( aff3_mvx[i] != (float)HUGE_VAL ){ + assert( aff3_mvy[i] != (float)HUGE_VAL ); + + if(fmv->aff_idx == count){ + fmv->aff3_mvx = aff3_mvx[i] + fmv->aff3_dmvx; + fmv->aff3_mvy = aff3_mvy[i] + fmv->aff3_dmvy; + break; + } + count++; + } + } + + } + else if(fmv->merge_dir == LEFT){ + assert(fmv->aff_idx == 0 || fmv->aff_idx == 1); + fmv->aff1_mvx = cur_frame_motion_field[y*hor + (x-1)].mvx; + fmv->aff1_mvy = cur_frame_motion_field[y*hor + (x-1)].mvy; + + fmv->aff1_mvx = cur_frame_motion_field[y*hor + (x-2)].mvx + 2 * (cur_frame_motion_field[y*hor + (x-2)].mvx - cur_frame_motion_field[y*hor + (x-3)].mvx); + fmv->aff1_mvy = cur_frame_motion_field[y*hor + (x-2)].mvy + 2 * (cur_frame_motion_field[y*hor + (x-2)].mvy - cur_frame_motion_field[y*hor + (x-3)].mvy); + + fmv->aff1_mvx = fmv->aff1_mvx * AFF_SUBPEL; + fmv->aff1_mvy = fmv->aff1_mvy * AFF_SUBPEL; + int_mvx = (int)(fmv->aff1_mvx); + int_mvy = (int)(fmv->aff1_mvy); + fmv->aff1_mvx = (float)(int_mvx); + fmv->aff1_mvy = (float)(int_mvy); + fmv->aff1_mvx = fmv->aff1_mvx / AFF_SUBPEL; + fmv->aff1_mvy = fmv->aff1_mvy / AFF_SUBPEL; + + if(cur_frame_motion_field[y*hor + (x-2)].mvx == (float)HUGE_VAL){ + fmv->aff1_mvx = (float)HUGE_VAL; + fmv->aff1_mvy = (float)HUGE_VAL; + } + + for(i=0;i<2;i++){ + if( aff2_mvx[i] != (float)HUGE_VAL ){ + assert( aff2_mvy[i] != (float)HUGE_VAL ); + + if(fmv->aff_idx == count){ + fmv->aff2_mvx = aff2_mvx[i] + fmv->aff2_dmvx; + fmv->aff2_mvy = aff2_mvy[i] + fmv->aff2_dmvy; + break; + } + count++; + } + } + + fmv->aff3_mvx = cur_frame_motion_field[(y+yblk-1)*hor + (x-1)].mvx; + fmv->aff3_mvy = cur_frame_motion_field[(y+yblk-1)*hor + (x-1)].mvy; + + fmv->aff3_mvx = cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk-2)*hor + (x-3)].mvx) + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx - cur_frame_motion_field[(y+yblk-3)*hor + (x-2)].mvx); + fmv->aff3_mvy = cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk-2)*hor + (x-3)].mvy) + 2*(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvy - cur_frame_motion_field[(y+yblk-3)*hor + (x-2)].mvy); + + fmv->aff3_mvx = fmv->aff3_mvx * AFF_SUBPEL; + fmv->aff3_mvy = fmv->aff3_mvy * AFF_SUBPEL; + int_mvx = (int)(fmv->aff3_mvx); + int_mvy = (int)(fmv->aff3_mvy); + fmv->aff3_mvx = (float)(int_mvx); + fmv->aff3_mvy = (float)(int_mvy); + fmv->aff3_mvx = fmv->aff3_mvx / AFF_SUBPEL; + fmv->aff3_mvy = fmv->aff3_mvy / AFF_SUBPEL; + + if(cur_frame_motion_field[(y+yblk-2)*hor + (x-2)].mvx == (float)HUGE_VAL){ + fmv->aff3_mvx = (float)HUGE_VAL; + fmv->aff3_mvy = (float)HUGE_VAL; + } + + + }else if(fmv->merge_dir == PAL_L){ + + if(fmv->aff_idx >= 0){ + assert(fmv->aff1_dmvx != (float)HUGE_VAL && fmv->aff1_dmvy != (float)HUGE_VAL && fmv->aff2_dmvx != (float)HUGE_VAL && + fmv->aff2_dmvy != (float)HUGE_VAL && fmv->aff3_dmvx != (float)HUGE_VAL && fmv->aff3_dmvy != (float)HUGE_VAL); + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if(aff1_mvx[i]!=(float)HUGE_VAL && aff1_mvy[i]!=(float)HUGE_VAL && aff2_mvx[j]!=(float)HUGE_VAL && aff2_mvy[j]!=(float)HUGE_VAL && + aff3_mvx[k]!=(float)HUGE_VAL && aff3_mvy[k]!=(float)HUGE_VAL){ + if(count == fmv->aff_idx){ + fmv->aff1_mvx = aff1_mvx[i] + fmv->aff1_dmvx; + fmv->aff1_mvy = aff1_mvy[i] + fmv->aff1_dmvy; + fmv->aff2_mvx = aff2_mvx[j] + fmv->aff2_dmvx; + fmv->aff2_mvy = aff2_mvy[j] + fmv->aff2_dmvy; + fmv->aff3_mvx = aff3_mvx[k] + fmv->aff3_dmvx; + fmv->aff3_mvy = aff3_mvy[k] + fmv->aff3_dmvy; + goto sign2; + } + count++; + } + } + } + } +sign2: ; + }//if not parallel side + }else{ + assert(fmv->merge_dir == TRAN_P); + + fmv->aff1_mvx = fmv->mvx + fmv->aff1_dmvx; + fmv->aff1_mvy = fmv->mvy + fmv->aff1_dmvy; + fmv->aff2_mvx = fmv->mvx + fmv->aff2_dmvx; + fmv->aff2_mvy = fmv->mvy + fmv->aff2_dmvy; + fmv->aff3_mvx = fmv->mvx + fmv->aff3_dmvx; + fmv->aff3_mvy = fmv->mvy + fmv->aff3_dmvy; + } + }//if MERGE + else{ + assert(fmv->merge_idx == INTER); + // printf("fmv->aff_idx = %d\n",fmv->aff_idx); + + assert(fmv->aff1_dmvx != (float)HUGE_VAL && fmv->aff1_dmvy != (float)HUGE_VAL && fmv->aff2_dmvx != (float)HUGE_VAL && + fmv->aff2_dmvy != (float)HUGE_VAL && fmv->aff3_dmvx != (float)HUGE_VAL && fmv->aff3_dmvy != (float)HUGE_VAL); + + for(i=0;i<3;i++){ + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + if(aff1_mvx[i]!=(float)HUGE_VAL && aff1_mvy[i]!=(float)HUGE_VAL && aff2_mvx[j]!=(float)HUGE_VAL && aff2_mvy[j]!=(float)HUGE_VAL && + aff3_mvx[k]!=(float)HUGE_VAL && aff3_mvy[k]!=(float)HUGE_VAL){ + if(count == fmv->aff_idx){ + fmv->aff1_mvx = aff1_mvx[i] + fmv->aff1_dmvx; + fmv->aff1_mvy = aff1_mvy[i] + fmv->aff1_dmvy; + fmv->aff2_mvx = aff2_mvx[j] + fmv->aff2_dmvx; + fmv->aff2_mvy = aff2_mvy[j] + fmv->aff2_dmvy; + fmv->aff3_mvx = aff3_mvx[k] + fmv->aff3_dmvx; + fmv->aff3_mvy = aff3_mvy[k] + fmv->aff3_dmvy; + goto sign3; + } + count++; + } + } + } + } +sign3: ; + } + } +} +//////////////////////////////// + +// the bit output for sub-symbols +void put_splitted_mvbits(char bit, char sub_index, int layer_index) +{ + (splitted_mv_byte_array[layer_index][sub_index]) <<=1; + (splitted_mv_byte_array[layer_index][sub_index]) |= bit; + if ( --(splitted_bit_num_array[layer_index][sub_index]) == 0 ) + { + store_splitted_bytes_array[layer_index][sub_index][(splitted_mv_byte_num_array[layer_index][sub_index])++] + = splitted_mv_byte_array[layer_index][sub_index]; + splitted_mv_byte_array[layer_index][sub_index] = 0; + splitted_bit_num_array[layer_index][sub_index] = 8; + } +} + + +// the bit output for addition sign +void put_splitted_signbits(char bit, int layer_index) +{ + (splitted_sign_byte[layer_index]) <<=1; + splitted_sign_byte[layer_index] |= bit; + if ( --(splitted_sign_bit_num[layer_index]) == 0 ) + { + store_splitted_sign[layer_index][(splitted_sign_byte_num[layer_index])++] = + splitted_sign_byte[layer_index]; + splitted_sign_byte[layer_index] = 0; + splitted_sign_bit_num[layer_index] = 8; + } +} + +void output_huff_bits(vector_ptr fmv1, int num, int *cnt, videoinfo info, int *mapbits){ + int i,j,k; + int max, min1, min2; + int rank; + + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); +//Triple case + if(num == 3){ + rank = 2; + for(i = 0; i <= 2; i++){ + if(i != fmv1->med_idx){ + if(cnt[fmv1->med_idx] > cnt[i]) + rank --; + else if(cnt[fmv1->med_idx] == cnt[i] && fmv1->med_idx < i) + rank --; + } + } + putbits(tripleHuffPred[rank].code, tripleHuffPred[rank].len); + *mapbits += tripleHuffPred[rank].len; + idx_info += tripleHuffPred[rank].len; + } +//Quartet case + else if(num == 4){ +//Quartet huffman tree decision + for(i = 0;i < num;i ++){ + rank = 3; + for(j = 0;j < num;j ++){ + if(j != i){ + if(cnt[i] > cnt[j]) + rank --; + else if(cnt[i] == cnt[j] && i < j) + rank --; + } + } + if(rank == 0) + max = cnt[i]; + else if(rank == 2) + min1 = cnt[i]; + else if(rank == 3) + min2 = cnt[i]; + } + if(max > min1 + min2){ //Slanted version + rank = 3; + for(i = 0; i < num; i++){ + if(i != fmv1->med_idx){ + if(cnt[fmv1->med_idx] > cnt[i]) + rank --; + else if(cnt[fmv1->med_idx] == cnt[i] && fmv1->med_idx < i) + rank --; + } + } + putbits(quartetHuffPredS[rank].code, quartetHuffPredS[rank].len); + *mapbits += quartetHuffPredS[rank].len; + idx_info += quartetHuffPredS[rank].len; + } + else{ //Flat version + putbits(fmv1->med_idx,2); + *mapbits += 2; + idx_info += 2; + } + } + else + assert(0); + +//Update distribution + cnt[fmv1->med_idx]++; + +} + +void input_huff_bits(vector_ptr fmv1, int num, int *cnt, videoinfo info){ + int i,j,bit; + int max, min1, min2, length; + + int val, getnum, rank; + +//Triple case + if(num == 3){ + rank = -1; + val = 0; + length = 0; + + while(rank == -1){ + val <<= 1; + input_bit(bit); + val |= bit; + length++; + + for(i=0;i < num;i++){ + if(tripleHuffPred[i].code == val && tripleHuffPred[i].len == length){ + rank = i; + break; + } + } + }//while + + for(i=0;i< num;i++){ + getnum = 2; + for(j=0;j< num;j++){ + if(j != i){ + if(cnt[i] > cnt[j]) + getnum --; + else if(cnt[i] == cnt[j] && i < j) + getnum --; + } + } + if(getnum == rank){ + fmv1->med_idx = i; + break; + } + } + } +//Quartet case + else if(num == 4){ +//Quartet huffman tree decision + for(i = 0;i <= 3;i ++){ + rank = 3; + for(j = 0;j <= 3;j ++){ + if(j != i){ + if(cnt[i] > cnt[j]) + rank --; + else if(cnt[i] == cnt[j] && i < j) + rank --; + } + } + if(rank == 0) + max = cnt[i]; + else if(rank == 2) + min1 = cnt[i]; + else if(rank == 3) + min2 = cnt[i]; + } + if(max > min1 + min2){ //Slanted version + rank = -1; + val = 0; + length = 0; + + while(rank == -1){ + val <<= 1; + input_bit(bit); + val |= bit; + length++; + + for(i=0;i < num;i++){ + if(quartetHuffPredS[i].code == val && quartetHuffPredS[i].len == length){ + rank = i; + break; + } + } + }//while + + for(i=0;i< num;i++){ + getnum = 3; + for(j=0;j< num;j++){ + if(j != i){ + if(cnt[i] > cnt[j]) + getnum --; + else if(cnt[i] == cnt[j] && i < j) + getnum --; + } + } + if(getnum == rank){ + fmv1->med_idx = i; + break; + } + } + } + else{ //Flat version + getnum = getbits(2); + fmv1->med_idx = getnum; + } + } + else + assert(0); + +//Update distribution + cnt[fmv1->med_idx]++; +} + +/* + * get_blockmode() + * get block mode and if in PREDICTED, also get means + */ +void +get_blockmode( vector_ptr fmv, int meandepth, videoinfo info ) +{ + int bit; + + input_bit( bit ); + if( bit == 0 ) + fmv->lifting_mode = CONNECTED; + else { + fmv->lifting_mode = PREDICTED; + } +} + +int get_mode_coding_cost(enum BiMode bi_mode, vector_ptr fmv2, int bi_sign, int t_level) +{ + if (fmv2 == NULL) { + return uni_mode_VLC[bi_mode].len; + } else { + if ( bi_sign ) + { + if (t_level<=CORRELATED_TEMPORAL_LEVELS) + { + return bi_mode_VLC_1_012[bi_mode].len; + }else + { + return bi_mode_VLC_1_345[bi_mode].len; + } + } + else + return bi_mode_VLC_0[bi_mode].len; + } +} + +int encode_block_mode(vector_ptr fmv1, vector_ptr fmv2, videoinfo info, int t_level) +{ + + int length = 0; + int getnum; + + if (fmv2 == NULL) { + putbits(uni_mode_VLC[fmv1->bi_mode].code, + uni_mode_VLC[fmv1->bi_mode].len); + length += uni_mode_VLC[fmv1->bi_mode].len; + } else { + // by Yongjun Wu + if ( info.bi_mv[t_level] ) // bi-directional motion field, including RIGHT_CONNECTED mode + { + if (t_level<=CORRELATED_TEMPORAL_LEVELS) + { + if(use_huff == 0){ + putbits(bi_mode_VLC_1_012[fmv1->bi_mode].code, + bi_mode_VLC_1_012[fmv1->bi_mode].len); + length += bi_mode_VLC_1_012[fmv1->bi_mode].len; + }else{ + assert(use_huff == 1); + putbits(bi_mode_VLC_enc_1_012[fmv1->bi_mode].code, + bi_mode_VLC_enc_1_012[fmv1->bi_mode].len); + length += bi_mode_VLC_enc_1_012[fmv1->bi_mode].len; + } + + }else + { + putbits(bi_mode_VLC_1_345[fmv1->bi_mode].code, + bi_mode_VLC_1_345[fmv1->bi_mode].len); + length += bi_mode_VLC_1_345[fmv1->bi_mode].len; + } + }else + { + assert(0); + putbits(bi_mode_VLC_0[fmv1->bi_mode].code, + bi_mode_VLC_0[fmv1->bi_mode].len); + length += bi_mode_VLC_0[fmv1->bi_mode].len; + } + } + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // code the spatial prediction mode for directional IBLOCK + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) + { + putbits(spatialmodeVLC[fmv1->iblock_spatial_mode].code, + spatialmodeVLC[fmv1->iblock_spatial_mode].len); + length += spatialmodeVLC[fmv1->iblock_spatial_mode].len; + } +#endif + +////////////////// Added by Yuan Liu //////////////////// + if(fmv1->bi_mode >= 9){ + + if(fmv2 != NULL) + assert(fmv1->bi_mode == fmv2->bi_mode); + + if(fmv1->direct_idx == DIRECT){ //This bit decides if the affine mode is DIRECT, 0 for DIRECT and 1 for non-DIRECT + + putbits(0,1); //0 for direct affine mode + length += 1; + } + else{ //INDIRECT case + putbits(1,1); //1 for indirect affine mode + length += 1; + + if(fmv1->merge_idx == MERGE){ + putbits(0,1); //0 for merge mode + length += 1; + + if(fmv1->bi_mode == BI_CONNECTED_AFF){ + + if( !(fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L || fmv1->merge_dir == TRAN_P) ) ) + assert(fmv1->aff_idx >= 0 && fmv2->aff_idx >= 0); + + if(fmv1->merge_dir == UP){ //Merge to the left + putbits(fmv1->merge_dir,2); + length += 2; + } + else if(fmv1->merge_dir == LEFT){ //Merge to the up + putbits(fmv1->merge_dir,2); + length += 2; + } + else if(fmv1->merge_dir == PAL_L){ //Must be a parallel affine mode + putbits(fmv1->merge_dir,2); + length += 2; + }else{ + assert(fmv1->merge_dir = TRAN_P); + putbits(fmv1->merge_dir,2); + length += 2; + + //transmit trans MV residual or not + putbits(fmv1->trans_pred_idx,1); + length += 1; + } + }else if(fmv1->bi_mode == LEFT_CONNECTED_AFF){ + + if(fmv1->merge_dir == UP){ //Merge to the left + putbits(0,1); + length += 1; + }else if(fmv1->merge_dir == LEFT){ //Merge to the up, 10 + putbits(2,2); + length += 2; + }else{ //Must be trans pred, 11 + assert(fmv1->merge_dir == TRAN_P); + putbits(3,2); + length += 2; + + //transmit trans MV residual or not + putbits(fmv1->trans_pred_idx,1); + length += 1; + } + }else{ + assert(fmv1->bi_mode == RIGHT_CONNECTED_AFF); + + if(fmv1->merge_dir == UP){ //Merge to the left + putbits(0,1); + length += 1; + } + else if(fmv1->merge_dir == LEFT){ //Merge to the up, 10 + putbits(2,2); + length += 2; + }else{ //Must be trans pred, 11 + assert(fmv1->merge_dir == TRAN_P); + putbits(3,2); + length += 2; + + //transmit trans MV residual or not + putbits(fmv1->trans_pred_idx,1); + length += 1; + } + } + }else{ //INTER affine mode + assert(fmv1->merge_idx == INTER); + + putbits(1,1); //1 for inter mode + length += 1; + } + } + } +///////////////// Added by Yuan Liu ///////////////////// + return length; +} + +void decode_block_mode(vector_ptr fmv1, vector_ptr fmv2, int meandepth, videoinfo info, int t_level) +{ + int i, j; + int bit, val; + const VLCtable *bi_mode_VLC; + int getnum; + + if (fmv2 == NULL) { + + fmv1->bi_mode = UNDEFINED; + fmv1->mvx = fmv1->mvy = (float)HUGE_VAL; + + fmv1->aff1_mvx = (float)HUGE_VAL; fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL; fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL; fmv1->aff3_mvy = (float)HUGE_VAL; + + i = 0; + val = 0; + while (fmv1->bi_mode == UNDEFINED) { + i++; + val <<= 1; + input_bit(bit); + val |= bit; + for (j = 0; j < NUMBER_OF_BI_MODES; j++) { + if ((uni_mode_VLC[j].len == i) && (uni_mode_VLC[j].code == val)) { + fmv1->bi_mode = (BiMode)j; + fmv1->lifting_mode = left_mode[j]; + break; + } + } + } + + } else { + + fmv1->bi_mode = UNDEFINED; + fmv1->mvx = fmv1->mvy = (float)HUGE_VAL; + fmv2->mvx = fmv2->mvy = (float)HUGE_VAL; + + fmv1->aff1_mvx = (float)HUGE_VAL; fmv1->aff1_mvy = (float)HUGE_VAL; + fmv1->aff2_mvx = (float)HUGE_VAL; fmv1->aff2_mvy = (float)HUGE_VAL; + fmv1->aff3_mvx = (float)HUGE_VAL; fmv1->aff3_mvy = (float)HUGE_VAL; + + fmv2->aff1_mvx = (float)HUGE_VAL; fmv2->aff1_mvy = (float)HUGE_VAL; + fmv2->aff2_mvx = (float)HUGE_VAL; fmv2->aff2_mvy = (float)HUGE_VAL; + fmv2->aff3_mvx = (float)HUGE_VAL; fmv2->aff3_mvy = (float)HUGE_VAL; + + i = 0; + val = 0; + if (t_level<=CORRELATED_TEMPORAL_LEVELS) + { + if(use_huff == 0) + bi_mode_VLC= bi_mode_VLC_1_012; + else + bi_mode_VLC= bi_mode_VLC_enc_1_012; + + }else{ + bi_mode_VLC= bi_mode_VLC_1_345; + } + + while (fmv1->bi_mode == UNDEFINED) { + i++; + val <<= 1; + input_bit(bit); + val |= bit; + for (j = 0; j < NUMBER_OF_BI_MODES; j++) { + if ( info.bi_mv[t_level] ) + { + if ((bi_mode_VLC[j].len == i) && (bi_mode_VLC[j].code == val)) { + fmv1->bi_mode = (BiMode)j; + fmv2->bi_mode = (BiMode)j; + fmv1->lifting_mode = left_mode[j]; + fmv2->lifting_mode = right_mode[j]; + break; + } + + }else + { + if ((bi_mode_VLC_0[j].len == i) && (bi_mode_VLC_0[j].code == val)) { + fmv1->bi_mode = (BiMode)j; + fmv2->bi_mode = (BiMode)j; + fmv1->lifting_mode = left_mode[j]; + fmv2->lifting_mode = right_mode[j]; + break; + } + } + } + } + } + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // by Yongjun Wu + // code the spatial prediction mode for directional IBLOCK + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) + { + fmv1->iblock_spatial_mode = INVALID_SPATIAL_MODE; + i = 0; + val = 0; + while (fmv1->iblock_spatial_mode == INVALID_SPATIAL_MODE) { + i++; + val <<= 1; + input_bit(bit); + val |= bit; + for (j = 0; j < PRE_MODE_NUM; j++) { + if ((spatialmodeVLC[j].len == i) && (spatialmodeVLC[j].code == val)) { + fmv1->iblock_spatial_mode = (spatialMODE)j; + if (fmv2 != NULL) + fmv2->iblock_spatial_mode = (spatialMODE)j; + break; + } + } + } + } +#endif + + if(fmv1->bi_mode == BLOCK_MERGING){ + fmv1->aff_mrg = NO; + + if(fmv2 != NULL) + fmv2->aff_mrg = NO; + } + +////////////////// Added by Yuan Liu //////////////////// + if(fmv1->bi_mode >= 9){ + + val = getbits(1); + + if(val == 0){ //DIRECT affine mode + fmv1->direct_idx = DIRECT; + if(fmv2 != NULL) + fmv2->direct_idx = DIRECT; + }else if(val == 1){//INDIRECT affine mode + + fmv1->direct_idx = INDIRECT; + if(fmv2 != NULL) + fmv2->direct_idx = INDIRECT; + + val = getbits(1); + if(val == 1){ //INTER mode + + fmv1->merge_idx = INTER; + if(fmv2 != NULL) + fmv2->merge_idx = INTER; + } + else if(val == 0){ //MERGE mode + fmv1->merge_idx = MERGE; + if(fmv2 != NULL) + fmv2->merge_idx = MERGE; + + if(fmv1->bi_mode == LEFT_CONNECTED_AFF){ + val = getbits(1);//get MERGE direction + + if(val == 0){ + fmv1->merge_dir = UP; + if(fmv2 != NULL) + fmv2->merge_dir = UP; + }else{ + assert(val == 1); + val = getbits(1); + + if(val == 0){ //LEFT merge mode, code 10 + fmv1->merge_dir = LEFT; + if(fmv2 != NULL) + fmv2->merge_dir = LEFT; + }else{ //TRAN_P merge mode, code 11 + assert(val == 1); + + fmv1->merge_dir = TRAN_P; + if(fmv2 != NULL) + fmv2->merge_dir = TRAN_P; + + val = getbits(1); + fmv1->trans_pred_idx = val; + if(fmv2 != NULL) + fmv2->trans_pred_idx = val; + } + } + }else if(fmv1->bi_mode == RIGHT_CONNECTED_AFF){ + val = getbits(1);//get MERGE direction + + if(val == 0){ + fmv1->merge_dir = UP; + if(fmv2 != NULL) + fmv2->merge_dir = UP; + }else{ + assert(val == 1); + val = getbits(1); + + if(val == 0){ //LEFT merge mode, code 10 + fmv1->merge_dir = LEFT; + if(fmv2 != NULL) + fmv2->merge_dir = LEFT; + }else{ //TRAN_P merge mode, code 11 + assert(val == 1); + + fmv1->merge_dir = TRAN_P; + if(fmv2 != NULL) + fmv2->merge_dir = TRAN_P; + + val = getbits(1); + fmv1->trans_pred_idx = val; + if(fmv2 != NULL) + fmv2->trans_pred_idx = val; + } + } + }else{ + assert(fmv1->bi_mode == BI_CONNECTED_AFF); + val = getbits(2); + assert(val >= 0 && val <= 3); + + fmv1->merge_dir = val; + fmv2->merge_dir = val; + + if( fmv1->merge_dir == PAL_L ){ + fmv1->aff_idx = 0; + fmv2->aff_idx = -1; + }else if(fmv1->merge_dir == TRAN_P){ + val = getbits(1); + + fmv1->trans_pred_idx = val; + fmv2->trans_pred_idx = val; + } + +/* if(val == 0){//UP merge + fmv1->merge_dir = val; + fmv2->merge_dir = val; + }else{//LEFT or parallel merge + assert(val == 1); + val = getbits(1); + val = val + 2; + + fmv1->merge_dir = val; + fmv2->merge_dir = val; + + if( fmv1->merge_dir == PAL_L ){ + fmv1->aff_idx = 0; + fmv2->aff_idx = -1; + } + } +*/ + } + } + } + } +///////////////// Added by Yuan Liu ///////////////////// +} + + +/****************************************************************************/ +/* child_mv_encode_further() */ +/****************************************************************************/ +void +child_mv_encode_further( vector_ptr fmv1_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int encode_parallelmv, int t_level, int blk_thresh, int count) +{ + int dmvx, dmvy, cx, cy; + int ctx_x, ctx_y; + float mvpred_x, mvpred_y; + float major_mvx, major_mvy, major_predx, major_predy, this_mvx, this_mvy; + int sub_symx, sub_symy, sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale, sub_bit; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i,num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + printf("child_mv_encode_further\n"); + assert(0); + + if( fmv1->child && xblk>blk_thresh) { + cx = x; + cy = y; + child_mv_encode_further(fmv1_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_encode_further(fmv1_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_encode_further(fmv1_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_encode_further(fmv1_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!(fmv1->child)) // there are no children for this block with size>=blk_thresh + { + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + this_mvx = fmv1->mvx; this_mvy = fmv1->mvy; + } else + { + // this is a merged (blk_thresh x blk_thresh ) block + if ( !fmv1->mv_exist) return; // no motion vector for this big block + + // irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child) + { + blk_thresh = 0; + child_mv_encode_further( fmv1_array, fmv1, fmv2, pmvx, pmvy, num_symbol, subpel, + x, y, xblk, yblk, hor, ver, info, encode_parallelmv, t_level, + blk_thresh, count); + return; + } + + if ( fmv1->merge_sign ) + { + this_mvx = fmv1->sample_mvx; + this_mvy = fmv1->sample_mvy; + }else + { + blk_thresh = 0; + child_mv_encode_further( fmv1_array, fmv1, fmv2, pmvx, pmvy, num_symbol, subpel, + x, y, xblk, yblk, hor, ver, info, encode_parallelmv, t_level, + blk_thresh, count); + return; + } + } + + if (this_mvx == (float)HUGE_VAL || this_mvy == (float)HUGE_VAL){ + if( (fmv1->bi_mode >= 9 && fmv1->bi_mode <= 11) || (fmv1->bi_mode == 7 && fmv1->aff_mrg == YES) ){ + assert(fmv1->aff1_mvx != (float)HUGE_VAL && fmv1->aff1_mvy != (float)HUGE_VAL && fmv1->aff2_mvx != (float)HUGE_VAL && + fmv1->aff2_mvy != (float)HUGE_VAL && fmv1->aff3_mvx != (float)HUGE_VAL && fmv1->aff3_mvy != (float)HUGE_VAL); + } + else{ + printf("error in mvcoding.c: mvx / mvy = (float)HUGE_VAL; " + "x = %d, y = %d, xblk = %d, yblk = %d\n", x, y, xblk, yblk ); + exit ( 1 ); + } + } + assert(0); + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, blk_thresh); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !encode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(fmv1->med_idx == -1){ + assert(num == 0); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); +// putbits(fmv1->med_idx,2); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if (!info.AGP_level[t_level]) // no AGP, layer structure( this function is always for layer structure) + { + fmv1->dmvx = this_mvx - mvpred_x; + fmv1->dmvy = this_mvy - mvpred_y; + } + + if (info.AGP_level[t_level]) // AGP, layer structure + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + +#ifdef DEBUG_SCALABLE_MV + fprintf(fpAGP_debug, "x=%03d y=%03d blk=%2d ", x, y, xblk ); + fprintf(fpAGP_debug, "major_mvx=%.1f major_mvy=%.1f major_predx=%.1f major_predy=%.1f", + major_mvx, major_mvy, major_predx, major_predy) ; + fprintf(fpAGP_debug, " dmvx=%.1f dmvy=%.1f mvx=%.2f mvy=%.2f\n", + fmv1->dmvx, fmv1->dmvy, this_mvx, this_mvy) ; +#endif + + // code the sub-symbols as binary sequence + for (sub_bit=0; sub_bit>sub_bit, sub_bit, 0); + put_splitted_mvbits( (sub_symy & (1<>sub_bit, sub_bit, 0); + } + // additional sign bit + if (major_mvx==0) // 0: positive, 1: negative + put_splitted_signbits( (this_mvx<0), 0 ); + if (major_mvy==0) // 0: positive, 1: negative + put_splitted_signbits( (this_mvy<0), 0 ); + + } + + + +#ifdef DEBUG_LAYER_STRUCTURE + char base_file[80]; + FILE *fpbase; + // make base_file and enhance_file empty + sprintf(base_file, "base%d.txt", count); + fpbase=fopen(base_file, "at"); + fprintf(fpbase, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, this_mvx, this_mvy, mvpred_x, mvpred_y); + fclose(fpbase); +#endif + + // prediction error after AGP + dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->dmvx); + dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->dmvy); + + mvStat_setPos(x, y); + mvStat_setDMV((float)dmvx, (float)dmvy); + + // get the context for coding this motion vector + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x, y, info, t_level, blk_thresh); + ec_encode_word(dmvx, ctx_x); + ec_update_model(dmvx, ctx_x); + ec_encode_word(dmvy, ctx_y); + ec_update_model(dmvy, ctx_y); + fmv1->is_predictor = YES; + mvStat_writeDMVCTX(); + // update the motion feild in this frame + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, this_mvx, this_mvy); + + } + +} + + +/****************************************************************************/ +/* child_mv_encode() */ +/****************************************************************************/ +void +child_mv_encode( vector_ptr fmv1_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int encode_parallelmv, int t_level, int blk_thresh, int count) +{ + int dmvx, dmvy, cx, cy; + int ctx_x, ctx_y; + int enc_trans; + float mvpred_x, mvpred_y; + int xblk2, yblk2; // debug + float major_mvx, major_mvy, major_predx, major_predy, this_mvx, this_mvy; + int sub_symx, sub_symy, sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale, sub_bit; + int aff1_dmvx, aff1_dmvy, aff2_dmvx, aff2_dmvy, aff3_dmvx, aff3_dmvy; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0, num_dir = 0; + int getnum; + + float getval; + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk>blk_thresh) { + cx = x; + cy = y; + child_mv_encode(fmv1_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_encode(fmv1_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_encode(fmv1_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_encode(fmv1_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) // there are no children for this block with size>=blk_thresh + { + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + + this_mvx = fmv1->mvx; + this_mvy = fmv1->mvy; + + } else //Never gonna happen, don't care! + { + printf("this is a merged (blk_thresh x blk_thresh ) block\n"); + // this is a merged (blk_thresh x blk_thresh ) block + if ( !fmv1->mv_exist ) return; // no motion vector for this big block + + if ( fmv1->merge_sign ) + { + this_mvx = fmv1->sample_mvx; + this_mvy = fmv1->sample_mvy; + }else + { + child_mv_encode_further( fmv1_array, fmv1, fmv2, pmvx, pmvy, num_symbol, subpel, + x, y, xblk, yblk, hor, ver, info, encode_parallelmv, t_level, + blk_thresh/2, count); + return; + } + } + + assert(fmv1->bi_mode >= 0); //Added ib 04.02.2016 + if(fmv2!=NULL) + assert(fmv1->bi_mode == fmv2->bi_mode); + + if (this_mvx == (float)HUGE_VAL || this_mvy == (float)HUGE_VAL){ + if( (fmv1->bi_mode >= 9 && fmv1->bi_mode <= 11) || (fmv1->bi_mode == 7 && fmv1->aff_mrg == YES)){ + if(fmv1->aff1_mvx == (float)HUGE_VAL || fmv1->aff1_mvy == (float)HUGE_VAL || fmv1->aff2_mvx == (float)HUGE_VAL || + fmv1->aff2_mvy == (float)HUGE_VAL || fmv1->aff3_mvx == (float)HUGE_VAL || fmv1->aff3_mvy == (float)HUGE_VAL){ + + printf("\nbi_mode = %d, sad_cost = %f, med_idx = %d, x = %d, y = %d, xblk = %d, yblk = %d\nfmv1->mvx = %f, fmv1->mvy = %f, fmv1->dmvx = %f, fmv1->dmvy = %f\n" + ,fmv1->bi_mode, fmv1->sad_cost, fmv1->med_idx,x,y,xblk,yblk,fmv1->mvx,fmv1->mvy,fmv1->dmvx,fmv1->dmvy); + + if(fmv1->direct_idx == DIRECT){ + printf("aff_index = %d\nfmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\n" + ,fmv1->aff_idx,fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy); + } + else if(fmv1->direct_idx != DIRECT){ + printf("aff_index = %d\nfmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\nmerge_idx = %d, merge_dir = %d\n" + ,fmv1->aff_idx,fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy,fmv1->merge_idx,fmv1->merge_dir); + if(fmv1->merge_idx == MERGE && fmv1->merge_dir == UP) + printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n", fmv1->aff3_dmvx, fmv1->aff3_dmvy); + else if(fmv1->merge_idx == MERGE && fmv1->merge_dir == LEFT) + printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n", fmv1->aff2_dmvx, fmv1->aff2_dmvy); + else{ + assert(fmv1->merge_idx == INTER); + printf("\nfmv1->aff1_dmvx = %f, fmv1->aff1_dmvy = %f\n", fmv1->aff1_dmvx, fmv1->aff1_dmvy); + printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n", fmv1->aff2_dmvx, fmv1->aff2_dmvy); + printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n\n", fmv1->aff3_dmvx, fmv1->aff3_dmvy); + } + } + assert(0); + } + } + else{ + printf("error in mvcoding.c: mvx / mvy = (float)HUGE_VAL; " + "x = %d, y = %d, xblk = %d, yblk = %d\n", x, y, xblk, yblk ); + exit ( 1 ); + } + } + + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, blk_thresh); //Get translational motion field, may be still useful in AFFINE MODEL + + ///////////////////////////////// + if( (fmv1->bi_mode <= 8 && !(fmv1->bi_mode == PARALLEL && !encode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING) || + ( fmv1->bi_mode>=9 && fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == INDIR) ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL){ + num++; + if(fmv1->bi_mode == BLOCK_MERGING){ + if( (float(x)-mvpredstr_x[i] >= 0) && (float(x)-mvpredstr_x[i]<= (hor - xblk2)) && (float(y)-mvpredstr_y[i] >= 0) + && (float(y) - mvpredstr_y[i] <= (ver - yblk2)) ) + num_dir++; + } + } + } + + if(num == 0){ + assert(fmv1->med_idx == -1); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + if(fmv1->bi_mode == BLOCK_MERGING){ + if(num_dir > 0){//Encode the med_idx only if there is something fit for BLOCK_MERGING mode + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + else{ + assert(fmv1->med_idx == -1); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + } + else{ + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + }else if( (fmv1->bi_mode == PARALLEL && !encode_parallelmv) ){ + fmv1->med_idx = fmv2->med_idx; + } + + if (!info.AGP_level[t_level]) // AGP, layer structure only or no layer + { + if( ((fmv1->bi_mode == PARALLEL) && !encode_parallelmv) || (fmv1->bi_mode == BLOCK_MERGING) ){ + fmv1->dmvx = 0.0; + fmv1->dmvy = 0.0; + }else if( fmv1->bi_mode >= 9 && fmv1->bi_mode <= 11 ){ + if(fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == INDIR){ + assert( fmv1->dmvx == (fmv1->mvx - mvpred_x) && fmv1->dmvy == (fmv1->mvy - mvpred_y) ); + }else{ + fmv1->dmvx = 0.0; + fmv1->dmvy = 0.0; + } + + }else{ + fmv1->dmvx = this_mvx - mvpred_x; + fmv1->dmvy = this_mvy - mvpred_y; + } + /////////////////////////////////////// + if( (fmv1->bi_mode == BLOCK_MERGING) && (fmv1->dmvx != 0 || fmv1->dmvy!= 0) ){ + assert(0); + } + /////////////////////////////////////// + } + else if (info.AGP_level[t_level]) // AGP - Never happened, don't care! + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + +#ifdef DEBUG_SCALABLE_MV + fprintf(fpAGP_debug, "x=%03d y=%03d blk=%2d ", x, y, xblk ); + fprintf(fpAGP_debug, "major_mvx=%.1f major_mvy=%.1f major_predx=%.1f major_predy=%.1f", + major_mvx, major_mvy, major_predx, major_predy) ; + fprintf(fpAGP_debug, " dmvx=%.1f dmvy=%.1f mvx=%.2f mvy=%.2f\n", + fmv1->dmvx, fmv1->dmvy, this_mvx, this_mvy) ; +#endif + + if ( !info.layer_mv[t_level] ) // no layer structure: put sub-symbol + { + // motion vector in BLOCK_MERGING block should be perfectly predicted + assert((fmv1->bi_mode != BLOCK_MERGING)|| + (sub_symx == sub_sym_predx && sub_symy==sub_sym_predy && + fmv1->dmvx ==0 && fmv1->dmvy == 0 )); + if ( (fmv1->bi_mode != BLOCK_MERGING) && !( (fmv1->bi_mode == PARALLEL) && !encode_parallelmv ) ) { + // code the sub-symbols as binary sequence + for (sub_bit=0; sub_bit>sub_bit, sub_bit, 0); + put_splitted_mvbits( (sub_symy & (1<>sub_bit, sub_bit, 0); + } + // additional sign bit + if (major_mvx==0) // 0: positive, 1: negative + put_splitted_signbits( (this_mvx<0), 0 ); + if (major_mvy==0) // 0: positive, 1: negative + put_splitted_signbits( (this_mvy<0), 0 ); + } + }else // layer structure : put sub-symbol + { + // code the sub-symbols as binary sequence + for (sub_bit=0; sub_bit>sub_bit, sub_bit, 0); + put_splitted_mvbits( (sub_symy & (1<>sub_bit, sub_bit, 0); + } + // additional sign bit + if (major_mvx==0) // 0: positive, 1: negative + put_splitted_signbits( (this_mvx<0), 0 ); + if (major_mvy==0) // 0: positive, 1: negative + put_splitted_signbits( (this_mvy<0), 0 ); + } + }// AGP + +#ifdef DEBUG_LAYER_STRUCTURE + char base_file[80]; + FILE *fpbase; + // make base_file and enhance_file empty + sprintf(base_file, "base%d.txt", count); + fpbase=fopen(base_file, "at"); + fprintf(fpbase, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, this_mvx, this_mvy, mvpred_x, mvpred_y); + fclose(fpbase); +#endif + + if (!info.layer_mv[t_level] ) // no layer structure, AGP or no AGP + assert( fmv1->bi_mode != BLOCK_MERGING || fmv1->dmvx==0 && fmv1->dmvy==0 ); + + // prediction error after AGP or no AGP + dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->dmvx); + dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->dmvy); + + if( fmv1->bi_mode >= 9 && fmv1->bi_mode <= 11 ){ + if(fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE){ + if(fmv1->merge_dir == LEFT){ + aff2_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff2_dmvx); + aff2_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff2_dmvy); + // printf("aff2_dmvx = %d, aff2_dmvy = %d\n",aff2_dmvx,aff2_dmvy); + }else if(fmv1->merge_dir == UP){ + aff3_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff3_dmvx); + aff3_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff3_dmvy); + // printf("aff3_dmvx = %d, aff3_dmvy = %d\n",aff3_dmvx,aff3_dmvy); + }else if( (fmv1->merge_dir == PAL_L && fmv1->aff_idx >= 0) || fmv1->merge_dir == TRAN_P ){ + aff1_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff1_dmvx); + aff1_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff1_dmvy); + // printf("aff1_dmvx = %d, aff1_dmvy = %d\n",aff1_dmvx,aff1_dmvy); + + aff2_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff2_dmvx); + aff2_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff2_dmvy); + // printf("aff2_dmvx = %d, aff2_dmvy = %d\n",aff2_dmvx,aff2_dmvy); + + aff3_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff3_dmvx); + aff3_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff3_dmvy); + // printf("aff3_dmvx = %d, aff3_dmvy = %d\n",aff3_dmvx,aff3_dmvy); + } + }else if(fmv1->direct_idx == INDIRECT && fmv1->merge_idx == INTER){ + aff1_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff1_dmvx); + aff1_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff1_dmvy); +// printf("aff1_dmvx = %d, aff1_dmvy = %d\n",aff1_dmvx,aff1_dmvy); + + aff2_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff2_dmvx); + aff2_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff2_dmvy); +// printf("aff2_dmvx = %d, aff2_dmvy = %d\n",aff2_dmvx,aff2_dmvy); + + aff3_dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff3_dmvx); + aff3_dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->aff3_dmvy); +// printf("aff3_dmvx = %d, aff3_dmvy = %d\n",aff3_dmvx,aff3_dmvy); + } + } + + mvStat_setPos(x, y); + mvStat_setDMV((float)dmvx, (float)dmvy); + + if (!info.layer_mv[t_level]) // no layer structure, AGP or no AGP + { + if ( (fmv1->bi_mode <=8 && fmv1->bi_mode != BLOCK_MERGING && !(fmv1->bi_mode == PARALLEL && !encode_parallelmv)) || + ( (fmv1->bi_mode>=9 && fmv1->bi_mode<=11) && (fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == INDIR) ) ) // Translational model + { + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x, y, info, t_level, blk_thresh); + + if (EC_TYPE == AR_NARY) + { + if (dmvx > num_symbol / 2) + dmvx -= num_symbol; + else if (dmvx < -(num_symbol / 2)) + dmvx += num_symbol; + if (dmvy > num_symbol / 2) + dmvy -= num_symbol; + else if (dmvy < -(num_symbol / 2)) + dmvy += num_symbol; + } + ec_encode_word(dmvx, ctx_x); + ec_update_model(dmvx, ctx_x); + ec_encode_word(dmvy, ctx_y); + ec_update_model(dmvy, ctx_y); + } + + if( fmv1->bi_mode >=9 && fmv1->bi_mode <=11 ){ // Affine model employed + + if(fmv1->direct_idx == INDIRECT){ +//affine V1 + if(fmv1->merge_idx == INTER || + (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0 ) + || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x, y, info, t_level, blk_thresh); + + if (EC_TYPE == AR_NARY) + { + if (aff1_dmvx > num_symbol / 2) + aff1_dmvx -= num_symbol; + else if (aff1_dmvx < -(num_symbol / 2)) + aff1_dmvx += num_symbol; + if (aff1_dmvy > num_symbol / 2) + aff1_dmvy -= num_symbol; + else if (aff1_dmvy < -(num_symbol / 2)) + aff1_dmvy += num_symbol; + } + ec_encode_word(aff1_dmvx, ctx_x); + ec_update_model(aff1_dmvx, ctx_x); + ec_encode_word(aff1_dmvy, ctx_y); + ec_update_model(aff1_dmvy, ctx_y); + } +//affine V2 + if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && fmv1->merge_dir == LEFT) || + (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) + || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x+xblk2-1, y, info, t_level, blk_thresh); + + if (EC_TYPE == AR_NARY) + { + if (aff2_dmvx > num_symbol / 2) + aff2_dmvx -= num_symbol; + else if (aff2_dmvx < -(num_symbol / 2)) + aff2_dmvx += num_symbol; + if (aff2_dmvy > num_symbol / 2) + aff2_dmvy -= num_symbol; + else if (aff2_dmvy < -(num_symbol / 2)) + aff2_dmvy += num_symbol; + } + ec_encode_word(aff2_dmvx, ctx_x); + ec_update_model(aff2_dmvx, ctx_x); + ec_encode_word(aff2_dmvy, ctx_y); + ec_update_model(aff2_dmvy, ctx_y); + } +//affine V3 + if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && fmv1->merge_dir == UP) || + (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) || + (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x, y+yblk2-1, info, t_level, blk_thresh); + + if (EC_TYPE == AR_NARY) + { + if (aff3_dmvx > num_symbol / 2) + aff3_dmvx -= num_symbol; + else if (aff3_dmvx < -(num_symbol / 2)) + aff3_dmvx += num_symbol; + if (aff3_dmvy > num_symbol / 2) + aff3_dmvy -= num_symbol; + else if (aff3_dmvy < -(num_symbol / 2)) + aff3_dmvy += num_symbol; + } + ec_encode_word(aff3_dmvx, ctx_x); + ec_update_model(aff3_dmvx, ctx_x); + ec_encode_word(aff3_dmvy, ctx_y); + ec_update_model(aff3_dmvy, ctx_y); + } + }// if INDIRECT + else //DIRECT mode, don't code anything + { + assert(fmv1->direct_idx == DIRECT); + } + } + + assert(fmv1->is_predictor == YES); + mvStat_writeDMVCTX(); + }else // layer structure, AGP or no AGP + { + printf("layer structure detected!\n"); + assert(0); + + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x, y, info, t_level, blk_thresh); + ec_encode_word(dmvx, ctx_x); + ec_update_model(dmvx, ctx_x); + ec_encode_word(dmvy, ctx_y); + ec_update_model(dmvy, ctx_y); + fmv1->is_predictor = YES; + mvStat_writeDMVCTX(); + } + + ///////////////////////// +// printf("bi_mode = %d, x = %d, y = %d, xblk = %d, yblk = %d, ctx_x = %d, ctx_y = %d\n fmv->dmvx = %f, fmv->dmvy = %f\n", +// fmv1->bi_mode,x,y,xblk2,yblk2,ctx_x, ctx_y,fmv1->dmvx,fmv1->dmvy); + ///////////////////////// + + if(fmv1->bi_mode == 1 || fmv1->bi_mode == 2 || fmv1->bi_mode == 4 || fmv1->bi_mode == 5 || fmv1->bi_mode == 10 || fmv1->bi_mode == 11){ + calc_res_sad += fmv1->sad_cost; + } + else{ + calc_res_sad += fmv1->sad_cost/2; + } + + // update the motion field in this frame + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, this_mvx, this_mvy); + + } + +} + + +/****************************************************************************/ +/* child_mv_encode_enhance_sub() */ +/****************************************************************************/ +void +child_mv_encode_enhance_sub( vector_ptr fmv1_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int encode_parallelmv, int t_level, int blk_thresh, + int *first_available, int count, int merge_sign) +{ + int dmvx, dmvy, cx, cy; + int ctx_x, ctx_y; + float mvpred_x, mvpred_y; + int xblk2, yblk2; // debug + float major_mvx, major_mvy, major_predx, major_predy; + int sub_symx, sub_symy, sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale, sub_bit; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + printf("child_mv_encode_enhance_sub\n"); + + if( fmv1->child && xblk>blk_thresh) { + cx = x; + cy = y; + child_mv_encode_enhance_sub(fmv1_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, first_available, + count, merge_sign); + + cx = x + xblk / 2; + cy = y; + child_mv_encode_enhance_sub(fmv1_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, first_available, + count, merge_sign); + + cx = x; + cy = y + yblk / 2; + child_mv_encode_enhance_sub(fmv1_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, first_available, + count, merge_sign); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_encode_enhance_sub(fmv1_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, first_available, + count, merge_sign); + } else { + if( x >= hor || y >= ver ) return; + + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + assert(0); + // re-do the spatial prediction no matter it's first motion vector or not + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !encode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(fmv1->med_idx == -1){ + assert(num == 0); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); + putbits(fmv1->med_idx,2); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + } + + if (info.AGP_level[t_level]) // AGP + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + + if (!merge_sign) return; + + if ( *first_available ) // the first motion vector is in base layer + { + *first_available = 0; + return; + } + + // because this is true motion field + assert((fmv1->bi_mode != BLOCK_MERGING)||(fmv1->dmvx==0 && fmv1->dmvy==0)); + + // prediction error after AGP + dmvx = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->dmvx); + dmvy = (int) ((1 << (subpel-info.AGP_level[t_level]) ) * fmv1->dmvy); + + mvStat_setPos(x, y); + mvStat_setDMV((float)dmvx, (float)dmvy); + +#ifdef DEBUG_LAYER_STRUCTURE + char enhance_file[80]; + FILE *fpenhance; + // make base_file and enhance_file empty + sprintf(enhance_file, "enhance%d.txt", count); + fpenhance=fopen(enhance_file, "at"); + fprintf(fpenhance, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, fmv1->mvx, fmv1->mvy, mvpred_x, mvpred_y); + fclose(fpenhance); +#endif + + if ( (fmv1->bi_mode != BLOCK_MERGING) && !((fmv1->bi_mode == PARALLEL) && !encode_parallelmv) ) + { + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x, y, info, t_level, blk_thresh); + ec_encode_word(dmvx, ctx_x); + ec_update_model(dmvx, ctx_x); + ec_encode_word(dmvy, ctx_y); + ec_update_model(dmvy, ctx_y); + } + + if ( info.AGP_level[t_level] ) + { + assert((fmv1->bi_mode != BLOCK_MERGING)|| + (sub_symx == sub_sym_predx && sub_symy==sub_sym_predy && + fmv1->dmvx ==0 && fmv1->dmvy == 0 )); + if ( (fmv1->bi_mode != BLOCK_MERGING) && + !( (fmv1->bi_mode == PARALLEL) && !encode_parallelmv ) ) { + // code the sub-symbols as binary sequence + for (sub_bit=0; sub_bit>sub_bit, sub_bit, 1); + put_splitted_mvbits( (sub_symy & (1<>sub_bit, sub_bit, 1); + } + // additional sign bit + if (major_mvx==0) // 0: positive, 1: negative + put_splitted_signbits( (fmv1->mvx<0), 1 ); + if (major_mvy==0) // 0: positive, 1: negative + put_splitted_signbits( (fmv1->mvy<0), 1 ); + } + } + + mvStat_writeDMVCTX(); + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + assert( (x + xblk2 - fmv1->mvx <= hor ) && + (y + yblk2 - fmv1->mvy <= ver ) && + (x - fmv1->mvx >= 0 ) && + (y - fmv1->mvy >= 0 ) ); + assert( (!(fmv1->bi_mode == PARALLEL)) || + ((x + xblk2 - fmv2->mvx <= hor ) && + (y + yblk2 - fmv2->mvy <= ver ) && + (x - fmv2->mvx >= 0 ) && + (y - fmv2->mvy >= 0 )) ); + } +} + +/****************************************************************************/ +/* child_mv_encode_enhance_further() */ +/****************************************************************************/ +void +child_mv_encode_enhance_further( vector_ptr fmv1_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int encode_parallelmv, int t_level, int blk_thresh, int count) +{ + int cx, cy; + float mvpred_x, mvpred_y; + int first_available; + float major_mvx, major_mvy, major_predx, major_predy; + int sub_symx, sub_symy, sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk>blk_thresh) { + cx = x; + cy = y; + child_mv_encode_enhance_further(fmv1_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_encode_enhance_further(fmv1_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_encode_enhance_further(fmv1_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_encode_enhance_further(fmv1_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child ) // if there are no children for this block with size>=blk_thresh + { + // no motion vector for this block on this side + if (fmv1->lifting_mode == IGNORED) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + assert(0); + // re-do the spatial prediction + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !encode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(fmv1->med_idx == -1){ + assert(num == 0); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); + putbits(fmv1->med_idx,2); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else // with AGP + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + return; + } else + { + if ( !fmv1->mv_exist ) return; + + // classified as irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child) + fmv1->merge_sign = 0; + + first_available = 1; + blk_thresh = 0; + child_mv_encode_enhance_sub( fmv1_array, fmv1, fmv2, pmvx, pmvy, num_symbol, subpel, + x, y, xblk, yblk, hor, ver, info, encode_parallelmv, + t_level, blk_thresh, &first_available, count, fmv1->merge_sign); + } + } +} + + +/****************************************************************************/ +/* child_mv_encode_enhance() */ +/****************************************************************************/ +void +child_mv_encode_enhance( vector_ptr fmv1_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int encode_parallelmv, int t_level, int blk_thresh, int count) +{ + int cx, cy; + float mvpred_x, mvpred_y; + int first_available; + float major_mvx, major_mvy, major_predx, major_predy; + int sub_symx, sub_symy, sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + printf("child_mv_encode_enhance\n"); + + if( fmv1->child && xblk>blk_thresh) { + cx = x; + cy = y; + child_mv_encode_enhance(fmv1_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_encode_enhance(fmv1_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_encode_enhance(fmv1_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_encode_enhance(fmv1_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child ) // if there are no children for this block with size>=blk_thresh + { + // no motion vector for this block on this side + if (fmv1->lifting_mode == IGNORED) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + assert(0); + // re-do the spatial prediction + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !encode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(fmv1->med_idx == -1){ + assert(num == 0); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); + putbits(fmv1->med_idx,2); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + return; + } else + { + if ( !fmv1->mv_exist ) return; + + if ( fmv1->merge_sign ) + { + first_available = 1; + blk_thresh = 0; + child_mv_encode_enhance_sub( fmv1_array, fmv1, fmv2, pmvx, pmvy, num_symbol, subpel, + x, y, xblk, yblk, hor, ver, info, encode_parallelmv, + t_level, blk_thresh, &first_available, count, fmv1->merge_sign); + }else + { + child_mv_encode_enhance_further( fmv1_array, fmv1, fmv2, + pmvx, pmvy, num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, encode_parallelmv, t_level, blk_thresh/2, count); + } + } + } +} + + +/****************************************************************************/ +/* child_map_pre_encode() */ +/****************************************************************************/ +void child_map_pre_encode( vector_ptr fmv1, vector_ptr fmv2, int x, int y, + int xblk, int yblk, int hor, int ver, int small, + videoinfo info, int t_level ) +{ + int cx, cy; + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child ) { + +// ctl_info ++; + + cx = x; + cy = y; + child_map_pre_encode( fmv1->child0, fmv2 ? fmv2->child0 : NULL, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + + cx = x + xblk / 2; + cy = y; + child_map_pre_encode( fmv1->child1, fmv2 ? fmv2->child1 : NULL, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + + cx = x; + cy = y + yblk / 2; + child_map_pre_encode( fmv1->child2, fmv2 ? fmv2->child2 : NULL, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_map_pre_encode( fmv1->child3, fmv2 ? fmv2->child3 : NULL, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + } else { + + if( x >= hor || y >= ver ) return; + + if(fmv2 != NULL){ + ///////////////// + assert(fmv1->bi_mode >= 0 && fmv1->bi_mode <= 11); + if (t_level<=CORRELATED_TEMPORAL_LEVELS) + bi_mode_num012[fmv1->bi_mode] ++; + else + bi_mode_num345[fmv1->bi_mode] ++; + ///////////////// + } + } + +} + +/****************************************************************************/ +/* child_map_encode() */ +/****************************************************************************/ +void +child_map_encode( vector_ptr fmv1, vector_ptr fmv2, int *mapbit, int x, int y, + int xblk, int yblk, int hor, int ver, int small, + videoinfo info, int t_level ) +{ + int cx, cy; + + int middle; + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child ) { + output_bit( 1 ); + ( *mapbit )++; +// ctl_info ++; + + cx = x; + cy = y; + child_map_encode( fmv1->child0, fmv2 ? fmv2->child0 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + + cx = x + xblk / 2; + cy = y; + child_map_encode( fmv1->child1, fmv2 ? fmv2->child1 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + + cx = x; + cy = y + yblk / 2; + child_map_encode( fmv1->child2, fmv2 ? fmv2->child2 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_map_encode( fmv1->child3, fmv2 ? fmv2->child3 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level ); + } else { + //////////////////// + avg_blk_size[t_level] += xblk; + blk_num ++; + //////////////////// + if( x >= hor || y >= ver ) return; + if( xblk > small ) { + output_bit( 0 ); + ( *mapbit )++; /*for tree structure */ +// ctl_info ++; + } + //output block mode + middle = encode_block_mode(fmv1, fmv2, info, t_level); + + (*mapbit) += middle; +// ctl_info += middle; + + } +} + +// further selective mergence from 8x8->16x16 +void +child_merge_encode_further( vector_ptr fmv1, vector_ptr fmv2, int *mapbit, int x, int y, + int xblk, int yblk, int hor, int ver, int small, + videoinfo info, int t_level, int blk_thresh, int count ) +{ + int cx, cy; + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + if( fmv1->child && xblk>blk_thresh) { + + cx = x; + cy = y; + child_merge_encode_further( fmv1->child0, fmv2 ? fmv2->child0 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + + cx = x + xblk / 2; + cy = y; + child_merge_encode_further( fmv1->child1, fmv2 ? fmv2->child1 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + + cx = x; + cy = y + yblk / 2; + child_merge_encode_further( fmv1->child2, fmv2 ? fmv2->child2 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_merge_encode_further( fmv1->child3, fmv2 ? fmv2->child3 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) return; + + if (!fmv1->mv_exist) return; // no subsampled motion vector in this big block + + // irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child ) + return; + + assert( fmv1->merge_sign==0 || fmv1->merge_sign==1); + output_bit( fmv1->merge_sign ); + ( *mapbit )++; + + FILE *fmerge; + char merge_file[80]; + sprintf(merge_file, "merge_sign%d.txt", count); + fmerge = fopen(merge_file, "at"); + fprintf(fmerge, "%d\n", fmv1->merge_sign); + fclose(fmerge); + + } +} + + +/****************************************************************************/ +/* child_merge_encode() */ +/****************************************************************************/ +void +child_merge_encode( vector_ptr fmv1, vector_ptr fmv2, int *mapbit, int x, int y, + int xblk, int yblk, int hor, int ver, int small, + videoinfo info, int t_level, int blk_thresh, int count ) +{ + int cx, cy; + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + if( fmv1->child && xblk>blk_thresh) { + + cx = x; + cy = y; + child_merge_encode( fmv1->child0, fmv2 ? fmv2->child0 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + + cx = x + xblk / 2; + cy = y; + child_merge_encode( fmv1->child1, fmv2 ? fmv2->child1 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + + cx = x; + cy = y + yblk / 2; + child_merge_encode( fmv1->child2, fmv2 ? fmv2->child2 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_merge_encode( fmv1->child3, fmv2 ? fmv2->child3 : NULL, mapbit, + cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level, + blk_thresh, count ); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) return; + + if (!fmv1->mv_exist) return; // no subsampled motion vector in this big block + + printf("ain't returned from child_merge_encode"); + assert(0); + + FILE *fmerge; + char merge_file[80]; + sprintf(merge_file, "merge_sign%d.txt", count); + fmerge = fopen(merge_file, "at"); + fprintf(fmerge, "%d\n", fmv1->merge_sign); + fclose(fmerge); + + assert( fmv1->merge_sign==0 || fmv1->merge_sign==1); + output_bit( fmv1->merge_sign ); + ( *mapbit )++; + if (! fmv1->merge_sign ) + // further selective mergence from 8x8->16x16 + child_merge_encode_further( fmv1, fmv2, mapbit, x, y, xblk, yblk, + hor, ver, small, info, t_level, blk_thresh/2, count ); + } +} + +///////////////// Added by Yuan Liu on 01.30.2016 ///////////////////// +/*****************************************************************************/ +/* child_cand_encode() */ +/*****************************************************************************/ +void +child_cand_encode( int *mapbit, vector_ptr fmv1_array, vector_ptr fmv1, vector_ptr fmv2_array, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int encode_parallelmv, int t_level, int blk_thresh, int count ) +{ + int xblk2,yblk2,cx,cy; + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0, num_dir = 0, mrg_num = 0; + int getnum; + int ctx_x, ctx_y; + int middle; + + FLAG do_fmv1 = YES, do_fmv2 = YES; + int map_side; + vector_ptr mrg_left[4],mrg_right[4]; + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk>blk_thresh) { + + if(fmv2!=NULL) + assert(fmv2->child); + + cx = x; + cy = y; + child_cand_encode(mapbit, fmv1_array, fmv1->child0, fmv2_array, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_cand_encode(mapbit, fmv1_array, fmv1->child1, fmv2_array, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_cand_encode(mapbit, fmv1_array, fmv1->child2, fmv2_array, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_cand_encode(mapbit, fmv1_array, fmv1->child3, fmv2_array, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, encode_parallelmv, t_level, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) // there are no children for this block with size>=blk_thresh + { + if(fmv2 != NULL) + assert(!fmv2->child); + + //We must decide lifting mode of MERGE blocks in ME stage, for subbands will be generated before MV encoding stage + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) do_fmv1 = NO; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) do_fmv1 = NO; +#endif + if (fmv1->lifting_mode == UNDECIDED) assert(0); + + if(fmv2 != NULL){ + // no motion vector for this block on this side + if ((fmv2->lifting_mode == IGNORED)) do_fmv2 = NO; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv2->bi_mode==DIRECTIONAL_IBLOCK) do_fmv2 = NO; +#endif + if (fmv2->lifting_mode == UNDECIDED) assert(0); + } + }else + assert(0); + + /////////////// MERGE detection /////////////////////// + if( fmv1->bi_mode == BLOCK_MERGING || ( fmv1->bi_mode>=9 && fmv1->direct_idx == INDIRECT && + fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == DIR) ){ + + assert(do_fmv1 == YES || do_fmv2 == YES); + + if(fmv2 != NULL) + assert(fmv1->med_idx == fmv2->med_idx); + + for(i=0;i<=3;i++){ + mrg_left[i] = new vector; + mrg_right[i] = new vector; + + clean_mrg_mv(mrg_left[i]); + clean_mrg_mv(mrg_right[i]); + } + + if(fmv1->aff_mrg == YES){ +// printf("Aff MRG blk: cx = %d, cy = %d, xblk = %d, yblk = %d\n",x,y,xblk2,yblk2); + } + + if(fmv2 != NULL) + get_field_merge_mv_info(mrg_left, mrg_right,x,y,xblk2,yblk2,hor,ver,info,t_level,frame_motion_field, frame_motion_field2, prev_frame_motion_field2, prev_frame_motion_field1,0); + else + get_field_merge_mv_info(mrg_left, mrg_right,x,y,xblk2,yblk2,hor,ver,info,t_level,frame_motion_field, frame_motion_field2, prev_frame_motion_field2, prev_frame_motion_field1,1); + + for(i=0;i<=3;i++){ + + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) + || (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + mrg_num ++; + } + } +// printf("mrg_num = %d\n",mrg_num); + if(mrg_num == 0) + assert(0); + + /////////////////// MRG idx enc ////////////////// + if(mrg_num == 0) + assert(fmv1->med_idx == -1); + else if(mrg_num == 1) + assert(fmv1->med_idx == 0); + else if( mrg_num == 2){ + putbits(fmv1->med_idx,1); + *mapbit += 1; + idx_info += 1; + }else{ + assert(mrg_num == 3 || mrg_num == 4); + if(mrg_num == 3) + output_huff_bits(fmv1,mrg_num,cnt_tri,info,mapbit); + else + output_huff_bits(fmv1,mrg_num,cnt_quad,info,mapbit); + } + + ////////////////////////////////////////////////// + if(fmv1->bi_mode == BLOCK_MERGING){ + if(mrg_left[fmv1->med_idx]->aff1_mvx != (float)HUGE_VAL || mrg_right[fmv1->med_idx]->aff1_mvx != (float)HUGE_VAL){ + assert( (mrg_left[fmv1->med_idx]->aff2_mvx != (float)HUGE_VAL && mrg_left[fmv1->med_idx]->aff3_mvx != (float)HUGE_VAL) || + (mrg_right[fmv1->med_idx]->aff2_mvx != (float)HUGE_VAL && mrg_right[fmv1->med_idx]->aff3_mvx != (float)HUGE_VAL) ); + aff_mrg_blk ++; + + assert(fmv1->aff_mrg == 0 || fmv1->aff_mrg == 1); + putbits(fmv1->aff_mrg,1); + *mapbit += 1; + idx_info += 1; + } + } + /////////////////////////////////////////////////// + + }//if BLOCK_MERGING + /////////////////////////////////////////////////////// + + if(do_fmv1 == YES){ + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + map_side = encode_parallelmv; + assert(map_side == 1); + + if( ( fmv1->bi_mode <= 8 && !(fmv1->bi_mode == PARALLEL && !map_side) && fmv1->bi_mode != BLOCK_MERGING ) || + (fmv1->bi_mode >= 9 && fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == INDIR) ){ + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL){ + num++; + if(fmv1->bi_mode == BLOCK_MERGING){ + if( (float(x)-mvpredstr_x[i] >= 0) && (float(x)-mvpredstr_x[i]<= (hor - xblk2)) && (float(y)-mvpredstr_y[i] >= 0) + && (float(y) - mvpredstr_y[i] <= (ver - yblk2)) ) + num_dir++; + } + } + } + + if(num == 0) + assert(fmv1->med_idx == -1); + else if(num == 1){ + assert(fmv1->med_idx == 0); + } + else if(num == 2){ + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 1); + putbits(fmv1->med_idx,1); + *mapbit += 1; + idx_info += 1; + + } + else{ + assert(num == 3 || num == 4); + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3); + if(num == 3) + output_huff_bits(fmv1,num,cnt_tri,info,mapbit); + else + output_huff_bits(fmv1,num,cnt_quad,info,mapbit); + idx_info += 2; + } + + } + + if( fmv1->bi_mode >= 9 ){ + middle = put_aff_mvs(fmv1,x,y,xblk2,yblk2,hor,ver,frame_motion_field, prev_frame_motion_field2,1); + (*mapbit) += middle; + } + ///////////////////////////////////////////////////////////// + + fmv1->is_predictor = YES; + +// printf("\nfmv->bi_mode=%d, fmv->med_idx=%d", fmv1->bi_mode,fmv1->med_idx); + + ////////////// Added by Yuan Liu ////////////////// + if(fmv1->bi_mode >= 7 && fmv1->bi_mode <= 11){ + if( (fmv1->bi_mode == 7 && fmv1->aff_mrg == YES) || fmv1->bi_mode >= 9 ) + printf("\nbi_mode = %d, sad_cost = %f, skip = %d, med_idx = %d, x = %d, y = %d, xblk = %d, yblk = %d\nfmv1->mvx = %f, fmv1->mvy = %f, fmv1->dmvx = %f, fmv1->dmvy = %f\n" + ,fmv1->bi_mode, fmv1->sad_cost, fmv1->skip_sign, fmv1->med_idx,x,y,xblk2,yblk2,fmv1->mvx,fmv1->mvy,fmv1->dmvx,fmv1->dmvy); + + if(fmv1->bi_mode>=9 && fmv1->direct_idx == DIRECT){ + printf("aff_index = %d\nfmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\n" + ,fmv1->aff_idx,fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy); + } + else if(fmv1->bi_mode>=9 && fmv1->direct_idx != DIRECT){ + printf("aff_index = %d\nfmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\nmerge_idx = %d, merge_dir = %d\n" + ,fmv1->aff_idx,fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy,fmv1->merge_idx,fmv1->merge_dir); + if(fmv1->merge_idx == MERGE && fmv1->merge_dir == UP) + printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n", fmv1->aff3_dmvx, fmv1->aff3_dmvy); + else if(fmv1->merge_idx == MERGE && fmv1->merge_dir == LEFT) + printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n", fmv1->aff2_dmvx, fmv1->aff2_dmvy); + else if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && fmv1->merge_dir == PAL_L && fmv1->aff_idx >=0) + || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + printf("\nfmv1->aff1_dmvx = %f, fmv1->aff1_dmvy = %f\n", fmv1->aff1_dmvx, fmv1->aff1_dmvy); + printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n", fmv1->aff2_dmvx, fmv1->aff2_dmvy); + printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n\n", fmv1->aff3_dmvx, fmv1->aff3_dmvy); + } + } + if( (fmv1->bi_mode == 7 && fmv1->aff_mrg == YES) || fmv1->bi_mode >= 9 ) + printf("\n"); + } + ////////////////////////////////////////////////////// + + if(num == 2 && fmv1->bi_mode != BLOCK_MERGING && fmv1->bi_mode <= 8 ) + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 1); + + if( fmv1->bi_mode <= 6 || fmv1->bi_mode == 8 || (fmv1->bi_mode == 7 && fmv1->aff_mrg == NO) ){ + assert( (x + xblk2 - fmv1->mvx <= hor ) && (y + yblk2 - fmv1->mvy <= ver ) && + (x - fmv1->mvx >= 0 ) && (y - fmv1->mvy >= 0 ) ); + assert( (!(fmv1->bi_mode == PARALLEL)) || + ((x + xblk2 - fmv2->mvx <= hor ) && (y + yblk2 - fmv2->mvy <= ver ) && + (x - fmv2->mvx >= 0 ) && (y - fmv2->mvy >= 0 )) ); + } + // update the motion field in this frame + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + }//if do_fmv1 + +/*************************************************************************/ +/************************** fmv2 **************************************/ +/*************************************************************************/ +if(do_fmv2 == YES){ + if(fmv2 != NULL){ + //////////// Added by Yuan Liu on 08.20.2016 ////////////// + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + map_side = (encode_parallelmv + 1) % 2; + assert(map_side == 0); + num = 0; + num_dir = 0; + + ///////////////// Added on 01.28.2016 ////////////////////// + if( (fmv2->bi_mode <= 8 && !(fmv2->bi_mode == PARALLEL && !map_side) && fmv2->bi_mode != BLOCK_MERGING) || + (fmv2->bi_mode >= 9 && fmv2->direct_idx == INDIRECT && fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P && fmv2->trans_pred_idx == INDIR) ){ + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field2, prev_frame_motion_field1, + x, y, xblk, yblk, info, t_level, 0); + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL){ + num++; + if(fmv2->bi_mode == BLOCK_MERGING){ + if( (float(x)-mvpredstr_x[i] >= 0) && (float(x)-mvpredstr_x[i]<= (hor - xblk2)) && (float(y)-mvpredstr_y[i] >= 0) + && (float(y) - mvpredstr_y[i] <= (ver - yblk2)) ) + num_dir++; + } + } + } + +// assert( fmv2->bi_mode >= 0 && fmv2->bi_mode <= 8 ); + + if(num == 0) + assert(fmv2->med_idx == -1); + else if(num == 1){ + assert(fmv2->med_idx == 0); + } + else if(num == 2){ + assert(fmv2->med_idx >= 0 && fmv2->med_idx <= 1); + putbits(fmv2->med_idx,1); + *mapbit += 1; + idx_info += 1; + } + else{ + assert(num == 3 || num == 4); + assert(fmv2->med_idx >= 0 && fmv2->med_idx <= 3); + if(num == 3) + output_huff_bits(fmv2,num,cnt_tri,info,mapbit); + else + output_huff_bits(fmv2,num,cnt_quad,info,mapbit); + idx_info += 2; + } + + }else if( fmv2->bi_mode >= 9 ){ + if(fmv2->direct_idx == INDIRECT && fmv2->merge_idx == MERGE && fmv2->merge_dir == PAL_L) + middle = put_aff_mvs(fmv2,x,y,xblk2,yblk2,hor,ver,frame_motion_field2, prev_frame_motion_field1,0); + else + middle = put_aff_mvs(fmv2,x,y,xblk2,yblk2,hor,ver,frame_motion_field2, prev_frame_motion_field1,1); + + (*mapbit) += middle; + } + ///////////////////////////////////////////////////////////// + + fmv2->is_predictor = YES; + + ////////////// Added by Yuan Liu ////////////////// + if(fmv2->bi_mode >= 7 && fmv2->bi_mode <= 11){ + if( (fmv2->bi_mode == 7 && fmv2->aff_mrg == YES) || fmv2->bi_mode >= 9 ) + printf("\nbi_mode = %d, sad_cost = %f, skip = %d, med_idx = %d, x = %d, y = %d, xblk = %d, yblk = %d\nfmv2->mvx = %f, fmv2->mvy = %f, fmv2->dmvx = %f, fmv2->dmvy = %f\n" + ,fmv2->bi_mode, fmv2->sad_cost, fmv2->skip_sign, fmv2->med_idx,x,y,xblk2,yblk2,fmv2->mvx,fmv2->mvy,fmv2->dmvx,fmv2->dmvy); + + if(fmv2->bi_mode>=9 && fmv2->direct_idx == DIRECT){ + printf("aff_index = %d\nfmv2->aff1_mvx = %f, fmv2->aff1_mvy = %f\n fmv2->aff2_mvx = %f, fmv2->aff2_mvy = %f\n fmv2->aff3_mvx = %f, fmv2->aff3_mvy = %f\n" + ,fmv2->aff_idx,fmv2->aff1_mvx, fmv2->aff1_mvy, fmv2->aff2_mvx , fmv2->aff2_mvy, fmv2->aff3_mvx, fmv2->aff3_mvy); + } + else if(fmv2->bi_mode>=9 && fmv2->direct_idx != DIRECT){ + printf("aff_index = %d\nfmv2->aff1_mvx = %f, fmv2->aff1_mvy = %f\n fmv2->aff2_mvx = %f, fmv2->aff2_mvy = %f\n fmv2->aff3_mvx = %f, fmv2->aff3_mvy = %f\nmerge_idx = %d, merge_dir = %d\n" + ,fmv2->aff_idx,fmv2->aff1_mvx, fmv2->aff1_mvy, fmv2->aff2_mvx , fmv2->aff2_mvy, fmv2->aff3_mvx, fmv2->aff3_mvy,fmv2->merge_idx,fmv2->merge_dir); + if(fmv2->merge_idx == MERGE && fmv2->merge_dir == UP) + printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n", fmv2->aff3_dmvx, fmv2->aff3_dmvy); + else if(fmv2->merge_idx == MERGE && fmv2->merge_dir == LEFT) + printf("fmv2->aff2_dmvx = %f, fmv2->aff2_dmvy = %f\n", fmv2->aff2_dmvx, fmv2->aff2_dmvy); + else if(fmv2->merge_idx == INTER || (fmv2->merge_idx == MERGE && fmv2->merge_dir == PAL_L && fmv2->aff_idx >=0) + || (fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P) ){ + printf("\nfmv2->aff1_dmvx = %f, fmv2->aff1_dmvy = %f\n", fmv2->aff1_dmvx, fmv2->aff1_dmvy); + printf("fmv2->aff2_dmvx = %f, fmv2->aff2_dmvy = %f\n", fmv2->aff2_dmvx, fmv2->aff2_dmvy); + printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n\n", fmv2->aff3_dmvx, fmv2->aff3_dmvy); + } + } + if( (fmv2->bi_mode == 7 && fmv2->aff_mrg == YES) || fmv2->bi_mode >= 9 ) + printf("\n\n"); + } + ////////////////////////////////////////////////////// + + if(num == 2 && fmv2->bi_mode != BLOCK_MERGING && fmv2->bi_mode <= 8 ) + assert(fmv2->med_idx >= 0 && fmv2->med_idx <= 1); + + if( fmv2->bi_mode <= 6 || fmv2->bi_mode == 8 || (fmv2->bi_mode == 7 && fmv2->aff_mrg == NO) ){ + assert( (x + xblk2 - fmv2->mvx <= hor ) && (y + yblk2 - fmv2->mvy <= ver ) && + (x - fmv2->mvx >= 0 ) && (y - fmv2->mvy >= 0 ) ); + assert( (!(fmv2->bi_mode == PARALLEL)) || + ((x + xblk2 - fmv1->mvx <= hor ) && (y + yblk2 - fmv1->mvy <= ver ) && + (x - fmv1->mvx >= 0 ) && (y - fmv1->mvy >= 0 )) ); + } + // update the motion field in this frame + update_frame_motion_field(frame_motion_field2, x, y, xblk, yblk, info, fmv2, fmv2->dmvx, + fmv2->dmvy, fmv2->mvx, fmv2->mvy); + + }//If fmv2 != NULL + +}//if do_fmv2 + + /////////////// MERGE detection ////////////////////// + if( fmv1->bi_mode == BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + delete(mrg_left[i]); + delete(mrg_right[i]); + } + } + /////////////////////////////////////////////////////// + + assert(fmv1->bi_mode >= 0); + mean_mode_mse[fmv1->bi_mode] += fmv1->mse; + mean_mode_num[fmv1->bi_mode] ++; + +}//child else + +} +/////////////////////////////////////////////////////////////////////////// + +/*****************************************************************************/ +/* mv_encode() */ +/*****************************************************************************/ +void +mv_encode( int *mvbit, int *mapbit, vector_ptr fmv1, vector_ptr fmv2, + int encode_map, videoinfo info, int large, int t_level, int sub_mv[LAYER_NUM][MAX_AGP_LEVEL], + int *sub_sign, int count, int GOP_counter ) +{ + int partition, x, y, X, Y, xnum, ynum, xblk, yblk, hor, ver, pos, small, itemp, subpel; + int num_symbol; + float pmvx, pmvy; + int sub_bit, blk_thresh, layer_num; + int i,j; + + if(fmv2 != NULL){ + for(i=0;i<=11;i++){ + bi_mode_num012[i]=0; + bi_mode_num345[i]=0; + } + use_huff = 0; + } + + // for motion field in a frame + frame_motion_field = (FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(FRAME_MOTION_FIELD), "frame_motion_field"); + frame_motion_field2 = (FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(FRAME_MOTION_FIELD), "frame_motion_field2"); + + blk_thresh = 0; + if (info.layer_mv[t_level]) + blk_thresh = LAYER_BLOCK_SIZE; + +#ifdef DEBUG_LAYER_STRUCTURE + FILE *fpbase, *fpenhance; + char base_file[80], enhance_file[80]; + + // make base_file and enhance_file empty + sprintf(base_file, "base%d.txt", count); + if (fpbase=fopen(base_file, "rt") ) + { + fclose(fpbase); + fpbase=fopen(base_file, "wt"); + fclose(fpbase); + } + sprintf(enhance_file, "enhance%d.txt", count); + if (fpenhance=fopen(enhance_file, "rt") ) + { + fclose(fpenhance); + fpenhance=fopen(enhance_file, "wt"); + fclose(fpenhance); + } +#endif + + // initialization for scalable motion vector coding: AGP and layer structure + for (layer_num=0; layer_num=0; sub_bit--) + { + if (splitted_bit_num_array[0][sub_bit] != 8) + { + splitted_mv_byte_array[0][sub_bit] <<= splitted_bit_num_array[0][sub_bit]; + store_splitted_bytes_array[0][sub_bit][splitted_mv_byte_num_array[0][sub_bit]++] = + splitted_mv_byte_array[0][sub_bit]; + } + done_splitted_bytes(store_splitted_bytes_array[0][sub_bit], + splitted_mv_byte_num_array[0][sub_bit], + info, t_level); + // 2 bytes for the length of splitted motion vector bit-stream + sub_mv[0][sub_bit] = 8* (splitted_mv_byte_num_array[0][sub_bit]+2); + } + } + + + if (info.layer_mv[t_level]) // layer structure: enhancement layer + { + assert(0); + ec_enc_init(info, EC_TYPE, num_symbol, 3, 1); + clear_frame_motion_field(frame_motion_field, info); + blk_thresh = LAYER_BLOCK_SIZE; + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) { + pos = Y * xnum + X; + child_mv_encode_enhance( fmv1, &fmv1[pos], fmv2 ? (&fmv2[pos]) : NULL, + &pmvx, &pmvy, num_symbol, subpel, x, y, xblk, yblk, + hor, ver, info, encode_map, t_level, blk_thresh, count ); + } + } + ec_enc_end1(); + ec_enc_end2(); + + mvbit[1] = 8 * outbyte; // enhancement layer bytes + if (info.AGP_level[t_level]) + { + // additional sign bits + if (splitted_sign_bit_num[1] != 8) + { + splitted_sign_byte[1] <<= splitted_sign_bit_num[1]; + store_splitted_sign[1][splitted_sign_byte_num[1]++] = splitted_sign_byte[1]; + } + done_splitted_bytes(store_splitted_sign[1], splitted_sign_byte_num[1], info, t_level); + // 2 bytes for the length of splitted additional sign + sub_sign[1] = 8* (splitted_sign_byte_num[1]+2); + // save the sub-symbol bits in the order of significance + for (sub_bit=info.AGP_level[t_level]-1; sub_bit>=0; sub_bit--) + { + if (splitted_bit_num_array[1][sub_bit] != 8) + { + splitted_mv_byte_array[1][sub_bit] <<= splitted_bit_num_array[1][sub_bit]; + store_splitted_bytes_array[1][sub_bit][splitted_mv_byte_num_array[1][sub_bit]++] = + splitted_mv_byte_array[1][sub_bit]; + } + done_splitted_bytes(store_splitted_bytes_array[1][sub_bit], + splitted_mv_byte_num_array[1][sub_bit], + info, t_level); + // 2 bytes for the length of splitted motion vector bit-stream + sub_mv[1][sub_bit] = 8* (splitted_mv_byte_num_array[1][sub_bit]+2); + } + } + + } + +#ifdef DEBUG_SCALABLE_MV + fclose(fpAGP_debug); +#endif + + free(frame_motion_field); + free(frame_motion_field2); + +} + +void write_mv_length(int AGP_level, int layer_mv, FILE *fp_mv, Rate FrsRate, + int count, int sub_sign[LAYER_NUM], int itmp, int simul_enc) +{ + int partition, layer_num; + + if (AGP_level && !layer_mv ) // AGP, no layer structure + { + // major part: mapbits + mvbits (bytes) + fprintf(fp_mv, "%d ", (FrsRate.map[count] + FrsRate.mv[0][count])>>3); + // additional sign part + fprintf(fp_mv, "%d ", sub_sign[0]>>3); + // sub-symbol part (bytes) + for (partition=0; partition>3 ); + } + + if (!AGP_level && layer_mv ) // no AGP, layer structure + { + // major part: mapbits + mvbits (bytes) + fprintf(fp_mv, "%d ", (FrsRate.map[count] + FrsRate.mv[0][count])>>3); + for (layer_num=1; layer_num>3); + } + + if (AGP_level && layer_mv ) // AGP, layer structure + { + // major part: mapbits + mvbits (bytes) + fprintf(fp_mv, "%d ", (FrsRate.map[count] + FrsRate.mv[0][count])>>3); + // additional sign part + fprintf(fp_mv, "%d ", sub_sign[0]>>3); + // sub-symbol part (bytes) + for (partition=0; partition>3 ); + for (layer_num=1; layer_num>3); + // additional sign part + fprintf(fp_mv, "%d ", sub_sign[layer_num]>>3); + // sub-symbol part (bytes) + for (partition=0; partition>3 ); + } + } + + // total sum for this set of motion vectors +// if(simul_enc == NO) + fprintf( fp_mv, "%d\n", itmp >> 3); +} + + + +/*****************************************************************************/ +/* mv_encoding() */ +/*****************************************************************************/ +int +mv_encoding( videoinfo info, Rate FrsRate, vector_ptr * yfmv, int GOP_counter, int simul_enc, int curr ) +{ + int partition, i, j, sum, itmp, count, mv_count, dist, GOPsz; + int eff_GOPsz[20]; // maximum number of temporal levels = 20; + int mvrate1[LAYER_NUM], maprate1; + int mvrate2[LAYER_NUM], maprate2; + // for scalable motion vector coding + int sub_mv1[LAYER_NUM][MAX_AGP_LEVEL], sub_mv2[LAYER_NUM][MAX_AGP_LEVEL]; + int sub_sign1[LAYER_NUM], sub_sign2[LAYER_NUM]; + int layer_num; + + int a,b; + int res_frame, do_res = NO; + int *level_res_frame; + float getval; + + for(i = 0; i < NUMBER_OF_BI_MODES; i ++){ + mean_mode_mse[i] = 0; + mean_mode_num[i] = 0; + } + + level_res_frame = (int*)getarray(info.tPyrLev, sizeof(int), "level_res_frame"); + + res_frame = info.act_last - curr + 1; + if( res_frame > 0 && res_frame < info.GOPsz ){ + do_res = YES; + for(i = 0; i < info.tPyrLev; i ++){ + level_res_frame[i] = res_frame; + + if(res_frame % 2 == 0) + res_frame = res_frame / 2; + else + res_frame = (res_frame+1) / 2; + } + }else{ + res_frame = info.GOPsz; + for(i = 0; i < info.tPyrLev; i ++) + level_res_frame[i] = res_frame; + } + + ctl_info = 0; + mv_info = 0; + idx_info = 0; + + aff_mrg_blk = 0; + + mv_res_bits = 0; + calc_res_bits = 0; + + printf("GOP_counter = %d\n",GOP_counter); + +// test(); + + for(i=0;i<=2;i++){ + cnt_tri[i]=0; + } + for(i=0;i<=3;i++){ + cnt_quad[i]=0; + } + // enum FLAG Level_change; + FILE *fpstat, *fp_mv; + + prev_frame_motion_field1 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field1"); + prev_frame_motion_field2 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field2"); + + //Added on 08.20.2016 + prev_frame_motion_field_left1 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field_left1"); + prev_frame_motion_field_left2 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field_left2"); + //Added on 08.20.2016 + + if(GOP_counter == 0 && simul_enc == NO){ + for(i = 0;i <= info.tPyrLev - 2; i++){ + buffer_frame_motion_field1[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "buffer_frame_motion_field1"); + buffer_frame_motion_field2[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "buffer_frame_motion_field2"); + + clear_frame_motion_field_simp(buffer_frame_motion_field1[i], info); + clear_frame_motion_field_simp(buffer_frame_motion_field2[i], info); +//Added on 02.05.2018 + save_buffer_frame_motion_field1[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "save_buffer_frame_motion_field1"); + save_buffer_frame_motion_field2[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "save_buffer_frame_motion_field2"); + + clear_frame_motion_field_simp(save_buffer_frame_motion_field1[i], info); + clear_frame_motion_field_simp(save_buffer_frame_motion_field2[i], info); + } + } + + if(simul_enc == YES){ + for(i = 0; i <= info.tPyrLev - 2; i++){ + copy_frame_motion_field2(save_buffer_frame_motion_field1[i], buffer_frame_motion_field1[i], info); + copy_frame_motion_field2(save_buffer_frame_motion_field2[i], buffer_frame_motion_field2[i], info); + } + } + + if((info.GOPsz * GOP_counter) == SIMUL_POINT){ + printf("\nMV_coding SIMUL_POINT = %d\n", SIMUL_POINT); + + for(i = 0; i <= info.tPyrLev - 2; i++){ + copy_frame_motion_field2(buffer_frame_motion_field1[i], save_buffer_frame_motion_field1[i], info); + copy_frame_motion_field2(buffer_frame_motion_field2[i], save_buffer_frame_motion_field2[i], info); + } + } + + GOPsz = info.GOPsz; + + dist = ( int )pow( 2.0, ( double )( info.tPyrLev - 1 ) ); + + fpstat = fopen( info.statname, "at+" ); + if( !( fp_mv = fopen( info.mvstatname, "at+" ) ) ) { + printf( "can not open %s\n", info.mvstatname ); + exit( 1 ); + } + + // determine effective GOP size in level i + for( i = 0; i < info.tPyrLev; i++ ) { + eff_GOPsz[i] = GOPsz; + GOPsz /= 2; + } + + FrsRate.map[0] = 0; + for (layer_num=0; layer_num= 0; i-- ) { + FrsRate.map[count] = 0; + for (layer_num=0; layer_num= 1 && i <= info.tPyrLev - 2){ + copy_frame_motion_field2(buffer_frame_motion_field1[i], prev_frame_motion_field1, info); + copy_frame_motion_field2(buffer_frame_motion_field2[i], prev_frame_motion_field2, info); + } + + avg_blk_size[i] = 0; + blk_num = 0; + + for( j = 1; j <= eff_GOPsz[i]; j += 2 ) { + + // initialization + maprate1 = maprate2 = 0 ; + for (layer_num=0; layer_num 0) { + // mapbits & mvbits + fprintf(fpstat, "Num%.2d: mapbits = %4d ", count, FrsRate.map[count]); + for (layer_num=0; layer_num> 3); + write_mv_length(info.AGP_level[i], info.layer_mv[i], fp_mv, FrsRate, count, sub_sign1, itmp, simul_enc); + // the overall sum + if(do_res == NO) + sum += itmp; + else{ + assert(do_res == YES); + if(j < level_res_frame[i]) + sum += itmp; + else + printf("Current mv set skipped!\n"); + } + + mv_count++; + } else { + fprintf(fpstat, "Fr%.2d: no motion information needed\n", count); + +// if(simul_enc == NO) + fprintf( fp_mv, "%d\n", 0); + } + count++; + + if (j < eff_GOPsz[i]) { + + FrsRate.map[count] = maprate2; + itmp = maprate2; + ctl_info += maprate2; + for (layer_num=0; layer_num 0) { + // mapbits & mvbits + fprintf(fpstat, "Num%.2d: mapbits = %4d ", count, FrsRate.map[count]); + for (layer_num=0; layer_num> 3); + + write_mv_length(info.AGP_level[i], info.layer_mv[i], fp_mv, FrsRate, count, sub_sign2, itmp, simul_enc); + // the overall sum + if(do_res == NO) + sum += itmp; + else{ + assert(do_res == YES); + if(j < level_res_frame[i]) + sum += itmp; + else + printf("Current mv set skipped!\n"); + } + + mv_count++; + } else { + fprintf(fpstat, "Fr%.2d: no motion information needed\n", count); +// if(simul_enc == NO) + fprintf(fp_mv, "%d\n", 0); + } + count++; + } + }// j + dist /= 2; + ////////////////////// + avg_blk_size[i] = avg_blk_size[i]/blk_num; + + printf("before copy!\n"); + + if(i <= info.tPyrLev - 2){ + copy_frame_motion_field2(prev_frame_motion_field1, buffer_frame_motion_field1[i], info); + copy_frame_motion_field2(prev_frame_motion_field2, buffer_frame_motion_field2[i], info); + } + ////////////////////// + } + fprintf( fpstat, "---> %.2d MV sets -- total sum = %7d (%d bytes)\n", mv_count, sum, sum >> 3 ); + printf ( "---> %.2d MV sets -- total sum = %7d (%d bytes)\n\n", mv_count, sum, sum >> 3 ); + fclose( fpstat ); + fclose( fp_mv ); + + free(prev_frame_motion_field1); + free(prev_frame_motion_field2); + + free(prev_frame_motion_field_left1); + free(prev_frame_motion_field_left2); + + free(level_res_frame); + + if(GOP_counter == (get_GOP_num(info) - 1) ){ + for(i = 0;i < G_LEVEL; i++){ + free(buffer_frame_motion_field1[i]); + free(buffer_frame_motion_field2[i]); + free(save_buffer_frame_motion_field1[i]); + free(save_buffer_frame_motion_field2[i]); + } + } + + printf("\n"); + for(i = 0; i < NUMBER_OF_BI_MODES; i ++){ + printf("mean_mode_mse[%d] = %f, num[%d] = %d\n", i, mean_mode_mse[i]/mean_mode_num[i], i, mean_mode_num[i] ); + } + printf("\n"); + + return ( sum ); +} + + + + +void +alloc_vector_child( vector_ptr *fmv1, vector_ptr *fmv2, int meandepth, + int cx, int cy, int xblk, int yblk, int hor, int ver, + int small, videoinfo info, int t_level ) +{ + *fmv1 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv1" ); + + if (fmv2 != NULL) { + *fmv2 = ( vector_ptr ) getarray( 1, sizeof( vector ), "fmv2" ); + } + + if( cx < hor && cy < ver ) { /* Feb23 */ + if( xblk > small ) { + child_map_decode( *fmv1, fmv2 ? (*fmv2) : NULL, meandepth, cx, cy, + xblk, yblk, hor, ver, small, info, t_level ); + } else { + + (*fmv1)->child = 0; + if (fmv2 != NULL) { + (*fmv2)->child = 0; + } + + /* !!! NOTE THAT BLOCK MODES ARE ALSO READ in child_mv_decode !!! */ + decode_block_mode(*fmv1, fmv2 ? (*fmv2) : NULL, meandepth, info, t_level); +#ifdef BLOCKMODE_STATISTICS + record_blockmode_statistics(xblk, yblk, (*fmv1)->bi_mode, + fmv2 != NULL, hor, ver); +#endif + } + } else { + (*fmv1)->child = 0; + if (fmv2 != NULL) { + (*fmv2)->child = 0; + } + } +} + + +/****************************************************************************/ +/* child_map_decode() */ +/* decode quature structure, block modes and means(Y,U,V) of PREDICTEDS */ +/****************************************************************************/ +void +child_map_decode( vector_ptr fmv1, vector_ptr fmv2, int meandepth, + int x, int y, int xblk, int yblk, int hor, int ver, + int small, videoinfo info, int t_level ) +{ + int bit, cx, cy; + + input_bit( bit ); + fmv1->child = bit; + + if (fmv2 != NULL) { + fmv2->child = bit; + } + + if( fmv1->child ) { + cx = x; + cy = y; + alloc_vector_child(&(fmv1->child0), fmv2 ? (&(fmv2->child0)) : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level); + + cx = x + xblk / 2; + cy = y; + alloc_vector_child(&(fmv1->child1), fmv2 ? (&(fmv2->child1)) : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level); + + cx = x; + cy = y + yblk / 2; + alloc_vector_child(&(fmv1->child2), fmv2 ? (&(fmv2->child2)) : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level); + + cx = x + xblk / 2; + cy = y + yblk / 2; + alloc_vector_child(&(fmv1->child3), fmv2 ? (&(fmv2->child3)) : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, info, t_level); + + } else { /* Feb23 */ + /* !!! NOTE THAT BLOCK MODES ARE ALSO READ in alloc_vector_child !!! */ + decode_block_mode(fmv1, fmv2, meandepth, info, t_level); +#ifdef BLOCKMODE_STATISTICS + record_blockmode_statistics(xblk, yblk, fmv1->bi_mode, + fmv2 != NULL, hor, ver); +#endif + } +} + + +/****************************************************************************/ +/* child_merge_decode() */ +/****************************************************************************/ +void +child_merge_decode_further( vector_ptr fmv1, vector_ptr fmv2, int meandepth, + int x, int y, int xblk, int yblk, int hor, int ver, + int small, videoinfo info, int t_level, int blk_thresh, int count ) +{ + int bit, cx, cy; + + if( fmv1->child && xblk>blk_thresh ) { + cx = x; + cy = y; + child_merge_decode_further(fmv1->child0, fmv2 ? fmv2->child0 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_merge_decode_further(fmv1->child1, fmv2 ? fmv2->child1 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_merge_decode_further(fmv1->child2, fmv2 ? fmv2->child2 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_merge_decode_further(fmv1->child3, fmv2 ? fmv2->child3 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + } else { + + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) return; + + if (!fmv1->mv_exist) return; // no subsampled motion vector in this big block + + // irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child) + return; + + input_bit(bit); + fmv1->merge_sign = bit; + + FILE *fmerge; + char merge_file[80]; + sprintf(merge_file, "decode_merge_sign%d.txt", count); + fmerge = fopen(merge_file, "at"); + fprintf(fmerge, "%d\n", bit); + fclose(fmerge); + } +} + + +/****************************************************************************/ +/* child_merge_decode() */ +/****************************************************************************/ +void +child_merge_decode( vector_ptr fmv1, vector_ptr fmv2, int meandepth, + int x, int y, int xblk, int yblk, int hor, int ver, + int small, videoinfo info, int t_level, int blk_thresh, int count ) +{ + int bit, cx, cy; + + if( fmv1->child && xblk>blk_thresh ) { + cx = x; + cy = y; + child_merge_decode(fmv1->child0, fmv2 ? fmv2->child0 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_merge_decode(fmv1->child1, fmv2 ? fmv2->child1 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_merge_decode(fmv1->child2, fmv2 ? fmv2->child2 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_merge_decode(fmv1->child3, fmv2 ? fmv2->child3 : NULL, + meandepth, cx, cy, xblk / 2, yblk / 2, hor, ver, small, + info, t_level, blk_thresh, count); + + } else { + + if( x >= hor || y >= ver ) return; + + if (!fmv1->child) return; + + if (!fmv1->mv_exist) return; // no subsampled motion vector in this big block + + assert(0); + + input_bit(bit); + fmv1->merge_sign = bit; + + FILE *fmerge; + char merge_file[80]; + sprintf(merge_file, "decode_merge_sign%d.txt", count); + fmerge = fopen(merge_file, "at"); + fprintf(fmerge, "%d\n", bit); + fclose(fmerge); + + if (!fmv1->merge_sign ) + child_merge_decode_further( fmv1, fmv2, meandepth, + x, y, xblk, yblk, hor, ver, small, info, t_level, blk_thresh/2, count ); + } +} + + + +char get_splitted_mvbits(char whichsub, int layer_index) +{ + int value = 0; + + if ( --(splitted_bit_num_array[layer_index][whichsub]) <0 ) + { + splitted_mv_byte_array[layer_index][whichsub] = + store_splitted_bytes_array[layer_index][whichsub][splitted_mv_byte_num_array[layer_index][whichsub]++]; + splitted_bit_num_array[layer_index][whichsub] = 7; + } + value = ((splitted_mv_byte_array[layer_index][whichsub] >> splitted_bit_num_array[layer_index][whichsub]) & 0x01); + + return value; + +} + + +char get_splitted_signbits(int layer_index) +{ + int value = 0; + + if ( --splitted_sign_bit_num[layer_index] <0 ) + { + splitted_sign_byte[layer_index] = store_splitted_sign[layer_index][splitted_sign_byte_num[layer_index]++]; + splitted_sign_bit_num[layer_index] = 7; + } + value = ((splitted_sign_byte[layer_index] >> splitted_sign_bit_num[layer_index]) & 0x01); + return value; +} + +/****************************************************************************/ +/* child_mv_decode_enhance_sub() */ +/****************************************************************************/ +void +child_mv_decode_enhance_sub( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int *first_available, int count, int merge_sign ) +{ + int dmvx, dmvy, cx, cy; + int ctx_x, ctx_y; + float mvpred_x, mvpred_y; + char value; + int xblk2, yblk2; + float major_mvx, major_mvy, sub_mvx, sub_mvy; + float major_predx, major_predy; + int AGP_scale, subpel_scale, sub_symx, sub_symy, sub_bit, sub_signx, sub_signy; + char sub_sym_predx, sub_sym_predy; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk > blk_thresh ) { + cx = x; + cy = y; + child_mv_decode_enhance_sub(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, + first_available, count, merge_sign); + + cx = x + xblk / 2; + cy = y; + child_mv_decode_enhance_sub(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, + first_available, count, merge_sign); + + cx = x; + cy = y + yblk / 2; + child_mv_decode_enhance_sub(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, + first_available, count, merge_sign); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_decode_enhance_sub(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, + first_available, count, merge_sign); + } else { + if( x >= hor || y >= ver ) return; + + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + + assert(0); + + if (!merge_sign) + { + // re-do the spatial prediction when it's first motion vector or not + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !decode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(num == 0){ + fmv1->med_idx = -1; + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + fmv1->med_idx = getbits(2); + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + return; + } + + if ( *first_available ) // the first motion vector is skipped since it's already coded in base layer + { + // re-do the spatial prediction when it's first motion vector or not + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !decode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(num == 0){ + fmv1->med_idx = -1; + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + fmv1->med_idx = getbits(2); + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + *first_available = 0; + return; + } + + if (!bidir_exist) // the motion vectors on RIGHT side has been discarded + { + if ((fmv1->bi_mode == PARALLEL)&&(!decode_parallelmv)) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + } + if (fmv1->bi_mode==RIGHT_CONNECTED) + assert(0); // RIGHT_CONNECTED mode is prevented + return; + } + + if ( (fmv1->bi_mode != BLOCK_MERGING)&& !((fmv1->bi_mode == PARALLEL)&&(!decode_parallelmv)) ) { + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x, y, info, t_level, blk_thresh); + + dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(dmvx, ctx_x); + if (EC_TYPE == AR_NARY) { + if (dmvx > num_symbol / 2 - (int) ((1 << subpel) * *pmvx)) + dmvx -= num_symbol; + else if (dmvx < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvx)) + dmvx += num_symbol; + } + + dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(dmvy, ctx_y); + if (EC_TYPE == AR_NARY) { + if (dmvy > num_symbol / 2 - (int) ((1 << subpel) * *pmvy)) + dmvy -= num_symbol; + else if (dmvy < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvy)) + dmvy += num_symbol; + } + } else { // BLOCK_MERGING + dmvx = 0; + dmvy = 0; + } + + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !decode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(num == 0){ + fmv1->med_idx = -1; + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + fmv1->med_idx = getbits(2); + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + if ( !info.AGP_level[t_level] ) + { + if ((fmv1->bi_mode == PARALLEL)&&(!decode_parallelmv)) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + } else { + fmv1->mvx = (float) dmvx / (1 << subpel) + mvpred_x; + fmv1->mvy = (float) dmvy / (1 << subpel) + mvpred_y; + } + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<bi_mode == PARALLEL)&&(!decode_parallelmv)) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + major_mvx = (int)(fmv1->mvx*AGP_scale)/(float)AGP_scale; + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + } else if ( fmv1->bi_mode == BLOCK_MERGING ) + { + fmv1->mvx = mvpred_x; + fmv1->mvy = mvpred_y; + assert(dmvx ==0 && dmvy == 0 ); + major_mvx = (int)(fmv1->mvx*AGP_scale)/(float)AGP_scale; + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + }else + { + major_mvx = (float) dmvx / AGP_scale + major_predx; + major_mvy = (float) dmvy / AGP_scale + major_predy; + // code the sub-symbols as binary sequence + sub_symx = sub_symy = 0; + for (sub_bit=0; sub_bitmvx = major_mvx + sub_mvx; + fmv1->mvy = major_mvy + sub_mvy; + } + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + +#ifdef DEBUG_SCALABLE_MV + fpAGP_debug = fopen(decoder_AGPdebug, "at"); + fprintf(fpAGP_debug, "x=%03d y=%03d blk=%2d ", x, y, xblk ); + fprintf(fpAGP_debug, "major_mvx=%.1f major_mvy=%.1f major_predx=%.1f major_predy=%.1f", + major_mvx, major_mvy, major_predx, major_predy) ; + fprintf(fpAGP_debug, " dmvx=%.1f dmvy=%.1f mvx=%.2f mvy=%.2f\n", + fmv1->dmvx, fmv1->dmvy, fmv1->mvx, fmv1->mvy) ; + fclose(fpAGP_debug); +#endif + + } + + // double check + assert((fmv1->bi_mode != BLOCK_MERGING)||(fmv1->dmvx==0 && fmv1->dmvy==0)); // just to be shure. mwi + + mvStat_setPos(x, y); + mvStat_setDMV((float)dmvx, (float)dmvy); + mvStat_writeDMVCTX(); + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + + +#ifdef DEBUG_LAYER_STRUCTURE // write the enhancement motion vectors + char enhance_file[80]; + FILE *fpenhance; + // make base_file and enhance_file empty + sprintf(enhance_file, "decode_enhance%d.txt", count); + fpenhance=fopen(enhance_file, "at"); + fprintf(fpenhance, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, fmv1->mvx, fmv1->mvy, mvpred_x, mvpred_y); + fclose(fpenhance); +#endif + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + + assert( (x + xblk2 - fmv1->mvx <= hor ) && + (y + yblk2 - fmv1->mvy <= ver ) && + (x - fmv1->mvx >= 0 ) && + (y - fmv1->mvy >= 0 ) ); + + if (!decode_parallelmv) { + assert( (!(fmv1->bi_mode == PARALLEL)) || + ((x + xblk2 - fmv2->mvx <= hor ) && + (y + yblk2 - fmv2->mvy <= ver ) && + (x - fmv2->mvx >= 0 ) && + (y - fmv2->mvy >= 0 )) ); + } + + } +} + +void +child_mv_decode_enhance_further( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int cx, cy; + float mvpred_x, mvpred_y; + int first_available; + float major_mvx, major_mvy, major_predx, major_predy; + int sub_symx, sub_symy; + char sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk > blk_thresh ) { + cx = x; + cy = y; + child_mv_decode_enhance_further(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_decode_enhance_further(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_decode_enhance_further(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_decode_enhance_further(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + + if( x >= hor || y >= ver ) return; + + if (!(fmv1->child)) // if there are no children for this block with size>=blk_thresh + { + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + // re-do the spatial prediction + assert(0); + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !decode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(num == 0){ + fmv1->med_idx = -1; + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + fmv1->med_idx = getbits(2); + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + return; + } else + { + if ( !fmv1->mv_exist ) return; + + // irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child) + fmv1->merge_sign = 0; + + first_available = 1; + blk_thresh = 0; + child_mv_decode_enhance_sub( fmv1_array, fmv2_array, fmv1, fmv2, pmvx, pmvy, + num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, + blk_thresh, &first_available, count, fmv1->merge_sign ); + } + + } + +} + +void +child_mv_decode_enhance( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int cx, cy; + float mvpred_x, mvpred_y; + int first_available; + float major_mvx, major_mvy, major_predx, major_predy; + int sub_symx, sub_symy, sub_sym_predx, sub_sym_predy; + int AGP_scale, subpel_scale; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk > blk_thresh ) { + cx = x; + cy = y; + child_mv_decode_enhance(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_decode_enhance(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_decode_enhance(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_decode_enhance(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + + if( x >= hor || y >= ver ) return; + + if (!(fmv1->child)) // if there are no children for this block with size>=blk_thresh + { + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + assert(0); + // re-do the spatial prediction + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, 0); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !decode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(num == 0){ + fmv1->med_idx = -1; + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + fmv1->med_idx = getbits(2); + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if ( !info.AGP_level[t_level] ) + { + fmv1->dmvx = fmv1->mvx - mvpred_x; + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<mvx*AGP_scale)/(float)AGP_scale; + // sub-symbol (already converted to integer) + sub_symx = (char)(fabs( (fmv1->mvx - major_mvx) * subpel_scale )); + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + sub_symy = (char)(fabs( (fmv1->mvy - major_mvy) * subpel_scale )); + major_predx = (int)(mvpred_x*AGP_scale)/(float)AGP_scale; + sub_sym_predx = (char)(fabs( (mvpred_x - major_predx)*subpel_scale )); + major_predy = (int)(mvpred_y*AGP_scale)/(float)AGP_scale; + sub_sym_predy = (char)(fabs( (mvpred_y - major_predy)*subpel_scale)); + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + return; + } else + { + if ( !fmv1->mv_exist ) return; + + if ( fmv1->merge_sign ) + { + first_available = 1; + blk_thresh = 0; + child_mv_decode_enhance_sub( fmv1_array, fmv2_array, fmv1, fmv2, pmvx, pmvy, + num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, + blk_thresh, &first_available, count, fmv1->merge_sign ); + }else + { + child_mv_decode_enhance_further( fmv1_array, fmv2_array, fmv1, fmv2, + pmvx, pmvy, num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, blk_thresh/2, count ); + } + } + + } + +} + +/****************************************************************************/ +/* child_mv_decode_further() */ +/****************************************************************************/ +void +child_mv_decode_further( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int dmvx, dmvy, cx, cy; + int ctx_x, ctx_y; +#ifdef MEDIAN_PREDICTION + float mvpred_x, mvpred_y; +#endif + char value; + float major_mvx, major_mvy, sub_mvx, sub_mvy; + float major_predx, major_predy; + int AGP_scale, subpel_scale, sub_symx, sub_symy, sub_bit, sub_signx, sub_signy; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk > blk_thresh ) { + cx = x; + cy = y; + child_mv_decode_further(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_decode_further(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_decode_further(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_decode_further(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + + if( x >= hor || y >= ver ) return; + + if ( !fmv1->child ) // there are no children for this block and size>=blk_thresh + { + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + } else + { + assert(0); + if ( !fmv1->mv_exist ) return; // the whole (blk_thresh x blk_thresh) has no motion vector + + // irregular motion area + if ( fmv1->child0->child || fmv1->child1->child || + fmv1->child2->child || fmv1->child3->child) + { + blk_thresh = 0; + child_mv_decode_further( fmv1_array, fmv2_array, fmv1, fmv2, pmvx, pmvy, + num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, blk_thresh/2, count ); + return; + } + + if ( !fmv1->merge_sign ) + { + blk_thresh = 0; + child_mv_decode_further( fmv1_array, fmv2_array, fmv1, fmv2, pmvx, pmvy, + num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, blk_thresh/2, count ); + return; + } + } + + // the motion vectors on RIGHT side has been discarded for alternative reconstruction + if (!bidir_exist) + { + if ((fmv1->bi_mode == PARALLEL)&&(!decode_parallelmv)) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + } + if (fmv1->bi_mode==RIGHT_CONNECTED) + assert(0); // RIGHT_CONNECTED mode is prevented + return; + } + + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, x, y, info, t_level, blk_thresh); + dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(dmvx, ctx_x); + dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(dmvy, ctx_y); + + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, blk_thresh); + ///////////////////////////////// + if( !((fmv1->bi_mode == PARALLEL) && !decode_parallelmv) && fmv1->bi_mode != BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + + if(num == 0){ + fmv1->med_idx = -1; + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + fmv1->med_idx = getbits(2); + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + else if(fmv1->bi_mode == BLOCK_MERGING ){ + num = 0; + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL) + num++; + } + switch(num){ + case 0: + mvpred_x = 0.0; + mvpred_y = 0.0; + break; + + case 1: + case 2: + if(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[0]; + mvpred_y = mvpredstr_y[0]; + } + else if(mvpredstr_x[1] != (float)HUGE_VAL && mvpredstr_y[1] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[1]; + mvpred_y = mvpredstr_y[1]; + } + else if(mvpredstr_x[2] != (float)HUGE_VAL && mvpredstr_y[2] != (float)HUGE_VAL){ + mvpred_x = mvpredstr_x[2]; + mvpred_y = mvpredstr_y[2]; + } + else{ + assert(mvpredstr_x[3] != (float)HUGE_VAL && mvpredstr_y[3] != (float)HUGE_VAL); + mvpred_x = mvpredstr_x[3]; + mvpred_y = mvpredstr_y[3]; + } + break; + + case 3: + if(mvpredstr_x[0] == (float)HUGE_VAL && mvpredstr_y[0] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[1],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[1],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[1] == (float)HUGE_VAL && mvpredstr_y[1] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[2],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[2],mvpredstr_y[3]); + } + else if(mvpredstr_x[2] == (float)HUGE_VAL && mvpredstr_y[2] == (float)HUGE_VAL){ + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[3]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[3]); + } + else{ + assert(mvpredstr_x[3] == (float)HUGE_VAL && mvpredstr_y[3] == (float)HUGE_VAL); + mvpred_x = medi(mvpredstr_x[0],mvpredstr_x[1],mvpredstr_x[2]); + mvpred_y = medi(mvpredstr_y[0],mvpredstr_y[1],mvpredstr_y[2]); + } + break; + } + } + ///////////////////////////////// + + if (!info.AGP_level[t_level]) // no AGP, layer structure + { + // subsampled motion vector + fmv1->sample_mvx = fmv1->mvx = (float) dmvx / (1 << subpel) + mvpred_x; + fmv1->sample_mvy = fmv1->mvy = (float) dmvy / (1 << subpel) + mvpred_y; + fmv1->dmvx = fmv1->mvx - mvpred_x; // update the prediction error + fmv1->dmvy = fmv1->mvy - mvpred_y; + }else // AGP, layer structure + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<sample_mvx = fmv1->mvx = major_mvx + sub_mvx; + fmv1->sample_mvy = fmv1->mvy = major_mvy + sub_mvy; + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + +#ifdef DEBUG_SCALABLE_MV + fpAGP_debug = fopen(decoder_AGPdebug, "at"); + fprintf(fpAGP_debug, "x=%03d y=%03d blk=%2d ", x, y, xblk ); + fprintf(fpAGP_debug, "major_mvx=%.1f major_mvy=%.1f major_predx=%.1f major_predy=%.1f", + major_mvx, major_mvy, major_predx, major_predy) ; + fprintf(fpAGP_debug, " dmvx=%.1f dmvy=%.1f mvx=%.2f mvy=%.2f\n", + fmv1->dmvx, fmv1->dmvy, fmv1->mvx, fmv1->mvy) ; + fclose(fpAGP_debug); +#endif + } + + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + + mvStat_setPos(x, y); + mvStat_setDMV((float)dmvx, (float)dmvy); + mvStat_writeDMVCTX(); + +#ifdef DEBUG_LAYER_STRUCTURE // for debug the layer structure coding + char base_file[80]; + FILE *fpbase; + // make base_file and enhance_file empty + sprintf(base_file, "decode_base%d.txt", count); + fpbase=fopen(base_file, "at"); + fprintf(fpbase, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, fmv1->mvx, fmv1->mvy, mvpred_x, mvpred_y); + fclose(fpbase); +#endif + + } + +} + + +/****************************************************************************/ +/* child_mv_decode() */ +/****************************************************************************/ +void +child_mv_decode( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int dmvx, dmvy, cx, cy, xblk2, yblk2; + int aff1_dmvx, aff1_dmvy, aff2_dmvx, aff2_dmvy, aff3_dmvx, aff3_dmvy;//Added by Yuan Liu on 03.20.2016 + int ctx_x, ctx_y; +#ifdef MEDIAN_PREDICTION + float mvpred_x, mvpred_y; +#endif + char value; + float major_mvx, major_mvy, sub_mvx, sub_mvy; + float major_predx, major_predy; + int AGP_scale, subpel_scale, sub_symx, sub_symy, sub_bit, sub_signx, sub_signy; + int enc_trans = 0; + int getnum; + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + float mvpredstr_x[4], mvpredstr_y[4]; + int i, num = 0; + + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + if( fmv1->child && xblk > blk_thresh ) { + cx = x; + cy = y; + child_mv_decode(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_mv_decode(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_mv_decode(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_mv_decode(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if ( !fmv1->child ) // there are no children for this block and size>=blk_thresh + { + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) return; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) return; +#endif + } else //This will never happen! + { + if ( !fmv1->mv_exist ) return; // the whole (blk_thresh x blk_thresh) has no motion vector + + if ( !fmv1->merge_sign ) + { + child_mv_decode_further( fmv1_array, fmv2_array, fmv1, fmv2, pmvx, pmvy, + num_symbol, subpel, x, y, xblk, yblk, hor, ver, + info, decode_parallelmv, t_level, bidir_exist, blk_thresh/2, count ); + return; + } + } + + // the motion vectors on RIGHT side has been discarded for alternative reconstruction + if (!bidir_exist) + { + if ( (fmv1->bi_mode == PARALLEL)&&(!decode_parallelmv) ) { + assert(0); + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + printf("!bidir_exist parallel detected\n"); + } + if ( (fmv1->bi_mode == RIGHT_CONNECTED_AFF) || fmv1->bi_mode==RIGHT_CONNECTED) + assert(0); // RIGHT_CONNECTED mode is prevented + return; + } + + assert(fmv1->bi_mode >= 0); //Added ib 04.02.2016 + if(fmv2!=NULL) + assert(fmv1->bi_mode == fmv2->bi_mode); + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + + if ( !info.layer_mv[t_level] ) // no layer structure, AGP or no AGP + { + if ( ( fmv1->bi_mode<=8 && fmv1->bi_mode != BLOCK_MERGING && !(fmv1->bi_mode == PARALLEL && !decode_parallelmv) ) || + ( fmv1->bi_mode>=9 && fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == INDIR) ){ + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x, y, info, t_level, blk_thresh); + + dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(dmvx, ctx_x); + if (EC_TYPE == AR_NARY) { + if (dmvx > num_symbol / 2 - (int) ((1 << subpel) * *pmvx)) + dmvx -= num_symbol; + else if (dmvx < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvx)) + dmvx += num_symbol; + } + + dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(dmvy, ctx_y); + if (EC_TYPE == AR_NARY) { + if (dmvy > num_symbol / 2 - (int) ((1 << subpel) * *pmvy)) + dmvy -= num_symbol; + else if (dmvy < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvy)) + dmvy += num_symbol; + } + }else if( fmv1->bi_mode <=8 || ( fmv1->bi_mode>=9 && fmv1->direct_idx == INDIRECT + && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == DIR) ){ + dmvx = 0; + dmvy = 0; + ////////////////////////// Added by Yuan Liu ///////////////////////////// + } + + if( fmv1->bi_mode >=9 && fmv1->bi_mode<=11 ){ //gotta decode trans MVs if they are applied + + if( !(fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + dmvx = 0; + dmvy = 0; + } + + if(fmv1->direct_idx == INDIRECT){ +//affine V1 + if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) || + (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) ){ +// printf("unusual encoding processes detected!\n"); +// assert(0); + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x, y, info, t_level, blk_thresh); + + aff1_dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(aff1_dmvx, ctx_x); + if (EC_TYPE == AR_NARY) { + if (aff1_dmvx > num_symbol / 2 - (int) ((1 << subpel) * *pmvx)) + aff1_dmvx -= num_symbol; + else if (aff1_dmvx < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvx)) + aff1_dmvx += num_symbol; + } + + aff1_dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(aff1_dmvy, ctx_y); + if (EC_TYPE == AR_NARY) { + if (aff1_dmvy > num_symbol / 2 - (int) ((1 << subpel) * *pmvy)) + aff1_dmvy -= num_symbol; + else if (aff1_dmvy < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvy)) + aff1_dmvy += num_symbol; + } + } +//affine V2 + if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) || + (fmv1->merge_idx == MERGE && fmv1->merge_dir == LEFT) || (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) ){ + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x+xblk2-1, y, info, t_level, blk_thresh); + + aff2_dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(aff2_dmvx, ctx_x); + if (EC_TYPE == AR_NARY) { + if (aff2_dmvx > num_symbol / 2 - (int) ((1 << subpel) * *pmvx)) + aff2_dmvx -= num_symbol; + else if (aff2_dmvx < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvx)) + aff2_dmvx += num_symbol; + } + + aff2_dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(aff2_dmvy, ctx_y); + if (EC_TYPE == AR_NARY) { + if (aff2_dmvy > num_symbol / 2 - (int) ((1 << subpel) * *pmvy)) + aff2_dmvy -= num_symbol; + else if (aff2_dmvy < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvy)) + aff2_dmvy += num_symbol; + } + } +//affine V3 + if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) || + (fmv1->merge_idx == MERGE && fmv1->merge_dir == UP) || (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) ){ + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x, y+yblk2-1, info, t_level, blk_thresh); + + aff3_dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(aff3_dmvx, ctx_x); + if (EC_TYPE == AR_NARY) { + if (aff3_dmvx > num_symbol / 2 - (int) ((1 << subpel) * *pmvx)) + aff3_dmvx -= num_symbol; + else if (aff3_dmvx < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvx)) + aff3_dmvx += num_symbol; + } + + aff3_dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(aff3_dmvy, ctx_y); + if (EC_TYPE == AR_NARY) { + if (aff3_dmvy > num_symbol / 2 - (int) ((1 << subpel) * *pmvy)) + aff3_dmvy -= num_symbol; + else if (aff3_dmvy < -(num_symbol / 2) - (int) ((1 << subpel) * *pmvy)) + aff3_dmvy += num_symbol; + } + } + } + else if(fmv1->direct_idx == DIRECT){ + + } + } + }else // layer structure, AGP or no AGP + { + ec_get_contexts_motion_field(&ctx_x, &ctx_y, frame_motion_field, + x, y, info, t_level, blk_thresh); + dmvx = ec_decode_word(ctx_x); // decode the mvx + ec_update_model(dmvx, ctx_x); + dmvy = ec_decode_word(ctx_y); // decode the mvy + ec_update_model(dmvy, ctx_y); + } + + if ( info.AGP_level[t_level] ) // AGP + { + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<bi_mode == PARALLEL)&&(!decode_parallelmv)) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + major_mvx = (int)(fmv1->mvx*AGP_scale)/(float)AGP_scale; + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + } else if ( fmv1->bi_mode == BLOCK_MERGING ) + { + fmv1->mvx = mvpred_x; + fmv1->mvy = mvpred_y; + assert(dmvx ==0 && dmvy == 0 ); + major_mvx = (int)(fmv1->mvx*AGP_scale)/(float)AGP_scale; + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + }else + { + major_mvx = (float) dmvx / AGP_scale + major_predx; + major_mvy = (float) dmvy / AGP_scale + major_predy; + // code the sub-symbols as binary sequence + sub_symx = sub_symy = 0; + for (sub_bit=0; sub_bitmvx = major_mvx + sub_mvx; + fmv1->mvy = major_mvy + sub_mvy; + } + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + +#ifdef DEBUG_SCALABLE_MV + fpAGP_debug = fopen(decoder_AGPdebug, "at"); + fprintf(fpAGP_debug, "x=%03d y=%03d blk=%2d ", x, y, xblk ); + fprintf(fpAGP_debug, "major_mvx=%.1f major_mvy=%.1f major_predx=%.1f major_predy=%.1f", + major_mvx, major_mvy, major_predx, major_predy) ; + fprintf(fpAGP_debug, " dmvx=%.1f dmvy=%.1f mvx=%.2f mvy=%.2f, ctx_x=%d\t ctx_y=%d\n", + fmv1->dmvx, fmv1->dmvy, fmv1->mvx, fmv1->mvy, ctx_x, ctx_x) ; + fclose(fpAGP_debug); +#endif + } + + if ( info.layer_mv[t_level] ) // layer structure + { + major_mvx = (float) dmvx / AGP_scale + major_predx; + major_mvy = (float) dmvy / AGP_scale + major_predy; + // code the sub-symbols as binary sequence + sub_symx = sub_symy = 0; + for (sub_bit=0; sub_bitsample_mvx = fmv1->mvx = major_mvx + sub_mvx; + fmv1->sample_mvy = fmv1->mvy = major_mvy + sub_mvy; + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + } // if ( info.AGP_level[t_level] ) // AGP + else if(!info.AGP_level[t_level]){ + fmv1->dmvx = (float) dmvx / (1 << subpel); + fmv1->dmvy = (float) dmvy / (1 << subpel); + + if(fmv1->bi_mode >= 9 && fmv1->bi_mode <= 11){ + if(fmv1->direct_idx == INDIRECT){ + if( fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && + fmv1->merge_dir == PAL_L && fmv1->aff_idx >= 0) || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + fmv1->aff1_dmvx = (float)aff1_dmvx/ (1 << subpel); + fmv1->aff1_dmvy = (float)aff1_dmvy/ (1 << subpel); + } + if( (fmv1->merge_idx == MERGE && fmv1->merge_dir == LEFT) || fmv1->merge_idx == INTER || + (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) + || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + fmv1->aff2_dmvx = (float)aff2_dmvx/ (1 << subpel); + fmv1->aff2_dmvy = (float)aff2_dmvy/ (1 << subpel); + } + if( (fmv1->merge_idx == MERGE && fmv1->merge_dir == UP) || fmv1->merge_idx == INTER || + (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx >= 0) + || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + fmv1->aff3_dmvx = (float)aff3_dmvx/ (1 << subpel); + fmv1->aff3_dmvy = (float)aff3_dmvy/ (1 << subpel); + } + } + } + } + + ///////////////////////// +// printf("bi_mode = %d, x = %d, y = %d, xblk = %d, yblk = %d, ctx_x = %d, ctx_y = %d\n fmv->dmvx = %f, fmv->dmvy = %f\n", +// fmv1->bi_mode,x,y,xblk2,yblk2,ctx_x, ctx_y,fmv1->dmvx,fmv1->dmvy); + ///////////////////////// + + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, 0, 0); + mvStat_setPos(x, y); + mvStat_setDMV((float)dmvx, (float)dmvy); + mvStat_writeDMVCTX(); + +#ifdef DEBUG_LAYER_STRUCTURE // for debug the layer structure coding + char base_file[80]; + FILE *fpbase; + // make base_file and enhance_file empty + sprintf(base_file, "decode_base%d.txt", count); + fpbase=fopen(base_file, "at"); + fprintf(fpbase, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, fmv1->mvx, fmv1->mvy, mvpred_x, mvpred_y); + fclose(fpbase); +#endif + + } + +} + +///////////////// Added by Yuan Liu on 01.30.2016 ///////////////////// +/*****************************************************************************/ +/* child_cand_decode() */ +/*****************************************************************************/ +void +child_cand_decode( vector_ptr fmv1_array, vector_ptr fmv2_array, vector_ptr fmv1, vector_ptr fmv2, + float *pmvx, float *pmvy, int num_symbol, int subpel, + int x, int y, int xblk, int yblk, int hor, int ver, + videoinfo info, int decode_parallelmv, int t_level, int bidir_exist, + int blk_thresh, int count ) +{ + int dmvx, dmvy, cx, cy, xblk2, yblk2; + int ctx_x, ctx_y; +#ifdef MEDIAN_PREDICTION + float mvpred_x, mvpred_y; +#endif + char value; + float major_mvx, major_mvy, sub_mvx, sub_mvy; + float major_predx, major_predy; + int AGP_scale, subpel_scale, sub_symx, sub_symy, sub_bit, sub_signx, sub_signy; + int enc_trans = 0; + int getnum; + + float mvpredstr_x[4], mvpredstr_y[4]; + vector_ptr mrg_left[4], mrg_right[4]; + int i, num = 0, num_dir = 0, mrg_num = 0; + + int map_side; + + int do_fmv1 = YES, do_fmv2 = YES; + + assert(fmv2 == NULL || fmv1->child == fmv2->child); + + xblk2 = ( x + xblk <= hor ) ? xblk : hor - x; + yblk2 = ( y + yblk <= ver ) ? yblk : ver - y; + + if( fmv1->child && xblk > blk_thresh ) { + + if(fmv2 != NULL) + assert(fmv2->child); + + cx = x; + cy = y; + child_cand_decode(fmv1_array, fmv2_array, fmv1->child0, fmv2 ? fmv2->child0 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y; + child_cand_decode(fmv1_array, fmv2_array, fmv1->child1, fmv2 ? fmv2->child1 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x; + cy = y + yblk / 2; + child_cand_decode(fmv1_array, fmv2_array, fmv1->child2, fmv2 ? fmv2->child2 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + + cx = x + xblk / 2; + cy = y + yblk / 2; + child_cand_decode(fmv1_array, fmv2_array, fmv1->child3, fmv2 ? fmv2->child3 : NULL, + pmvx, pmvy, num_symbol, subpel, cx, cy, xblk / 2, yblk / 2, + hor, ver, info, decode_parallelmv, t_level, bidir_exist, blk_thresh, count); + } else { + if( x >= hor || y >= ver ) return; + + if ( !fmv1->child ) // there are no children for this block and size>=blk_thresh + { + if(fmv2 != NULL) + assert( !fmv2->child ); + + // no motion vector for this block on this side + if ((fmv1->lifting_mode == IGNORED)) do_fmv1 = NO; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv1->bi_mode==DIRECTIONAL_IBLOCK) do_fmv1 = NO; +#endif + + if(fmv2 != NULL){ + // no motion vector for this block on this side + if ((fmv2->lifting_mode == IGNORED)) do_fmv2 = NO; +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + if (fmv2->bi_mode==DIRECTIONAL_IBLOCK) do_fmv2 = NO; +#endif + } + + } + + /////////////// MERGE detection /////////////////////// + if( fmv1->bi_mode == BLOCK_MERGING || + (fmv1->bi_mode >= 9 && fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == DIR) ){ + + if(fmv1->bi_mode == BLOCK_MERGING) + assert(do_fmv1 == YES && do_fmv2 == YES); + + for(i=0;i<=3;i++){ + mrg_left[i] = new vector; + mrg_right[i] = new vector; + + clean_mrg_mv(mrg_left[i]); + clean_mrg_mv(mrg_right[i]); + } + + if(fmv2 != NULL) + get_field_merge_mv_info(mrg_left, mrg_right,x,y,xblk2,yblk2,hor,ver,info,t_level,frame_motion_field, frame_motion_field2, prev_frame_motion_field2, prev_frame_motion_field1,0); + else + get_field_merge_mv_info(mrg_left, mrg_right,x,y,xblk2,yblk2,hor,ver,info,t_level,frame_motion_field, frame_motion_field2, prev_frame_motion_field2, prev_frame_motion_field1,1); + + + /////////////////////////// +/* for(i = 0;i <= 3;i++){ + printf("mrg_left[%d].mvx = %f, mrg_left[%d].mvy = %f\n",i,mrg_left[i]->mvx,i,mrg_left[i]->mvy); + + if(fmv2 != NULL){ + printf("mrg_right[%d].mvx = %f, mrg_right[%d].mvy = %f\n",i,mrg_right[i]->mvx,i,mrg_right[i]->mvy); + } + } +*/ /////////////////////////// + + for(i=0;i<=3;i++){ + if( (mrg_left[i]->mvx != (float)HUGE_VAL && mrg_left[i]->mvy != (float)HUGE_VAL) + || (mrg_right[i]->mvx != (float)HUGE_VAL && mrg_right[i]->mvy != (float)HUGE_VAL) ){ + mrg_num ++; + } + } +// printf("mrg_num = %d\n",mrg_num); + + /////////////////// MRG idx dec ////////////////// + if(mrg_num == 0) + assert(0); + else if(mrg_num == 1){ + fmv1->med_idx = 0; + + if(fmv2!=NULL) + fmv2->med_idx = 0; + }else if(mrg_num == 2){ + fmv1->med_idx = getbits(1); + + if(fmv2 != NULL) + fmv2->med_idx = fmv1->med_idx; + }else{ + assert(mrg_num == 3 || mrg_num == 4); + if(mrg_num == 3) + input_huff_bits(fmv1,mrg_num,cnt_tri,info); + else + input_huff_bits(fmv1,mrg_num,cnt_quad,info); + + assert(fmv1->med_idx >= 0 && fmv1->med_idx <= 3 ); + + if(fmv2!=NULL) + fmv2->med_idx = fmv1->med_idx; + } + + ////////////////////////////////////////////////// + if(fmv1->bi_mode == BLOCK_MERGING){ + if(mrg_left[fmv1->med_idx]->aff1_mvx != (float)HUGE_VAL || mrg_right[fmv1->med_idx]->aff1_mvx != (float)HUGE_VAL){ + assert( (mrg_left[fmv1->med_idx]->aff2_mvx != (float)HUGE_VAL && mrg_left[fmv1->med_idx]->aff3_mvx != (float)HUGE_VAL) || + (mrg_right[fmv1->med_idx]->aff2_mvx != (float)HUGE_VAL && mrg_right[fmv1->med_idx]->aff3_mvx != (float)HUGE_VAL) ); + + fmv1->aff_mrg = getbits(1); + + if(fmv2 != NULL) + fmv2->aff_mrg = fmv1->aff_mrg; + }else{ + fmv1->aff_mrg = NO; + + if(fmv2 != NULL) + fmv2->aff_mrg = NO; + } + + assert(fmv1->lifting_mode == UNDECIDED); + if(fmv2 != NULL) + assert(fmv2->lifting_mode == UNDECIDED); + } + //////////////////////////////////////////// + + if(fmv2 != NULL) + assert( (mrg_left[fmv1->med_idx]->mvx != (float)HUGE_VAL && mrg_left[fmv1->med_idx]->mvy != (float)HUGE_VAL) || + (mrg_right[fmv2->med_idx]->mvx != (float)HUGE_VAL && mrg_right[fmv2->med_idx]->mvy != (float)HUGE_VAL) ); + + if(mrg_left[fmv1->med_idx]->mvx != (float)HUGE_VAL && mrg_left[fmv1->med_idx]->mvy != (float)HUGE_VAL){ + fmv1->is_predictor = YES; + fmv1->lifting_mode = CONNECTED; + }else{ + fmv1->is_predictor = NO; + fmv1->lifting_mode = IGNORED; + do_fmv1 = NO; + } + + if(fmv2 != NULL){ + if(mrg_right[fmv2->med_idx]->mvx != (float)HUGE_VAL && mrg_right[fmv2->med_idx]->mvy != (float)HUGE_VAL){ + fmv2->is_predictor = YES; + fmv2->lifting_mode = CONNECTED; + }else{ + fmv2->is_predictor = NO; + fmv2->lifting_mode = IGNORED; + do_fmv2 = NO; + } + }else{ + do_fmv2 = NO; + } + } + /////////////////////////////////////////////////////// + + + if(do_fmv1 == YES){ + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + map_side = decode_parallelmv; + + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field, prev_frame_motion_field2, + x, y, xblk, yblk, info, t_level, blk_thresh); + + ///////////////////////////////// + if(fmv1->bi_mode == BLOCK_MERGING || (fmv1->bi_mode >= 9 && fmv1->direct_idx == INDIRECT && + fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == DIR) ){ + mvpred_x = mrg_left[fmv1->med_idx]->mvx; + mvpred_y = mrg_left[fmv1->med_idx]->mvy; + + if( fmv1->bi_mode == BLOCK_MERGING ){ + fmv1->aff1_mvx = mrg_left[fmv1->med_idx]->aff1_mvx;fmv1->aff1_mvy = mrg_left[fmv1->med_idx]->aff1_mvy; + fmv1->aff2_mvx = mrg_left[fmv1->med_idx]->aff2_mvx;fmv1->aff2_mvy = mrg_left[fmv1->med_idx]->aff2_mvy; + fmv1->aff3_mvx = mrg_left[fmv1->med_idx]->aff3_mvx;fmv1->aff3_mvy = mrg_left[fmv1->med_idx]->aff3_mvy; + } + + assert(mvpred_x != (float)HUGE_VAL && mvpred_y != (float)HUGE_VAL); + }else if( ( fmv1->bi_mode <= 8 && !(fmv1->bi_mode == PARALLEL && !map_side) && fmv1->bi_mode != BLOCK_MERGING ) || + (fmv1->bi_mode >= 9 && fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P && fmv1->trans_pred_idx == INDIR) ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL){ + num++; + if(fmv1->bi_mode == BLOCK_MERGING){ + if( (float(x)-mvpredstr_x[i] >= 0) && (float(x)-mvpredstr_x[i]<= (hor - xblk2)) && (float(y)-mvpredstr_y[i] >= 0) + && (float(y) - mvpredstr_y[i] <= (ver - yblk2)) ) + num_dir++; + } + } + } + assert(num_dir <= num); + +// assert( (fmv1->bi_mode >= 0 && fmv1->bi_mode <= 8) || ); + + if(num == 0) + fmv1->med_idx = -1; + else if(num == 1){ + assert(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL); + fmv1->med_idx = 0; + } + else if(num == 2){ + getnum = getbits(1); + fmv1->med_idx = getnum; + } + else if(num >= 3){ + assert(num == 3 || num == 4); + if(num == 3) + input_huff_bits(fmv1,num,cnt_tri,info); + else + input_huff_bits(fmv1,num,cnt_quad,info); + } + else + assert(0); + + if(num == 0){ + mvpred_x = 0.0; + mvpred_y = 0.0; + }else{ + if( (fmv1->bi_mode == BLOCK_MERGING) && num_dir == 0){ + assert(fmv1->med_idx == -1); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else if( (fmv1->bi_mode >= 0 && fmv1->bi_mode <= 8) || (fmv1->bi_mode >= 9) ){ + assert(fmv1->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv1->med_idx]; + mvpred_y = mvpredstr_y[fmv1->med_idx]; + } + } + } + else if( (fmv1->bi_mode == PARALLEL && !map_side) ){ + + if( (fmv1->bi_mode == PARALLEL && !map_side) ) + fmv1->med_idx = fmv2->med_idx; + else + assert(0); + } + ///////////////////////////////// + + if (!info.AGP_level[t_level]) // no AGP + { + if (!info.layer_mv[t_level]) // no layer structure in this temporal level + { + if ( ((fmv1->bi_mode <=8) && (fmv1->bi_mode == PARALLEL)&&(!map_side)) ) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + } else if( fmv1->bi_mode <=8 || + (fmv1->bi_mode >= 9 && fmv1->direct_idx == INDIRECT && fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + fmv1->mvx = fmv1->dmvx + mvpred_x; + fmv1->mvy = fmv1->dmvy + mvpred_y; + } + + ////////////// Added by Yuan Liu ////////////////// + if(fmv1->bi_mode >= 7 && fmv1->bi_mode <= 11){ + if( (fmv1->bi_mode >= 7 && fmv1->aff_mrg == YES) || fmv1->bi_mode >= 9 ) + printf("\nbi_mode = %d, med_idx = %d, x = %d, y = %d, xblk = %d, yblk = %d\nfmv1->mvx = %f, fmv1->mvy = %f, fmv1->dmvx = %f, fmv1->dmvy = %f\n" + ,fmv1->bi_mode, fmv1->med_idx,x,y,xblk2,yblk2,fmv1->mvx,fmv1->mvy, fmv1->dmvx, fmv1->dmvy); + + if(fmv1->bi_mode == 7 && fmv1->aff_mrg == YES){ + printf("AFF_MRG!\n"); + printf("fmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\n", + fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy); + } + + if(fmv1->bi_mode>=9 && fmv1->direct_idx == DIRECT){ + + fmv1->aff_idx = -1; + + get_aff_mvs(fmv1,x,y,xblk2,yblk2,hor,ver,frame_motion_field, prev_frame_motion_field2,1); + printf("aff_index = %d\nfmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\n" + ,fmv1->aff_idx,fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy); + } + else if(fmv1->bi_mode>=9 && fmv1->direct_idx != DIRECT){ + get_aff_mvs(fmv1,x,y,xblk2,yblk2,hor,ver,frame_motion_field, prev_frame_motion_field2,1); + + ////////////////////////////////////////// + if(fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) && fmv1->aff_idx == -1 ){ + fmv1->aff1_mvx = (-1) * fmv2->aff1_mvx; + fmv1->aff1_mvy = (-1) * fmv2->aff1_mvy; + fmv1->aff2_mvx = (-1) * fmv2->aff2_mvx; + fmv1->aff2_mvy = (-1) * fmv2->aff2_mvy; + fmv1->aff3_mvx = (-1) * fmv2->aff3_mvx; + fmv1->aff3_mvy = (-1) * fmv2->aff3_mvy; + } + ////////////////////////////////////////// + + printf("aff_index = %d\nfmv1->aff1_mvx = %f, fmv1->aff1_mvy = %f\n fmv1->aff2_mvx = %f, fmv1->aff2_mvy = %f\n fmv1->aff3_mvx = %f, fmv1->aff3_mvy = %f\nmerge_idx = %d, merge_dir = %d\n" + ,fmv1->aff_idx,fmv1->aff1_mvx, fmv1->aff1_mvy, fmv1->aff2_mvx , fmv1->aff2_mvy, fmv1->aff3_mvx, fmv1->aff3_mvy,fmv1->merge_idx,fmv1->merge_dir); + + if(fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) + printf("fmv1->trans_pred_idx = %d\n",fmv1->trans_pred_idx); + + if(fmv1->merge_idx == MERGE && fmv1->merge_dir == UP) + printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n", fmv1->aff3_dmvx, fmv1->aff3_dmvy); + else if(fmv1->merge_idx == MERGE && fmv1->merge_dir == LEFT) + printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n", fmv1->aff2_dmvx, fmv1->aff2_dmvy); + else if(fmv1->merge_idx == INTER || (fmv1->merge_idx == MERGE && (fmv1->merge_dir == PAL_L) + && fmv1->aff_idx >=0) || (fmv1->merge_idx == MERGE && fmv1->merge_dir == TRAN_P) ){ + printf("\nfmv1->aff1_dmvx = %f, fmv1->aff1_dmvy = %f\n", fmv1->aff1_dmvx, fmv1->aff1_dmvy); + printf("fmv1->aff2_dmvx = %f, fmv1->aff2_dmvy = %f\n", fmv1->aff2_dmvx, fmv1->aff2_dmvy); + printf("fmv1->aff3_dmvx = %f, fmv1->aff3_dmvy = %f\n\n", fmv1->aff3_dmvx, fmv1->aff3_dmvy); + } + } + } +//Added on 08.08.2018 + frame_mv_cnt ++; + sum_mv2 += (fmv1->mvx*fmv1->mvx + fmv1->mvy*fmv1->mvy); + sum_mv1 += sqrt(fmv1->mvx*fmv1->mvx + fmv1->mvy*fmv1->mvy); + ////////////////////////////////////////////////////// + + if(fmv1->bi_mode <= 6 || fmv1->bi_mode == 8 || (fmv1->bi_mode == 7 && fmv1->aff_mrg == NO) ){// Added by Yuan Liu + assert( (x + xblk2 - fmv1->mvx <= hor ) && + (y + yblk2 - fmv1->mvy <= ver ) && + (x - fmv1->mvx >= 0 ) && + (y - fmv1->mvy >= 0 ) ); + if (!map_side) { + assert( (!(fmv1->bi_mode == PARALLEL)) || + ((x + xblk2 - fmv2->mvx <= hor ) && + (y + yblk2 - fmv2->mvy <= ver ) && + (x - fmv2->mvx >= 0 ) && + (y - fmv2->mvy >= 0 )) ); + } + }//Added by Yuan Liu + + }else // layer structure + { + fmv1->sample_mvx = fmv1->mvx = fmv1->dmvx + mvpred_x; + fmv1->sample_mvy = fmv1->mvy = fmv1->dmvy + mvpred_y; + } + + if(fmv1->bi_mode >= 0 && fmv1->bi_mode <= 8){ + fmv1->dmvx = fmv1->mvx - mvpred_x; // update the prediction error + fmv1->dmvy = fmv1->mvy - mvpred_y; + } + } + + if ( info.AGP_level[t_level] ) // AGP + { + assert(0); + AGP_scale = 1<< (subpel-info.AGP_level[t_level]); + subpel_scale = 1<bi_mode == PARALLEL)&&(!map_side)) { + fmv1->mvx = -fmv2->mvx; + fmv1->mvy = -fmv2->mvy; + major_mvx = (int)(fmv1->mvx*AGP_scale)/(float)AGP_scale; + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + } else if ( fmv1->bi_mode == BLOCK_MERGING ) + { + fmv1->mvx = mvpred_x; + fmv1->mvy = mvpred_y; + assert(dmvx ==0 && dmvy == 0 ); + major_mvx = (int)(fmv1->mvx*AGP_scale)/(float)AGP_scale; + major_mvy = (int)(fmv1->mvy*AGP_scale)/(float)AGP_scale; + }else + { + major_mvx = (float) dmvx / AGP_scale + major_predx; + major_mvy = (float) dmvy / AGP_scale + major_predy; + // code the sub-symbols as binary sequence + sub_symx = sub_symy = 0; + for (sub_bit=0; sub_bitmvx = major_mvx + sub_mvx; + fmv1->mvy = major_mvy + sub_mvy; + } + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + +#ifdef DEBUG_SCALABLE_MV + fpAGP_debug = fopen(decoder_AGPdebug, "at"); + fprintf(fpAGP_debug, "x=%03d y=%03d blk=%2d ", x, y, xblk ); + fprintf(fpAGP_debug, "major_mvx=%.1f major_mvy=%.1f major_predx=%.1f major_predy=%.1f", + major_mvx, major_mvy, major_predx, major_predy) ; + fprintf(fpAGP_debug, " dmvx=%.1f dmvy=%.1f mvx=%.2f mvy=%.2f, ctx_x=%d\t ctx_y=%d\n", + fmv1->dmvx, fmv1->dmvy, fmv1->mvx, fmv1->mvy, ctx_x, ctx_x) ; + fclose(fpAGP_debug); +#endif + } + + if ( info.layer_mv[t_level] ) // layer structure + { + major_mvx = (float) dmvx / AGP_scale + major_predx; + major_mvy = (float) dmvy / AGP_scale + major_predy; + // code the sub-symbols as binary sequence + sub_symx = sub_symy = 0; + for (sub_bit=0; sub_bitsample_mvx = fmv1->mvx = major_mvx + sub_mvx; + fmv1->sample_mvy = fmv1->mvy = major_mvy + sub_mvy; + // only major symbols are median predicted, sub-symbols are coded by binary sequence + fmv1->dmvx = major_mvx - major_predx; + fmv1->dmvy = major_mvy - major_predy; + } + } // if ( info.AGP_level[t_level] ) // AGP + + fmv1->is_predictor = YES; + update_frame_motion_field(frame_motion_field, x, y, xblk, yblk, info, fmv1, fmv1->dmvx, + fmv1->dmvy, fmv1->mvx, fmv1->mvy); + +#ifdef DEBUG_LAYER_STRUCTURE // for debug the layer structure coding + char base_file[80]; + FILE *fpbase; + // make base_file and enhance_file empty + sprintf(base_file, "decode_base%d.txt", count); + fpbase=fopen(base_file, "at"); + fprintf(fpbase, "x=%03d y=%03d blk=%d\t mvx=%.2f\t mvy=%.2f\t predx=%.2f predy=%.2f \n", + x, y, xblk, fmv1->mvx, fmv1->mvy, mvpred_x, mvpred_y); + fclose(fpbase); +#endif + + }//if do_fmv1 + +/**********************************************************/ +/***************** fmv2 *******************************/ +/**********************************************************/ + +if(do_fmv2 == YES){ + + if(fmv2 != NULL){ + + //////////// Added by Yuan Liu on 01.23.2016 ////////////// + for(i=0;i<=3;i++){ + mvpredstr_x[i] = (float)HUGE_VAL; + mvpredstr_y[i] = (float)HUGE_VAL; + } + ///////////////////////////////////////////////////////////// + + map_side = (decode_parallelmv + 1) % 2; + assert(map_side == 0); + + num = 0; + num_dir = 0; + + get_median_predictor_motion_field(mvpredstr_x, mvpredstr_y, frame_motion_field2,prev_frame_motion_field1, + x, y, xblk, yblk, info, t_level, blk_thresh); + + ///////////////////////////////// + if(fmv2->bi_mode == BLOCK_MERGING || (fmv2->bi_mode >= 9 && fmv2->direct_idx == INDIRECT && + fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P && fmv2->trans_pred_idx == DIR) ){ + mvpred_x = mrg_right[fmv2->med_idx]->mvx; + mvpred_y = mrg_right[fmv2->med_idx]->mvy; + + if(fmv2->bi_mode == BLOCK_MERGING){ + fmv2->aff1_mvx = mrg_right[fmv2->med_idx]->aff1_mvx;fmv2->aff1_mvy = mrg_right[fmv2->med_idx]->aff1_mvy; + fmv2->aff2_mvx = mrg_right[fmv2->med_idx]->aff2_mvx;fmv2->aff2_mvy = mrg_right[fmv2->med_idx]->aff2_mvy; + fmv2->aff3_mvx = mrg_right[fmv2->med_idx]->aff3_mvx;fmv2->aff3_mvy = mrg_right[fmv2->med_idx]->aff3_mvy; + } + + assert(mvpred_x != (float)HUGE_VAL && mvpred_y != (float)HUGE_VAL); + }else if( (fmv2->bi_mode <= 8 && !(fmv2->bi_mode == PARALLEL && !map_side && fmv2->bi_mode != BLOCK_MERGING) ) || + (fmv2->bi_mode >= 9 && fmv2->direct_idx == INDIRECT && fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P && fmv2->trans_pred_idx == INDIR) ){ + for(i=0;i<=3;i++){ + if(mvpredstr_x[i] != (float)HUGE_VAL && mvpredstr_y[i] != (float)HUGE_VAL){ + num++; + if(fmv2->bi_mode == BLOCK_MERGING){ + if( (float(x)-mvpredstr_x[i] >= 0) && (float(x)-mvpredstr_x[i]<= (hor - xblk2)) && (float(y)-mvpredstr_y[i] >= 0) + && (float(y) - mvpredstr_y[i] <= (ver - yblk2)) ) + num_dir++; + } + } + } + assert(num_dir <= num); + + if(num == 0) + fmv2->med_idx = -1; + else if(num == 1){ + assert(mvpredstr_x[0] != (float)HUGE_VAL && mvpredstr_y[0] != (float)HUGE_VAL); + fmv2->med_idx = 0; + } + else if(num == 2){ + getnum = getbits(1); + fmv2->med_idx = getnum; + } + else if(num >= 3){ + assert(num == 3 || num == 4); + if(num == 3) + input_huff_bits(fmv2,num,cnt_tri,info); + else + input_huff_bits(fmv2,num,cnt_quad,info); + } + else + assert(0); + + if(num == 0){ + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else{ + if( (fmv2->bi_mode == BLOCK_MERGING) && num_dir == 0){ + assert(fmv2->med_idx == -1); + mvpred_x = 0.0; + mvpred_y = 0.0; + } + else if( (fmv2->bi_mode >= 0 && fmv2->bi_mode <= 8) || (fmv2->bi_mode >= 9) ){ + assert(fmv2->med_idx >= 0); + mvpred_x = mvpredstr_x[fmv2->med_idx]; + mvpred_y = mvpredstr_y[fmv2->med_idx]; + } + } + } + else if( (fmv2->bi_mode == PARALLEL && !map_side) ){ + + if( (fmv2->bi_mode == PARALLEL && !map_side) ) + fmv2->med_idx = fmv2->med_idx; + else + assert(0); + } + ///////////////////////////////// + + if (!info.AGP_level[t_level]) // no AGP + { + if (!info.layer_mv[t_level]) // no layer structure in this temporal level + { + if ( ((fmv2->bi_mode <=8) && (fmv2->bi_mode == PARALLEL)&&(!map_side)) ) { + fmv2->mvx = -fmv1->mvx; + fmv2->mvy = -fmv1->mvy; + } else if( fmv2->bi_mode <=8 || (fmv2->bi_mode >= 9 && fmv2->direct_idx == INDIRECT && + fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P) ) { + fmv2->mvx = fmv2->dmvx + mvpred_x; + fmv2->mvy = fmv2->dmvy + mvpred_y; + } + + ////////////// Added by Yuan Liu ////////////////// + if(fmv2->bi_mode >= 7 && fmv2->bi_mode <= 11){ + if( (fmv2->bi_mode >= 7 && fmv2->aff_mrg == YES) || fmv2->bi_mode >= 9 ) + printf("\nbi_mode = %d, med_idx = %d, x = %d, y = %d, xblk = %d, yblk = %d\nfmv2->mvx = %f, fmv2->mvy = %f, fmv2->dmvx = %f, fmv2->dmvy = %f\n" + ,fmv2->bi_mode, fmv2->med_idx,x,y,xblk2,yblk2,fmv2->mvx,fmv2->mvy, fmv2->dmvx, fmv2->dmvy); + + if(fmv2->bi_mode == 7 && fmv2->aff_mrg == YES){ + printf("AFF_MRG!\n"); + printf("fmv2->aff1_mvx = %f, fmv2->aff1_mvy = %f\n fmv2->aff2_mvx = %f, fmv2->aff2_mvy = %f\n fmv2->aff3_mvx = %f, fmv2->aff3_mvy = %f\n", + fmv2->aff1_mvx, fmv2->aff1_mvy, fmv2->aff2_mvx , fmv2->aff2_mvy, fmv2->aff3_mvx, fmv2->aff3_mvy); + } + + if(fmv2->bi_mode>=9 && fmv2->direct_idx == DIRECT){ + + fmv2->aff_idx = -1; + + get_aff_mvs(fmv2,x,y,xblk2,yblk2,hor,ver,frame_motion_field2,prev_frame_motion_field1,1); + printf("aff_index = %d\nfmv2->aff1_mvx = %f, fmv2->aff1_mvy = %f\n fmv2->aff2_mvx = %f, fmv2->aff2_mvy = %f\n fmv2->aff3_mvx = %f, fmv2->aff3_mvy = %f\n" + ,fmv2->aff_idx,fmv2->aff1_mvx, fmv2->aff1_mvy, fmv2->aff2_mvx , fmv2->aff2_mvy, fmv2->aff3_mvx, fmv2->aff3_mvy); + } + else if(fmv2->bi_mode>=9 && fmv2->direct_idx != DIRECT){ + + if(fmv2->direct_idx == INDIRECT && fmv2->merge_idx == MERGE && fmv2->merge_dir == PAL_L) + get_aff_mvs(fmv2,x,y,xblk2,yblk2,hor,ver,frame_motion_field2,prev_frame_motion_field1,0); + else + get_aff_mvs(fmv2,x,y,xblk2,yblk2,hor,ver,frame_motion_field2,prev_frame_motion_field1,1); + + ////////////////////////////////////////// + if(fmv2->merge_idx == MERGE && fmv2->merge_dir == PAL_L && fmv2->aff_idx == -1 ){ + fmv2->aff1_mvx = (-1) * fmv1->aff1_mvx; + fmv2->aff1_mvy = (-1) * fmv1->aff1_mvy; + fmv2->aff2_mvx = (-1) * fmv1->aff2_mvx; + fmv2->aff2_mvy = (-1) * fmv1->aff2_mvy; + fmv2->aff3_mvx = (-1) * fmv1->aff3_mvx; + fmv2->aff3_mvy = (-1) * fmv1->aff3_mvy; + } + ////////////////////////////////////////// + + printf("aff_index = %d\nfmv2->aff1_mvx = %f, fmv2->aff1_mvy = %f\n fmv2->aff2_mvx = %f, fmv2->aff2_mvy = %f\n fmv2->aff3_mvx = %f, fmv2->aff3_mvy = %f\nmerge_idx = %d, merge_dir = %d\n" + ,fmv2->aff_idx,fmv2->aff1_mvx, fmv2->aff1_mvy, fmv2->aff2_mvx , fmv2->aff2_mvy, fmv2->aff3_mvx, fmv2->aff3_mvy,fmv2->merge_idx,fmv2->merge_dir); + + if(fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P) + printf("fmv2->trans_pred_idx = %d\n",fmv2->trans_pred_idx); + + if(fmv2->merge_idx == MERGE && fmv2->merge_dir == UP) + printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n", fmv2->aff3_dmvx, fmv2->aff3_dmvy); + else if(fmv2->merge_idx == MERGE && fmv2->merge_dir == LEFT) + printf("fmv2->aff2_dmvx = %f, fmv2->aff2_dmvy = %f\n", fmv2->aff2_dmvx, fmv2->aff2_dmvy); + else if(fmv2->merge_idx == INTER || (fmv2->merge_idx == MERGE && (fmv2->merge_dir == PAL_L) + && fmv2->aff_idx >=0) || (fmv2->merge_idx == MERGE && fmv2->merge_dir == TRAN_P) ){ + printf("\nfmv2->aff1_dmvx = %f, fmv2->aff1_dmvy = %f\n", fmv2->aff1_dmvx, fmv2->aff1_dmvy); + printf("fmv2->aff2_dmvx = %f, fmv2->aff2_dmvy = %f\n", fmv2->aff2_dmvx, fmv2->aff2_dmvy); + printf("fmv2->aff3_dmvx = %f, fmv2->aff3_dmvy = %f\n\n", fmv2->aff3_dmvx, fmv2->aff3_dmvy); + } + } + } + ////////////////////////////////////////////////////// + + if(fmv2->bi_mode <= 6 || fmv2->bi_mode == 8 || (fmv2->bi_mode == 7 && fmv2->aff_mrg == NO) ){// Added by Yuan Liu + assert( (x + xblk2 - fmv2->mvx <= hor ) && + (y + yblk2 - fmv2->mvy <= ver ) && + (x - fmv2->mvx >= 0 ) && + (y - fmv2->mvy >= 0 ) ); + if (!map_side) { + assert( (!(fmv2->bi_mode == PARALLEL)) || + ((x + xblk2 - fmv1->mvx <= hor ) && + (y + yblk2 - fmv1->mvy <= ver ) && + (x - fmv1->mvx >= 0 ) && + (y - fmv1->mvy >= 0 )) ); + } + }//Added by Yuan Liu + + }else // layer structure + { + fmv2->sample_mvx = fmv2->mvx = fmv2->dmvx + mvpred_x; + fmv2->sample_mvy = fmv2->mvy = fmv2->dmvy + mvpred_y; + } + + if(fmv2->bi_mode >= 0 && fmv2->bi_mode <= 8){ + fmv2->dmvx = fmv2->mvx - mvpred_x; // update the prediction error + fmv2->dmvy = fmv2->mvy - mvpred_y; + } + } + + + fmv2->is_predictor = YES; + update_frame_motion_field(frame_motion_field2, x, y, xblk, yblk, info, fmv2, fmv2->dmvx, + fmv2->dmvy, fmv2->mvx, fmv2->mvy); + + }//if fmv2 != NULL + +}//if do_fmv2 + +if( fmv1->bi_mode == BLOCK_MERGING ){ + for(i=0;i<=3;i++){ + delete(mrg_left[i]); + delete(mrg_right[i]); + } +} + +}//if child else + +} + +/****************************************************************************/ +/* mv_decode() 解码mv 解码一帧 */ +/****************************************************************************/ +long int +mv_decode( vector_ptr fmv1, vector_ptr fmv2, int decode_map, + int meandepth, videoinfo info, int large, int t_level, long int starting_pos, + int bidir_exist, int count, int GOP_counter) +{ + int x, y, X, Y, xnum, ynum, xblk, yblk, hor, ver, pos, small, itemp, subpel; + int num_symbol; + float pmvx, pmvy; + long int mvBytes = 0, major_bytes, initial_pos, enhance_bytes; + int sub_bit, blk_thresh; + int i,j; + + if(decode_map == 0 || fmv2 == NULL){ + frame_mv_cnt = 0; + sum_mv2 = 0; + sum_mv1 = 0; + } + + if(fmv2 != NULL){ + for(i=0;i<=11;i++){ + bi_mode_num012[i]=0; + bi_mode_num345[i]=0; + } + use_huff = 0; + } + + // for motion field in a frame 申请运动场 + frame_motion_field = (FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(FRAME_MOTION_FIELD), "frame_motion_field"); + frame_motion_field2 = (FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(FRAME_MOTION_FIELD), "frame_motion_field2"); + + blk_thresh = 0; + if (info.layer_mv[t_level]) + blk_thresh = LAYER_BLOCK_SIZE; + +#ifdef DEBUG_LAYER_STRUCTURE + char base_file[80], enhance_file[80]; + FILE *fpbase, *fpenhance; + // make base_file and enhance_file empty + sprintf(base_file, "decode_base%d.txt", count); + if (fpbase=fopen(base_file, "rt") ) + { + fclose(fpbase); + fpbase=fopen(base_file, "wt"); + fclose(fpbase); + } + sprintf(enhance_file, "decode_enhance%d.txt", count); + if (fpenhance=fopen(enhance_file, "rt") ) + { + fclose(fpenhance); + fpenhance=fopen(enhance_file, "wt"); + fclose(fpenhance); + } +#endif + + initial_pos = starting_pos; // for scalable motion vector coding 为可伸缩运动矢量编码 + + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + subpel = info.subpel[t_level]; + hor = info.ywidth; + ver = info.yheight; + small = xblk; + itemp = info.level[t_level]; + while( itemp != 1 ) { + small /= 2; + itemp--; + } + +#ifdef DEBUG_SCALABLE_MV + sprintf(decoder_AGPdebug, "decoder_AGP_debugfile_GOP%03d_count%03d.txt", GOP_counter, count); + debug_counter++; +#endif + + num_symbol = 0; + + if (bidir_exist) // the sign whethe the motion vectors on this side exist 标示在这边运动向量是否存在 + { + fseek(fpbit, initial_pos, SEEK_SET); + major_bytes = ec_dec_preinit(fpbit); // the number of bytes for major symbols in base layer 字节的数量为主要符号在基本层 + starting_pos += major_bytes; + if (info.AGP_exist[t_level])// 子像素存在多少 + { + // sign bytes + get_splitted_bytes(store_splitted_sign[0], &(splitted_sign_byte_num[0]), info, t_level, fpbit, starting_pos); + starting_pos += splitted_sign_byte_num[0]+2; + splitted_sign_bit_num[0] = 0; + splitted_sign_byte_num[0] = 0; // reset to starting position 0 + // get the sub-symbol bits in the order of significance 根据重要性获得子符号的bit + for (sub_bit=0; sub_bit 0){ + sum_mv2 /= frame_mv_cnt; + sum_mv1 /= frame_mv_cnt; + sum_mv2 = sum_mv2 - sum_mv1*sum_mv1; + + printf("VAR = %f, frame_mv_cnt = %d\n",sum_mv2, frame_mv_cnt); + } + } + + return mvBytes; // the number of motion vector bytes for this set of motion vectors + + +} + + +/*****************************************************************************/ +/* mv_decoding() 解码mv */ +/*****************************************************************************/ +long int +mv_decoding( videoinfo info, vector_ptr * yfmv, int GOP_counter, long int starting_pos, int simul_dec, int theo_dec ) +{ + int i, j, count, dist, meandepth, GOPsz; + int eff_GOPsz[20]; // maximum number of temporal levels = 20; + long int mvBytes = 0; // the total number of bytes for all sets of motion vectors + long int cur_bytes; // the number of bytes for current set of motion vectors + + for(i=0;i<=2;i++){ + cnt_tri[i]=0; + } + for(i=0;i<=3;i++){ + cnt_quad[i]=0; + } + + for(i=0;i<27;i++) + aff_cum_idx[i]=0; + + // starting_pos: the starting position for current set of motion vectors in the video bitstream + + prev_frame_motion_field1 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, // 先前帧的运动场 + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field1"); + prev_frame_motion_field2 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field2"); + + //Added on 08.20.2016 + prev_frame_motion_field_left1 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, // 先前帧的运动场左边 + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field_left1"); + prev_frame_motion_field_left2 = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "prev_frame_motion_field_left2"); + //Added on 08.20.2016 + + if(GOP_counter == 0 && simul_dec == NO // 第一个gop。申请空间并初始化 +// && theo_dec == YES + ) + { + for(i = 0;i < G_LEVEL; i++){ + buffer_frame_motion_field1_dec[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "buffer_frame_motion_field1_dec"); + buffer_frame_motion_field2_dec[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "buffer_frame_motion_field2_dec"); + + clear_frame_motion_field_simp(buffer_frame_motion_field1_dec[i], info); + clear_frame_motion_field_simp(buffer_frame_motion_field2_dec[i], info); + +//Added on 02.05.2018 + save_buffer_frame_motion_field1_dec[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "buffer_frame_motion_field1_dec"); + save_buffer_frame_motion_field2_dec[i] = (SIMP_FRAME_MOTION_FIELD*)getarray(info.yheight*info.ywidth, + sizeof(SIMP_FRAME_MOTION_FIELD), "buffer_frame_motion_field2_dec"); + + clear_frame_motion_field_simp(save_buffer_frame_motion_field1_dec[i], info); + clear_frame_motion_field_simp(save_buffer_frame_motion_field2_dec[i], info); + } + } + +//Added on 02.08.2018 + if(simul_dec == YES){ + for(i = 0; i <= info.tPyrLev - 2; i++){ + copy_frame_motion_field2(save_buffer_frame_motion_field1_dec[i], buffer_frame_motion_field1_dec[i], info); + copy_frame_motion_field2(save_buffer_frame_motion_field2_dec[i], buffer_frame_motion_field2_dec[i], info); + } + } + + if((info.GOPsz * GOP_counter) == SIMUL_POINT && theo_dec == NO) + { + for(i = 0; i <= info.tPyrLev - 2; i++){ + copy_frame_motion_field2(buffer_frame_motion_field1_dec[i], save_buffer_frame_motion_field1_dec[i], info); + copy_frame_motion_field2(buffer_frame_motion_field2_dec[i], save_buffer_frame_motion_field2_dec[i], info); + } + } + + + GOPsz = info.GOPsz; + dist = ( int )pow( 2.0, ( double )( info.tPyrLev - 1 ) ); + + // determine effective GOP size in level i + for( i = 0; i < info.tPyrLev; i++ ) { + eff_GOPsz[i] = GOPsz; + GOPsz /= 2; + } + + count = 1; + for( i = info.tPyrLev - 1; i >= 0; i-- ) {// 逐时域层向下减 + meandepth = info.pixeldepth + ( i+1 + 1 ) / 2; // i+1 is the tPyrLev 位深,越高的位深越大 + count++; + + printf("LEVEL CHANGED!\n"); + clear_frame_motion_field_simp(prev_frame_motion_field1, info); + clear_frame_motion_field_simp(prev_frame_motion_field2, info); + + //Added on 08.20.2016 + clear_frame_motion_field_simp(prev_frame_motion_field_left1, info); + clear_frame_motion_field_simp(prev_frame_motion_field_left2, info); + //Added on 08.20.2016 + + if(GOP_counter >= 1 && i <= info.tPyrLev - 2){ + copy_frame_motion_field2(buffer_frame_motion_field1_dec[i], prev_frame_motion_field1, info); + copy_frame_motion_field2(buffer_frame_motion_field2_dec[i], prev_frame_motion_field2, info); + } + + for( j = 1; j <= eff_GOPsz[i]; j += 2 ) // 一帧一帧去做 + { + if (j == eff_GOPsz[i]) // 最后一帧 + { // single MVF + printf("single MVF detected!\n"); + + if( i >= info.t_level ) { + if (dec_scene_change[i][j] == NO) { + mvStat_setFrame(GOP_counter, i, j); + cur_bytes = mv_decode(yfmv[count], NULL, 1, + meandepth, info, dist, i, starting_pos, 1, count, GOP_counter ); + mvBytes += cur_bytes; starting_pos += cur_bytes; + if ( info.layer_mv[i] && !info.layer_exist[i] ) // enhancement layer is discarded + layer_structure_mv_trim(info, i, j, yfmv[count], count); +#ifdef DEBUG_BLOCK_MODE_MV_INFO + write_block_mode_motion_vector("decoderleft", GOP_counter, count, 1, yfmv[count], info, i); +#endif + } + } + count++; + } + else + { + if( i >= info.t_level ) { + if (dec_scene_change[i][j] == NO && dec_scene_change[i][j + 1] == NO) // 左右都可参考 + { + printf("\n\nBI MC, i = %d, j = %d, eff_GOPsz = %d, count = %d, count+1 = %d\n",i,j,eff_GOPsz[i], count,count+1); + mvStat_setFrame(GOP_counter, i, j); + cur_bytes = mv_decode(yfmv[count], yfmv[count + 1], 1, + meandepth, info, dist, i, starting_pos, 1, count, GOP_counter ); + mvBytes += cur_bytes; + starting_pos += cur_bytes; + mvStat_setFrame(GOP_counter, i, j + 1); + printf("\n\nBI MC, i = %d, j = %d, eff_GOPsz = %d, count+1 = %d, count = %d\n",i,j,eff_GOPsz[i], count+1,count); + cur_bytes = mv_decode(yfmv[count + 1], yfmv[count], 0, + meandepth, info, dist, i, starting_pos, info.bi_exist[i], count+1, GOP_counter ); + mvBytes += cur_bytes; starting_pos += cur_bytes; + if ( info.layer_mv[i] && !info.layer_exist[i] ) // enhancement layer is discarded + { + layer_structure_mv_trim(info, i, j, yfmv[count], count); + layer_structure_mv_trim(info, i, j+1, yfmv[count+1], count+1); + } +#ifdef DEBUG_BLOCK_MODE_MV_INFO + write_block_mode_motion_vector("decoderleft", GOP_counter, count, 0, yfmv[count], info, i); + write_block_mode_motion_vector("decoderright",GOP_counter, count+1, 0, yfmv[count+1], info, i); +#endif + + } + else if (dec_scene_change[i][j] == NO) { + printf("\n\nLEFT MC, i = %d, j = %d, eff_GOPsz = %d, count = %d\n",i,j,eff_GOPsz[i], count); + + mvStat_setFrame(GOP_counter, i, j); + cur_bytes = mv_decode(yfmv[count], NULL, 1, + meandepth, info, dist, i, starting_pos, 1, count, GOP_counter ); + mvBytes += cur_bytes; starting_pos += cur_bytes; + if ( info.layer_mv[i] && !info.layer_exist[i] ) // enhancement layer is discarded + layer_structure_mv_trim(info, i, j, yfmv[count], count); +#ifdef DEBUG_BLOCK_MODE_MV_INFO + write_block_mode_motion_vector("decoderleft", GOP_counter, count, 1, yfmv[count], info, i); +#endif + /////////////// Added by Yuan Liu on 04.21.2016 /////////// +// if( simul_dec != MUDA ){ + copy_frame_motion_field2(prev_frame_motion_field1, prev_frame_motion_field2, info); + clear_frame_motion_field_simp(prev_frame_motion_field1, info); +// } + /////////////////////////////////////////////////////////// + } + else if (dec_scene_change[i][j + 1] == NO) { + + /////////////// Added by Yuan Liu on 04.21.2016 /////////// +// if( GOP_counter != (get_GOP_num(info) - 1) ){ + copy_frame_motion_field2(prev_frame_motion_field1, prev_frame_motion_field2, info); + clear_frame_motion_field_simp(prev_frame_motion_field1, info); +// } + /////////////////////////////////////////////////////////// + printf("\n\nRIGHT MC, i = %d, j = %d, eff_GOPsz = %d, count+1 = %d\n",i,j,eff_GOPsz[i], count+1); + + mvStat_setFrame(GOP_counter, i, j + 1); + cur_bytes = mv_decode(yfmv[count + 1], NULL, 1, + meandepth, info, dist, i, starting_pos, 1, count+1, GOP_counter ); + mvBytes += cur_bytes; starting_pos += cur_bytes; + if ( info.layer_mv[i] && !info.layer_exist[i] ) // enhancement layer is discarded + layer_structure_mv_trim(info, i, j+1, yfmv[count+1], count+1); +#ifdef DEBUG_BLOCK_MODE_MV_INFO + write_block_mode_motion_vector("decoderright", GOP_counter, count+1, 2, yfmv[count+1], info, i); +#endif + } + else{ //Added by Yuan Liu on 04.21.2016 + assert(dec_scene_change[i][j] == YES && dec_scene_change[i][j + 1] == YES); + printf("\n\nISOLATED FRAMES, i = %d, j = %d, eff_GOPsz = %d, count = %d, count+1 = %d\n",i,j,eff_GOPsz[i], count,count+1); + printf("\n\nISOLATED FRAMES, i = %d, j = %d, eff_GOPsz = %d, count+1 = %d, count = %d\n",i,j,eff_GOPsz[i], count+1,count); + clear_frame_motion_field_simp(prev_frame_motion_field1, info); + clear_frame_motion_field_simp(prev_frame_motion_field2, info); + } + } + count += 2; + } + }// j + ////////////////////// + if(i <= info.tPyrLev - 2 && theo_dec == NO){ + copy_frame_motion_field2(prev_frame_motion_field1, buffer_frame_motion_field1_dec[i], info); + copy_frame_motion_field2(prev_frame_motion_field2, buffer_frame_motion_field2_dec[i], info); + } + + ////////////////////// + dist /= 2; + }// i + + // free + if(GOP_counter == (get_GOP_num(info) - 1) ){ + for(i = 0;i < G_LEVEL; i++){ + free(buffer_frame_motion_field1_dec[i]); + free(buffer_frame_motion_field2_dec[i]); + free(save_buffer_frame_motion_field1_dec[i]); + free(save_buffer_frame_motion_field2_dec[i]); + } + } + + free(prev_frame_motion_field1); + free(prev_frame_motion_field2); + + free(prev_frame_motion_field_left1); + free(prev_frame_motion_field_left2); + +/* + printf("\n tmp lvl 0 - 2\n"); + for(i=0;i<=11;i++) + printf("bi_mode_num012[%d] = %d\n",i,bi_mode_num012[i]); + + printf("\n tmp lvl 3\n"); + for(i=0;i<=11;i++) + printf("bi_mode_num345[%d] = %d\n",i,bi_mode_num345[i]); + + printf("\n"); + for(i=0;i<27;i++) + printf("aff_cum_idx[%d] = %d\n",i,aff_cum_idx[i]); +*/ + return mvBytes; +} + + +/*****************************************************************************/ +/* child_mv_compare */ +/*****************************************************************************/ +void +child_mv_compare( vector_ptr fmv1, vector_ptr fmv2, videoinfo info ) +{ + if( fmv1->child ) { + child_mv_compare( fmv1->child0, fmv2->child0, info ); + child_mv_compare( fmv1->child1, fmv2->child1, info ); + child_mv_compare( fmv1->child2, fmv2->child2, info ); + child_mv_compare( fmv1->child3, fmv2->child3, info ); + } else { + if( fmv1->mvx != fmv2->mvx ) { + printf( "error x\n" ); + exit( 1 ); + } + if( fmv1->mvy != fmv2->mvy ) { + printf( "error y\n" ); + exit( 1 ); + } + } +} + + + +/****************************************************************************/ +/* write_number() */ +/****************************************************************************/ +void +write_number( ) +{ + + if( outbyte < 0 ) { + printf( "error in write_number() outbyte = %d\n", outbyte ); + exit( 1 ); + } + + if( outbyte <= 0x7fffffff ) { + write_number_core( outbyte, fpbit ); + //printf("in write_number() outbyte=%d\n", outbyte); + } else { + printf( "error in write_number() outbyte=%d\n", outbyte ); + exit( 1 ); + } + +} + + +/****************************************************************************/ +/* read_number() */ +/****************************************************************************/ +long int +read_number( int with ) +{ + + if( with ) { + inbyte = read_number_core( fpbit ); + } else + inbyte = 65535; + + //printf("inbyte = %d ..............(arcodemv.c)\n", inbyte); + return ( inbyte + 4 ); // 4 bytes for the value of inbytes +} + + +int +write_GOPheader( enum FLAG **scene_change, videoinfo info ) // 就是把场景是否改变写进码流,改变标记为1,未改变标记为零 +{ + int i, j, eff_GOPsz, GOPsz, count = 0; + enum FLAG Level_change; // flag:YES/NO,用来标记是否是最后一个不满的gop + + GOPsz = info.GOPsz; + + if ( info.eff_GOPsz < info.GOPsz ) { + Level_change = YES; + eff_GOPsz = info.eff_GOPsz; + } + else { + Level_change = NO; + eff_GOPsz = info.GOPsz; + } + + encode_init( info ); // 初始化一下编码 + + for( i = 0; i < info.tPyrLev; i++ ) { + for( j = 0; j <= GOPsz; j++ ) { + if ( j != 0 ) { // scene_change[i][0] is always YES! + + if( scene_change[i][j] == YES ) { + output_bit( 1 ); count++; + // printf("scene_change[%d][%d] = YES\n",i,j); +// printf("i = %d, j = %d, 1 ",i,j); + } else { + output_bit( 0 ); count++; + // printf("scene_change[%d][%d] = NO\n",i,j); +// printf("i = %d, j = %d, 0 ",i,j); + } + + } + else { + // printf("scene_change[%d][%d] = YES --> not transmitted\n",i,j); + } + } + GOPsz /= 2; + + if ( Level_change == YES ) + eff_GOPsz = (int) ceil ((double)info.eff_GOPsz / (pow ( (float)2, (int)i + 1))); + else + eff_GOPsz = GOPsz; + } +// printf("\n\n"); + + encode_end( 0, info ); + + return outbyte; +} + + +// 标记每一帧是否发生场景改变,返回这个gop标记这些场景改变花费的bit +int +read_GOPheader( enum FLAG **dec_scene_change, videoinfo info )// +{ + int i, j, bit, GOPsz, GOPheader_bytes, count = 0; + + GOPsz = info.GOPsz; + + decode_init( ); + + for( i = 0; i < info.tPyrLev; i++ ) { // 统计有多少帧 + for( j = 1; j <= GOPsz; j++ ) + count++; + GOPsz /= 2; + } + + GOPsz = info.GOPsz; + + GOPheader_bytes = ( count + 7 ) / 8; + inbyte = GOPheader_bytes; + + for( i = 0; i < info.tPyrLev; i++ ) { // 逐时域层 + for( j = 0; j <= GOPsz; j++ ) { // 逐gop帧 + if (j != 0) { // scene_change[i][0] is always YES! + input_bit( bit );// + if( bit == 1 ) { + dec_scene_change[i][j] = YES; + // printf("scene_change[%d][%d] = YES\n",i,j); + } else { + dec_scene_change[i][j] = NO; + // printf("scene_change[%d][%d] = NO\n",i,j); + } + } + else { + dec_scene_change[i][j] = YES; + // printf("scene_change[%d][%d] = YES --> not transmitted\n",i,j); + } + } + GOPsz /= 2; + } + + decode_end( ); + + return GOPheader_bytes; +} diff --git a/Interframe EZBC/TempSub/src/obmc_varblk.c b/Interframe EZBC/TempSub/src/obmc_varblk.c new file mode 100644 index 0000000..d5f9276 --- /dev/null +++ b/Interframe EZBC/TempSub/src/obmc_varblk.c @@ -0,0 +1,872 @@ +#include +#include +#include +#include +#include +#include "structN.h" +#include "basic.h" +#include "iostream" +#define EXTERN extern +#include "coderN.h" +#include "util_filtering.h" + + +// 获得每个块的mv信息 +void get_child_mv_info(vector_ptr fmv2, vector_ptr fmv3, + int cx, int cy, int xblk, int yblk, int hor, + int ver, int *vector_num, + ImageMEinfo *imagemeinfo, Varblkarrayinfo *imageblkarray, + int connect_info, + vector_ptr mv_ref2, vector_ptr mv_ref3, int t_level, videoinfo info) +{ + int i, j, h_len, v_len, continue_sign=0; + enum BiMode cur_bi_mode; + enum spatialMODE cur_iblock_spatial_mode; + + int aff_mrg, skip_sign; + + float left_mvx, left_mvy, right_mvx, right_mvy; + + float left_aff1_mvx,left_aff1_mvy,left_aff2_mvx,left_aff2_mvy,left_aff3_mvx,left_aff3_mvy; + float right_aff1_mvx,right_aff1_mvy,right_aff2_mvx,right_aff2_mvy,right_aff3_mvx,right_aff3_mvy; + +/* + if(fmv2 == NULL) + printf("left NULL!\n"); + if(fmv3 == NULL) + printf("right NULL!\n"); +*/ + + switch (connect_info) + { + case 0: + if (fmv2->child && fmv3->child) // 可继续划分 + { + get_child_mv_info(fmv2->child0, fmv3->child0, cx, cy, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(fmv2->child1, fmv3->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(fmv2->child2, fmv3->child2, cx, cy+yblk/2, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(fmv2->child3, fmv3->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + }else + continue_sign = 1; + break; + case 1: + if (fmv2->child && mv_ref3==NULL) + { + get_child_mv_info(fmv2->child0, NULL, cx, cy, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(fmv2->child1, NULL, cx+xblk/2, cy, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(fmv2->child2, NULL, cx, cy+yblk/2, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(fmv2->child3, NULL, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + }else + continue_sign = 1; + break; + case 2: + if (mv_ref2==NULL && fmv3->child) + { + get_child_mv_info(NULL, fmv3->child0, cx, cy, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(NULL, fmv3->child1, cx+xblk/2, cy, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(NULL, fmv3->child2, cx, cy+yblk/2, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + get_child_mv_info(NULL, fmv3->child3, cx+xblk/2, cy+yblk/2, xblk/2, yblk/2, hor, + ver, vector_num, imagemeinfo, imageblkarray, + connect_info, mv_ref2, mv_ref3, t_level, info); + }else + continue_sign = 1; + break; + } + +// printf("continue_sign = %d\n",continue_sign); + + if (continue_sign) // 不可继续划分了。根据前面的划分模式,记录mv信息 + { + if (cxbi_mode; + aff_mrg = fmv2->aff_mrg; + skip_sign = fmv2->skip_sign; + + cur_iblock_spatial_mode = INVALID_SPATIAL_MODE; + if (info.bi_mv[t_level]) // bi-directional motion vectors + { + switch (cur_bi_mode) + { + case BI_CONNECTED: + case BI_PREDICTED: + case PARALLEL: + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + break; + case BLOCK_MERGING: + if(fmv2->aff_mrg == YES){ + printf("bingo BI!\n"); + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + + printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); + printf("left_aff1_mvx = %f, left_aff1_mvy = %f\nleft_aff2_mvx = %f, left_aff2_mvy = %f\nleft_aff3_mvx = %f, left_aff3_mvy = %f\n", + left_aff1_mvx, left_aff1_mvy, left_aff2_mvx, left_aff2_mvy, left_aff3_mvx, left_aff3_mvy ); + printf("right_aff1_mvx = %f, right_aff1_mvy = %f\nright_aff2_mvx = %f, right_aff2_mvy = %f\nright_aff3_mvx = %f, right_aff3_mvy = %f\n\n", + right_aff1_mvx, right_aff1_mvy, right_aff2_mvx, right_aff2_mvy, right_aff3_mvx, right_aff3_mvy ); + }else{ + assert(fmv2->aff_mrg == NO); + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + } + break; + case LEFT_CONNECTED: + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = (float)HUGE_VAL; right_mvy = (float)HUGE_VAL; + break; + case RIGHT_CONNECTED: + left_mvx = (float)HUGE_VAL; left_mvy = (float)HUGE_VAL; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + break; + case DIRECTIONAL_IBLOCK: + left_mvx = left_mvy = right_mvx = right_mvy = (float)HUGE_VAL; + cur_iblock_spatial_mode = fmv2->iblock_spatial_mode; + assert(fmv2->iblock_spatial_mode == fmv3->iblock_spatial_mode ); + break; + ////////// Added by Yuan Liu ////////// + case LEFT_CONNECTED_AFF: + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = (float)HUGE_VAL;right_aff1_mvy = (float)HUGE_VAL; + right_aff2_mvx = (float)HUGE_VAL;right_aff2_mvy = (float)HUGE_VAL; + right_aff3_mvx = (float)HUGE_VAL;right_aff3_mvy = (float)HUGE_VAL; + break; + + case RIGHT_CONNECTED_AFF: + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + + left_aff1_mvx = (float)HUGE_VAL;left_aff1_mvy = (float)HUGE_VAL; + left_aff2_mvx = (float)HUGE_VAL;left_aff2_mvy = (float)HUGE_VAL; + left_aff3_mvx = (float)HUGE_VAL;left_aff3_mvy = (float)HUGE_VAL; + break; + + case BI_CONNECTED_AFF: + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + break; + ///////////////////////////////////////// + case UNDEFINED: + assert(0); + break; + default: + assert(0); + break; + } + } + + if ( !info.bi_mv[t_level] ) // bi-directional motion vectors + { + assert(0); // 不能进来 + switch (cur_bi_mode) + { + case BI_CONNECTED: + case BI_PREDICTED: + case PARALLEL: + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + break; + case BLOCK_MERGING: + if(fmv2->aff_mrg == YES){ + printf("bingo!\n"); + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + }else{ + assert(fmv2->aff_mrg == NO); + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + } + break; + case LEFT_CONNECTED: + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = (float)HUGE_VAL; right_mvy = (float)HUGE_VAL; + break; + case RIGHT_CONNECTED: // RIGHT_CONNECTED mode is prevented + assert(0); + break; + case DIRECTIONAL_IBLOCK: + left_mvx = left_mvy = right_mvx = right_mvy = (float)HUGE_VAL; + cur_iblock_spatial_mode = fmv2->iblock_spatial_mode; + assert(fmv2->iblock_spatial_mode == fmv3->iblock_spatial_mode ); + break; + + ////////// Added by Yuan Liu ////////// + case LEFT_CONNECTED_AFF: + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = (float)HUGE_VAL;right_aff1_mvy = (float)HUGE_VAL; + right_aff2_mvx = (float)HUGE_VAL;right_aff2_mvy = (float)HUGE_VAL; + right_aff3_mvx = (float)HUGE_VAL;right_aff3_mvy = (float)HUGE_VAL; + break; + + case RIGHT_CONNECTED_AFF: + assert(0); + break; + + case BI_CONNECTED_AFF: + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + break; + case UNDEFINED: + assert(0); + break; + default: + assert(0); + break; + } + } + break; + case 1: // left connected + cur_bi_mode = fmv2->bi_mode; + aff_mrg = fmv2->aff_mrg; + skip_sign = fmv2->skip_sign; + + cur_iblock_spatial_mode = INVALID_SPATIAL_MODE; + switch (cur_bi_mode) + { + case LEFT_CONNECTED: + case LEFT_PREDICTED: + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = (float)HUGE_VAL; right_mvy = (float)HUGE_VAL; + break; + case BLOCK_MERGING: + if(fmv2->aff_mrg == YES){ + printf("bingo LEFT!\n"); + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = (float)HUGE_VAL;right_aff1_mvy = (float)HUGE_VAL; + right_aff2_mvx = (float)HUGE_VAL;right_aff2_mvy = (float)HUGE_VAL; + right_aff3_mvx = (float)HUGE_VAL;right_aff3_mvy = (float)HUGE_VAL; + + printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); + printf("left_aff1_mvx = %f, left_aff1_mvy = %f\nleft_aff2_mvx = %f, left_aff2_mvy = %f\nleft_aff3_mvx = %f, left_aff3_mvy = %f\n", + left_aff1_mvx, left_aff1_mvy, left_aff2_mvx, left_aff2_mvy, left_aff3_mvx, left_aff3_mvy ); + printf("right_aff1_mvx = %f, right_aff1_mvy = %f\nright_aff2_mvx = %f, right_aff2_mvy = %f\nright_aff3_mvx = %f, right_aff3_mvy = %f\n\n", + right_aff1_mvx, right_aff1_mvy, right_aff2_mvx, right_aff2_mvy, right_aff3_mvx, right_aff3_mvy ); + }else{ + assert(fmv2->aff_mrg == NO); + left_mvx = fmv2->mvx; left_mvy = fmv2->mvy; + right_mvx = (float)HUGE_VAL; right_mvy = (float)HUGE_VAL; + +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); +// printf("left_mvx = %f, left_mvy = %f\n",left_mvx, left_mvy); +// printf("right_mvx = %f, right_mvy = %f\n\n",right_mvx, right_mvy); + } + break; + case DIRECTIONAL_IBLOCK: + left_mvx = left_mvy = right_mvx = right_mvy = (float)HUGE_VAL; + cur_iblock_spatial_mode = fmv2->iblock_spatial_mode; + break; + ////////// Added by Yuan Liu ////////// + case LEFT_CONNECTED_AFF: + left_aff1_mvx = fmv2->aff1_mvx;left_aff1_mvy = fmv2->aff1_mvy; + left_aff2_mvx = fmv2->aff2_mvx;left_aff2_mvy = fmv2->aff2_mvy; + left_aff3_mvx = fmv2->aff3_mvx;left_aff3_mvy = fmv2->aff3_mvy; + + right_aff1_mvx = (float)HUGE_VAL;right_aff1_mvy = (float)HUGE_VAL; + right_aff2_mvx = (float)HUGE_VAL;right_aff2_mvy = (float)HUGE_VAL; + right_aff3_mvx = (float)HUGE_VAL;right_aff3_mvy = (float)HUGE_VAL; + break; + ///////////////////////////////////////// + case UNDEFINED: + assert(0); + break; + default: + assert(0); + break; + } + break; + case 2: // right connected +// assert(0); + cur_bi_mode = fmv3->bi_mode; + aff_mrg = fmv3->aff_mrg; + skip_sign = fmv3->skip_sign; + + cur_iblock_spatial_mode = INVALID_SPATIAL_MODE; + switch (cur_bi_mode) + { + case LEFT_CONNECTED: + case LEFT_PREDICTED: + left_mvx = (float)HUGE_VAL; left_mvy = (float)HUGE_VAL; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + break; + case BLOCK_MERGING: + if(fmv3->aff_mrg == YES){ + printf("bingo RIGHT!\n"); + left_aff1_mvx = (float)HUGE_VAL;left_aff1_mvy = (float)HUGE_VAL; + left_aff2_mvx = (float)HUGE_VAL;left_aff2_mvy = (float)HUGE_VAL; + left_aff3_mvx = (float)HUGE_VAL;left_aff3_mvy = (float)HUGE_VAL; + + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + + printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); + printf("left_aff1_mvx = %f, left_aff1_mvy = %f\nleft_aff2_mvx = %f, left_aff2_mvy = %f\nleft_aff3_mvx = %f, left_aff3_mvy = %f\n", + left_aff1_mvx, left_aff1_mvy, left_aff2_mvx, left_aff2_mvy, left_aff3_mvx, left_aff3_mvy ); + printf("right_aff1_mvx = %f, right_aff1_mvy = %f\nright_aff2_mvx = %f, right_aff2_mvy = %f\nright_aff3_mvx = %f, right_aff3_mvy = %f\n\n", + right_aff1_mvx, right_aff1_mvy, right_aff2_mvx, right_aff2_mvy, right_aff3_mvx, right_aff3_mvy ); + }else{ + assert(fmv3->aff_mrg == NO); + left_mvx = (float)HUGE_VAL; left_mvy = (float)HUGE_VAL; + right_mvx = fmv3->mvx; right_mvy = fmv3->mvy; + +// printf("cx = %d, cy = %d, xblk = %d, yblk = %d\n",cx,cy,xblk,yblk); +// printf("left_mvx = %f, left_mvy = %f\n",left_mvx, left_mvy); +// printf("right_mvx = %f, right_mvy = %f\n\n",right_mvx, right_mvy); + } + break; + case DIRECTIONAL_IBLOCK: + left_mvx = left_mvy = right_mvx = right_mvy = (float)HUGE_VAL; + cur_iblock_spatial_mode = fmv3->iblock_spatial_mode; + break; + ////////// Added by Yuan Liu ////////// + case LEFT_CONNECTED_AFF: + right_aff1_mvx = fmv3->aff1_mvx;right_aff1_mvy = fmv3->aff1_mvy; + right_aff2_mvx = fmv3->aff2_mvx;right_aff2_mvy = fmv3->aff2_mvy; + right_aff3_mvx = fmv3->aff3_mvx;right_aff3_mvy = fmv3->aff3_mvy; + + left_aff1_mvx = (float)HUGE_VAL;left_aff1_mvy = (float)HUGE_VAL; + left_aff2_mvx = (float)HUGE_VAL;left_aff2_mvy = (float)HUGE_VAL; + left_aff3_mvx = (float)HUGE_VAL;left_aff3_mvy = (float)HUGE_VAL; + break; + ///////////////////////////////////////// + case UNDEFINED: + assert(0); + break; + default: + assert(0); + break; + } + break; + } + + // /****************查看是否还有connect模式******************/ + //if(fmv2 != NULL) + // printf("%d ", fmv2->lifting_mode); + //if(fmv3 != NULL) + // printf("%d ", fmv3->lifting_mode); + ///**********************************/ + + for (i=0; i=9 && cur_bi_mode<=11) || (cur_bi_mode == 7 && aff_mrg == YES) ){ + imagemeinfo[(cy+j)*hor+(cx+i)].left_mvx = (left_aff2_mvx - left_aff1_mvx)*i/h_len + (left_aff3_mvx - left_aff1_mvx)*j/v_len + left_aff1_mvx; + imagemeinfo[(cy+j)*hor+(cx+i)].left_mvy = (left_aff2_mvy - left_aff1_mvy)*i/h_len + (left_aff3_mvy - left_aff1_mvy)*j/v_len + left_aff1_mvy; + imagemeinfo[(cy+j)*hor+(cx+i)].right_mvx = (right_aff2_mvx - right_aff1_mvx)*i/h_len + (right_aff3_mvx - right_aff1_mvx)*j/v_len + right_aff1_mvx; + imagemeinfo[(cy+j)*hor+(cx+i)].right_mvy = (right_aff2_mvy - right_aff1_mvy)*i/h_len + (right_aff3_mvy - right_aff1_mvy)*j/v_len + right_aff1_mvy; + + if( left_aff1_mvx == (float)HUGE_VAL || left_aff1_mvy == (float)HUGE_VAL || + left_aff2_mvx == (float)HUGE_VAL || left_aff2_mvy == (float)HUGE_VAL || + left_aff3_mvx == (float)HUGE_VAL || left_aff3_mvy == (float)HUGE_VAL){ + imagemeinfo[(cy+j)*hor+(cx+i)].left_mvx = (float)HUGE_VAL; + imagemeinfo[(cy+j)*hor+(cx+i)].left_mvy = (float)HUGE_VAL; + } + if( right_aff1_mvx == (float)HUGE_VAL || right_aff1_mvy == (float)HUGE_VAL || + right_aff2_mvx == (float)HUGE_VAL || right_aff2_mvy == (float)HUGE_VAL || + right_aff3_mvx == (float)HUGE_VAL || right_aff3_mvy == (float)HUGE_VAL){ + imagemeinfo[(cy+j)*hor+(cx+i)].right_mvx = (float)HUGE_VAL; + imagemeinfo[(cy+j)*hor+(cx+i)].right_mvy = (float)HUGE_VAL; + } + } + + if( (cur_bi_mode == 7 && aff_mrg == YES) || cur_bi_mode >= 9) + imagemeinfo[(cy+j)*hor+(cx+i)].mk_sign = 1; + else + imagemeinfo[(cy+j)*hor+(cx+i)].mk_sign = 0; + + if( ( (cur_bi_mode == 7 && aff_mrg == YES) || cur_bi_mode >= 0) && (i == 0 || i == h_len-1 || j == 0 || j == v_len-1) ) + imagemeinfo[(cy+j)*hor+(cx+i)].mrg_blk_bdr = 1; + else + imagemeinfo[(cy+j)*hor+(cx+i)].mrg_blk_bdr = 0; + + + if( (fmv2 != NULL && fmv2->two_comp_src == 1) || (fmv3 != NULL && fmv3->two_comp_src == 1) ) + imagemeinfo[(cy+j)*hor+(cx+i)].two_comp_src = 1; + else + imagemeinfo[(cy+j)*hor+(cx+i)].two_comp_src = 0; + + if( ( (fmv2 != NULL && fmv2->two_comp_src == 1) || (fmv3 != NULL && fmv3->two_comp_src == 1) ) && (i == 0 || i == h_len-1 || j == 0 || j == v_len-1) ) + imagemeinfo[(cy+j)*hor+(cx+i)].two_comp_bdr = 1; + else + imagemeinfo[(cy+j)*hor+(cx+i)].two_comp_bdr = 0; + + } + + // side information for each block + imageblkarray[*vector_num].leftx = cx; + imageblkarray[*vector_num].topy = cy; + imageblkarray[*vector_num].blksize = xblk; // here we should use xblk + (*vector_num)++; // the number of blocks + } + } +} + + + +// get the block motion/mode information for each pixel and block 为每个像素和块获取块的运动/模式信息 +void get_mv_side_information(videoinfo info, vector_ptr fmv2, vector_ptr fmv3, + vector_ptr mv_ref2, vector_ptr mv_ref3, + ImageMEinfo *imagemeinfo, Varblkarrayinfo *imageblkarray, + int *total_blk, int t_level, int j, + enum FLAG left_scene, enum FLAG right_scene, int encoder_sign) +{ + int X, x, Y, y; + int vector_num, xnum, ynum, xblk, yblk; + int hor, ver, pos; + int connect_info; + int s_level; + FILE *pc; + +// printf("left_scene = %d, right_scene = %d\n",left_scene,right_scene); + +// pc = fopen("enc_block.txt","at"); + + *total_blk = 0; + if (encoder_sign) //in encoder use "left_scene" and "right_scene" for connection checking + { + if (left_scene == NO && right_scene == NO ) // 两侧场景都没有改变,则双向连接 + connect_info = 0; // bi-connected 双向连接 + if (left_scene == NO && right_scene == YES) + connect_info = 1; // left connected + if (left_scene == YES && right_scene == NO ) + connect_info = 2; // right connected + if (left_scene == YES && right_scene == YES) + { + printf("total_block = %d\n", 0); +// fprintf(pc,"%d\n",0); + return; // intra frame + } + } + else // in decoder use "mv_ref2" and "mv_ref3" for connection checking + { + if (mv_ref2 != NULL && mv_ref3 != NULL ) + connect_info = 0; // bi-connected + if (mv_ref2 != NULL && mv_ref3 == NULL ) + connect_info = 1; // left connected + if (mv_ref2 == NULL && mv_ref3 != NULL ) + connect_info = 2; // right connected + if (mv_ref2 == NULL && mv_ref3 == NULL ) + { + printf("total_block = %d\n", 0); +// fprintf(pc,"%d\n",0); + return; // intra frame + } + } + + // the spatial resolution reduction in decoder + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES));// 目前info.s_level = 0 + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + hor = info.ywidth << s_level; + ver = info.yheight << s_level; + vector_num = 0; + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) { // 块为单位进行 + pos = Y * xnum + X; + if (encoder_sign) + get_child_mv_info( ( left_scene == NO ) ? (&fmv2[pos]):NULL, + ( right_scene == NO ) ? (&fmv3[pos]):NULL, + x, y, xblk, yblk, hor, + ver, &vector_num, + imagemeinfo, imageblkarray, connect_info, + ( left_scene == NO ) ? mv_ref2 : NULL, + ( right_scene == NO ) ? mv_ref3 : NULL, + t_level, info); + else + get_child_mv_info( mv_ref2 ? (&fmv2[pos]):NULL, + mv_ref3 ? (&fmv3[pos]):NULL, + x, y, xblk, yblk, hor, + ver, &vector_num, + imagemeinfo, imageblkarray, connect_info, + mv_ref2, mv_ref3, t_level, info); + } + } + + *total_blk = vector_num; + printf("total_block = %d\n", *total_blk); // 返回的是这一帧的信息 + if(encoder_sign == YES && t_level == 0){ + gop_block += *total_blk; + frame_cnt ++; + } +// fprintf(pc,"%d\n",*total_blk); + +// fclose(pc); +} + +// 复制预定义的权重矩阵 +void copy_weight_matrix(int blksize_cur, enum BiMode cur_bi_mode, + float **self_weight_matrix, float **ver_weight_matrix, float **hor_weight_matrix) +{ + int i, j; + + switch (blksize_cur) { + case 4: + if (cur_bi_mode != DIRECTIONAL_IBLOCK) + { + for (i=0; i 0) && pixelmeinfo[pos].bi_mode!=DIRECTIONAL_IBLOCK ) + { + // the block size for top neighbor is equal to current neighbor's + if (blksize_cur == pixelmeinfo[pos].blksize) + top_weight = 1.0; + // the neighbor block size is smaller + if (blksize_cur > pixelmeinfo[pos].blksize) + { + // the effective range for the top neighbor + neighbor_effect = pixelmeinfo[pos].blksize / 2; + if (i pixelmeinfo[pos].blksize) + { + neighbor_effect = pixelmeinfo[pos].blksize/2; + if (yblk-(i+1) 0) && pixelmeinfo[pos].bi_mode!=DIRECTIONAL_IBLOCK ) + { + if (blksize_cur == pixelmeinfo[pos].blksize) + left_weight = 1.0; + if (blksize_cur > pixelmeinfo[pos].blksize) + { + neighbor_effect = pixelmeinfo[pos].blksize/2; + if (j pixelmeinfo[pos].blksize) + { + neighbor_effect = pixelmeinfo[pos].blksize/2; + if (xblk-(j+1)> 1)) { + // top neighbor is effective, and also affected by shrinking scheme + pixelmeinfo[row*yhor+col].v_weight = ver_weight_matrix[i][j]*top_weight; + // modify self weight (raise self_weight to compensate the top_weight in vertical direction) + pixelmeinfo[row*yhor+col].self_weight += ver_weight_matrix[i][j]*(1-top_weight); + }else if (i >= (yblk >> 1)) { + // bottom neighbor is effective, whose weights are symmetric to top neighbor's + pixelmeinfo[row*yhor+col].v_weight = ver_weight_matrix[yblk - i - 1][j]*bottom_weight; + pixelmeinfo[row*yhor+col].self_weight += ver_weight_matrix[yblk - i - 1][j]*(1-bottom_weight); + } + if( (j < (xblk >> 1)) ) { // left neighbor + pixelmeinfo[row*yhor+col].h_weight = hor_weight_matrix[i][j]*left_weight; + pixelmeinfo[row*yhor+col].self_weight += hor_weight_matrix[i][j]*(1-left_weight); + }else if( (j >= (xblk >> 1)) ) { // right + pixelmeinfo[row*yhor+col].h_weight = hor_weight_matrix[i][xblk - j - 1]*right_weight; + pixelmeinfo[row*yhor+col].self_weight += hor_weight_matrix[i][xblk - j - 1]*(1-right_weight); + } + + pixelmeinfo[row*yhor+col].self_weight /= (float)xblk; // normalize + pixelmeinfo[row*yhor+col].h_weight /= (float)xblk; // normalize + pixelmeinfo[row*yhor+col].v_weight /= (float)xblk; // normalize + assert(fabs(pixelmeinfo[row*yhor+col].self_weight+pixelmeinfo[row*yhor+col].h_weight + +pixelmeinfo[row*yhor+col].v_weight-1.0)< pow((float)10, int(-5) ) ); + col++; + } + row++; + } + + for (i=0; i +#include +#include +#include +#include +#include "structN.h" +#include "memoryN.h" + +extern long int totalY[5], totalU[5], totalV[5], totalmap[5], totalMV[5]; /*initiated in initN.c */ +extern float avgpsnr[3][16], avgvar[3][16]; +extern long int *unconnectedL; + +void read_frame( YUVimage_ptr frame, videoinfo info, char *inname, int index, + enum FORMAT format ); + +/****************************************************************************/ +/* snr_frame() */ +/****************************************************************************/ +void +snr_frame( float *ysnr, float *usnr, float *vsnr, YUVimage_ptr codeframe, + YUVimage_ptr inframe, videoinfo info ) +{ + int i, ypix, cpix; + double sum, diff, peak; + + ypix = (info.ywidth * info.yheight); // >> (2 * info.s_level); + cpix = (info.cwidth * info.cheight); // >> (2 * info.s_level); + + switch ( info.format ) { + case YUV: + case RAS: + peak = 255.; + break; + case DPX: + peak = 1023.; + break; + default: + printf( "image format error format = %d(pstatN.c)\n", info.format ); + exit( 1 ); + } + + sum = 0.; + for( i = 0; i < ypix; i++ ) { + diff = inframe->Y[i] - codeframe->Y[i]; + sum += diff * diff; + } + *ysnr = + ( ypix ) ? ( float )( 20. * log10( peak / sqrt( sum / ypix ) ) ) : 0; + + sum = 0.; + for( i = 0; i < cpix; i++ ) { + diff = inframe->U[i] - codeframe->U[i]; + sum += diff * diff; + } + *usnr = + ( cpix ) ? ( float )( 20. * log10( peak / sqrt( sum / cpix ) ) ) : 0; + + sum = 0.; + for( i = 0; i < cpix; i++ ) { + diff = inframe->V[i] - codeframe->V[i]; + sum += diff * diff; + } + *vsnr = + ( cpix ) ? ( float )( 20. * log10( peak / sqrt( sum / cpix ) ) ) : 0; +} + + +/****************************************************************************/ +/* snr_crop() */ +/****************************************************************************/ +void +snr_crop( float *ysnr, float *usnr, float *vsnr, YUVimage_ptr codeframe, + YUVimage_ptr inframe, videoinfo info ) +{ + int i, j, start_x, start_y, width, height, pos, ypix, cpix; + double sum, diff, peak; + + start_x = 65; + start_y = 0; + width = 59; + height = 240; + ypix = width * height; + cpix = ypix / 2; + + switch ( info.format ) { + case YUV: + case RAS: + peak = 255.; + break; + case DPX: + peak = 1023.; + break; + default: + printf( "image format error format = %d(pstatN.c)\n", info.format ); + exit( 1 ); + } + + sum = 0.; + for( i = 0; i < height; i++ ) { + for( j = 0; j < width; j++ ) { + pos = i * info.ywidth + start_x + j; + diff = inframe->Y[pos] - codeframe->Y[pos]; + sum += diff * diff; + } + } + + *ysnr = ( float )( 20. * log10( peak / sqrt( sum / ypix ) ) ); + //*ysnr = sum; + + sum = 0.; + for( i = 0; i < height / 2; i++ ) { + for( j = 0; j < width / 2; j++ ) { + pos = i * info.cwidth + start_x / 2 + j; + diff = inframe->U[pos] - codeframe->U[pos]; + sum += diff * diff; + } + } + *usnr = ( float )( 20. * log10( peak / sqrt( sum / cpix ) ) ); + //*usnr = sum; + + sum = 0.; + for( i = 0; i < height / 2; i++ ) { + for( j = 0; j < width / 2; j++ ) { + pos = i * info.cwidth + start_x / 2 + j; + diff = inframe->V[pos] - codeframe->V[pos]; + sum += diff * diff; + } + } + *vsnr = ( float )( 20. * log10( peak / sqrt( sum / cpix ) ) ); + //*vsnr = sum; +} + + + +/****************************************************************************/ +/* calsnr() */ +/****************************************************************************/ +float +calsnr( int start, int last, videoinfo info ) +{ + int i, num; // j + float ysnr, usnr, vsnr, mean1, mean2, mean3; + YUVimage fr0, fr1; + FILE *fpstat; + + + //TR info.coding_domain = LOG; // calculate PSNR in LOG domain + + frame_alloc( &fr0, info ); + frame_alloc( &fr1, info ); + fpstat = fopen( info.statname, "at+" ); + fprintf( fpstat, "\n \n" ); + fprintf( fpstat, " ysnr usnr vsnr\n" ); + printf( "\n" ); + printf( " calculate PSNR frame %d ~ frame %d\n", start, last ); + + num = 0; + mean1 = 0.; + mean2 = 0.; + mean3 = 0.; + for( i = start; i <= last; i = i + (1 << info.t_level) ) { + +/* + if ((strchr (info.decname, '%'))==0){ //check for frame or video mode + read_frame(&fr0, info, info.decname, (i - start) >> info.t_level, info.format); + }else +*/ + read_frame(&fr0, info, info.decname, i, info.format); /* coded frame */ + + read_frame( &fr1, info, info.inname, i, info.format ); /* original frame */ + + snr_frame( &ysnr, &usnr, &vsnr, &fr0, &fr1, info ); + mean1 += ysnr; + mean2 += usnr; + mean3 += vsnr; + num++; + fprintf( fpstat, "%.2f\t %.2f\t %.2f\n", ysnr, usnr, vsnr ); + printf( " frame %3d: %.2f\t %.2f\t %.2f\n", i, ysnr, usnr, vsnr ); + } + + fprintf( fpstat, "==================================================\n" ); + printf( "==================================================\n" ); + // num = last - start + 1; + fprintf( fpstat, "%6s(%03d) ysnr = %.2f usnr = %.2f vsnr = %.2f\n", "avg", + num, mean1 / num, mean2 / num, mean3 / num ); + printf( " avg (%03d) ysnr = %.2f usnr = %.2f vsnr = %.2f\n\n", + num, mean1 / num, mean2 / num, mean3 / num ); + fclose( fpstat ); + + free_frame( fr0 ); + free_frame( fr1 ); + + mean1 = mean1 / num; + + return mean1; +} + + + +/* + * calsnr_seq() + * calculate psnr of the whole sequence + */ +void +calsnr_seq( YUVimage_ptr fr0, YUVimage_ptr fr1, int start, int last, + videoinfo info ) +{ + int i, num; + float ysnr, usnr, vsnr, mean1, mean2, mean3; + FILE *fpstat; + + mean1 = 0.; + mean2 = 0.; + mean3 = 0.; + fpstat = fopen( info.statname, "at+" ); /* this is the difference from calsnr */ + fprintf( fpstat, "\n \n" ); + fprintf( fpstat, " ysnr usnr vsnr\n" ); + printf( "start %d last %d\n", start, last ); + + for( i = start; i <= last; i++ ) { + read_frame( fr1, info, info.inname, i, info.format ); /* original frame */ + read_frame( fr0, info, info.decname, i, info.format ); /* coded frame */ + snr_frame( &ysnr, &usnr, &vsnr, fr0, fr1, info ); + mean1 += ysnr; + mean2 += usnr; + mean3 += vsnr; + + fprintf( fpstat, "%.2f\t %.2f\t %.2f\n", ysnr, usnr, vsnr ); + } + + fprintf( fpstat, "=================================================\n" ); + + num = last - start + 1; + + fprintf( fpstat, "%6s(%03d) ysnr = %.2f usnr = %.2f vsnr = %.2f\n", "avg", + num, mean1 / num, mean2 / num, mean3 / num ); + fclose( fpstat ); + +} + +/* + * calsnr_frame() + * calculate psnr of a frame + */ + +void +calsnr_frame( YUVimage_ptr fr0, YUVimage_ptr fr1, int curr, videoinfo info ) +{ + int num; + float ysnr, usnr, vsnr; + static float mean1 = 0., mean2 = 0., mean3 = 0.; + FILE *fpstat; + + //mean1=0.; mean2=0.; mean3=0.; + fpstat = fopen( info.statname, "at+" ); /* this is the difference from calsnr */ + if( curr == info.start ) { + fprintf( fpstat, "\n \n" ); + fprintf( fpstat, " ysnr usnr vsnr\n" ); + } + + snr_frame( &ysnr, &usnr, &vsnr, fr0, fr1, info ); + + mean1 += ysnr; + mean2 += usnr; + mean3 += vsnr; + + fprintf( fpstat, "%.2f\t %.2f\t %.2f\n", ysnr, usnr, vsnr ); + + if( curr == info.last ) { + fprintf( fpstat, "=================================================\n" ); + num = info.last - info.start + 1; + fprintf( fpstat, "%6s(%03d) ysnr = %.2f usnr = %.2f vsnr = %.2f\n", "avg", + num, mean1 / num, mean2 / num, mean3 / num ); + } + fclose( fpstat ); +} + + +void +print_mvbits( videoinfo info, Rate FrsRate ) +{ + int i, j, nlev, nfrs, count, itmp, sum; + FILE *fp_mv; + + if( !( fp_mv = fopen( info.mvstatname, "at+" ) ) ) { + printf( "can not open %s\n", info.mvstatname ); + exit( 1 ); + } + + nlev = info.tPyrLev; + + nfrs = 2; + count = 1; + sum = 0; + itmp = 0; + for( i = nlev - 1; i >= 0; i-- ) { + for( j = 0; j <= nfrs; count++, j++ ) + { +// itmp = (FrsRate.map[count] + FrsRate.mv[count]); + sum += itmp; + printf ("Fr%.2d: mvbits sum = %5d\n", count, itmp); + fprintf (fp_mv, "%d\n", itmp >> 3); + } + nfrs *= 2; + } + fclose( fp_mv ); + printf( "---> %.2d MV sets -- total sum = %7d\n\n", count, sum); +} diff --git a/Interframe EZBC/TempSub/src/pull.c b/Interframe EZBC/TempSub/src/pull.c new file mode 100644 index 0000000..6fdecdd --- /dev/null +++ b/Interframe EZBC/TempSub/src/pull.c @@ -0,0 +1,2079 @@ +/* + This file pulls out bit stream from the pre-encoded bit stream + +*/ +#include +#include +#include +#include +#include +#include "iostream" +#define EXTERN +#include "structN.h" +#include "coderN.h" +#include "miscN.h" +#include "ioN.h" +#include "pstatN.h" +#include "basic.h" +#include "dpx.h" +#include "zlib.h" // zip-Library +#include "general.h" + +#define INVALID_AGP_EXIST 10 +#define INVALID_LAYER_EXIST 10 +#define INVALID_BI_MV -1 +#define MV_PERCENT_THERSH 0.55 // the threshold for motion vector percentage + // above the threshold we discard some sub-symbols + +int read_number_core( FILE * fp ); + +unsigned int read_number_sub( FILE * fp ); + +void write_number_sub(unsigned int outputbyte, FILE * fp ); + +int GOP_motion_bytes; + + +void write_number_core( int outputbyte, FILE * fp ); +int read_GOPheader( enum FLAG **dec_scene_change, videoinfo info ); +int read_substream_length( int *length, FILE * fp ); +int write_substream_length( int length, FILE * fp ); +int bit_alloc_VBR( videoinfo info, unsigned char *qp, + long int sum_mv, long int overhead ); +int bit_alloc_CBR( videoinfo info, unsigned char *qp, + long int overhead, unsigned long *gop_sum_mv, int curr_last ); + +int bit_alloc_VBR_v2( videoinfo info, unsigned char *qp, long int overhead, + unsigned long *gop_sum_mv, int curr_last, int vbr_bound ); + +int simulcast_pull( char *pre_stream, char *bit_alloc_name, + int t_level, int s_level, int kbps, + int qp ); + +void +pull_usage( ) +{ + printf( "pull pre_encoded_stream -t t_level -s s_level -r kbps [-C]\n" ); +} + +void +read_command( int argc, char **argv, short int *t_level, short int *s_level, + int *kbps, int *AGP_exist, int *layer_exist, int *bi_exist, + char *pre_stream, enum FLAG *CBR, enum FLAG *list, enum FLAG *VBR_ADAPT, + char *list_name) +{ + int i, j, k, argnum = 1; + + *CBR = NO; + *VBR_ADAPT = NO; + *list = NO; + *t_level = 0; + *s_level = 0; + list_name[0] = '\0'; + // how many sub-symbols exist + for (j = 0; j < MAX_TLEVELS; j++) + { + AGP_exist[j] = INVALID_AGP_EXIST; + layer_exist[j] = INVALID_LAYER_EXIST; + bi_exist[j] = INVALID_BI_MV; + } + + for( i = 1; i < argc; i++ ) { + if( *( argv[i] ) == '-' ) { + + switch ( *( ++argv[i] ) ) { + default: + printf( "-%c such an option is not available\n", *( argv[i] ) ); + pull_usage( ); + exit( 1 ); + case 'h': + pull_usage( ); + exit( 1 ); + break; + + case 'y': // the parameter for layer structure + j = 0; + while (j < MAX_TLEVELS ) { + layer_exist[j] = atoi( argv[++i] ); + j++; + if ( i==argc-1 ) // no more parameters + break; + if ( *( argv[i+1] ) == '-' ) // next parameter + break; + } + if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of layer_exist values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + layer_exist[k] = layer_exist[k-1]; + } + break; + + case 'a': // the parameter for AGP + j = 0; + while (j < MAX_TLEVELS ) { + AGP_exist[j] = atoi( argv[++i] ); + j++; + if ( i==argc-1 ) // no more parameters + break; + if ( *( argv[i+1] ) == '-' ) // next parameter + break; + } + if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of AGP_exist values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + AGP_exist[k] = AGP_exist[k-1]; + } + break; + case 'b': // the parameter for bi-directional motion field + j = 0; + while (j < MAX_TLEVELS ) { + bi_exist[j] = atoi( argv[++i] ); + j++; + if ( i==argc-1 ) // no more parameters + break; + if ( *( argv[i+1] ) == '-' ) // next parameter + break; + } + if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of bi_mv values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + bi_exist[k] = bi_exist[k-1]; + } + break; + + case 't': + *t_level = atoi( argv[++i] ); + break; + case 's': + *s_level = atoi( argv[++i] ); + break; + case 'r': + *kbps = atoi( argv[++i] ); + break; + case 'C': + *CBR = YES; + break; + case 'l': // name of list file for static output rates + strcpy( list_name, argv[++i] ); + break; + case 'n': // flag for display target rate list + *list = YES; + break; + case 'V': + *VBR_ADAPT = YES; + break; + } + } else { + switch ( argnum ) { + default: + printf( "more parameters are specified\n" ); + pull_usage( ); + exit( 1 ); + case 1: + strcpy( pre_stream, argv[i] ); + argnum++; + break; + } + } + } + +} + + +int +read_listfile( char *list_name, unsigned short int *list_rates, unsigned char *list_tlevel, + unsigned char *list_slevel, unsigned char *list_simulcast, + char **list_simulname, videoinfo info ) +{ + int i, counter = 0, rate = 0, tlevel = 0, slevel = 0, simulcast = 0; + char iline[256], token[80]; + FILE *fplist; + + if( !( fplist = fopen( list_name, "rb" ) ) ) { + printf( "can not open: %s\n", list_name ); + exit( 1 ); + } + + while( fgets( iline, 254, fplist ) ){ + sscanf( iline, "%s", token ); + + if( !strcmp( token, "-listitem" ) ) { + sscanf( iline, "%s%d%d%d%d%s", token, &tlevel, &slevel, + &rate, &simulcast, list_simulname[counter] ); + list_tlevel[counter] = tlevel; + list_slevel[counter] = slevel; + list_rates[counter] = rate; + list_simulcast[counter] = simulcast; + counter++; + } + } + if ( counter == 0 ){ + printf( "no listitems in: %s\n", list_name ); + exit( 1 ); + } + + for ( i = 1; i < counter; i++ ){ + if ( list_tlevel[i] < info.t_level ){ + printf( "target t_level too low in: %s\n", list_name ); + exit( 1 ); + } + if ( list_slevel[i] < info.s_level ){ + printf( "target s_level too low in: %s\n", list_name ); + exit( 1 ); + } + if ( list_rates[i] >= info.bitrate ){ + printf( "target rate too high in: %s\n", list_name ); + exit( 1 ); + } + } + + fclose( fplist ); + + return counter; +} + + +// 在后缀为.mvby的文件中读取mv的每一帧bit数 +unsigned long int +read_mv_bytes( char *seq_name, videoinfo info, int AGP_sign, int layer_sign, + unsigned long int *exist_sum_mv ) +{ + int j, k, remaining_frs, curr, last; + int mv, mv1, mv2, GOPsz, eff_GOPsz[20]; + unsigned long int sum_mv; + char mvstatname[250]; + FILE *FID; + int major_mv, sign_bytes, sub_bit, sub_mv, total_mv ; + + GOPsz = info.GOPsz; + + // determine effective GOP size in level j 决定有效的gop的大小 + for( j = 0; j < info.tPyrLev; j++ ) { + eff_GOPsz[j] = GOPsz; + GOPsz /= 2; + } + + curr = info.start; + last = info.last; + // *exist_sum_mv: the number of existing motion vector bytes up to this temporal level + sum_mv = *exist_sum_mv = 0; + sprintf( mvstatname, "%s.mvby", seq_name ); // Hanke, 16.09.02 + FID = fopen( mvstatname, "rb" ); + if( FID == NULL ) { + printf( "can not open file mvby\n" ); + exit( 1 ); + } + + while( curr <= last ) { // 处理完所有帧 + remaining_frs = last - curr + 1; + + for( j = info.tPyrLev - 1; j >= 0; j-- ) { // 处理一个gop + if ( info.bi_exist[j] ) // bi-directional motion field 双向运动场 + { + for( k = 0; k <= eff_GOPsz[j]; k++ ) { + // scalable motion vector coding +// printf("eff_GOPsz[j] = %d\n",eff_GOPsz[j]); + if ( !AGP_sign && !layer_sign) // no AGP, no layer structure + { + fscanf( FID, "%d\n", &mv ); + if( j >= info.t_level ) + { + sum_mv += mv; + *exist_sum_mv += mv; // here *exist_sum_mv is the same as sum_mv + } + } + + if ( AGP_sign && !layer_sign ) // AGP, no layer structure + { + fscanf( FID, "%d ", &major_mv ); + if (major_mv==0) continue; // no motion vector, i.e. scene change + if( j >= info.t_level ) sum_mv += major_mv; // major_mv is always necessary + if (info.AGP_level[j]) // AGP in this temporal level + { + fscanf( FID, "%d ", &sign_bytes); + if (info.AGP_exist[j] && j >= info.t_level ) sum_mv += sign_bytes; + for (sub_bit=0; sub_bit= info.t_level ) sum_mv += sub_mv; + } + fscanf( FID, "%d ", &total_mv); // total bytes for this set of motion vectors + if (j>=info.t_level) *exist_sum_mv += total_mv ; + }else + if (j>=info.t_level) *exist_sum_mv += major_mv ; + } + + if ( !AGP_sign && layer_sign ) // no AGP, layer structure + { + fscanf( FID, "%d ", &major_mv ); + if (major_mv==0) continue; // no motion vector, i.e. scene change + if( j >= info.t_level ) sum_mv += major_mv; // major_mv is always necessary + if (info.layer_mv[j]) // layer structure in this temporal level + { + fscanf( FID, "%d ", &sub_mv); + if (info.layer_exist[j] && j >= info.t_level ) sum_mv += sub_mv; + fscanf( FID, "%d ", &total_mv); // total bytes for this set of motion vectors + if (j>=info.t_level) *exist_sum_mv += total_mv ; + }else + if (j>=info.t_level) *exist_sum_mv += major_mv ; + } + + if ( AGP_sign && layer_sign ) // AGP, layer structure + { + fscanf( FID, "%d ", &major_mv ); + if (major_mv==0) continue; // no motion vector, i.e. scene change + if( j >= info.t_level ) sum_mv += major_mv; // major_mv is always necessary + if (info.AGP_level[j]) // AGP in this temporal level + { + fscanf( FID, "%d ", &sign_bytes); + if (info.AGP_exist[j] && j >= info.t_level ) sum_mv += sign_bytes; + for (sub_bit=0; sub_bit= info.t_level ) sum_mv += sub_mv; + } + } + + if ( info.layer_mv[j]) + { + fscanf( FID, "%d ", &sub_mv); + if ( info.layer_exist[j] && j >= info.t_level ) sum_mv += sub_mv; + if ( info.AGP_level[j]) + { + fscanf( FID, "%d ", &sign_bytes); + if (info.AGP_exist[j] && j >= info.t_level ) sum_mv += sign_bytes; + for (sub_bit=0; sub_bit= info.t_level ) sum_mv += sub_mv; + } + } + + } + + if ( info.layer_mv[j] || info.AGP_level[j] ) + { + fscanf( FID, "%d ", &total_mv); // total bytes for this set of motion vectors + if (j>=info.t_level) *exist_sum_mv += total_mv ; + }else + if (j>=info.t_level) *exist_sum_mv += major_mv ; + } + + } + } // if ( info.bi_exist[j] ) + + // alternative Haar reconstruction + if ( ! info.bi_exist[j] ) // not bi-directional motion field, alternative reconstruction with Harr + { + assert(0); + k=0; + while ( k <= eff_GOPsz[j] ) + { + if (AGP_sign==0) // without AGP ( non-scalable motion vectors ) + { + if (k==0) // the first set of motion vectors are always 0 + { + fscanf( FID, "%d\n", &mv ); + assert(mv==0); + k++; + }else + { + fscanf( FID, "%d\n", &mv1 ); // left set mv + k++; + fscanf( FID, "%d\n", &mv2 ); // right set mv + k++; + if( j >= info.t_level ) + { + // bi-directional motion vector or left set motion vector + if ( ( mv1 && mv2 ) || ( mv1 && !mv2) ) + { + sum_mv += mv1; // only left set is reserved finally + *exist_sum_mv += mv1+mv2; + } + + if (!mv1 && mv2) // right set motion vector + { + sum_mv += mv2; + *exist_sum_mv += mv1+mv2; + } + } + } + }else // with AGP + { + + } // with AGP + } + } // if ( ! info.bi_mv[j] ) + + } + + curr += info.GOPsz; + } + fclose( FID ); + + return sum_mv; +} + + +void +gop_read_mv_bytes( char *seq_name, videoinfo info, int AGP_sign, int layer_sign, + unsigned long int *gop_exist_sum_mv, int num_of_GOP, unsigned long int *gop_sum_mv ) +{ + int i, j, k, remaining_frs, curr, last; + int mv, mv1, mv2, GOPsz, eff_GOPsz[20]; + unsigned long int sum_mv; + char mvstatname[250]; + FILE *FID; + int major_mv, sign_bytes, sub_bit, sub_mv, total_mv ; + + GOPsz = info.GOPsz; + + // determine effective GOP size in level j + for( j = 0; j < info.tPyrLev; j++ ) { + eff_GOPsz[j] = GOPsz; + GOPsz /= 2; + } + + curr = info.start; + last = info.last; + + assert( (last - curr + 1) == num_of_GOP*info.GOPsz ); + + + + // *exist_sum_mv: the number of existing motion vector bytes up to this temporal level + sum_mv = *gop_exist_sum_mv = 0; + sprintf( mvstatname, "%s.mvby", seq_name ); // Hanke, 16.09.02 + FID = fopen( mvstatname, "rb" ); + if( FID == NULL ) { + printf( "can not open file mvby\n" ); + exit( 1 ); + } + + for(i = 0; i < num_of_GOP; i ++){ + gop_sum_mv[i] = 0; + } + + i = 0; + + while( curr <= last ) { + remaining_frs = last - curr + 1; + + for( j = info.tPyrLev - 1; j >= 0; j-- ) { + + if ( info.bi_exist[j] ) // bi-directional motion field + { + for( k = 0; k <= eff_GOPsz[j]; k++ ) { + + // scalable motion vector coding + + if ( !AGP_sign && !layer_sign) // no AGP, no layer structure + { + fscanf( FID, "%d\n", &mv ); + if( j >= info.t_level ) + { + sum_mv += mv; + gop_sum_mv[i] += mv; // here *exist_sum_mv is the same as sum_mv + } + } + + } + } // if ( info.bi_exist[j] ) + + } + + curr += info.GOPsz; + i ++; + } + fclose( FID ); + +} + +// automatically allocate the bits between motion vector and subband data +// according to some empirically bit-allcoation model +void automatic_bit_allocation_with_AGP(unsigned long int *sum_mv, videoinfo *info, + char *seq_name, int AGP_sign, int layer_sign) +{ + double budget; + double mv_percent; + videoinfo info_bak; + unsigned long int exist_sum_mv; + int i; + + budget = ( double )info->bitrate * 1000 / 8 * ( info->last - info->start + 1 ) / info->framerate; + mv_percent = *sum_mv/budget; // the percentage of motion vector bytes in the available budget + if (mv_percent<=MV_PERCENT_THERSH) + return; // tolerable percentage according empirical bit allocation model + else + { + // discard motion vector sub-symbols starting from the top temporal level + for (i=info->t_level; i<=info->tPyrLev-1; i++) + { + while (info->AGP_exist[i]>0 && mv_percent>MV_PERCENT_THERSH) + { + (info->AGP_exist[i])--; + info_bak = *info; + *sum_mv = read_mv_bytes( seq_name, info_bak, AGP_sign, layer_sign, &exist_sum_mv ); + mv_percent = *sum_mv/budget; + } + if (mv_percent<=MV_PERCENT_THERSH) + return; + } + for (i=info->t_level; i<=info->tPyrLev-1; i++) + assert( info->AGP_exist[i]==0 ); + } +} + +/* +unsigned long int +write_zip( char *bit_alloc_name, FILE *fphead, enum FLAG compress_flag ) +{ + int err; + unsigned long int input_size = 0, in_len, out_len = 1000000000; + unsigned char *input_data , *compressed; + FILE *fpbytes; + + // read input_file + if( !( fpbytes = fopen( bit_alloc_name, "rb" ) ) ) { + printf( "can not open %s\n", bit_alloc_name ); + exit( 1 ); + } + fseek( fpbytes, 0, SEEK_END ); + input_size = ftell( fpbytes ); + fseek( fpbytes, 0, SEEK_SET ); + + input_data = + ( unsigned char * )getarray( input_size, sizeof( unsigned char ), + "input_data" ); + if( fread( input_data, sizeof( unsigned char ), input_size, fpbytes ) != + ( unsigned ) input_size ) { + printf( "fread error \n" ); + exit( 1 ); + } + fclose ( fpbytes ); + + in_len = input_size * sizeof( unsigned char ); + + compressed = + ( unsigned char * )getarray( in_len, sizeof( unsigned char ), + "compressed" ); + + if( compress_flag == YES ){ + err = compress(compressed, &out_len, (Bytef*)input_data, in_len); + if (err) { + printf("error during zip compression.\n"); + exit(1); + } + assert ( out_len <= in_len ); + + // write zip to overhead stream + fwrite( compressed, sizeof( unsigned char ), out_len, fphead ); + } else { + // write uncompressed input_data to overhead stream + fwrite( input_data, sizeof( unsigned char ), in_len, fphead ); + } + + free( input_data ); + free( compressed ); + return ( compress_flag == YES ) ? out_len : in_len; +} +*/ +/* +void +extract_zip( char *bit_alloc_name, unsigned char *compressed, + unsigned long int in_len, enum FLAG decompress_flag ) +{ + int err; + unsigned long int out_len = 20000000; + unsigned char *decompressed; + FILE *fpbytes; + + decompressed = + ( unsigned char * )getarray( out_len, sizeof( unsigned char ), + "decompressed" ); + + if( decompress_flag == YES ){ + // extract zip archive + err = uncompress((Bytef*)decompressed, &out_len, compressed, in_len); + if (err) { + printf("error during zip uncompression.\n"); + exit(1); + } + } + + // write data to file + if( !( fpbytes = fopen( bit_alloc_name, "wb" ) ) ) { + printf( "can not open %s\n", bit_alloc_name ); + exit( 1 ); + } + + if( decompress_flag == YES ){ + fwrite( decompressed, sizeof( unsigned char ), out_len, fpbytes ); + } else { + fwrite( compressed, sizeof( unsigned char ), in_len, fpbytes ); + } + + fclose ( fpbytes ); + free ( decompressed ); +} +*/ + +// get one section of bits for AGP +void get_bytes_section(FILE *fpbit, FILE *outfp, FILE * fptab, int write_sign, long int *in_bytes, long int *out_bytes, + long int *total_mv_bytes, enum FLAG pulled_bitstream ) +{ + unsigned int section_Bytes; + unsigned char *data; + + section_Bytes = read_number_sub( fpbit ); // fpbit will move forward by 2 bytes + *in_bytes += 2; + if ( write_sign ) + { + write_number_sub( section_Bytes, outfp ); + *out_bytes += 2; + *total_mv_bytes +=2; + data = ( unsigned char * )getarray( section_Bytes, sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), section_Bytes, fpbit ) != ( unsigned )section_Bytes ) { + printf( "fread error2 %d\n", section_Bytes ); + exit( 1 ); + } + *in_bytes += section_Bytes; + fwrite( data, sizeof( unsigned char ), section_Bytes, outfp ); + *out_bytes += section_Bytes; + *total_mv_bytes += section_Bytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% motion_bytes\n", section_Bytes + 2 ); + GOP_motion_bytes += section_Bytes; + } + free( data ); + } else { + fseek( fpbit, section_Bytes, SEEK_CUR ); + in_bytes += section_Bytes; + } +} + +// get the section for enhancement layer +void get_bytes_section_enhance(FILE *fpbit, FILE *outfp, FILE * fptab, int write_sign, long int *in_bytes, long int *out_bytes, + long int *total_mv_bytes, enum FLAG pulled_bitstream ) +{ + unsigned int enhance_Bytes; + unsigned char *data; + + enhance_Bytes = read_number_core( fpbit ); // fpbit will move forward by 2 bytes + *in_bytes += 4; + if ( write_sign ) + { + write_number_core( enhance_Bytes, outfp ); + *out_bytes += 4; + *total_mv_bytes +=4; + data = ( unsigned char * )getarray( enhance_Bytes, sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), enhance_Bytes, fpbit ) != ( unsigned )enhance_Bytes ) { + printf( "fread error2 %d\n", enhance_Bytes ); + exit( 1 ); + } + *in_bytes += enhance_Bytes; + fwrite( data, sizeof( unsigned char ), enhance_Bytes, outfp ); + *out_bytes += enhance_Bytes; + *total_mv_bytes += enhance_Bytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% motion_bytes\n", enhance_Bytes + 4 ); + GOP_motion_bytes += enhance_Bytes; + } + free( data ); + } else { + fseek( fpbit, enhance_Bytes, SEEK_CUR ); + in_bytes += enhance_Bytes; + } +} + + +// process major section for motion vector +void process_mv_section(long int mvBytes, FILE *outfp, long int *out_bytes, long int *total_mv_bytes, + long int *in_bytes, FILE *fpbit, FILE *fptab, enum FLAG pulled_bitstream) +{ + unsigned char *data; + + write_number_core( mvBytes, outfp ); + *out_bytes += 4; + *total_mv_bytes += 4; + data = ( unsigned char * )getarray( mvBytes, sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), mvBytes, fpbit ) != ( unsigned )mvBytes ) { + printf( "fread error2 %d\n", mvBytes ); + exit( 1 ); + } + *in_bytes += mvBytes; + fwrite( data, sizeof( unsigned char ), mvBytes, outfp ); + *out_bytes += mvBytes; + *total_mv_bytes += mvBytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% motion_bytes\n", mvBytes + 4 ); + GOP_motion_bytes += mvBytes; + } + free( data ); +} + + + +int +main( int argc, char **argv ) +{ + int i, j, k, nm, curr, last, num_of_GOP, GOPheader_bytes, Per_GOPheader_bytes, FAT_bytes; + int count = 0, remaining_frs, num_subband, bytes, mvBytes; + int kbps = 0, tmp, GOPsz, eff_GOPsz, is_pullable; + int *subband_fat, *newsubband_fat; + long int in_bytes = 0, out_bytes = 0, FAT_start = 0, overhead_start; + long int overhead = 0, estimated_overhead = 0, GOP_estimated_overhead = 0, total_mv_bytes = 0; + long int subband_bytes = 0, total_subband_bytes = 0, *newfat; + short int t_level, s_level, rel_s_level, target_rate; + + int getnum; + + unsigned char *data; + char pre_stream[256], post_stream[256], overhead_stream[256]; + char seq_name[256], seq_name2[256], bit_alloc_name[256], bit_alloc_table[256]; + char list_name[256], simulcast_name[256], **list_simulname; + + int list_size = 0, list_counter = 0, max_tlevel = 0; + unsigned char list_tlevel[25], list_slevel[25], list_qp[25], list_simulcast[25]; + unsigned short int list_rates[25], simul_bitstream = 0; + unsigned long int sum_mv[10], exist_sum_mv[10], list_out_bytes[25], simul_bitstream_pos = 0; + + unsigned long int *gop_sum_mv[10], *gop_exist_sum_mv[10]; + + enum FLAG CBR, display_list, pulled_bitstream, VBR_ADAPT; + FILE *outfp, *fpbytes, *fptab, *fphead; + int AGP_sign, sub_bit, AGP_exist_pull[MAX_TLEVELS], bi_exist[MAX_TLEVELS]; + long int major_mvBytes; + enum FLAG scene_change_left, scene_change_right; + int layer_sign, layer_exist_pull[MAX_TLEVELS]; + + int GOP_subband_bytes; + + videoinfo info; + + printf("Built on %s at %s.\n", __DATE__, __TIME__); + + read_command( argc, argv, &t_level, &s_level, &kbps, AGP_exist_pull, layer_exist_pull, + bi_exist, pre_stream, &CBR, &display_list, &VBR_ADAPT, list_name ); + + if( kbps <= 0 ) { + printf( "kbps parameter is not right\n" ); + pull_usage( ); + exit( 1 ); + } + + /**********/ + /* header */ + /**********/ + + read_header( pre_stream, &info );// 读头信息,并将头信息转换为info + in_bytes += sizeof( videoheader ); + + num_of_GOP = get_GOP_num( info ); + printf("num_of_GOP = %d\n",num_of_GOP); + + if(CBR == YES || VBR_ADAPT == YES){ + for(i = 0; i < 10; i ++){ + gop_sum_mv[i] = ( unsigned long * )getarray( num_of_GOP, sizeof( unsigned long ), "gop_sum_mv" ); + gop_exist_sum_mv[i] = ( unsigned long * )getarray( num_of_GOP, sizeof( unsigned long ), "gop_sum_mv" ); + } + } + + // scalable motion vector coding 可伸缩运动向量编码,以及可伸缩分辨率编码 + AGP_sign = layer_sign = 0; + for (i = 0; i < MAX_TLEVELS; i++) + { + if ( info.AGP_level[i] ) + AGP_sign = 1; + // no value for AGP_exist_pull, then we use default value for it + if ( AGP_exist_pull[i]== INVALID_AGP_EXIST ) AGP_exist_pull[i] = info.AGP_level[i]; + // for resolution scalability, when we reduce one level of resolution, we discard one least + // significant sub-symbol until no sub-symbol can be discarded + // hence, AGP_exist_pull can not be larger than info.AGP_level[i]-s_level + if ( AGP_exist_pull[i]>info.AGP_level[i]-s_level ) + AGP_exist_pull[i]= MY_MAX (0, info.AGP_level[i]-s_level); + info.AGP_exist[i] = AGP_exist_pull[i]; + + if ( info.layer_mv[i] ) layer_sign = 1; + // no value for layer_exist_pull, the we use the default values + if ( layer_exist_pull[i]== INVALID_LAYER_EXIST ) layer_exist_pull[i] = 1; + if ( layer_exist_pull[i]>info.layer_mv[i] ) + layer_exist_pull[i]= info.layer_mv[i]; + info.layer_exist[i] = layer_exist_pull[i]; + + // alternative Haar reconstruction + // only when info.bi_mv[i] == 0, mv on RIGHT side can be discarded + assert( bi_exist[i] == INVALID_BI_MV || bi_exist[i] == 0 || bi_exist[i] == 1 ); + assert( info.bi_exist[i] == 1 || info.bi_exist[i] == 0 ); + assert( info.bi_mv[i]== 1 || info.bi_mv[i] == 0 ); + if ( bi_exist[i] != INVALID_BI_MV && info.bi_mv[i]==0) + info.bi_exist[i] = bi_exist[i]; + } + + pulled_bitstream = ( info.bitrate != 0 ) ? YES : NO; + + if ( pulled_bitstream == NO ){ + info.bitrate = kbps; + info.t_level = max_tlevel = t_level; + info.s_level = s_level; + + } + + rel_s_level = info.s_level - (info.denoise_flag == YES);// + + if( strlen(list_name) > 0 ){ //NOT WORKING + if( pulled_bitstream == YES ){ + printf("bitstream already pulled before - please use -n option to display pullable rates.\n"); + exit( 1 ); + } + // get array for simulcast_names + list_simulname = ( char ** ) malloc( 25 * sizeof ( char * ) ); + for( i = 0; i < 25; i++ ) { + list_simulname[i] = ( char * ) malloc( 256 * sizeof ( char ) ); + } + + // read in list file for output rates etc. + list_counter = read_listfile( list_name, list_rates, list_tlevel, list_slevel, + list_simulcast, list_simulname, info ); + if( list_counter > 0 ){ + for ( i = 0; i < list_counter; i++ ){ + if ( list_tlevel[i] > max_tlevel){ + max_tlevel = list_tlevel[i]; + } + } + } + } //NOT WORKING + + strcpy( info.bitname, pre_stream ); + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); + seq_name[strlen( info.bitname ) - 4] = '\0'; + + // GOPheader_bytes (cmp. mvcoding.c) + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + for( j = 0; j < GOPsz; j++ ) + count++;// 记录有多少个时域子带 + GOPsz /= 2; + } + GOPsz = info.GOPsz; + GOPheader_bytes = (( count + 7 ) / 8) * num_of_GOP; // 每个时域子带一个bit。记录整个序列需要多少字节 + + Per_GOPheader_bytes = GOPheader_bytes / num_of_GOP; + + printf("num_of_GOP = %d, GOPsz = %d\n",num_of_GOP,GOPsz); + + // FAT bytes + FAT_bytes = num_of_GOP * sizeof( long int ); // DENOISE ? -> only larger values 每个gop占一个long int + + if( pulled_bitstream == NO ){ + // read MV bytes + + info.org_yheight = info.yheight; + info.org_ywidth = info.ywidth; + + //printf("max_tlevel = %d\n",max_tlevel); + + for ( i = 0; i <= max_tlevel; i++ ){ + getnum = 0; + + info.t_level = i; + sum_mv[i] = read_mv_bytes( seq_name, info, AGP_sign, layer_sign, &exist_sum_mv[i] ); // 读取每一帧mv的字节数 + printf("%d \t %d \n", sum_mv[i], exist_sum_mv[i]); + if(CBR == YES || VBR_ADAPT == YES){ + gop_read_mv_bytes( seq_name, info, AGP_sign, layer_sign, + gop_exist_sum_mv[i], num_of_GOP, gop_sum_mv[i] ); + + for(j = 0; j < num_of_GOP; j ++) + getnum += gop_sum_mv[i][j]; + + printf("getnum = %d, sum_mv = %d\n",getnum, sum_mv[i]); + } + } + info.t_level = t_level; + +// if (AGP_sign && layer_sign) // automatic bit allocation according to empirical model +// automatic_bit_allocation_with_AGP(&sum_mv[t_level], &info, seq_name, AGP_sign, layer_sign ); + + sprintf( bit_alloc_table, "%s_%d.alloc_table", seq_name, info.bitrate ); + if( !( fptab = fopen( bit_alloc_table, "wb" ) ) ) { + printf( "can not open: %s\n", bit_alloc_table ); + exit( 1 ); + } +/* + if( list_counter > 0 ){ //NOT WORKING + list_size = sizeof( unsigned char ) + 2 * sizeof( unsigned long int ) + + list_counter * ( sizeof( unsigned short int ) + 4 * sizeof( unsigned char ) + + sizeof( unsigned long int ) ) ; // List + overhead FAT + estimated_overhead += list_size; + + printf( "---------------------------------------------------------------\n" ); + printf( " List file : %s\n", list_name); + printf( " List size : %d bytes\n", list_size ); + fprintf( fptab, "%%---------------------------------------------------------------\n" ); + fprintf( fptab, "%s %% list_file\n", list_name ); + fprintf( fptab, "%d \t %% list_size\n", list_size ); + + // open overhead substream + sprintf( overhead_stream, "%s.overhead", seq_name ); + if( !( fphead = fopen( overhead_stream , "wb" ) ) ) { + printf( "can not open: %s\n", overhead_stream ); + exit( 1 ); + } + + printf("list_counter = %d\n",list_counter); + + for ( i = 0; i < list_counter; i++ ){ + if( list_simulcast[i] ){ + // SIMULCAST --> determine filesize for overhead + assert(0); + strncpy( seq_name2, list_simulname[i], strlen( list_simulname[i] ) - 4 ); + seq_name2[strlen( list_simulname[i] ) - 4] = '\0'; + + is_pullable = simulcast_pull( list_simulname[i], seq_name2, list_tlevel[i], + list_slevel[i], list_rates[i], 0 ); + if ( is_pullable == -1 ){ + printf("Simulcast-File %s not pullable\n", list_simulname[i]); + exit(1); + } + list_qp[i] = is_pullable; + + // write file(s) + if( list_simulcast[i] == 1){ + sprintf( simulcast_name, "%s_%d.bit", seq_name2, list_rates[i] ); + list_out_bytes[i] = write_zip( simulcast_name, fphead, NO ); + estimated_overhead += list_out_bytes[i]; + } else if( list_simulcast[i] == 2) { + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name2, list_rates[i] ); + list_out_bytes[i] = write_zip( bit_alloc_name, fphead, YES ); + estimated_overhead += list_out_bytes[i]; + } else { + printf("Unknown Simulcast-Mode!\n"); + exit (1); + } + + printf( " Target %2d : t_level %d, s_level %d, rate %5d, qp %2d, simulcast %d --> %6ld bytes\n", + i, list_tlevel[i], list_slevel[i], list_rates[i], list_qp[i], list_simulcast[i], + list_out_bytes[i] ); + fprintf( fptab, "%ld \t %% target %d : t_level %d, s_level %d, rate %5d, qp %2d, simulcast %d\n", + list_out_bytes[i], i, list_tlevel[i], list_slevel[i], list_rates[i], list_qp[i], + list_simulcast[i]); + } else { + info.t_level = list_tlevel[i]; + info.s_level = list_slevel[i]; + info.bitrate = list_rates[i]; + overhead = sizeof( videoheader ) + GOPheader_bytes + FAT_bytes; + + // bit_alloc file (bytes_per_GOP) calculate for every target rate + if( CBR == NO ){ + is_pullable = bit_alloc_VBR( info, &info.qp, sum_mv[info.t_level], overhead ); + + if (!is_pullable){ + list_simulcast[i] = 1; + i--; + } else { + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, info.bitrate ); + list_out_bytes[i] = write_zip( bit_alloc_name, fphead, YES ); + estimated_overhead += list_out_bytes[i]; + list_qp[i] = info.qp; + printf( " Target %2d : t_level %d, s_level %d, rate %5d, qp %2d, simulcast %d --> %6ld bytes\n", + i, list_tlevel[i], list_slevel[i], list_rates[i], list_qp[i], list_simulcast[i], + list_out_bytes[i] ); + fprintf( fptab, "%ld \t %% target %d : t_level %d, s_level %d, rate %5d, qp %2d, simulcast %d\n", + list_out_bytes[i], i, list_tlevel[i], list_slevel[i], list_rates[i], list_qp[i], + list_simulcast[i]); + } + } + } + } + fclose ( fphead ); + + // reset values to main output bit stream + info.t_level = t_level; + info.s_level = s_level; + info.bitrate = kbps; + } //NOT WORKING +*/ + + estimated_overhead += sizeof( videoheader ) + GOPheader_bytes + FAT_bytes; + + printf("GOPheader_bytes = %d\n",GOPheader_bytes); + + GOP_estimated_overhead = estimated_overhead / num_of_GOP;// 每个gop的overhead + + if( CBR == NO ){ + if(VBR_ADAPT == NO) + is_pullable = bit_alloc_VBR( info, &info.qp, sum_mv[info.t_level], estimated_overhead );// 全是NO + else + is_pullable = bit_alloc_VBR_v2(info, &info.qp, estimated_overhead, gop_sum_mv[info.t_level], info.last, info.last - info.GOPsz); + + }else if(CBR == YES){ + is_pullable = bit_alloc_CBR( info, &info.qp, estimated_overhead, gop_sum_mv[info.t_level], info.last ); + } + + if( !is_pullable ){ + printf("bitstream is not pullable!\n"); + exit(1); + } + } // end of pulled_bitstream == NO + + if( !( fpbit = fopen( pre_stream, "rb" ) ) ) { + printf( "can not open: %s\n", pre_stream ); + exit( 1 ); + } +/* + // get and extract data from pulled bitstream + if( pulled_bitstream == YES ){ //NOT WORKING + FAT_start = in_bytes; + fseek( fpbit, -sizeof( unsigned long int ), SEEK_END ); + fread( &overhead_start, sizeof( unsigned long int ), 1, fpbit ); + estimated_overhead = ftell( fpbit ) - overhead_start; + fseek( fpbit, overhead_start, SEEK_SET ); + in_bytes = overhead_start; + + // read target rate list + fread( &list_counter, sizeof( unsigned char ), 1, fpbit ); + in_bytes += sizeof( unsigned char ); + for ( i = 0; i < list_counter; i++ ){ + fread( &list_rates[i], sizeof( unsigned short int ), 1, fpbit ); + fread( &list_tlevel[i], sizeof( unsigned char ), 1, fpbit ); + fread( &list_slevel[i], sizeof( unsigned char ), 1, fpbit ); + fread( &list_qp[i], sizeof( unsigned char ), 1, fpbit ); + fread( &list_simulcast[i], sizeof( unsigned char ), 1, fpbit ); + fread( &list_out_bytes[i], sizeof( unsigned long int ), 1, fpbit ); + in_bytes += sizeof( unsigned short int )+ 4 * sizeof( unsigned char ) + + sizeof( unsigned long int ); + } + + unsigned long overhead_size = 0; + unsigned char *input_data; + + // read in total overhead size + fread( &overhead_size, sizeof( unsigned long int ), 1, fpbit ); + in_bytes += sizeof( unsigned long int ); + + target_rate = -1; + for ( i = 0; i < list_counter; i++ ){ + if( list_rates[i] == kbps ){ + target_rate = i; + info.bitrate = list_rates[i]; + info.t_level = list_tlevel[i]; + info.s_level = list_slevel[i]; + info.qp = list_qp[i]; + rel_s_level = info.s_level - (info.denoise_flag == YES); + printf( " Target %2d : t_level %d, s_level %d, rate %5d, qp %2d\n", + i, list_tlevel[i], list_slevel[i], list_rates[i], list_qp[i] ); + break; + } else { + if ( list_simulcast[i] == 1 ){ + simul_bitstream = i; + simul_bitstream_pos = in_bytes; + } + in_bytes += list_out_bytes[i]; + fseek( fpbit, in_bytes, SEEK_SET ); + } + } + if ( target_rate < 0 || display_list == YES ){ + printf( "possible target output configurations: \n" ); + printf( " Mainstream : t_level %d, s_level %d, rate %5d ( decodeable without pull )\n", + info.t_level, info.s_level, info.bitrate); + for ( i = 0; i < list_counter; i++ ){ + printf( " Target %2d : t_level %d, s_level %d, rate %5d, qp %2d, simulcast %d --> %6ld bytes\n", + i, list_tlevel[i], list_slevel[i], list_rates[i], list_qp[i], list_simulcast[i], + list_out_bytes[i] ); + } + exit (1); + } + + // read in zipped overhead information file + fseek( fpbit, in_bytes, SEEK_SET ); + + input_data = + ( unsigned char * )getarray( list_out_bytes[target_rate], sizeof( unsigned char ), + "input_data" ); + if( fread( input_data, sizeof( unsigned char ), list_out_bytes[target_rate], fpbit ) != + ( unsigned ) list_out_bytes[target_rate] ) { + printf( "fread error \n" ); + exit( 1 ); + } + + // extract and save overhead file + if( list_simulcast[i] ){ + assert(0); + if( list_simulcast[i] == 2 ){ // extract bytes_per_GOP file + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, list_rates[target_rate] ); + extract_zip( bit_alloc_name, input_data, list_out_bytes[target_rate], YES ); + + free( input_data ); + // and extract simulcast main bitstream + fseek( fpbit, simul_bitstream_pos, SEEK_SET ); + + input_data = + ( unsigned char * )getarray( list_out_bytes[simul_bitstream], sizeof( unsigned char ), + "input_data" ); + if( fread( input_data, sizeof( unsigned char ), list_out_bytes[simul_bitstream], fpbit ) != + ( unsigned ) list_out_bytes[simul_bitstream] ) { + printf( "fread error \n" ); + exit( 1 ); + } + sprintf( simulcast_name, "%s_%d.bit", seq_name, list_rates[simul_bitstream] ); + extract_zip( simulcast_name, input_data, list_out_bytes[simul_bitstream], NO ); + + // proceed with pulling simulcast-files for target rate + is_pullable = simulcast_pull( simulcast_name, seq_name, list_tlevel[target_rate], + list_slevel[target_rate], list_rates[target_rate], + list_qp[target_rate] ); + if ( is_pullable == -1 ){ + printf("Simulcast-File %s not pullable\n", simulcast_name); + exit(1); + } + } else { // only extract simulcast main bitstream + sprintf( simulcast_name, "%s_%d.bit", seq_name, list_rates[target_rate] ); + extract_zip( simulcast_name, input_data, list_out_bytes[target_rate], NO ); + printf("Finished.\n"); + } + exit(1); + } else{ + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, list_rates[target_rate] ); + extract_zip( bit_alloc_name, input_data, list_out_bytes[target_rate], YES ); + } + + // go to start of bitstream + in_bytes = FAT_start; + fseek( fpbit, FAT_start, SEEK_SET ); + + free( input_data ); + } //NOT WORKING +*/ + sprintf( post_stream, "%s_%d.bit", seq_name, info.bitrate ); + + write_header( post_stream, info ); + out_bytes += sizeof( videoheader ); + + if( !( outfp = fopen( post_stream, "r+b" ) ) ) { + printf( "can not open: %s\n", post_stream ); + exit( 1 ); + } + + printf( "---------------------------------------------------------------\n" ); + printf( " Sequence name : %s\n", seq_name ); + printf( " Sequence length : %03d frames ( %03d - %03d )\n", + info.last - info.start + 1, info.start, info.last ); + printf( " Output bit rate : %d kbit/sec\n", info.bitrate ); + printf( " Output frame rate : %0.2f frames/sec (t_level %d)\n", + ((double)(info.framerate) / pow((float)2, info.t_level)), info.t_level ); + printf( " Output frame size : (Y) %d x %d (C) %d x %d (s_level %d)\n", + info.ywidth >> rel_s_level, info.yheight >> rel_s_level, + info.cwidth >> rel_s_level, info.cheight >> rel_s_level, + info.s_level ); + printf( " Number of GOPs : %d\n", num_of_GOP ); + printf( " Header/FAT bytes : %d bytes\n", + sizeof( videoheader ) + FAT_bytes + GOPheader_bytes ); + // printf( " Header size : %d bytes\n", sizeof( videoheader ) ); + // printf( " GOP FAT bytes : %d bytes\n", FAT_bytes ); + // printf( " GOP header bytes : %d bytes\n", GOPheader_bytes ); + printf( " Overhead bytes : %ld bytes\n", estimated_overhead + - (sizeof( videoheader ) - FAT_bytes - GOPheader_bytes) + * ( pulled_bitstream == NO )); +#ifdef MY_SCALE + printf( " MY_SCALE : %d (%d extra bits)\n", MY_SCALE, (int)log2(MY_SCALE)); +#endif + printf( "---------------------------------------------------------------\n" ); + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%%---------------------------------------------------------------\n" ); + fprintf( fptab, "%s %% sequence_name\n", seq_name ); + fprintf( fptab, "%03d \t %% sequence_length\n", info.last - info.start + 1 ); + fprintf( fptab, "%03d \t %% start\n", info.start ); + fprintf( fptab, "%03d \t %% last\n", info.last ); + fprintf( fptab, "%d \t %% bit_rate\n", info.bitrate ); + fprintf( fptab, "%0.2f\t %% frame_rate\n", + ((double)(info.framerate) / pow((float)2, info.t_level))); + fprintf( fptab, "%d \t %% t_level\n", info.t_level ); + fprintf( fptab, "%d \t %% Y_size_x\n", info.ywidth >> rel_s_level); + fprintf( fptab, "%d \t %% Y_size_y\n", info.yheight >> rel_s_level); + fprintf( fptab, "%d \t %% C_size_x\n", info.cwidth >> rel_s_level); + fprintf( fptab, "%d \t %% C_size_y\n", info.cheight >> rel_s_level); + fprintf( fptab, "%d \t %% s_level\n", info.s_level ); + fprintf( fptab, "%d \t %% number_of_GOP\n", num_of_GOP ); + fprintf( fptab, "%d \t %% header/fat_size\n", + sizeof( videoheader ) + FAT_bytes + GOPheader_bytes ); + fprintf( fptab, "%ld \t %% overhead_size\n", estimated_overhead + - (sizeof( videoheader ) - FAT_bytes - GOPheader_bytes) ); + fprintf( fptab, "---------------------------------------------------------------\n" ); + } + + /*******/ + /* FAT */ + /*******/ + newfat = ( long int * )getarray( num_of_GOP, sizeof( long int ), "newfat" ); + + //skip FAT + in_bytes += num_of_GOP * sizeof( long int ); + fseek( fpbit, in_bytes, SEEK_SET ); + + fseek( outfp, out_bytes, SEEK_SET ); + fwrite( newfat, sizeof( long int ), num_of_GOP, outfp ); + FAT_start = out_bytes; + out_bytes += num_of_GOP * sizeof( long int ); + overhead = out_bytes; + + scene_change = + ( enum FLAG ** )getarray( info.tPyrLev, sizeof( enum FLAG * ), + "scene_change" ); + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + scene_change[i] = + ( enum FLAG * )getarray( GOPsz + 1, sizeof( enum FLAG ), "scene_change" ); + GOPsz /= 2; + } + + curr = info.start; + last = info.last; + + int GOPcounter = 0; + + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, info.bitrate ); + if( CBR == NO || CBR == YES ) { + if( !( fpbytes = fopen( bit_alloc_name, "rb" ) ) ) { + printf( "can not open %s\n", bit_alloc_name ); + exit( 1 ); + } + } + + fscanf( fpbytes, "%d\n", &num_subband ); + + subband_fat = + ( int * )getarray( num_subband, sizeof( int ), "subband_fat" ); + newsubband_fat = + ( int * )getarray( num_subband, sizeof( int ), "newsubband_fat" ); + + + while( curr <= last ) { /* MCTF decoding */ + + remaining_frs = last - curr + 1; //printf("remaining frames = %d\n", remaining_frs); + + if ( remaining_frs < info.GOPsz ){ + // Level_change = YES; + info.eff_GOPsz = remaining_frs; + } else { + // Level_change = NO; // full GOP + info.eff_GOPsz = info.GOPsz; // effective GOP size + } + + printf( " pulling GOP %d: frame %d - %d\n", GOPcounter, + curr, curr + info.eff_GOPsz - 1 ); + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%% GOP %2d %% frame %d - %d\n", GOPcounter, + curr, curr + info.eff_GOPsz - 1 ); + } + + GOPheader_bytes = 0; + if( info.tPyrLev >= 1 ) { + + /*************/ + /* GOPheader */ + /*************/ + + GOPheader_bytes = read_GOPheader( scene_change, info ); //printf("%d\n", GOPheader_bytes); + fseek( fpbit, -GOPheader_bytes, SEEK_CUR ); + + data = + ( unsigned char * )getarray( GOPheader_bytes, sizeof( unsigned char ), + "data" ); + if( fread( data, sizeof( unsigned char ), GOPheader_bytes, fpbit ) != + ( unsigned )GOPheader_bytes ) { + printf( "fread error1 \n" ); + exit( 1 ); + } + in_bytes += GOPheader_bytes; + + fwrite( data, sizeof( unsigned char ), GOPheader_bytes, outfp ); + out_bytes += GOPheader_bytes; + overhead += GOPheader_bytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% GOPheader_bytes\n", GOPheader_bytes ); + } + free( data ); + + /******/ + /* MV */ + /******/ + + GOP_motion_bytes = 0; //Added on 10.06.2017 + + GOPsz = 2; + for( j = info.tPyrLev - 1; j >= 0; j-- ) { + + if (info.bi_exist[j]) // bi-directional motion field + { + for( k = 0; k <= GOPsz; k++ ) { + if( scene_change[j][k] == NO ) { + + // scalable motion vector coding: AGP and layer structure + + if ( !AGP_sign && !layer_sign ) // no AGP, no layer structure + { + mvBytes = read_number_core( fpbit ); // fpbit will move forward by 4 bytes + in_bytes += 4; + + printf("mvBytes = %d\n",mvBytes); + if( j >= info.t_level ) { // temporal scalability + process_mv_section(mvBytes, outfp, &out_bytes, &total_mv_bytes, &in_bytes, fpbit, + fptab, pulled_bitstream); + } else { + fseek( fpbit, mvBytes, SEEK_CUR ); + in_bytes += mvBytes; + } + } + + if ( AGP_sign && !layer_sign ) // AGP, no layer structure + { + major_mvBytes = read_number_core( fpbit ); // fpbit will move forward by 4 bytes + in_bytes += 4; + if( j >= info.t_level ) { // temporal scalability + process_mv_section(major_mvBytes, outfp, &out_bytes, &total_mv_bytes, &in_bytes, fpbit, + fptab, pulled_bitstream); + if ( info.AGP_level[j] ) + { + if (info.AGP_exist[j]) // sign bytes + get_bytes_section(fpbit, outfp, fptab, 1, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + else + get_bytes_section(fpbit, outfp, fptab, 0, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + for (sub_bit=0; sub_bit= info.t_level ) { // temporal scalability + process_mv_section(major_mvBytes, outfp, &out_bytes, &total_mv_bytes, &in_bytes, fpbit, + fptab, pulled_bitstream); + if ( info.layer_mv[j] ) + { + if (info.layer_exist[j]) // enhancement bytes + get_bytes_section_enhance(fpbit, outfp, fptab, 1, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + else + get_bytes_section_enhance(fpbit, outfp, fptab, 0, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + } + } else { + fseek( fpbit, major_mvBytes, SEEK_CUR ); + in_bytes += major_mvBytes; + if ( info.layer_mv[j] ) + { + get_bytes_section_enhance(fpbit, outfp, fptab, 0, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + } + } + } + + if ( AGP_sign && layer_sign ) // AGP, layer structure + { + major_mvBytes = read_number_core( fpbit ); // fpbit will move forward by 4 bytes + in_bytes += 4; + if( j >= info.t_level ) { // temporal scalability + process_mv_section(major_mvBytes, outfp, &out_bytes, &total_mv_bytes, &in_bytes, fpbit, + fptab, pulled_bitstream); + if ( info.AGP_level[j] ) // AGP for base layer + { + if (info.AGP_exist[j]) // sign bytes + get_bytes_section(fpbit, outfp, fptab, 1, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + else + get_bytes_section(fpbit, outfp, fptab, 0, &in_bytes, &out_bytes, &total_mv_bytes, + pulled_bitstream); + for (sub_bit=0; sub_bit= info.t_level ) { // temporal scalability + process_mv_section(mvBytes, outfp, &out_bytes, &total_mv_bytes, &in_bytes, fpbit, + fptab, pulled_bitstream); + } else { + fseek( fpbit, mvBytes, SEEK_CUR ); + in_bytes += mvBytes; + } + }else + { + + } + + if ( scene_change_left==NO && scene_change_right==NO ) + if ( AGP_sign==0 ) + { + mvBytes = read_number_core( fpbit ); // fpbit will move forward by 4 bytes + in_bytes += 4; + fseek( fpbit, mvBytes, SEEK_CUR ); + in_bytes += mvBytes; + }else { + + } + } + } // while ( k <= GOPsz ) + } // if ( ! info.bi_mv[j]) + + GOPsz *= 2; + } // for( j = info.tPyrLev - 1; j >= 0; j-- ) + + fprintf(fptab, "%ld \t %% GOP motion_bytes\n", GOP_motion_bytes); + + } + + /*************/ + /* Bitplanes */ + /*************/ + + newfat[GOPcounter] = 0; + + eff_GOPsz = info.eff_GOPsz; + if( info.denoise_flag == YES ) { + eff_GOPsz *= ( YUV420 == 1 ) ? 2 : 4; + } +// printf("num_subband = %d, eff_GOPsz = %d\n",num_subband, eff_GOPsz); + + GOP_subband_bytes = 0; + + for( j = 0; j < eff_GOPsz; j++ ) { + subband_bytes = 0; + for( nm = 0; nm < num_subband; nm++ ) { + // read bit plane + in_bytes += read_substream_length( &subband_fat[nm], fpbit ); + data = + ( unsigned char * )getarray( subband_fat[nm], + sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), subband_fat[nm], fpbit ) != + ( unsigned )subband_fat[nm] ) { + printf( "read error3 %d %d\n", GOPcounter, subband_fat[nm] ); + exit( 1 ); + } + in_bytes += sizeof( unsigned char ) * subband_fat[nm]; + + // write bit plane + fscanf( fpbytes, "%d\n", &tmp ); +// printf("tmp = %d\n",tmp); + newsubband_fat[nm] = tmp; + if( newsubband_fat[nm] != 0 ) { + if( subband_fat[nm] < newsubband_fat[nm] ) { + newsubband_fat[nm] = subband_fat[nm]; + } + // write subband header + bytes = write_substream_length( newsubband_fat[nm], outfp ); + out_bytes += bytes; + newfat[GOPcounter] += bytes; + subband_bytes += bytes; + total_subband_bytes += bytes; + + if( fwrite + ( data, sizeof( unsigned char ), newsubband_fat[nm], + outfp ) != ( unsigned )newsubband_fat[nm] ) { + printf( "write error %d\n", newsubband_fat[nm] ); + exit( 1 ); + } + out_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + newfat[GOPcounter] += sizeof( unsigned char ) * newsubband_fat[nm]; + subband_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + total_subband_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + } + free( data ); + } + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%ld \t %% subband_bytes\n", subband_bytes ); + GOP_subband_bytes += subband_bytes; + } + } + + fprintf(fptab, "%ld \t %% GOP subband_bytes\n", GOP_subband_bytes); + + curr += info.GOPsz; + GOPcounter++; + } // while + + assert((unsigned int)total_mv_bytes==sum_mv[info.t_level]); + assert((unsigned int)total_mv_bytes<=exist_sum_mv[info.t_level]); + + /*************/ + /* write FAT */ + /*************/ + fseek( outfp, FAT_start, SEEK_SET ); + + if( fwrite( newfat, sizeof( long int ), num_of_GOP, outfp ) != + ( unsigned )num_of_GOP ) { + printf( "write error \n" ); + exit( 1 ); + } + + for( i = 0; i < info.tPyrLev; i++ ) { + free( scene_change[i] ); + } + free( scene_change ); + + /******************/ + /* write overhead */ + /******************/ + if( list_counter > 0 && pulled_bitstream == NO ){ // NOT WORKING + assert(0); + fseek( outfp, out_bytes, SEEK_SET ); + overhead_start = out_bytes; + + // write list + fwrite( &list_counter, sizeof( unsigned char ), 1, outfp ); + out_bytes += sizeof( unsigned char ); + for ( i = 0; i < list_counter; i++ ){ + fwrite( &list_rates[i], sizeof( unsigned short int ), 1, outfp ); + fwrite( &list_tlevel[i], sizeof( unsigned char ), 1, outfp ); + fwrite( &list_slevel[i], sizeof( unsigned char ), 1, outfp ); + fwrite( &list_qp[i], sizeof( unsigned char ), 1, outfp ); + fwrite( &list_simulcast[i], sizeof( unsigned char ), 1, outfp ); + fwrite( &list_out_bytes[i], sizeof( unsigned long int ), 1, outfp ); + out_bytes += sizeof( unsigned short int )+ 4 * sizeof( unsigned char ) + + sizeof( unsigned long int ); + } + + unsigned long input_size = 0, in_len; + unsigned char *input_data; + + // load overhead file + if( !( fphead = fopen( overhead_stream , "rb" ) ) ) { + printf( "can not open %s\n", overhead_stream ); + exit( 1 ); + } + fseek( fphead, 0, SEEK_END ); + input_size = ftell( fphead ); + fseek( fphead, 0, SEEK_SET ); + + input_data = + ( unsigned char * )getarray( input_size, sizeof( unsigned char ), + "input_data" ); + if( fread( input_data, sizeof( unsigned char ), input_size, fphead ) != + ( unsigned ) input_size ) { + printf( "fread error \n" ); + exit( 1 ); + } + fclose( fphead ); + + // write overhead file to bitstream + in_len = input_size * sizeof( unsigned char ); + fwrite( &in_len, sizeof( unsigned long int ), 1, outfp ); + fwrite( input_data, sizeof( unsigned char ), in_len, outfp ); + out_bytes += sizeof( unsigned long int ) + in_len * sizeof( unsigned char ); + + // write overhead position to bitstream + fwrite( &overhead_start, sizeof( unsigned long int ), 1, outfp ); + out_bytes += sizeof( unsigned long int ); + + overhead += (out_bytes - overhead_start); + free( input_data ); + }// NOT WORKING + + if ( pulled_bitstream == NO ) + assert ( overhead == estimated_overhead ); + + printf( "---------------------------------------------------------------\n" ); + printf( " total overhead : %ld bytes\n", overhead); + printf( " + motion data : %ld bytes out of existing motion data %ld bytes \n", + total_mv_bytes, exist_sum_mv[info.t_level] ); + printf( " + subband data : %ld bytes\n", total_subband_bytes ); + printf( " == total output : %ld bytes (%ld bytes read)\n", + out_bytes, in_bytes ); + printf( "---------------------------------------------------------------\n" ); + + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%%---------------------------------------------------------------\n" ); + fprintf( fptab, "%ld \t %% == total_input\n", in_bytes ); + fprintf( fptab, "%%---------------------------------------------------------------\n" ); + fprintf( fptab, "%ld \t %% total_overhead \n", overhead ); + fprintf( fptab, "%ld \t %% + motion_data \n", total_mv_bytes ); + fprintf( fptab, "%ld \t %% + subband_data \n", total_subband_bytes ); + fprintf( fptab, "%ld \t %% == total_output\n", out_bytes ); + fprintf( fptab, "%%---------------------------------------------------------------\n" ); + fclose( fptab ); + } + + fclose( fpbytes ); + fclose( fpbit ); + fclose( outfp ); + + free( subband_fat ); + free( newsubband_fat ); + free( newfat ); + + if(CBR == YES || VBR_ADAPT == YES){ + for(i = 0; i < 10; i ++){ + free(gop_sum_mv[i]); + free(gop_exist_sum_mv[i]); + } + } + + return 0; +} + + +int +simulcast_pull( char *pre_stream, char *output_name, int t_level, + int s_level, int kbps, int qp ) +{ + int i, j, k, nm, curr, last, num_of_GOP, GOPheader_bytes, FAT_bytes; + int count = 0, remaining_frs, num_subband, bytes, mvBytes; + int tmp, GOPsz, eff_GOPsz, is_pullable; + int *subband_fat, *newsubband_fat; + long int in_bytes = 0, out_bytes = 0, FAT_start = 0, *newfat; + long int overhead = 0, estimated_overhead = 0, total_mv_bytes = 0; + long int subband_bytes = 0, total_subband_bytes = 0; + short int rel_s_level; + + unsigned char *data; + char post_stream[256], seq_name[256], bit_alloc_name[256]; + int AGP_sign = 0, layer_sign=0; + + unsigned long int sum_mv, exist_sum_mv; + + enum FLAG CBR = NO, pulled_bitstream; + FILE *outfp, *fpbytes; + + videoinfo info; + + + /**********/ + /* header */ + /**********/ + + read_header( pre_stream, &info ); + in_bytes += sizeof( videoheader ); + + pulled_bitstream = ( info.bitrate != 0 ) ? YES : NO; + int display_operations = (pulled_bitstream == YES); // display pull operations + + info.bitrate = kbps; + info.t_level = t_level; + info.s_level = s_level; + rel_s_level = s_level - (info.denoise_flag == YES); + info.qp = qp; + + strcpy( info.bitname, pre_stream ); + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); + seq_name[strlen( info.bitname ) - 4] = '\0'; + + num_of_GOP = get_GOP_num( info ); + + // GOPheader_bytes (cmp. mvcoding.c) + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + for( j = 0; j < GOPsz; j++ ) + count++; + GOPsz /= 2; + } + GOPsz = info.GOPsz; + GOPheader_bytes = (( count + 7 ) / 8) * num_of_GOP; + + // FAT bytes + FAT_bytes = num_of_GOP * sizeof( long int ); + + if( pulled_bitstream == NO ){ + + // read MV bytes + sum_mv = read_mv_bytes( seq_name, info, AGP_sign, layer_sign, &exist_sum_mv ); + + // pull if target rate was found in list, then unzip data + estimated_overhead += sizeof( videoheader ) + GOPheader_bytes + FAT_bytes; + + if( CBR == NO ) + is_pullable = bit_alloc_VBR( info, &info.qp, sum_mv, estimated_overhead ); + + if( !is_pullable ){ + return -1; + } + } + + if( !( fpbit = fopen( pre_stream, "rb" ) ) ) { // total bitstream + printf( "can not open: %s\n", pre_stream ); + exit( 1 ); + } + + if (pulled_bitstream == NO){ + sprintf( post_stream, "%s_%d.bit", seq_name, info.bitrate ); + } else { + sprintf( post_stream, "%s_%d.bit", output_name, info.bitrate ); + } + + write_header( post_stream, info ); + out_bytes += sizeof( videoheader ); + + if( !( outfp = fopen( post_stream, "r+b" ) ) ) { + printf( "can not open: %s\n", post_stream ); + exit( 1 ); + } + + if( display_operations ){ + printf( "---------------------------------------------------------------\n" ); + printf( " Sequence name : %s\n", seq_name ); + printf( " Sequence length : %03d frames ( %03d - %03d )\n", + info.last - info.start + 1, info.start, info.last ); + printf( " Output bit rate : %d kbit/sec\n", info.bitrate ); + printf( " Output frame rate : %0.2f frames/sec (t_level %d)\n", + ((double)(info.framerate) / pow((float)2, info.t_level)), info.t_level ); + printf( " Output frame size : (Y) %d x %d (C) %d x %d (s_level %d)\n", + info.ywidth << rel_s_level, info.yheight << rel_s_level, + info.cwidth << rel_s_level, info.cheight << rel_s_level, + info.s_level ); + printf( " Number of GOPs : %d\n", num_of_GOP ); + // printf( " Header size : %d bytes\n", sizeof( videoheader ) ); + // printf( " GOP FAT bytes : %d bytes\n", FAT_bytes ); + // printf( " GOP header bytes : %d bytes\n", GOPheader_bytes ); + printf( " Total overhead : %ld bytes\n", estimated_overhead ); +#ifdef MY_SCALE + printf( " MY_SCALE : %d (%d extra bits)\n", MY_SCALE, (int)log2(MY_SCALE)); +#endif + printf( "---------------------------------------------------------------\n" ); + } + + + /*******/ + /* FAT */ + /*******/ + newfat = ( long int * )getarray( num_of_GOP, sizeof( long int ), "newfat" ); + + //skip FAT + in_bytes += num_of_GOP * sizeof( long int ); + fseek( fpbit, in_bytes, SEEK_SET ); + + fseek( outfp, out_bytes, SEEK_SET ); + fwrite( newfat, sizeof( long int ), num_of_GOP, outfp ); + FAT_start = out_bytes; + out_bytes += num_of_GOP * sizeof( long int ); + overhead = out_bytes; + + scene_change = + ( enum FLAG ** )getarray( info.tPyrLev, sizeof( enum FLAG * ), + "scene_change" ); + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + scene_change[i] = + ( enum FLAG * )getarray( GOPsz + 1, sizeof( enum FLAG ), "scene_change" ); + GOPsz /= 2; + } + + curr = info.start; + last = info.last; + + int GOPcounter = 0; + if( pulled_bitstream == NO ){ + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, info.bitrate ); + } else { + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", output_name, info.bitrate ); + } + + if( CBR == NO ) { + if( !( fpbytes = fopen( bit_alloc_name, "rb" ) ) ) { + printf( "can not open %s\n", bit_alloc_name ); + exit( 1 ); + } + } + + fscanf( fpbytes, "%d\n", &num_subband ); + + subband_fat = + ( int * )getarray( num_subband, sizeof( int ), "subband_fat" ); + newsubband_fat = + ( int * )getarray( num_subband, sizeof( int ), "newsubband_fat" ); + + + while( curr <= last ) { /* MCTF decoding */ + + remaining_frs = last - curr + 1; //printf("remaining frames = %d\n", remaining_frs); + + if ( remaining_frs < info.GOPsz ){ + // Level_change = YES; + info.eff_GOPsz = remaining_frs; + } else { + // Level_change = NO; // full GOP + info.eff_GOPsz = info.GOPsz; // effective GOP size + } + if( display_operations ){ + printf( " pulling GOP %d: frame %d - %d\n", GOPcounter, + curr, curr + info.eff_GOPsz - 1 ); + } + + GOPheader_bytes = 0; + if( info.tPyrLev >= 1 ) { + + /*************/ + /* GOPheader */ + /*************/ + + GOPheader_bytes = read_GOPheader( scene_change, info ); //printf("%d\n", GOPheader_bytes); + fseek( fpbit, -GOPheader_bytes, SEEK_CUR ); + + data = + ( unsigned char * )getarray( GOPheader_bytes, sizeof( unsigned char ), + "data" ); + if( fread( data, sizeof( unsigned char ), GOPheader_bytes, fpbit ) != + ( unsigned )GOPheader_bytes ) { + printf( "fread error1 \n" ); + exit( 1 ); + } + in_bytes += GOPheader_bytes; + + fwrite( data, sizeof( unsigned char ), GOPheader_bytes, outfp ); + out_bytes += GOPheader_bytes; + overhead += GOPheader_bytes; + free( data ); + + /******/ + /* MV */ + /******/ + + GOPsz = 2; + for( j = info.tPyrLev - 1; j >= 0; j-- ) { + for( k = 0; k <= GOPsz; k++ ) { + if( scene_change[j][k] == NO ) { + + mvBytes = read_number_core( fpbit ); // fpbit will move forward by 4 bytes + in_bytes += 4; + + if( j >= info.t_level ) { // temporal scalability + write_number_core( mvBytes, outfp ); + out_bytes += 4; + total_mv_bytes += 4; + + // printf("mvBytes %d\n", mvBytes); + data = + ( unsigned char * )getarray( mvBytes, sizeof( unsigned char ), + "data" ); + if( fread( data, sizeof( unsigned char ), mvBytes, fpbit ) != + ( unsigned )mvBytes ) { + printf( "fread error2 %d\n", mvBytes ); + exit( 1 ); + } + in_bytes += mvBytes; + fwrite( data, sizeof( unsigned char ), mvBytes, outfp ); + out_bytes += mvBytes; + total_mv_bytes += mvBytes; + free( data ); + } else { + fseek( fpbit, mvBytes, SEEK_CUR ); + in_bytes += mvBytes; + } + } + } + GOPsz *= 2; + } + } // if( info.tPyrLev >= 1 ) + + /*************/ + /* Bitplanes */ + /*************/ + + newfat[GOPcounter] = 0; + + eff_GOPsz = info.eff_GOPsz; + if( info.denoise_flag == YES ) { + eff_GOPsz *= ( YUV420 == 1 ) ? 2 : 4; + } + + for( j = 0; j < eff_GOPsz; j++ ) { + subband_bytes = 0; + for( nm = 0; nm < num_subband; nm++ ) { + // read bit plane + in_bytes += read_substream_length( &subband_fat[nm], fpbit ); + data = + ( unsigned char * )getarray( subband_fat[nm], + sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), subband_fat[nm], fpbit ) != + ( unsigned )subband_fat[nm] ) { + printf( "read error3 %d %d\n", GOPcounter, subband_fat[nm] ); + exit( 1 ); + } + in_bytes += sizeof( unsigned char ) * subband_fat[nm]; //printf("%d\n", in_bytes); + + // write bit plane + fscanf( fpbytes, "%d\n", &tmp ); // Read "bytes_per_GOP" (bitalloc.c) + newsubband_fat[nm] = tmp; + if( newsubband_fat[nm] != 0 ) { + if( subband_fat[nm] < newsubband_fat[nm] ) { + newsubband_fat[nm] = subband_fat[nm]; + } + // write subband header + bytes = write_substream_length( newsubband_fat[nm], outfp ); + out_bytes += bytes; + newfat[GOPcounter] += bytes; + subband_bytes += bytes; + total_subband_bytes += bytes; + + if( fwrite + ( data, sizeof( unsigned char ), newsubband_fat[nm], + outfp ) != ( unsigned )newsubband_fat[nm] ) { + printf( "write error %d\n", newsubband_fat[nm] ); + exit( 1 ); + } + out_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + newfat[GOPcounter] += sizeof( unsigned char ) * newsubband_fat[nm]; + subband_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + total_subband_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + } + free( data ); + } + } + + curr += info.GOPsz; + GOPcounter++; + } // while + + /*************/ + /* write FAT */ + /*************/ + fseek( outfp, FAT_start, SEEK_SET ); + + if( fwrite( newfat, sizeof( long int ), num_of_GOP, outfp ) != + ( unsigned )num_of_GOP ) { + printf( "write error \n" ); + exit( 1 ); + } + + for( i = 0; i < info.tPyrLev; i++ ) { + free( scene_change[i] ); + } + free( scene_change ); + + if( display_operations ){ + printf( "---------------------------------------------------------------\n" ); + printf( " total overhead : %ld bytes\n", overhead ); + printf( " + motion data : %ld bytes\n", total_mv_bytes ); + printf( " + subband data : %ld bytes\n", total_subband_bytes ); + printf( " == total output : %ld bytes (%ld bytes read)\n", + out_bytes, in_bytes ); + printf( "---------------------------------------------------------------\n" ); + } + + fclose( fpbytes ); + fclose( fpbit ); + fclose( outfp ); + + free( subband_fat ); + free( newsubband_fat ); + + return info.qp; +} \ No newline at end of file diff --git a/Interframe EZBC/TempSub/src/ras_util.c b/Interframe EZBC/TempSub/src/ras_util.c new file mode 100644 index 0000000..34b77bc --- /dev/null +++ b/Interframe EZBC/TempSub/src/ras_util.c @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include "basic.h" +#include "rasterfile.h" +#include "structN.h" +#include "dpx.h" +#include "unix_pc.h" +#include "util_filtering.h" +#define EXTERN extern +#include "coderN.h" + +struct rasterfile make_header( int hor, int ver, int depth ); + +/*****************************************************************************/ +/* make_header() */ +/*****************************************************************************/ +struct rasterfile +make_header( int hor, int ver, int depth ) +{ + struct rasterfile header; + + header.ras_magic = RAS_MAGIC; + header.ras_width = hor; + header.ras_height = ver; + header.ras_depth = depth; + header.ras_type = RT_STANDARD; + + if( depth == GRAYDATA ) { + header.ras_length = hor * ver; + header.ras_maptype = RMT_EQUAL_RGB; + header.ras_maplength = 256 * 3; + } else if( depth == RGBDATA ) { + header.ras_length = 3 * hor * ver; + header.ras_maptype = 0; + header.ras_maplength = 0; + /*header.ras_type = RT_FORMAT_RGB; */ + } + return header; +} + +/*****************************************************************************/ +/* write_ras() */ +/*****************************************************************************/ +void +write_ras( char *filename, struct rasterfile header, unsigned char *frame ) +{ + FILE *fp; + int i, ver, hor; + int write; + unsigned char map[256]; + int length; + U32 *p; + struct rasterfile temphead; + + /* open the file */ + if( ( fp = fopen( filename, "wb" ) ) == NULL ) { + printf( "write_ras: can't open %s for writing\n", filename ); + exit( 1 ); + } + + /* write the file header */ + temphead = header; + p = ( U32 * ) & temphead; + for( i = 0; i < 8; i++ ) { + p[i] = exchange_4byte_order( p[i] ); + } + /*if((write = fwrite(header, sizeof(struct rasterfile), 1, fp)) != 1) { + printf("write_ras: can't write header to %s\n", filename); + exit(1); + } */ + + if( ( write = fwrite( p, sizeof( U32 ), 8, fp ) ) != 8 ) { + printf( "write_ras: can't write header to %s\n", filename ); + exit( 1 ); + } + + /* write the color map */ + if( header.ras_maplength ) { + for( i = 0; i < 256; i++ ) + map[i] = ( unsigned char )i; + for( i = 0; i < 3; i++ ) { + if( fwrite( map, sizeof( unsigned char ), 256, fp ) != 256 ) { + printf( "write_ras: can't write colormap to %s(gray)\n", filename ); + exit( 1 ); + } + } + } + + /* write the image data */ + ver = header.ras_height; + hor = header.ras_width; + if( ( header.ras_type == RT_STANDARD ) + || ( header.ras_type == RT_FORMAT_RGB ) ) { + if( header.ras_depth == GRAYDATA ) + length = hor * ver; + else if( header.ras_depth == RGBDATA ) + length = 3 * hor * ver; + + if( ( write = + fwrite( frame, sizeof( unsigned char ), length, fp ) ) != length ) { + printf( "write_ras: can't write data of %s write %d length %d\n", + filename, write, length ); + exit( 1 ); + } + } else { + printf( "write_ras: input file is not standard file\n" ); + exit( 1 ); + } + + /* file close */ + fclose( fp ); +} + +/*****************************************************************************/ +/* read_ras() */ +/*****************************************************************************/ +struct rasterfile * +read_ras( char *filename, unsigned char **frame ) +{ + FILE *fp; + int i, ver, hor; + unsigned char map[256], index; + int length; + U32 *p; + struct rasterfile *header; + + /* open the file */ + if( ( fp = fopen( filename, "rb" ) ) == NULL ) { + printf( "read_ras: can't open %s for reading\n", filename ); + exit( 1 ); + } + + p = ( U32 * ) getarray( 8, sizeof( U32 ), "p" ); + /* read the file header */ + if( fread( p, sizeof( U32 ), 8, fp ) != 8 ) { + printf( "read_ras: can't read header to %s (read_ras)\n", filename ); + exit( 1 ); + } + for( i = 0; i < 8; i++ ) { + p[i] = exchange_4byte_order( p[i] ); + } + header = ( struct rasterfile * )p; + + //printf("maplength %d\n", header->ras_maplength); + /* read the color map */ + if( header->ras_maplength ) { + for( i = 0; i < header->ras_maplength / 3; i++ ) + map[i] = ( unsigned char )i; + for( i = 0; i < 3; i++ ) { + if( fread( map, sizeof( unsigned char ), header->ras_maplength / 3, fp ) + != ( unsigned )header->ras_maplength / 3 ) { + printf( "read_ras: can't read colormap to %s(gray)\n", filename ); + exit( 1 ); + } + } + } + + /* read the image data */ + ver = header->ras_height; + hor = header->ras_width; + //if((header->ras_type == RT_STANDARD) || (header->ras_type == RT_FORMAT_RGB)){ + if( 1 ) { + if( header->ras_depth == GRAYDATA ) + length = hor * ver; + else if( header->ras_depth == RGBDATA ) + length = 3 * hor * ver; + + *frame = + ( unsigned char * )getarray( length, sizeof( unsigned char ), + "*frame" ); + if( fread( *frame, sizeof( unsigned char ), length, fp ) != + ( unsigned )length ) { + printf( "read_ras: can't read data of %s(read_ras)\n", filename ); + exit( 1 ); + } + if( header->ras_depth == GRAYDATA ) { //printf("gray(ras_util.c)"); + for( i = 0; i < length; i++ ) { + index = ( *frame )[i]; + ( *frame )[i] = map[index]; + } + } + } else { + printf( "read_ras: input file is not standard file\n" ); + exit( 1 ); + } + + /* file close */ + fclose( fp ); + + return ( header ); +} + + +struct rasterfile * +read_charimg24( char *name, unsigned char **img ) +{ + struct rasterfile *rhead = NULL; + FILE *fp; + int nn_3, i, tt; + unsigned char *buffer = NULL; + U32 *p; + + + + /* open file stream to read */ + if( !name ) { + fp = stdin; + } else if( ( fp = fopen( name, "rb" ) ) == NULL ) { + fprintf( stderr, "read_charimg24: can't open %s for read\n", name ); + exit( 1 ); + } + + + /* read in ras header */ + rhead = + ( struct rasterfile * )getarray( 1, sizeof( struct rasterfile ), + "rhead" ); + if( fread( ( char * )rhead, sizeof( struct rasterfile ), 1, fp ) != 1 ) { + fprintf( stderr, "read_charimg: can't read ras header of %s\n", name ); + exit( 1 ); + } + p = ( U32 * ) rhead; + for( i = 0; i < 8; i++ ) { + p[i] = exchange_4byte_order( p[i] ); + } + rhead = ( struct rasterfile * )p; + + if( rhead->ras_type != RT_STANDARD || rhead->ras_depth != 24 ) { + fprintf( stderr, "read_charimg24: Mismatch image read types\n" ); + exit( -1 ); + } + if( rhead->ras_maplength != 0 ) { + fseek( fp, ( long )rhead->ras_maplength, 1 ); + } + nn_3 = 3 * rhead->ras_width * rhead->ras_height; + + + /* allocate memory for image */ + buffer = + ( unsigned char * )getarray( nn_3, sizeof( unsigned char ), "buffer" ); + + + /* read in image into buffer */ + if( ( tt = fread( buffer, sizeof( unsigned char ), nn_3, fp ) ) != nn_3 ) { + fprintf( stderr, "Error reading %s %d %d \n", name, tt, nn_3 ); + exit( -1 ); + } + fclose( fp ); + + + *img = buffer; + return ( rhead ); +} diff --git a/Interframe EZBC/TempSub/src/showtime.c b/Interframe EZBC/TempSub/src/showtime.c new file mode 100644 index 0000000..aeb7fc6 --- /dev/null +++ b/Interframe EZBC/TempSub/src/showtime.c @@ -0,0 +1,28 @@ +#include +#include + +void +print_time( double sc ) +{ + int hr, mn; + hr = ( int )( sc / 3600.0 ); + sc -= 3600.0 * hr; + mn = ( int )( sc / 60.0 ); + sc -= 60.0 * mn; + + if( hr ) { + printf( "%d hour", hr ); + if( hr > 1 ) + printf( "s, " ); + else + printf( ", " ); + } + if( ( hr ) || ( mn ) ) { + printf( "%d minute", mn ); + if( mn > 1 ) + printf( "s, and " ); + else + printf( ", and " ); + } + printf( "%5.2f seconds.\n", sc ); +} diff --git a/Interframe EZBC/TempSub/src/simul_func.cpp b/Interframe EZBC/TempSub/src/simul_func.cpp new file mode 100644 index 0000000..af753ea --- /dev/null +++ b/Interframe EZBC/TempSub/src/simul_func.cpp @@ -0,0 +1,516 @@ +#include +#include +#include +#include +#include +#define EXTERN extern +#include "structN.h" +#include "coderN.h" +#include "miscN.h" +#include "ioN.h" +#include "pstatN.h" +#include "basic.h" +#include "dpx.h" +#include "zlib.h" // zip-Library +#include "general.h" + +#define INVALID_AGP_EXIST 10 +#define INVALID_LAYER_EXIST 10 +#define INVALID_BI_MV -1 +#define MV_PERCENT_THERSH 0.55 // the threshold for motion vector percentage + // above the threshold we discard some sub-symbols + +int read_number_core( FILE * fp ); + +unsigned int read_number_sub( FILE * fp ); + +void write_number_sub(unsigned int outputbyte, FILE * fp ); + +void write_number_core( int outputbyte, FILE * fp ); +int read_GOPheader( enum FLAG **dec_scene_change, videoinfo info ); +int bit_alloc_VBR( videoinfo info, unsigned char *qp, + long int sum_mv, long int overhead ); +int bit_alloc_CBR( videoinfo info, unsigned char *qp, + long int overhead, unsigned long *gop_sum_mv, int curr_last ); +int bit_alloc_VBR_v2( videoinfo info, unsigned char *qp, long int overhead, + unsigned long *gop_sum_mv, int curr_last, int vbr_bound ); + +int simulcast_pull( char *pre_stream, char *bit_alloc_name, + int t_level, int s_level, int kbps, + int qp ); + +void +pull_usage( ) +{ + printf( "pull pre_encoded_stream -t t_level -s s_level -r kbps [-C]\n" ); +} + +void +read_command( int argc, char **argv, short int *t_level, short int *s_level, + int *kbps, int *AGP_exist, int *layer_exist, int *bi_exist, + char *pre_stream, enum FLAG *CBR, enum FLAG *list, + char *list_name) +{ + int i, j, k, argnum = 1; + + *CBR = NO; + *list = NO; + *t_level = 0; + *s_level = 0; + list_name[0] = '\0'; + // how many sub-symbols exist + for (j = 0; j < MAX_TLEVELS; j++) + { + AGP_exist[j] = INVALID_AGP_EXIST; + layer_exist[j] = INVALID_LAYER_EXIST; + bi_exist[j] = INVALID_BI_MV; + } + + for( i = 1; i < argc; i++ ) { + if( *( argv[i] ) == '-' ) { + + switch ( *( ++argv[i] ) ) { + default: + printf( "-%c such an option is not available\n", *( argv[i] ) ); + pull_usage( ); + exit( 1 ); + case 'h': + pull_usage( ); + exit( 1 ); + break; + + case 'y': // the parameter for layer structure + j = 0; + while (j < MAX_TLEVELS ) { + layer_exist[j] = atoi( argv[++i] ); + j++; + if ( i==argc-1 ) // no more parameters + break; + if ( *( argv[i+1] ) == '-' ) // next parameter + break; + } + if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of layer_exist values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + layer_exist[k] = layer_exist[k-1]; + } + break; + + case 'a': // the parameter for AGP + j = 0; + while (j < MAX_TLEVELS ) { + AGP_exist[j] = atoi( argv[++i] ); + j++; + if ( i==argc-1 ) // no more parameters + break; + if ( *( argv[i+1] ) == '-' ) // next parameter + break; + } + if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of AGP_exist values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + AGP_exist[k] = AGP_exist[k-1]; + } + break; + case 'b': // the parameter for bi-directional motion field + j = 0; + while (j < MAX_TLEVELS ) { + bi_exist[j] = atoi( argv[++i] ); + j++; + if ( i==argc-1 ) // no more parameters + break; + if ( *( argv[i+1] ) == '-' ) // next parameter + break; + } + if (j == MAX_TLEVELS) { + printf("WARNING: Maxmimum number of bi_mv values reached!\n"); + } + for (k = j; k < MAX_TLEVELS; k++) { + bi_exist[k] = bi_exist[k-1]; + } + break; + + case 't': + *t_level = atoi( argv[++i] ); + break; + case 's': + *s_level = atoi( argv[++i] ); + break; + case 'r': + *kbps = atoi( argv[++i] ); + break; + case 'C': + *CBR = YES; + break; + case 'l': // name of list file for static output rates + strcpy( list_name, argv[++i] ); + break; + case 'n': // flag for display target rate list + *list = YES; + break; + } + } else { + switch ( argnum ) { + default: + printf( "more parameters are specified\n" ); + pull_usage( ); + exit( 1 ); + case 1: + strcpy( pre_stream, argv[i] ); + argnum++; + break; + } + } + } + +} + + +int +read_listfile( char *list_name, unsigned short int *list_rates, unsigned char *list_tlevel, + unsigned char *list_slevel, unsigned char *list_simulcast, + char **list_simulname, videoinfo info ) +{ + int i, counter = 0, rate = 0, tlevel = 0, slevel = 0, simulcast = 0; + char iline[256], token[80]; + FILE *fplist; + + if( !( fplist = fopen( list_name, "rb" ) ) ) { + printf( "can not open: %s\n", list_name ); + exit( 1 ); + } + + while( fgets( iline, 254, fplist ) ){ + sscanf( iline, "%s", token ); + + if( !strcmp( token, "-listitem" ) ) { + sscanf( iline, "%s%d%d%d%d%s", token, &tlevel, &slevel, + &rate, &simulcast, list_simulname[counter] ); + list_tlevel[counter] = tlevel; + list_slevel[counter] = slevel; + list_rates[counter] = rate; + list_simulcast[counter] = simulcast; + counter++; + } + } + if ( counter == 0 ){ + printf( "no listitems in: %s\n", list_name ); + exit( 1 ); + } + + for ( i = 1; i < counter; i++ ){ + if ( list_tlevel[i] < info.t_level ){ + printf( "target t_level too low in: %s\n", list_name ); + exit( 1 ); + } + if ( list_slevel[i] < info.s_level ){ + printf( "target s_level too low in: %s\n", list_name ); + exit( 1 ); + } + if ( list_rates[i] >= info.bitrate ){ + printf( "target rate too high in: %s\n", list_name ); + exit( 1 ); + } + } + + fclose( fplist ); + + return counter; +} + + +unsigned long int +read_mv_bytes( char *seq_name, videoinfo info, int AGP_sign, int layer_sign, + unsigned long int *exist_sum_mv ) +{ + int j, k, remaining_frs, curr, last; + int mv, mv1, mv2, GOPsz, eff_GOPsz[20]; + unsigned long int sum_mv; + char mvstatname[250]; + FILE *FID; + int major_mv, sign_bytes, sub_bit, sub_mv, total_mv ; + + GOPsz = info.GOPsz; + + // determine effective GOP size in level j + for( j = 0; j < info.tPyrLev; j++ ) { + eff_GOPsz[j] = GOPsz; + GOPsz /= 2; + } + + curr = info.start; + last = info.last; + // *exist_sum_mv: the number of existing motion vector bytes up to this temporal level + sum_mv = *exist_sum_mv = 0; + sprintf( mvstatname, "%s.mvby", seq_name ); // Hanke, 16.09.02 + FID = fopen( mvstatname, "rb" ); + if( FID == NULL ) { + printf( "can not open file mvby\n" ); + exit( 1 ); + } + + while( curr <= last ) { + remaining_frs = last - curr + 1; + + for( j = info.tPyrLev - 1; j >= 0; j-- ) { + + if ( info.bi_exist[j] ) // bi-directional motion field + { + for( k = 0; k <= eff_GOPsz[j]; k++ ) { + + // scalable motion vector coding +// printf("eff_GOPsz[j] = %d\n",eff_GOPsz[j]); + + if ( !AGP_sign && !layer_sign) // no AGP, no layer structure + { + fscanf( FID, "%d\n", &mv ); + if( j >= info.t_level ) + { + sum_mv += mv; + *exist_sum_mv += mv; // here *exist_sum_mv is the same as sum_mv + } + } + + if ( AGP_sign && !layer_sign ) // AGP, no layer structure + { + fscanf( FID, "%d ", &major_mv ); + if (major_mv==0) continue; // no motion vector, i.e. scene change + if( j >= info.t_level ) sum_mv += major_mv; // major_mv is always necessary + if (info.AGP_level[j]) // AGP in this temporal level + { + fscanf( FID, "%d ", &sign_bytes); + if (info.AGP_exist[j] && j >= info.t_level ) sum_mv += sign_bytes; + for (sub_bit=0; sub_bit= info.t_level ) sum_mv += sub_mv; + } + fscanf( FID, "%d ", &total_mv); // total bytes for this set of motion vectors + if (j>=info.t_level) *exist_sum_mv += total_mv ; + }else + if (j>=info.t_level) *exist_sum_mv += major_mv ; + } + + if ( !AGP_sign && layer_sign ) // no AGP, layer structure + { + fscanf( FID, "%d ", &major_mv ); + if (major_mv==0) continue; // no motion vector, i.e. scene change + if( j >= info.t_level ) sum_mv += major_mv; // major_mv is always necessary + if (info.layer_mv[j]) // layer structure in this temporal level + { + fscanf( FID, "%d ", &sub_mv); + if (info.layer_exist[j] && j >= info.t_level ) sum_mv += sub_mv; + fscanf( FID, "%d ", &total_mv); // total bytes for this set of motion vectors + if (j>=info.t_level) *exist_sum_mv += total_mv ; + }else + if (j>=info.t_level) *exist_sum_mv += major_mv ; + } + + if ( AGP_sign && layer_sign ) // AGP, layer structure + { + fscanf( FID, "%d ", &major_mv ); + if (major_mv==0) continue; // no motion vector, i.e. scene change + if( j >= info.t_level ) sum_mv += major_mv; // major_mv is always necessary + if (info.AGP_level[j]) // AGP in this temporal level + { + fscanf( FID, "%d ", &sign_bytes); + if (info.AGP_exist[j] && j >= info.t_level ) sum_mv += sign_bytes; + for (sub_bit=0; sub_bit= info.t_level ) sum_mv += sub_mv; + } + } + + if ( info.layer_mv[j]) + { + fscanf( FID, "%d ", &sub_mv); + if ( info.layer_exist[j] && j >= info.t_level ) sum_mv += sub_mv; + if ( info.AGP_level[j]) + { + fscanf( FID, "%d ", &sign_bytes); + if (info.AGP_exist[j] && j >= info.t_level ) sum_mv += sign_bytes; + for (sub_bit=0; sub_bit= info.t_level ) sum_mv += sub_mv; + } + } + + } + + if ( info.layer_mv[j] || info.AGP_level[j] ) + { + fscanf( FID, "%d ", &total_mv); // total bytes for this set of motion vectors + if (j>=info.t_level) *exist_sum_mv += total_mv ; + }else + if (j>=info.t_level) *exist_sum_mv += major_mv ; + } + + } + } // if ( info.bi_exist[j] ) + + + // alternative Haar reconstruction + if ( ! info.bi_exist[j] ) // not bi-directional motion field, alternative reconstruction with Harr + { + assert(0); + k=0; + while ( k <= eff_GOPsz[j] ) + { + if (AGP_sign==0) // without AGP ( non-scalable motion vectors ) + { + if (k==0) // the first set of motion vectors are always 0 + { + fscanf( FID, "%d\n", &mv ); + assert(mv==0); + k++; + }else + { + fscanf( FID, "%d\n", &mv1 ); // left set mv + k++; + fscanf( FID, "%d\n", &mv2 ); // right set mv + k++; + if( j >= info.t_level ) + { + // bi-directional motion vector or left set motion vector + if ( ( mv1 && mv2 ) || ( mv1 && !mv2) ) + { + sum_mv += mv1; // only left set is reserved finally + *exist_sum_mv += mv1+mv2; + } + + if (!mv1 && mv2) // right set motion vector + { + sum_mv += mv2; + *exist_sum_mv += mv1+mv2; + } + } + } + }else // with AGP + { + + } // with AGP + } + } // if ( ! info.bi_mv[j] ) + + } + + curr += info.GOPsz; + } + fclose( FID ); + + return sum_mv; +} + + +void +gop_read_mv_bytes( char *seq_name, videoinfo info, int AGP_sign, int layer_sign, + unsigned long int *gop_exist_sum_mv, int num_of_GOP, unsigned long int *gop_sum_mv ) +{ + int i, j, k, remaining_frs, curr, last; + int mv, mv1, mv2, GOPsz, eff_GOPsz[20]; + unsigned long int sum_mv; + char mvstatname[250]; + FILE *FID; + int major_mv, sign_bytes, sub_bit, sub_mv, total_mv ; + + GOPsz = info.GOPsz; + + // determine effective GOP size in level j + for( j = 0; j < info.tPyrLev; j++ ) { + eff_GOPsz[j] = GOPsz; + GOPsz /= 2; + } + + curr = info.start; + last = info.last; + + assert( (last - curr + 1) == num_of_GOP*info.GOPsz ); + + + + // *exist_sum_mv: the number of existing motion vector bytes up to this temporal level + sum_mv = *gop_exist_sum_mv = 0; + sprintf( mvstatname, "%s.mvby", seq_name ); // Hanke, 16.09.02 + FID = fopen( mvstatname, "rb" ); + if( FID == NULL ) { + printf( "can not open file mvby\n" ); + exit( 1 ); + } + + for(i = 0; i < num_of_GOP; i ++){ + gop_sum_mv[i] = 0; + } + + i = 0; + + while( curr <= last ) { + remaining_frs = last - curr + 1; + + for( j = info.tPyrLev - 1; j >= 0; j-- ) { + + if ( info.bi_exist[j] ) // bi-directional motion field + { + for( k = 0; k <= eff_GOPsz[j]; k++ ) { + + // scalable motion vector coding + + if ( !AGP_sign && !layer_sign) // no AGP, no layer structure + { + fscanf( FID, "%d\n", &mv ); + if( j >= info.t_level ) + { + sum_mv += mv; + gop_sum_mv[i] += mv; // here *exist_sum_mv is the same as sum_mv + } + } + + } + } // if ( info.bi_exist[j] ) + + } + + curr += info.GOPsz; + i ++; + } + fclose( FID ); + +} + +// automatically allocate the bits between motion vector and subband data +// according to some empirically bit-allcoation model +void automatic_bit_allocation_with_AGP(unsigned long int *sum_mv, videoinfo *info, + char *seq_name, int AGP_sign, int layer_sign) +{ + double budget; + double mv_percent; + videoinfo info_bak; + unsigned long int exist_sum_mv; + int i; + + budget = ( double )info->bitrate * 1000 / 8 * ( info->last - info->start + 1 ) / info->framerate; + mv_percent = *sum_mv/budget; // the percentage of motion vector bytes in the available budget + if (mv_percent<=MV_PERCENT_THERSH) + return; // tolerable percentage according empirical bit allocation model + else + { + // discard motion vector sub-symbols starting from the top temporal level + for (i=info->t_level; i<=info->tPyrLev-1; i++) + { + while (info->AGP_exist[i]>0 && mv_percent>MV_PERCENT_THERSH) + { + (info->AGP_exist[i])--; + info_bak = *info; + *sum_mv = read_mv_bytes( seq_name, info_bak, AGP_sign, layer_sign, &exist_sum_mv ); + mv_percent = *sum_mv/budget; + } + if (mv_percent<=MV_PERCENT_THERSH) + return; + } + for (i=info->t_level; i<=info->tPyrLev-1; i++) + assert( info->AGP_exist[i]==0 ); + } +} \ No newline at end of file diff --git a/Interframe EZBC/TempSub/src/simul_pull.c b/Interframe EZBC/TempSub/src/simul_pull.c new file mode 100644 index 0000000..d19d43e --- /dev/null +++ b/Interframe EZBC/TempSub/src/simul_pull.c @@ -0,0 +1,509 @@ +#include +#include +#include +#include +#include + +#include "structN.h" + +#include "zlib.h" +#include "dpx.h" + +#define EXTERN extern +#include "coderN.h" +#include "miscN.h" +#include "ioN.h" +#include "pstatN.h" +#include "basic.h" + +#define INVALID_AGP_EXIST 10 +#define INVALID_LAYER_EXIST 10 +#define INVALID_BI_MV -1 +#define MV_PERCENT_THERSH 0.55 // the threshold for motion vector percentage + // above the threshold we discard some sub-symbols + +int read_number_core( FILE * fp ); + +unsigned int read_number_sub( FILE * fp ); + +void write_number_sub(unsigned int outputbyte, FILE * fp ); + +int GOP_motion_bytes; + + +void write_number_core( int outputbyte, FILE * fp ); +int read_GOPheader( enum FLAG **dec_scene_change, videoinfo info ); +int read_substream_length( int *length, FILE * fp ); +int write_substream_length( int length, FILE * fp ); +int bit_alloc_VBR( videoinfo info, unsigned char *qp, + long int sum_mv, long int overhead ); +int bit_alloc_CBR( videoinfo info, unsigned char *qp, + long int overhead, unsigned long *gop_sum_mv, int curr_last ); +int bit_alloc_VBR_v2( videoinfo info, unsigned char *qp, long int overhead, + unsigned long *gop_sum_mv, int curr_last, int vbr_bound ); + +int simulcast_pull( char *pre_stream, char *bit_alloc_name, + int t_level, int s_level, int kbps, + int qp ); + +// process major section for motion vector +void process_mv_section(long int mvBytes, FILE *outfp, long int *out_bytes, long int *total_mv_bytes, + long int *in_bytes, FILE *fpbit, FILE *fptab, enum FLAG pulled_bitstream) +{ + unsigned char *data; + + write_number_core( mvBytes, outfp ); + *out_bytes += 4; + *total_mv_bytes += 4; + data = ( unsigned char * )getarray( mvBytes, sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), mvBytes, fpbit ) != ( unsigned )mvBytes ) { + printf( "fread error2 %d\n", mvBytes ); + exit( 1 ); + } + *in_bytes += mvBytes; + fwrite( data, sizeof( unsigned char ), mvBytes, outfp ); + *out_bytes += mvBytes; + *total_mv_bytes += mvBytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% motion_bytes\n", mvBytes + 4 ); + GOP_motion_bytes += mvBytes; + } + free( data ); +} + +// get one section of bits for AGP +void get_bytes_section(FILE *fpbit, FILE *outfp, FILE * fptab, int write_sign, long int *in_bytes, long int *out_bytes, + long int *total_mv_bytes, enum FLAG pulled_bitstream ) +{ + unsigned int section_Bytes; + unsigned char *data; + + section_Bytes = read_number_sub( fpbit ); // fpbit will move forward by 2 bytes + *in_bytes += 2; + if ( write_sign ) + { + write_number_sub( section_Bytes, outfp ); + *out_bytes += 2; + *total_mv_bytes +=2; + data = ( unsigned char * )getarray( section_Bytes, sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), section_Bytes, fpbit ) != ( unsigned )section_Bytes ) { + printf( "fread error2 %d\n", section_Bytes ); + exit( 1 ); + } + *in_bytes += section_Bytes; + fwrite( data, sizeof( unsigned char ), section_Bytes, outfp ); + *out_bytes += section_Bytes; + *total_mv_bytes += section_Bytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% motion_bytes\n", section_Bytes + 2 ); + GOP_motion_bytes += section_Bytes; + } + free( data ); + } else { + fseek( fpbit, section_Bytes, SEEK_CUR ); + in_bytes += section_Bytes; + } +} + +// get the section for enhancement layer +void get_bytes_section_enhance(FILE *fpbit, FILE *outfp, FILE * fptab, int write_sign, long int *in_bytes, long int *out_bytes, + long int *total_mv_bytes, enum FLAG pulled_bitstream ) +{ + unsigned int enhance_Bytes; + unsigned char *data; + + enhance_Bytes = read_number_core( fpbit ); // fpbit will move forward by 2 bytes + *in_bytes += 4; + if ( write_sign ) + { + write_number_core( enhance_Bytes, outfp ); + *out_bytes += 4; + *total_mv_bytes +=4; + data = ( unsigned char * )getarray( enhance_Bytes, sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), enhance_Bytes, fpbit ) != ( unsigned )enhance_Bytes ) { + printf( "fread error2 %d\n", enhance_Bytes ); + exit( 1 ); + } + *in_bytes += enhance_Bytes; + fwrite( data, sizeof( unsigned char ), enhance_Bytes, outfp ); + *out_bytes += enhance_Bytes; + *total_mv_bytes += enhance_Bytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% motion_bytes\n", enhance_Bytes + 4 ); + GOP_motion_bytes += enhance_Bytes; + } + free( data ); + } else { + fseek( fpbit, enhance_Bytes, SEEK_CUR ); + in_bytes += enhance_Bytes; + } +} + + +void test( videoinfo info, unsigned char *qp, int estimated_overhead, unsigned long int *gop_mv, int curr_last, int type ){ + + int i, j, k, nm, curr, last, num_of_GOP, GOPheader_bytes, Per_GOPheader_bytes, FAT_bytes; + int count = 0, remaining_frs, num_subband, bytes, mvBytes; + int kbps = 0, tmp, GOPsz, eff_GOPsz, is_pullable; + int *subband_fat, *newsubband_fat; + long int in_bytes = 0, out_bytes = 0, FAT_start = 0, overhead_start; + long int overhead = 0, total_mv_bytes = 0; + long int subband_bytes = 0, total_subband_bytes = 0, *newfat; + short int t_level, s_level, rel_s_level, target_rate; + int counter, buffer; + + int getnum; + enum FLAG CBR = YES; + + unsigned char *data; + char pre_stream[256], post_stream[256], overhead_stream[256]; + char seq_name[256], bit_alloc_name[256], bit_alloc_table[256]; + + unsigned char list_tlevel[25], list_slevel[25], list_qp[25], list_simulcast[25]; + unsigned short int list_rates[25], simul_bitstream = 0; + unsigned long int sum_mv, exist_sum_mv[10], list_out_bytes[25], simul_bitstream_pos = 0; + + enum FLAG pulled_bitstream; + FILE *outfp, *fpbytes, *fptab, *fphead; + int AGP_sign, sub_bit, AGP_exist_pull[MAX_TLEVELS], bi_exist[MAX_TLEVELS]; + long int major_mvBytes; + enum FLAG scene_change_left, scene_change_right; + int layer_sign, layer_exist_pull[MAX_TLEVELS]; + + int GOP_subband_bytes; + + pulled_bitstream = NO; + + in_bytes += sizeof( videoheader ); + num_of_GOP = (info.last - info.start + info.GOPsz) / info.GOPsz; +// printf("num_of_GOP = %d\n",num_of_GOP); + + strncpy( seq_name, info.bitname, strlen( info.bitname ) - 4 ); + seq_name[strlen( info.bitname ) - 4] = '\0'; + + // GOPheader_bytes (cmp. mvcoding.c) + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + for( j = 0; j < GOPsz; j++ ) + count++; + GOPsz /= 2; + } + GOPsz = info.GOPsz; + GOPheader_bytes = (( count + 7 ) / 8) * num_of_GOP; + + Per_GOPheader_bytes = GOPheader_bytes / num_of_GOP; + + // FAT bytes + FAT_bytes = num_of_GOP * sizeof( long int ); // DENOISE ? -> only larger values + + if(type == 0) + is_pullable = bit_alloc_CBR(info, qp, estimated_overhead, gop_mv, curr_last); + else{ + assert(type == 1); + + sum_mv = 0; + counter = 0; + curr = 0; + last = curr_last - info.start; + + while( curr <= last ){ + sum_mv += gop_mv[counter]; + printf("gop_counter = %d, gop_sum_mv = %d\n",counter,gop_mv[counter]); + counter ++; + curr += info.GOPsz; + } + + buffer = info.last; + info.last = curr_last; + is_pullable = bit_alloc_VBR_v2(info, qp, estimated_overhead, gop_mv, curr_last, curr_last - info.GOPsz); + info.last = buffer; + } + + sprintf( bit_alloc_table, "%s_%d.alloc_table", seq_name, info.bitrate ); + if( !( fptab = fopen( bit_alloc_table, "wb" ) ) ) { + printf( "can not open: %s\n", bit_alloc_table ); + exit( 1 ); + } + + if( !is_pullable ){ + printf("bitstream is not pullable!\n"); + exit(1); + } +// + if( !( fpbit = fopen( info.bitname, "rb" ) ) ) { + printf( "can not open: %s\n", info.bitname ); + exit( 1 ); + } + + sprintf( post_stream, "%s_%d.bit", seq_name, info.bitrate ); + + write_header( post_stream, info ); + out_bytes += sizeof( videoheader ); + + if( !( outfp = fopen( post_stream, "r+b" ) ) ) { + printf( "can not open: %s\n", post_stream ); + exit( 1 ); + } + + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%%---------------------------------------------------------------\n" ); + fprintf( fptab, "%s %% sequence_name\n", seq_name ); + fprintf( fptab, "%03d \t %% sequence_length\n", info.last - info.start + 1 ); + fprintf( fptab, "%03d \t %% start\n", info.start ); + fprintf( fptab, "%03d \t %% last\n", info.last ); + fprintf( fptab, "%d \t %% bit_rate\n", info.bitrate ); + fprintf( fptab, "%0.2f\t %% frame_rate\n", + ((double)(info.framerate) / pow((float)2, info.t_level))); + fprintf( fptab, "%d \t %% t_level\n", info.t_level ); + fprintf( fptab, "%d \t %% Y_size_x\n", info.ywidth >> rel_s_level); + fprintf( fptab, "%d \t %% Y_size_y\n", info.yheight >> rel_s_level); + fprintf( fptab, "%d \t %% C_size_x\n", info.cwidth >> rel_s_level); + fprintf( fptab, "%d \t %% C_size_y\n", info.cheight >> rel_s_level); + fprintf( fptab, "%d \t %% s_level\n", info.s_level ); + fprintf( fptab, "%d \t %% number_of_GOP\n", num_of_GOP ); + fprintf( fptab, "%d \t %% header/fat_size\n", + sizeof( videoheader ) + FAT_bytes + GOPheader_bytes ); + fprintf( fptab, "%ld \t %% overhead_size\n", estimated_overhead + - (sizeof( videoheader ) - FAT_bytes - GOPheader_bytes) ); + fprintf( fptab, "---------------------------------------------------------------\n" ); + } + + + /*******/ + /* FAT */ + /*******/ + newfat = ( long int * )getarray( num_of_GOP, sizeof( long int ), "newfat" ); + + //skip FAT + in_bytes += num_of_GOP * sizeof( long int ); + fseek( fpbit, in_bytes, SEEK_SET ); + + fseek( outfp, out_bytes, SEEK_SET ); + fwrite( newfat, sizeof( long int ), num_of_GOP, outfp ); + FAT_start = out_bytes; + out_bytes += num_of_GOP * sizeof( long int ); + overhead = out_bytes; + + simul_scene_change = + ( enum FLAG ** )getarray( info.tPyrLev, sizeof( enum FLAG * ), + "simul_scene_change" ); + GOPsz = info.GOPsz; + for( i = 0; i < info.tPyrLev; i++ ) { + simul_scene_change[i] = + ( enum FLAG * )getarray( GOPsz + 1, sizeof( enum FLAG ), "simul_scene_change" ); + GOPsz /= 2; + } + + curr = info.start; + last = curr_last; + + int GOPcounter = 0; + + sprintf( bit_alloc_name, "%s_%d.bytes_per_GOP", seq_name, info.bitrate ); + if( CBR == NO || CBR == YES ) { + if( !( fpbytes = fopen( bit_alloc_name, "rb" ) ) ) { + printf( "can not open %s\n", bit_alloc_name ); + exit( 1 ); + } + } + + fscanf( fpbytes, "%d\n", &num_subband ); + + subband_fat = + ( int * )getarray( num_subband, sizeof( int ), "subband_fat" ); + newsubband_fat = + ( int * )getarray( num_subband, sizeof( int ), "newsubband_fat" ); + + while( curr <= last ) { /* MCTF decoding */ + + remaining_frs = last - curr + 1; //printf("remaining frames = %d\n", remaining_frs); + + if ( remaining_frs < info.GOPsz ){ + // Level_change = YES; + info.eff_GOPsz = remaining_frs; + } else { + // Level_change = NO; // full GOP + info.eff_GOPsz = info.GOPsz; // effective GOP size + } + +// printf( " pulling GOP %d: frame %d - %d\n", GOPcounter, +// curr, curr + info.eff_GOPsz - 1 ); + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%% GOP %2d %% frame %d - %d\n", GOPcounter, + curr, curr + info.eff_GOPsz - 1 ); + } + + GOPheader_bytes = 0; + if( info.tPyrLev >= 1 ) { + + /*************/ + /* GOPheader */ + /*************/ + + GOPheader_bytes = read_GOPheader( simul_scene_change, info ); //printf("GOPheader_bytes = %d\n", GOPheader_bytes); + fseek( fpbit, -GOPheader_bytes, SEEK_CUR ); + + data = + ( unsigned char * )getarray( GOPheader_bytes, sizeof( unsigned char ), + "data" ); + if( fread( data, sizeof( unsigned char ), GOPheader_bytes, fpbit ) != + ( unsigned )GOPheader_bytes ) { + printf( "fread error1 \n" ); + exit( 1 ); + } + in_bytes += GOPheader_bytes; + + fwrite( data, sizeof( unsigned char ), GOPheader_bytes, outfp ); + out_bytes += GOPheader_bytes; + overhead += GOPheader_bytes; + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%d \t %% GOPheader_bytes\n", GOPheader_bytes ); + } + free( data ); + + /******/ + /* MV */ + /******/ + + AGP_sign = 0; + layer_sign = 0; + + GOP_motion_bytes = 0; //Added on 10.06.2017 + + GOPsz = 2; + for( j = info.tPyrLev - 1; j >= 0; j-- ) { + + if (info.bi_exist[j]) // bi-directional motion field + { + for( k = 0; k <= GOPsz; k++ ) { + if( simul_scene_change[j][k] == NO ) { + + // scalable motion vector coding: AGP and layer structure + + if ( !AGP_sign && !layer_sign ) // no AGP, no layer structure + { + mvBytes = read_number_core( fpbit ); // fpbit will move forward by 4 bytes + in_bytes += 4; + +// printf("mvBytes = %d\n",mvBytes); + +// printf("mvBytes = %d\n",mvBytes); + if( j >= info.t_level ) { // temporal scalability + process_mv_section(mvBytes, outfp, &out_bytes, &total_mv_bytes, &in_bytes, fpbit, + fptab, pulled_bitstream); + } else { + fseek( fpbit, mvBytes, SEEK_CUR ); + in_bytes += mvBytes; + } + } + } + } + } // if (info.bi_mv[j]) + + GOPsz *= 2; + } // for( j = info.tPyrLev - 1; j >= 0; j-- ) + + fprintf(fptab, "%ld \t %% GOP motion_bytes\n", GOP_motion_bytes); + + } + + /*************/ + /* Bitplanes */ + /*************/ + + newfat[GOPcounter] = 0; + + eff_GOPsz = info.eff_GOPsz; + if( info.denoise_flag == YES ) { + eff_GOPsz *= ( YUV420 == 1 ) ? 2 : 4; + } +// printf("num_subband = %d, eff_GOPsz = %d\n",num_subband, eff_GOPsz); + + GOP_subband_bytes = 0; + + for( j = 0; j < eff_GOPsz; j++ ) { + subband_bytes = 0; + for( nm = 0; nm < num_subband; nm++ ) { + // read bit plane + in_bytes += read_substream_length( &subband_fat[nm], fpbit ); + data = + ( unsigned char * )getarray( subband_fat[nm], + sizeof( unsigned char ), "data" ); + if( fread( data, sizeof( unsigned char ), subband_fat[nm], fpbit ) != + ( unsigned )subband_fat[nm] ) { + printf( "read error3 %d %d\n", GOPcounter, subband_fat[nm] ); + exit( 1 ); + } + in_bytes += sizeof( unsigned char ) * subband_fat[nm]; + + // write bit plane + fscanf( fpbytes, "%d\n", &tmp ); +// printf("tmp = %d\n",tmp); + newsubband_fat[nm] = tmp; + if( newsubband_fat[nm] != 0 ) { + if( subband_fat[nm] < newsubband_fat[nm] ) { + newsubband_fat[nm] = subband_fat[nm]; + } + // write subband header + bytes = write_substream_length( newsubband_fat[nm], outfp ); + out_bytes += bytes; + newfat[GOPcounter] += bytes; + subband_bytes += bytes; + total_subband_bytes += bytes; + + if( fwrite + ( data, sizeof( unsigned char ), newsubband_fat[nm], + outfp ) != ( unsigned )newsubband_fat[nm] ) { + printf( "write error %d\n", newsubband_fat[nm] ); + exit( 1 ); + } + out_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + newfat[GOPcounter] += sizeof( unsigned char ) * newsubband_fat[nm]; + subband_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + total_subband_bytes += sizeof( unsigned char ) * newsubband_fat[nm]; + } + free( data ); + } + if ( pulled_bitstream == NO ){ + fprintf( fptab, "%ld \t %% subband_bytes\n", subband_bytes ); + GOP_subband_bytes += subband_bytes; + } + } + + fprintf(fptab, "%ld \t %% GOP subband_bytes\n", GOP_subband_bytes); + +// printf("newfat = %d\n",newfat[GOPcounter]); + + curr += info.GOPsz; + GOPcounter++; + } // while + +// assert((unsigned int)total_mv_bytes==sum_mv[info.t_level]); +// assert((unsigned int)total_mv_bytes<=exist_sum_mv[info.t_level]); + + /*************/ + /* write FAT */ + /*************/ + fseek( outfp, FAT_start, SEEK_SET ); + + if( fwrite( newfat, sizeof( long int ), num_of_GOP, outfp ) != + ( unsigned )num_of_GOP ) { + printf( "write error \n" ); + exit( 1 ); + } + + for( i = 0; i < info.tPyrLev; i++ ) { + free( simul_scene_change[i] ); + } + free( simul_scene_change ); + +/*********************************************/ + fclose( fpbytes ); + fclose( fpbit ); + fclose( outfp ); + fclose( fptab ); + + free( subband_fat ); + free( newsubband_fat ); + free( newfat ); +} \ No newline at end of file diff --git a/Interframe EZBC/TempSub/src/spatial.c b/Interframe EZBC/TempSub/src/spatial.c new file mode 100644 index 0000000..fd24c79 --- /dev/null +++ b/Interframe EZBC/TempSub/src/spatial.c @@ -0,0 +1,150 @@ +#include "stdio.h" +#include "stdlib.h" +#include "basic.h" +#include "structN.h" +#include "Choisubband.h" +#include + + + /*************************************************/ + /* in out */ + /* ----------- ----------- */ + /* | | | | | */ + /* | | | LL | HL | */ + /* | | ----------- */ + /* | | | | | */ + /* | | | LH | HH | */ + /* ----------- ----------- */ + /*************************************************/ +/* + * spatial_anal() + * subband decomposition + * full: input image for analysis + * (hor, ver): size of the full + */ + +void +spatial_anal( float *full, int hor, int ver, float *ll, float *lh, float *hl, + float *hh, int filterType ) +{ + int i, k, l, pos, ppos, sx, sy; + int half_hor, half_ver; + float *image, *subband[4]; // image[comp], subband[comp][sub] + + if( ( hor % 2 != 0 ) || ( ver % 2 != 0 ) ) { + printf( "can not handle this case(encoder.c)\n" ); + exit( 1 ); + } + + half_hor = hor / 2; + half_ver = ver / 2; + + image = ( float * )getarray( hor * ver, sizeof( float ), "image" ); + for( i = 0; i < hor * ver; i++ ) + image[i] = full[i]; + + subband[0] = ll; + subband[1] = lh; + subband[2] = hl; + subband[3] = hh; + + analysis( image, 0, 0, hor, ver, hor, ver, filterType ); // subband.c + + for( i = 0; i < 4; i++ ) { + sx = i / 2; + sy = i % 2; + //printf("sx = %d, sy = %d (encoder.c)\n", sx, sy); + for( k = 0; k < half_ver; k++ ) { + pos = k * half_hor; + ppos = ( sy * half_ver + k ) * hor + sx * half_hor; + + for( l = 0; l < half_hor; l++ ) { + subband[i][pos + l] = image[ppos + l]; + } + } + } + free( image ); +} + +void +spatial_anal_frame( YUVimage_ptr fr, videoinfo info, YUVimage_ptr low, + YUVimage_ptr high0, YUVimage_ptr high1, + YUVimage_ptr high2, int filterType ) +{ + + spatial_anal( fr->Y, info.ywidth, info.yheight, low->Y, + high0->Y, high1->Y, high2->Y, filterType ); + + + if( info.cwidth && info.cheight ) { + spatial_anal( fr->U, info.cwidth, info.cheight, low->U, + high0->U, high1->U, high2->U, filterType ); + + spatial_anal( fr->V, info.cwidth, info.cheight, low->V, + high0->V, high1->V, high2->V, filterType ); + } + +} + +/* + * spatial_syn() + * subband synthesis + * full: result of synthesis + * (hor, ver): size of the full + */ +void +spatial_syn( float *full, int hor, int ver, float *ll, float *lh, float *hl, + float *hh, int filterType ) +{ + int i, k, l, pos, ppos, sx, sy; + int half_hor, half_ver; + float *subband[4]; // image[comp], subband[comp][sub] + + if( ( hor % 2 != 0 ) || ( ver % 2 != 0 ) ) { + printf( "can not handle this case(encoder.c)\n" ); + exit( 1 ); + } + + half_hor = hor / 2; + half_ver = ver / 2; + + + subband[0] = ll; + subband[1] = lh; + subband[2] = hl; + subband[3] = hh; + + for( i = 0; i < 4; i++ ) { + sx = i / 2; + sy = i % 2; + //printf("sx = %d, sy = %d (encoder.c)\n", sx, sy); + for( k = 0; k < half_ver; k++ ) { + pos = k * half_hor; + ppos = ( sy * half_ver + k ) * hor + sx * half_hor; + + for( l = 0; l < half_hor; l++ ) { + full[ppos + l] = subband[i][pos + l]; + } + } + } + + synthesis( full, 0, 0, hor, ver, hor, ver, filterType ); // subband.c +} + + +void +spatial_syn_frame( YUVimage_ptr fr, videoinfo info, YUVimage_ptr low, + YUVimage_ptr high0, YUVimage_ptr high1, YUVimage_ptr high2, + int filterType ) +{ + spatial_syn( fr->Y, info.ywidth, info.yheight, low->Y, + high0->Y, high1->Y, high2->Y, filterType ); + + if( info.cwidth && info.cheight ) { + spatial_syn( fr->U, info.cwidth, info.cheight, low->U, + high0->U, high1->U, high2->U, filterType ); + + spatial_syn( fr->V, info.cwidth, info.cheight, low->V, + high0->V, high1->V, high2->V, filterType ); + } +} diff --git a/Interframe EZBC/TempSub/src/subband_choi.c b/Interframe EZBC/TempSub/src/subband_choi.c new file mode 100644 index 0000000..390c0ec --- /dev/null +++ b/Interframe EZBC/TempSub/src/subband_choi.c @@ -0,0 +1,762 @@ +#include +#include +#include +#include +#include "basic.h" +#include "structN.h" +#include "Choisubband.h" +#define LL 1 +#define HL 2 +#define LH 3 +#define HH 4 + + +int filter_coeff( float **lpf, float **hpf, int filterType, int analsyn ); +void filter_2d( float *obuf, float *ibuf, float *buf1, float *buf2, int lenx, + int leny, float *lpf, float *hpf, int tap, int mode ); +void interpol_2d( float *obuf, float *in, float *ibuf, float *buf1, + float *buf2, float *buf3, float *lpf, float *hpf, int tap, + int lenx, int leny, int sx, int sy, int hor, int mode ); +void filter_1d( float *out, float *in, int length, float *filter, int tap, + int start ); +void filter_1d_normal( float *out, float *in, int length, float *filter, + int tap, int start ); + + +/*****************************************************************************/ +/* analysis() */ +/*****************************************************************************/ +void +analysis( float *in, int sx, int sy, int lenx, int leny, int hor, int ver, + int filterType ) +{ + /*************************************************/ + /* in out */ + /* ----------- ----------- */ + /* | | | | | */ + /* | | | LL | HL | */ + /* | | ----------- */ + /* | | | | | */ + /* | | | LH | HH | */ + /* ----------- ----------- */ + /*************************************************/ + int x, y, pos, ipos, tap; + float *lpf, *hpf; + float *ibuf, *obuf, *buf1, *buf2; + + tap = filter_coeff( &lpf, &hpf, filterType, 0 ); /* filter */ + + ibuf = ( float * )calloc( lenx * leny, sizeof( float ) ); + obuf = ( float * )calloc( lenx * leny, sizeof( float ) ); + buf1 = ( float * )calloc( leny, sizeof( float ) ); + buf2 = ( float * )calloc( leny, sizeof( float ) ); + + /* in--> ibuf */ + /* since inframe is filtered 4 times */ + /* output is saved in inframe, so we need buffer */ + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + pos = y * lenx + x; + ipos = ( y + sy ) * hor + ( x + sx ); + ibuf[pos] = in[ipos]; /* int -> float */ + } + } + + /* LL */ + filter_2d( obuf, ibuf, buf1, buf2, lenx, leny, lpf, hpf, tap, LL ); + for( y = 0; y < leny; y += 2 ) { /* subsampling */ + for( x = 0; x < lenx; x += 2 ) { + pos = y * lenx + x; + ipos = ( y / 2 + sy ) * hor + ( x / 2 + sx ); + in[ipos] = obuf[pos]; + } + } + + // goto stop; + + /* HL */ + filter_2d( obuf, ibuf, buf1, buf2, lenx, leny, lpf, hpf, tap, HL ); + for( y = 0; y < leny; y += 2 ) { /* subsampling */ + for( x = 1; x < lenx; x += 2 ) { + pos = y * lenx + x; + ipos = ( y / 2 + sy ) * hor + ( x / 2 + sx + lenx / 2 ); + in[ipos] = obuf[pos]; + } + } + + /* LH */ + filter_2d( obuf, ibuf, buf1, buf2, lenx, leny, lpf, hpf, tap, LH ); + for( y = 1; y < leny; y += 2 ) { /* subsampling */ + for( x = 0; x < lenx; x += 2 ) { + pos = y * lenx + x; + ipos = ( y / 2 + sy + leny / 2 ) * hor + ( x / 2 + sx ); + in[ipos] = obuf[pos]; + } + } + + /* HH */ + filter_2d( obuf, ibuf, buf1, buf2, lenx, leny, lpf, hpf, tap, HH ); + for( y = 1; y < leny; y += 2 ) { /* subsampling */ + for( x = 1; x < lenx; x += 2 ) { + pos = y * lenx + x; + ipos = ( y / 2 + sy + leny / 2 ) * hor + ( x / 2 + sx + lenx / 2 ); + in[ipos] = obuf[pos]; + } + } + + // stop: printf("only do LL filtering (subband.c)\n"); + + free( ibuf ); + free( obuf ); + free( buf1 ); + free( buf2 ); + free( lpf ); + free( hpf ); + + return; +} + + +/*****************************************************************************/ +/* synthesis() */ +/*****************************************************************************/ +void +synthesis( float *in, int sx, int sy, int lenx, int leny, int hor, int ver, + int filterType ) +{ + /*************************************************/ + /* in out */ + /* ----------- ----------- */ + /* | | | | | */ + /* | LL | HL | | | */ + /* ----------- | | */ + /* | | | | | */ + /* | LH | HH | | | */ + /* ----------- ----------- */ + /*************************************************/ + + int x, y, pos, ipos, tap; + float *lpf, *hpf; + float *ibuf, *obuf, *tbuf, *buf1, *buf2, *buf3; + float *fptr1, *fptr2; + + tap = filter_coeff( &lpf, &hpf, filterType, 1 ); /* filter coefficient */ + + ibuf = ( float * )calloc( lenx * leny, sizeof( float ) ); + obuf = ( float * )calloc( lenx * leny, sizeof( float ) ); + tbuf = ( float * )calloc( lenx * leny, sizeof( float ) ); + buf1 = ( float * )calloc( lenx + tap - 1, sizeof( float ) ); + buf2 = ( float * )calloc( leny + tap - 1, sizeof( float ) ); + buf3 = ( float * )calloc( leny, sizeof( float ) ); + + /* LL */ + interpol_2d( obuf, in, ibuf, buf1, buf2, buf3, lpf, hpf, tap, lenx, leny, + sx, sy, hor, LL ); + fptr1 = tbuf; + fptr2 = obuf; + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + *fptr1++ = 4 * ( *fptr2++ ); + } + } + + /* HL */ + interpol_2d( obuf, in, ibuf, buf1, buf2, buf3, lpf, hpf, tap, lenx, leny, + sx, sy, hor, HL ); + fptr1 = tbuf; + fptr2 = obuf; + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + *fptr1++ += 4 * ( *fptr2++ ); + } + } + + /* LH */ + interpol_2d( obuf, in, ibuf, buf1, buf2, buf3, lpf, hpf, tap, lenx, leny, + sx, sy, hor, LH ); + fptr1 = tbuf; + fptr2 = obuf; + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + *fptr1++ += 4 * ( *fptr2++ ); + } + } + + /* HH */ + interpol_2d( obuf, in, ibuf, buf1, buf2, buf3, lpf, hpf, tap, lenx, leny, + sx, sy, hor, HH ); + fptr1 = tbuf; + fptr2 = obuf; + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + *fptr1++ += 4 * ( *fptr2++ ); + } + } + + /* tbuf --> in */ + for( y = 0; y < leny; y++ ) { + for( x = 0; x < lenx; x++ ) { + pos = y * lenx + x; + ipos = ( y + sy ) * hor + ( x + sx ); + in[ipos] = tbuf[pos]; + } + } + + free( ibuf ); + free( obuf ); + free( tbuf ); + free( buf1 ); + free( buf2 ); + free( buf3 ); + free( lpf ); + free( hpf ); + + return; +} + +/****************************************************************************/ +/* analysis_child() */ +/****************************************************************************/ +void +analysis_child( float *frame, int sx, int sy, int lenx, int leny, int hor, + int ver, int filterType ) +{ + + analysis( frame, sx, sy, lenx / 2, leny / 2, hor, ver, filterType ); + analysis( frame, sx + lenx / 2, sy, lenx / 2, leny / 2, hor, ver, + filterType ); + analysis( frame, sx, sy + leny / 2, lenx / 2, leny / 2, hor, ver, + filterType ); + analysis( frame, sx + lenx / 2, sy + leny / 2, lenx / 2, leny / 2, hor, ver, + filterType ); +} + +/****************************************************************************/ +/* synthesis_child() */ +/****************************************************************************/ +void +synthesis_child( float *frame, int sx, int sy, int lenx, int leny, int hor, + int ver, int filterType ) +{ + synthesis( frame, sx, sy, lenx / 2, leny / 2, hor, ver, filterType ); + synthesis( frame, sx + lenx / 2, sy, lenx / 2, leny / 2, hor, ver, + filterType ); + synthesis( frame, sx, sy + leny / 2, lenx / 2, leny / 2, hor, ver, + filterType ); + synthesis( frame, sx + lenx / 2, sy + leny / 2, lenx / 2, leny / 2, hor, + ver, filterType ); +} + + +/*****************************************************************************/ +/* filter_2d() */ +/*****************************************************************************/ +void +filter_2d( float *obuf, float *ibuf, float *buf1, float *buf2, int lenx, + int leny, float *lpf, float *hpf, int tap, int mode ) +{ + int x, y; + + /* horizontal direction */ + for( y = 0; y < leny; y++ ) { + if( mode == LL || mode == LH ) + filter_1d( &obuf[y * lenx], &ibuf[y * lenx], lenx, lpf, tap, 0 ); + else + filter_1d( &obuf[y * lenx], &ibuf[y * lenx], lenx, hpf, tap, 1 ); + } + + /* vertical direction */ + for( x = 0; x < lenx; x++ ) { + for( y = 0; y < leny; y++ ) + buf1[y] = obuf[y * lenx + x]; + if( mode == LL || mode == HL ) + filter_1d( buf2, buf1, leny, lpf, tap, 0 ); + else + filter_1d( buf2, buf1, leny, hpf, tap, 1 ); + for( y = 0; y < leny; y++ ) + obuf[y * lenx + x] = buf2[y]; + } +} + + + +/*****************************************************************************/ +/* interpol_2d() */ +/*****************************************************************************/ +void +interpol_2d( float *obuf, float *in, float *ibuf, float *buf1, float *buf2, + float *buf3, float *lpf, float *hpf, int tap, int lenx, int leny, + int sx, int sy, int hor, int mode ) +{ + int x, y; + + /* horizontal interpolation and filtering */ + for( y = 0; y < leny / 2; y++ ) { + for( x = 0; x < lenx; x++ ) { + buf1[x + tap / 2] = 0; + if( mode == LL && !( x % 2 ) ) + buf1[x + tap / 2] = in[( y + sy ) * hor + ( x / 2 + sx )]; + else if( mode == HL && ( x % 2 ) ) + buf1[x + tap / 2] = in[( y + sy ) * hor + ( x / 2 + sx + lenx / 2 )]; + else if( mode == LH && !( x % 2 ) ) + buf1[x + tap / 2] = in[( y + sy + leny / 2 ) * hor + ( x / 2 + sx )]; + else if( mode == HH && ( x % 2 ) ) + buf1[x + tap / 2] = + in[( y + sy + leny / 2 ) * hor + ( x / 2 + sx + lenx / 2 )]; + } + if( mode == LL || mode == LH ) + filter_1d_normal( &ibuf[y * lenx], buf1 + tap / 2, lenx, lpf, tap, 0 ); + else + filter_1d_normal( &ibuf[y * lenx], buf1 + tap / 2, lenx, hpf, tap, 1 ); + } + + /* vertical interpolation and filtering */ + for( x = 0; x < lenx; x++ ) { + for( y = 0; y < leny; y++ ) { + buf2[y + tap / 2] = 0; + if( mode == LL || mode == HL ) { + if( !( y % 2 ) ) + buf2[y + tap / 2] = ibuf[( y / 2 ) * lenx + x]; + } else { + if( ( y % 2 ) ) + buf2[y + tap / 2] = ibuf[( y / 2 ) * lenx + x]; + } + } + if( mode == LL || mode == HL ) + filter_1d_normal( buf3, buf2 + tap / 2, leny, lpf, tap, 0 ); + else + filter_1d_normal( buf3, buf2 + tap / 2, leny, hpf, tap, 1 ); + + for( y = 0; y < leny; y++ ) + obuf[y * lenx + x] = buf3[y]; + } +} + +/*****************************************************************************/ +/* filter_1d() */ +/*****************************************************************************/ +void +filter_1d( float *out, float *in, int length, float *filter, int tap, + int start ) +{ + int i, j, k; + float tempf; + + /* 1 dimensional filtering by convolution */ + /* the symmetric extension for the boundary data */ + /* Example, for filter tap = 7 and data length = 10 */ + /* -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /* 3 2 1 0 1 2 3 4 5 6 7 8 9 8 7 6 */ + /* 18 18 18 */ + + for( i = start; i < length; i += 2 ) { /* considering the subsampling process */ + tempf = 0.; + for( j = 0; j < tap; j++ ) { + k = i - j + tap / 2; + if( k < 0 ) + k = -k; + else if( k >= length ) + k = ( length - 1 ) * 2 - k; + + if( k < 0 || k >= length ) { + printf( "output range k %d\n", k ); + exit( 0 ); + } + tempf += in[k] * filter[j]; + } + out[i] = tempf; + } +} + +/*****************************************************************************/ +/* filter_1d_normal() */ +/*****************************************************************************/ +void +filter_1d_normal( float *out, float *in, int length, float *filter, int tap, + int start ) +{ + int i, j, jstart; + float tempf, *fptr1, *fptr2; + + /* 1 dimensional filtering by convolution */ + /* the symmetric extension for the boundary data */ + /* Example, for filter tap = 7 and data length = 10 */ + /* -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /* 3 2 1 0 1 2 3 4 5 6 7 8 9 8 7 6 */ + /* 18 18 18 */ + + /* reflection for boundary */ + for( i = 1; i <= tap / 2; i++ ) { + in[-i] = in[i]; + in[length - 1 + i] = in[length - 1 - i]; + } + + /* we don't have to multiply zeros which is filled for upsampling */ + for( i = 0; i < length; i++ ) { + tempf = 0.; + + fptr1 = &in[i - tap / 2]; + fptr2 = filter; + jstart = 0; + if( ( ( i % 2 ) && !start ) || ( !( i % 2 ) && start ) ) { + fptr1++; + fptr2++; + jstart = 1; + } + + for( j = jstart; j < tap; j += 2 ) { + tempf += ( *fptr1 ) * ( *fptr2 ); + fptr1 += 2; + fptr2 += 2; + } + out[i] = tempf; + } +} + +/*****************************************************************************/ +/* filter_coeff() */ +/*****************************************************************************/ +int +filter_coeff( float **lpf, float **hpf, int FILTER, int analsyn ) +{ + int i, tap; + float *h0, *h1, *g0, *g1; + FILE *fp; + + if( FILTER == 0 ) { + tap = 9; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[4] = ( float )0.5645751; /* Adelson and Simoncelli */ + h0[3] = h0[5] = ( float )0.2927051; /* 9 tap filter */ + h0[2] = h0[6] = ( float )-0.05224239; /* Senoo and Girod '92 paper */ + h0[1] = h0[7] = ( float )-0.04270508; + h0[0] = h0[8] = ( float )0.01995484; + + tap = 9; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[4] = ( float )0.5645751; + h1[3] = h1[5] = ( float )-0.2927051; + h1[2] = h1[6] = ( float )-0.05224239; + h1[1] = h1[7] = ( float )0.04270508; + h1[0] = h1[8] = ( float )0.01995484; + } else if( FILTER == 1 ) { + tap = 9; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[4] = ( float )0.635577; /* Nguyen and Vaidyanathan */ + h0[3] = h0[5] = ( float )0.307180; + h0[2] = h0[6] = ( float )-0.164740; + h0[1] = h0[7] = ( float )0.002902; + h0[0] = h0[8] = ( float )0.036870; + + tap = 9; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[4] = ( float )0.490663; + h1[3] = h1[5] = ( float )-0.309311; + h1[2] = h1[6] = ( float )0.004668; + h1[1] = h1[7] = ( float )0.059311; + h1[0] = h1[8] = ( float )0.0; + + } else if( FILTER == 2 ) { /* Daubechies */ + tap = 9; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[4] = ( float )0.602949; + h0[3] = h0[5] = ( float )0.266864; + h0[2] = h0[6] = ( float )-0.078223; + h0[1] = h0[7] = ( float )-0.016864; + h0[0] = h0[8] = ( float )0.026749; + + tap = 9; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[4] = ( float )0.557543; + h1[3] = h1[5] = ( float )-0.295636; + h1[2] = h1[6] = ( float )-0.028772; + h1[1] = h1[7] = ( float )0.045636; + h1[0] = h1[8] = ( float )0.0; + } else if( FILTER == 3 ) { /* MPEG half band filter */ + tap = 9; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[4] = ( float )138. / 256; + h0[3] = h0[5] = ( float )88. / 256; + h0[2] = h0[6] = ( float )0; + h0[1] = h0[7] = ( float )-29. / 256; + h0[0] = h0[8] = ( float )0.; + + tap = 9; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[4] = ( float )0.; + h1[3] = h1[5] = ( float )0.; + h1[2] = h1[6] = ( float )0.; + h1[1] = h1[7] = ( float )0.; + h1[0] = h1[8] = ( float )0.0; + } else if( FILTER == 4 ) { /* new MPEG half band filter */ + tap = 13; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[6] = ( float )26. / 64; + h0[5] = h0[7] = ( float )19. / 64; + h0[4] = h0[8] = ( float )5. / 64; + h0[3] = h0[9] = ( float )-3. / 64; + h0[2] = h0[10] = ( float )-4. / 64; + h0[1] = h0[11] = ( float )0.; + h0[0] = h0[12] = ( float )2. / 64; + + tap = 13; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[6] = ( float )0.; + h1[5] = h1[7] = ( float )0.; + h1[4] = h1[8] = ( float )0.; + h1[3] = h1[9] = ( float )0.; + h1[2] = h1[10] = ( float )0.; + h1[1] = h1[11] = ( float )0.; + h1[0] = h1[12] = ( float )0.; + } else if( FILTER == 5 ) { /* Daubechies exchange the analytic filter and synthetic filter */ + tap = 9; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[4] = ( float )0.557543; + h0[3] = h0[5] = ( float )0.295636; + h0[2] = h0[6] = ( float )-0.028772; + h0[1] = h0[7] = ( float )-0.045636; + h0[0] = h0[8] = ( float )0.0; + + tap = 9; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[4] = ( float )0.602949; + h1[3] = h1[5] = ( float )-0.266864; + h1[2] = h1[6] = ( float )-0.078223; + h1[1] = h1[7] = ( float )0.016864; + h1[0] = h1[8] = ( float )0.026749; + + } else if( FILTER == 6 ) { + tap = 33; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + if( ( fp = fopen( "z:\\3d_ezbc\\Filter\\halfband.txt", "rb" ) ) == NULL ) { + printf( "can not open z:\\3d_ezbc\\Filter\\halfband.txt\n" ); + exit( 1 ); + } + for( i = 0; i < tap; i++ ) { + fscanf( fp, "%f\n", &h0[i] ); + } + fclose( fp ); + + } else if( FILTER == 7 ) { /* Daubechies - scaled to sqrt(2) */ + // printf ("use Daubechies spatial filters ( %d )\n", FILTER); + tap = 9; + h0 = ( float * )getarray( tap, sizeof( float ), "h0" ); + + h0[4] = ( float )0.852699; + h0[3] = h0[5] = ( float ) 0.377403; + h0[2] = h0[6] = ( float )-0.110624; + h0[1] = h0[7] = ( float )-0.023849; + h0[0] = h0[8] = ( float ) 0.037829; + + tap = 9; + h1 = ( float * )getarray( tap, sizeof( float ), "h1" ); + + h1[4] = ( float )0.788485; + h1[3] = h1[5] = ( float )-0.418092; + h1[2] = h1[6] = ( float )-0.040690; + h1[1] = h1[7] = ( float ) 0.064539; + h1[0] = h1[8] = ( float ) 0.0; + } else { + printf( "error in filter_coeff()\n" ); + exit( 1 ); + } + + if( !analsyn ) { + *lpf = h0; + *hpf = h1; + } else { + if( FILTER == 3 ) { + tap = 9; + g0 = ( float * )getarray( tap, sizeof( float ), "g0" ); + + g0[4] = ( float )256. / 256 / 2; + g0[3] = g0[5] = ( float )140. / 256 / 2; + g0[2] = g0[6] = ( float )0.; + g0[1] = g0[7] = ( float )-12. / 256 / 2; + g0[0] = g0[8] = ( float )0; + + tap = 9; + g1 = ( float * )getarray( tap, sizeof( float ), "g1" ); + + g1[4] = h1[4]; + g1[3] = g1[5] = -h1[3]; + g1[2] = g1[6] = h1[2]; + g1[1] = g1[7] = -h1[1]; + g1[0] = g1[8] = h1[0]; + } else if( FILTER == 4 ) { + printf( "not available\n" ); + exit( 1 ); + } else if( FILTER == 7 ) { /* Daubechies - scaled to sqrt(2) */ + // printf ("use Daubechies spatial filters ( %d )\n", FILTER); + /* + tap = 9; + g0 = ( float * )getarray( tap, sizeof( float ), "g0" ); + + g0[4] = ( float )0.852699; + g0[3] = g0[5] = ( float )0.418092; + g0[2] = g0[6] = ( float )-0.110624; + g0[1] = g0[7] = ( float )-0.064539; + g0[0] = g0[8] = ( float )0.037829; + + tap = 9; + g1 = ( float * )getarray( tap, sizeof( float ), "g1" ); + + g1[4] = ( float )0.788485; + g1[3] = g1[5] = ( float )-0.377403; + g1[2] = g1[6] = ( float )-0.040690; + g1[1] = g1[7] = ( float )0.023849; + g1[0] = g1[8] = ( float )0.0; + */ + float alpha = 2.0; + tap = 9; + g0 = ( float * )getarray( tap, sizeof( float ), "g0" ); + + g0[4] = h1[4] / alpha; + g0[3] = g0[5] = -h1[3] / alpha; + g0[2] = g0[6] = h1[2] / alpha; + g0[1] = g0[7] = -h1[1] / alpha; + g0[0] = g0[8] = h1[0] / alpha; + + tap = 9; + g1 = ( float * )getarray( tap, sizeof( float ), "g1" ); + + g1[4] = h0[4] / alpha; + g1[3] = g1[5] = -h0[3] / alpha; + g1[2] = g1[6] = h0[2] / alpha; + g1[1] = g1[7] = -h0[1] / alpha; + g1[0] = g1[8] = h0[0] / alpha; + } else { + // printf ("use inverted reconstruction filters ( %d )\n", FILTER); + tap = 9; + g0 = ( float * )getarray( tap, sizeof( float ), "g0" ); + + g0[4] = h1[4]; + g0[3] = g0[5] = -h1[3]; + g0[2] = g0[6] = h1[2]; + g0[1] = g0[7] = -h1[1]; + g0[0] = g0[8] = h1[0]; + + tap = 9; + g1 = ( float * )getarray( tap, sizeof( float ), "g1" ); + + g1[4] = h0[4]; + g1[3] = g1[5] = -h0[3]; + g1[2] = g1[6] = h0[2]; + g1[1] = g1[7] = -h0[1]; + g1[0] = g1[8] = h0[0]; + } + *lpf = g0; + *hpf = g1; + + free( h0 ); + free( h1 ); + } + + return tap; +} + +/****************************************************************************/ +/* analysis_1frame() */ +/****************************************************************************/ +void +analysis_1frame( float *frame, int band, int hor, int ver, int filterType ) +{ + + /******************************/ + /* ----------------- */ + /* | 0 | 1 | 4 | 5 | */ + /* ----------------- */ + /* | 2 | 3 | 6 | 7 | */ + /* ----------------- */ + /* | 8 | 9 | 12| 13| */ + /* ----------------- */ + /* | 10| 11| 14| 15| */ + /* ----------------- */ + /******************************/ + + /**********************************/ + /* --------------------- */ + /* |0 1 | | | */ + /* |2 3 | 4 | | */ + /* ----------- 7 | */ + /* | | | | */ + /* | 5 | 6 | | */ + /* --------------------- */ + /* | | | */ + /* | | | */ + /* | 8 | 9 | */ + /* | | | */ + /* | | | */ + /* --------------------- */ + /**********************************/ + + + switch ( band ) { + default: + printf( "error in analysis_1frame()\n" ); + exit( 1 ); + break; + case 4: + analysis( frame, 0, 0, hor, ver, hor, ver, filterType ); + break; + case 7: + analysis( frame, 0, 0, hor, ver, hor, ver, filterType ); + analysis( frame, 0, 0, hor / 2, ver / 2, hor, ver, filterType ); + break; + case 10: + analysis( frame, 0, 0, hor, ver, hor, ver, filterType ); + analysis( frame, 0, 0, hor / 2, ver / 2, hor, ver, filterType ); + analysis( frame, 0, 0, hor / 4, ver / 4, hor, ver, filterType ); + break; + case 16: + analysis( frame, 0, 0, hor, ver, hor, ver, filterType ); + analysis_child( frame, 0, 0, hor, ver, hor, ver, filterType ); + break; + } +} + + +/****************************************************************************/ +/* synthesis_1frame() */ +/****************************************************************************/ +void +synthesis_1frame( float *frame, int band, int hor, int ver, int filterType ) +{ + + switch ( band ) { + default: + printf( "error in synthesis_1frame()\n" ); + exit( 1 ); + break; + case 4: + synthesis( frame, 0, 0, hor, ver, hor, ver, filterType ); + break; + case 7: + synthesis( frame, 0, 0, hor / 2, ver / 2, hor, ver, filterType ); + synthesis( frame, 0, 0, hor, ver, hor, ver, filterType ); + break; + case 10: + synthesis( frame, 0, 0, hor / 4, ver / 4, hor, ver, filterType ); + synthesis( frame, 0, 0, hor / 2, ver / 2, hor, ver, filterType ); + synthesis( frame, 0, 0, hor, ver, hor, ver, filterType ); + break; + case 16: + synthesis_child( frame, 0, 0, hor, ver, hor, ver, filterType ); + synthesis( frame, 0, 0, hor, ver, hor, ver, filterType ); + break; + } +} diff --git a/Interframe EZBC/TempSub/src/syn.c b/Interframe EZBC/TempSub/src/syn.c new file mode 100644 index 0000000..fe70408 --- /dev/null +++ b/Interframe EZBC/TempSub/src/syn.c @@ -0,0 +1,1406 @@ +#include +#include +#include +#include +#include +#include +#define EXTERN extern +#include "basic.h" +#include "rasterfile.h" +#include "structN.h" +#include "coderN.h" +#include "analsyn.h" +#include "ioN.h" +#include "miscN.h" +#include "memoryN.h" +#include "chrom.h" +#include "mvcodingN.h" +#include "ezbc_dec_3d.h" +#include "bmeN.h" +#include "pstatN.h" +#include "video_utils.h" + +#include "directional_iblock.h" + +#include "obmc_varblk.h" + +#include "util_filtering.h" + + +void calsnr_frame( YUVimage_ptr fr0, YUVimage_ptr fr1, int curr, + videoinfo info ); + +void ezbc3d_dec_GOP( YUVimage * pyrFrs, videoinfo info, long total_bytes_past, + long int GOP_counter, int curr ); + + +void +decode_MV( long int *total_bytes_past, videoinfo info, int GOP_counter, int simul_dec, int theo_dec ) +{ + // this function should go to mvcodingN.c + // KH, 2003-12-02 + + long int starting_pos; + + int mvBytes, GOPheader_bytes, s_level; + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + + if( s_level > 0 ) { // 调整分辨率的大小 + info.ywidth <<= s_level; + info.yheight <<= s_level; + info.cwidth <<= s_level; + info.cheight <<= s_level; + } + + if( info.tPyrLev >= 1 ) { + if( !( fpbit = fopen( info.bitname, "rb" ) ) ) { // 打开bit文件 + printf( "init_dec: %s\n", info.bitname ); + exit( 1 ); + } + + fseek( fpbit, *total_bytes_past, SEEK_SET );// 定位文件位置 + GOPheader_bytes = read_GOPheader( dec_scene_change, info ); // 标记每一帧是否有场景改变 + *total_bytes_past += GOPheader_bytes; + starting_pos = *total_bytes_past; //后移GOPheader_bytes的定位 + mvBytes = mv_decoding( info, dec_yfmv, GOP_counter, starting_pos, simul_dec, theo_dec );// 解码mv + *total_bytes_past += mvBytes; + fclose( fpbit ); + } +} + +// 合成一层的重建,不是一帧 +void +temporal_synthesis( YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int level, videoinfo info ) + /* fr1--current, fr0--reference */ +{ + int yhor, yver, chor, cver; + float *ymvx0, *ymvy0, *ymvx1, *ymvy1, *ymvx2, *ymvy2; + float *cmvx0, *cmvy0, *cmvx1, *cmvy1, *cmvx2, *cmvy2; + float *ymvx0_int, *ymvy0_int, *ymvx1_int, *ymvy1_int, *ymvx2_int, *ymvy2_int; + float *cmvx0_int, *cmvy0_int, *cmvx1_int, *cmvy1_int, *cmvx2_int, *cmvy2_int; + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + blockmv2pixelmv( fmv0, &ymvx0, &ymvy0, &cmvx0, &cmvy0, CONNECTED, info, level ); + blockmv2pixelmv( fmv1, &ymvx1, &ymvy1, &cmvx1, &cmvy1, CONNECTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2, &ymvy2, &cmvx2, &cmvy2, CONNECTED, info, level ); + blockmv2pixelmv( fmv0, &ymvx0_int, &ymvy0_int, &cmvx0_int, &cmvy0_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv1, &ymvx1_int, &ymvy1_int, &cmvx1_int, &cmvy1_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2_int, &ymvy2_int, &cmvx2_int, &cmvy2_int, PREDICTED, info, level ); + + mc_synthesis( fr0->Y, fr1->Y, H0.Y, L1.Y, H1.Y, frp.Y, + ymvx0, ymvy0, ymvx1, ymvy1, ymvx2, ymvy2, + ymvx0_int, ymvy0_int, ymvx1_int, ymvy1_int, + ymvx2_int, ymvy2_int, mv_ref0, mv_ref1, mv_ref2, + yhor, yver, level, info ); + + if( info.cwidth && info.cheight ) + { + mc_synthesis( fr0->U, fr1->U, H0.U, L1.U, H1.U, frp.U, + cmvx0, cmvy0, cmvx1, cmvy1, cmvx2, cmvy2, + cmvx0_int, cmvy0_int, cmvx1_int, cmvy1_int, + cmvx2_int, cmvy2_int, mv_ref0, mv_ref1, mv_ref2, + chor, cver, level, info ); + mc_synthesis( fr0->V, fr1->V, H0.V, L1.V, H1.V, frp.V, + cmvx0, cmvy0, cmvx1, cmvy1, cmvx2, cmvy2, + cmvx0_int, cmvy0_int, cmvx1_int, cmvy1_int, + cmvx2_int, cmvy2_int, mv_ref0, mv_ref1, mv_ref2, + chor, cver, level, info ); + } + + free( ymvx0 ); + free( ymvy0 ); + free( cmvx0 ); + free( cmvy0 ); + + free( ymvx1 ); + free( ymvy1 ); + free( cmvx1 ); + free( cmvy1 ); + + free( ymvx2 ); + free( ymvy2 ); + free( cmvx2 ); + free( cmvy2 ); + + free( ymvx0_int ); + free( ymvy0_int ); + free( cmvx0_int ); + free( cmvy0_int ); + + free( ymvx1_int ); + free( ymvy1_int ); + free( cmvx1_int ); + free( cmvy1_int ); + + free( ymvx2_int ); + free( ymvy2_int ); + free( cmvx2_int ); + free( cmvy2_int ); + +} + + +void +temporal_synthesis_with_OBMC( YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int level, videoinfo info, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) + /* fr1--current, fr0--reference */ +{ + int yhor, yver, chor, cver; + float *ymvx0, *ymvy0, *ymvx1, *ymvy1, *ymvx2, *ymvy2; + float *cmvx0, *cmvy0, *cmvx1, *cmvy1, *cmvx2, *cmvy2; + float *ymvx0_int, *ymvy0_int, *ymvx1_int, *ymvy1_int, *ymvx2_int, *ymvy2_int; + float *cmvx0_int, *cmvy0_int, *cmvx1_int, *cmvy1_int, *cmvx2_int, *cmvy2_int; + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + + blockmv2pixelmv( fmv0, &ymvx0, &ymvy0, &cmvx0, &cmvy0, CONNECTED, info, level ); + blockmv2pixelmv( fmv1, &ymvx1, &ymvy1, &cmvx1, &cmvy1, CONNECTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2, &ymvy2, &cmvx2, &cmvy2, CONNECTED, info, level ); + blockmv2pixelmv( fmv0, &ymvx0_int, &ymvy0_int, &cmvx0_int, &cmvy0_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv1, &ymvx1_int, &ymvy1_int, &cmvx1_int, &cmvy1_int, PREDICTED, info, level ); + blockmv2pixelmv( fmv2, &ymvx2_int, &ymvy2_int, &cmvx2_int, &cmvy2_int, PREDICTED, info, level ); + + mc_synthesis_with_OBMC( fr0->Y, fr1->Y, H0.Y, L1.Y, H1.Y, frp.Y, + ymvx0, ymvy0, ymvx1, ymvy1, ymvx2, ymvy2, + ymvx0_int, ymvy0_int, ymvx1_int, ymvy1_int, + ymvx2_int, ymvy2_int, mv_ref0, mv_ref1, mv_ref2, + yhor, yver, level, info, frameMEinfo, varblkarray, 0, 0); + + if( info.cwidth && info.cheight ) + { + mc_synthesis_with_OBMC( fr0->U, fr1->U, H0.U, L1.U, H1.U, frp.U, + cmvx0, cmvy0, cmvx1, cmvy1, cmvx2, cmvy2, + cmvx0_int, cmvy0_int, cmvx1_int, cmvy1_int, + cmvx2_int, cmvy2_int, mv_ref0, mv_ref1, mv_ref2, + chor, cver, level, info, frameMEinfo, varblkarray, 1, 1); + mc_synthesis_with_OBMC( fr0->V, fr1->V, H0.V, L1.V, H1.V, frp.V, + cmvx0, cmvy0, cmvx1, cmvy1, cmvx2, cmvy2, + cmvx0_int, cmvy0_int, cmvx1_int, cmvy1_int, + cmvx2_int, cmvy2_int, mv_ref0, mv_ref1, mv_ref2, + chor, cver, level, info, frameMEinfo, varblkarray, 1, 0); + } + + free( ymvx0 ); + free( ymvy0 ); + free( cmvx0 ); + free( cmvy0 ); + + free( ymvx1 ); + free( ymvy1 ); + free( cmvx1 ); + free( cmvy1 ); + + free( ymvx2 ); + free( ymvy2 ); + free( cmvx2 ); + free( cmvy2 ); + + free( ymvx0_int ); + free( ymvy0_int ); + free( cmvx0_int ); + free( cmvy0_int ); + + free( ymvx1_int ); + free( ymvy1_int ); + free( cmvx1_int ); + free( cmvy1_int ); + + free( ymvx2_int ); + free( ymvy2_int ); + free( cmvx2_int ); + free( cmvy2_int ); + +} + + + +void +directional_iblock_synthesis_with_OBMC( YUVimage_ptr fr0, YUVimage_ptr fr1, YUVimage H0, + YUVimage L1, YUVimage H1, YUVimage frp, + vector_ptr fmv0, vector_ptr fmv1, vector_ptr fmv2, + vector_ptr mv_ref0, vector_ptr mv_ref1, + vector_ptr mv_ref2, int t_level, videoinfo info, + ImageMEinfo *frameMEinfo, Varblkarrayinfo *varblkarray) + /* fr1--current, fr0--reference */ +{ + int x, y, X, Y, yhor, yver; + int xnum, ynum, xblk, yblk; + vector_ptr fmv; + int s_level; + + // left scene change and right scene change, this is an intra-frame + if( mv_ref0 == NULL && mv_ref1 == NULL ) return; + + s_level = MY_MAX (0, info.s_level - (info.denoise_flag == YES)); + + yhor = info.ywidth << s_level; + yver = info.yheight << s_level; + xnum = info.xnum[t_level]; + ynum = info.ynum[t_level]; + xblk = info.xblk[t_level]; + yblk = info.yblk[t_level]; + + if (mv_ref0 != NULL ) + fmv = fmv0; + else if ( mv_ref1 != NULL ) + fmv = fmv1; + else + assert(0); + + for( y = 0, Y = 0; Y < ynum; y += yblk, Y++ ) { + for( x = 0, X = 0; X < xnum; x += xblk, X++ ) { + // fmv is for current high temporal frame H0 ( non-NULL motion vector quad-tree ) + // fmv[Y * xnum + X] is current Macro-block + rec_directional_iblock_synthesis_with_OBMC( &fmv[Y * xnum + X], x, y, xblk, yblk, yhor, yver, + fr0, fr1, H0, L1, H1, frp, + fmv0, fmv1, fmv2, mv_ref0, mv_ref1, + mv_ref2, t_level, info, fmv, + frameMEinfo, varblkarray); + } + } + +} + + +// by Yongjun Wu +// In decoder mv_ref0, mv_ref1 and mv_ref2 (whether it's NULL ) can exactly indicate the scene change +// information and the existence of motion vectors in left and/or rigth directions. +// However, in encoder mv_ref1, mv_ref2 and mv_ref3 can not exactly indicate the information. +// Sometimes scene is changed but mv_refi is still not NULL. +// hence we have to use the correpsonding scene_change[][] to indicate the information. + +/* + * synscheme 3 + */ +void +synscheme3( int curr, videoinfo info, enum FLAG first_GOP, + enum FLAG Level_change, int remaining_frs, int simul_dec, int theo_dec ) +{ + int i, j, k, tPyrLev, t_level, dist, yhor, yver, chor, cver; + int bigGOP, GOPsz, half_bigGOP, half_GOPsz, GOPIndex; + int ind_mv_GOP[20], ind_pyrFrs_bigGOP[20], ind_pyrFrs_GOP[20]; + int eff_GOPsz[20]; // eff_GOPsz in level i + YUVimage dumb; + + YUVimage middle; + + int total_varblk; // for MCTF with OBMC + + frame_alloc(&dumb, info); + + frame_alloc(&middle, info); + + /*****************/ + /* Base Settings */ + /*****************/ + + yhor = info.ywidth; + yver = info.yheight; + chor = info.cwidth; + cver = info.cheight; + tPyrLev = info.tPyrLev; + t_level = 0; + bigGOP = info.bigGOP; // 31, 15, 7, 3 + half_bigGOP = info.bigGOP / 2; // 15, 7, 3, 1 + GOPsz = info.GOPsz; // 16, 8, 4, 2 + half_GOPsz = info.GOPsz / 2; // 8, 4, 2, 1 + GOPIndex = curr / GOPsz; + + // determine effective GOP size in level i + for( i = 0; i < info.tPyrLev; i++ ) { + if ( Level_change == YES ) + eff_GOPsz[i] = (int) ceil ((double)info.eff_GOPsz / (pow (2, i))); + else + eff_GOPsz[i] = GOPsz; + GOPsz /= 2; + } + GOPsz = info.GOPsz; + + dist = 1 << ( info.tPyrLev - 1 ); + + // note: indices for bigGop are not the same as in analysis! + // MV indices for transmission, e.g. for tPyrLev = 4: + // Level0: 18-34; Level1: 9-17; Level2: 4-8; Level3: 1-3 + // the first set of motion vectors are always NULL + // such as 1 in level3, 4 in level 2, ... + ind_mv_GOP [tPyrLev] = -1; // 1, 4, 9 , 18, ... + + // Indices of BigGOP-Array + ind_pyrFrs_bigGOP[tPyrLev] = 0; // 0, 1, 3, 6, 11, ... + ind_pyrFrs_GOP [tPyrLev] = 1; // 0, 1, 2, 4, 8 , ... + + // calculation of base indices for MV-sets and frames + for( i = tPyrLev - 1; i >= 0; i-- ){ + ind_mv_GOP[i] = (int)(pow (2, tPyrLev-i-1)) + ind_mv_GOP[i+1] + 1; + ind_pyrFrs_bigGOP[i] = (int)(pow (2, tPyrLev-i-2)) + ind_pyrFrs_bigGOP[i+1] + 1; + ind_pyrFrs_GOP[i] = (int)(pow (2, tPyrLev-i-1)); + } + +// printf("Enter scene change\n"); + // free MV in case of scene changes + for( i = 0; i < tPyrLev; i++ ){ + for( j = 0; j <= GOPsz; j++ ){ // effective GOPsz! + if( dec_scene_change[i][j] == YES ){ + free_vector( dec_yfmv[j + ind_mv_GOP[i]], info ); + mv_ref[j + ind_mv_GOP[i]] = NULL; + } else { + mv_ref[j + ind_mv_GOP[i]] = dec_yfmv[j + ind_mv_GOP[i]]; + } + } + GOPsz /= 2; + } + GOPsz = info.GOPsz; + +// printf("Out of scene change\n"); + + // not really necessary? + free_vector( dec_yfmv[1], info ); + mv_ref[1] = NULL; + + /**********************/ + /* Temporal Filtering */ + /**********************/ + + if( first_GOP == YES ){ // *** first_GOP = YES *** // 合成一个gop + // decode first frame (..., LLL, LL, L, A) + GOPsz = 1; + for( i = tPyrLev - 1; i >= t_level; i-- ){ // 逐级的合成 + // for synthesis all MV's must be given 为了synthesis,所有的MV必须要给 + // ==> initialize missing MV's and set mode = PREDICTED 初始化丢失的MV,并且设置mode = PREDICTED,mvx & mvy = (float)HUGE_VAL + // ==> mvx & mvy = (float)HUGE_VAL in temporal_synthesis + if( i == tPyrLev - 1 ){ // *** last level *** 最下面一层,先进行这里 +#ifdef MCTF_WITH_OBMC + // no need for MCTF with OBMC here, since H0 is dumb 这里不需要带OBMC的MCTF,因为H0是哑的 + // no need for directional IBLOCK reconstruction since H0 is dumb 这里不需要directional IBLOCK reconstruction,因为H0是哑的 + printf("i == tPyrLev - 1 level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis_with_OBMC( + &dumb, // fr0 (B1), dumb + &dec_pyrTemp[i][0], // fr1 (A1) + dumb, // H0, dumb + dec_pyrFrs[0], // L1 + dec_pyrFrs[1], // H1 + dumb, // frp (A0), dumb + dec_yfmv[1], // mv0, free + dec_yfmv[1], // mv1, free + dec_yfmv[2], // mv2 + mv_ref[1], // NULL + mv_ref[1], // NULL + mv_ref[2], // ref_mv2 + i, info, NULL, NULL ); + +#else +// printf("i == tPyrLev - 1 level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis( &dumb, // fr0 (B1), dumb + &dec_pyrTemp[i][0], // fr1 (A1) + dumb, // H0, dumb + dec_pyrFrs[0], // L1 + dec_pyrFrs[1], // H1 + dumb, // frp (A0), dumb + dec_yfmv[1], // mv0, free + dec_yfmv[1], // mv1, free + dec_yfmv[2], // mv2 + mv_ref[1], // NULL + mv_ref[1], // NULL + mv_ref[2], // ref_mv2 + i, info ); + +#endif + } + else { // *** next levels *** +#ifdef MCTF_WITH_OBMC + // no need for MCTF with OBMC here, since H0 is dumb + // no need for directional IBLOCK reconstruction since H0 is dumb + + printf("next levels, level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis_with_OBMC( + &dumb, // fr0 (B1), dumb + &dec_pyrTemp[i][0], // fr1 (A1) + dumb, // H0, dumb + dec_pyrTemp[i + 1][0], // L1 + dec_pyrFrs[ind_pyrFrs_GOP[i]], // H1 + dumb, // frp (A0), dumb + dec_yfmv[1], // mv0, free + dec_yfmv[1], // mv1, free + dec_yfmv[ind_mv_GOP[i] + 1], // mv2 + mv_ref[1], // NULL + mv_ref[1], // NULL + mv_ref[ind_mv_GOP[i] + 1], // ref_mv2 + i, info, NULL, NULL ); + +#else +// printf("next levels, level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis( &dumb, // fr0 (B1), dumb + &dec_pyrTemp[i][0], // fr1 (A1) + dumb, // H0, dumb + dec_pyrTemp[i + 1][0], // L1 + dec_pyrFrs[ind_pyrFrs_GOP[i]], // H1 + dumb, // frp (A0), dumb + dec_yfmv[1], // mv0, free + dec_yfmv[1], // mv1, free + dec_yfmv[ind_mv_GOP[i] + 1], // mv2 + mv_ref[1], // NULL + mv_ref[1], // NULL + mv_ref[ind_mv_GOP[i] + 1], // ref_mv2 + i, info ); + +#endif + } + GOPsz *= 2; + } + } + else { // *** first_GOP = NO *** + + // copy first frame / MVF of new GOP to last position of preceeding (big)GOP + // in order to be able to decode the preceeding GOP completely 为了完全解码前面一个gop,复制新gop的第一帧/MVF到先前gop的最后一个位置 + if ( remaining_frs != 0 ){ + GOPsz = 2; + for( i = tPyrLev - 1; i >= t_level; i-- ){ + + // bigGOP-Array + copyframe( &dec_pyrFrs[ind_pyrFrs_GOP[i]], &dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + GOPsz / 2 ], info ); + free_vector( dec_yfmv_bigGOP[ind_mv_GOP[i] + GOPsz], info ); + mv_copy( dec_yfmv[ind_mv_GOP[i] + 1], dec_yfmv_bigGOP[ind_mv_GOP[i] + GOPsz], info ); + dec_mv_ref_bigGOP[ind_mv_GOP[i] + GOPsz] = mv_ref[ind_mv_GOP[i] + 1] ? dec_yfmv_bigGOP[ind_mv_GOP[i] + GOPsz] : NULL; + + GOPsz *= 2; + } + copyframe( &dec_pyrFrs[0], &dec_pyrFrs_bigGOP[0], info ); // lowpass copy + } + + // decode GOP + + // *** last level *** + + for( k = 1; k <= 3; k++ ){ + assert ((dec_mv_ref_bigGOP[k] == dec_yfmv_bigGOP[k]) || (dec_mv_ref_bigGOP[k] == NULL)); + } + +#ifdef MCTF_WITH_OBMC + if (tPyrLev - 1 >= info.t_level) { + get_mv_side_information(info, + dec_yfmv_bigGOP[1], // mv0 + dec_yfmv_bigGOP[2], // mv1 + dec_mv_ref_bigGOP[1], // ref_mv0 + dec_mv_ref_bigGOP[2], // ref_mv1 + frameMEinfo, varblkarray, + &total_varblk, tPyrLev - 1, 0, + NO, NO, 0); + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, tPyrLev - 1, 0); + } + + printf("i == tPyrLev - 1 , next GOP, level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis_with_OBMC( + &dec_pyrTemp[tPyrLev - 1][0], // fr0 (B1) + &dec_pyrTemp[tPyrLev - 1][1], // fr1 (A1) + dec_pyrFrs_bigGOP[1], // H0 + dec_pyrFrs_bigGOP[0], // L1 + dec_pyrFrs_bigGOP[2], // H1 + dec_pyrFrs_first[tPyrLev - 1], // frp (A0) + dec_yfmv_bigGOP[1], // mv0 + dec_yfmv_bigGOP[2], // mv1 + dec_yfmv_bigGOP[3], // mv2 + dec_mv_ref_bigGOP[1], // ref_mv0 + dec_mv_ref_bigGOP[2], // ref_mv1 + dec_mv_ref_bigGOP[3], // ref_mv2 + tPyrLev - 1, info, + frameMEinfo, varblkarray); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // synthesis IBLOCK + directional_iblock_synthesis_with_OBMC( + &dec_pyrTemp[tPyrLev - 1][0], // fr0 (B1) + &dec_pyrTemp[tPyrLev - 1][1], // fr1 (A1) + dec_pyrFrs_bigGOP[1], // H0 + dec_pyrFrs_bigGOP[0], // L1 + dec_pyrFrs_bigGOP[2], // H1 + dec_pyrFrs_first[tPyrLev - 1], // frp (A0) + dec_yfmv_bigGOP[1], // mv0 + dec_yfmv_bigGOP[2], // mv1 + dec_yfmv_bigGOP[3], // mv2 + dec_mv_ref_bigGOP[1], // ref_mv0 + dec_mv_ref_bigGOP[2], // ref_mv1 + dec_mv_ref_bigGOP[3], // ref_mv2 + tPyrLev - 1, info, + frameMEinfo, varblkarray); +#endif + + +#else + if (tPyrLev - 1 >= info.t_level) { + get_mv_side_information(info, + dec_yfmv_bigGOP[1], // mv0 + dec_yfmv_bigGOP[2], // mv1 + dec_mv_ref_bigGOP[1], // ref_mv0 + dec_mv_ref_bigGOP[2], // ref_mv1 + frameMEinfo, varblkarray, + &total_varblk, tPyrLev - 1, 0, + NO, NO, 0); + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, tPyrLev - 1, 0); + } + +// printf("i == tPyrLev - 1 , next GOP, level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis( &dec_pyrTemp[tPyrLev - 1][0], // fr0 (B1) + &dec_pyrTemp[tPyrLev - 1][1], // fr1 (A1) + dec_pyrFrs_bigGOP[1], // H0 + dec_pyrFrs_bigGOP[0], // L1 + dec_pyrFrs_bigGOP[2], // H1 + dec_pyrFrs_first[tPyrLev - 1], // frp (A0) + dec_yfmv_bigGOP[1], // mv0 + dec_yfmv_bigGOP[2], // mv1 + dec_yfmv_bigGOP[3], // mv2 + dec_mv_ref_bigGOP[1], // ref_mv0 + dec_mv_ref_bigGOP[2], // ref_mv1 + dec_mv_ref_bigGOP[3], // ref_mv2 + tPyrLev - 1, info ); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED // synthesis IBLOCK + + directional_iblock_synthesis_with_OBMC( + &dec_pyrTemp[tPyrLev - 1][0], // fr0 (B1) + &dec_pyrTemp[tPyrLev - 1][1], // fr1 (A1) + dec_pyrFrs_bigGOP[1], // H0 + dec_pyrFrs_bigGOP[0], // L1 + dec_pyrFrs_bigGOP[2], // H1 + dec_pyrFrs_first[tPyrLev - 1], // frp (A0) + dec_yfmv_bigGOP[1], // mv0 + dec_yfmv_bigGOP[2], // mv1 + dec_yfmv_bigGOP[3], // mv2 + dec_mv_ref_bigGOP[1], // ref_mv0 + dec_mv_ref_bigGOP[2], // ref_mv1 + dec_mv_ref_bigGOP[3], // ref_mv2 + tPyrLev - 1, info, + frameMEinfo, varblkarray); +#endif + +#endif + + // *** next levels *** + GOPsz = 2; + for( i = tPyrLev - 2; i >= t_level; i-- ){ + for( j = 0; j < GOPsz; j++ ){ + + for( k = (ind_mv_GOP[i] + 2 * j); k <= (ind_mv_GOP[i] + 2 * j + 2); k++ ){ + assert ((dec_mv_ref_bigGOP[k] == dec_yfmv_bigGOP[k]) || (dec_mv_ref_bigGOP[k] == NULL)); + } + if( j == 0 ){ +#ifdef MCTF_WITH_OBMC + if (i >= info.t_level) { + get_mv_side_information(info, + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + frameMEinfo, varblkarray, + &total_varblk, i, j, + NO, NO, 0); + + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + } + + printf("Next level, next GOP, level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis_with_OBMC( + &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1],// H1 + dec_pyrFrs_first[i], // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info, + frameMEinfo, varblkarray); +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + directional_iblock_synthesis_with_OBMC( + &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1],// H1 + dec_pyrFrs_first[i], // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info, + frameMEinfo, varblkarray); +#endif + + if(i == EXTRACT_TMP && EXT){ + if( dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j] != NULL || dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1] != NULL ){ + wcopyframe(&dec_pyrTemp[i][2 * j], &middle, 1/pow(LPW1[1],EXTRACT_TMP), info); + write_frame(middle,info,info.jp2k_decname,curr/2 + 2*j, info.format); + }else{ +// wcopyframe(&dec_pyrTemp[i][2 * j], &middle, 1, info); +// assert(0); + } + + if( dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1] != NULL || dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2] != NULL ){ + wcopyframe(&dec_pyrTemp[i][2 * j + 1], &middle, 1/pow(LPW1[1],EXTRACT_TMP), info); + write_frame(middle,info,info.jp2k_decname,curr/2 + 2*j + 1, info.format); + }else{ +// wcopyframe(&dec_pyrTemp[i][2 * j + 1], &middle, 1, info); +// assert(0); + } + + } + +#else + if (i >= info.t_level) { + get_mv_side_information(info, + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + frameMEinfo, varblkarray, + &total_varblk, i, j, + NO, NO, 0); + + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + } + +// printf("Next level, next GOP, level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis( &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1],// H1 + dec_pyrFrs_first[i], // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info ); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + + directional_iblock_synthesis_with_OBMC( + &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1],// H1 + dec_pyrFrs_first[i], // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info, + frameMEinfo, varblkarray); +#endif + +#endif + } else { + +#ifdef MCTF_WITH_OBMC + if (i >= info.t_level) { + get_mv_side_information(info, + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + frameMEinfo, varblkarray, + &total_varblk, i, j, + NO, NO, 0); + + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + } + + printf("level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis_with_OBMC( + &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1], // H1 + dec_pyrTemp[i][2 * j - 1], // statt pyrFrs_first // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info, + frameMEinfo, varblkarray); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + directional_iblock_synthesis_with_OBMC( + &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1], // H1 + dec_pyrTemp[i][2 * j - 1], // statt pyrFrs_first // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info, + frameMEinfo, varblkarray); +#endif + +#else + if (i >= info.t_level) { + get_mv_side_information(info, + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + frameMEinfo, varblkarray, + &total_varblk, i, j, + NO, NO, 0); + + mv_weight_info(info, frameMEinfo, varblkarray, total_varblk, i, j); + } + +// printf("level and frame: i = %d, j = %d\n",i,j); + temporal_synthesis( &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1], // H1 + dec_pyrTemp[i][2 * j - 1], // statt pyrFrs_first // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info ); + +#ifdef DIRECTIONAL_IBLOCK_EMPLOYED + + directional_iblock_synthesis_with_OBMC( + &dec_pyrTemp[i][2 * j], // fr0 (B1) + &dec_pyrTemp[i][2 * j + 1], // fr1 (A1) + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j], // H0 + dec_pyrTemp[i + 1][j], // L1 + dec_pyrFrs_bigGOP[ind_pyrFrs_bigGOP[i] + j + 1], // H1 + dec_pyrTemp[i][2 * j - 1], // statt pyrFrs_first // frp (A0) + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j], // mv0 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // mv1 + dec_yfmv_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // mv2 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j], // ref_mv0 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 1], // ref_mv1 + dec_mv_ref_bigGOP[ind_mv_GOP[i] + 2 * j + 2], // ref_mv2 + i, info, + frameMEinfo, varblkarray); +#endif + +#endif + } + } + GOPsz *= 2; + } + // last GOP: remaining_frs == 0 ! + + } + + /********************/ + /* Save information 为下一个gop保存信息 */ + /* for next GOP */ + /********************/ + if ( remaining_frs != 0 && theo_dec == NO ){ // 最后不满一个gop也会进来,来保存信息,因为下一个gop不读fream的 + + GOPsz = info.GOPsz >> t_level; + + for( i = t_level; i < tPyrLev; i++ ){ + // save dec_pyrTemp[i][0] for next GOP 保存第一帧 + if ( first_GOP == YES ) + copyframe( &dec_pyrTemp[i][0], &dec_pyrFrs_first[i], info ); + else { + copyframe( &dec_pyrTemp[i][GOPsz - 1], &dec_pyrFrs_first[i], info ); + } + + for( j = 0; j < GOPsz / 2; j++ ){ //eff_GOPsz[i] + // copy frames 保存帧 + copyframe( &dec_pyrFrs[j + ind_pyrFrs_GOP[i]], &dec_pyrFrs_bigGOP[j + ind_pyrFrs_bigGOP[i]], info ); + } + + for( j = 0; j <= GOPsz; j++ ){ + if (j + ind_mv_GOP[i] != 1){ + // copy MVs 保存mv + free_vector( dec_yfmv_bigGOP[j + ind_mv_GOP[i] - 1], info ); + mv_copy( dec_yfmv[j + ind_mv_GOP[i]], dec_yfmv_bigGOP[j + ind_mv_GOP[i] - 1], info ); + dec_mv_ref_bigGOP[j + ind_mv_GOP[i] - 1] = mv_ref[j + ind_mv_GOP[i]] ? + dec_yfmv_bigGOP[j + ind_mv_GOP[i] - 1] : NULL; + } + } + GOPsz /= 2; + } + }// if simul_dec + +} + + +void +denoise_mctf_syn_ezbc( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info, enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs ) +{ + int i, j, t_level, nfrs, dist; + int filterType = DENOISE_FILTER; + YUVimage tempfr, tempfr2; + + t_level = MY_MIN (info.t_level, info.tPyrLev); + dist = 1 << ( t_level ); + + if ( remaining_frs != 0 ){ + nfrs = info.GOPsz; + } else { + nfrs = info.eff_GOPsz; + } + + if ( first_GOP == YES ) nfrs = 1; + + /*************/ + /* MV + EZBC */ + /*************/ + if ( remaining_frs != 0 ){ + decode_MV( total_bytes_past, info, GOP_counter, 0, 0 ); + ezbc3d_dec_GOP( Four_GOP, info, *total_bytes_past, GOP_counter, curr ); + + if ( info.s_level == 0 ){ + if ( first_GOP == YES ){ + for( i = 1; i < ((YUV420 == 1) ? 2 : 4); i++ ) { + for( j = 0; j < info.GOPsz; j++ ) { + spatial_high[(i-1)][j] = Four_GOP[i * info.GOPsz + j]; + } + } + } else { // first_GOP == NO + for( i = 1; i < ((YUV420 == 1) ? 2 : 4); i++ ) { + copyframe( &Four_GOP[i * info.GOPsz], &Four_bigGOP[(i+1) * info.GOPsz - (1 << t_level)], info ); + // printf("copyframe( &Four_GOP[%d], &Four_bigGOP[%d] );\n", i * info.GOPsz, (i+1) * info.GOPsz - (1 << t_level)); + + for( j = 0; j < info.GOPsz; j++ ) { + spatial_high[(i-1)][j] = Four_bigGOP[i * info.GOPsz + j]; + } + } + } + } + + for( j = 0; j < info.GOPsz; j++ ) { + dec_pyrFrs[j] = Four_GOP[j]; + } + + } + + /********/ + /* MCTF */ + /********/ + mc_syn( curr, total_bytes_past, info, first_GOP, + Level_change, remaining_frs, 0, 0 ); + + /*************/ + /* spatial */ + /* synthesis */ + /*************/ + if( info.s_level == 0 ){ // Quarter == 0 + + info.ywidth *= 2; + info.yheight *= 2; + info.cwidth *= 2; + info.cheight *= 2; + + // for( i = 0; i < info.eff_GOPsz; i++ ) { + for( i = 0; i < nfrs; i += dist ) { + frame_alloc( &tempfr, info ); + frame_alloc( &tempfr2, info ); + + if ( first_GOP == YES ) dist = 1; + + if( YUV420 == 1 ) { + spatial_syn( tempfr.Y, info.ywidth, info.yheight, dec_pyrTemp[0][i + dist - 1].Y, + spatial_high[0][i].Y, spatial_high[0][i].U, + spatial_high[0][i].V, filterType ); + + for( j = 0; j < info.cwidth * info.cheight / 4; j++ ) { + tempfr.U[j] = dec_pyrTemp[0][i + dist - 1].U[j] * 4; + tempfr.V[j] = dec_pyrTemp[0][i + dist - 1].V[j] * 4; + } + read_frame( &tempfr2, info, info.inname, curr + i, info.format ); + + f444_420( info, &tempfr2 ); + info.cwidth /= 2; + info.cheight /= 2; + calsnr_frame( &tempfr, &tempfr2, curr + i, info ); + + f420_444( info, &tempfr ); + info.cwidth *= 2; + info.cheight *= 2; + + } else { // YUV420 == 0 + spatial_syn_frame( &tempfr, info, &dec_pyrTemp[0][i + dist - 1], &spatial_high[0][i], + &spatial_high[1][i], &spatial_high[2][i], filterType ); + // printf("spatial_syn_frame( &dec_pyrTemp[0][%d], &spatial_high[0][%d], &spatial_high[1][%d], &spatial_high[2][%d]);\n", + // i >> t_level, i, i, i); + } + + if ( first_GOP == YES ) + write_frame( tempfr, info, info.decname, curr, info.format ); + else{ + if ( (curr - info.GOPsz + i + dist) <= info.last ){ + write_frame( tempfr, info, info.decname, curr - info.GOPsz + i + dist, info.format ); + // printf(" write_frame( tempfr, curr - info.GOPsz + i + dist %d );\n", curr - info.GOPsz + i + dist ); + } + } + + free_frame( tempfr ); + free_frame( tempfr2 ); + } + + info.ywidth /= 2; + info.yheight /= 2; + info.cwidth /= 2; + info.cheight /= 2; + + } else { // Quarter == 1 + // printf( "denoise_mctf_syn_ezbc: only output spatial LL bands\n" ); + + for( i = 0; i < nfrs; i += dist ) { + if ( filterType == 7 ){ + // scale down frame (correct scaling of the spatial transform) + wcopyframe( &dec_pyrTemp[0][i], &dec_pyrTemp[0][i], ( float )pow( 2, -1 ), info ); + } + + if ( first_GOP == YES ) + write_frame( dec_pyrTemp[0][0], info, info.decname, curr, info.format ); + else { + if ( (curr - info.GOPsz + i + dist) <= info.last ){ + write_frame( dec_pyrTemp[0][i + dist - 1], info, info.decname, curr - info.GOPsz + i + dist, info.format ); + // printf(" write_frame( dec_pyrTemp[0][%d], curr - info.GOPsz + i + dist %d );\n", i, curr - info.GOPsz + i + dist ); + } + } + } + + } + + /********************/ + /* Save information */ + /* for next GOP */ + /********************/ + if ( remaining_frs != 0 ){ + for( i = 1; i < ((YUV420 == 1) ? 2 : 4); i++ ) { + for( j = 1 << t_level; j < info.eff_GOPsz; j+=dist ) { + copyframe( &Four_GOP[i * info.GOPsz + j], &Four_bigGOP[i * info.GOPsz + j - (1 << t_level)], info ); + // printf("-> copyframe( &Four_GOP[%d], &Four_bigGOP[%d] );\n", i * info.GOPsz + j, i * info.GOPsz + j - (1 << t_level)); + } + } + } + +} + + +/* + * mc_syn mc综合网络 + */ +void +mc_syn( int curr, long int *total_bytes_past, videoinfo info, + enum FLAG first_GOP, enum FLAG Level_change, int remaining_frs, int simul_dec, int theo_dec ) +{ + + // GOP header and motion fields + if( info.tPyrLev >= 1 ) { + + synscheme3( curr, info, first_GOP, Level_change, remaining_frs, simul_dec, theo_dec ); + + free_mvs( dec_yfmv, info ); + } + else { // necessary??? KH, 2003-12-12 + copyframe( &dec_pyrFrs[0], &dec_pyrTemp[0][0], info ); + } +} + + +void +mctf_syn_ezbc( int curr, int GOP_counter, long int *total_bytes_past, + videoinfo info, enum FLAG first_GOP, enum FLAG Level_change, + int remaining_frs, int simul_dec, int theo_dec ) +{ + int t_level, nfrs, dist; + int i,j; + float small_y=0, small_u=0, small_v=0, large_y=0, large_u=0, large_v=0; + + /*************/ + /* MV + EZBC */ + /*************/ + if (remaining_frs != 0) { // 如果是最后一帧,这次就不读了 + decode_MV(total_bytes_past, info, GOP_counter, simul_dec, theo_dec); // 解码MV +#ifdef CNN_wavelet + { // 以文本形式读入 + //std::cout << "open file" << info.hpcbindata << std::endl; + // std::ifstream myfile(info.hpcbindata); + // //std::ifstream myfile("BasketballDrill_832x480_50FTFS_GOP1_000.data"); + // if (myfile.is_open() == NULL) + // { + // std::cout << "file open failed!"; + // exit(0); + // } + // float temp = 0; + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // myfile >> temp; + // dec_pyrFrs[pic].Y[i*info.ywidth + j] = temp; + // } + // } + // } + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // myfile >> temp; + // dec_pyrFrs[pic].U[i*info.cwidth + j] = temp; + // } + // } + // } + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // myfile >> temp; + // dec_pyrFrs[pic].V[i*info.cwidth + j] = temp; + // } + // } + // } + // myfile.close(); + } + {// 读二进制文件 + //char name[200] = "BasketballDrill_832x480_50_FTFS_GOP1_000.bindata"; + //std::cout << "open file" << name << std::endl; + //std::ifstream myfile(name, std::ios::binary); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file failed" << std::endl; + // exit(0); + //} + //short int temp = 0; + //myfile.seekg(sizeof(short int) * info.cwidth * info.cheight * 6 * GOP_counter * info.GOPsz); + //std::cout << "GOP_counter" << GOP_counter << std::endl; + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // myfile.read((char*)(&temp), sizeof(short int)); + // dec_pyrFrs[pic].Y[i*info.ywidth + j] = temp; + // } + // } + //} + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // myfile.read((char*)(&temp), sizeof(short int)); + // dec_pyrFrs[pic].U[i*info.cwidth + j] = temp; + // } + // } + //} + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // myfile.read((char*)(&temp), sizeof(short int)); + // dec_pyrFrs[pic].V[i*info.cwidth + j] = temp; + // } + // } + //} + //myfile.close(); + } + {// 读二进制文件 float形式读取 读Y + // //char name_y[200] = "hpcbindata/Tango2_3840x2160_60FTFS_GOP1_000.hpcbindata"; + // //char name_u[200] = "RaceHorses_352x288_30FTFS_GOP1_000_post_u.bindata"; + // //char name_v[200] = "RaceHorses_352x288_30FTFS_GOP1_000_post_v.bindata"; + // std::cout << "open file" << info.hpcbindata << std::endl; + // std::ifstream myfile_y(info.hpcbindata, std::ios::binary); + // //std::ifstream myfile_u(name_u, std::ios::binary); + // //std::ifstream myfile_v(name_v, std::ios::binary); + // if (myfile_y.is_open() == NULL) + // { + // std::cout << "open file_y failed" << std::endl; + // exit(0); + // } + // //if (myfile_u.is_open() == NULL) + // //{ + // // std::cout << "open file_u failed" << std::endl; + // // exit(0); + // //} + // //if (myfile_v.is_open() == NULL) + // //{ + // // std::cout << "open file_v failed" << std::endl; + // // exit(0); + // //} + // myfile_y.seekg(sizeof(float) * info.ywidth * info.yheight * GOP_counter * info.GOPsz); + // //myfile_u.seekg(sizeof(float) * info.cwidth * info.cheight * GOP_counter * info.GOPsz); + // //myfile_v.seekg(sizeof(float) * info.cwidth * info.cheight * GOP_counter * info.GOPsz); + // std::cout << "GOP_counter" << GOP_counter << std::endl; + // float temp = 0; + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // myfile_y.read((char*)(&temp), sizeof(float)); + // dec_pyrFrs[pic].Y[i*info.ywidth + j] = temp; + // } + // } + // } + // //for (int pic = 0; pic < info.GOPsz; pic++) + // //{ + // // for (int i = 0; i < info.cheight; i++) + // // { + // // for (int j = 0; j < info.cwidth; j++) + // // { + // // myfile_u.read((char*)(&temp), sizeof(float)); + // // dec_pyrFrs[pic].U[i*info.cwidth + j] = temp; + // // } + // // } + // //} + // //for (int pic = 0; pic < info.GOPsz; pic++) + // //{ + // // for (int i = 0; i < info.cheight; i++) + // // { + // // for (int j = 0; j < info.cwidth; j++) + // // { + // // myfile_v.read((char*)(&temp), sizeof(float)); + // // dec_pyrFrs[pic].V[i*info.cwidth + j] = temp; + // // } + // // } + // //} + // myfile_y.close(); + // //myfile_u.close(); + // //myfile_v.close(); + } + {// 读二进制文件 float形式读取 读Y + //std::cout << "open file" << info.hpcbindata << std::endl; + //std::ifstream myfile(info.hpcbindata, std::ios::binary); + //if (myfile.is_open() == NULL) + //{ + // std::cout << "open file_y failed" << std::endl; + // exit(0); + //} + // + ////myfile.seekg(sizeof(short int) * info.cwidth * info.cheight * 6 * GOP_counter * info.GOPsz); + //myfile.seekg(sizeof(float) * info.cwidth * info.cheight * 4 * GOP_counter * info.GOPsz); + //std::cout << "GOP_counter" << GOP_counter << std::endl; + ////short int temp = 0; + //float temp = 0; + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // //myfile.read((char*)(&temp), sizeof(short int)); + // myfile.read((char*)(&temp), sizeof(float)); + // dec_pyrFrs[pic].Y[i*info.ywidth + j] = temp; + // } + // } + //} + //myfile.close(); + } + {// 读二进制文件 float形式读取 读YUV + std::cout << "open file" << info.hpcbindata << std::endl; + std::ifstream myfile(info.hpcbindata, std::ios::binary); + if (myfile.is_open() == NULL) + { + std::cout << "open file_y failed" << std::endl; + exit(0); + } + + //myfile.seekg(sizeof(short int) * info.cwidth * info.cheight * 6 * GOP_counter * info.GOPsz); + myfile.seekg(sizeof(float) * info.cwidth * info.cheight * 6 * GOP_counter * info.GOPsz); + std::cout << "GOP_counter" << GOP_counter << std::endl; + //short int temp = 0; + float temp = 0; + for (int pic = 0; pic < info.GOPsz; pic++) + { + for (int i = 0; i < info.yheight; i++) + { + for (int j = 0; j < info.ywidth; j++) + { + //myfile.read((char*)(&temp), sizeof(short int)); + myfile.read((char*)(&temp), sizeof(float)); + //std::cout << temp << std::endl; + dec_pyrFrs[pic].Y[i*info.ywidth + j] = temp; + } + } + } + for (int pic = 0; pic < info.GOPsz; pic++) + { + for (int i = 0; i < info.cheight; i++) + { + for (int j = 0; j < info.cwidth; j++) + { + //myfile.read((char*)(&temp), sizeof(short int)); + myfile.read((char*)(&temp), sizeof(float)); + dec_pyrFrs[pic].U[i*info.cwidth + j] = temp; + } + } + } + for (int pic = 0; pic < info.GOPsz; pic++) + { + for (int i = 0; i < info.cheight; i++) + { + for (int j = 0; j < info.cwidth; j++) + { + //myfile.read((char*)(&temp), sizeof(short int)); + myfile.read((char*)(&temp), sizeof(float)); + dec_pyrFrs[pic].V[i*info.cwidth + j] = temp; + } + } + } + myfile.close(); + } + // ezbc3d_dec_GOP( dec_pyrFrs, info, *total_bytes_past, GOP_counter, curr );// 获得重建帧 + //std::ofstream myfile("dec_Y_float_3.txt", std::ios::app); + //for (int pic = 0; pic < info.GOPsz; pic++) + //{ + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // float temp = dec_pyrFrs[pic].Y[i*info.ywidth + j]; + // myfile << temp << " "; + // } + // myfile << std::endl; + // } + //} + //myfile.close(); +#else + ezbc3d_dec_GOP( dec_pyrFrs, info, *total_bytes_past, GOP_counter, curr );// 获得重建帧 + + //{// 写文本文件 + // char name[256], data_file_name[256], start[10]; + // strncpy(name, info.bitname, strlen(info.bitname) - 4); + // name[strlen(info.bitname) - 4] = '_'; + // snprintf(start, 9, "%03d", info.start); + // for (int i = 0; i < 3; i++) + // { + // name[strlen(info.bitname) - 3 + i] = start[i]; + // } + // name[strlen(info.bitname)] = '\0'; // + // sprintf(data_file_name, "%s.decdata", name); + // std::cout << data_file_name << std::endl; + // std::ofstream myfile(data_file_name, std::ios::app); + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.yheight; i++) + // { + // for (int j = 0; j < info.ywidth; j++) + // { + // //int temp = round(pyrFrs[pic].Y[i*info.ywidth + j]); + // float temp = (dec_pyrFrs[pic].Y[i*info.ywidth + j]); + // myfile << temp << " "; + // } + // myfile << std::endl; + // } + // } + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // //int temp = round(pyrFrs[pic].U[i*info.cwidth + j]); + // float temp = (dec_pyrFrs[pic].U[i*info.cwidth + j]); + // myfile << temp << " "; + // } + // myfile << std::endl; + // } + // } + // for (int pic = 0; pic < info.GOPsz; pic++) + // { + // for (int i = 0; i < info.cheight; i++) + // { + // for (int j = 0; j < info.cwidth; j++) + // { + // //int temp = round(pyrFrs[pic].V[i*info.cwidth + j]); + // float temp = (dec_pyrFrs[pic].V[i*info.cwidth + j]); + // myfile << temp << " "; + // } + // myfile << std::endl; + // } + // } + // myfile.close(); + //} + + +#endif + } + + /********/ + /* MCTF */ + /********/ + + mc_syn( curr, total_bytes_past, info, first_GOP, + Level_change, remaining_frs, simul_dec, theo_dec ); + + /****************/ + /* write frames */ + /****************/ + + t_level = MY_MIN (info.t_level, info.tPyrLev); + dist = 1 << ( t_level ); + + if ( remaining_frs != 0 ){ + nfrs = info.GOPsz; + } else { + nfrs = info.eff_GOPsz; + } + + if( first_GOP == YES ){ + write_frame( dec_pyrTemp[0][0], info, info.decname, curr, info.format ); + // printf(" write_frame( dec_pyrTemp[0][0], curr %d );\n", curr ); + } + else + { + for( i = 0; i < nfrs; i += dist ) + { + if ( (curr - info.GOPsz + i + dist) <= info.last ){ + write_frame( dec_pyrTemp[0][i + dist - 1], info, info.decname, curr - info.GOPsz + i + dist, info.format ); + // printf(" write_frame( dec_pyrTemp[0][%d], curr - info.GOPsz + i + dist %d );\n", i, curr - info.GOPsz + i + dist ); + } + } + } + +} + diff --git a/Interframe EZBC/Utils/inc/ar_code.h b/Interframe EZBC/Utils/inc/ar_code.h new file mode 100644 index 0000000..af9962e --- /dev/null +++ b/Interframe EZBC/Utils/inc/ar_code.h @@ -0,0 +1,565 @@ + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// A R I T H M E T I C C O D E C L A S S E S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// > > > > C++ version 3.02 - 02/01/96 < < < < + +// Amir Said - amir@densis.fee.unicamp.br +// University of Campinas (UNICAMP) +// 13081 Campinas, SP, Brazil + +// William A. Pearlman - pearlman@ecse.rpi.edu +// Rensselaer Polytechnic Institute +// Troy, NY 12180, USA + + +// C++ implementation of the arithmetic-coding algorithm by I.H. Witten, +// R.M. Neal, and J.G. Cleary, published in ``Arithmetic coding for data +// compression,'' {\em Commun. ACM}, vol.~30, pp.~520--540, June 1987. + + +// - - Inclusion - - - - - - - - - - - - - -------- - - - - - - - - - - - - - - +#ifndef AR_CODE +#define AR_CODE +#include +#ifndef General_H +#include "general.h" +#endif + +#include "structN.h" + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Class definitions + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = == = = = = = = = = = = + +const double ZERO_ENT = -1.0; + +double ent( double p0 ); +double xent( double p0, double pp0 ); + +class Histo +{ +protected: + static const double OneLog2; + static const int MaxFreq; +}; + +class HistoBi:public Histo +{ +protected: + int c0; + int c1; +public: + HistoBi( void ) + { + c0 = c1 = 0; + } + HistoBi( HistoBi & hist ) + { + reset( hist ); + } + void reset( int i ) + { + c0 = c1 = i; + } + void reset( HistoBi & hist ) + { + c0 = hist.c0; + c1 = hist.c1; + } + int get_c0( void ) + { + return c0; + } + double get_p0( void ) + { + if( c0 && c1 ) + return double ( c0 ) / double ( c0 + c1 ); + else + return ZERO_ENT; + } + double get_p1( void ) + { + if( c0 && c1 ) + return double ( c1 ) / double ( c0 + c1 ); + else + return ZERO_ENT; + } + int get_c1( void ) + { + return c1; + } + int get_total( void ) + { + return c0 + c1; + } + double entropy0( void ) + { + if( c0 && c1 ) + return -log( double ( c0 ) / double ( c0 + c1 ) )*OneLog2; + else + return ZERO_ENT; + } + double entropy1( void ) + { + if( c0 && c1 ) + return -log( double ( c1 ) / double ( c0 + c1 ) )*OneLog2; + else + return ZERO_ENT; + } + double bit_cost( int bit ) + { + if( bit ) + return entropy1( ); + else + return entropy0( ); + } + double cost0( void ) + { + if( c0 && c1 ) + return c0 * entropy0( ); + else + return ZERO_ENT; + } + double cost1( void ) + { + if( c0 && c1 ) + return c1 * entropy1( ); + else + return ZERO_ENT; + } + double total_cost( void ) + { + if( c0 && c1 ) + return cost1( ) + cost0( ); + else + return ZERO_ENT; + } + double entropy_avg( void ) + { + if( c0 && c1 ) + return ( cost0( ) + cost1( ) ) / ( double )( c0 + c1 ); + else + return ZERO_ENT; + } + void update( int c ) + { + if( c ) + c1++; + else + c0++; + } + void reset( void ) + { + c0 = c1 = 1; + } + void add_to_c0( int n ) + { + c0 += n; + } + void add_to_c1( int n ) + { + c1 += n; + } + int get_min( void ) + { + return ( c0 < c1 ) ? c0 : c1; + } +}; + + +class HistoBiModel:public HistoBi +{ +protected: + friend class Encoder; + friend class Decoder; + int max_f; + static float ThreshRecScale; //max allowed XH after recursives_cale() + static float ThreshUpdate; //max allowed XH after update() + static int MinMaxFreq; + static int InitMaxFreq; + static int UpdateScheme; + static int MAX_MIN; + void update( int c ); + void update_test_total( void ); + void update_test_total_and_min( void ); +public: + HistoBiModel( int max_freq = InitMaxFreq ):HistoBi( ), max_f( max_freq ) + { + } + HistoBiModel( HistoBi & hist ):HistoBi( hist ) + { + } + void set_symbols( int s ) + { + max_f = InitMaxFreq; + if( s == 2 ) + reset( 1 ); + else { + fprintf( stderr, "set_symbols: model is binary.\n" ); + exit( 1 ); + } + } + void set_symbols( int s, int max_freq ) + { + set_symbols( s ); + max_f = max_freq; + } + void scale( void ) + { + c0 = ( c0 + 1 ) >> 1; + c1 = ( c1 + 1 ) >> 1; + } + void recursive_scale( void ); + void taub_scale( int min_thre = 2, int total_thre = 32, int trunc_flag = + 0 ); + void set_max_freq( int max_freq ) + { + while( get_total( ) >= max_freq ) + scale( ); + max_f = max_freq; + } + void reset_maxf( int max_freq ) + { + max_f = max_freq; + } + int get_maxf( void ) + { + return max_f; + } + void set_model( HistoBiModel & model ) + { + reset( model ); + max_f = model.max_f; + } + void set_update_scheme( int scheme ) + { + UpdateScheme = scheme; + } +}; + + +class Adaptive_Model +{ + // . private data . . . . . . . . . . . . . . . . . . + + int max_f, nsb, *cum_f, *freq, *indx_to_sb, *sb_to_indx; + + // . friend classes . . . . . . . . . . . . . . . . . + + friend class Encoder; + + friend class Decoder; + + // . private functions . . . . . . . . . . . . . . . . + + void update( int index ); + + int select_symbol( long value, long *l, long *h ); + + void new_interval( int symb, long *l, long *h ); + + // . constructors and destructor . . . . . . . . . . . . . + + public:Adaptive_Model( void ) + { + nsb = 0; + cum_f = NULL; + } + + Adaptive_Model( int ns ) + { + nsb = 0; + cum_f = NULL; + set_symbols( ns ); + } + + ~Adaptive_Model( void ) + { + nsb = 0; + delete cum_f; + } + + // . public functions . . . . . . . . . . . . . . . . + + void reset( void ); + + void set_symbols( int ns ); + + void set_symbols( int s, int max_freq ); + + float get_cost( int symbol ); + + void scale( void ); + + void set_max_freq( int max_freq ); + + void set_model( Adaptive_Model & model ); +}; // end definition of class < Adaptive_Model > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +class Encoder +{ + // . private data . . . . . . . . . . . . . . . . . . + FILE *out_file; + + int bit_buffer, bit_index, closed, temp; + + long byte_counter, symbol_counter, low, high, bits_to_follow; + + // . private functions . . . . . . . . . . . . . . . . + + void bit_plus_follow( int b ); + + void update_interval( void ); + + void reset( char *file_name ); + + void reset_append( char *file_name ); + + void stop( void ); + + // . constructor . . . . . . . . . . . . . . . . . . + + public:Encoder( void ) + { + byte_upto_bitplane = NULL; + closed = 1; + } //062602 + ~Encoder( void ) + { //printf("run destructor of Encoder (ar_code.h)\n"); + if( byte_upto_bitplane ) + delete[]byte_upto_bitplane; + } + + // . public data . . . . . . . . . . . . . . . . + + long int *byte_upto_bitplane; // allocated in 062602 + + char temp_name[250]; + + static int object_count; //062602 + + + // . public functions . . . . . . . . . . . . . . . . + + long bytes_used( void ) + { //062602 + if( bit_index == 8 ) + return byte_counter; + else + return byte_counter + 1; + + } + + long symbols_encoded( void ) + { + return symbol_counter; + } + + //int getCount(void) {return object_count;} + + void new_open_file( void ); //062602 + + void open_file( void ); + + void new_open_file( char *file_name ); + + void open_file( char *file_name ); + + void close_file( char *file_name ); + + void close_file( void ); + + void code_symbol( int s, Adaptive_Model & ); + + void code_bits( int bits, int word ); + + int code_bit( int bit ); + // void code_bit_arith(int bit, HistoBiModel &); + void code_symbol( int bit, HistoBiModel & ); +}; // end definition of class < Encoder > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +class Decoder +{ + // . private data . . . . . . . . . . . . . . . . . . + + + int bit_buffer, bit_index, extra_bits, ext_stop, closed; + + long low, high, value, symbol_counter, byte_counter, mss_symbols; + + // . private functions . . . . . . . . . . . . . . . . + + void input_byte( void ); + + void update_interval( void ); + + // . constructor . . . . . . . . . . . . . . . . . . + + public:int byte_budget; // not include header + FILE *in_file; + + + Decoder( void ) + { + closed = 1; + } + + // . public functions . . . . . . . . . . . . . . . . + + int end_of_file( void ) + { + return ( symbol_counter >= mss_symbols ); + } + + long bytes_used( void ) + { + return byte_counter; + } + + long symbols_decoded( void ) + { + return symbol_counter; + } + + long message_symbols( void ) + { + return mss_symbols; + } + + void new_open_file( char *file_name, long shift_bytes ); + void new_open_file( char *file_name, long shift_bytes, long budget ); //062602 + + void open_file( char *file_name ); + + void close_file( void ); + + int decode_symbol( Adaptive_Model & ); + + int decode_bits( int bits ); + + int decode_bit( void ); + // int decode_bit_arith(HistoBiModel &hist); + int decode_symbol( HistoBiModel & hist ); +}; // end definition of class < Decoder > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Inline functions + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +inline void +HistoBiModel::update_test_total( void ) +{ + if( get_total( ) == max_f ) + scale( ); +} + +inline void +HistoBiModel::update_test_total_and_min( void ) +{ + if( get_min( ) == MAX_MIN || get_total( ) == max_f ) + scale( ); +} + +//#if 0 + +inline void +HistoBiModel::update( int c ) +{ + //update_test_total_and_min(); //suggested by Taubman + update_test_total( ); + if( c == 0 ) + c0++; + else + c1++; +} + +//#endif + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +inline int +Encoder::code_bit( int bit ) +{ + long lm1 = low - 1, range = high - lm1; + if( bit ) + low += range >> 1; + else + high = lm1 + ( range >> 1 ); + + update_interval( ); + return bit; +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +inline void +Encoder::code_symbol( int bit, HistoBiModel & hist ) +{ + long lm1 = low - 1; + long range = ( high - lm1 ) * hist.get_c0( ) / hist.get_total( ); + + if( bit ) + low += range; + else + high = lm1 + range; + + hist.update( bit ); + update_interval( ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +inline int +Decoder::decode_bit( void ) +{ + + long lm1 = low - 1, range = high - lm1; + int bit = int ( ( ( ( value - lm1 ) << 1 ) - 1 ) / range ); + + if( bit ) { + low += range >> 1; + } else + high = lm1 + ( range >> 1 ); + + update_interval( ); + return bit; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +inline int +Decoder::decode_symbol( HistoBiModel & hist ) +{ + + long lm1 = low - 1, range = high - lm1; + + int cum = int ( ( ( value - lm1 ) * hist.get_total( ) - 1 ) / range ); + + int bit = ( cum >= hist.get_c0( ) ); + range = range * hist.get_c0( ) / hist.get_total( ); + + if( bit ) + low += range; + else + high = lm1 + range; + + hist.update( bit ); + update_interval( ); + return bit; +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +#endif +// end of file < Ar_Code.H > diff --git a/Interframe EZBC/Utils/inc/general.h b/Interframe EZBC/Utils/inc/general.h new file mode 100644 index 0000000..f9c7fd0 --- /dev/null +++ b/Interframe EZBC/Utils/inc/general.h @@ -0,0 +1,197 @@ + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// G E N E R A L P U R P O S E F U N C T I O N S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// > > > > C++ version 1.08 - 02/01/96 < < < < + +// Amir Said - amir@densis.fee.unicamp.br +// University of Campinas (UNICAMP) +// Campinas, SP 13081, Brazil + +// William A. Pearlman - pearlman@ecse.rpi.edu +// Rensselaer Polytechnic Institute +// Troy, NY 12180, USA + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// Copyright (c) 1995, 1996 Amir Said & William A. Pearlman + +// This program is Copyright (c) by Amir Said & William A. Pearlman. +// It may not be redistributed without the consent of the copyright +// holders. In no circumstances may the copyright notice be removed. +// The program may not be sold for profit nor may they be incorporated +// in commercial programs without the written permission of the copyright +// holders. This program is provided as is, without any express or +// implied warranty, without even the warranty of fitness for a +// particular purpose. + + +// - - Control definition - - - - - - - - - - - - - - - - - - - - - - - + +#ifndef General_H +#define General_H + +// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include +#include +#include +#include +#undef abs + + +// - - Type definitions - - - - - - - - - - - - - - - - - - - - - - - - + +#define boolean int +#define true 1 +#define false 0 + +typedef char Char_Line[80]; +typedef unsigned char byte; +typedef unsigned long word; + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Macros + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +#define NEW_VECTOR(X,N,TYPE,MSG) Test_Pointer(X = new TYPE[N], MSG) + +#define CREATE_VECTOR(X,N,TYPE,MSG) TYPE * X = new TYPE[N];\ + Test_Pointer(X, MSG) + +#define NEW_OBJECT(X,TYPE,MSG) Test_Pointer(X = new TYPE, MSG) + +#define CREATE_OBJECT(X,TYPE,MSG) TYPE * X = new TYPE;\ + Test_Pointer(X, MSG) + +#define DELETE_VECTOR(X) delete [] X; X = NULL + +#define DELETE_OBJECT(X) delete X; X = NULL + +#define SWAP(X,Y,T) T = X; X = Y; Y = T + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Inline functions + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +_inline int Min( int a, int b ){ + return ( a < b ? a : b ); +} + +_inline int Max( int a, int b ){ + return ( a > b ? a : b ); +} + +_inline long Round( double x ) +{ + return ( (x >= 0.0) ? long ( x + 0.5 ) : long ( x - 0.5 ) ); +} + +_inline float Sqr( float x ) +{ + return ( x * x ); +} + +_inline double dBW( double x ) +{ + return 4.34294481904 * log( x ); +} + +_inline double dBW_inv( double x ) +{ + return exp( 0.2302585093 * x ); +} + +_inline double log2( double x ) +{ + assert( x >= 0); + return log((float)x) / log((float)2); +} + +_inline int log2( int N ) +{ + assert( N >= 0 ); + int i; + for( i = 0; N > 1; N >>= 1, i++ ); + return ( i ); +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Function prototypes + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +void Warning( char * ); + +void Error( char * ); + +void Test_Pointer( void *ptr, char *msg = NULL ); + +//void Pause( void ); + +//char *Input_Line( char *msg = NULL, char *res = NULL ); + +//int Input_Int( char * ); + +//float Input_Float( char * ); + +//boolean Input_Answer( char * ); + +//FILE *Open_File( char *msg, char *mode ); + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Definition of the class < Chronometer > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +class Chronometer +{ + // . private data . . . . . . . . . . . . . . . . . . + + int stat; // chronometer status: 0 = off, 1 = on + + long mark, elp; // initial and elapsed time + + // . constructor . . . . . . . . . . . . . . . . . . + +public: + + Chronometer( void ) + { + elp = stat = 0; + } + + // . public functions . . . . . . . . . . . . . . . . + + void reset( void ) + { + elp = stat = 0; + } + + void start( char *s = NULL ); + + void stop( void ); + + float read( void ); + + void display( char *s = NULL ); + +}; // end definition of class < Chronometer > + +#endif + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// end of file < General.H > diff --git a/Interframe EZBC/Utils/inc/ifc.h b/Interframe EZBC/Utils/inc/ifc.h new file mode 100644 index 0000000..766da05 --- /dev/null +++ b/Interframe EZBC/Utils/inc/ifc.h @@ -0,0 +1,81 @@ +#ifndef _IFC_H +#define _IFC_H + +#include + +/*****************************************************************************/ +/* std_int */ +/*****************************************************************************/ + +#if (INT_MAX == 2147483647) +typedef int std_int; +#elif (LONG_MAX == 2147483647) +typedef long int std_int +#else +# error "Platform does not support 32-bit integers" +#endif + +#define MAX_STD_INT ((std_int) 0x7FFFFFFF) +#define MIN_STD_INT ((std_int)-0x80000000) + +/*****************************************************************************/ +/* std_short */ +/*****************************************************************************/ + +#if (SHRT_MAX == 32767) +typedef short int std_short; +#else +# error "Platform does not support 16-bit integers" +#endif + +/*****************************************************************************/ +/* std_ushort */ +/*****************************************************************************/ + +#if (SHRT_MAX == 32767) +typedef unsigned short int std_ushort; +#else +# error "Platform does not support 16-bit integers" +#endif + +/*****************************************************************************/ +/* std_byte */ +/*****************************************************************************/ + +typedef unsigned char std_byte; + + +/* ========================================================================= */ +/* -------------------- IMPLEMENTATION PRECISION --------------------------- */ +/* ========================================================================= */ + +#ifdef IMPLEMENT_32 +# define IMPLEMENTATION_PRECISION 32 +#endif /* IMPLEMENT_32 */ + +#ifdef IMPLEMENT_16 +# define IMPLEMENTATION_PRECISION 16 +#endif /* IMPLEMENT_16 */ + +#ifndef IMPLEMENTATION_PRECISION +# define IMPLEMENTATION_PRECISION 32 /* Must be one of 16 or 32 currently. */ +#endif /* IMPLEMENTATION_PRECISION */ + +#if (IMPLEMENTATION_PRECISION == 16) +typedef short int ifc_int; +#elif (IMPLEMENTATION_PRECISION == 32) +# if (INT_MAX == 2147483647) +typedef int ifc_int; +# elif (LONG_MAX == 2147483647) +typedef long int ifc_int; +# else +# error "Platform does not support 32 bit integers!" +# endif +#else +# error "IMPLEMENTATION_PRECISION must be one of 16 or 32!" +#endif + +#define MIN_IFC_INT ((ifc_int)((-1)<<(IMPLEMENTATION_PRECISION-1))) +#define MAX_IFC_INT (~MIN_IFC_INT) + +#endif diff --git a/Interframe EZBC/Utils/inc/image_bw.h b/Interframe EZBC/Utils/inc/image_bw.h new file mode 100644 index 0000000..3896a37 --- /dev/null +++ b/Interframe EZBC/Utils/inc/image_bw.h @@ -0,0 +1,238 @@ + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// I M A G E C L A S S +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// > > > > C++ version 11.04 - 02/01/96 < < < < +// Amir Said - amir@densis.fee.unicamp.br +// University of Campinas (UNICAMP) +// Campinas, SP 13081, Brazil +// William A. Pearlman - pearlman@ecse.rpi.edu +// Rensselaer Polytechnic Institute +// Troy, NY 12180, USA +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Copyright (c) 1995, 1996 Amir Said & William A. Pearlman +// This program is Copyright (c) by Amir Said & William A. Pearlman. +// It may not be redistributed without the consent of the copyright +// holders. In no circumstances may the copyright notice be removed. +// The program may not be sold for profit nor may they be incorporated +// in commercial programs without the written permission of the copyright +// holders. This program is provided as is, without any express or +// implied warranty, without even the warranty of fitness for a +// particular purpose. +// - - External definitions - - - - - - - - - - - - - - - - - - - - - - +#ifndef _IMAGE_BW_ +#define _IMAGE_BW_ + +#include +#ifdef LOSSLESS + +typedef int Pel_Type; +#define ABS abs + +#else + +typedef float Pel_Type; +#define ABS fabs + +#endif + + +struct Image_Coord +{ + int x, y; + Image_Coord( void ) + { + x = y = 0; + } + Image_Coord( int i, int j ) + { + x = i; + y = j; + } + Image_Coord( int i ) + { + x = y = i; + } + Image_Coord & operator -= ( Image_Coord in_ord ) { + x -= in_ord.x; + y -= in_ord.y; + return *this; + } + Image_Coord & operator += ( Image_Coord in_ord ) { + x += in_ord.x; + y += in_ord.y; + return *this; + } + Image_Coord operator + ( Image_Coord in_ord ) + { + in_ord.x += x; + in_ord.y += y; + return in_ord; + } + Image_Coord operator - ( Image_Coord in_ord ) + { + in_ord.x = x - in_ord.x; + in_ord.y = y - in_ord.y; + return in_ord; + } + Image_Coord t( ) + { + return Image_Coord( y, x ); + } +}; + +//ostream & operator << ( ostream & out, Image_Coord & in_ord ); + +// - - Class definition - - - - - - - - - - - - - - - - - - - - - - - - + +enum FRAME_RES +{ SD, SD2, CIF, HD, INVALID_RES }; + + +class Image_BW +{ + // . private data . . . . . . . . . . . . . . . . . . + + Image_Coord dim, pdim; // 表示图像的大小 coordinates坐标 + + float mse; //Added on 11.26.2017 + + int levels, bytes, mean, shift, smoothing; // level:空域进行小波变换的次数 + + Pel_Type **coeff; + + // . private functions . . . . . . . . . . . . . . . . + + int max_levels( int ); + + void assign_mem( Image_Coord, int ); + + void free_mem( void ); + + void extend( void ); + + // . constructor and destructor . . . . . . . . . . . . . + +public: + + int s_level; + enum FRAME_RES frame_res; + int high_band; //Added on 08.14.2018 + Image_BW( void ) + { + levels = -1; + } +// Image_BW(const Image_BW&); + ~Image_BW( void ) + { + free_mem( ); + } + + // . public functions . . . . . . . . . . . . . . . . + + Pel_Type & operator[]( const Image_Coord & c ) { + return coeff[c.x][c.y]; + } + + Pel_Type & operator( )( int i, int j ) { + return coeff[i][j]; + } + + Pel_Type *address( const Image_Coord & c ) + { + return coeff[c.x] + c.y; + } + + Image_Coord dimension( void ) + { + return dim; + } + + Image_Coord pyramid_dim( void ) + { + return pdim; + } + + int transform_mean( void ) + { + return mean; + } + + int mean_shift( void ) + { + return shift; + } + + int smoothing_factor( void ) + { + return smoothing; + } + + int pyramid_levels( void ) + { + return levels; + } // accurately this subband decomposition level + + int pixel_bytes( void ) + { + return bytes; + } + + float compare( char *file_name ); + + void read_pic( Image_Coord, char *file_name, int nbytes = 1 ); + + void read_float_image( Image_Coord, float *image ); + + void write_pic( char *file_name ); + + void write_float_image( float *image ); + + void reset( Image_Coord ); + + void reset( int m, int mshift, int smoothing_factor = 0 ); + + void reset( Image_Coord, int nbytes, int m, int mshift, + int smoothing_factor = 0 ); + + void transform( int smoothing_factor = 0 ); + + void scale_down( void ); + + void scale_up( void ); + + void subtract_mean( ); + + void intensity_density( ); + + void density_intensity( ); + + void add_mean( ); + + void recover( void ); + + void one_step_decompose(int dx, int dy, int lenx, int leny); + void one_step_recover(int dx, int dy, int lenx, int leny); + + void dispose( void ) + { + free_mem( ); + } + + float get_mse( ) //Added on 11.26.2017 + { + return mse; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + void write_raw( char *filename ); + + void read_raw( Image_Coord d, char *filename ); + +}; // end definition of class < Image_BW > + +#endif +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// end of file < Image_BW.H > diff --git a/Interframe EZBC/Utils/inc/subband.h b/Interframe EZBC/Utils/inc/subband.h new file mode 100644 index 0000000..1dfd5ff --- /dev/null +++ b/Interframe EZBC/Utils/inc/subband.h @@ -0,0 +1,275 @@ +/* ========================================================================= */ +/* Description: wavelet decomposotion structure */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#ifndef _SUBBAND_ +#define _SUBBAND_ + +#include "ifc.h" +#include "general.h" +#include "image_bw.h" + +typedef ifc_int SUB_COEFF_TYPE; + +class SubbandLayer; //forward def. +class SubSet; +class SubSetLayer; + +typedef SubbandLayer SUBBAND_TYPE; + +const SUB_COEFF_TYPE MAX_SUB_COEFF = MAX_IFC_INT; +const SUB_COEFF_TYPE MIN_SUB_COEFF = MIN_IFC_INT; +const SUB_COEFF_TYPE SIGN_BIT = MIN_IFC_INT; +const SUB_COEFF_TYPE MAG_MASK = ~SIGN_BIT; +const std_short PARITY_MASK_SHT = ~( ( std_short ) 1 ); + +// old definition +const SUB_COEFF_TYPE sign = 1 << ( 8 * sizeof( SUB_COEFF_TYPE ) - 1 ); +const SUB_COEFF_TYPE SIGN = 1 << ( 8 * sizeof( SUB_COEFF_TYPE ) - 1 ); + +#define EXTRA_BIT 1 +#define NO_CHILD -1 + +enum ORIENTATION +{ LL, HL, LH, HH }; + +class Subband +{ +protected: + int band_idx, transpose_flag; + Image_Coord dim; + Image_Coord mem_org; + Image_Coord mem_dim; + SUB_COEFF_TYPE **coeff; + SubSet *wp; + + void alloc_coeff( void ); + void free_coeff( void ); + /*static const SUB_COEFF_TYPE SIGN = 1 << (8 * sizeof(SUB_COEFF_TYPE) - 1); */ + +public: + Subband( void ) + { + coeff = NULL; + } + Subband( Image_Coord dimen ); + Subband( Image_Coord dimen, Image_Coord memo_org, Image_Coord memo_dim ); + virtual ~ Subband( void ) + { + free_coeff( ); + } + int initialization( Image_Coord dimen, Image_Coord memo_org, + Image_Coord memo_dim ); + int initialization( Image_Coord dimen ) + { + return initialization( dimen, 0, dimen ); + } + void transpose( void ); + void remove( void ) + { + free_coeff( ); + } + void reset_coeff( ); + SUB_COEFF_TYPE *get_coeff_mem_head_ptr( ) + { + return &( coeff[mem_org.x][mem_org.x] ); + } + SUB_COEFF_TYPE *get_coeff_org_ptr( ) + { + return &( coeff[0][0] ); + } + SUB_COEFF_TYPE **get_coeff( ) + { + return coeff; + } + SUB_COEFF_TYPE & operator[]( const Image_Coord & c ) { + return coeff[c.x][c.y]; + } + SUB_COEFF_TYPE & operator( )( int i, int j ) { + return coeff[i][j]; + } + SUB_COEFF_TYPE *address( const Image_Coord & c ) + { + return coeff[c.x] + c.y; + } + Image_Coord get_dim( void ) + { + return dim; + } + Image_Coord get_mem_dim( void ) + { + return mem_dim; + } + Image_Coord get_mem_org( void ) + { + return mem_org; + } + int get_transpose_flag( void ) + { + return transpose_flag; + } + void set_wp( SubSet * subset ) + { + wp = subset; + } + SubSet *get_wp( void ) + { + return wp; + } + void set_band_idx( int idx ) + { + band_idx = idx; + } + int get_band_idx( ) + { + return band_idx; + } + int get_band_level( ); + int get_child_band_idx( ); + int get_grand_child_band_idx( ); + int get_band_size( void ) + { + return dim.x * dim.y; + } +}; + +class SubbandLayer:public Subband // 子带层 +{ +protected: + Image_Coord org; + int par_ind, max_msb; + + //static variable + static int lsb; +public: + + SubbandLayer( void ):Subband( ) + { + } + SubbandLayer( Image_BW & image_pyr, Image_Coord org, Image_Coord dim, + int par ); + SubbandLayer( Image_Coord org, Image_Coord dim, int par, int msb ); + ~SubbandLayer( void ) + { + } + void remove( void ) + { + free_coeff( ); + } + Image_Coord get_org( void ) + { + return org; + } + int get_par( void ) + { + return par_ind; + } + int get_max_msb( void ) + { + return max_msb; + } + void set_max_msb( int msb_digit ) + { + max_msb = msb_digit; + } + double subband_energy( ); + int get_lsb( void ) + { + return lsb; + } + int get_sign( int i, int j ) + { + return ( coeff[i][j] & SIGN ) != 0; + } + void set_sign( int bit, int i, int j ) + { + if( bit ) + coeff[i][j] |= SIGN; + } + SUB_COEFF_TYPE get_mag( int i, int j ) + { + return coeff[i][j] & MAG_MASK; + } + int read_bit( SUB_COEFF_TYPE mask, int i, int j ) + { + return coeff[i][j] & mask; + } + void write_bit( int bit, SUB_COEFF_TYPE mask, int i, int j ) + { + if( bit ) + coeff[i][j] |= mask; + } + enum ORIENTATION get_orientation( ); +}; + + +class SubSet +{ +protected: + int pyr_levels; // 空域分解的次数 + int nband; // 空域分解得到的子带的数量 nband = 1 + 3 * pyr_levels + Image_Coord pdim; + SUBBAND_TYPE **bands; + +public: + SubSet( void ) + { + bands = NULL; + nband = 0; + } + ~SubSet( void ) + { + if( bands ) { + for( int i = 0; i < nband; i++ ) + delete bands[i]; + delete[]bands; + } + } + SUBBAND_TYPE *operator[] ( int k ) + { + return bands[k]; + } + SUBBAND_TYPE *get_band_ptr( int k ) + { + return bands[k]; + } + int get_pyr_levels( void ) + { + return pyr_levels; + } + int get_nband( void ) + { + return nband; + } + Image_Coord get_pdim( void ) + { + return pdim; + } +}; + + +class SubSetLayer:public SubSet +{ +protected: + int max_msb; + +public: + SubSetLayer( void ):SubSet( ) + { + max_msb = -1; + } + //msb_layers = NULL: initialize for encoding + //OW nitialize for decoding + SubSetLayer( Image_BW & image_pyr, int s_level, int *msb_layers = NULL ); + void SubSetLayer2Image_BW( Image_BW & image_pyr ); + int get_max_msb( void ) + { + return max_msb; + } + void reset_max_msb( void ); + int cal_band_level( int band_idx ); +}; +#endif diff --git a/Interframe EZBC/Utils/src/ar_code.cpp b/Interframe EZBC/Utils/src/ar_code.cpp new file mode 100644 index 0000000..3c32357 --- /dev/null +++ b/Interframe EZBC/Utils/src/ar_code.cpp @@ -0,0 +1,793 @@ +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// A R I T H M E T I C C O D E C L A S S E S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// > > > > C++ version 3.02 - 02/01/96 < < < < + +// Amir Said - amir@densis.fee.unicamp.br +// University of Campinas (UNICAMP) +// 13081 Campinas, SP, Brazil + +// William A. Pearlman - pearlman@ecse.rpi.edu +// Rensselaer Polytechnic Institute +// Troy, NY 12180, USA + +// C++ implementation of the arithmetic-coding algorithm by I.H. Witten, +// R.M. Neal, and J.G. Cleary, published in ``Arithmetic coding for data +// compression,'' {\em Commun. ACM}, vol.~30, pp.~520--540, June 1987. + + + +// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - ------- - - - - +#include "stdio.h" +#include "string.h" +#include "ar_code.h" + + +// - - Constants - - - - - - - - - - - - - - - - - - - - - - - - - - -------- - + +int + Encoder::object_count = + 0; + + +const int + Histo::MaxFreq = + 16383; // 2^14 - 1 + +const double + Histo::OneLog2 = + 1 / +log( 2. ); + +float + HistoBiModel::ThreshRecScale = ( float ) + 0.05; + +float + HistoBiModel::ThreshUpdate = ( float ) + 0.005; + +int + HistoBiModel::MinMaxFreq = + 32; // 1 << 5 + +int + HistoBiModel::InitMaxFreq = + 512; //16383; + +int + HistoBiModel::UpdateScheme = + 0; + +int + HistoBiModel::MAX_MIN = + 16; //max allowed get_min() used in update() + +static const int + MaxFrequency = + 16383; // 2^14 - 1 + +static const int + MaxSymbols = + 1024; + +static const float + one_log2 = ( float ) + 1.442695; + +static const int + CodeValueBits = + 16; + +static const long + TopValue = + 65535L; // 2^CodeValueBits - 1 + +static const long + FirstQtr = + 16384L; // (TopValue + 1) / 4 + +static const long + Half = + 32768L; // 2 * FirstQtr + +static const long + ThirdQtr = + 49152L; // 3 * FirstQtr + + +static char * + R_MSG = + "< Encoder > cannot read from file"; + +static char * + W_MSG = + "< Decoder > cannot write to file"; + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Functions of the base class < Adaptive_Model > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// - - Private functions - - - - - - - - - - - - - - - - - - - - - - - - +/* +double +fabs(double ftmp) +{ + return (ftmp > 0)? ftmp: (-1) * ftmp; +} +*/ +double +ent( double p0 ) +{ + return ( ( -p0 ) * log( p0 ) - ( 1 - p0 ) * log( 1 - p0 ) ) * one_log2; +} + +double +xent( double p0, double pp0 ) +{ + return fabs( ent( p0 ) - ent( pp0 ) ); +} + +void +HistoBiModel::recursive_scale( ) +{ + HistoBiModel tmp_model( *this ); + int count = 0; + double org_ent = entropy_avg( ); + + tmp_model.scale( ); + while( ( fabs( org_ent - tmp_model.entropy_avg( ) ) < ThreshRecScale ) && tmp_model.get_min( ) > 1 ) { // avoid infinite loop caused by c0=c1=1; + tmp_model.scale( ); + count++; + } + for( ; count > 0; count--, scale( ) ); + +} + +//---------------------------------------------------------------------------- + +// taub_scale() + +// suggested by Taubman in EBCOT + +//---------------------------------------------------------------------------- +void +HistoBiModel::taub_scale( int min_thre, int total_thre, int trunc_flag ) +{ + + assert( ( min_thre > 0 ) && ( total_thre > 2 ) ); + if( trunc_flag ) + while( ( get_min( ) > min_thre ) && ( get_total( ) > total_thre ) ) { + c0 >>= 1; + c1 >>= 1; + } //truncation + else + while( ( get_min( ) > min_thre ) && ( get_total( ) > total_thre ) ) { + scale( ); + } //ceiling + +} + +//----------------------------------------------------------------------------- + + +void +Adaptive_Model::update( int index ) +{ + int i, j; + if( cum_f[0] == max_f ) { + int cum = 0; + for( j = nsb; j >= 0; j-- ) { + cum_f[j] = cum; + cum += ( freq[j] = ( ( freq[j] + 1 ) / 2 ) ); + } + } + + for( i = index; freq[i] == freq[i - 1]; i-- ); + if( i < index ) { + int sb_1 = indx_to_sb[i], sb_2 = indx_to_sb[index]; + indx_to_sb[i] = sb_2; + indx_to_sb[index] = sb_1; + sb_to_indx[sb_1] = index; + sb_to_indx[sb_2] = i; + } + + freq[i]++; + while( i > 0 ) + cum_f[--i]++; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +int +Adaptive_Model::select_symbol( long value, long *l, long *h ) +{ + long lm1 = *l - 1, range = *h - lm1; + int index, cum = int ( ( ( value - lm1 ) * cum_f[0] - 1 ) / range ); + + for( index = 1; cum_f[index] > cum; index++ ); + + *h = lm1 + ( range * cum_f[index - 1] ) / cum_f[0]; + *l += ( range * cum_f[index] ) / cum_f[0]; + + int symbol = indx_to_sb[index]; + update( index ); + return symbol; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Adaptive_Model::new_interval( int symbol, long *l, long *h ) +{ + int index = sb_to_indx[symbol]; + long lm1 = *l - 1, range = *h - lm1; + *h = lm1 + ( range * cum_f[index - 1] ) / cum_f[0]; + *l += ( range * cum_f[index] ) / cum_f[0]; + update( index ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - Public functions - - - - - - - - - - - - - - - - - - - - - - - - + +void +Adaptive_Model::set_symbols( int s ) +{ + if( ( s < 2 ) || ( s > MaxSymbols ) ) + Error( "invalid number of < Adaptive_Model > symbols" ); + + if( s != nsb ) { + nsb = s++; + max_f = Min( nsb << 5, MaxFrequency ); + delete[]cum_f; + if( ( cum_f = new int[s << 2] ) == NULL ) + Error( "< Adaptive_Model > : insufficient memory" ); + freq = cum_f + s; + indx_to_sb = freq + s; + sb_to_indx = indx_to_sb + s; + } + reset( ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void +Adaptive_Model::set_symbols( int s, int max_freq ) +{ + + set_symbols( s ); + max_f = max_freq; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Adaptive_Model::reset( void ) +{ + if( nsb == 0 ) + return; + + int i; + for( i = 0; i <= nsb; i++ ) { + freq[i] = 1; + cum_f[i] = nsb - i; + } + for( freq[0] = i = 0; i < nsb; i++ ) { + sb_to_indx[i] = i + 1; + indx_to_sb[i + 1] = i; + } +} + + +//H------ stat-data begin-------------------------------- + +float +Adaptive_Model::get_cost( int symbol ) +{ + int index = sb_to_indx[symbol]; + + return ( ( float ) + ( -log + ( ( double )( cum_f[index - 1] - cum_f[index] ) / + ( double )cum_f[0] ) * one_log2 ) ); + +} + +void +Adaptive_Model::scale( void ) +{ + int j, cum = 0; + + for( j = nsb; j >= 0; j-- ) { + cum_f[j] = cum; + cum += ( freq[j] = ( ( freq[j] + 1 ) / 2 ) ); + } +} + + +void +Adaptive_Model::set_max_freq( int max_freq ) +{ + while( cum_f[0] >= max_freq ) + scale( ); + max_f = max_freq; +} + +void +Adaptive_Model::set_model( Adaptive_Model & model ) +{ + int i; + + if( nsb != model.nsb ) { + fprintf( stderr, "set_model: error, not the model of the same size.\n" ); + exit( 1 ); + } + for( i = 0; i <= nsb; i++ ) { + freq[i] = model.freq[i]; + cum_f[i] = model.cum_f[i]; + } + for( i = 0; i < nsb; i++ ) { + sb_to_indx[i] = model.sb_to_indx[i]; + indx_to_sb[i] = model.indx_to_sb[i]; + } +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Functions of the class < Encoder > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// - - Private functions - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::bit_plus_follow( int b ) +{ + bit_buffer >>= 1; + if( b ) + bit_buffer |= 0x80; + if( !( --bit_index ) ) { + byte_counter++; + bit_index = 8; + if( putc( bit_buffer, out_file ) == EOF ) + Error( W_MSG ); + } + while( bits_to_follow > 0 ) { + bits_to_follow--; + bit_buffer >>= 1; + if( !b ) + bit_buffer |= 0x80; + if( !( --bit_index ) ) { + byte_counter++; + bit_index = 8; + if( putc( bit_buffer, out_file ) == EOF ) + Error( W_MSG ); + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::update_interval( void ) +{ + ++symbol_counter; + for( ;; ) { + if( high < Half ) + bit_plus_follow( 0 ); + else if( low >= Half ) { + bit_plus_follow( 1 ); + low -= Half; + high -= Half; + } else if( ( low >= FirstQtr ) && ( high < ThirdQtr ) ) { + bits_to_follow++; + low -= FirstQtr; + high -= FirstQtr; + } else + break; + low <<= 1; + high += high + 1; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::reset( char *file_name ) +{ + if( !closed ) + Error( "< Encoder > file already open" ); + + out_file = ( temp ? tmpfile( ) : fopen( file_name, "wb" ) ); + if( out_file == NULL ) + Error( W_MSG ); + symbol_counter = low = bits_to_follow = bit_buffer = closed = 0; + bit_index = 8; + high = TopValue; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::reset_append( char *file_name ) +{ + if( !closed ) + Error( "< Encoder > file already open" ); + + out_file = ( temp ? tmpfile( ) : fopen( file_name, "a+b" ) ); // open for append, the only difference from reset(char *) + if( out_file == NULL ) + Error( W_MSG ); + symbol_counter = low = bits_to_follow = bit_buffer = closed = 0; + bit_index = 8; + high = TopValue; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::stop( void ) +{ + if( closed ) + Error( "< Encoder > file already closed" ); + + bits_to_follow++; + bit_plus_follow( low >= FirstQtr ); + if( putc( bit_buffer >> bit_index, out_file ) == EOF ) + Error( W_MSG ); + byte_counter++; + closed = 1; + + bit_index = 8; // no bits left in bit_buffer 062602 + + //printf("%d\n", byte_counter); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - Public functions - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::open_file( void ) +{ + temp = 1; + reset( NULL ); + byte_counter = 5; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::open_file( char *file_name ) +{ + temp = 0; + + reset( file_name ); + byte_counter = 1; + if( putc( 0x6F, out_file ) == EOF ) + Error( W_MSG ); +} + +void +Encoder::new_open_file( char *file_name ) // for video coding by chen +{ + temp = 0; + + reset_append( file_name ); + byte_counter = 0; +} + +void +Encoder::new_open_file( void ) // for video coding by chen +{ + temp = 0; + //char *name; + + sprintf( temp_name, "sub%03d.bit", object_count ); + object_count++; + //printf("%s (ar_code.cpp)\n", temp_name); + reset( temp_name ); + byte_counter = 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::close_file( char *file_name ) +{ + if( !temp ) + Error( "< Encoder > invalid close file function" ); + + stop( ); + +// copy from temporary file to output file + + FILE *new_file = fopen( file_name, "wb" ); + if( new_file == NULL ) + Error( W_MSG ); + + unsigned char buff[256]; + long ns = symbol_counter; + + buff[0] = 0x53; + for( int i = 4; i >= 1; i-- ) { + buff[i] = ( unsigned char )( ns & 0xFF ); + ns >>= 8; + } + if( fwrite( ( char * )buff, sizeof( char ), 5, new_file ) != 5 ) + Error( W_MSG ); + + if( fflush( new_file ) ) + Error( W_MSG ); + rewind( out_file ); + + int nbs; + do { + nbs = fread( ( char * )buff, sizeof( char ), 256, out_file ); + if( nbs == 0 ) + break; + if( fwrite( ( char * )buff, sizeof( char ), nbs, new_file ) != + ( unsigned )nbs ) + Error( W_MSG ); + } while( nbs == 256 ); + + if( ( fclose( new_file ) == EOF ) || ( fclose( out_file ) == EOF ) ) + Error( W_MSG ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::close_file( void ) +{ + if( temp ) + Error( "< Encoder > invalid command to close file" ); + stop( ); + if( fclose( out_file ) == EOF ) + Error( W_MSG ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::code_symbol( int s, Adaptive_Model & model ) +{ + model.new_interval( s, &low, &high ); + update_interval( ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Encoder::code_bits( int bits, int word ) +{ + long lm1 = low - 1, range = high - lm1; + word &= ( 1 << bits ) - 1; + high = lm1 + ( ( range * ( word + 1 ) ) >> bits ); + low += ( range * word ) >> bits; + + update_interval( ); +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Functions of the class < Decoder > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// - - Private functions - - - - - - - - - - - - - - - - - - - - - - - - + +void +Decoder::input_byte( void ) +{ + if( ( bit_buffer = getc( in_file ) ) == EOF || byte_counter >= byte_budget ) { + bit_buffer = EOF; + //printf("%d, %x\n", bit_buffer, EOF); + //printf("end of bitstream reached(ar_code.cpp) \n"); + //printf("bytes read %d\n", byte_counter+1); + //printf("extra_bits %d\n", extra_bits); + if( ++extra_bits > CodeValueBits - 2 ) + Error( "< Decoder > end of file reached" ); + } + + bit_index = 8; + ++byte_counter; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Decoder::update_interval( void ) +{ + if( ++symbol_counter >= mss_symbols ) { + printf( "from Decoder::update_interval()\n" ); + close_file( ); + } else + for( ;; ) { + if( high >= Half ) + if( low >= Half ) { + value -= Half; + low -= Half; + high -= Half; + } else if( ( low >= FirstQtr ) && ( high < ThirdQtr ) ) { + value -= FirstQtr; + low -= FirstQtr; + high -= FirstQtr; + } else + break; + low <<= 1; + high += high + 1; + value <<= 1; + if( !bit_index ) + input_byte( ); + if( bit_buffer & 1 ) + value++; + bit_buffer >>= 1; + bit_index--; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - Public functions - - - - - - - - - - - - - - - - - - - - - - - - + +void +Decoder::open_file( char *file_name ) +{ + if( !closed ) + Error( "< Decoder > file already open" ); + + if( ( in_file = fopen( file_name, "rb" ) ) == NULL ){ + printf("Decoder::open_file( char *file_name ) !\n"); + Error( R_MSG ); + } + + byte_counter = 1; + symbol_counter = 0; + + int i, magic_char = getc( in_file ); + + //printf("%x\n", magic_char); + if( magic_char == 0x6F ) { + //ext_stop = 1; mss_symbols = 0x1000000L; } //unclear what is this for + ext_stop = 1; + mss_symbols = 0x10000000L; + } else if( magic_char == 0x53 ) { + ext_stop = 0; + byte_counter += 4; + unsigned char buff[4]; + if( fread( ( char * )buff, sizeof( char ), 4, in_file ) != 4 ){ + printf("fread( ( char * )buff, sizeof( char ), 4, in_file ) != 4 !\n"); + Error( R_MSG ); + } + for( mss_symbols = i = 0; i < 4; i++ ) + mss_symbols = ( mss_symbols << 8 ) + long ( buff[i] ); + } else + Error( "invalid < Decoder > file" ); + + high = TopValue; + value = low = bit_index = extra_bits = closed = 0; + for( i = 0; i < CodeValueBits; i++ ) { + if( !bit_index ) + input_byte( ); + value += value + ( bit_buffer & 1 ); + bit_buffer >>= 1; + bit_index--; + } +} + + + +void +Decoder::new_open_file( char *file_name, long shift_bytes ) // for video coding by chen +{ + if( !closed ) + Error( "< Decoder > file already open" ); + + if( ( in_file = fopen( file_name, "rb" ) ) == NULL ){ + printf("Decoder::new_open_file( char *file_name, long shift_bytes ) !\n"); + Error( R_MSG ); + } + + fseek( in_file, shift_bytes, SEEK_SET ); // chen + + byte_counter = 0; + symbol_counter = 0; + int i; + + //ext_stop = 1; mss_symbols = 0x1000000L; } //unclear what is this for + ext_stop = 1; + mss_symbols = 0x10000000L; + + high = TopValue; + value = low = bit_index = extra_bits = closed = 0; + for( i = 0; i < CodeValueBits; i++ ) { + if( !bit_index ) + input_byte( ); + value += value + ( bit_buffer & 1 ); + bit_buffer >>= 1; + bit_index--; + } + + printf( "%d\n", (int) byte_counter ); + +} + +void +Decoder::new_open_file( char *file_name, long shift_bytes, long budget ) // for video coding by chen +{ + if( !closed ) + Error( "< Decoder > file already open" ); + + in_file = fopen( file_name, "rb" ); + if( in_file == NULL ){ + printf("No file open in Decoder::new_open_file!\n"); + Error( R_MSG ); + } + fseek( in_file, shift_bytes, SEEK_SET ); // chen + + byte_budget = budget; + + byte_counter = 0; + symbol_counter = 0; + int i; + + //ext_stop = 1; mss_symbols = 0x1000000L; } //unclear what is this for + ext_stop = 1; + mss_symbols = 0x10000000L; + + high = TopValue; + value = low = bit_index = extra_bits = closed = 0; + for( i = 0; i < CodeValueBits; i++ ) { + if( !bit_index ) + input_byte( ); + value += value + ( bit_buffer & 1 ); + bit_buffer >>= 1; + bit_index--; + } +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Decoder::close_file( void ) +{ + if( closed ) + Error( "< Decoder > file already closed" ); + fclose( in_file ); + closed = 1; + mss_symbols = 0; + //printf("byte_counter = %d\n", byte_counter); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +int +Decoder::decode_symbol( Adaptive_Model & model ) +{ + int symbol = model.select_symbol( value, &low, &high ); + update_interval( ); + return symbol; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +int +Decoder::decode_bits( int bits ) +{ + long lm1 = low - 1, range = high - lm1; + int word = int ( ( ( ( value - lm1 ) << bits ) - 1 ) / range ); + long prod = word * range; + high = lm1 + ( ( prod + range ) >> bits ); + low += prod >> bits; + update_interval( ); + return word; +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// end of file < AritCode.C > diff --git a/Interframe EZBC/Utils/src/general.cpp b/Interframe EZBC/Utils/src/general.cpp new file mode 100644 index 0000000..24ab94e --- /dev/null +++ b/Interframe EZBC/Utils/src/general.cpp @@ -0,0 +1,159 @@ + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// G E N E R A L P U R P O S E F U N C T I O N S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// > > > > C++ version 1.08 - 02/01/96 < < < < + +// Amir Said - amir@densis.fee.unicamp.br +// University of Campinas (UNICAMP) +// Campinas, SP 13081, Brazil + +// William A. Pearlman - pearlman@ecse.rpi.edu +// Rensselaer Polytechnic Institute +// Troy, NY 12180, USA + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// Copyright (c) 1995, 1996 Amir Said & William A. Pearlman + +// This program is Copyright (c) by Amir Said & William A. Pearlman. +// It may not be redistributed without the consent of the copyright +// holders. In no circumstances may the copyright notice be removed. +// The program may not be sold for profit nor may they be incorporated +// in commercial programs without the written permission of the copyright +// holders. This program is provided as is, without any express or +// implied warranty, without even the warranty of fitness for a +// particular purpose. + + +// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include "general.h" +#include +#include + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1e6 +#endif + + +// - - Static variable - - - - - - - - - - - - - - - - - - - - - - - - - + +//static Char_Line line; + + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Error-handling functions + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +void +Error( char *s ) +{ + fprintf( stderr, "\n\n\a -> Error: " ); + fputs( s, stderr ); + fputs( "\n Execution terminated!\n", stderr ); + exit( 1 ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Warning( char *s ) +{ + fprintf( stderr, "\n\n\a -> Warning: " ); + fputs( s, stderr ); + // Pause( ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Test_Pointer( void *p, char *orig ) +{ + if( p == NULL ) { + fputs( "\n\n\a -> Error: insufficient memory.", stderr ); + if( orig != NULL ) + fprintf( stderr, "\nOrigin = %s\n", orig ); + fputs( "\n Execution terminated!\n", stderr ); + exit( 1 ); + } +} + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Functions of the class < Chronometer > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +void +Chronometer::start( char *s ) +{ + if( s != NULL ) + puts( s ); + if( stat ) + Warning( "chronometer already on!" ); + else { + mark = clock( ); + stat = 1; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Chronometer::stop( void ) +{ + if( stat ) { + elp += clock( ) - mark; + stat = 0; + } else + Warning( "chronometer already off!" ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +float +Chronometer::read( void ) +{ + return float ( stat ? elp + ( clock( ) - mark ) : elp ) / CLOCKS_PER_SEC; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Chronometer::display( char *s ) +{ + float sc = + float ( stat ? elp + ( clock( ) - mark ) : elp ) / CLOCKS_PER_SEC; + int hr = int ( sc / 3600.0 ); + sc -= ( float )3600.0 *hr; + int mn = int ( sc / 60.0 ); + sc -= ( float )60.0 *mn; + if( s != NULL ) + printf( " %s ", s ); + if( hr ) { + printf( "%d hour", hr ); + if( hr > 1 ) + printf( "s, " ); + else + printf( ", " ); + } + if( ( hr ) || ( mn ) ) { + printf( "%d minute", mn ); + if( mn > 1 ) + printf( "s, and " ); + else + printf( ", and " ); + } + printf( "%5.2f seconds.\n", sc ); +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// end of file < General.C > diff --git a/Interframe EZBC/Utils/src/image_bw.cpp b/Interframe EZBC/Utils/src/image_bw.cpp new file mode 100644 index 0000000..8a96e2e --- /dev/null +++ b/Interframe EZBC/Utils/src/image_bw.cpp @@ -0,0 +1,1131 @@ + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// I M A G E C L A S S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// > > > > C++ version 11.06 - 02/01/96 < < < < + +// Amir Said - amir@densis.fee.unicamp.br +// University of Campinas (UNICAMP) +// Campinas, SP 13081, Brazil + +// William A. Pearlman - pearlman@ecse.rpi.edu +// Rensselaer Polytechnic Institute +// Troy, NY 12180, USA + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// Copyright (c) 1995, 1996 Amir Said & William A. Pearlman + +// This program is Copyright (c) by Amir Said & William A. Pearlman. +// It may not be redistributed without the consent of the copyright +// holders. In no circumstances may the copyright notice be removed. +// The program may not be sold for profit nor may they be incorporated +// in commercial programs without the written permission of the copyright +// holders. This program is provided as is, without any express or +// implied warranty, without even the warranty of fitness for a +// particular purpose. + +// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#include +#include "general.h" +#include "image_bw.h" +#include "structN.h" +#include + +// - - Constants - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static char *M_MSG = "< Image_SP >"; + +static char *R_MSG = "< Image_BW > cannot read from file"; + +static char *W_MSG = "< Image_BW > cannot write to file"; + +static char *L_MSG = "< Image_BW > larger than specified dimension"; + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Auxiliary functions + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +//ostream & operator << ( ostream & out, Image_Coord & in_ord ) { +// cout << "( " << in_ord.x << ", " << in_ord.y << " )"; +// return out; +//} + +#ifdef LOSSLESS + +static void +SP_Transform( int m, int in[], int l[], int h[] ) +{ + int i, k, d1, d2, mm = m - 1; + + for( i = k = 0; i < m; i++, k += 2 ) { + l[i] = ( in[k] + in[k + 1] ) >> 1; + h[i] = in[k] - in[k + 1]; + } + + h[0] -= ( d2 = l[0] - l[1] ) >> 2; + for( i = 1; i < mm; i++ ) { + d1 = d2; + d2 = l[i] - l[i + 1]; + h[i] -= ( ( ( d1 + d2 - h[i + 1] ) << 1 ) + d2 + 3 ) >> 3; + } + h[i] -= d2 >> 2; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static void +SP_Recover( int m, int l[], int h[], int out[] ) +{ + int i, k, d1, d2, t; + + t = ( h[m - 1] += ( d1 = l[m - 2] - l[m - 1] ) >> 2 ); + for( i = m - 2; i > 0; i-- ) { + d2 = d1; + d1 = l[i - 1] - l[i]; + t = ( h[i] += ( ( ( d1 + d2 - t ) << 1 ) + d2 + 3 ) >> 3 ); + } + h[0] += d1 >> 2; + + for( i = k = 0; i < m; i++, k += 2 ) { + out[k] = l[i] + ( ( h[i] + 1 ) >> 1 ); + out[k + 1] = out[k] - h[i]; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#else + // 下面是进行小波变换的系数 +static const float SmoothingFactor = ( float )0.8; + +static const int NumbTap = 4; + +static const float T_LowPass[5] = + { ( float )0.852699, ( float )0.377403, ( float )-0.110624, +( float )-0.023849, ( float )0.037829 }; + +static const float T_HighPass[5] = + { ( float )0.788485, ( float )-0.418092, ( float )-0.040690, +( float )0.064539, ( float )0.0 }; + +static const float R_LowPass[5] = + { ( float )0.852699, ( float )0.418092, ( float )-0.110624, +( float )-0.064539, ( float )0.037829 }; + +static const float R_HighPass[5] = + { ( float )0.788485, ( float )-0.377403, ( float )-0.040690, +( float )0.023849, ( float )0.0 }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +inline float +Filter_L( const float *f, float *v ) +{ + return f[0] * v[0] + + f[1] * ( v[1] + v[-1] ) + f[2] * ( v[2] + v[-2] ) + + f[3] * ( v[3] + v[-3] ) + f[4] * ( v[4] + v[-4] ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +inline float +Filter_H( const float *f, float *v ) +{ + return f[0] * v[0] + + f[1] * ( v[1] + v[-1] ) + f[2] * ( v[2] + v[-2] ) + + f[3] * ( v[3] + v[-3] ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static void +Reflection( float *h, float *t ) +{ + for( int i = 1; i <= NumbTap; i++ ) { + h[-i] = h[i]; + t[i] = t[-i]; + } +} + +#endif + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// Member functions of the class < Image_BW > + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// - - Private functions - - - - - - - - - - - - - - - - - - - - - - - - + +int +Image_BW::max_levels( int n ) // 能进行二维小波分解的最大的次数 +{ + int l1, l2; + for( l1 = 0; !( n & 1 ); l1++ ) // 最小的n的偶数,表示能进行的最大的二维小波分解的次数 + n >>= 1; +#ifdef LOSSLESS + for( l2 = l1 - 3; n; l2++ ) + n >>= 1; +#else + for( l2 = l1 - 4; n; l2++ ) + n >>= 1; // this makes sure the size of the lowest subband will be larger or equal to 8 +#endif + return ( l1 < l2 ? l1 : l2 ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::assign_mem( Image_Coord d, int b ) +{ + if( ( b < 1 ) || ( b > 2 ) ) + Error( "Invalid number of < Image_BW > bytes" ); + if( ( levels >= 0 ) && ( dim.x == d.x ) && ( dim.y == d.y ) ) + return; + free_mem( ); + if( ( d.x < 64 ) || ( d.y < 64 ) ) { + printf( "d.x = %d, d.y = %d\n", d.x, d.y ); + Error( "< Image_BW > dimension is too small or negative" ); + } + dim = d; + +#ifdef EXPAND + // expand image to garantee the number of spatial decomposition levels (refering to max_levels()) + pdim.x = ( (d.x < 256) ? ( d.x + 7 ) & 0x3FF8 : ( d.x + 15 ) & 0x3FF0 ); + pdim.y = ( (d.y < 256) ? ( d.y + 7 ) & 0x3FF8 : ( d.y + 15 ) & 0x3FF0 ); +#else + pdim = dim; +#endif + + + + + NEW_VECTOR( coeff, pdim.x, Pel_Type *, M_MSG ); + for( int i = 0; i < pdim.x; i++ ) { + NEW_VECTOR( coeff[i], pdim.y, Pel_Type, M_MSG ); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::free_mem( void ) +{ + if( levels >= 0 ) { + for( int i = pdim.x - 1; i >= 0; i-- ) + delete[]coeff[i]; + delete[]coeff; + } + bytes = dim.x = dim.y = 0; + levels = -1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::extend( void ) +{ + int i, j; + for( j = dim.y - 1; j < pdim.y - 1; j++ ) { + coeff[0][j + 1] = ( coeff[0][j] + coeff[1][j] ) / 2; + coeff[dim.x - 1][j + 1] = + ( coeff[dim.x - 1][j] + coeff[dim.x - 2][j] ) / 2; + for( i = dim.x - 2; i > 0; i-- ) + coeff[i][j + 1] = + ( coeff[i - 1][j] + coeff[i][j] + coeff[i + 1][j] ) / 3; + } + for( i = dim.x - 1; i < pdim.x - 1; i++ ) { + coeff[i + 1][0] = ( coeff[i][0] + coeff[i][1] ) / 2; + coeff[i + 1][pdim.y - 1] = + ( coeff[i][pdim.y - 1] + coeff[i][pdim.y - 2] ) / 2; + for( j = pdim.y - 2; j > 0; j-- ) + coeff[i + 1][j] = + ( coeff[i][j - 1] + coeff[i][j] + coeff[i][j + 1] ) / 3; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - Public functions - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::read_pic( Image_Coord d, char *file_name, int b ) +{ + assign_mem( d, b ); + mean = levels = 0; + bytes = b; + + FILE *in_file = fopen( file_name, "rb" ); + if( in_file == NULL ) + Error( R_MSG ); + + int i, j, k, p, c; + for( i = 0; i < dim.x; i++ ) + for( j = 0; j < dim.y; j++ ) { + for( p = k = 0; k < bytes; k++ ) { + if( ( c = getc( in_file ) ) == EOF ) + Error( R_MSG ); + p = ( p << 8 ) | c; + } + coeff[i][j] = ( float )p; + } + if( getc( in_file ) != EOF ) + Error( L_MSG ); + fclose( in_file ); + + extend( ); +} + +void +Image_BW::read_float_image( Image_Coord d, float *image ) +{ + assign_mem( d, 1 ); + mean = levels = 0; + bytes = 1; + + int i, j, k = 0; + for( i = 0; i < dim.x; i++ ) + for( j = 0; j < dim.y; j++ ) + //coeff[i][j] = *image++; + coeff[i][j] = image[k++]; + + extend( ); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +float +Image_BW::compare( char *file_name ) +{ + if( levels ) + Error( "cannot compare < Image_BW >" ); + + FILE *in_file = fopen( file_name, "rb" ); + if( in_file == NULL ) + Error( R_MSG ); + + double mse = 0.0; + int i, j, k, p, c, t; + for( i = 0; i < dim.x; i++ ) + for( j = 0; j < dim.y; j++ ) { +#ifdef LOSSLESS + t = coeff[i][j]; +#else + t = int ( floor( 0.499 + coeff[i][j] ) ); +#endif + if( t < 0 ) + t = 0; + if( ( bytes == 1 ) && ( t > 255 ) ) + t = 255; + for( p = k = 0; k < bytes; k++ ) { + if( ( c = getc( in_file ) ) == EOF ) + Error( R_MSG ); + p = ( p << 8 ) | c; + } + mse += Sqr( ( float )( p - t ) ); + } + if( getc( in_file ) != EOF ) + Error( L_MSG ); + fclose( in_file ); + + return ( float )( ( mse / dim.x ) / dim.y ); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::write_pic( char *file_name ) +{ + if( levels ) + Error( "cannot write < Image_BW >" ); + + FILE *out_file = fopen( file_name, "wb" ); + if( out_file == NULL ) + Error( W_MSG ); + + int i, j, k; + for( i = 0; i < dim.x; i++ ) + for( j = 0; j < dim.y; j++ ) { +#ifdef LOSSLESS + k = coeff[i][j]; +#else + k = int ( floor( 0.499 + coeff[i][j] ) ); +#endif + if( k < 0 ) + k = 0; + if( bytes == 2 ) { + if( putc( k >> 8, out_file ) == EOF ) + Error( W_MSG ); + } else { + if( k > 255 ) + k = 255; + } + if( putc( k & 0xFF, out_file ) == EOF ) + Error( W_MSG ); + } + + fclose( out_file ); +} + +void +Image_BW::write_float_image( float *image ) +{ + int i, j; + + for( i = 0; i < dim.x; i++ ) + for( j = 0; j < dim.y; j++ ) + *image++ = coeff[i][j]; + + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::reset( Image_Coord d ) +{ + assign_mem( d, 1 ); + bytes = 1; + mean = shift = smoothing = 0; + + + + levels = Min( max_levels( pdim.x ), max_levels( pdim.y ) ); + + int i, j; + for( i = 0; i < pdim.x; i++ ) + for( j = 0; j < pdim.y; j++ ) + coeff[i][j] = 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::reset( int m, int shf, int smt ) +{ + mean = m; + shift = shf; + smoothing = smt; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::reset( Image_Coord d, int b, int m, int shf, int smt ) +{ + reset( d ); + bytes = b; + mean = m; + shift = shf; + smoothing = smt; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::transform( int sm_numb ) // sm_numb 平滑系数 +{ + if( levels ) + Error( "cannot transform < Image_BW >" ); + if( ( dim.x < 32 ) || ( dim.y < 32 ) ) + Error( "< Image_BW > is too small to transform" ); + + float sum; + + // Chronometer cpu_time; + // cpu_time.start("\n Starting image transformation..."); + if(high_band == NO){ + levels = Min( max_levels( pdim.x ), max_levels( pdim.y ) ); //levels = 5 for luma, levels = 4 for chroma bands +// printf("LOW band!\n"); + } + else{ + assert(high_band == YES); + levels = 2; +// printf("HIGH band!\n"); + } + + if( levels <= 0 ) + Error( "invalid < Image_BW > dimension" ); + + smoothing = sm_numb; + if( ( sm_numb < 0 ) || ( sm_numb > 7 ) ) + Error( "invalid < Image_BW > smoothing factor" ); + +#ifdef LOSSLESS + int i = 0, j = Max( pdim.x, pdim.y ), k = j << 1; +#else + int i = NumbTap, j = 0, k = Max( pdim.x, pdim.y ) + ( i << 1 ); + //float sm_mt; +#endif + CREATE_VECTOR( temp_line, k, Pel_Type, M_MSG ); + Pel_Type *t, *in_line = temp_line + i; // *out_line = in_line + j; + +// hierarchical wavelet or S+P transformation + + int lv, nx, ny, mx = pdim.x, my = pdim.y; +// printf("pdimx = %d, pdimy = %d, dimx = %d, dimy = %d\n",pdim.x,pdim.y,dim.x,dim.y); + + //printf("subband decomposition levels = %d(image_bw.cpp)\n", levels); + + for( lv = 0; lv < levels; lv++ ) { // 子带进行几次分解 + + // shifts are halved, multiplier is updated + + nx = mx; + mx >>= 1; + ny = my; + my >>= 1; + +#ifndef LOSSLESS + float sm_mt = 1 + smoothing * SmoothingFactor / ( 2 + lv * lv ); +#endif + // transformation of columns + + for( j = 0; j < ny; j++ ) + { + for( i = 0; i < nx; i++ ) + in_line[i] = coeff[i][j]; // 读取一列系数 +#ifdef LOSSLESS + SP_Transform( mx, in_line, out_line, out_line + mx ); + for( i = 0; i < nx; i++ ) + coeff[i][j] = out_line[i]; + } +#else + +#ifdef Haar + for( i = 0; i < mx; i++ ) { + coeff[i][j] = + sm_mt * ( in_line[i * 2] + in_line[i * 2 + 1] ) / sqrt( 2. ); + coeff[i + mx][j] = + ( in_line[i * 2] - in_line[i * 2 + 1] ) / sqrt( 2. ); + } + } +#else + Reflection( in_line, in_line + nx - 1 ); + for( i = 0, t = in_line; i < mx; i++ ) { + coeff[i][j] = sm_mt * Filter_L( T_LowPass, t++ ); + coeff[i + mx][j] = Filter_H( T_HighPass, t++ ); + } + } +#endif + +#endif + + // transformation of rows + + for( i = 0; i < nx; i++ ) { + memcpy( in_line, coeff[i], ny * sizeof( Pel_Type ) ); +#ifdef LOSSLESS + SP_Transform( my, in_line, coeff[i], coeff[i] + my ); + } + } +#else + +#ifdef Haar + for( j = 0; j < my; j++ ) { + coeff[i][j] = + sm_mt * ( in_line[j * 2] + in_line[j * 2 + 1] ) / sqrt( 2. ); + coeff[i][j + my] = + ( in_line[j * 2] - in_line[j * 2 + 1] ) / sqrt( 2. ); + } + } + } +#else + Reflection( in_line, in_line + ny - 1 ); + for( j = 0, t = in_line; j < my; j++ ) { + coeff[i][j] = sm_mt * Filter_L( T_LowPass, t++ ); + coeff[i][j + my] = Filter_H( T_HighPass, t++ ); + } + } + } +#endif + +#endif + +#ifdef ROLL_STRUCTURE_TWO + // for frequency roll off structure two, we want small subbands in this level + int dx, dy, lenx, leny; + // decompose LH subband further into 4 small bands + dx = 0; dy = pdim.y/4; + lenx = pdim.x/4; leny = pdim.y/4; + one_step_decompose(dx, dy, lenx, leny); + // decompose HL subband further into 4 small bands + dx = pdim.x/4; dy = 0; + one_step_decompose(dx, dy, lenx, leny); + // decompose HH subband further into 4 small bands + dx = pdim.x/4; dy = pdim.y/4; + one_step_decompose(dx, dy, lenx, leny); +#endif + + + // calculate and subtract mean + float s = 0; + for( i = 0; i < mx; i++ ) + for( j = 0; j < my; j++ ) + s += coeff[i][j]; + s /= float ( mx ) * float ( my ); + +// for (shift = 0; s > 1e3; shift++) s *= 0.25; + for( shift = 0; abs( ( int )s ) > 1e3; shift++ ) + s *= 0.25; + mean = int ( 0.5 + s ); + +#ifdef LOSSLESS + int tm = mean << ( shift + shift ); +#else + float tm = ( float )( mean * pow( 4, shift ) ); +#endif + for( i = 0; i < mx; i++ ) + for( j = 0; j < my; j++ ) + coeff[i][j] -= tm; + +#ifdef MY_SCALE + for (i = 0; i < pdim.x; i++) + for (j = 0; j < pdim.y; j++) + coeff[i][j] *= MY_SCALE; +#endif + + delete[]temp_line; +// cpu_time.display(" Image transformed in"); + +/* + sum = 0; + printf("Transformed band:\n"); + for( i = 0; i < dim.x; i++ ){ + for( j = 0; j < dim.y; j++ ){ +// printf("%f\t",coeff[i][j]*coeff[i][j]); + sum += coeff[i][j]*coeff[i][j]; + } +// printf("\n"); + } +// printf("\n\n"); + +// printf("sum = %f\n",sum); + sum = sum / (dim.x * dim.y); + printf("avg = %f\n",sum); + + mse = sum; +*/ +// printf("pixel num = %d\n",(dim.x * dim.y)); +} + + +void Image_BW::one_step_decompose(int dx, int dy, int lenx, int leny) +{ + int i = NumbTap, j = 0, k = Max(lenx, leny) + (i << 1); + CREATE_VECTOR(temp_line, k, Pel_Type, M_MSG); + Pel_Type * t, * in_line = temp_line + i, * out_line = in_line + j; + + int nx, ny, mx = lenx, my = leny; + + nx = mx; mx >>= 1; ny = my; my >>= 1; + // transformation of columns + for (j = 0; j < ny; j++) { + for (i = 0; i < nx; i++) in_line[i] = coeff[dx+i][dy+j]; + Reflection(in_line, in_line + nx - 1); + for (i = 0, t = in_line; i < mx; i++) { + coeff[dx+i][dy+j] = Filter_L(T_LowPass, t++); + coeff[dx+i+mx][dy+j] = Filter_H(T_HighPass, t++); + } + } + // transformation of rows + for (i = 0; i < nx; i++) { + for (j=0; j < ny; j++ ) in_line[j] = coeff[dx+i][dy+j]; + Reflection(in_line, in_line + ny - 1); + for (j = 0, t = in_line; j < my; j++) { + coeff[dx+i][dy+j] = Filter_L(T_LowPass, t++); + coeff[dx+i][dy+j+my] = Filter_H(T_HighPass, t++); + } + } + + delete [] temp_line; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::scale_down( void ) +{ + int i, j; + int mx = pdim.x, my = pdim.y; + + mx >>= 1; + my >>= 1; + + for( i = mx; i < pdim.x; i++ ) + for( j = 0; j < my; j++ ) + coeff[i][j] /= 2; + + for( i = mx; i < pdim.x; i++ ) + for( j = my; j < pdim.y; j++ ) + coeff[i][j] /= 2; + + for( i = 0; i < mx; i++ ) + for( j = my; j < pdim.y; j++ ) + coeff[i][j] /= 2; + + +} + + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::scale_up( void ) +{ + + int i, j; + int mx = pdim.x, my = pdim.y; + + mx >>= 1; + my >>= 1; + + for( i = mx; i < pdim.x; i++ ) + for( j = 0; j < my; j++ ) + coeff[i][j] *= 2; + + for( i = mx; i < pdim.x; i++ ) + for( j = my; j < pdim.y; j++ ) + coeff[i][j] *= 2; + + for( i = 0; i < mx; i++ ) + for( j = my; j < pdim.y; j++ ) + coeff[i][j] *= 2; + + +} + + + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +void +Image_BW::recover( void ) +{ + if( levels <= 0 ) + Error( "cannot recover < Image_BW >" ); + + // Chronometer cpu_time; + // cpu_time.start("\n Starting inverse transformation..."); + // printf("subband decomposition levels = %d(image_bw.cpp)\n", levels); + +#ifdef LOSSLESS + int i = 0, j = Max( pdim.x, pdim.y ), k = j << 1; +#else + int i = NumbTap, j = 0, k = Max( pdim.x, pdim.y ) + ( i << 1 ); + //float sm_mt; +#endif + CREATE_VECTOR( temp_line, k, Pel_Type, M_MSG ); + Pel_Type *t, *in_line = temp_line + i; // *out_line = in_line + j; + + if(high_band == NO){ + levels = Min( max_levels( pdim.x ), max_levels( pdim.y ) ); //levels = 5 for luma, levels = 4 for chroma bands +// printf("LOW band!\n"); + }else{ + assert(high_band == YES); + levels = 2; +// printf("HIGH band!\n"); + } + + int lv, mx, my, nx = pdim.x >> levels, ny = pdim.y >> levels; + +#ifdef MY_SCALE + for (i = 0; i < pdim.x; i++) + for (j = 0; j < pdim.y; j++) + coeff[i][j] /= MY_SCALE; +#endif + +// add mean + +#ifdef FREQUENCY_ROLL_OFF + FILE *froll; + float roll_factors[15]; + int factor_num; + + if ( (s_level==1 || s_level==2) && frame_res==HD) + { +#ifdef ROLL_STRUCTURE_ONE + froll=fopen("roll_factors_structure_one.txt", "rt"); + for (factor_num=0; factor_num<6; factor_num++) + fscanf(froll, "%f", &(roll_factors[factor_num])); + fclose(froll); + if (s_level==1) + for (i=0; i= 0; lv-- ) { + + // shifts are doubled, multiplier is updated + + mx = nx; + nx <<= 1; + my = ny; + ny <<= 1; + +#ifndef LOSSLESS + float sm_mt = 1 / ( 1 + smoothing * SmoothingFactor / ( 2 + lv * lv ) ); +#endif + + // inverse transformation of rows + + for( i = 0; i < nx; i++ ) { +#ifdef LOSSLESS + memcpy( in_line, coeff[i], ny * sizeof( Pel_Type ) ); + SP_Recover( my, in_line, in_line + my, coeff[i] ); + } +#else + for( j = 0, t = in_line; j < my; j++ ) { + *( t++ ) = sm_mt * coeff[i][j]; + *( t++ ) = coeff[i][j + my]; + } + +#ifdef Haar + for( j = 0; j < ny; ) { + coeff[i][j] = ( in_line[j] + in_line[j + 1] ) / sqrt( 2. ); + coeff[i][j + 1] = ( in_line[j] - in_line[j + 1] ) / sqrt( 2. ); + j = j + 2; + } + } +#else + Reflection( in_line, in_line + ny - 1 ); + for( j = 0, t = in_line; j < ny; ) { + coeff[i][j++] = Filter_H( R_HighPass, t++ ); + coeff[i][j++] = Filter_L( R_LowPass, t++ ); + } + } +#endif + +#endif + + // inverse transformation of columns + + for( j = 0; j < ny; j++ ) { +#ifdef LOSSLESS + for( i = 0; i < nx; i++ ) + in_line[i] = coeff[i][j]; + SP_Recover( mx, in_line, in_line + mx, out_line ); + for( i = 0; i < nx; i++ ) + coeff[i][j] = out_line[i]; + } + } +#else + for( i = 0, t = in_line; i < mx; i++ ) { + *( t++ ) = sm_mt * coeff[i][j]; + *( t++ ) = coeff[i + mx][j]; + } + +#ifdef Haar + for( i = 0; i < nx; ) { + coeff[i][j] = ( in_line[i] + in_line[i + 1] ) / sqrt( 2. ); + coeff[i + 1][j] = ( in_line[i] - in_line[i + 1] ) / sqrt( 2. ); + i = i + 2; + } + } + } +#else + Reflection( in_line, in_line + nx - 1 ); + for( i = 0, t = in_line; i < nx; ) { + coeff[i++][j] = Filter_H( R_HighPass, t++ ); + coeff[i++][j] = Filter_L( R_LowPass, t++ ); + } + } + } +#endif + +#endif + + levels = 0; + delete[]temp_line; +// cpu_time.display(" Image transformed in"); +} + +void Image_BW::one_step_recover(int dx, int dy, int lenx, int leny) +{ + + int i = NumbTap, j = 0, k = Max(lenx, leny) + (i << 1); + + CREATE_VECTOR(temp_line, k, Pel_Type, M_MSG); + Pel_Type * t, * in_line = temp_line + i, * out_line = in_line + j; + + int mx, my, nx = lenx/2, ny = leny/2; + + mx = nx; nx <<= 1; my = ny; ny <<= 1; + + // inverse transformation of rows + for (i = 0; i < nx; i++) { + for (j = 0, t = in_line; j < my; j++) { + *(t++) = coeff[dx+i][dy+j]; + *(t++) = coeff[dx+i][dy+j+my]; + } + Reflection(in_line, in_line + ny - 1); + for (j = 0, t = in_line; j < ny;){ + coeff[dx+i][dy+j] = Filter_H(R_HighPass, t++); + j++; + coeff[dx+i][dy+j] = Filter_L(R_LowPass, t++); + j++; + } + } + + // inverse transformation of columns + for (j = 0; j < ny; j++) { + for (i = 0, t = in_line; i < mx; i++) { + *(t++) = coeff[dx+i][dy+j]; + *(t++) = coeff[dx+i+mx][dy+j]; + } + Reflection(in_line, in_line + nx - 1); + for (i = 0, t = in_line; i < nx;) { + coeff[dx+i][dy+j] = Filter_H(R_HighPass, t++); + i++; + coeff[dx+i][dy+j] = Filter_L(R_LowPass, t++); + i++; + } + } + + delete [] temp_line; + +} + + +void Image_BW::write_raw( char *file_name ) +{ + int i; + + FILE *out_file = fopen( file_name, "wb" ); + if( out_file == NULL ) { + char msg[512]; + sprintf(msg, "%s: %s\n", W_MSG, file_name); + Error(msg); + } + + for( i = 0; i < dim.x; i++ ) { + if(fwrite( coeff[i], sizeof( Pel_Type ), dim.y, out_file ) - dim.y != 0) { + char msg[512]; + sprintf(msg, "%s: %s\n", W_MSG, file_name); + Error(msg); + } + } + + fclose( out_file ); +} + +void Image_BW::read_raw( Image_Coord d, char *file_name ) +{ + int i; + + assign_mem( d, 1 ); + mean = levels = 0; + bytes = 1; + + FILE *in_file = fopen( file_name, "rb" ); + if( in_file == NULL ) { + char msg[512]; + sprintf(msg, "%s: %s\n", R_MSG, file_name); + Error(msg); + } + + for( i = 0; i < dim.x; i++ ) { + if(fread( coeff[i], sizeof( Pel_Type ), dim.y, in_file ) - dim.y != 0) { + char msg[512]; + sprintf(msg, "%s: %s\n", R_MSG, file_name); + Error(msg); + } + } + + fclose( in_file ); +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// end of file < Image_BW.C > + + diff --git a/Interframe EZBC/Utils/src/subband.cpp b/Interframe EZBC/Utils/src/subband.cpp new file mode 100644 index 0000000..7ff684e --- /dev/null +++ b/Interframe EZBC/Utils/src/subband.cpp @@ -0,0 +1,452 @@ +/* ========================================================================= */ +/* Description: function implementation of wavelet decomposotion */ +/* Author: Shih-Ta Hsiang */ +/* Version: v0.a */ +/* Last Revised: Aug. 15, 2000 */ +/* ========================================================================= */ + +#include +#include +#include +#include "subband.h" + +#include "structN.h" + + +int + SubbandLayer::lsb = - EXTRA_BIT; + +int +Subband:: + +initialization( Image_Coord dimen, Image_Coord memory_org, + Image_Coord memory_dim ) +{ + + dim = dimen; + mem_org = memory_org; + mem_dim = memory_dim; + alloc_coeff( ); + + transpose_flag = 0; + + return 0; +} + + +Subband::Subband( Image_Coord dimen ):coeff( NULL ) +{ + initialization( dimen ); +} + + +Subband::Subband( Image_Coord dimen, Image_Coord org_ord, Image_Coord mem_dimen ):coeff + ( NULL ) +{ + initialization( dimen, org_ord, mem_dimen ); +} + +void +Subband::reset_coeff( ) +{ + memset( &( coeff[mem_org.x][mem_org.y] ), 0, + sizeof( SUB_COEFF_TYPE ) * mem_dim.x * mem_dim.y ); +} + +void +Subband::alloc_coeff( void ) +{ + + free_coeff( ); + + NEW_VECTOR( coeff, mem_dim.x, SUB_COEFF_TYPE *, "matrix_row" ); + + SUB_COEFF_TYPE **dp = coeff; + + coeff -= mem_org.x; + + int nn = mem_dim.x * mem_dim.y; + + NEW_VECTOR( *dp, nn, SUB_COEFF_TYPE, "matrix_row" ); + memset( *dp, 0, nn * sizeof( SUB_COEFF_TYPE ) ); + + SUB_COEFF_TYPE *sp = *dp -= mem_org.y; + + for( int i = mem_dim.x - 1; i > 0; i--, *( ++dp ) = ( sp += mem_dim.y ) ); + +} + +void +Subband::free_coeff( ) +{ + if( coeff ) { + delete[] & ( coeff[mem_org.x][mem_org.y] ); + delete[] & ( coeff[mem_org.x] ); + coeff = NULL; + } +} +int +Subband::get_band_level( ) +{ + assert( wp ); + if( band_idx < 4 ) + return wp->get_pyr_levels( ); + return wp->get_pyr_levels( ) - ( band_idx - 1 ) / 3; +} + +//----------------------------------------------------------------------------- + +// get_child_band_idx() + +// ATTENTION to band 0 and bottom bands +//----------------------------------------------------------------------------- +int +Subband::get_child_band_idx( void ) +{ + + if( get_band_level( ) > 1 ) + return band_idx + 3; + else + return NO_CHILD; +} + +//----------------------------------------------------------------------------- + +// get_child_band_idx() + +// ATTENTION to band 0 and bottom bands +//----------------------------------------------------------------------------- +int +Subband::get_grand_child_band_idx( void ) +{ + + if( get_band_level( ) > 2 ) + return band_idx + 6; + else + return NO_CHILD; +} + +void +Subband::transpose( void ) +{ + + transpose_flag = !transpose_flag; + Image_Coord old_dim = dim; + Image_Coord old_mem_org = mem_org; + Image_Coord old_mem_dim = mem_dim; + SUB_COEFF_TYPE **old_coeff = coeff; + + dim = old_dim.t( ); + mem_org = old_mem_org.t( ); + mem_dim = old_mem_dim.t( ); + coeff = NULL; + alloc_coeff( ); + + for( int i = old_mem_dim.x + old_mem_org.x - 1; i >= old_mem_org.x; i-- ) + for( int j = old_mem_dim.y + old_mem_org.y - 1; j >= old_mem_org.y; j-- ) + coeff[j][i] = old_coeff[i][j]; + + delete[] & ( old_coeff[old_mem_org.x][old_mem_org.y] ); + delete[] & ( old_coeff[old_mem_org.x] ); +} + +/*----------------------------------------------------------------- + +The bitplane corresponds to the integral parts of the DWT coeffs. +When floating parts are needed (lsb < 0), the bitplane is shifted +to the left according to the digits of floating number needed. + +------------------------------------------------------------------*/ + +SubbandLayer:: +SubbandLayer( Image_BW & image_pyr, Image_Coord orig, Image_Coord dimen, + int par_n ) + : +Subband( dimen, -1, dimen + 2 ), +org( orig ), +par_ind( par_n ) +{ + + int i, j, m, n; + + + int max = 0; + + if( lsb < 0 ) { + int scale = 1 << ( -lsb ); + for( i = 0, m = org.x; i < dim.x; i++, m++ ) + for( j = 0, n = org.y; j < dim.y; j++, n++ ) { + coeff[i][j] = int ( ABS( image_pyr( m, n ) * scale ) ); + if( max < coeff[i][j] ) + max = coeff[i][j]; + if( image_pyr( m, n ) < 0 ) + coeff[i][j] |= sign; + } + } else { + for( i = 0, m = org.x; i < dim.x; i++, m++ ) + for( j = 0, n = org.y; j < dim.y; j++, n++ ) { + coeff[i][j] = int ( ABS( image_pyr( m, n ) ) ); + if( max < coeff[i][j] ) + max = coeff[i][j]; + if( image_pyr( m, n ) < 0 ) + coeff[i][j] |= sign; + } + } + + max_msb = log2( max ); + if( lsb < 0 ){ + max_msb += lsb; + // printf("lsb %d, max %d\n ", lsb, max / (1<<(-lsb))); + } + +} + +/*------------------------------------------------------------ + + initialization for decoding +_____________________________________________________________*/ + + +SubbandLayer:: +SubbandLayer( Image_Coord orig, Image_Coord dimen, int par_n, int msb ) + : +Subband( dimen, -1, dimen + 2 ), +org( orig ), +par_ind( par_n ), +max_msb( msb ) +{ +// int i, j, m, n; + + reset_coeff( ); + +} + +enum ORIENTATION +SubbandLayer::get_orientation( ) +{ + if( band_idx ) + return ORIENTATION( ( band_idx - 1 ) % 3 + 1 ); + else + return LL; +} + + +SubSetLayer::SubSetLayer( Image_BW & image_pyr, int s_level, int *msb_layers ) +:SubSet( ) +{ + int i; + Image_Coord dim, org, small_dim; + + + pyr_levels = image_pyr.pyramid_levels( ); + pdim = image_pyr.pyramid_dim( ); + if( pyr_levels < 0 ) { + fprintf( stderr, "SubbandSet: Input Image object is empty\n" ); + exit( -1 ); + } else if( pyr_levels == 0 ) { + image_pyr.transform( 0 ); // smoothing = 0 + pyr_levels = image_pyr.pyramid_levels( ); + } + +#ifdef ROLL_STRUCTURE_TWO + if (s_level<2) + { + nband = 1 + 3 * pyr_levels+9; // there are additional 9 subbands for structure two + }else + nband = 1 + 3 * pyr_levels; + +#else + nband = 1 + 3 * pyr_levels; // 子带个数 +#endif + + + NEW_VECTOR( bands, nband, SUBBAND_TYPE *, "bands*" ); // 为每个子带申请位置 + + dim = pdim; + dim.x >>= pyr_levels; + dim.y >>= pyr_levels; + org.x = org.y = 0; + + //parent index + + int par_n = -1; + bands[0] = ( !msb_layers ) ? new SUBBAND_TYPE( image_pyr, org, dim, par_n ) + : new SUBBAND_TYPE( org, dim, par_n, msb_layers[0] ); + assert( bands[0] ); + bands[0]->set_wp( this ); + bands[0]->set_band_idx( 0 ); + + int cur = 1; + for( i = 0; i < pyr_levels; i++ ) { +#ifdef ROLL_STRUCTURE_TWO + int m, n; + if (i!= pyr_levels-2+s_level ) // pyr_levels-2 in encoder, pyr_levels-2+s_level in decoder + { + org.x = 0; org.y = dim.y; + par_n = i ? cur-3 : 0; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, dim, par_n) + : new SUBBAND_TYPE(org, dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); + bands[cur]->set_band_idx(cur); + cur++; + + org.x = dim.x; org.y = 0; + par_n = i ? cur-3 : 0; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, dim, par_n) + : new SUBBAND_TYPE(org, dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); + bands[cur]->set_band_idx(cur); + cur++; + + org.x = dim.x; org.y = dim.y; + par_n = i ? cur-3 : 0; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, dim, par_n) + : new SUBBAND_TYPE(org, dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); + bands[cur]->set_band_idx(cur); + cur++; + + dim.x <<= 1; dim.y <<= 1; + }else + { + // now there are four small bands in HL subband at level 5 + small_dim.x = dim.x/2; small_dim.y = dim.y/2; + par_n = 100; + for (m=0; m<2; m++) + for (n=0; n<2; n++) + { + org.x = m*small_dim.x; org.y = dim.y+n*small_dim.y; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, small_dim, par_n) + : new SUBBAND_TYPE(org, small_dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); + bands[cur]->set_band_idx(cur); + cur++; + } + + // now there are four small bands in LH subband at level 5 + for (m=0; m<2; m++) + for (n=0; n<2; n++) + { + org.x = dim.x+m*small_dim.x; org.y = n*small_dim.y; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, small_dim, par_n) + : new SUBBAND_TYPE(org, small_dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); bands[cur]->set_band_idx(cur); + cur++; + } + + // now there are four small bands in HH subband at level 5 + for (m=0; m<2; m++) + for (n=0; n<2; n++) + { + org.x = dim.x+m*small_dim.x; org.y = dim.y+n*small_dim.y; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, small_dim, par_n) + : new SUBBAND_TYPE(org, small_dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); bands[cur]->set_band_idx(cur); + cur++; + } + + dim.x <<= 1; dim.y <<= 1; + } + +#else + org.x = 0; org.y = dim.y; + par_n = i ? cur-3 : 0; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, dim, par_n) + : new SUBBAND_TYPE(org, dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); bands[cur]->set_band_idx(cur); + cur++; + + org.x = dim.x; org.y = 0; + par_n = i ? cur-3 : 0; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, dim, par_n) + : new SUBBAND_TYPE(org, dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); bands[cur]->set_band_idx(cur); + cur++; + + org.x = dim.x; org.y = dim.y; + par_n = i ? cur-3 : 0; + bands[cur] = (!msb_layers)? new SUBBAND_TYPE(image_pyr, org, dim, par_n) + : new SUBBAND_TYPE(org, dim, par_n, msb_layers[cur]); + assert(bands[cur]); + bands[cur]->set_wp(this); bands[cur]->set_band_idx(cur); + cur++; + + dim.x <<= 1; dim.y <<= 1; +#endif + + } + + for( i = 1, max_msb = bands[0]->get_max_msb( ); i < nband; i++ ) { + if( max_msb < bands[i]->get_max_msb( ) ) + max_msb = bands[i]->get_max_msb( ); + } +} + +//----------------------------------------------------------------------------- + +// reset_max_msb + +//----------------------------------------------------------------------------- +void +SubSetLayer::reset_max_msb( ) +{ + int i; + + for( i = 1, max_msb = bands[0]->get_max_msb( ); i < nband; i++ ) { + if( max_msb < bands[i]->get_max_msb( ) ) + max_msb = bands[i]->get_max_msb( ); + + } + +} + + +/*----------------------------------------------------------------------------- + +This function tries to reconstructs the image pyramid from the +received bit planes. The reconstructed coeffs take the input bitplane +values after bitplane shifting. + +-----------------------------------------------------------------------------*/ + +void +SubSetLayer::SubSetLayer2Image_BW( Image_BW & image_pyr ) +{ + int shift, lsb, sig, i, j, k; + Image_Coord dim, org; + SUB_COEFF_TYPE **base_coeff; + + for( k = 0; k < nband; k++ ) { + if( bands[k]->get_transpose_flag( ) ) + bands[k]->transpose( ); + org = bands[k]->get_org( ); + dim = bands[k]->get_dim( ); + lsb = bands[k]->get_lsb( ); + base_coeff = bands[k]->get_coeff( ); + shift = ( lsb < 0 ) ? (-lsb) : 0; + for( i = 0; i < dim.x; i++ ) { + for( j = 0; j < dim.y; j++ ) { + sig = ( base_coeff[i][j] & SIGN_BIT ) ? (-1) : 1; + image_pyr( org.x + i, org.y + j ) = ( float ) + ( sig * ( ( base_coeff[i][j] & MAG_MASK ) >> shift ) ); + } + } + } +} + +int +SubSetLayer::cal_band_level( int band_idx ) +{ + if( band_idx ) + return pyr_levels - ( band_idx - 1 ) / 3; + else + return pyr_levels; +}