diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 32212fc22..4a9efea35 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -9,4 +9,5 @@ if(CONFIG_HAS_STM32LIB) add_subdirectory_ifdef(CONFIG_BT_STM32_IPM stm32wb) add_subdirectory_ifdef(CONFIG_BT_STM32WBA stm32wba) add_subdirectory_ifdef(CONFIG_BT_STM32WB0 stm32wb0) + add_subdirectory_ifdef(CONFIG_VIDEO_STM32_VENC vc8000nanoe) endif() diff --git a/lib/vc8000nanoe/CMakeLists.txt b/lib/vc8000nanoe/CMakeLists.txt new file mode 100644 index 000000000..099435cca --- /dev/null +++ b/lib/vc8000nanoe/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2025 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_compile_definitions(H1_HAVE_ENCDEBUG_H) +#zephyr_library_compile_definitions(CONFIG_VENC_DEBUG) +zephyr_include_directories(inc) +zephyr_include_directories(source/common) +zephyr_include_directories(source/h264) + +zephyr_library_sources(source/common/encasiccontroller.c) +zephyr_library_sources(source/common/encasiccontroller_v2.c) +zephyr_library_sources(source/common/encpreprocess.c) +zephyr_library_sources(source/common/encswhwregisters.c) + +zephyr_library_sources(source/h264/H264Cabac.c) +zephyr_library_sources(source/h264/H264CodeFrame.c) +zephyr_library_sources(source/h264/H264Denoise.c) +zephyr_library_sources(source/h264/H264EncApi.c) +zephyr_library_sources(source/h264/H264Init.c) +zephyr_library_sources(source/h264/H264Mad.c) +zephyr_library_sources(source/h264/H264NalUnit.c) +zephyr_library_sources(source/h264/H264PictureBuffer.c) +zephyr_library_sources(source/h264/H264PictureParameterSet.c) +zephyr_library_sources(source/h264/H264PutBits.c) +zephyr_library_sources(source/h264/H264RateControl.c) +zephyr_library_sources(source/h264/H264Sei.c) +zephyr_library_sources(source/h264/H264SequenceParameterSet.c) +zephyr_library_sources(source/h264/H264Slice.c) +zephyr_library_sources(source/h264/h264encapi_ext.c) + + diff --git a/lib/vc8000nanoe/LICENSE.md b/lib/vc8000nanoe/LICENSE.md new file mode 100644 index 000000000..1a4f74694 --- /dev/null +++ b/lib/vc8000nanoe/LICENSE.md @@ -0,0 +1,3 @@ +# Copyright (c) 2023 STMicroelectronics + +This software component is licensed by STMicroelectronics under the **BSD-3-Clause** license. You may not use this software except in compliance with this license. You may obtain a copy of the license [here](https://opensource.org/licenses/BSD-3-Clause). \ No newline at end of file diff --git a/lib/vc8000nanoe/doc/Hantro.VC8000NanoE.V50x.SW.Integration.Guide-v1.02-20200708.pdf b/lib/vc8000nanoe/doc/Hantro.VC8000NanoE.V50x.SW.Integration.Guide-v1.02-20200708.pdf new file mode 100644 index 000000000..4ecdd6ebd Binary files /dev/null and b/lib/vc8000nanoe/doc/Hantro.VC8000NanoE.V50x.SW.Integration.Guide-v1.02-20200708.pdf differ diff --git a/lib/vc8000nanoe/inc/basetype.h b/lib/vc8000nanoe/inc/basetype.h new file mode 100644 index 000000000..d90611646 --- /dev/null +++ b/lib/vc8000nanoe/inc/basetype.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Basic type definitions. + * + ******************************************************************************** + */ + +#ifndef BASETYPE_H_INCLUDED +#define BASETYPE_H_INCLUDED + +#include + +#define VOLATILE volatile + +#ifdef __linux__ /* typedefs for Linux */ + +#include /* for size_t, NULL, etc. */ + +typedef unsigned char u8; +typedef signed char i8; +typedef unsigned short u16; +typedef signed short i16; +typedef unsigned int u32; +typedef signed int i32; +typedef unsigned long long u64; +typedef int64_t i64; + +typedef size_t ptr_t; + +#ifdef ADDRESS_WIDTH_64 +#define PRT_PTR "lx" +#else +#define PRT_PTR "x" +#endif + +#ifndef __cplusplus +typedef enum { + false = 0, + true = 1 +} bool; +#endif + +#else /* __symbian__ or __win__ or whatever, customize it to suit well */ + +#include + +#ifndef _SIZE_T_DEFINED +typedef uint32_t size_t; + +#define _SIZE_T_DEFINED +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else /* */ +#define NULL ((void *)0) +#endif /* */ +#endif + +typedef uint32_t ptr_t; + +typedef uint8_t u8; +typedef int8_t i8; +typedef uint16_t u16; +typedef int16_t i16; +typedef uint32_t u32; +typedef int32_t i32; +typedef uint64_t u64; +typedef int64_t i64; + + +#ifndef __cplusplus +#ifndef __bool_true_false_are_defined +typedef enum { + false = 0, + true = 1 +} bool; +#endif +#endif + +#endif + +#if defined(VC1SWDEC_16BIT) || defined(MP4ENC_ARM11) +typedef uint16_t u16x; +typedef int16_t i16x; +#else +typedef uint16_t u16x; +typedef int16_t i16x; +#endif + +#endif /* BASETYPE_H_INCLUDED */ diff --git a/lib/vc8000nanoe/inc/encInputLineBuffer.h b/lib/vc8000nanoe/inc/encInputLineBuffer.h new file mode 100644 index 000000000..600ad3689 --- /dev/null +++ b/lib/vc8000nanoe/inc/encInputLineBuffer.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : For test/fpga_verification/example purpose. operations on Input + * line buffer. + * + ******************************************************************************** + */ + +#ifndef ENC_INPUTLINEBUFREGISTER_H +#define ENC_INPUTLINEBUFREGISTER_H + +#include "basetype.h" + +typedef u32 (*getHEncRdMbLines)(const void *inst); +typedef i32 (*setHEncWrMbLines)(const void *inst, u32 lines); + +typedef struct +{ + u8 *buf; + ptr_t busAddress; +} lineBufMem; + +/* struct for input mb line buffer */ +typedef struct +{ + /* src picture related pointers */ + u8 *src; /* source buffer */ + u8 *lumSrc; + u8 *cbSrc; + u8 *crSrc; + + /* line buffer related pointers */ + u8 *buf; /* line buffer virtual address */ + u32 *reg; /* virtual address of registers in line buffer, only for fpga verification purpose */ + ptr_t busAddress; /* line buffer bus address */ + lineBufMem lumBuf; /*luma address in line buffer */ + lineBufMem cbBuf; /*cb address in line buffer */ + lineBufMem crBuf; /*cr address in line buffer */ + + /* encoding parameters */ + u32 inputFormat; /* format of input video */ + u32 pixOnRow; /* pixels in one line */ + u32 encWidth; + u32 encHeight; + u32 srcHeight; + u32 srcVerOffset; + + /* parameters of line buffer mode */ + i32 wrCnt; + u32 depth; /* number of MB_row lines in the input line buffer */ + u32 loopBackEn; + u32 hwHandShake; + + /*functions */ + getHEncRdMbLines getMbLines; /* get read mb lines from encoder register */ + setHEncWrMbLines setMbLines; /* set written mb lines to encoder register */ + + /* encoder instance */ + void *inst; +}inputLineBufferCfg; + +#ifdef PCIE_FPGA_VERI_LINEBUF +#include "encswhwregisters.h" +/* HW Register field names */ +typedef enum { + InputlineBufWrCntr, + InputlineBufDepth, + InputlineBufHwHandshake, + InputlineBufPicHeight, + InputlineBufRdCntr, +} lineBufRegName; + +#define LINE_BUF_SWREG_AMOUNT 4 /*4x 32-bit*/ + +static const regField_s lineBufRegisterDesc[] = { +/* HW ID register, read-only */ + {InputlineBufWrCntr , 0x000, 0x000001ff, 0, 0, RW, "slice_wr_cntr. +slice_depth when one slice is filled into slice_fifo"}, + {InputlineBufDepth , 0x000, 0x0003fe00, 9, 0, RW, "slice_depth. unit is MB line"}, + {InputlineBufHwHandshake , 0x000, 0x00040000, 18, 0, RW, "slice_hw_mode_en. active high. enable bit of slice_fifo hardware mode. should be disabled before the start of next frame."}, + {InputlineBufPicHeight , 0x000, 0x0ff80000, 19, 0, RW, "pic_height. same value of swreg14[18:10] in H1."}, + {InputlineBufRdCntr , 0x008, 0x000001ff, 0, 0, RO, "slice_rd_cntr. read only"}, +}; +#endif + +void HEncInitInputLineBufSrcPtr (inputLineBufferCfg *lineBufCfg); +void HEncInitInputLineBufPtr (inputLineBufferCfg *lineBufCfg); +i32 HEncInitInputLineBuffer(inputLineBufferCfg *lineBufCfg, const void *ewl); +void HEncStartInputLineBuffer(inputLineBufferCfg * lineBufCfg); +void HEncInputMBLineBufDone (void *pAppData); + +#endif + diff --git a/lib/vc8000nanoe/inc/enccommon.h b/lib/vc8000nanoe/inc/enccommon.h new file mode 100644 index 000000000..961d1aba3 --- /dev/null +++ b/lib/vc8000nanoe/inc/enccommon.h @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encoder common definitions for control code and system model + * + ******************************************************************************** + */ + +#ifndef __ENC_COMMON_H__ +#define __ENC_COMMON_H__ + +/*------------------------------------------------------------------------------ + 1. External compiler flags +------------------------------------------------------------------------------*/ + +/* Encoder global definitions + * + * _ASSERT_USED # Asserts enabled + * _DEBUG_PRINT # Prints debug information on stdout + * TRACE_STREAM # Creates stream trace file + * TEST_DATA # Creates test data files + * + * Can be defined here or using compiler flags */ + +#define DNF_PARAM_REGS + +/*------------------------------------------------------------------------------ + 2. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "ewl.h" + +/* Test data generation requires stream trace */ +#ifdef TEST_DATA +#ifndef TRACE_STREAM +#define TRACE_STREAM +#endif +#endif + +/* Stream tracing requires encdebug.h */ +#ifdef TRACE_STREAM +#ifndef H1_HAVE_ENCDEBUG_H +#define H1_HAVE_ENCDEBUG_H +#endif +#endif + +#ifdef H1_HAVE_ENCDEBUG_H +#include "encdebug.h" +#else +#define ASSERT(expr) +#define DEBUG_PRINT(args) +#define COMMENT(x) +#define COMMENTMBTYPE(x,y) +#define TRACE_BIT_STREAM(v,n) +#endif + +#ifdef H1_HAVE_ENCTRACE_H +#include "enctrace.h" +#endif + +/*------------------------------------------------------------------------------ + 3. Module defines +------------------------------------------------------------------------------*/ + +typedef enum +{ + ENCHW_NOK = -1, + ENCHW_OK = 0 +} bool_e; + +typedef enum +{ + ENCHW_NO = 0, + ENCHW_YES = 1 +} true_e; + +typedef enum +{ + NONIDR = 1, /* Coded slice of a non-IDR picture */ + IDR = 5, /* Coded slice of an IDR picture */ + SEI = 6, /* SEI message */ + SPSET = 7, /* Sequence parameter set */ + PPSET = 8, /* Picture parameter set */ + AUD_NUT = 9, + ENDOFSEQUENCE = 10, /* End of sequence */ + ENDOFSTREAM = 11, /* End of stream */ + FILLERDATA = 12, /* Filler data */ + PREFIX = 14, /* Prefix */ + SSPSET = 15, /* Subset sequence parameter set */ + MVC = 20 /* Coded slice of a view picture */ +} nalUnitType_e; + +/* VLC TABLE */ +typedef struct +{ + i32 value; /* Value of bits */ + i32 number; /* Number of bits */ +} table_s; + +/* used in stream buffer handling */ +typedef struct +{ + u8 *stream; /* Pointer to next byte of stream */ + u32 size; /* Byte size of stream buffer */ + u32 byteCnt; /* Byte counter */ + u32 bitCnt; /* Bit counter */ + u32 byteBuffer; /* Byte buffer */ + u32 bufferedBits; /* Amount of bits in byte buffer, [0-7] */ + u32 zeroBytes; /* Amount of consecutive zero bytes */ + i32 overflow; /* This will signal a buffer overflow */ + u32 emulCnt; /* Counter for emulation_3_byte, needed in SEI */ + i32 *table; /* Video packet or Gob sizes */ + i32 tableSize; /* Size of above table */ + i32 tableCnt; /* Table counter of above table */ +} stream_s; + +/* General tools */ +#define ABS(x) ((x) < (0) ? -(x) : (x)) +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#define SIGN(a) ((a) < (0) ? (-1) : (1)) +#define OUT_OF_RANGE(x,a,b) ((((i32)x)<(a)?(1):(0)) || ((x)>(b)?(1):(0))) +#define CLIP3(v, min, max) ((v) < (min) ? (min) : ((v) > (max) ? (max) : (v))) + +/* VP8 MB output information. Amount of data is 32 bytes/macroblock. */ + +/* Encoder MB output information defined as a struct. + + NOTE! By defining this struct we rely that ASIC output endianess + is configured properly to produce output that is identical + to the way the compiler constructs this struct. */ + +typedef struct +{ + u8 mode; /* refIdx 2b, chromaIntraMode 2b, mbMode 4b */ + u8 nonZeroCnt; + u16 bitCount; + i8 mvY[4]; + i16 mvX[4]; + u8 intra4x4[8]; /* 4 bits per block */ + u16 intraSad; + u16 interSad; + u8 inputMad_div128; + u8 yMean; + u8 cbMean; + u8 crMean; + u8 boostQp; /* H264 macroblock autoboost qp */ + u8 dummy0; /* Dummy (not used) place holder */ + u16 varRecon[3]; /* Mb variance after reconstruction but before DB-filter */ + u8 dummy1[2]; /* Dummy (not used) place holder */ + u16 varInput[3]; /* Mb variance before encoding loop */ +} encOutputMbInfo_s; + +typedef struct +{ + u8 mode; /* refIdx 2b, chromaIntraMode 2b, mbMode 4b */ + u8 nonZeroCnt; + u16 bitCount; + i8 mvY[4]; + i16 mvX[4]; + u8 intra4x4[8]; /* 4 bits per block */ + u16 intraSad; + u16 interSad; + u8 inputMad_div128; + u8 yMean; + u8 cbMean; + u8 crMean; + u8 boostQp; /* H264 macroblock autoboost qp */ + u8 dummy0; /* Dummy (not used) place holder */ + u16 varRecon[3]; /* Mb variance after reconstruction but before DB-filter */ + u8 dummy1[2]; /* Dummy (not used) place holder */ + u16 varInput[3]; /* Mb variance before encoding loop */ + u8 data[8]; +} encOutputMbInfoDebug_s; + +/* Masks for encOutputMbInfo.mode */ +#define MBOUT_8_MODE_MASK 0x0F +#define MBOUT_8_CHROMA_MODE_MASK 0x30 +#define MBOUT_8_REFIDX_MASK 0xC0 + +/* MB output information. Amount of data/mb in 16-bit words / bytes. + This is how things used to be before Foxtail release. + Older models rely on these defines. + For Foxtail data has increased to 48 bytes/MB, this is defined in model. */ +#define MBOUT_16 16 +#define MBOUT_8 32 + +/* 16-bit pointer offset to field. */ +#define MBOUT_16_BITCOUNT 1 +#define MBOUT_16_MV_B0_X 4 +#define MBOUT_16_MV_B1_X 5 +#define MBOUT_16_MV_B2_X 6 +#define MBOUT_16_MV_B3_X 7 +#define MBOUT_16_INTRA_SAD 12 +#define MBOUT_16_INTER_SAD 13 + +/* 8-bit pointer offset to field. */ +#define MBOUT_8_MODE 0 +#define MBOUT_8_NONZERO_CNT 1 +#define MBOUT_8_MV_B0_Y 4 +#define MBOUT_8_MV_B1_Y 5 +#define MBOUT_8_MV_B2_Y 6 +#define MBOUT_8_MV_B3_Y 7 +#define MBOUT_8_I4X4 16 +#define MBOUT_8_INPUT_MAD 28 +#define MBOUT_8_LUMA_MEAN 29 +#define MBOUT_8_CB_MEAN 30 +#define MBOUT_8_CR_MEAN 31 + +#define MBOUT_8_BOOS_QP 32 +#define MBOUT_8_VAR_REC_LUM 34 /* varRecon[0] */ +#define MBOUT_8_VAR_INP_LUM 42 /* varInput[0] */ + +/* for denoise */ +#define USE_TOP_CTRL_DENOISE (1) +#define FIX_POINT_BIT_WIDTH (10) +#define SIG_RECI_BIT_WIDTH (12) +#define MB_NUM_BIT_WIDTH (20) + +#define SNR_MAX (2< + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encoder debug definitions + * + ******************************************************************************** + */ + +#ifndef __ENC_DEBUG_H__ +#define __ENC_DEBUG_H__ + +#define CONFIG_ASSERT +#define CONFIG_ASSERT_LEVEL 2 + +#include + +#ifdef CONFIG_VENC_DEBUG +#define ASSERT(expr) __ASSERT_NO_MSG(expr) +#define DEBUG_PRINT(args) printf(args);printf("\n"); +#define COMMENT(x) printf(x);printf("\n"); +#define TRACE_BIT_STREAM(v,n) +#define APITRACE(x) printf(x);printf("\n"); +#define APITRACEPARAM(x,y) printf(" %s: %d\n",x,y); +#define APITRACEPARAMX(x,y) printf(" %s: 0x%x\n",x,y); +#else +#define ASSERT(expr) __ASSERT_NO_MSG(expr) +#define DEBUG_PRINT(args) +#define COMMENT(x) +#define TRACE_BIT_STREAM(v,n) +#define APITRACE(x) +#define APITRACEPARAM(x,y) +#define APITRACEPARAMX(x,y) +#endif + +#endif diff --git a/lib/vc8000nanoe/inc/encswhwregisters.h b/lib/vc8000nanoe/inc/encswhwregisters.h new file mode 100644 index 000000000..9983f96b8 --- /dev/null +++ b/lib/vc8000nanoe/inc/encswhwregisters.h @@ -0,0 +1,1617 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encoder SW/HW interface register definitions + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + +------------------------------------------------------------------------------*/ +#ifndef ENC_SWHWREGISTERS_H +#define ENC_SWHWREGISTERS_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#define ASIC_ID_BLUEBERRY 0x48311220 +#define ASIC_ID_CLOUDBERRY 0x48311480 +#define ASIC_ID_DRAGONFLY 0x48312170 +#define ASIC_ID_EVERGREEN 0x48313590 +#define ASIC_ID_EVERGREEN_PLUS 0x48314470 +#define ASIC_ID_FOXTAIL 0x48314780 +#define ASIC_ID_VCNE_V5 0x6e655000 +#define ASIC_ID_V6 0x48314780 +#define ASIC_ID_V7BASE 0x48317000 +#define ASIC_ID_V7 0x48317010 + +#define ASIC_INPUT_YUV420PLANAR 0x00 +#define ASIC_INPUT_YUV420SEMIPLANAR 0x01 +#define ASIC_INPUT_YUYV422INTERLEAVED 0x02 +#define ASIC_INPUT_UYVY422INTERLEAVED 0x03 +#define ASIC_INPUT_RGB565 0x04 +#define ASIC_INPUT_RGB555 0x05 +#define ASIC_INPUT_RGB444 0x06 +#define ASIC_INPUT_RGB888 0x07 +#define ASIC_INPUT_RGB101010 0x08 +#define ASIC_INPUT_SP_101010 0x09 //yuv420 10bit, semi-planar +#define ASIC_INPUT_P010 0x0a //yuv420 10 bit, planar, in 16 bit pixel, high 10bits valid, low 6 bits invalid. + + +/* Bytes of external memory for VP8 counters for probability updates, + * 252 counters for dct coeff probs, 1 for skipped, 1 for intra type and + * 2 * 11 for mv probs, each counter 2 bytes */ +#define ASIC_VP8_PROB_COUNT_SIZE 244*2 +#define ASIC_VP8_PROB_COUNT_MODE_OFFSET 220 +#define ASIC_VP8_PROB_COUNT_MV_OFFSET 222 + +/* HW Register field names */ +typedef enum { + HEncProductID, + HEncProductMajor, + HEncProductMinor, + HEncProductBuild, + + HEncIRQFuse, + HEncIRQSliceReady, + HEncIRQTimeout, + HEncIRQBuffer, + HEncIRQReset, + HEncIRQBusError, + HEncIRQFrameReady, + HEncIRQDisable, + HEncIRQ, + + HEncAXIWriteID, + HEncAXIReadID, + HEncOutputSwap16, + HEncInputSwap16, + HEncBurstLength, + HEncBurstDisable, + HEncBurstIncr, + HEncDataDiscard, + HEncClockGating, + HEncOutputSwap32, + HEncInputSwap32, + HEncOutputSwap8, + HEncInputSwap8, + + HEncScaleOutputSwap8, + HEncScaleOutputSwap16, + HEncScaleOutputSwap32, + HEncMvOutputSwap8, + HEncMvOutputSwap16, + HEncMvOutputSwap32, + HEncInputReadChunk, + HEncAXIDualCh, + HEncTestIrq, + + HEncBaseStream, + HEncBaseControl, + HEncBaseRefLum, + HEncBaseRefChr, + HEncBaseRecLum, + HEncBaseRecChr, + HEncBaseInLum, + HEncBaseInCb, + HEncBaseInCr, + + HEncIntTimeout, + HEncMvWrite, + HEncNalSizeWrite, + HEncIntSliceReady, + HEncWidth, + HEncHeight, + HEncRecWriteBuffer, + HEncRecWriteDisable, + HEncPictureType, + HEncEncodingMode, + HEncEnable, + + HEncChrOffset, + HEncLumOffset, + HEncRowLength, + HEncXFill, + HEncYFill, + HEncInputFormat, + HEncInputRot, + + HEncBaseRefLum2, + HEncBaseRefChr2, + HEncPicInitQp, + HEncSliceAlpha, + HEncSliceBeta, + HEncChromaQp, + HEncIdrPicId, + HEncConstrIP, + HEncPPSID, + HEncIPPrevModeFavor, + HEncFrameNum, + + HEncDeblocking, + HEncSliceSize, + HEncDisableQPMV, + HEncTransform8x8, + HEncCabacInitIdc, + HEncCabacEnable, + HEncInter4Restrict, + HEncStreamMode, + HEncIPIntra16Favor, + + HEncChromaSwap, + HEncSplitMv, + HEncDMVPenalty1p, + HEncDMVPenalty4p, + HEncDMVPenaltyQp, + + HEncJpegMode, + HEncJpegSlice, + HEncJpegRSTInt, + HEncJpegRST, + HEncSplitPenalty16x8, + HEncSplitPenalty8x8, + HEncSplitPenalty8x4, + + HEncSkipPenalty, + HEncNumSlicesReady, + HEncInterFavor, + + HEncStrmHdrRem1, + HEncStrmHdrRem2, + + HEncStrmBufLimit, + + HEncMadQpDelta, + HEncMadThreshold, + HEncQpSum, + + HEncQp, + HEncMaxQp, + HEncMinQp, + HEncCPDist, + + HEncCP1WordTarget, + HEncCP2WordTarget, + HEncCP3WordTarget, + HEncCP4WordTarget, + HEncCP5WordTarget, + HEncCP6WordTarget, + HEncCP7WordTarget, + HEncCP8WordTarget, + HEncCP9WordTarget, + HEncCP10WordTarget, + + HEncCPWordError1, + HEncCPWordError2, + HEncCPWordError3, + HEncCPWordError4, + HEncCPWordError5, + HEncCPWordError6, + + HEncCPDeltaQp1, + HEncCPDeltaQp2, + HEncCPDeltaQp3, + HEncCPDeltaQp4, + HEncCPDeltaQp5, + HEncCPDeltaQp6, + HEncCPDeltaQp7, + + HEncH264BaseRefLum2, + HEncH264BaseRefChr2, + HEncH264MvRefIdx, + HEncH264MarkCurrentLongTerm, + HEncH264Ref2Enable, + HEncH264LongTermPenalty, + + HEncVp8Y1QuantDc, + HEncVp8Y1ZbinDc, + HEncVp8Y1RoundDc, + HEncVp8Y1QuantAc, + HEncVp8Y1ZbinAc, + HEncVp8Y1RoundAc, + HEncVp8Y2QuantDc, + HEncVp8Y2ZbinDc, + HEncVp8Y2RoundDc, + HEncVp8Y2QuantAc, + HEncVp8Y2ZbinAc, + HEncVp8Y2RoundAc, + HEncVp8ChQuantDc, + HEncVp8ChZbinDc, + HEncVp8ChRoundDc, + HEncVp8ChQuantAc, + HEncVp8ChZbinAc, + HEncVp8ChRoundAc, + + HEncVp8Y1DequantDc, + HEncVp8Y1DequantAc, + HEncVp8Y2DequantDc, + HEncVp8MvRefIdx, + HEncVp8Y2DequantAc, + HEncVp8ChDequantDc, + HEncVp8ChDequantAc, + HEncVp8MvRefIdx2, + HEncVp8Ref2Enable, + HEncVp8SegmentEnable, + HEncVp8SegmentMapUpdate, + HEncVp8DeadzoneEnable, + HEncVp8BoolEncValue, + HEncVp8GoldenPenalty, + HEncVp8FilterSharpness, + HEncVp8FilterLevel, + HEncVp8DctPartitionCount, + HEncVp8BoolEncValueBits, + HEncVp8BoolEncRange, + + HEncIpolFilterMode, + HEncStartOffset, + HEncRlcSum, + HEncMadCount, + HEncMbCount, + + HEncBaseNextLum, + + HEncStabMode, + HEncStabMinimum, + HEncStabMotionSum, + HEncStabGmvX, + HEncStabMatrix1, + HEncStabGmvY, + HEncStabMatrix2, + HEncStabMatrix3, + HEncStabMatrix4, + HEncStabMatrix5, + HEncStabMatrix6, + HEncStabMatrix7, + HEncStabMatrix8, + HEncStabMatrix9, + + HEncBaseCabacCtx, + HEncBaseMvWrite, + + HEncRGBCoeffA, + HEncRGBCoeffB, + HEncRGBCoeffC, + HEncRGBCoeffE, + HEncRGBCoeffF, + + HEncRMaskMSB, + HEncGMaskMSB, + HEncBMaskMSB, + + HEncIntraAreaLeft, + HEncIntraAreaRight, + HEncIntraAreaTop, + HEncIntraAreaBottom, + + HEncCirStart, + HEncCirInterval, + + HEncIntraSliceMap1, + HEncIntraSliceMap2, + HEncIntraSliceMap3, + HEncBasePartition1, + HEncBasePartition2, + HEncBaseVp8ProbCount, + + HEncRoi1Left, + HEncRoi1Right, + HEncRoi1Top, + HEncRoi1Bottom, + + HEncRoi2Left, + HEncRoi2Right, + HEncRoi2Top, + HEncRoi2Bottom, + + HEncRoi1DeltaQp, + HEncRoi2DeltaQp, + HEncZeroMvFavor, + HEncSplitPenalty4x4, + + HEncMvcPriorityId, + HEncMvcViewId, + HEncMvcTemporalId, + HEncMvcAnchorPicFlag, + HEncMvcInterViewFlag, + + HEncHWChSearchArea, + HEncHWScalingSupport, + HEncHWSearchArea, + HEncHWRgbSupport, + HEncHWH264Support, + HEncHWVp8Support, + HEncHWJpegSupport, + HEncHWStabSupport, + HEncHWBus, + HEncHWSynthesisLan, + HEncHWBusWidth, + HEncHWMaxVideoWidth, + + HEncJpegQuantLuma1, + HEncJpegQuantLuma2, + HEncJpegQuantLuma3, + HEncJpegQuantLuma4, + HEncJpegQuantLuma5, + HEncJpegQuantLuma6, + HEncJpegQuantLuma7, + HEncJpegQuantLuma8, + HEncJpegQuantLuma9, + HEncJpegQuantLuma10, + HEncJpegQuantLuma11, + HEncJpegQuantLuma12, + HEncJpegQuantLuma13, + HEncJpegQuantLuma14, + HEncJpegQuantLuma15, + HEncJpegQuantLuma16, + + HEncJpegQuantChroma1, + HEncJpegQuantChroma2, + HEncJpegQuantChroma3, + HEncJpegQuantChroma4, + HEncJpegQuantChroma5, + HEncJpegQuantChroma6, + HEncJpegQuantChroma7, + HEncJpegQuantChroma8, + HEncJpegQuantChroma9, + HEncJpegQuantChroma10, + HEncJpegQuantChroma11, + HEncJpegQuantChroma12, + HEncJpegQuantChroma13, + HEncJpegQuantChroma14, + HEncJpegQuantChroma15, + HEncJpegQuantChroma16, + + /* VP8 penalty registers */ + HEncVp8Mode0Penalty, + HEncVp8Mode1Penalty, + HEncVp8Mode2Penalty, + HEncVp8Mode3Penalty, + HEncVp8Bmode0Penalty, + HEncVp8Bmode1Penalty, + HEncVp8Bmode2Penalty, + HEncVp8Bmode3Penalty, + HEncVp8Bmode4Penalty, + HEncVp8Bmode5Penalty, + HEncVp8Bmode6Penalty, + HEncVp8Bmode7Penalty, + HEncVp8Bmode8Penalty, + HEncVp8Bmode9Penalty, + HEncBaseVp8SegmentMap, + HEncVp8Seg1Y1QuantDc, + HEncVp8Seg1Y1ZbinDc, + HEncVp8Seg1Y1RoundDc, + HEncVp8Seg1Y1QuantAc, + HEncVp8Seg1Y1ZbinAc, + HEncVp8Seg1Y1RoundAc, + HEncVp8Seg1Y2QuantDc, + HEncVp8Seg1Y2ZbinDc, + HEncVp8Seg1Y2RoundDc, + HEncVp8Seg1Y2QuantAc, + HEncVp8Seg1Y2ZbinAc, + HEncVp8Seg1Y2RoundAc, + HEncVp8Seg1ChQuantDc, + HEncVp8Seg1ChZbinDc, + HEncVp8Seg1ChRoundDc, + HEncVp8Seg1ChQuantAc, + HEncVp8Seg1ChZbinAc, + HEncVp8Seg1ChRoundAc, + HEncVp8Seg1Y1DequantDc, + HEncVp8Seg1Y1DequantAc, + HEncVp8Seg1Y2DequantDc, + HEncVp8Seg1Y2DequantAc, + HEncVp8Seg1ChDequantDc, + HEncVp8Seg1ChDequantAc, + HEncVp8Seg1FilterLevel, + HEncVp8Seg2Y1QuantDc, + HEncVp8Seg2Y1ZbinDc, + HEncVp8Seg2Y1RoundDc, + HEncVp8Seg2Y1QuantAc, + HEncVp8Seg2Y1ZbinAc, + HEncVp8Seg2Y1RoundAc, + HEncVp8Seg2Y2QuantDc, + HEncVp8Seg2Y2ZbinDc, + HEncVp8Seg2Y2RoundDc, + HEncVp8Seg2Y2QuantAc, + HEncVp8Seg2Y2ZbinAc, + HEncVp8Seg2Y2RoundAc, + HEncVp8Seg2ChQuantDc, + HEncVp8Seg2ChZbinDc, + HEncVp8Seg2ChRoundDc, + HEncVp8Seg2ChQuantAc, + HEncVp8Seg2ChZbinAc, + HEncVp8Seg2ChRoundAc, + HEncVp8Seg2Y1DequantDc, + HEncVp8Seg2Y1DequantAc, + HEncVp8Seg2Y2DequantDc, + HEncVp8Seg2Y2DequantAc, + HEncVp8Seg2ChDequantDc, + HEncVp8Seg2ChDequantAc, + HEncVp8Seg2FilterLevel, + HEncVp8Seg3Y1QuantDc, + HEncVp8Seg3Y1ZbinDc, + HEncVp8Seg3Y1RoundDc, + HEncVp8Seg3Y1QuantAc, + HEncVp8Seg3Y1ZbinAc, + HEncVp8Seg3Y1RoundAc, + HEncVp8Seg3Y2QuantDc, + HEncVp8Seg3Y2ZbinDc, + HEncVp8Seg3Y2RoundDc, + HEncVp8Seg3Y2QuantAc, + HEncVp8Seg3Y2ZbinAc, + HEncVp8Seg3Y2RoundAc, + HEncVp8Seg3ChQuantDc, + HEncVp8Seg3ChZbinDc, + HEncVp8Seg3ChRoundDc, + HEncVp8Seg3ChQuantAc, + HEncVp8Seg3ChZbinAc, + HEncVp8Seg3ChRoundAc, + HEncVp8Seg3Y1DequantDc, + HEncVp8Seg3Y1DequantAc, + HEncVp8Seg3Y2DequantDc, + HEncVp8Seg3Y2DequantAc, + HEncVp8Seg3ChDequantDc, + HEncVp8Seg3ChDequantAc, + HEncVp8Seg3FilterLevel, + + HEncDmvPenalty1, + HEncDmvPenalty2, + HEncDmvPenalty3, + HEncDmvPenalty4, + HEncDmvPenalty5, + HEncDmvPenalty6, + HEncDmvPenalty7, + HEncDmvPenalty8, + HEncDmvPenalty9, + HEncDmvPenalty10, + HEncDmvPenalty11, + HEncDmvPenalty12, + HEncDmvPenalty13, + HEncDmvPenalty14, + HEncDmvPenalty15, + HEncDmvPenalty16, + HEncDmvPenalty17, + HEncDmvPenalty18, + HEncDmvPenalty19, + HEncDmvPenalty20, + HEncDmvPenalty21, + HEncDmvPenalty22, + HEncDmvPenalty23, + HEncDmvPenalty24, + HEncDmvPenalty25, + HEncDmvPenalty26, + HEncDmvPenalty27, + HEncDmvPenalty28, + HEncDmvPenalty29, + HEncDmvPenalty30, + HEncDmvPenalty31, + HEncDmvPenalty32, + + HEncDmvQpelPenalty1, + HEncDmvQpelPenalty2, + HEncDmvQpelPenalty3, + HEncDmvQpelPenalty4, + HEncDmvQpelPenalty5, + HEncDmvQpelPenalty6, + HEncDmvQpelPenalty7, + HEncDmvQpelPenalty8, + HEncDmvQpelPenalty9, + HEncDmvQpelPenalty10, + HEncDmvQpelPenalty11, + HEncDmvQpelPenalty12, + HEncDmvQpelPenalty13, + HEncDmvQpelPenalty14, + HEncDmvQpelPenalty15, + HEncDmvQpelPenalty16, + HEncDmvQpelPenalty17, + HEncDmvQpelPenalty18, + HEncDmvQpelPenalty19, + HEncDmvQpelPenalty20, + HEncDmvQpelPenalty21, + HEncDmvQpelPenalty22, + HEncDmvQpelPenalty23, + HEncDmvQpelPenalty24, + HEncDmvQpelPenalty25, + HEncDmvQpelPenalty26, + HEncDmvQpelPenalty27, + HEncDmvQpelPenalty28, + HEncDmvQpelPenalty29, + HEncDmvQpelPenalty30, + HEncDmvQpelPenalty31, + HEncDmvQpelPenalty32, + HEncVp8CostInter, + HEncVp8DmvCostConst, + HEncSplitZeroPenalty, + HEncVp8CostGoldenRef, + /* VP8 loop filter deltas */ + HEncVp8LfRefDelta0, + HEncVp8LfRefDelta1, + HEncVp8LfRefDelta2, + HEncVp8LfRefDelta3, + HEncVp8LfModeDelta0, + HEncVp8LfModeDelta1, + HEncVp8LfModeDelta2, + HEncVp8LfModeDelta3, + + HEncVp8DzCoeffRate0, + HEncVp8DzCoeffRate1, + HEncVp8DzCoeffRate2, + HEncVp8DzCoeffRate3, + HEncVp8DzCoeffRate4, + HEncVp8DzCoeffRate5, + HEncVp8DzCoeffRate6, + HEncVp8DzCoeffRate7, + HEncVp8DzCoeffRate8, + HEncVp8DzCoeffRate9, + HEncVp8DzCoeffRate10, + HEncVp8DzCoeffRate11, + HEncVp8DzCoeffRate12, + HEncVp8DzCoeffRate13, + HEncVp8DzCoeffRate14, + HEncVp8DzCoeffRate15, + HEncVp8DzCoeffRate16, + HEncVp8DzCoeffRate17, + HEncVp8DzCoeffRate18, + HEncVp8DzCoeffRate19, + HEncVp8DzCoeffRate20, + HEncVp8DzCoeffRate21, + HEncVp8DzCoeffRate22, + HEncVp8DzCoeffRate23, + HEncVp8DzCoeffRate24, + HEncVp8DzCoeffRate25, + HEncVp8DzCoeffRate26, + HEncVp8DzCoeffRate27, + HEncVp8DzCoeffRate28, + HEncVp8DzCoeffRate29, + HEncVp8DzCoeffRate30, + HEncVp8DzCoeffRate31, + HEncVp8DzCoeffRate32, + HEncVp8DzCoeffRate33, + HEncVp8DzCoeffRate34, + HEncVp8DzCoeffRate35, + HEncVp8DzCoeffRate36, + HEncVp8DzCoeffRate37, + HEncVp8DzCoeffRate38, + HEncVp8DzCoeffRate39, + HEncVp8DzCoeffRate40, + HEncVp8DzCoeffRate41, + HEncVp8DzCoeffRate42, + HEncVp8DzCoeffRate43, + HEncVp8DzCoeffRate44, + HEncVp8DzCoeffRate45, + HEncVp8DzCoeffRate46, + HEncVp8DzCoeffRate47, + + HEncVp8DzEobRate0, + HEncVp8DzEobRate1, + HEncVp8DzEobRate2, + HEncVp8DzEobRate3, + HEncVp8DzEobRate4, + HEncVp8DzEobRate5, + HEncVp8DzEobRate6, + HEncVp8DzEobRate7, + HEncVp8DzEobRate8, + HEncVp8DzEobRate9, + HEncVp8DzEobRate10, + HEncVp8DzEobRate11, + HEncVp8DzEobRate12, + HEncVp8DzEobRate13, + HEncVp8DzEobRate14, + HEncVp8DzEobRate15, + + HEncVp8DzRateM0, + HEncVp8DzRateM1, + HEncVp8DzRateM2, + HEncVp8DzRateM3, + + HEncVp8DzSkipRate0, + HEncVp8DzSkipRate1, + + HEncBaseScaledOutLum, + HEncScaleMode, + HEncScaledOutWidth, + HEncScaledOutWidthRatio, + HEncScaledOutHeight, + HEncScaledOutHeightRatio, + + HEncSquaredError, + + HEncMadThreshold2, + HEncMadQpDelta2, + HEncMadCount2, + + HEncMadThreshold3, + HEncMadQpDelta3, + HEncMadCount3, + + HEncVp8IpolCoeff01, + HEncVp8IpolCoeff02, + HEncVp8IpolCoeff03, + HEncVp8IpolCoeff04, + HEncVp8IpolCoeff05, + HEncVp8IpolCoeff06, + HEncVp8IpolCoeff11, + HEncVp8IpolCoeff12, + HEncVp8IpolCoeff13, + HEncVp8IpolCoeff14, + HEncVp8IpolCoeff15, + HEncVp8IpolCoeff16, + HEncVp8IpolCoeff21, + HEncVp8IpolCoeff22, + HEncVp8IpolCoeff23, + HEncVp8IpolCoeff24, + HEncVp8IpolCoeff25, + HEncVp8IpolCoeff26, + HEncVp8IpolCoeff31, + HEncVp8IpolCoeff32, + HEncVp8IpolCoeff33, + HEncVp8IpolCoeff34, + HEncVp8IpolCoeff35, + HEncVp8IpolCoeff36, + HEncVp8IpolCoeff41, + HEncVp8IpolCoeff42, + HEncVp8IpolCoeff43, + HEncVp8IpolCoeff44, + HEncVp8IpolCoeff45, + HEncVp8IpolCoeff46, + + HEncBasePartition3, + HEncBasePartition4, + + HEncSeg1I16Mode0Penalty, + HEncSeg1I16Mode1Penalty, + HEncSeg1I16Mode2Penalty, + HEncSeg1I16Mode3Penalty, + HEncSeg1I4Mode0Penalty, + HEncSeg1I4Mode1Penalty, + HEncSeg1I4Mode2Penalty, + HEncSeg1I4Mode3Penalty, + HEncSeg1I4Mode4Penalty, + HEncSeg1I4Mode5Penalty, + HEncSeg1I4Mode6Penalty, + HEncSeg1I4Mode7Penalty, + HEncSeg1I4Mode8Penalty, + HEncSeg1I4Mode9Penalty, + HEncSeg1I4PrevModeFavor, + HEncSeg1CostInter, + HEncSeg1I16Favor, + HEncSeg1InterFavor, + HEncSeg1SkipPenalty, + HEncSeg1GoldenPenalty, + HEncSeg1SplitPenalty8x4, + HEncSeg1SplitPenalty8x8, + HEncSeg1SplitPenalty16x8, + HEncSeg1SplitPenalty4x4, + HEncSeg1SplitZeroPenalty, + HEncSeg1DMVPenaltyQp, + HEncSeg1DzRateM0, + HEncSeg1DzRateM1, + HEncSeg1DzRateM2, + HEncSeg1DzRateM3, + HEncSeg1DzSkipRate0, + HEncSeg1DzSkipRate1, + HEncSeg1DmvCostConst, + + HEncSeg2I16Mode0Penalty, + HEncSeg2I16Mode1Penalty, + HEncSeg2I16Mode2Penalty, + HEncSeg2I16Mode3Penalty, + HEncSeg2I4Mode0Penalty, + HEncSeg2I4Mode1Penalty, + HEncSeg2I4Mode2Penalty, + HEncSeg2I4Mode3Penalty, + HEncSeg2I4Mode4Penalty, + HEncSeg2I4Mode5Penalty, + HEncSeg2I4Mode6Penalty, + HEncSeg2I4Mode7Penalty, + HEncSeg2I4Mode8Penalty, + HEncSeg2I4Mode9Penalty, + HEncSeg2I4PrevModeFavor, + HEncSeg2CostInter, + HEncSeg2I16Favor, + HEncSeg2InterFavor, + HEncSeg2SkipPenalty, + HEncSeg2GoldenPenalty, + HEncSeg2SplitPenalty8x4, + HEncSeg2SplitPenalty8x8, + HEncSeg2SplitPenalty16x8, + HEncSeg2SplitPenalty4x4, + HEncSeg2SplitZeroPenalty, + HEncSeg2DMVPenaltyQp, + HEncSeg2DzRateM0, + HEncSeg2DzRateM1, + HEncSeg2DzRateM2, + HEncSeg2DzRateM3, + HEncSeg2DzSkipRate0, + HEncSeg2DzSkipRate1, + HEncSeg2DmvCostConst, + + HEncSeg3I16Mode0Penalty, + HEncSeg3I16Mode1Penalty, + HEncSeg3I16Mode2Penalty, + HEncSeg3I16Mode3Penalty, + HEncSeg3I4Mode0Penalty, + HEncSeg3I4Mode1Penalty, + HEncSeg3I4Mode2Penalty, + HEncSeg3I4Mode3Penalty, + HEncSeg3I4Mode4Penalty, + HEncSeg3I4Mode5Penalty, + HEncSeg3I4Mode6Penalty, + HEncSeg3I4Mode7Penalty, + HEncSeg3I4Mode8Penalty, + HEncSeg3I4Mode9Penalty, + HEncSeg3I4PrevModeFavor, + HEncSeg3CostInter, + HEncSeg3I16Favor, + HEncSeg3InterFavor, + HEncSeg3SkipPenalty, + HEncSeg3GoldenPenalty, + HEncSeg3SplitPenalty8x4, + HEncSeg3SplitPenalty8x8, + HEncSeg3SplitPenalty16x8, + HEncSeg3SplitPenalty4x4, + HEncSeg3SplitZeroPenalty, + HEncSeg3DMVPenaltyQp, + HEncSeg3DzRateM0, + HEncSeg3DzRateM1, + HEncSeg3DzRateM2, + HEncSeg3DzRateM3, + HEncSeg3DzSkipRate0, + HEncSeg3DzSkipRate1, + HEncSeg3DmvCostConst, + + HEncVp8AvgVar, + HEncVp8InvAvgVar, + HEncFieldPicFlag, + HEncBottomFieldFlag, + HEncFieldParity, + + HEncBoostQp, + HEncBoostVar1, + HEncBoostVar2, + + HEncVarLimit, + HEncVarInterFavor, + HEncVarMultiplier, + HEncVarAdd, + HEncPskipMode, + + +#include "reg_enum_v7.h" + + HEncRegisterAmount + +} regName; + +/* HW Register field descriptions */ +typedef struct { + u32 name; /* Register name and index */ + i32 base; /* Register base address */ + u32 mask; /* Bitmask for this field */ + i32 lsb; /* LSB for this field [31..0] */ + i32 trace; /* Enable/disable writing in swreg_params.trc */ + i32 rw; /* 1=Read-only 2=Write-only 3=Read-Write */ + char *description; /* Field description */ +} regField_s; + +/* Flags for read-only, write-only and read-write */ +#define RO 1 +#define WO 2 +#define RW 3 + +/* Description field only needed for system model build. */ +#ifdef TEST_DATA + #define H1REG(name, base, mask, lsb, trace, rw, desc) \ + {name, base, mask, lsb, trace, rw, desc} +#else + #define H1REG(name, base, mask, lsb, trace, rw, desc) \ + {name, base, mask, lsb, trace, rw, ""} +#endif + +/* NOTE: Don't use ',' in descriptions, because it is used as separator in csv + * parsing. */ +static const regField_s asicRegisterDesc[] = { +/* HW ID register, read-only */ + H1REG(HEncProductID , 0x000, 0xffff0000, 16, 0, RO, "Product ID"), + H1REG(HEncProductMajor , 0x000, 0x0000f000, 12, 0, RO, "Major number"), + H1REG(HEncProductMinor , 0x000, 0x00000ff0, 4, 0, RO, "Minor number"), + H1REG(HEncProductBuild , 0x000, 0x0000000f, 0, 0, RO, "Build number defined in synthesis."), +/* Encoder interrupt register */ + H1REG(HEncIRQFuse , 0x004, 0x00000200, 9, 0, RW, "IRQ stream format fuse status bit. Format disabled by fuse."), + H1REG(HEncIRQSliceReady , 0x004, 0x00000100, 8, 0, RW, "IRQ slice ready status bit. Slice is ready but frame encoding continues."), + H1REG(HEncIRQTimeout , 0x004, 0x00000040, 6, 0, RW, "IRQ HW timeout status bit. HW encoding failed."), + H1REG(HEncIRQBuffer , 0x004, 0x00000020, 5, 1, RW, "IRQ buffer full status bit. bufferFullInterrupt"), + H1REG(HEncIRQReset , 0x004, 0x00000010, 4, 0, RW, "IRQ SW reset status bit."), + H1REG(HEncIRQBusError , 0x004, 0x00000008, 3, 0, RW, "IRQ bus error status bit."), + H1REG(HEncIRQFrameReady , 0x004, 0x00000004, 2, 0, RW, "IRQ frame ready status bit. Encoder has finished a frame."), + H1REG(HEncIRQDisable , 0x004, 0x00000002, 1, 0, RW, "IRQ disable. No interrupts from HW. SW must use polling."), + H1REG(HEncIRQ , 0x004, 0x00000001, 0, 0, RW, "HINTenc Interrupt from HW. SW resets at IRQ handler."), +/* Encoder configuration register */ + H1REG(HEncAXIWriteID , 0x008, 0xff000000, 24, 0, RW, "AXI Write ID"), + H1REG(HEncAXIReadID , 0x008, 0x00ff0000, 16, 0, RW, "AXI Read ID"), + H1REG(HEncOutputSwap16 , 0x008, 0x00008000, 15, 0, RW, "Enable output stream swap 16-bits"), + H1REG(HEncInputSwap16 , 0x008, 0x00004000, 14, 0, RW, "Enable input swap 16-bits"), + H1REG(HEncBurstLength , 0x008, 0x00003f00, 8, 0, RW, "Burst length. 0=incremental. 4=max BURST4.8=max BURST8. 16=max BURST16"), + H1REG(HEncBurstDisable , 0x008, 0x00000080, 7, 0, RW, "Disable burst mode for AXI"), + H1REG(HEncBurstIncr , 0x008, 0x00000040, 6, 0, RW, "Burst incremental. 1=INCR burst allowed. 0=use SINGLE burst"), + H1REG(HEncDataDiscard , 0x008, 0x00000020, 5, 0, RW, "Enable burst data discard. 2 or 3 long reads are using BURST4"), + H1REG(HEncClockGating , 0x008, 0x00000010, 4, 0, RW, "Enable clock gating"), + H1REG(HEncOutputSwap32 , 0x008, 0x00000008, 3, 0, RW, "Enable output stream swap 32-bits"), + H1REG(HEncInputSwap32 , 0x008, 0x00000004, 2, 0, RW, "Enable input swap 32-bits"), + H1REG(HEncOutputSwap8 , 0x008, 0x00000002, 1, 0, RW, "Enable output stream swap 8-bits"), + H1REG(HEncInputSwap8 , 0x008, 0x00000001, 0, 0, RW, "Enable input swap 8-bits"), + H1REG(HEncScaleOutputSwap8 , 0x00c, 0x08000000, 27, 0, RW, "Enable output scaled image swap for 8-bits"), + H1REG(HEncScaleOutputSwap16, 0x00c, 0x04000000, 26, 0, RW, "Enable output scaled image swap for 16-bits"), + H1REG(HEncScaleOutputSwap32, 0x00c, 0x02000000, 25, 0, RW, "Enable output scaled image swap for 32-bits"), + H1REG(HEncMvOutputSwap8 , 0x00c, 0x01000000, 24, 0, RW, "Enable output MV (MB info) swap for 8-bits"), + H1REG(HEncMvOutputSwap16 , 0x00c, 0x00800000, 23, 0, RW, "Enable output MV (MB info) swap for 16-bits"), + H1REG(HEncMvOutputSwap32 , 0x00c, 0x00400000, 22, 0, RW, "Enable output MV (MB info) swap for 32-bits"), + H1REG(HEncInputReadChunk , 0x00c, 0x00200000, 21, 0, RW, "Chunk size for input picture read 0=4 MBs. 1=1 MB"), + H1REG(HEncAXIDualCh , 0x00c, 0x00100000, 20, 0, RW, "Disable dual channel AXI. 0=use two channels. 1=use single channel."), + H1REG(HEncTestIrq , 0x00c, 0x00000001, 0, 0, RW, "Enable MB bus timing info output."), +/* External memory base addresses for encoder input/outputput */ + H1REG(HEncBaseStream , 0x014, 0xffffffff, 0, 0, RW, "Base address for output stream data"), + H1REG(HEncBaseControl , 0x018, 0xffffffff, 0, 0, RW, "Base address for output control data"), + H1REG(HEncBaseRefLum , 0x01c, 0xffffffff, 0, 0, RW, "Base address for reference luma"), + H1REG(HEncBaseRefChr , 0x020, 0xffffffff, 0, 0, RW, "Base address for reference chroma"), + H1REG(HEncBaseRecLum , 0x024, 0xffffffff, 0, 0, RW, "Base address for reconstructed luma"), + H1REG(HEncBaseRecChr , 0x028, 0xffffffff, 0, 0, RW, "Base address for reconstructed chroma"), + H1REG(HEncBaseInLum , 0x02c, 0xffffffff, 0, 0, RW, "Base address for input picture luma"), + H1REG(HEncBaseInCb , 0x030, 0xffffffff, 0, 0, RW, "Base address for input picture cb"), + H1REG(HEncBaseInCr , 0x034, 0xffffffff, 0, 0, RW, "Base address for input picture cr"), + H1REG(HEncIntTimeout , 0x038, 0x80000000, 31, 0, RW, "Enable interrupt for timeout"), + H1REG(HEncMvWrite , 0x038, 0x40000000, 30, 1, RW, "Enable writing MV and SAD of each MB to BaseMvWrite"), + H1REG(HEncNalSizeWrite , 0x038, 0x20000000, 29, 1, RW, "Enable writing size of each NAL unit to BaseControl, nalSizeWriteOut"), + H1REG(HEncIntSliceReady , 0x038, 0x10000000, 28, 0, RW, "Enable interrupt for slice ready"), + H1REG(HEncWidth , 0x038, 0x0ff80000, 19, 1, RW, "Encoded width. lumWidth (macroblocks) H264:[9..255] JPEG:[6..511]"), + H1REG(HEncHeight , 0x038, 0x0007fc00, 10, 1, RW, "Encoded height. lumHeight (macroblocks) H264:[6..255] JPEG:[2..511]"), + H1REG(HEncRecWriteBuffer , 0x038, 0x00000080, 7, 1, RW, "Size of buffer used when writing reconstructed image. 0=1 MB buffered (write burst for every MB). 1=4 MBs buffered (write burst for every fourth MB)"), + H1REG(HEncRecWriteDisable , 0x038, 0x00000040, 6, 1, RW, "Disable writing of reconstructed image. recWriteDisable"), + H1REG(HEncPictureType , 0x038, 0x00000018, 3, 1, RW, "Encoded picture type. frameType. 0=INTER. 1=INTRA(IDR). 2=MVC-INTER. 3=MVC-INTER(ref mod)."), + H1REG(HEncEncodingMode , 0x038, 0x00000006, 1, 1, RW, "Encoding mode. streamType. 1=VP8. 2=JPEG. 3=H264"), + H1REG(HEncEnable , 0x038, 0x00000001, 0, 0, RW, "Encoder enable"), + H1REG(HEncChrOffset , 0x03c, 0xe0000000, 29, 0, RW, "Input chrominance offset (bytes) [0..7]"), + H1REG(HEncLumOffset , 0x03c, 0x1c000000, 26, 0, RW, "Input luminance offset (bytes) [0..7]"), + H1REG(HEncRowLength , 0x03c, 0x03fff000, 12, 1, RW, "Input luminance row length. lumWidthSrc (bytes) [96..8192]"), + H1REG(HEncXFill , 0x03c, 0x00000c00, 10, 0, RW, "Overfill pixels on right edge of image div4 [0..3]"), + H1REG(HEncYFill , 0x03c, 0x000003c0, 6, 1, RW, "Overfill pixels on bottom edge of image. YFill. [0..15]"), + H1REG(HEncInputFormat , 0x03c, 0x0000003c, 2, 1, RW, "Input image format. inputFormat. YUV420P/YUV420SP/YUYV422/UYVY422/RGB565/RGB555/RGB444/RGB888/RGB101010/P010SP/P010P"), + H1REG(HEncInputRot , 0x03c, 0x00000003, 0, 1, RW, "Input image rotation. 0=disabled. 1=90 degrees right. 2=90 degrees left. 3=180 degrees right."), + +/* VP8 / H.264 mixed definitions */ + H1REG(HEncBaseRefLum2 , 0x040, 0xffffffff, 0, 0, RW, "Base address for second reference luma"), + H1REG(HEncBaseRefChr2 , 0x044, 0xffffffff, 0, 0, RW, "Base address for second reference chroma"), + H1REG(HEncPicInitQp , 0x040, 0xfc000000, 26, 0, RW, "H.264 Pic init qp in PPS [0..51]"), + H1REG(HEncSliceAlpha , 0x040, 0x03c00000, 22, 0, RW, "H.264 Slice filter alpha c0 offset div2 [-6..6]"), + H1REG(HEncSliceBeta , 0x040, 0x003c0000, 18, 0, RW, "H.264 Slice filter beta offset div2 [-6..6]"), + H1REG(HEncChromaQp , 0x040, 0x0003e000, 13, 0, RW, "H.264 Chroma qp index offset [-12..12]"), + H1REG(HEncIdrPicId , 0x040, 0x0000001e, 1, 0, RW, "H.264 IDR picture ID"), + H1REG(HEncConstrIP , 0x040, 0x00000001, 0, 1, RW, "H.264 Constrained intra prediction enable. constIntraPred"), + H1REG(HEncPPSID , 0x044, 0xff000000, 24, 0, RW, "H.264 pic_parameter_set_id"), + H1REG(HEncIPPrevModeFavor , 0x044, 0x00ff0000, 16, 0, RW, "H.264 Intra prediction previous 4x4 mode favor"), + H1REG(HEncFrameNum , 0x044, 0x0000ffff, 0, 0, RW, "H.264 Frame num"), + + H1REG(HEncDeblocking , 0x048, 0xc0000000, 30, 0, RW, "Deblocking filter mode. 0=enabled. 1=disabled (vp8=simple). 2=disabled on slice borders"), + H1REG(HEncSliceSize , 0x048, 0x3f800000, 23, 1, RW, "H.264 Slice size. mbRowPerSlice (mb rows) [0..127] 0=one slice per picture"), + H1REG(HEncDisableQPMV , 0x048, 0x00400000, 22, 1, RW, "H.264 Disable quarter pixel MVs. disableQuarterPixelMv"), + H1REG(HEncTransform8x8 , 0x048, 0x00200000, 21, 1, RW, "H.264 Transform 8x8 enable. High Profile H.264. transform8x8Mode"), + H1REG(HEncCabacInitIdc , 0x048, 0x00180000, 19, 0, RW, "H.264 CABAC initial IDC. [0..2]"), + H1REG(HEncCabacEnable , 0x048, 0x00040000, 18, 1, RW, "H.264 CABAC / VP8 boolenc enable. entropyCodingMode. 0=CAVLC (Baseline Profile H.264). 1=CABAC (Main Profile H.264)"), + H1REG(HEncInter4Restrict , 0x048, 0x00020000, 17, 1, RW, "H.264 Inter 4x4 mode restriction. restricted4x4Mode"), + H1REG(HEncStreamMode , 0x048, 0x00010000, 16, 1, RW, "H.264 Stream mode. byteStream. 0=NAL unit stream. 1=Byte stream"), + H1REG(HEncIPIntra16Favor , 0x048, 0x0000ffff, 0, 0, RW, "Intra prediction intra 16x16 mode favor"), + H1REG(HEncChromaSwap , 0x04c, 0x80000000, 31, 1, RW, "Swap order of chroma bytes in semiplanar input format."), + H1REG(HEncSplitMv , 0x04c, 0x40000000, 30, 1, RW, "Enable using more than 1 MV per macroblock."), + H1REG(HEncDMVPenalty1p , 0x04c, 0x000003ff, 0, 1, RW, "Differential MV penalty for 1p ME. DMVPenalty1p"), + H1REG(HEncDMVPenalty4p , 0x04c, 0x000ffc00, 10, 1, RW, "Differential MV penalty for 4p ME. DMVPenalty4p"), + H1REG(HEncDMVPenaltyQp , 0x04c, 0x3ff00000, 20, 1, RW, "Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + +/* Mixed definitions JPEG / video */ + H1REG(HEncJpegMode , 0x050, 0x02000000, 25, 0, RW, "JPEG mode. 0=4:2:0 (4lum+2chr blocks/MCU). 1=4:2:2 (2lum+2chr blocks/MCU)"), + H1REG(HEncJpegSlice , 0x050, 0x01000000, 24, 0, RW, "JPEG slice enable. 0=picture ends with EOI. 1=slice ends with RST"), + H1REG(HEncJpegRSTInt , 0x050, 0x00ff0000, 16, 0, RW, "JPEG restart marker interval when slices are disabled (mb rows) [0..255]"), + H1REG(HEncJpegRST , 0x050, 0x0000ffff, 0, 0, RW, "JPEG restart marker for first RST. incremented by HW for next RST"), + H1REG(HEncSplitPenalty16x8 , 0x050, 0x3ff00000, 20, 0, RW, "Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSplitPenalty8x8 , 0x050, 0x000ffc00, 10, 0, RW, "Penalty for using 8x8 MV."), + H1REG(HEncSplitPenalty8x4 , 0x050, 0x000003ff, 0, 0, RW, "Penalty for using 8x4 or 4x8 MV."), + + H1REG(HEncSkipPenalty , 0x054, 0xff000000, 24, 0, RW, "H.264 SKIP macroblock mode / VP8 zero/nearest/near mode penalty"), + H1REG(HEncNumSlicesReady , 0x054, 0x00ff0000, 16, 0, RW, "H.264 amount of completed slices."), + H1REG(HEncInterFavor , 0x054, 0x0000ffff, 0, 0, RW, "Inter MB mode favor in intra/inter selection"), + H1REG(HEncStrmHdrRem1 , 0x058, 0xffffffff, 0, 0, RW, "Stream header remainder bits MSB (MSB aligned)"), + H1REG(HEncStrmHdrRem2 , 0x05c, 0xffffffff, 0, 0, RW, "Stream header remainder bits LSB (MSB aligned)"), + H1REG(HEncStrmBufLimit , 0x060, 0xffffffff, 0, 1, RW, "Stream buffer limit (64bit addresses) / output stream size (bits). HWStreamDataCount. If limit is reached buffer full IRQ is given."), + H1REG(HEncMadQpDelta , 0x064, 0xf0000000, 28, 1, RW, "MAD based QP adjustment. madQpChange [-8..7]"), + H1REG(HEncMadThreshold , 0x064, 0x0fc00000, 22, 0, RW, "MAD threshold div256"), + H1REG(HEncQpSum , 0x064, 0x003fffff, 0, 0, RW, "QP Sum div2 output"), + +/* H.264 Rate control registers */ + H1REG(HEncQp , 0x06c, 0xfc000000, 26, 1, RW, "H.264 Initial QP. qpLum [0..51]"), + H1REG(HEncMaxQp , 0x06c, 0x03f00000, 20, 1, RW, "H.264 Maximum QP. qpMax [0..51]"), + H1REG(HEncMinQp , 0x06c, 0x000fc000, 14, 1, RW, "H.264 Minimum QP. qpMin [0..51]"), + H1REG(HEncCPDist , 0x06c, 0x00001fff, 0, 0, RW, "H.264 Checkpoint distance (mb) 0=disabled [0..8191]"), + H1REG(HEncCP1WordTarget , 0x070, 0xffff0000, 16, 0, RW, "H.264 Checkpoint 1 word target/usage div32 [0..65535]"), + H1REG(HEncCP2WordTarget , 0x070, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint 2 word target/usage div32 [0..65535]"), + H1REG(HEncCP3WordTarget , 0x074, 0xffff0000, 16, 0, RW, "H.264 Checkpoint 3 word target/usage div32 [0..65535]"), + H1REG(HEncCP4WordTarget , 0x074, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint 4 word target/usage div32 [0..65535]"), + H1REG(HEncCP5WordTarget , 0x078, 0xffff0000, 16, 0, RW, "H.264 Checkpoint 5 word target/usage div32 [0..65535]"), + H1REG(HEncCP6WordTarget , 0x078, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint 6 word target/usage div32 [0..65535]"), + H1REG(HEncCP7WordTarget , 0x07c, 0xffff0000, 16, 0, RW, "H.264 Checkpoint 7 word target/usage div32 [0..65535]"), + H1REG(HEncCP8WordTarget , 0x07c, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint 8 word target/usage div32 [0..65535]"), + H1REG(HEncCP9WordTarget , 0x080, 0xffff0000, 16, 0, RW, "H.264 Checkpoint 9 word target/usage div32 [0..65535]"), + H1REG(HEncCP10WordTarget , 0x080, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint 10 word target/usage div32 [0..65535]"), + H1REG(HEncCPWordError1 , 0x084, 0xffff0000, 16, 0, RW, "H.264 Checkpoint word error 1 div4 [-32768..32767]"), + H1REG(HEncCPWordError2 , 0x084, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint word error 2 div4 [-32768..32767]"), + H1REG(HEncCPWordError3 , 0x088, 0xffff0000, 16, 0, RW, "H.264 Checkpoint word error 3 div4 [-32768..32767]"), + H1REG(HEncCPWordError4 , 0x088, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint word error 4 div4 [-32768..32767]"), + H1REG(HEncCPWordError5 , 0x08c, 0xffff0000, 16, 0, RW, "H.264 Checkpoint word error 5 div4 [-32768..32767]"), + H1REG(HEncCPWordError6 , 0x08c, 0x0000ffff, 0, 0, RW, "H.264 Checkpoint word error 6 div4 [-32768..32767]"), + H1REG(HEncCPDeltaQp1 , 0x090, 0x0f000000, 24, 0, RW, "H.264 Checkpoint delta QP 1 [-8..7]"), + H1REG(HEncCPDeltaQp2 , 0x090, 0x00f00000, 20, 0, RW, "H.264 Checkpoint delta QP 2 [-8..7]"), + H1REG(HEncCPDeltaQp3 , 0x090, 0x000f0000, 16, 0, RW, "H.264 Checkpoint delta QP 3 [-8..7]"), + H1REG(HEncCPDeltaQp4 , 0x090, 0x0000f000, 12, 0, RW, "H.264 Checkpoint delta QP 4 [-8..7]"), + H1REG(HEncCPDeltaQp5 , 0x090, 0x00000f00, 8, 0, RW, "H.264 Checkpoint delta QP 5 [-8..7]"), + H1REG(HEncCPDeltaQp6 , 0x090, 0x000000f0, 4, 0, RW, "H.264 Checkpoint delta QP 6 [-8..7]"), + H1REG(HEncCPDeltaQp7 , 0x090, 0x0000000f, 0, 0, RW, "H.264 Checkpoint delta QP 7 [-8..7]"), + +/* H264 long-term ref bases */ + H1REG(HEncH264BaseRefLum2 , 0x070, 0xffffffff, 0, 0, RW, "H264 secondary ref pic base"), + H1REG(HEncH264BaseRefChr2 , 0x074, 0xffffffff, 0, 0, RW, "H264 secondary ref pic base"), + H1REG(HEncH264MvRefIdx , 0x084, 0x0c000000, 26, 0, RW, "H264 mvRefIdx for first reference frame. 0=ipf. 1=ltr."), + H1REG(HEncH264MarkCurrentLongTerm, 0x088, 0x04000000, 26, 0, RW, "H264 flag to mark current pic as long term ref"), + H1REG(HEncH264Ref2Enable , 0x088, 0x10000000, 28, 1, RW, "H264 enable for second reference frame."), + H1REG(HEncH264LongTermPenalty , 0x090, 0xff000000, 24, 0, RW, "H264 Penalty value for second reference frame zero-mv [0..255]"), + +/* VP8 Rate control registers, register 0x6C redefined for VP8 */ + H1REG(HEncVp8Y1QuantDc , 0x06C, 0x00003fff, 0, 1, RW, "VP8 qpY1QuantDc 14b"), + H1REG(HEncVp8Y1ZbinDc , 0x06C, 0x007fc000, 14, 1, RW, "VP8 qpY1ZbinDc 9b"), + H1REG(HEncVp8Y1RoundDc , 0x06C, 0x7f800000, 23, 1, RW, "VP8 qpY1RoundDc 8b"), + H1REG(HEncVp8Y1QuantAc , 0x070, 0x00003fff, 0, 1, RW, "VP8 qpY1QuantAc 14b"), + H1REG(HEncVp8Y1ZbinAc , 0x070, 0x007fc000, 14, 1, RW, "VP8 qpY1ZbinAc 9b"), + H1REG(HEncVp8Y1RoundAc , 0x070, 0x7f800000, 23, 1, RW, "VP8 qpY1RoundAc 8b"), + H1REG(HEncVp8Y2QuantDc , 0x074, 0x00003fff, 0, 1, RW, "VP8 qpY2QuantDc 14b"), + H1REG(HEncVp8Y2ZbinDc , 0x074, 0x007fc000, 14, 1, RW, "VP8 qpY2ZbinDc 9b"), + H1REG(HEncVp8Y2RoundDc , 0x074, 0x7f800000, 23, 1, RW, "VP8 qpY2RoundDc 8b"), + H1REG(HEncVp8Y2QuantAc , 0x078, 0x00003fff, 0, 1, RW, "VP8 qpY2QuantAc 14b"), + H1REG(HEncVp8Y2ZbinAc , 0x078, 0x007fc000, 14, 1, RW, "VP8 qpY2ZbinAc 9b"), + H1REG(HEncVp8Y2RoundAc , 0x078, 0x7f800000, 23, 1, RW, "VP8 qpY2RoundAc 8b"), + H1REG(HEncVp8ChQuantDc , 0x07C, 0x00003fff, 0, 1, RW, "VP8 qpChQuantDc 14b"), + H1REG(HEncVp8ChZbinDc , 0x07C, 0x007fc000, 14, 1, RW, "VP8 qpChZbinDc 9b"), + H1REG(HEncVp8ChRoundDc , 0x07C, 0x7f800000, 23, 1, RW, "VP8 qpChRoundDc 8b"), + H1REG(HEncVp8ChQuantAc , 0x080, 0x00003fff, 0, 1, RW, "VP8 qpChQuantAc 14b"), + H1REG(HEncVp8ChZbinAc , 0x080, 0x007fc000, 14, 1, RW, "VP8 qpChZbinAc 9b"), + H1REG(HEncVp8ChRoundAc , 0x080, 0x7f800000, 23, 1, RW, "VP8 qpChRoundAc 8b"), + H1REG(HEncVp8Y1DequantDc , 0x084, 0x000000ff, 0, 1, RW, "VP8 qpY1DequantDc 8b"), + H1REG(HEncVp8Y1DequantAc , 0x084, 0x0001ff00, 8, 1, RW, "VP8 qpY1DequantAc 9b"), + H1REG(HEncVp8Y2DequantDc , 0x084, 0x03fe0000, 17, 1, RW, "VP8 qpY2DequantDc 9b"), + H1REG(HEncVp8MvRefIdx , 0x084, 0x0c000000, 26, 0, RW, "VP8 mvRefIdx for first reference frame. 0=ipf. 1=grf. 2=arf."), + H1REG(HEncVp8Y2DequantAc , 0x088, 0x000001ff, 0, 1, RW, "VP8 qpY2DequantAc 9b"), + H1REG(HEncVp8ChDequantDc , 0x088, 0x0001fe00, 9, 1, RW, "VP8 qpChDequantDc 8b"), + H1REG(HEncVp8ChDequantAc , 0x088, 0x03fe0000, 17, 1, RW, "VP8 qpChDequantAc 9b"), + H1REG(HEncVp8MvRefIdx2 , 0x088, 0x0c000000, 26, 0, RW, "VP8 mvRefIdx for second reference frame. 0=ipf. 1=grf. 2=arf."), + H1REG(HEncVp8Ref2Enable , 0x088, 0x10000000, 28, 0, RW, "VP8 enable for second reference frame."), + H1REG(HEncVp8SegmentEnable , 0x088, 0x20000000, 29, 1, RW, "VP8 enable for segmentation. Segmentation map is stored in BaseSegmentMap."), + H1REG(HEncVp8SegmentMapUpdate , 0x088, 0x40000000, 30, 0, RW, "VP8 enable for segmentation map update. Map is different from previous frame and is written in stream. "), + H1REG(HEncVp8DeadzoneEnable , 0x088, 0x80000000, 31, 0, RW, "VP8 enable for deadzone."), + H1REG(HEncVp8BoolEncValue , 0x08C, 0xffffffff, 0, 1, RW, "VP8 boolEncValue"), + H1REG(HEncVp8GoldenPenalty , 0x090, 0xff000000, 24, 0, RW, "VP8 Penalty value for second reference frame zero-mv [0..255]"), + H1REG(HEncVp8FilterSharpness , 0x090, 0x00e00000, 21, 0, RW, "VP8 Deblocking filter sharpness [0..7]"), + H1REG(HEncVp8FilterLevel , 0x090, 0x001f8000, 15, 0, RW, "VP8 Deblocking filter level [0..63]"), + H1REG(HEncVp8DctPartitionCount, 0x090, 0x00006000, 13, 0, RW, "VP8 DCT partition count. 0=1. 1=2. 2=4 [0..2]"), + H1REG(HEncVp8BoolEncValueBits , 0x090, 0x00001f00, 8, 1, RW, "VP8 boolEncValueBitsMinus8 [0..23]"), + H1REG(HEncVp8BoolEncRange , 0x090, 0x000000ff, 0, 1, RW, "VP8 boolEncRange [0..255]"), + + H1REG(HEncIpolFilterMode , 0x094, 0x80000000, 31, 0, RW, "Mode for VP8 interpolation filter. 0=bicubic. 1=bilinear."), + H1REG(HEncStartOffset , 0x094, 0x1f800000, 23, 0, RW, "Stream start offset = amount of StrmHdrRem (bits) [0..63]"), + H1REG(HEncRlcSum , 0x094, 0x007fffff, 0, 0, RW, "RLC codeword count div4 output. max 255*255*384/4"), + H1REG(HEncMadCount , 0x098, 0xffff0000, 16, 0, RW, "Macroblock count with MAD value under threshold output"), + H1REG(HEncMbCount , 0x098, 0x0000ffff, 0, 0, RW, "MB count output. max 255*255"), +/* Stabilization parameters and outputs */ + H1REG(HEncBaseNextLum , 0x09c, 0xffffffff, 0, 0, RW, "Base address for next pic luminance"), + H1REG(HEncStabMode , 0x0a0, 0xc0000000, 30, 1, RW, "Stabilization mode. 0=disabled. 1=stab only. 2=stab+encode"), + H1REG(HEncStabMinimum , 0x0a0, 0x00ffffff, 0, 0, RW, "Stabilization minimum value output. max 253*253*255"), + H1REG(HEncStabMotionSum , 0x0a4, 0xffffffff, 0, 0, RW, "Stabilization motion sum div8 output. max 253*253*255*1089/8"), + H1REG(HEncStabGmvX , 0x0a8, 0xfc000000, 26, 0, RW, "Stabilization GMV horizontal output [-16..16]"), + H1REG(HEncStabMatrix1 , 0x0a8, 0x00ffffff, 0, 0, RW, "Stabilization matrix 1 (up-left position) output"), + H1REG(HEncStabGmvY , 0x0ac, 0xfc000000, 26, 0, RW, "Stabilization GMV vertical output [-16..16]"), + H1REG(HEncStabMatrix2 , 0x0ac, 0x00ffffff, 0, 0, RW, "Stabilization matrix 2 (up position) output"), + H1REG(HEncStabMatrix3 , 0x0b0, 0x00ffffff, 0, 0, RW, "Stabilization matrix 3 (up-right position) output"), + H1REG(HEncStabMatrix4 , 0x0b4, 0x00ffffff, 0, 0, RW, "Stabilization matrix 4 (left position) output"), + H1REG(HEncStabMatrix5 , 0x0b8, 0x00ffffff, 0, 0, RW, "Stabilization matrix 5 (GMV position) output"), + H1REG(HEncStabMatrix6 , 0x0bc, 0x00ffffff, 0, 0, RW, "Stabilization matrix 6 (right position) output"), + H1REG(HEncStabMatrix7 , 0x0c0, 0x00ffffff, 0, 0, RW, "Stabilization matrix 7 (down-left position) output"), + H1REG(HEncStabMatrix8 , 0x0c4, 0x00ffffff, 0, 0, RW, "Stabilization matrix 8 (down position) output"), + H1REG(HEncStabMatrix9 , 0x0c8, 0x00ffffff, 0, 0, RW, "Stabilization matrix 9 (down-right position) output"), + H1REG(HEncBaseCabacCtx , 0x0cc, 0xffffffff, 0, 0, RW, "Base address for cabac context tables (H264) or probability tables (VP8)"), + H1REG(HEncBaseMvWrite , 0x0d0, 0xffffffff, 0, 0, RW, "Base address for MV output writing"), +/* Pre-processor color conversion parameters */ + H1REG(HEncRGBCoeffA , 0x0d4, 0x0000ffff, 0, 0, RW, "RGB to YUV conversion coefficient A"), + H1REG(HEncRGBCoeffB , 0x0d4, 0xffff0000, 16, 0, RW, "RGB to YUV conversion coefficient B"), + H1REG(HEncRGBCoeffC , 0x0d8, 0x0000ffff, 0, 0, RW, "RGB to YUV conversion coefficient C"), + H1REG(HEncRGBCoeffE , 0x0d8, 0xffff0000, 16, 0, RW, "RGB to YUV conversion coefficient E"), + H1REG(HEncRGBCoeffF , 0x0dc, 0x0000ffff, 0, 0, RW, "RGB to YUV conversion coefficient F"), + H1REG(HEncRMaskMSB , 0x0dc, 0x001f0000, 16, 0, RW, "RGB R-component mask MSB bit position [0..31]"), + H1REG(HEncGMaskMSB , 0x0dc, 0x03e00000, 21, 0, RW, "RGB G-component mask MSB bit position [0..31]"), + H1REG(HEncBMaskMSB , 0x0dc, 0x7c000000, 26, 0, RW, "RGB B-component mask MSB bit position [0..31]"), + H1REG(HEncIntraAreaLeft , 0x0e0, 0xff000000, 24, 0, RW, "Intra area left mb column (inside area) [0..255]"), + H1REG(HEncIntraAreaRight , 0x0e0, 0x00ff0000, 16, 0, RW, "Intra area right mb column (outside area) [0..255]"), + H1REG(HEncIntraAreaTop , 0x0e0, 0x0000ff00, 8, 0, RW, "Intra area top mb row (inside area) [0..255]"), + H1REG(HEncIntraAreaBottom , 0x0e0, 0x000000ff, 0, 0, RW, "Intra area bottom mb row (outside area) [0..255]"), + H1REG(HEncCirStart , 0x0e4, 0xffff0000, 16, 0, RW, "CIR first intra mb. 0=disabled [0..65535]"), + H1REG(HEncCirInterval , 0x0e4, 0x0000ffff, 0, 0, RW, "CIR intra mb interval. 0=disabled [0..65535]"), + +/* H264 / VP8 mixed definitions */ + H1REG(HEncIntraSliceMap1 , 0x0e8, 0xffffffff, 0, 0, RW, "Intra slice bitmap for slices 0..31. LSB=slice0. MSB=slice31. 1=intra."), + H1REG(HEncIntraSliceMap2 , 0x0ec, 0xffffffff, 0, 0, RW, "Intra slice bitmap for slices 32..63. LSB=slice32. MSB=slice63. 1=intra."), + H1REG(HEncIntraSliceMap3 , 0x068, 0xffffffff, 0, 0, RW, "Intra slice bitmap for slices 64..95. LSB=slice64. MSB=slice95. 1=intra."), + H1REG(HEncBasePartition1 , 0x0e8, 0xffffffff, 0, 0, RW, "Base address for VP8 1st DCT partition"), + H1REG(HEncBasePartition2 , 0x0ec, 0xffffffff, 0, 0, RW, "Base address for VP8 2nd DCT partition"), + H1REG(HEncBaseVp8ProbCount , 0x068, 0xffffffff, 0, 0, RW, "Base address for VP8 counters for probability updates"), + + H1REG(HEncRoi1Left , 0x0f0, 0xff000000, 24, 0, RW, "1st ROI area left mb column (inside area) qp+=Roi1DeltaQp"), + H1REG(HEncRoi1Right , 0x0f0, 0x00ff0000, 16, 0, RW, "1st ROI area right mb column (outside area) qp-=Roi1DeltaQp"), + H1REG(HEncRoi1Top , 0x0f0, 0x0000ff00, 8, 0, RW, "1st ROI area top mb row (inside area)"), + H1REG(HEncRoi1Bottom , 0x0f0, 0x000000ff, 0, 0, RW, "1st ROI area bottom mb row (outside area)"), + H1REG(HEncRoi2Left , 0x0f4, 0xff000000, 24, 0, RW, "2nd ROI area left mb column (inside area) qp+=Roi2DeltaQp"), + H1REG(HEncRoi2Right , 0x0f4, 0x00ff0000, 16, 0, RW, "2nd ROI area right mb column (outside area) qp-=Roi2DeltaQp"), + H1REG(HEncRoi2Top , 0x0f4, 0x0000ff00, 8, 0, RW, "2nd ROI area top mb row (inside area)"), + H1REG(HEncRoi2Bottom , 0x0f4, 0x000000ff, 0, 0, RW, "2nd ROI area bottom mb row (outside area)"), + H1REG(HEncRoi1DeltaQp , 0x0f8, 0x000000f0, 4, 0, RW, "1st ROI area delta QP. qp = Qp - Roi1DeltaQp [0..15]"), + H1REG(HEncRoi2DeltaQp , 0x0f8, 0x0000000f, 0, 0, RW, "2nd ROI area delta QP. qp = Qp - Roi2DeltaQp [0..15]"), + H1REG(HEncZeroMvFavor , 0x0f8, 0xf0000000, 28, 0, RW, "Zero 16x16 MV favor div2."), + H1REG(HEncSplitPenalty4x4 , 0x0f8, 0x0ff80000, 19, 0, RW, "Penalty for using 4x4 MV."), + H1REG(HEncMvcPriorityId , 0x0f8, 0x00070000, 16, 0, RW, "MVC priority_id [0..7]"), + H1REG(HEncMvcViewId , 0x0f8, 0x0000e000, 13, 0, RW, "MVC view_id [0..7]"), + H1REG(HEncMvcTemporalId , 0x0f8, 0x00001c00, 10, 0, RW, "MVC temporal_id [0..7]"), + H1REG(HEncMvcAnchorPicFlag , 0x0f8, 0x00000200, 9, 0, RW, "MVC anchor_pic_flag. Specifies that the picture is part of an anchor access unit."), + H1REG(HEncMvcInterViewFlag , 0x0f8, 0x00000100, 8, 0, RW, "MVC inter_view_flag. Specifies that the picture is used for inter-view prediction."), + +/* HW synthesis config register, read-only */ + H1REG(HEncHWChSearchArea , 0x0fc, 0x80000000, 31, 0, RO, "HW Chrominance search area internal buffer. 0=not supported. 1=supported."), + H1REG(HEncHWScalingSupport , 0x0fc, 0x40000000, 30, 0, RO, "Down-scaling supported by HW. 0=not supported. 1=supported"), + H1REG(HEncHWSearchArea , 0x0fc, 0x20000000, 29, 0, RO, "HW search area height. 0=5 MB rows. 1=3 MB rows"), + H1REG(HEncHWRgbSupport , 0x0fc, 0x10000000, 28, 0, RO, "RGB to YUV conversion supported by HW. 0=not supported. 1=supported"), + H1REG(HEncHWH264Support , 0x0fc, 0x08000000, 27, 0, RO, "H.264 encoding supported by HW. 0=not supported. 1=supported"), + H1REG(HEncHWVp8Support , 0x0fc, 0x04000000, 26, 0, RO, "VP8 encoding supported by HW. 0=not supported. 1=supported"), + H1REG(HEncHWJpegSupport , 0x0fc, 0x02000000, 25, 0, RO, "JPEG encoding supported by HW. 0=not supported. 1=supported"), + H1REG(HEncHWStabSupport , 0x0fc, 0x01000000, 24, 0, RO, "Stabilization supported by HW. 0=not supported. 1=supported"), + H1REG(HEncHWBus , 0x0fc, 0x00f00000, 20, 0, RO, "Bus connection of HW. 1=AHB. 2=OCP. 3=AXI. 4=PCI. 5=AXIAHB. 6=AXIAPB."), + H1REG(HEncHWSynthesisLan , 0x0fc, 0x000f0000, 16, 0, RO, "Synthesis language. 1=vhdl. 2=verilog"), + H1REG(HEncHWBusWidth , 0x0fc, 0x0000f000, 12, 0, RO, "Bus width of HW. 0=32b. 1=64b. 2=128b"), + H1REG(HEncHWMaxVideoWidth , 0x0fc, 0x00000fff, 0, 0, RO, "Maximum video width supported by HW (pixels)"), + +/* JPEG / VP8 mixed definitions regs 0x100-0x17C */ + H1REG(HEncJpegQuantLuma1 , 0x100, 0xffffffff, 0, 0, RW, "JPEG luma quantization 1"), + H1REG(HEncJpegQuantLuma2 , 0x104, 0xffffffff, 0, 0, RW, "JPEG luma quantization 2"), + H1REG(HEncJpegQuantLuma3 , 0x108, 0xffffffff, 0, 0, RW, "JPEG luma quantization 3"), + H1REG(HEncJpegQuantLuma4 , 0x10c, 0xffffffff, 0, 0, RW, "JPEG luma quantization 4"), + H1REG(HEncJpegQuantLuma5 , 0x110, 0xffffffff, 0, 0, RW, "JPEG luma quantization 5"), + H1REG(HEncJpegQuantLuma6 , 0x114, 0xffffffff, 0, 0, RW, "JPEG luma quantization 6"), + H1REG(HEncJpegQuantLuma7 , 0x118, 0xffffffff, 0, 0, RW, "JPEG luma quantization 7"), + H1REG(HEncJpegQuantLuma8 , 0x11c, 0xffffffff, 0, 0, RW, "JPEG luma quantization 8"), + H1REG(HEncJpegQuantLuma9 , 0x120, 0xffffffff, 0, 0, RW, "JPEG luma quantization 9"), + H1REG(HEncJpegQuantLuma10 , 0x124, 0xffffffff, 0, 0, RW, "JPEG luma quantization 10"), + H1REG(HEncJpegQuantLuma11 , 0x128, 0xffffffff, 0, 0, RW, "JPEG luma quantization 11"), + H1REG(HEncJpegQuantLuma12 , 0x12c, 0xffffffff, 0, 0, RW, "JPEG luma quantization 12"), + H1REG(HEncJpegQuantLuma13 , 0x130, 0xffffffff, 0, 0, RW, "JPEG luma quantization 13"), + H1REG(HEncJpegQuantLuma14 , 0x134, 0xffffffff, 0, 0, RW, "JPEG luma quantization 14"), + H1REG(HEncJpegQuantLuma15 , 0x138, 0xffffffff, 0, 0, RW, "JPEG luma quantization 15"), + H1REG(HEncJpegQuantLuma16 , 0x13c, 0xffffffff, 0, 0, RW, "JPEG luma quantization 16"), + H1REG(HEncJpegQuantChroma1 , 0x140, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 1"), + H1REG(HEncJpegQuantChroma2 , 0x144, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 2"), + H1REG(HEncJpegQuantChroma3 , 0x148, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 3"), + H1REG(HEncJpegQuantChroma4 , 0x14c, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 4"), + H1REG(HEncJpegQuantChroma5 , 0x150, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 5"), + H1REG(HEncJpegQuantChroma6 , 0x154, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 6"), + H1REG(HEncJpegQuantChroma7 , 0x158, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 7"), + H1REG(HEncJpegQuantChroma8 , 0x15c, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 8"), + H1REG(HEncJpegQuantChroma9 , 0x160, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 9"), + H1REG(HEncJpegQuantChroma10, 0x164, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 10"), + H1REG(HEncJpegQuantChroma11, 0x168, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 11"), + H1REG(HEncJpegQuantChroma12, 0x16c, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 12"), + H1REG(HEncJpegQuantChroma13, 0x170, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 13"), + H1REG(HEncJpegQuantChroma14, 0x174, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 14"), + H1REG(HEncJpegQuantChroma15, 0x178, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 15"), + H1REG(HEncJpegQuantChroma16, 0x17C, 0xffffffff, 0, 0, RW, "JPEG chroma quantization 16"), + H1REG(HEncVp8Mode0Penalty , 0x100, 0x000003ff, 0, 0, RW, "VP8 intra 16x16 mode 0 penalty"), + H1REG(HEncVp8Mode1Penalty , 0x100, 0x003ff000, 12, 0, RW, "VP8 intra 16x16 mode 1 penalty"), + H1REG(HEncVp8Mode2Penalty , 0x104, 0x000003ff, 0, 0, RW, "VP8 intra 16x16 mode 2 penalty"), + H1REG(HEncVp8Mode3Penalty , 0x104, 0x003ff000, 12, 0, RW, "VP8 intra 16x16 mode 3 penalty"), + H1REG(HEncVp8Bmode0Penalty , 0x108, 0x000003ff, 0, 0, RW, "VP8 intra 4x4 mode 0 penalty"), + H1REG(HEncVp8Bmode1Penalty , 0x108, 0x003ff000, 12, 0, RW, "VP8 intra 4x4 mode 1 penalty"), + H1REG(HEncVp8Bmode2Penalty , 0x10C, 0x000003ff, 0, 0, RW, "VP8 intra 4x4 mode 2 penalty"), + H1REG(HEncVp8Bmode3Penalty , 0x10C, 0x003ff000, 12, 0, RW, "VP8 intra 4x4 mode 3 penalty"), + H1REG(HEncVp8Bmode4Penalty , 0x110, 0x000003ff, 0, 0, RW, "VP8 intra 4x4 mode 4 penalty"), + H1REG(HEncVp8Bmode5Penalty , 0x110, 0x003ff000, 12, 0, RW, "VP8 intra 4x4 mode 5 penalty"), + H1REG(HEncVp8Bmode6Penalty , 0x114, 0x000003ff, 0, 0, RW, "VP8 intra 4x4 mode 6 penalty"), + H1REG(HEncVp8Bmode7Penalty , 0x114, 0x003ff000, 12, 0, RW, "VP8 intra 4x4 mode 7 penalty"), + H1REG(HEncVp8Bmode8Penalty , 0x118, 0x000003ff, 0, 0, RW, "VP8 intra 4x4 mode 8 penalty"), + H1REG(HEncVp8Bmode9Penalty , 0x118, 0x003ff000, 12, 0, RW, "VP8 intra 4x4 mode 9 penalty"), + H1REG(HEncBaseVp8SegmentMap , 0x11C, 0xffffffff, 0, 0, RW, "Base address for VP8 segmentation map, segmentId 2-bits/macroblock"), + H1REG(HEncVp8Seg1Y1QuantDc , 0x120, 0x00003fff, 0, 1, RW, "VP8 segment1 qpY1QuantDc 14b"), + H1REG(HEncVp8Seg1Y1ZbinDc , 0x120, 0x007fc000, 14, 1, RW, "VP8 segment1 qpY1ZbinDc 9b"), + H1REG(HEncVp8Seg1Y1RoundDc , 0x120, 0x7f800000, 23, 1, RW, "VP8 segment1 qpY1RoundDc 8b"), + H1REG(HEncVp8Seg1Y1QuantAc , 0x124, 0x00003fff, 0, 1, RW, "VP8 segment1 qpY1QuantAc 14b"), + H1REG(HEncVp8Seg1Y1ZbinAc , 0x124, 0x007fc000, 14, 1, RW, "VP8 segment1 qpY1ZbinAc 9b"), + H1REG(HEncVp8Seg1Y1RoundAc , 0x124, 0x7f800000, 23, 1, RW, "VP8 segment1 qpY1RoundAc 8b"), + H1REG(HEncVp8Seg1Y2QuantDc , 0x128, 0x00003fff, 0, 1, RW, "VP8 segment1 qpY2QuantDc 14b"), + H1REG(HEncVp8Seg1Y2ZbinDc , 0x128, 0x007fc000, 14, 1, RW, "VP8 segment1 qpY2ZbinDc 9b"), + H1REG(HEncVp8Seg1Y2RoundDc , 0x128, 0x7f800000, 23, 1, RW, "VP8 segment1 qpY2RoundDc 8b"), + H1REG(HEncVp8Seg1Y2QuantAc , 0x12C, 0x00003fff, 0, 1, RW, "VP8 segment1 qpY2QuantAc 14b"), + H1REG(HEncVp8Seg1Y2ZbinAc , 0x12C, 0x007fc000, 14, 1, RW, "VP8 segment1 qpY2ZbinAc 9b"), + H1REG(HEncVp8Seg1Y2RoundAc , 0x12C, 0x7f800000, 23, 1, RW, "VP8 segment1 qpY2RoundAc 8b"), + H1REG(HEncVp8Seg1ChQuantDc , 0x130, 0x00003fff, 0, 1, RW, "VP8 segment1 qpChQuantDc 14b"), + H1REG(HEncVp8Seg1ChZbinDc , 0x130, 0x007fc000, 14, 1, RW, "VP8 segment1 qpChZbinDc 9b"), + H1REG(HEncVp8Seg1ChRoundDc , 0x130, 0x7f800000, 23, 1, RW, "VP8 segment1 qpChRoundDc 8b"), + H1REG(HEncVp8Seg1ChQuantAc , 0x134, 0x00003fff, 0, 1, RW, "VP8 segment1 qpChQuantAc 14b"), + H1REG(HEncVp8Seg1ChZbinAc , 0x134, 0x007fc000, 14, 1, RW, "VP8 segment1 qpChZbinAc 9b"), + H1REG(HEncVp8Seg1ChRoundAc , 0x134, 0x7f800000, 23, 1, RW, "VP8 segment1 qpChRoundAc 8b"), + H1REG(HEncVp8Seg1Y1DequantDc , 0x138, 0x000000ff, 0, 1, RW, "VP8 segment1 qpY1DequantDc 8b"), + H1REG(HEncVp8Seg1Y1DequantAc , 0x138, 0x0001ff00, 8, 1, RW, "VP8 segment1 qpY1DequantAc 9b"), + H1REG(HEncVp8Seg1Y2DequantDc , 0x138, 0x03fe0000, 17, 1, RW, "VP8 segment1 qpY2DequantDc 9b"), + H1REG(HEncVp8Seg1Y2DequantAc , 0x13C, 0x000001ff, 0, 1, RW, "VP8 segment1 qpY2DequantAc 9b"), + H1REG(HEncVp8Seg1ChDequantDc , 0x13C, 0x0001fe00, 9, 1, RW, "VP8 segment1 qpChDequantDc 8b"), + H1REG(HEncVp8Seg1ChDequantAc , 0x13C, 0x03fe0000, 17, 1, RW, "VP8 segment1 qpChDequantAc 9b"), + H1REG(HEncVp8Seg1FilterLevel , 0x13C, 0xfc000000, 26, 1, RW, "VP8 segment1 filter level 6b"), + H1REG(HEncVp8Seg2Y1QuantDc , 0x140, 0x00003fff, 0, 1, RW, "VP8 segment2 qpY1QuantDc 14b"), + H1REG(HEncVp8Seg2Y1ZbinDc , 0x140, 0x007fc000, 14, 1, RW, "VP8 segment2 qpY1ZbinDc 9b"), + H1REG(HEncVp8Seg2Y1RoundDc , 0x140, 0x7f800000, 23, 1, RW, "VP8 segment2 qpY1RoundDc 8b"), + H1REG(HEncVp8Seg2Y1QuantAc , 0x144, 0x00003fff, 0, 1, RW, "VP8 segment2 qpY1QuantAc 14b"), + H1REG(HEncVp8Seg2Y1ZbinAc , 0x144, 0x007fc000, 14, 1, RW, "VP8 segment2 qpY1ZbinAc 9b"), + H1REG(HEncVp8Seg2Y1RoundAc , 0x144, 0x7f800000, 23, 1, RW, "VP8 segment2 qpY1RoundAc 8b"), + H1REG(HEncVp8Seg2Y2QuantDc , 0x148, 0x00003fff, 0, 1, RW, "VP8 segment2 qpY2QuantDc 14b"), + H1REG(HEncVp8Seg2Y2ZbinDc , 0x148, 0x007fc000, 14, 1, RW, "VP8 segment2 qpY2ZbinDc 9b"), + H1REG(HEncVp8Seg2Y2RoundDc , 0x148, 0x7f800000, 23, 1, RW, "VP8 segment2 qpY2RoundDc 8b"), + H1REG(HEncVp8Seg2Y2QuantAc , 0x14C, 0x00003fff, 0, 1, RW, "VP8 segment2 qpY2QuantAc 14b"), + H1REG(HEncVp8Seg2Y2ZbinAc , 0x14C, 0x007fc000, 14, 1, RW, "VP8 segment2 qpY2ZbinAc 9b"), + H1REG(HEncVp8Seg2Y2RoundAc , 0x14C, 0x7f800000, 23, 1, RW, "VP8 segment2 qpY2RoundAc 8b"), + H1REG(HEncVp8Seg2ChQuantDc , 0x150, 0x00003fff, 0, 1, RW, "VP8 segment2 qpChQuantDc 14b"), + H1REG(HEncVp8Seg2ChZbinDc , 0x150, 0x007fc000, 14, 1, RW, "VP8 segment2 qpChZbinDc 9b"), + H1REG(HEncVp8Seg2ChRoundDc , 0x150, 0x7f800000, 23, 1, RW, "VP8 segment2 qpChRoundDc 8b"), + H1REG(HEncVp8Seg2ChQuantAc , 0x154, 0x00003fff, 0, 1, RW, "VP8 segment2 qpChQuantAc 14b"), + H1REG(HEncVp8Seg2ChZbinAc , 0x154, 0x007fc000, 14, 1, RW, "VP8 segment2 qpChZbinAc 9b"), + H1REG(HEncVp8Seg2ChRoundAc , 0x154, 0x7f800000, 23, 1, RW, "VP8 segment2 qpChRoundAc 8b"), + H1REG(HEncVp8Seg2Y1DequantDc , 0x158, 0x000000ff, 0, 1, RW, "VP8 segment2 qpY1DequantDc 8b"), + H1REG(HEncVp8Seg2Y1DequantAc , 0x158, 0x0001ff00, 8, 1, RW, "VP8 segment2 qpY1DequantAc 9b"), + H1REG(HEncVp8Seg2Y2DequantDc , 0x158, 0x03fe0000, 17, 1, RW, "VP8 segment2 qpY2DequantDc 9b"), + H1REG(HEncVp8Seg2Y2DequantAc , 0x15C, 0x000001ff, 0, 1, RW, "VP8 segment2 qpY2DequantAc 9b"), + H1REG(HEncVp8Seg2ChDequantDc , 0x15C, 0x0001fe00, 9, 1, RW, "VP8 segment2 qpChDequantDc 8b"), + H1REG(HEncVp8Seg2ChDequantAc , 0x15C, 0x03fe0000, 17, 1, RW, "VP8 segment2 qpChDequantAc 9b"), + H1REG(HEncVp8Seg2FilterLevel , 0x15C, 0xfc000000, 26, 1, RW, "VP8 segment2 filter level 6b"), + H1REG(HEncVp8Seg3Y1QuantDc , 0x160, 0x00003fff, 0, 1, RW, "VP8 segment3 qpY1QuantDc 14b"), + H1REG(HEncVp8Seg3Y1ZbinDc , 0x160, 0x007fc000, 14, 1, RW, "VP8 segment3 qpY1ZbinDc 9b"), + H1REG(HEncVp8Seg3Y1RoundDc , 0x160, 0x7f800000, 23, 1, RW, "VP8 segment3 qpY1RoundDc 8b"), + H1REG(HEncVp8Seg3Y1QuantAc , 0x164, 0x00003fff, 0, 1, RW, "VP8 segment3 qpY1QuantAc 14b"), + H1REG(HEncVp8Seg3Y1ZbinAc , 0x164, 0x007fc000, 14, 1, RW, "VP8 segment3 qpY1ZbinAc 9b"), + H1REG(HEncVp8Seg3Y1RoundAc , 0x164, 0x7f800000, 23, 1, RW, "VP8 segment3 qpY1RoundAc 8b"), + H1REG(HEncVp8Seg3Y2QuantDc , 0x168, 0x00003fff, 0, 1, RW, "VP8 segment3 qpY2QuantDc 14b"), + H1REG(HEncVp8Seg3Y2ZbinDc , 0x168, 0x007fc000, 14, 1, RW, "VP8 segment3 qpY2ZbinDc 9b"), + H1REG(HEncVp8Seg3Y2RoundDc , 0x168, 0x7f800000, 23, 1, RW, "VP8 segment3 qpY2RoundDc 8b"), + H1REG(HEncVp8Seg3Y2QuantAc , 0x16C, 0x00003fff, 0, 1, RW, "VP8 segment3 qpY2QuantAc 14b"), + H1REG(HEncVp8Seg3Y2ZbinAc , 0x16C, 0x007fc000, 14, 1, RW, "VP8 segment3 qpY2ZbinAc 9b"), + H1REG(HEncVp8Seg3Y2RoundAc , 0x16C, 0x7f800000, 23, 1, RW, "VP8 segment3 qpY2RoundAc 8b"), + H1REG(HEncVp8Seg3ChQuantDc , 0x170, 0x00003fff, 0, 1, RW, "VP8 segment3 qpChQuantDc 14b"), + H1REG(HEncVp8Seg3ChZbinDc , 0x170, 0x007fc000, 14, 1, RW, "VP8 segment3 qpChZbinDc 9b"), + H1REG(HEncVp8Seg3ChRoundDc , 0x170, 0x7f800000, 23, 1, RW, "VP8 segment3 qpChRoundDc 8b"), + H1REG(HEncVp8Seg3ChQuantAc , 0x174, 0x00003fff, 0, 1, RW, "VP8 segment3 qpChQuantAc 14b"), + H1REG(HEncVp8Seg3ChZbinAc , 0x174, 0x007fc000, 14, 1, RW, "VP8 segment3 qpChZbinAc 9b"), + H1REG(HEncVp8Seg3ChRoundAc , 0x174, 0x7f800000, 23, 1, RW, "VP8 segment3 qpChRoundAc 8b"), + H1REG(HEncVp8Seg3Y1DequantDc , 0x178, 0x000000ff, 0, 1, RW, "VP8 segment3 qpY1DequantDc 8b"), + H1REG(HEncVp8Seg3Y1DequantAc , 0x178, 0x0001ff00, 8, 1, RW, "VP8 segment3 qpY1DequantAc 9b"), + H1REG(HEncVp8Seg3Y2DequantDc , 0x178, 0x03fe0000, 17, 1, RW, "VP8 segment3 qpY2DequantDc 9b"), + H1REG(HEncVp8Seg3Y2DequantAc , 0x17C, 0x000001ff, 0, 1, RW, "VP8 segment3 qpY2DequantAc 9b"), + H1REG(HEncVp8Seg3ChDequantDc , 0x17C, 0x0001fe00, 9, 1, RW, "VP8 segment3 qpChDequantDc 8b"), + H1REG(HEncVp8Seg3ChDequantAc , 0x17C, 0x03fe0000, 17, 1, RW, "VP8 segment3 qpChDequantAc 9b"), + H1REG(HEncVp8Seg3FilterLevel , 0x17C, 0xfc000000, 26, 1, RW, "VP8 segment3 filter level 6b"), + + H1REG(HEncDmvPenalty1 , 0x180, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values 0-3"), + H1REG(HEncDmvPenalty2 , 0x184, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values 4-7"), + H1REG(HEncDmvPenalty3 , 0x188, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty4 , 0x18C, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty5 , 0x190, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty6 , 0x194, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty7 , 0x198, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty8 , 0x19C, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty9 , 0x1A0, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty10 , 0x1A4, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty11 , 0x1A8, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty12 , 0x1AC, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty13 , 0x1B0, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty14 , 0x1B4, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty15 , 0x1B8, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty16 , 0x1BC, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty17 , 0x1C0, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty18 , 0x1C4, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty19 , 0x1C8, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty20 , 0x1CC, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty21 , 0x1D0, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty22 , 0x1D4, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty23 , 0x1D8, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty24 , 0x1DC, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty25 , 0x1E0, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty26 , 0x1E4, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty27 , 0x1E8, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty28 , 0x1EC, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty29 , 0x1F0, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty30 , 0x1F4, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty31 , 0x1F8, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values"), + H1REG(HEncDmvPenalty32 , 0x1FC, 0xffffffff, 0, 0, WO, "DMV 4p/1p penalty values 124-127"), + + H1REG(HEncDmvQpelPenalty1 , 0x200, 0xffffffff, 0, 0, WO, "DMV qpel penalty values 0-3"), + H1REG(HEncDmvQpelPenalty2 , 0x204, 0xffffffff, 0, 0, WO, "DMV qpel penalty values 4-7"), + H1REG(HEncDmvQpelPenalty3 , 0x208, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty4 , 0x20C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty5 , 0x210, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty6 , 0x214, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty7 , 0x218, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty8 , 0x21C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty9 , 0x220, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty10 , 0x224, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty11 , 0x228, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty12 , 0x22C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty13 , 0x230, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty14 , 0x234, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty15 , 0x238, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty16 , 0x23C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty17 , 0x240, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty18 , 0x244, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty19 , 0x248, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty20 , 0x24C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty21 , 0x250, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty22 , 0x254, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty23 , 0x258, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty24 , 0x25C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty25 , 0x260, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty26 , 0x264, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty27 , 0x268, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty28 , 0x26C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty29 , 0x270, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty30 , 0x274, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty31 , 0x278, 0xffffffff, 0, 0, WO, "DMV qpel penalty values"), + H1REG(HEncDmvQpelPenalty32 , 0x27C, 0xffffffff, 0, 0, WO, "DMV qpel penalty values 124-127"), + + H1REG(HEncVp8CostInter , 0x280, 0x00000fff, 0, 1, RW, "VP8 bit cost of inter type"), + H1REG(HEncVp8DmvCostConst , 0x280, 0x00fff000, 12, 1, RW, "VP8 coeff for dmv penalty for intra/inter selection"), + H1REG(HEncSplitZeroPenalty , 0x280, 0xff000000, 24, 1, RW, "Penalty for using zero-MV in 16x8/8x16/8x8 split"), + H1REG(HEncVp8CostGoldenRef , 0x284, 0x00000fff, 0, 1, RW, "VP8 bit cost of golden ref frame (not used)"), + + H1REG(HEncVp8LfRefDelta0 , 0x288, 0x0000007f, 0, 1, RW, "VP8 loop filter delta for intra mb"), + H1REG(HEncVp8LfRefDelta1 , 0x288, 0x00003f80, 7, 1, RW, "VP8 loop filter delta for last ref"), + H1REG(HEncVp8LfRefDelta2 , 0x288, 0x001fc000, 14, 1, RW, "VP8 loop filter delta for golden ref"), + H1REG(HEncVp8LfRefDelta3 , 0x288, 0x0fe00000, 21, 1, RW, "VP8 loop filter delta for alt ref"), + H1REG(HEncVp8LfModeDelta0 , 0x28C, 0x0000007f, 0, 1, RW, "VP8 loop filter delta for BPRED"), + H1REG(HEncVp8LfModeDelta1 , 0x28C, 0x00003f80, 7, 1, RW, "VP8 loop filter delta for ZEROMV"), + H1REG(HEncVp8LfModeDelta2 , 0x28C, 0x001fc000, 14, 1, RW, "VP8 loop filter delta for NEWMV"), + H1REG(HEncVp8LfModeDelta3 , 0x28C, 0x0fe00000, 21, 1, RW, "VP8 loop filter delta for SPLITMV"), + + H1REG(HEncVp8DzCoeffRate0 , 0x290, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate1 , 0x294, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate2 , 0x298, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate3 , 0x29C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate4 , 0x2A0, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate5 , 0x2A4, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate6 , 0x2A8, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate7 , 0x2AC, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate8 , 0x2B0, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate9 , 0x2B4, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate10 , 0x2B8, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate11 , 0x2BC, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate12 , 0x2C0, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate13 , 0x2C4, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate14 , 0x2C8, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate15 , 0x2CC, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate16 , 0x2D0, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate17 , 0x2D4, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate18 , 0x2D8, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate19 , 0x2DC, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate20 , 0x2E0, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate21 , 0x2E4, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate22 , 0x2E8, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate23 , 0x2EC, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate24 , 0x2F0, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate25 , 0x2F4, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate26 , 0x2F8, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate27 , 0x2FC, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate28 , 0x300, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate29 , 0x304, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate30 , 0x308, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate31 , 0x30C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate32 , 0x310, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate33 , 0x314, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate34 , 0x318, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate35 , 0x31C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate36 , 0x320, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate37 , 0x324, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate38 , 0x328, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate39 , 0x32C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate40 , 0x330, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate41 , 0x334, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate42 , 0x338, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate43 , 0x33C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate44 , 0x340, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate45 , 0x344, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate46 , 0x348, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzCoeffRate47 , 0x34C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + + H1REG(HEncVp8DzEobRate0 , 0x350, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate1 , 0x354, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate2 , 0x358, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate3 , 0x35C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate4 , 0x360, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate5 , 0x364, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate6 , 0x368, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate7 , 0x36C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate8 , 0x370, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate9 , 0x374, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate10 , 0x378, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate11 , 0x37C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate12 , 0x380, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate13 , 0x384, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate14 , 0x388, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + H1REG(HEncVp8DzEobRate15 , 0x38C, 0xffffffff, 0, 0, RW, "VP8 deadzone lookup table"), + + H1REG(HEncVp8DzRateM0 , 0x390, 0x3fff0000, 16, 0, RW, "VP8 deadzone rate multiplier for plane 0"), + H1REG(HEncVp8DzRateM1 , 0x390, 0x00003fff, 0, 0, RW, "VP8 deadzone rate multiplier for plane 1"), + H1REG(HEncVp8DzRateM2 , 0x394, 0x3fff0000, 16, 0, RW, "VP8 deadzone rate multiplier for plane 2"), + H1REG(HEncVp8DzRateM3 , 0x394, 0x00003fff, 0, 0, RW, "VP8 deadzone rate multiplier for plane 3"), + + H1REG(HEncVp8DzSkipRate0 , 0x398, 0x003ff000, 12, 0, RW, "VP8 deadzone rate for macroblock skip token 0"), + H1REG(HEncVp8DzSkipRate1 , 0x398, 0x000003ff, 0, 0, RW, "VP8 deadzone rate for macroblock skip token 1"), + + H1REG(HEncBaseScaledOutLum , 0x39C, 0xffffffff, 0, 0, RW, "Base address for output of down-scaled encoder image in YUYV 4:2:2 format"), + H1REG(HEncScaleMode , 0x3A0, 0xc0000000, 30, 1, RW, "Scaling mode. ScalingMode. 0=disabled. 1=scaling only. 2=scale+encode"), + H1REG(HEncScaledOutWidth , 0x3A0, 0x1ffe0000, 17, 1, RW, "Scaling width of down-scaled image. ScaledWidth. [96..4076]"), + H1REG(HEncScaledOutWidthRatio , 0x3A0, 0x0001ffff, 0, 0, RW, "Scaling ratio for width of down-scaled image. Fixed point integer 1.16."), + H1REG(HEncScaledOutHeight , 0x3A4, 0x1ffe0000, 17, 1, RW, "Scaling width of down-scaled image. ScaledHeight. [2..4078]"), + H1REG(HEncScaledOutHeightRatio, 0x3A4, 0x0001ffff, 0, 0, RW, "Scaling ratio for height of down-scaled image. Fixed point integer 1.16."), + + H1REG(HEncSquaredError , 0x3B0, 0xffffffff, 0, 0, RW, "Squared error output calculated for 13x13 pixels per macroblock. 32-bit max"), + + H1REG(HEncMadThreshold2 , 0x3B4, 0x3f000000, 24, 0, RW, "MAD threshold div256. MadThreshold2 < MadThreshold"), + H1REG(HEncMadQpDelta2 , 0x3B4, 0x00ff0000, 16, 0, RW, "MAD based QP adjustment. madQpChange [-127..127]"), + H1REG(HEncMadCount2 , 0x3B4, 0x0000ffff, 0, 0, RW, "Macroblock count with MAD value under threshold output"), + + H1REG(HEncMadThreshold3 , 0x3B8, 0x3f000000, 24, 0, RW, "MAD threshold div256. MadThreshold3 < MadThreshold2"), + H1REG(HEncMadQpDelta3 , 0x3B8, 0x00ff0000, 16, 0, RW, "MAD based QP adjustment. madQpChange [-127..127]"), + H1REG(HEncMadCount3 , 0x3B8, 0x0000ffff, 0, 0, RW, "Macroblock count with MAD value under threshold output"), + + H1REG(HEncVp8IpolCoeff01 , 0x3BC, 0xe0000000, 29, 0, RW, "VP8 predictor interpolation coefficient for full pixel position tap=1"), + H1REG(HEncVp8IpolCoeff02 , 0x3BC, 0x1f000000, 24, 0, RW, "VP8 predictor interpolation coefficient for full pixel position tap=2"), + H1REG(HEncVp8IpolCoeff03 , 0x3BC, 0x00ff0000, 16, 0, RW, "VP8 predictor interpolation coefficient for full pixel position tap=3"), + H1REG(HEncVp8IpolCoeff04 , 0x3BC, 0x0000ff00, 8, 0, RW, "VP8 predictor interpolation coefficient for full pixel position tap=4"), + H1REG(HEncVp8IpolCoeff05 , 0x3BC, 0x000000f8, 3, 0, RW, "VP8 predictor interpolation coefficient for full pixel position tap=5"), + H1REG(HEncVp8IpolCoeff06 , 0x3BC, 0x00000007, 0, 0, RW, "VP8 predictor interpolation coefficient for full pixel position tap=6"), + H1REG(HEncVp8IpolCoeff11 , 0x3C0, 0xe0000000, 29, 0, RW, "VP8 predictor interpolation coefficient for 1/8 pixel position tap=1"), + H1REG(HEncVp8IpolCoeff12 , 0x3C0, 0x1f000000, 24, 0, RW, "VP8 predictor interpolation coefficient for 1/8 pixel position tap=2"), + H1REG(HEncVp8IpolCoeff13 , 0x3C0, 0x00ff0000, 16, 0, RW, "VP8 predictor interpolation coefficient for 1/8 pixel position tap=3"), + H1REG(HEncVp8IpolCoeff14 , 0x3C0, 0x0000ff00, 8, 0, RW, "VP8 predictor interpolation coefficient for 1/8 pixel position tap=4"), + H1REG(HEncVp8IpolCoeff15 , 0x3C0, 0x000000f8, 3, 0, RW, "VP8 predictor interpolation coefficient for 1/8 pixel position tap=5"), + H1REG(HEncVp8IpolCoeff16 , 0x3C0, 0x00000007, 0, 0, RW, "VP8 predictor interpolation coefficient for 1/8 pixel position tap=6"), + H1REG(HEncVp8IpolCoeff21 , 0x3C4, 0xe0000000, 29, 0, RW, "VP8 predictor interpolation coefficient for 2/8 pixel position tap=1"), + H1REG(HEncVp8IpolCoeff22 , 0x3C4, 0x1f000000, 24, 0, RW, "VP8 predictor interpolation coefficient for 2/8 pixel position tap=2"), + H1REG(HEncVp8IpolCoeff23 , 0x3C4, 0x00ff0000, 16, 0, RW, "VP8 predictor interpolation coefficient for 2/8 pixel position tap=3"), + H1REG(HEncVp8IpolCoeff24 , 0x3C4, 0x0000ff00, 8, 0, RW, "VP8 predictor interpolation coefficient for 2/8 pixel position tap=4"), + H1REG(HEncVp8IpolCoeff25 , 0x3C4, 0x000000f8, 3, 0, RW, "VP8 predictor interpolation coefficient for 2/8 pixel position tap=5"), + H1REG(HEncVp8IpolCoeff26 , 0x3C4, 0x00000007, 0, 0, RW, "VP8 predictor interpolation coefficient for 2/8 pixel position tap=6"), + H1REG(HEncVp8IpolCoeff31 , 0x3C8, 0xe0000000, 29, 0, RW, "VP8 predictor interpolation coefficient for 3/8 pixel position tap=1"), + H1REG(HEncVp8IpolCoeff32 , 0x3C8, 0x1f000000, 24, 0, RW, "VP8 predictor interpolation coefficient for 3/8 pixel position tap=2"), + H1REG(HEncVp8IpolCoeff33 , 0x3C8, 0x00ff0000, 16, 0, RW, "VP8 predictor interpolation coefficient for 3/8 pixel position tap=3"), + H1REG(HEncVp8IpolCoeff34 , 0x3C8, 0x0000ff00, 8, 0, RW, "VP8 predictor interpolation coefficient for 3/8 pixel position tap=4"), + H1REG(HEncVp8IpolCoeff35 , 0x3C8, 0x000000f8, 3, 0, RW, "VP8 predictor interpolation coefficient for 3/8 pixel position tap=5"), + H1REG(HEncVp8IpolCoeff36 , 0x3C8, 0x00000007, 0, 0, RW, "VP8 predictor interpolation coefficient for 3/8 pixel position tap=6"), + H1REG(HEncVp8IpolCoeff41 , 0x3CC, 0xe0000000, 29, 0, RW, "VP8 predictor interpolation coefficient for 4/8 pixel position tap=1"), + H1REG(HEncVp8IpolCoeff42 , 0x3CC, 0x1f000000, 24, 0, RW, "VP8 predictor interpolation coefficient for 4/8 pixel position tap=2"), + H1REG(HEncVp8IpolCoeff43 , 0x3CC, 0x00ff0000, 16, 0, RW, "VP8 predictor interpolation coefficient for 4/8 pixel position tap=3"), + H1REG(HEncVp8IpolCoeff44 , 0x3CC, 0x0000ff00, 8, 0, RW, "VP8 predictor interpolation coefficient for 4/8 pixel position tap=4"), + H1REG(HEncVp8IpolCoeff45 , 0x3CC, 0x000000f8, 3, 0, RW, "VP8 predictor interpolation coefficient for 4/8 pixel position tap=5"), + H1REG(HEncVp8IpolCoeff46 , 0x3CC, 0x00000007, 0, 0, RW, "VP8 predictor interpolation coefficient for 4/8 pixel position tap=6"), + + H1REG(HEncBasePartition3 , 0x3D0, 0xffffffff, 0, 0, RW, "Base address for VP8 3rd DCT partition"), + H1REG(HEncBasePartition4 , 0x3D4, 0xffffffff, 0, 0, RW, "Base address for VP8 4th DCT partition"), + + H1REG(HEncSeg1I16Mode0Penalty , 0x400, 0x000003ff, 0, 0, RW, "Segment 1: Intra 16x16 mode 0 penalty"), + H1REG(HEncSeg1I16Mode1Penalty , 0x400, 0x000ffc00, 10, 0, RW, "Segment 1: Intra 16x16 mode 1 penalty"), + H1REG(HEncSeg1I16Mode2Penalty , 0x400, 0x3ff00000, 20, 0, RW, "Segment 1: Intra 16x16 mode 2 penalty"), + H1REG(HEncSeg1I16Mode3Penalty , 0x404, 0x000003ff, 0, 0, RW, "Segment 1: Intra 16x16 mode 3 penalty"), + H1REG(HEncSeg1I4Mode0Penalty , 0x404, 0x000ffc00, 10, 0, RW, "Segment 1: Intra 4x4 mode 0 penalty"), + H1REG(HEncSeg1I4Mode1Penalty , 0x404, 0x3ff00000, 20, 0, RW, "Segment 1: Intra 4x4 mode 1 penalty"), + H1REG(HEncSeg1I4Mode2Penalty , 0x408, 0x000003ff, 0, 0, RW, "Segment 1: Intra 4x4 mode 2 penalty"), + H1REG(HEncSeg1I4Mode3Penalty , 0x408, 0x000ffc00, 10, 0, RW, "Segment 1: Intra 4x4 mode 3 penalty"), + H1REG(HEncSeg1I4Mode4Penalty , 0x408, 0x3ff00000, 20, 0, RW, "Segment 1: Intra 4x4 mode 4 penalty"), + H1REG(HEncSeg1I4Mode5Penalty , 0x40C, 0x000003ff, 0, 0, RW, "Segment 1: Intra 4x4 mode 5 penalty"), + H1REG(HEncSeg1I4Mode6Penalty , 0x40C, 0x000ffc00, 10, 0, RW, "Segment 1: Intra 4x4 mode 6 penalty"), + H1REG(HEncSeg1I4Mode7Penalty , 0x40C, 0x3ff00000, 20, 0, RW, "Segment 1: Intra 4x4 mode 7 penalty"), + H1REG(HEncSeg1I4Mode8Penalty , 0x410, 0x000003ff, 0, 0, RW, "Segment 1: Intra 4x4 mode 8 penalty"), + H1REG(HEncSeg1I4Mode9Penalty , 0x410, 0x000ffc00, 10, 0, RW, "Segment 1: Intra 4x4 mode 9 penalty"), + H1REG(HEncSeg1I4PrevModeFavor , 0x410, 0x0ff00000, 20, 0, RW, "Segment 1: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg1CostInter , 0x414, 0x00000fff, 0, 0, RW, "Segment 1: Bit cost of inter type"), + H1REG(HEncSeg1I16Favor , 0x414, 0x0ffff000, 12, 0, RW, "Segment 1: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg1InterFavor , 0x418, 0x0000ffff, 0, 0, RW, "Segment 1: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg1SkipPenalty , 0x418, 0x00ff0000, 16, 0, RW, "Segment 1: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg1GoldenPenalty , 0x418, 0xff000000, 24, 0, RW, "Segment 1: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg1SplitPenalty8x4 , 0x41C, 0x000003ff, 0, 0, RW, "Segment 1: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg1SplitPenalty8x8 , 0x41C, 0x000ffc00, 10, 0, RW, "Segment 1: Penalty for using 8x8 MV."), + H1REG(HEncSeg1SplitPenalty16x8, 0x41C, 0x3ff00000, 20, 0, RW, "Segment 1: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg1SplitPenalty4x4 , 0x420, 0x000001ff, 0, 0, RW, "Segment 1: Penalty for using 4x4 MV."), + H1REG(HEncSeg1SplitZeroPenalty, 0x420, 0x000ffc00, 10, 0, RW, "Segment 1: Penalty for using zero-MV in 16x8/8x16/8x8 split"), + H1REG(HEncSeg1DMVPenaltyQp , 0x420, 0x3ff00000, 20, 0, RW, "Segment 1: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg1DzRateM0 , 0x424, 0x00003fff, 0, 0, RW, "Segment 1: Deadzone rate multiplier for plane 0"), + H1REG(HEncSeg1DzRateM1 , 0x424, 0x0fffc000, 14, 0, RW, "Segment 1: Deadzone rate multiplier for plane 1"), + H1REG(HEncSeg1DzRateM2 , 0x428, 0x00003fff, 0, 0, RW, "Segment 1: Deadzone rate multiplier for plane 2"), + H1REG(HEncSeg1DzRateM3 , 0x428, 0x0fffc000, 14, 0, RW, "Segment 1: Deadzone rate multiplier for plane 3"), + H1REG(HEncSeg1DzSkipRate0 , 0x42C, 0x000003ff, 0, 0, RW, "Segment 1: Deadzone rate for macroblock skip token 0"), + H1REG(HEncSeg1DzSkipRate1 , 0x42C, 0x000ffc00, 10, 0, RW, "Segment 1: Deadzone rate for macroblock skip token 1"), + H1REG(HEncSeg1DmvCostConst , 0x42C, 0xfff00000, 20, 0, RW, "Segment 1: Coeff for dmv penalty for intra/inter selection"), + + H1REG(HEncSeg2I16Mode0Penalty , 0x430, 0x000003ff, 0, 0, RW, "Segment 2: Intra 16x16 mode 0 penalty"), + H1REG(HEncSeg2I16Mode1Penalty , 0x430, 0x000ffc00, 10, 0, RW, "Segment 2: Intra 16x16 mode 1 penalty"), + H1REG(HEncSeg2I16Mode2Penalty , 0x430, 0x3ff00000, 20, 0, RW, "Segment 2: Intra 16x16 mode 2 penalty"), + H1REG(HEncSeg2I16Mode3Penalty , 0x434, 0x000003ff, 0, 0, RW, "Segment 2: Intra 16x16 mode 3 penalty"), + H1REG(HEncSeg2I4Mode0Penalty , 0x434, 0x000ffc00, 10, 0, RW, "Segment 2: Intra 4x4 mode 0 penalty"), + H1REG(HEncSeg2I4Mode1Penalty , 0x434, 0x3ff00000, 20, 0, RW, "Segment 2: Intra 4x4 mode 1 penalty"), + H1REG(HEncSeg2I4Mode2Penalty , 0x438, 0x000003ff, 0, 0, RW, "Segment 2: Intra 4x4 mode 2 penalty"), + H1REG(HEncSeg2I4Mode3Penalty , 0x438, 0x000ffc00, 10, 0, RW, "Segment 2: Intra 4x4 mode 3 penalty"), + H1REG(HEncSeg2I4Mode4Penalty , 0x438, 0x3ff00000, 20, 0, RW, "Segment 2: Intra 4x4 mode 4 penalty"), + H1REG(HEncSeg2I4Mode5Penalty , 0x43C, 0x000003ff, 0, 0, RW, "Segment 2: Intra 4x4 mode 5 penalty"), + H1REG(HEncSeg2I4Mode6Penalty , 0x43C, 0x000ffc00, 10, 0, RW, "Segment 2: Intra 4x4 mode 6 penalty"), + H1REG(HEncSeg2I4Mode7Penalty , 0x43C, 0x3ff00000, 20, 0, RW, "Segment 2: Intra 4x4 mode 7 penalty"), + H1REG(HEncSeg2I4Mode8Penalty , 0x440, 0x000003ff, 0, 0, RW, "Segment 2: Intra 4x4 mode 8 penalty"), + H1REG(HEncSeg2I4Mode9Penalty , 0x440, 0x000ffc00, 10, 0, RW, "Segment 2: Intra 4x4 mode 9 penalty"), + H1REG(HEncSeg2I4PrevModeFavor , 0x440, 0x0ff00000, 20, 0, RW, "Segment 2: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg2CostInter , 0x444, 0x00000fff, 0, 0, RW, "Segment 2: Bit cost of inter type"), + H1REG(HEncSeg2I16Favor , 0x444, 0x0ffff000, 12, 0, RW, "Segment 2: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg2InterFavor , 0x448, 0x0000ffff, 0, 0, RW, "Segment 2: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg2SkipPenalty , 0x448, 0x00ff0000, 16, 0, RW, "Segment 2: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg2GoldenPenalty , 0x448, 0xff000000, 24, 0, RW, "Segment 2: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg2SplitPenalty8x4 , 0x44C, 0x000003ff, 0, 0, RW, "Segment 2: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg2SplitPenalty8x8 , 0x44C, 0x000ffc00, 10, 0, RW, "Segment 2: Penalty for using 8x8 MV."), + H1REG(HEncSeg2SplitPenalty16x8, 0x44C, 0x3ff00000, 20, 0, RW, "Segment 2: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg2SplitPenalty4x4 , 0x450, 0x000001ff, 0, 0, RW, "Segment 2: Penalty for using 4x4 MV."), + H1REG(HEncSeg2SplitZeroPenalty, 0x450, 0x000ffc00, 10, 0, RW, "Segment 2: Penalty for using zero-MV in 16x8/8x16/8x8 split"), + H1REG(HEncSeg2DMVPenaltyQp , 0x450, 0x3ff00000, 20, 0, RW, "Segment 2: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg2DzRateM0 , 0x454, 0x00003fff, 0, 0, RW, "Segment 2: Deadzone rate multiplier for plane 0"), + H1REG(HEncSeg2DzRateM1 , 0x454, 0x0fffc000, 14, 0, RW, "Segment 2: Deadzone rate multiplier for plane 1"), + H1REG(HEncSeg2DzRateM2 , 0x458, 0x00003fff, 0, 0, RW, "Segment 2: Deadzone rate multiplier for plane 2"), + H1REG(HEncSeg2DzRateM3 , 0x458, 0x0fffc000, 14, 0, RW, "Segment 2: Deadzone rate multiplier for plane 3"), + H1REG(HEncSeg2DzSkipRate0 , 0x45C, 0x000003ff, 0, 0, RW, "Segment 2: Deadzone rate for macroblock skip token 0"), + H1REG(HEncSeg2DzSkipRate1 , 0x45C, 0x000ffc00, 10, 0, RW, "Segment 2: Deadzone rate for macroblock skip token 1"), + H1REG(HEncSeg2DmvCostConst , 0x45C, 0xfff00000, 20, 0, RW, "Segment 2: Coeff for dmv penalty for intra/inter selection"), + + H1REG(HEncSeg3I16Mode0Penalty , 0x460, 0x000003ff, 0, 0, RW, "Segment 3: Intra 16x16 mode 0 penalty"), + H1REG(HEncSeg3I16Mode1Penalty , 0x460, 0x000ffc00, 10, 0, RW, "Segment 3: Intra 16x16 mode 1 penalty"), + H1REG(HEncSeg3I16Mode2Penalty , 0x460, 0x3ff00000, 20, 0, RW, "Segment 3: Intra 16x16 mode 2 penalty"), + H1REG(HEncSeg3I16Mode3Penalty , 0x464, 0x000003ff, 0, 0, RW, "Segment 3: Intra 16x16 mode 3 penalty"), + H1REG(HEncSeg3I4Mode0Penalty , 0x464, 0x000ffc00, 10, 0, RW, "Segment 3: Intra 4x4 mode 0 penalty"), + H1REG(HEncSeg3I4Mode1Penalty , 0x464, 0x3ff00000, 20, 0, RW, "Segment 3: Intra 4x4 mode 1 penalty"), + H1REG(HEncSeg3I4Mode2Penalty , 0x468, 0x000003ff, 0, 0, RW, "Segment 3: Intra 4x4 mode 2 penalty"), + H1REG(HEncSeg3I4Mode3Penalty , 0x468, 0x000ffc00, 10, 0, RW, "Segment 3: Intra 4x4 mode 3 penalty"), + H1REG(HEncSeg3I4Mode4Penalty , 0x468, 0x3ff00000, 20, 0, RW, "Segment 3: Intra 4x4 mode 4 penalty"), + H1REG(HEncSeg3I4Mode5Penalty , 0x46C, 0x000003ff, 0, 0, RW, "Segment 3: Intra 4x4 mode 5 penalty"), + H1REG(HEncSeg3I4Mode6Penalty , 0x46C, 0x000ffc00, 10, 0, RW, "Segment 3: Intra 4x4 mode 6 penalty"), + H1REG(HEncSeg3I4Mode7Penalty , 0x46C, 0x3ff00000, 20, 0, RW, "Segment 3: Intra 4x4 mode 7 penalty"), + H1REG(HEncSeg3I4Mode8Penalty , 0x470, 0x000003ff, 0, 0, RW, "Segment 3: Intra 4x4 mode 8 penalty"), + H1REG(HEncSeg3I4Mode9Penalty , 0x470, 0x000ffc00, 10, 0, RW, "Segment 3: Intra 4x4 mode 9 penalty"), + H1REG(HEncSeg3I4PrevModeFavor , 0x470, 0x0ff00000, 20, 0, RW, "Segment 3: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg3CostInter , 0x474, 0x00000fff, 0, 0, RW, "Segment 3: Bit cost of inter type"), + H1REG(HEncSeg3I16Favor , 0x474, 0x0ffff000, 12, 0, RW, "Segment 3: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg3InterFavor , 0x478, 0x0000ffff, 0, 0, RW, "Segment 3: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg3SkipPenalty , 0x478, 0x00ff0000, 16, 0, RW, "Segment 3: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg3GoldenPenalty , 0x478, 0xff000000, 24, 0, RW, "Segment 3: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg3SplitPenalty8x4 , 0x47C, 0x000003ff, 0, 0, RW, "Segment 3: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg3SplitPenalty8x8 , 0x47C, 0x000ffc00, 10, 0, RW, "Segment 3: Penalty for using 8x8 MV."), + H1REG(HEncSeg3SplitPenalty16x8, 0x47C, 0x3ff00000, 20, 0, RW, "Segment 3: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg3SplitPenalty4x4 , 0x480, 0x000001ff, 0, 0, RW, "Segment 3: Penalty for using 4x4 MV."), + H1REG(HEncSeg3SplitZeroPenalty, 0x480, 0x000ffc00, 10, 0, RW, "Segment 3: Penalty for using zero-MV in 16x8/8x16/8x8 split"), + H1REG(HEncSeg3DMVPenaltyQp , 0x480, 0x3ff00000, 20, 0, RW, "Segment 3: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg3DzRateM0 , 0x484, 0x00003fff, 0, 0, RW, "Segment 3: Deadzone rate multiplier for plane 0"), + H1REG(HEncSeg3DzRateM1 , 0x484, 0x0fffc000, 14, 0, RW, "Segment 3: Deadzone rate multiplier for plane 1"), + H1REG(HEncSeg3DzRateM2 , 0x488, 0x00003fff, 0, 0, RW, "Segment 3: Deadzone rate multiplier for plane 2"), + H1REG(HEncSeg3DzRateM3 , 0x488, 0x0fffc000, 14, 0, RW, "Segment 3: Deadzone rate multiplier for plane 3"), + H1REG(HEncSeg3DzSkipRate0 , 0x48C, 0x000003ff, 0, 0, RW, "Segment 3: Deadzone rate for macroblock skip token 0"), + H1REG(HEncSeg3DzSkipRate1 , 0x48C, 0x000ffc00, 10, 0, RW, "Segment 3: Deadzone rate for macroblock skip token 1"), + H1REG(HEncSeg3DmvCostConst , 0x48C, 0xfff00000, 20, 0, RW, "Segment 3: Coeff for dmv penalty for intra/inter selection"), + H1REG(HEncVp8AvgVar , 0x490, 0xffffffff, 0, 0, RW, "VP8 average variance in prev frame"), + H1REG(HEncVp8InvAvgVar , 0x494, 0x0000ffff, 0, 0, RW, "VP8 16384/avgVar in prev frame"), + H1REG(HEncFieldPicFlag , 0x494, 0x00010000, 16, 0, RW, "H.264 FieldPicFlag. 0=frame 1=field"), + H1REG(HEncBottomFieldFlag , 0x494, 0x00020000, 17, 0, RW, "H.264 BottomFieldFlag. 0=top 1=bottom field"), + H1REG(HEncFieldParity , 0x494, 0x000c0000, 18, 0, RW, "H.264 Field parity conditions for chroma MV. 0=same parity 1=top/bottom 2=bottom/top"), + H1REG(HEncBoostQp , 0x498, 0x0000003f, 0, 0, RW, "Mb boost qp"), + H1REG(HEncBoostVar1 , 0x498, 0x0007ffc0, 6, 0, RW, "Mb boost variance1"), + H1REG(HEncBoostVar2 , 0x498, 0xfff80000, 19, 0, RW, "Mb boost variance2"), + + H1REG(HEncVarLimit , 0x49c, 0x0000000f, 0, 0, RW, "Variance limit"), + H1REG(HEncVarInterFavor , 0x49c, 0x000000f0, 4, 0, RW, "Variance interFavor"), + H1REG(HEncVarMultiplier , 0x49c, 0x00001f00, 8, 0, RW, "Variance multiplier"), + H1REG(HEncVarAdd , 0x49c, 0x0000e000, 13, 0, RW, "Variance add"), + H1REG(HEncPskipMode , 0x49c, 0x00010000, 16, 0, RW, "Pskip coding mode"), +#include "reg_table_v7.h" +}; + +#include "reg_offset_v7.h" + +#define ASIC_SWREG_AMOUNT (BASE_HEncRegisterMax/4) + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void EncAsicSetRegisterValue(u32 *regMirror, regName name, u32 value); +u32 EncAsicGetRegisterValue(const void *ewl, u32 *regMirror, regName name); +void EncAsicWriteRegisterValue(const void *ewl, u32 *regMirror, regName name, u32 value); + +#ifdef ADDRESS_WIDTH_64 + +#define SET_ADDR_REG(reg_base, name, value) do {\ + EncAsicSetRegisterValue((reg_base), name, (u32)(value)); \ + EncAsicSetRegisterValue((reg_base), name##_MSB, (u32)((value) >> 32)); \ + } while (0) + +#define GET_ADDR_REG(ewl, reg_base, name) \ + (((ptr_t)EncAsicGetRegisterValue((ewl), (reg_base), name)) | \ + (((ptr_t)EncAsicGetRegisterValue((ewl), (reg_base), name##_MSB)) << 32)) + +#else + +#define SET_ADDR_REG(reg_base, name, value) do {\ + EncAsicSetRegisterValue((reg_base), name, (u32)(value)); \ + } while (0) + +#define GET_ADDR_REG(ewl, reg_base, name) \ + ((ptr_t)EncAsicGetRegisterValue((ewl), (reg_base), (name))) + +#endif + +#endif diff --git a/lib/vc8000nanoe/inc/ewl.h b/lib/vc8000nanoe/inc/ewl.h new file mode 100644 index 000000000..c94115813 --- /dev/null +++ b/lib/vc8000nanoe/inc/ewl.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Hantro Encoder Wrapper Layer for OS services + * + ******************************************************************************** + */ + +#ifndef __EWL_H__ +#define __EWL_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "basetype.h" +/* Return values */ +#define EWL_OK 0 +#define EWL_ERROR -1 + +#define EWL_HW_WAIT_OK EWL_OK +#define EWL_HW_WAIT_ERROR EWL_ERROR +#define EWL_HW_WAIT_TIMEOUT 1 + +/* HW configuration values */ +#define EWL_HW_BUS_TYPE_UNKNOWN 0 +#define EWL_HW_BUS_TYPE_AHB 1 +#define EWL_HW_BUS_TYPE_OCP 2 +#define EWL_HW_BUS_TYPE_AXI 3 +#define EWL_HW_BUS_TYPE_PCI 4 + +#define EWL_HW_BUS_WIDTH_UNKNOWN 0 +#define EWL_HW_BUS_WIDTH_32BITS 1 +#define EWL_HW_BUS_WIDTH_64BITS 2 +#define EWL_HW_BUS_WIDTH_128BITS 3 + +#define EWL_HW_SYNTHESIS_LANGUAGE_UNKNOWN 0 +#define EWL_HW_SYNTHESIS_LANGUAGE_VHDL 1 +#define EWL_HW_SYNTHESIS_LANGUAGE_VERILOG 2 + +#define EWL_HW_CONFIG_NOT_SUPPORTED 0 +#define EWL_HW_CONFIG_ENABLED 1 + +#define ASIC_STATUS_RFC_BUFF_OVERFLOW 0x800U +#define ASIC_STATUS_LINE_BUFFER_DONE 0x400U +#define ASIC_STATUS_FUSE 0x200U +#define ASIC_STATUS_SLICE_READY 0x100U +#define ASIC_STATUS_HW_TIMEOUT 0x040U +#define ASIC_STATUS_BUFF_FULL 0x020U +#define ASIC_STATUS_HW_RESET 0x010U +#define ASIC_STATUS_ERROR 0x008U +#define ASIC_STATUS_FRAME_READY 0x004U +#define ASIC_IRQ_LINE 0x001U + +#define ASIC_STATUS_ALL (ASIC_STATUS_RFC_BUFF_OVERFLOW |\ + ASIC_STATUS_LINE_BUFFER_DONE |\ + ASIC_STATUS_FUSE |\ + ASIC_STATUS_SLICE_READY |\ + ASIC_STATUS_HW_TIMEOUT |\ + ASIC_STATUS_BUFF_FULL |\ + ASIC_STATUS_HW_RESET |\ + ASIC_STATUS_ERROR |\ + ASIC_STATUS_FRAME_READY) + +/* new added fuse 2 bitmap */ +#define HWCFGAddress64Bits 0x80000000U +#define HWCFGDnfSupport 0x40000000U +#define HWCFGRfcSupport 0x30000000U +#define HWCFGQEnhanceSupport 0x08000000U +#define HWCFGInstantSupport 0x04000000U +#define HWCFGSvctSupport 0x02000000U +#define HWCFGAxiIdInSupport 0x01000000U +#define HWCFGIrqClearSupport 0x00800000U +#define HWCFGInLoopbackSupport 0x00400000U + +/* Hardware configuration description */ + typedef struct EWLHwConfig + { + /* first part in reg 63 */ + u32 maxEncodedWidth; /* Maximum supported width for video encoding (not JPEG) */ + u32 h264Enabled; /* HW supports H.264 */ + u32 jpegEnabled; /* HW supports JPEG */ + u32 vp8Enabled; /* HW supports VP8 */ + u32 vsEnabled; /* HW supports video stabilization */ + u32 rgbEnabled; /* HW supports RGB input */ + u32 searchAreaSmall; /* HW search area reduced */ + u32 scalingEnabled; /* HW supports down-scaling */ + u32 busType; /* HW bus type in use */ + u32 busWidth; + u32 synthesisLanguage; + + /* second part in reg 296 */ + u32 addr64Support; /* HW supports 64bit bus address */ + u32 dnfSupport; /* HW supports Denoise filter */ + u32 enhanceSupport; /* HW supports quality enhancement */ + u32 rfcSupport; /* HW supports reference frame compression */ + u32 instantSupport; /* HW supports low latency control */ + u32 svctSupport; /* HW supports SVCT */ + u32 inAxiIdSupport; /* HW supports configurable AXI Read ID for Input picture */ + u32 irqEnhanceSupport; /* HW supports to clear irq by write-one */ + u32 inLoopbackSupport; /* HW support input buffer loopback. */ + } EWLHwConfig_t; + +/* Allocated linear memory area information */ + typedef struct EWLLinearMem + { + u32 *virtualAddress; + u32 size; + ptr_t busAddress; + } EWLLinearMem_t; + +/* EWLInitParam is used to pass parameters when initializing the EWL */ + typedef struct EWLInitParam + { + u32 clientType; + } EWLInitParam_t; + +#define EWL_CLIENT_TYPE_H264_ENC 1U +#define EWL_CLIENT_TYPE_VP8_ENC 2U +#define EWL_CLIENT_TYPE_JPEG_ENC 3U +#define EWL_CLIENT_TYPE_VIDEOSTAB 4U + +extern u32 (*pollInputLineBufTestFunc)(void); + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +/* Read and return the HW ID register value, static implementation */ + u32 EWLReadAsicID(void); + +/* Read and return HW configuration info, static implementation */ + EWLHwConfig_t EWLReadAsicConfig(void); + +/* Initialize the EWL instance + * Returns a wrapper instance or NULL for error + * EWLInit is called when the encoder instance is initialized */ + const void *EWLInit(EWLInitParam_t * param); + +/* Release the EWL instance + * Returns EWL_OK or EWL_ERROR + * EWLRelease is called when the encoder instance is released */ + i32 EWLRelease(const void *inst); + +/* Reserve the HW resource for one codec instance + * EWLReserveHw is called when beginning a frame encoding + * The function may block until the resource is available. + * Returns EWL_OK if the resource was successfully reserved for this instance + * or EWL_ERROR if unable to reserve the resource. */ + i32 EWLReserveHw(const void *inst); + +/* Release the HW resource + * EWLReleaseHw is called when the HW has finished the frame encoding. + * The codec SW will continue the frame encoding but the HW can + * be used by another codec.*/ + void EWLReleaseHw(const void *inst); + +/* Frame buffers memory */ + i32 EWLMallocRefFrm(const void *inst, u32 size, EWLLinearMem_t * info); + void EWLFreeRefFrm(const void *inst, EWLLinearMem_t * info); + +/* SW/HW shared memory */ + i32 EWLMallocLinear(const void *inst, u32 size, EWLLinearMem_t * info); + void EWLFreeLinear(const void *inst, EWLLinearMem_t * info); + + /* D-Cache coherence *//* Not in use currently */ + void EWLDCacheRangeFlush(const void *instance, EWLLinearMem_t * info); + void EWLDCacheRangeRefresh(const void *instance, EWLLinearMem_t * info); + +/* Write value to a HW register + * All registers are written at once at the beginning of frame encoding + * Offset is relative to the the HW ID register (#0) in bytes + * Enable indicates when the HW is enabled. If shadow registers are used then + * they must be flushed to the HW registers when enable is '1' before + * writing the register that enables the HW */ + void EWLWriteReg(const void *inst, u32 offset, u32 val); + +/* Read and return the value of a HW register + * The status register is read after every macroblock encoding by SW + * The other registers which may be updated by the HW are read after + * BUFFER_FULL or FRAME_READY interrupt + * Offset is relative to the the HW ID register (#0) in bytes */ + u32 EWLReadReg(const void *inst, u32 offset); + + /* Writing all registers in one call *//*Not in use currently */ + void EWLWriteRegAll(const void *inst, const u32 * table, u32 size); + /* Reading all registers in one call *//*Not in use currently */ + void EWLReadRegAll(const void *inst, u32 * table, u32 size); + +/* HW enable/disable. This will write to register and by */ +/* this enablig/disabling the hardware. */ + void EWLEnableHW(const void *inst, u32 offset, u32 val); + void EWLDisableHW(const void *inst, u32 offset, u32 val); + +/* Synchronize SW with HW + * Returns EWL_HW_WAIT_OK, EWL_HW_WAIT_ERROR or EWL_HW_WAIT_TIMEOUT + * EWLWaitHwRdy is called after enabling the HW to wait for IRQ from HW. + * If slicesReady pointer is given, at input it should contain the number + * of slicesReady received. The function will return when the HW has finished + * encoding next slice. Upon return the slicesReady pointer will contain + * the number of slices that are ready and available in the HW output buffer. + */ + i32 EWLWaitHwRdy(const void *inst, u32 *slicesReady); + +/* SW/SW shared memory handling */ + void *EWLmalloc(u32 n); + void *EWLcalloc(u32 n, u32 s); + void EWLfree(void *p); + void *EWLmemcpy(void *d, const void *s, u32 n); + void *EWLmemset(void *d, i32 c, u32 n); + int EWLmemcmp(const void *s1, const void *s2, u32 n); + +/* Get the base address of on-chip sram used for input MB line buffer. */ +i32 EWLGetInputLineBufferBase(const void *instance, EWLLinearMem_t * info); + +#ifdef __cplusplus +} +#endif +#endif /*__EWL_H__*/ diff --git a/lib/vc8000nanoe/inc/h264encapi.h b/lib/vc8000nanoe/inc/h264encapi.h new file mode 100644 index 000000000..3da9fb169 --- /dev/null +++ b/lib/vc8000nanoe/inc/h264encapi.h @@ -0,0 +1,615 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Hantro H1 H.264 Encoder API + * + ******************************************************************************** + */ + +#ifndef __H264ENCAPI_H__ +#define __H264ENCAPI_H__ + +#include "basetype.h" +#include "enccommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \mainpage Introduction + * This document presents the Application Programming Interface (API) of the Hantro VC8000NanoE + * H.264 hardware based encoder. The encoder is able to encode H.264 standard [1] baseline, main + * or high profile video streams. + * + * The encoder conforms to the H.264 Baseline, Main and High profiles and can encode streams up + * to a maximum picture size of 4080x4080. The maximum bitrate and frame rate depends on the + * number of HW cores, core clock frequency and the DRAM latency. + * + * This document assumes that the reader understands the fundamentals of C-language and the + * H.264 standard. + */ + +/*------------------------------------------------------------------------------ + 1. Type definition for encoder instance +------------------------------------------------------------------------------*/ + + typedef const void *H264EncInst; + +/*------------------------------------------------------------------------------ + 2. Enumerations for API parameters +------------------------------------------------------------------------------*/ + +/** Function return values */ + typedef enum + { + H264ENC_OK = 0, + H264ENC_FRAME_READY = 1, + + H264ENC_ERROR = -1, + H264ENC_NULL_ARGUMENT = -2, + H264ENC_INVALID_ARGUMENT = -3, + H264ENC_MEMORY_ERROR = -4, + H264ENC_EWL_ERROR = -5, + H264ENC_EWL_MEMORY_ERROR = -6, + H264ENC_INVALID_STATUS = -7, + H264ENC_OUTPUT_BUFFER_OVERFLOW = -8, + H264ENC_HW_BUS_ERROR = -9, + H264ENC_HW_DATA_ERROR = -10, + H264ENC_HW_TIMEOUT = -11, + H264ENC_HW_RESERVED = -12, + H264ENC_SYSTEM_ERROR = -13, + H264ENC_INSTANCE_ERROR = -14, + H264ENC_HRD_ERROR = -15, + H264ENC_HW_RESET = -16, + H264ENC_FUSE_ERROR = -17, + } H264EncRet; + +/* Stream type for initialization */ + typedef enum + { + H264ENC_BYTE_STREAM = 0, /**< H.264 annex B: NAL unit starts with + * hex bytes '00 00 00 01' */ + H264ENC_NAL_UNIT_STREAM = 1 /**< Plain NAL units without startcode */ + } H264EncStreamType; + +/** Stream view mode and buffer requirement for initialization */ + typedef enum + { + H264ENC_BASE_VIEW_DOUBLE_BUFFER = 0, /**< H.264 stream using + two reference frame buffers */ + H264ENC_BASE_VIEW_SINGLE_BUFFER = 1, /**< H.264 stream using + one reference frame buffers, + HRD frame discard not possible */ + H264ENC_MVC_STEREO_INTER_VIEW_PRED = 2, /**< H.264 MVC Stereo stream using + one reference frame buffer, + no HRD frame discard, + second view is always + inter-view predicted */ + H264ENC_MVC_STEREO_INTER_PRED = 3, /**< H.264 MVC Stereo stream using + two reference frame buffers, + no HRD frame discard, + second view can be inter + predicted */ + H264ENC_BASE_VIEW_MULTI_BUFFER = 4, /**< H.264 stream using + two or more reference frame buffers */ + H264ENC_INTERLACED_FIELD = 5, /**< H.264 stream coded as fields + of interlaced video */ + } H264EncViewMode; + +/** Level for initialization */ + typedef enum + { + H264ENC_LEVEL_1 = 10, + H264ENC_LEVEL_1_b = 99, + H264ENC_LEVEL_1_1 = 11, + H264ENC_LEVEL_1_2 = 12, + H264ENC_LEVEL_1_3 = 13, + H264ENC_LEVEL_2 = 20, + H264ENC_LEVEL_2_1 = 21, + H264ENC_LEVEL_2_2 = 22, + H264ENC_LEVEL_3 = 30, + H264ENC_LEVEL_3_1 = 31, + H264ENC_LEVEL_3_2 = 32, + H264ENC_LEVEL_4 = 40, + H264ENC_LEVEL_4_1 = 41, + H264ENC_LEVEL_4_2 = 42, + H264ENC_LEVEL_5 = 50, + H264ENC_LEVEL_5_1 = 51 + } H264EncLevel; + +/** Picture YUV type for initialization */ + typedef enum + { + H264ENC_YUV420_PLANAR = 0, /**< YYYY... UUUU... VVVV... */ + H264ENC_YUV420_SEMIPLANAR, /**< YYYY... UVUVUV... */ + H264ENC_YUV420_SEMIPLANAR_VU, /**< YYYY... VUVUVU... */ + H264ENC_YUV422_INTERLEAVED_YUYV, /**< YUYVYUYV... */ + H264ENC_YUV422_INTERLEAVED_UYVY, /**< UYVYUYVY... */ + H264ENC_RGB565, /**< 16-bit RGB 16bpp */ + H264ENC_BGR565, /**< 16-bit RGB 16bpp */ + H264ENC_RGB555, /**< 15-bit RGB 16bpp */ + H264ENC_BGR555, /**< 15-bit RGB 16bpp */ + H264ENC_RGB444, /**< 12-bit RGB 16bpp */ + H264ENC_BGR444, /**< 12-bit RGB 16bpp */ + H264ENC_RGB888, /**< 24-bit RGB 32bpp */ + H264ENC_BGR888, /**< 24-bit RGB 32bpp */ + H264ENC_RGB101010, /**< 30-bit RGB 32bpp */ + H264ENC_BGR101010, /**< 30-bit RGB 32bpp */ + H264ENC_SP_101010, /**< yuv420 10bit, semi-planar */ + H264ENC_P010 /**< yuv420 10bit, planar */ + } H264EncPictureType; + +/** Picture rotation for pre-processing */ + typedef enum + { + H264ENC_ROTATE_0 = 0, + H264ENC_ROTATE_90R = 1, /**< Rotate 90 degrees clockwise */ + H264ENC_ROTATE_90L = 2, /**< Rotate 90 degrees counter-clockwise */ + H264ENC_ROTATE_180R = 3 /**< Rotate 180 degrees clockwise */ + } H264EncPictureRotation; + +/** Picture color space conversion (RGB input) for pre-processing */ + typedef enum + { + H264ENC_RGBTOYUV_BT601 = 0, /**< Color conversion according to BT.601 */ + H264ENC_RGBTOYUV_BT709 = 1, /**< Color conversion according to BT.709 */ + H264ENC_RGBTOYUV_USER_DEFINED = 2 /**< User defined color conversion */ + } H264EncColorConversionType; + +/** Picture type for encoding */ + typedef enum + { + H264ENC_INTRA_FRAME = 0, /**< IDR-frame or field */ + H264ENC_PREDICTED_FRAME = 1, /**< P-frame or field */ + H264ENC_NONIDR_INTRA_FRAME = 2, /**< Non-IDR I-frame or field */ + H264ENC_NOTCODED_FRAME /**< Used just as a return value */ + } H264EncPictureCodingType; + +/** Reference picture mode for reading and writing */ + typedef enum + { + H264ENC_NO_REFERENCE_NO_REFRESH = 0, + H264ENC_REFERENCE = 1, + H264ENC_REFRESH = 2, + H264ENC_REFERENCE_AND_REFRESH = 3 + } H264EncRefPictureMode; + +/*------------------------------------------------------------------------------ + 3. Structures for API function parameters +------------------------------------------------------------------------------*/ + +/** + * Configuration info for initialization + * + * Width and height are picture dimensions after rotation + * Width and height are restricted by level limitations + * Stream Profile will be automatically decided based on parameters: + * - CABAC -> Main/High Profile, + * - 8x8-transform -> High Profile, + * - MVC -> Stereo High Profile + */ + typedef struct + { + H264EncStreamType streamType; /**< Byte stream / Plain NAL units */ + H264EncViewMode viewMode; /**< Mode of stream to be generated and + the corresponding amount of encoder + internal frame buffers required */ + H264EncLevel level; + u32 width; /**< Encoded picture width in pixels, multiple of 4 */ + u32 height; /**< Encoded picture height in pixels, multiple of 2 */ + u32 frameRateNum; /**< The stream time scale, [1..1048575] */ + u32 frameRateDenom; /**< Maximum frame rate is frameRateNum/frameRateDenom + * in frames/second. The actual frame rate will be + * defined by timeIncrement of encoded pictures, + * [1..frameRateNum] */ + u32 scaledWidth; /**< Optional down-scaled output picture width, + multiple of 4. 0=disabled. [16..width] */ + u32 scaledHeight; /**< Optional down-scaled output picture height, + multiple of 2. [96..height] */ + u32 refFrameAmount; /**< Amount of reference frame buffers, [1..2] + * 1 = only last frame buffered, + * 2 = last and long term frames buffered */ + u32 refFrameCompress; /**< reference frame compress: 0=disable; 1=enable */ + u32 rfcLumBufLimit; /**< Limit of luma RFC buffer in percent of original reference frame size. */ + u32 rfcChrBufLimit; /**< Limit of chroma RFC buffer in percent of original reference frame size. */ + u32 svctLevel; /**< [0~3] Max Layers number SVC Temporal Scalable Coding. */ + u32 enableSvctPrefix; /**< [0~1] Enable SVCT prefix 0-Disable 1-Enable */ + } H264EncConfig; + +/** Defining rectangular macroblock area in encoder picture */ + typedef struct + { + u32 enable; /**< [0,1] Enables this area */ + u32 top; /**< Top macroblock row inside area [0..heightMbs-1] */ + u32 left; /**< Left macroblock row inside area [0..widthMbs-1] */ + u32 bottom; /**< Bottom macroblock row inside area [top..heightMbs-1] */ + u32 right; /**< Right macroblock row inside area [left..widthMbs-1] */ + } H264EncPictureArea; + +/** Coding control parameters */ + typedef struct + { + u32 sliceSize; /**< Slice size in macroblock rows, + * 0 to encode each picture in one slice, + * [0..height/16] + */ + u32 seiMessages; /**< Insert picture timing and buffering + * period SEI messages into the stream, + * [0,1] + */ + u32 idrHeader; /**< Insert SPS/PPS header to stream either + * for every IDR frame or only to the beginning + * of the sequence. + * [0,1] + */ + u32 videoFullRange; /**< Input video signal sample range, [0,1] + * 0 = Y range in [16..235], + * Cb&Cr range in [16..240] + * 1 = Y, Cb and Cr range in [0..255] + */ + u32 constrainedIntraPrediction; /**< 0 = No constrains, + * 1 = Only use intra neighbours */ + u32 disableDeblockingFilter; /**< 0 = Filter enabled, + * 1 = Filter disabled, + * 2 = Filter disabled on slice edges */ + u32 sampleAspectRatioWidth; /**< Horizontal size of the sample aspect + * ratio (in arbitrary units), 0 for + * unspecified, [0..65535] + */ + u32 sampleAspectRatioHeight; /**< Vertical size of the sample aspect ratio + * (in same units as sampleAspectRatioWidth) + * 0 for unspecified, [0..65535] + */ + u32 enableCabac; /* 0 = CAVLC - Baseline profile, + * 1 = CABAC - Main profile, + * 2 = CABAC/CAVLC frame based - + * Performance optimized Main profile with + * Intra frames encoded using CAVLC and + * Inter frames encoded using CABAC */ + u32 cabacInitIdc; /**< [0,2] CABAC table initial value */ + u32 transform8x8Mode; /**< Enable 8x8 transform mode, High profile + * 0=disabled, 1=adaptive 8x8, 2=always 8x8 */ + u32 quarterPixelMv; /**< 1/4 pixel motion estimation + * 0=disabled, 1=adaptive, 2=enabled */ + u32 cirStart; /**< [0..mbTotal] First macroblock for + Cyclic Intra Refresh */ + u32 cirInterval; /**< [0..mbTotal] Macroblock interval for + Cyclic Intra Refresh, 0=disabled */ + u32 intraSliceMap1; /**< Bitmap for forcing slices 0..31 to intra, + LSB=slice 0, MSB=slice 31, 1=intra. */ + u32 intraSliceMap2; /**< Bitmap for forcing slices 32..63 to intra, + LSB=slice 32, MSB=slice 63, 1=intra. */ + u32 intraSliceMap3; /**< Bitmap for forcing slices 64..95 to intra, + LSB=slice 64, MSB=slice 95, 1=intra. */ + H264EncPictureArea intraArea; /**< Area for forcing intra macroblocks */ + H264EncPictureArea roi1Area; /**< Area for 1st Region-Of-Interest */ + H264EncPictureArea roi2Area; /**< Area for 2nd Region-Of-Interest */ + i32 roi1DeltaQp; /**< [-15..0] QP delta value for 1st ROI */ + i32 roi2DeltaQp; /**< [-15..0] QP delta value for 2nd ROI */ + i32 adaptiveRoi; /**< [-51..0] QP delta value for adaptive ROI */ + i32 adaptiveRoiColor; /**< [-10..10] Color temperature sensitivity + * for adaptive ROI skin detection. + * -10 = 2000K, 0=3000K, 10=5000K */ + i32 roiMapEnable; /**< ROI map status, 0=disable, 1=enable. */ + i32 qpOffset[3]; /**< when roiMapEnable is 1, the qp offset for index 1,2,3. */ + u32 fieldOrder; /**< Field order for interlaced coding, + 0 = bottom field first, 1 = top field first */ + u32 gdrDuration; /**< how many pictures it will take to do GDR, if 0, not do GDR*/ + u32 svctLevel; /**< [0~3] Max Layers number SVC Temporal Scalable Coding. */ + + /* wiener denoise parameters */ + u32 noiseReductionEnable; /**<0 = disable noise reduction; 1 = enable noise reduction */ + u32 noiseLow; /**< valid value range :[1,30] , default: 5 */ + u32 noiseLevel; /**< valid value range :[1,30] , default :10*/ + + u32 inputLineBufEn; /**< enable input image control signals */ + u32 inputLineBufLoopBackEn; /**< input buffer loopback mode enable */ + u32 inputLineBufDepth; /**< input buffer depth in mb lines */ + u32 inputLineBufHwModeEn; /**< hw handshake*/ + u32 nBaseLayerPID; /**< priority_id of base temporal layer */ + u32 level; + u32 enableSVC; + } H264EncCodingCtrl; + +/* Rate control parameters */ + typedef struct + { + u32 pictureRc; /**< Adjust QP between pictures, [0,1] */ + u32 mbRc; /**< Adjust QP inside picture, [0,1] */ + u32 pictureSkip; /**< Allow rate control to skip pictures, [0,1] */ + i32 qpHdr; /**< QP for next encoded picture, [-1..51] + * -1 = Let rate control calculate initial QP + * This QP is used for all pictures if + * HRD and pictureRc and mbRc are disabled + * If HRD is enabled it may override this QP + */ + u32 qpMin; /**< Minimum QP for any picture, [0..51] */ + u32 qpMax; /**< Maximum QP for any picture, [0..51] */ + u32 bitPerSecond; /**< Target bitrate in bits/second, this is + * needed if pictureRc, mbRc, pictureSkip or + * hrd is enabled [10000..60000000] + */ + u32 hrd; /**< Hypothetical Reference Decoder model, [0,1] + * restricts the instantaneous bitrate and + * total bit amount of every coded picture. + * Enabling HRD will cause tight constrains + * on the operation of the rate control + */ + u32 hrdCpbSize; /**< Size of Coded Picture Buffer in HRD (bits) */ + u32 gopLen; /**< Length for Group of Pictures, indicates + * the distance of two intra pictures, + * including first intra [1..300] + */ + i32 intraQpDelta; /**< Intra QP delta. intraQP = QP + intraQpDelta + * This can be used to change the relative quality + * of the Intra pictures or to lower the size + * of Intra pictures. [-12..12] + */ + u32 fixedIntraQp; /**< Fixed QP value for all Intra pictures, [0..51] + * 0 = Rate control calculates intra QP. + */ + i32 mbQpAdjustment; /**< Encoder uses MAD thresholding to recognize + * macroblocks with least details. This value is + * used to adjust the QP of these macroblocks + * increasing the subjective quality. [-8..7] + */ + i32 longTermPicRate; /**< period between long term pic refreshes */ + i32 mbQpAutoBoost; /**< Encoder uses motion vectors and variance to + * recognize background/object macroblocks. + * This value is used to enable the auto QP + * boost of these macroblocks. [0,1] + */ + } H264EncRateCtrl; + +/* Encoder input structure */ + typedef struct + { + ptr_t busLuma; /**< Bus address for input picture + * planar format: luminance component + * semiplanar format: luminance component + * interleaved format: whole picture + */ + ptr_t busChromaU; /**< Bus address for input chrominance + * planar format: cb component + * semiplanar format: both chrominance + * interleaved format: not used + */ + ptr_t busChromaV; /**< Bus address for input chrominance + * planar format: cr component + * semiplanar format: not used + * interleaved format: not used + */ + u32 timeIncrement; /**< The previous picture duration in units + * of 1/frameRateNum. 0 for the very first picture + * and typically equal to frameRateDenom for the rest. + */ + u32 *pOutBuf; /**< Pointer to output stream buffer */ + size_t busOutBuf; /**< Bus address of output stream buffer */ + u32 outBufSize; /**< Size of output stream buffer in bytes */ + H264EncPictureCodingType codingType; /**< Proposed picture coding type, + * INTRA/PREDICTED + */ + size_t busLumaStab; /**< bus address of next picture to stabilize (luminance) */ + H264EncRefPictureMode ipf; /**< Immediately previous == last frame */ + H264EncRefPictureMode ltrf; /**< Long term reference frame */ + + u32 lineBufWrCnt; /**< The number of MB lines already in input MB line buffer */ + + u32 sendAUD; /**< 0=NOT send AUD, 1= send AUD */ + } H264EncIn; + +/** Encoder output structure */ + typedef struct + { + H264EncPictureCodingType codingType; /**< Realized picture coding type, + * INTRA/PREDICTED/NOTCODED + */ + u32 streamSize; /**< Size of output stream in bytes */ + i8 *motionVectors; /**< One pixel motion vector x and y and corresponding + SAD value for every macroblock. + Format: mb0x mb0y mb0sadMsb mb0sadLsb mb1x .. */ + u32 *pNaluSizeBuf; /**< Output buffer for NAL unit sizes + * pNaluSizeBuf[0] = NALU 0 size in bytes + * pNaluSizeBuf[1] = NALU 1 size in bytes + * etc + * Zero value is written after last NALU. + */ + u32 numNalus; /**< Amount of NAL units */ + u32 mse_mul256; /**< Encoded frame Mean Squared Error + multiplied by 256. */ + size_t busScaledLuma; /**< Bus address for scaled encoder picture luma */ + u8 *scaledPicture; /**< Pointer for scaled encoder picture */ + H264EncRefPictureMode ipf; /**< Immediately previous == last frame */ + H264EncRefPictureMode ltrf; /**< Long term reference frame */ + } H264EncOut; + +/** Input pre-processing */ + typedef struct + { + H264EncColorConversionType type; + u16 coeffA; /**< User defined color conversion coefficient */ + u16 coeffB; /**< User defined color conversion coefficient */ + u16 coeffC; /**< User defined color conversion coefficient */ + u16 coeffE; /**< User defined color conversion coefficient */ + u16 coeffF; /**< User defined color conversion coefficient */ + } H264EncColorConversion; + + typedef struct + { + u32 origWidth; /**< Input camera picture width */ + u32 origHeight; /**< Input camera picture height*/ + u32 xOffset; /**< Horizontal offset */ + u32 yOffset; /**< Vertical offset */ + H264EncPictureType inputType; /**< Input picture color format */ + H264EncPictureRotation rotation; /**< Input picture rotation */ + u32 videoStabilization; /**< Enable video stabilization */ + H264EncColorConversion colorConversion; /**< Define color conversion + parameters for RGB input */ + u32 scaledOutput; /**< Enable output of down-scaled + encoder picture. Dimensions + specified at Init. */ + u32 interlacedFrame; /**< Enable input frame format + with two interlaced fields. + Even pictures will be read + from top field, odd pictures + from bottom field. */ + } H264EncPreProcessingCfg; + +/** Callback struct and function type. The callback is made by the encoder + * when a slice is completed and available in the encoder stream output buffer. */ + + typedef struct + { + u32 slicesReadyPrev;/**< Indicates how many slices were completed at + previous callback. This is given because + several slices can be completed between + the callbacks. */ + u32 slicesReady; /**< Indicates how many slices are completed. */ + u32 *sliceSizes; /**< Holds the size (bytes) of every completed slice. */ + u32 *pOutBuf; /**< Pointer to beginning of output stream buffer. */ + void *pAppData; /**< Pointer to application data. */ + } H264EncSliceReady; + + typedef void (*H264EncSliceReadyCallBackFunc)(H264EncSliceReady *sliceReady); + +/** Version information */ + typedef struct + { + u32 major; /**< Encoder API major version */ + u32 minor; /**< Encoder API minor version */ + } H264EncApiVersion; + + typedef struct + { + u32 swBuild; /**< Software build ID */ + u32 hwBuild; /**< Hardware build ID */ + } H264EncBuild; + +/*------------------------------------------------------------------------------ + 4. Encoder API function prototypes +------------------------------------------------------------------------------*/ + +/** Version information */ + H264EncApiVersion H264EncGetApiVersion(void); + H264EncBuild H264EncGetBuild(void); + +/** Helper for input format bit-depths */ + u32 H264EncGetBitsPerPixel(H264EncPictureType type); + +/** Initialization & release */ + H264EncRet H264EncInit(const H264EncConfig * pEncConfig, + H264EncInst * instAddr); + H264EncRet H264EncRelease(H264EncInst inst); + +/** Encoder configuration before stream generation */ + H264EncRet H264EncSetCodingCtrl(H264EncInst inst, const H264EncCodingCtrl * + pCodingParams); + H264EncRet H264EncGetCodingCtrl(H264EncInst inst, H264EncCodingCtrl * + pCodingParams); + +/** Encoder configuration before and during stream generation */ + H264EncRet H264EncSetRateCtrl(H264EncInst inst, + const H264EncRateCtrl * pRateCtrl); + H264EncRet H264EncGetRateCtrl(H264EncInst inst, + H264EncRateCtrl * pRateCtrl); + + H264EncRet H264EncSetPreProcessing(H264EncInst inst, + const H264EncPreProcessingCfg * + pPreProcCfg); + H264EncRet H264EncGetPreProcessing(H264EncInst inst, + H264EncPreProcessingCfg * pPreProcCfg); + + H264EncRet H264EncSetRoiMap(H264EncInst inst, u8 *map); + +/** Encoder user data insertion during stream generation */ + H264EncRet H264EncSetSeiUserData(H264EncInst inst, const u8 * pUserData, + u32 userDataSize); + +/** Stream generation */ + +/** H264EncStrmStart generates the SPS and PPS. SPS is the first NAL unit and PPS + * is the second NAL unit. NaluSizeBuf indicates the size of NAL units. + */ + H264EncRet H264EncStrmStart(H264EncInst inst, const H264EncIn * pEncIn, + H264EncOut * pEncOut); + +/** H264EncStrmEncode encodes one video frame. If SEI messages are enabled the + * first NAL unit is a SEI message. When MVC mode is selected first encoded + * frame belongs to view=0 and second encoded frame belongs to view=1 and so on. + * When MVC mode is selected a prefix NAL unit is generated before view=0 frames. + */ + H264EncRet H264EncStrmEncode(H264EncInst inst, const H264EncIn * pEncIn, + H264EncOut * pEncOut, + H264EncSliceReadyCallBackFunc cbFunc, + EncInputMBLineBufCallBackFunc lineBufCbFunc, + void * pAppData); + +/** H264EncStrmEnd ends a stream with an EOS code. */ + H264EncRet H264EncStrmEnd(H264EncInst inst, const H264EncIn * pEncIn, + H264EncOut * pEncOut); + +/** Hantro internal encoder testing */ + H264EncRet H264EncSetTestId(H264EncInst inst, u32 testId); + +/** Set valid input MB lines for encoder to work */ + H264EncRet H264EncSetInputMbLines(H264EncInst inst, u32 lines); + +/** Get encoded lines information from encoder */ + u32 H264EncGetEncodedMbLines(H264EncInst inst); + +/** Set motionVectors field of H264EncOut structure to point macroblock mbNum */ + H264EncRet H264EncGetMbInfo(H264EncInst inst, H264EncOut * pEncOut, + u32 mbNum); + +/** Add AUD. */ + void H264AccessUnitDelimiter(stream_s *b, u32 byte_stream, u32 primary_pic_type); + +/*------------------------------------------------------------------------------ + 5. Encoder API tracing callback function +------------------------------------------------------------------------------*/ + + void H264EncTrace(const char *msg); + +#ifdef __cplusplus +} +#endif + +#endif /*__H264ENCAPI_H__*/ diff --git a/lib/vc8000nanoe/inc/h264encapi_ext.h b/lib/vc8000nanoe/inc/h264encapi_ext.h new file mode 100644 index 000000000..69e062b41 --- /dev/null +++ b/lib/vc8000nanoe/inc/h264encapi_ext.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Hantro 6250 H.264 Encoder Extended API + * + ******************************************************************************** + */ + +#ifndef __H264ENCAPI_EXT_H__ +#define __H264ENCAPI_EXT_H__ + +#include "basetype.h" +#include "h264encapi.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct + { + u32 disableDeblocking; + i32 filterOffsetA; + i32 filterOffsetB; + } H264EncFilter; + + H264EncRet H264EncGetFilter(H264EncInst inst, H264EncFilter * pEncCfg); + H264EncRet H264EncSetFilter(H264EncInst inst, + const H264EncFilter * pEncCfg); + + H264EncRet H264EncSetFilter(H264EncInst inst, + const H264EncFilter * pEncCfg); + + H264EncRet H264EncSetChromaQpIndexOffset(H264EncInst inst, i32 offset); + + H264EncRet H264EncSetHwBurstSize(H264EncInst inst, u32 burst); + + H264EncRet H264EncSetHwBurstType(H264EncInst inst, u32 burstType); + + H264EncRet H264EncTestInputLineBuf(H264EncInst inst); + + H264EncRet H264EncTestCropping(H264EncInst inst); + +#ifdef __cplusplus +} +#endif + +#endif /*__H264ENCAPI_EXT_H__*/ diff --git a/lib/vc8000nanoe/inc/jpegencapi.h b/lib/vc8000nanoe/inc/jpegencapi.h new file mode 100644 index 000000000..13639d9e2 --- /dev/null +++ b/lib/vc8000nanoe/inc/jpegencapi.h @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Hantro H1 JPEG Encoder API + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef __JPEGENCAPI_H__ +#define __JPEGENCAPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "enccommon.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + + typedef const void *JpegEncInst; + + typedef enum + { + JPEGENC_FRAME_READY = 1, + JPEGENC_RESTART_INTERVAL = 2, + JPEGENC_OK = 0, + JPEGENC_ERROR = -1, + JPEGENC_NULL_ARGUMENT = -2, + JPEGENC_INVALID_ARGUMENT = -3, + JPEGENC_MEMORY_ERROR = -4, + JPEGENC_INVALID_STATUS = -5, + JPEGENC_OUTPUT_BUFFER_OVERFLOW = -6, + JPEGENC_EWL_ERROR = -7, + JPEGENC_EWL_MEMORY_ERROR = -8, + JPEGENC_HW_BUS_ERROR = -9, + JPEGENC_HW_DATA_ERROR = -10, + JPEGENC_HW_TIMEOUT = -11, + JPEGENC_HW_RESERVED = -12, + JPEGENC_SYSTEM_ERROR = -13, + JPEGENC_INSTANCE_ERROR = -14, + JPEGENC_HW_RESET = -15 + } JpegEncRet; + +/* Picture YUV type for initialization */ + typedef enum + { + JPEGENC_YUV420_PLANAR = 0, /* YYYY... UUUU... VVVV... */ + JPEGENC_YUV420_SEMIPLANAR, /* YYYY... UVUVUV... */ + JPEGENC_YUV420_SEMIPLANAR_VU, /* YYYY... VUVUVU... */ + JPEGENC_YUV422_INTERLEAVED_YUYV, /* YUYVYUYV... */ + JPEGENC_YUV422_INTERLEAVED_UYVY, /* UYVYUYVY... */ + JPEGENC_RGB565, /* 16-bit RGB 16bpp */ + JPEGENC_BGR565, /* 16-bit RGB 16bpp */ + JPEGENC_RGB555, /* 15-bit RGB 16bpp */ + JPEGENC_BGR555, /* 15-bit RGB 16bpp */ + JPEGENC_RGB444, /* 12-bit RGB 16bpp */ + JPEGENC_BGR444, /* 12-bit RGB 16bpp */ + JPEGENC_RGB888, /* 24-bit RGB 32bpp */ + JPEGENC_BGR888, /* 24-bit RGB 32bpp */ + JPEGENC_RGB101010, /* 30-bit RGB 32bpp */ + JPEGENC_BGR101010 /* 30-bit RGB 32bpp */ + } JpegEncFrameType; + +/* Picture rotation for initialization */ + typedef enum + { + JPEGENC_ROTATE_0 = 0, + JPEGENC_ROTATE_90R = 1, /* Rotate 90 degrees clockwise */ + JPEGENC_ROTATE_90L = 2, /* Rotate 90 degrees counter-clockwise */ + JPEGENC_ROTATE_180R = 3 /* Rotate 180 degrees clockwise */ + } JpegEncPictureRotation; + +/* Picture color space conversion for RGB input */ + typedef enum + { + JPEGENC_RGBTOYUV_BT601 = 0, /* Color conversion according to BT.601 */ + JPEGENC_RGBTOYUV_BT709 = 1, /* Color conversion according to BT.709 */ + JPEGENC_RGBTOYUV_USER_DEFINED = 2 /* User defined color conversion */ + } JpegEncColorConversionType; + + typedef enum + { + JPEGENC_WHOLE_FRAME = 0, /* The whole frame is stored in linear memory */ + JPEGENC_SLICED_FRAME /* The frame is sliced into restart intervals; + * Input address is given for each slice */ + } JpegEncCodingType; + + typedef enum + { + JPEGENC_420_MODE = 0, /* Encoding in YUV 4:2:0 mode */ + JPEGENC_422_MODE /* Encoding in YUV 4:2:2 mode */ + } JpegEncCodingMode; + + typedef enum + { + JPEGENC_NO_UNITS = 0, /* No units, + * X and Y specify the pixel aspect ratio */ + JPEGENC_DOTS_PER_INCH = 1, /* X and Y are dots per inch */ + JPEGENC_DOTS_PER_CM = 2 /* X and Y are dots per cm */ + } JpegEncAppUnitsType; + + typedef enum + { + JPEGENC_SINGLE_MARKER = 0, /* Luma/Chroma tables are written behind + * one marker */ + JPEGENC_MULTI_MARKER /* Luma/Chroma tables are written behind + * one marker/component */ + } JpegEncTableMarkerType; + + typedef enum + { + JPEGENC_THUMB_JPEG = 0x10, /* Thumbnail coded using JPEG */ + JPEGENC_THUMB_PALETTE_RGB8 = 0x11, /* Thumbnail stored using 1 byte/pixel */ + JPEGENC_THUMB_RGB24 = 0x13 /* Thumbnail stored using 3 bytes/pixel */ + } JpegEncThumbFormat; + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ +/* Version information */ + typedef struct + { + u32 major; /* Encoder API major version */ + u32 minor; /* Encoder API minor version */ + } JpegEncApiVersion; + typedef struct + { + u32 swBuild; /* Software build ID */ + u32 hwBuild; /* Hardware build ID */ + } JpegEncBuild; + +/* thumbnail info */ + typedef struct + { + JpegEncThumbFormat format; /* Format of the thumbnail */ + u8 width; /* Width in pixels of thumbnail */ + u8 height; /* Height in pixels of thumbnail */ + const void *data; /* Thumbnail data */ + u16 dataLength; /* Data amount in bytes */ + } JpegEncThumb; + +/* RGB input to YUV color conversion */ + typedef struct + { + JpegEncColorConversionType type; + u16 coeffA; /* User defined color conversion coefficient */ + u16 coeffB; /* User defined color conversion coefficient */ + u16 coeffC; /* User defined color conversion coefficient */ + u16 coeffE; /* User defined color conversion coefficient */ + u16 coeffF; /* User defined color conversion coefficient */ + } JpegEncColorConversion; + +/* Encoder configuration */ + typedef struct + { + u32 inputWidth; /* Number of pixels/line in input image */ + u32 inputHeight; /* Number of lines in input image */ + u32 xOffset; /* Pixels from top-left corner of input image */ + u32 yOffset; /* to top-left corner of encoded image */ + u32 codingWidth; /* Width of encoded image */ + u32 codingHeight; /* Height of encoded image */ + u32 restartInterval; /* Restart interval (MCU lines) */ + u32 qLevel; /* Quantization level (0 - 9) */ + const u8 *qTableLuma; /* Quantization table for luminance [64], + * overrides quantization level, zigzag order */ + const u8 *qTableChroma; /* Quantization table for chrominance [64], + * overrides quantization level, zigzag order */ + JpegEncFrameType frameType; /* Input frame YUV / RGB format */ + JpegEncColorConversion colorConversion; /* RGB to YUV conversion */ + JpegEncPictureRotation rotation; /* rotation off/-90/+90 */ + JpegEncCodingType codingType; /* Whole frame / restart interval */ + JpegEncCodingMode codingMode; /* 4:2:0 / 4:2:2 coding */ + JpegEncAppUnitsType unitsType; /* Units for X & Y density in APP0 */ + JpegEncTableMarkerType markerType; /* Table marker type */ + u32 xDensity; /* Horizontal pixel density */ + u32 yDensity; /* Vertical pixel density */ + u32 comLength; /* Length of COM header */ + const u8 *pCom; /* Comment header pointer */ + u32 inputLineBufEn; /* enable input image control signals */ + u32 inputLineBufLoopBackEn; /* input buffer loopback mode enable */ + u32 inputLineBufDepth; /* input buffer depth in mb lines */ + u32 inputLineBufHwModeEn; /* hw handshake*/ + } JpegEncCfg; + +/* Input info */ + typedef struct + { + u32 frameHeader; /* Enable/disable creation of frame headers */ + size_t busLum; /* Bus address of luminance input (Y) */ + size_t busCb; /* Bus address of chrominance input (Cb) */ + size_t busCr; /* Bus address of chrominance input (Cr) */ + const u8 *pLum; /* Pointer to luminance input (Y) */ + const u8 *pCb; /* Pointer to chrominance input (Cb) */ + const u8 *pCr; /* Pointer to chrominance input (Cr) */ + u8 *pOutBuf; /* Pointer to output buffer */ + size_t busOutBuf; /* Bus address of output stream buffer */ + u32 outBufSize; /* Size of output buffer (bytes) */ + u32 lineBufWrCnt; /* The number of MB lines already in input MB line buffer */ + } JpegEncIn; + +/* Output info */ + typedef struct + { + u32 jfifSize; /* Encoded JFIF size (bytes) */ + } JpegEncOut; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +/* Version information */ + JpegEncApiVersion JpegEncGetApiVersion(void); + +/* Build information */ + JpegEncBuild JpegEncGetBuild(void); + +/* Helper for input format bit-depths */ + u32 JpegEncGetBitsPerPixel(JpegEncFrameType type); + +/* Initialization & release */ + JpegEncRet JpegEncInit(const JpegEncCfg * pEncCfg, JpegEncInst * instAddr); + JpegEncRet JpegEncRelease(JpegEncInst inst); + +/* Encoding configuration */ + JpegEncRet JpegEncSetPictureSize(JpegEncInst inst, + const JpegEncCfg * pEncCfg); + + JpegEncRet JpegEncSetThumbnail(JpegEncInst inst, + const JpegEncThumb * JpegThumb); + +/* Jfif generation */ + JpegEncRet JpegEncEncode(JpegEncInst inst, + const JpegEncIn * pEncIn, + JpegEncOut * pEncOut, + EncInputMBLineBufCallBackFunc lineBufCbFunc, + void * pAppData); + + /* Set valid input MB lines for encoder to work */ + u32 JpegEncGetEncodedMbLines(JpegEncInst inst); + + /* Get encoded lines information from encoder */ + JpegEncRet JpegEncSetInputMBLines(JpegEncInst inst, u32 lines); + +/*------------------------------------------------------------------------------ + 5. Encoder API tracing callback function +------------------------------------------------------------------------------*/ + + void JpegEnc_Trace(const char *msg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/vc8000nanoe/inc/reg_enum_v7.h b/lib/vc8000nanoe/inc/reg_enum_v7.h new file mode 100644 index 000000000..08347b646 --- /dev/null +++ b/lib/vc8000nanoe/inc/reg_enum_v7.h @@ -0,0 +1,654 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Register enum auto generated. + * + ******************************************************************************** + */ + +#ifdef __REGISTERS_ENUM_FAKE_H__ +typedef enum { +#endif /*__REGISTERS_ENUM_FAKE_H__*/ + +/* IRQ Source Map. */ + HEncIRQRfcBufOverflow, + HEncIRQLowLatency, + + +/* HW synthesis config register 2, read-only */ + HEncHWAddress64Bits, + HEncHWDnfSupport, + HEncHWRfcSupport, + HEncHWQEnhanceSupport, + HEncHWInstantSupport, + HEncHWSvctSupport, + HEncHWAxiIdInSupport, + HEncHWWriteOneClrIrqSupport, + HEncHWInputLoopbackSupport, + +/* HEncMBRC Control */ + HEncMBRCQpDeltaRange , + HEncMBRcSliceQpOffset , + +/* Segment 4 */ + HEncSeg4I4PrevModeFavor , + HEncSeg4I16Favor , + HEncSeg4GoldenPenalty , + HEncSeg4SkipPenalty , + HEncSeg4InterFavor , + HEncSeg4SplitPenalty16x8, + HEncSeg4SplitPenalty8x8 , + HEncSeg4SplitPenalty8x4 , + HEncSeg4DMVPenaltyQp , + HEncSeg4SplitPenalty4x4 , + +/* Segment 5 */ + HEncSeg5I4PrevModeFavor , + HEncSeg5I16Favor , + HEncSeg5GoldenPenalty , + HEncSeg5SkipPenalty , + HEncSeg5InterFavor , + HEncSeg5SplitPenalty16x8, + HEncSeg5SplitPenalty8x8 , + HEncSeg5SplitPenalty8x4 , + HEncSeg5DMVPenaltyQp , + HEncSeg5SplitPenalty4x4 , + +/* Segment 6 */ + HEncSeg6I4PrevModeFavor , + HEncSeg6I16Favor , + HEncSeg6GoldenPenalty , + HEncSeg6SkipPenalty , + HEncSeg6InterFavor , + HEncSeg6SplitPenalty16x8, + HEncSeg6SplitPenalty8x8 , + HEncSeg6SplitPenalty8x4 , + HEncSeg6DMVPenaltyQp , + HEncSeg6SplitPenalty4x4 , + +/* Segment 7 */ + HEncSeg7I4PrevModeFavor , + HEncSeg7I16Favor , + HEncSeg7GoldenPenalty , + HEncSeg7SkipPenalty , + HEncSeg7InterFavor , + HEncSeg7SplitPenalty16x8, + HEncSeg7SplitPenalty8x8 , + HEncSeg7SplitPenalty8x4 , + HEncSeg7DMVPenaltyQp , + HEncSeg7SplitPenalty4x4 , + +/* Segment 8 */ + HEncSeg8I4PrevModeFavor , + HEncSeg8I16Favor , + HEncSeg8GoldenPenalty , + HEncSeg8SkipPenalty , + HEncSeg8InterFavor , + HEncSeg8SplitPenalty16x8, + HEncSeg8SplitPenalty8x8 , + HEncSeg8SplitPenalty8x4 , + HEncSeg8DMVPenaltyQp , + HEncSeg8SplitPenalty4x4 , + +/* Segment 9 */ + HEncSeg9I4PrevModeFavor , + HEncSeg9I16Favor , + HEncSeg9GoldenPenalty , + HEncSeg9SkipPenalty , + HEncSeg9InterFavor , + HEncSeg9SplitPenalty16x8, + HEncSeg9SplitPenalty8x8 , + HEncSeg9SplitPenalty8x4 , + HEncSeg9DMVPenaltyQp , + HEncSeg9SplitPenalty4x4 , + +/* Segment 10 */ + HEncSeg10I4PrevModeFavor , + HEncSeg10I16Favor , + HEncSeg10GoldenPenalty , + HEncSeg10SkipPenalty , + HEncSeg10InterFavor , + HEncSeg10SplitPenalty16x8, + HEncSeg10SplitPenalty8x8 , + HEncSeg10SplitPenalty8x4 , + HEncSeg10DMVPenaltyQp , + HEncSeg10SplitPenalty4x4 , + +/* Segment 11 */ + HEncSeg11I4PrevModeFavor , + HEncSeg11I16Favor , + HEncSeg11GoldenPenalty , + HEncSeg11SkipPenalty , + HEncSeg11InterFavor , + HEncSeg11SplitPenalty16x8, + HEncSeg11SplitPenalty8x8 , + HEncSeg11SplitPenalty8x4 , + HEncSeg11DMVPenaltyQp , + HEncSeg11SplitPenalty4x4 , + +/* Segment 12 */ + HEncSeg12I4PrevModeFavor , + HEncSeg12I16Favor , + HEncSeg12GoldenPenalty , + HEncSeg12SkipPenalty , + HEncSeg12InterFavor , + HEncSeg12SplitPenalty16x8, + HEncSeg12SplitPenalty8x8 , + HEncSeg12SplitPenalty8x4 , + HEncSeg12DMVPenaltyQp , + HEncSeg12SplitPenalty4x4 , + +/* Segment 13 */ + HEncSeg13I4PrevModeFavor , + HEncSeg13I16Favor , + HEncSeg13GoldenPenalty , + HEncSeg13SkipPenalty , + HEncSeg13InterFavor , + HEncSeg13SplitPenalty16x8, + HEncSeg13SplitPenalty8x8 , + HEncSeg13SplitPenalty8x4 , + HEncSeg13DMVPenaltyQp , + HEncSeg13SplitPenalty4x4 , + +/* Segment 14 */ + HEncSeg14I4PrevModeFavor , + HEncSeg14I16Favor , + HEncSeg14GoldenPenalty , + HEncSeg14SkipPenalty , + HEncSeg14InterFavor , + HEncSeg14SplitPenalty16x8, + HEncSeg14SplitPenalty8x8 , + HEncSeg14SplitPenalty8x4 , + HEncSeg14DMVPenaltyQp , + HEncSeg14SplitPenalty4x4 , + +/* Segment 15 */ + HEncSeg15I4PrevModeFavor , + HEncSeg15I16Favor , + HEncSeg15GoldenPenalty , + HEncSeg15SkipPenalty , + HEncSeg15InterFavor , + HEncSeg15SplitPenalty16x8, + HEncSeg15SplitPenalty8x8 , + HEncSeg15SplitPenalty8x4 , + HEncSeg15DMVPenaltyQp , + HEncSeg15SplitPenalty4x4 , + +/* Segment 16 */ + HEncSeg16I4PrevModeFavor , + HEncSeg16I16Favor , + HEncSeg16GoldenPenalty , + HEncSeg16SkipPenalty , + HEncSeg16InterFavor , + HEncSeg16SplitPenalty16x8, + HEncSeg16SplitPenalty8x8 , + HEncSeg16SplitPenalty8x4 , + HEncSeg16DMVPenaltyQp , + HEncSeg16SplitPenalty4x4 , + +/* Segment 17 */ + HEncSeg17I4PrevModeFavor , + HEncSeg17I16Favor , + HEncSeg17GoldenPenalty , + HEncSeg17SkipPenalty , + HEncSeg17InterFavor , + HEncSeg17SplitPenalty16x8, + HEncSeg17SplitPenalty8x8 , + HEncSeg17SplitPenalty8x4 , + HEncSeg17DMVPenaltyQp , + HEncSeg17SplitPenalty4x4 , + +/* Segment 18 */ + HEncSeg18I4PrevModeFavor , + HEncSeg18I16Favor , + HEncSeg18GoldenPenalty , + HEncSeg18SkipPenalty , + HEncSeg18InterFavor , + HEncSeg18SplitPenalty16x8, + HEncSeg18SplitPenalty8x8 , + HEncSeg18SplitPenalty8x4 , + HEncSeg18DMVPenaltyQp , + HEncSeg18SplitPenalty4x4 , + +/* Segment 19 */ + HEncSeg19I4PrevModeFavor , + HEncSeg19I16Favor , + HEncSeg19GoldenPenalty , + HEncSeg19SkipPenalty , + HEncSeg19InterFavor , + HEncSeg19SplitPenalty16x8, + HEncSeg19SplitPenalty8x8 , + HEncSeg19SplitPenalty8x4 , + HEncSeg19DMVPenaltyQp , + HEncSeg19SplitPenalty4x4 , + +/* Segment 20 */ + HEncSeg20I4PrevModeFavor , + HEncSeg20I16Favor , + HEncSeg20GoldenPenalty , + HEncSeg20SkipPenalty , + HEncSeg20InterFavor , + HEncSeg20SplitPenalty16x8, + HEncSeg20SplitPenalty8x8 , + HEncSeg20SplitPenalty8x4 , + HEncSeg20DMVPenaltyQp , + HEncSeg20SplitPenalty4x4 , + +/* Segment 21 */ + HEncSeg21I4PrevModeFavor , + HEncSeg21I16Favor , + HEncSeg21GoldenPenalty , + HEncSeg21SkipPenalty , + HEncSeg21InterFavor , + HEncSeg21SplitPenalty16x8, + HEncSeg21SplitPenalty8x8 , + HEncSeg21SplitPenalty8x4 , + HEncSeg21DMVPenaltyQp , + HEncSeg21SplitPenalty4x4 , + +/* Segment 22 */ + HEncSeg22I4PrevModeFavor , + HEncSeg22I16Favor , + HEncSeg22GoldenPenalty , + HEncSeg22SkipPenalty , + HEncSeg22InterFavor , + HEncSeg22SplitPenalty16x8, + HEncSeg22SplitPenalty8x8 , + HEncSeg22SplitPenalty8x4 , + HEncSeg22DMVPenaltyQp , + HEncSeg22SplitPenalty4x4 , + +/* Segment 23 */ + HEncSeg23I4PrevModeFavor , + HEncSeg23I16Favor , + HEncSeg23GoldenPenalty , + HEncSeg23SkipPenalty , + HEncSeg23InterFavor , + HEncSeg23SplitPenalty16x8, + HEncSeg23SplitPenalty8x8 , + HEncSeg23SplitPenalty8x4 , + HEncSeg23DMVPenaltyQp , + HEncSeg23SplitPenalty4x4 , + +/* Segment 24 */ + HEncSeg24I4PrevModeFavor , + HEncSeg24I16Favor , + HEncSeg24GoldenPenalty , + HEncSeg24SkipPenalty , + HEncSeg24InterFavor , + HEncSeg24SplitPenalty16x8, + HEncSeg24SplitPenalty8x8 , + HEncSeg24SplitPenalty8x4 , + HEncSeg24DMVPenaltyQp , + HEncSeg24SplitPenalty4x4 , + +/* Segment 25 */ + HEncSeg25I4PrevModeFavor , + HEncSeg25I16Favor , + HEncSeg25GoldenPenalty , + HEncSeg25SkipPenalty , + HEncSeg25InterFavor , + HEncSeg25SplitPenalty16x8, + HEncSeg25SplitPenalty8x8 , + HEncSeg25SplitPenalty8x4 , + HEncSeg25DMVPenaltyQp , + HEncSeg25SplitPenalty4x4 , + +/* Segment 26 */ + HEncSeg26I4PrevModeFavor , + HEncSeg26I16Favor , + HEncSeg26GoldenPenalty , + HEncSeg26SkipPenalty , + HEncSeg26InterFavor , + HEncSeg26SplitPenalty16x8, + HEncSeg26SplitPenalty8x8 , + HEncSeg26SplitPenalty8x4 , + HEncSeg26DMVPenaltyQp , + HEncSeg26SplitPenalty4x4 , + +/* Segment 27 */ + HEncSeg27I4PrevModeFavor , + HEncSeg27I16Favor , + HEncSeg27GoldenPenalty , + HEncSeg27SkipPenalty , + HEncSeg27InterFavor , + HEncSeg27SplitPenalty16x8, + HEncSeg27SplitPenalty8x8 , + HEncSeg27SplitPenalty8x4 , + HEncSeg27DMVPenaltyQp , + HEncSeg27SplitPenalty4x4 , + +/* Segment 28 */ + HEncSeg28I4PrevModeFavor , + HEncSeg28I16Favor , + HEncSeg28GoldenPenalty , + HEncSeg28SkipPenalty , + HEncSeg28InterFavor , + HEncSeg28SplitPenalty16x8, + HEncSeg28SplitPenalty8x8 , + HEncSeg28SplitPenalty8x4 , + HEncSeg28DMVPenaltyQp , + HEncSeg28SplitPenalty4x4 , + +/* Segment 29 */ + HEncSeg29I4PrevModeFavor , + HEncSeg29I16Favor , + HEncSeg29GoldenPenalty , + HEncSeg29SkipPenalty , + HEncSeg29InterFavor , + HEncSeg29SplitPenalty16x8, + HEncSeg29SplitPenalty8x8 , + HEncSeg29SplitPenalty8x4 , + HEncSeg29DMVPenaltyQp , + HEncSeg29SplitPenalty4x4 , + +/* Segment 30 */ + HEncSeg30I4PrevModeFavor , + HEncSeg30I16Favor , + HEncSeg30GoldenPenalty , + HEncSeg30SkipPenalty , + HEncSeg30InterFavor , + HEncSeg30SplitPenalty16x8, + HEncSeg30SplitPenalty8x8 , + HEncSeg30SplitPenalty8x4 , + HEncSeg30DMVPenaltyQp , + HEncSeg30SplitPenalty4x4 , + +/* Segment 31 */ + HEncSeg31I4PrevModeFavor , + HEncSeg31I16Favor , + HEncSeg31GoldenPenalty , + HEncSeg31SkipPenalty , + HEncSeg31InterFavor , + HEncSeg31SplitPenalty16x8, + HEncSeg31SplitPenalty8x8 , + HEncSeg31SplitPenalty8x4 , + HEncSeg31DMVPenaltyQp , + HEncSeg31SplitPenalty4x4 , + +/* MBRC Control registers */ + HEncMBRCQpFrac , + HEncMBComplexityOffset , + HEncMBRCEnable , + HEncMBQpDeltaGain , + +/* HEncMBComplexity */ + HEncMBComplexityAverage , + +/* Reference Frame Compression */ + HEncRfcLumBufLimit , + HEncRfcIntEn , + HEncRfcLumDiscreteMode , + HEncRefChrCompress , + HEncRefLumCompress , + HEncBaseRefLumTbl , + HEncBaseRefChrTbl , + HEncBaseRecLumTbl , + HEncBaseRecChrTbl , + HEncBaseRefLumTbl2 , + HEncBaseRefChrTbl2 , + HEncRfcChrBufLimit , + +/* Reference Management Commands */ + HEncRefReorderFlag , + HEncRefReorderDiffPicNum, + +/* AXI Read ID for Input */ + HEncAXIReadIDInC0, + HEncAXIReadIDInC1, + HEncAXIReadIDInC2, + HEncAXIReadIDEnable, + +/* MSB for 64bit address access. */ + HEncBaseRefLumTbl_MSB, + HEncBaseRefChrTbl_MSB, + HEncBaseRecLumTbl_MSB, + HEncBaseRecChrTbl_MSB, + HEncBaseRefLumTbl2_MSB, + HEncBaseRefChrTbl2_MSB, + HEncBaseStream_MSB, + HEncBaseControl_MSB, + HEncBaseRefLum_MSB, + HEncBaseRefChr_MSB, + HEncBaseRecLum_MSB, + HEncBaseRecChr_MSB, + HEncBaseInLum_MSB, + HEncBaseInCb_MSB, + HEncBaseInCr_MSB, + HEncBaseRefLum2_MSB, + HEncBaseRefChr2_MSB, + HEncH264BaseRefLum2_MSB, + HEncH264BaseRefChr2_MSB, + HEncBaseNextLum_MSB, + HEncBaseCabacCtx_MSB, + HEncBaseMvWrite_MSB, + HEncBasePartition1_MSB, + HEncBasePartition2_MSB, + HEncBaseVp8ProbCount_MSB, + HEncBaseVp8SegmentMap_MSB, + HEncBaseScaledOutLum_MSB, + HEncBasePartition3_MSB, + HEncBasePartition4_MSB, + +/* Denoise Filter Control. */ + HEncDnfEnable, + HEncDnfStregth, + HEncDnfMbNum, + HEncDnfNoiseMax, + HEncDnfNoiseLevelInvC, + HEncDnfNoiseLevelInvY, + HEncDnfNoisePred, + HEncDnfThresholdPred, + +/* Denoise Filter Parameters. */ + HEncDnfParaS1_0, + HEncDnfParaS1_1, + HEncDnfParaS1_2, + HEncDnfParaS1_3, + HEncDnfParaS1_4, + HEncDnfParaS1_5, + HEncDnfParaS1_6, + HEncDnfParaS1_7, + HEncDnfParaS1_8, + HEncDnfParaS1_9, + HEncDnfParaS1_10, + HEncDnfParaS1_11, + HEncDnfParaS1_12, + HEncDnfParaS1_13, + HEncDnfParaS1_14, + HEncDnfParaS1_15, + HEncDnfParaS2_0, + HEncDnfParaS2_1, + HEncDnfParaS2_2, + HEncDnfParaS2_3, + HEncDnfParaS2_4, + HEncDnfParaS2_5, + HEncDnfParaS2_6, + HEncDnfParaS2_7, + HEncDnfParaS2_8, + HEncDnfParaS2_9, + HEncDnfParaS2_10, + HEncDnfParaS2_11, + HEncDnfParaS2_12, + HEncDnfParaS2_13, + HEncDnfParaS2_14, + HEncDnfParaS2_15, + HEncDnfParaS3_0, + HEncDnfParaS3_1, + HEncDnfParaS3_2, + HEncDnfParaS3_3, + HEncDnfParaS3_4, + HEncDnfParaS3_5, + HEncDnfParaS3_6, + HEncDnfParaS3_7, + HEncDnfParaS3_8, + HEncDnfParaS3_9, + HEncDnfParaS3_10, + HEncDnfParaS3_11, + HEncDnfParaS3_12, + HEncDnfParaS3_13, + HEncDnfParaS3_14, + HEncDnfParaS3_15, + HEncDnfParaS3_16, + HEncDnfParaS3_17, + HEncDnfParaS3_18, + HEncDnfParaS3_19, + HEncDnfParaS3_20, + HEncDnfParaS3_21, + HEncDnfParaS3_22, + HEncDnfParaS3_23, + HEncDnfParaS3_24, + HEncDnfParaS3_25, + HEncDnfParaS3_26, + HEncDnfParaS3_27, + HEncDnfParaS3_28, + HEncDnfParaS3_29, + HEncDnfParaS3_30, + HEncDnfParaS3_31, + HEncDnfParaS3_32, + HEncDnfParaS3_33, + HEncDnfParaS3_34, + HEncDnfParaS3_35, + HEncDnfParaS3_36, + HEncDnfParaS3_37, + HEncDnfParaS3_38, + HEncDnfParaS3_39, + HEncDnfParaS3_40, + HEncDnfParaS3_41, + HEncDnfParaS3_42, + HEncDnfParaS3_43, + HEncDnfParaS3_44, + HEncDnfParaS3_45, + HEncDnfParaS3_46, + HEncDnfParaS3_47, + HEncDnfParaS3_48, + HEncDnfParaS3_49, + HEncDnfParaS3_50, + HEncDnfParaS3_51, + HEncDnfParaS3_52, + HEncDnfParaS3_53, + HEncDnfParaS3_54, + HEncDnfParaS3_55, + HEncDnfParaS3_56, + HEncDnfParaS3_57, + HEncDnfParaS3_58, + HEncDnfParaS3_59, + HEncDnfParaS3_60, + HEncDnfParaS3_61, + HEncDnfParaS3_62, + HEncDnfParaS3_63, + HEncDnfParaS4_0, + HEncDnfParaS4_1, + HEncDnfParaS4_2, + HEncDnfParaS4_3, + HEncDnfParaS4_4, + HEncDnfParaS4_5, + HEncDnfParaS4_6, + HEncDnfParaS4_7, + HEncDnfParaS4_8, + HEncDnfParaS4_9, + HEncDnfParaS4_10, + HEncDnfParaS4_11, + HEncDnfParaS4_12, + HEncDnfParaS4_13, + HEncDnfParaS4_14, + HEncDnfParaS4_15, + HEncDnfParaS4_16, + HEncDnfParaS4_17, + HEncDnfParaS4_18, + HEncDnfParaS4_19, + HEncDnfParaS4_20, + HEncDnfParaS4_21, + HEncDnfParaS4_22, + HEncDnfParaS4_23, + HEncDnfParaS4_24, + HEncDnfParaS4_25, + HEncDnfParaS4_26, + HEncDnfParaS4_27, + HEncDnfParaS4_28, + HEncDnfParaS4_29, + HEncDnfParaS4_30, + HEncDnfParaS4_31, + HEncDnfParaS4_32, + HEncDnfParaS4_33, + HEncDnfParaS4_34, + HEncDnfParaS4_35, + HEncDnfParaS4_36, + HEncDnfParaS4_37, + HEncDnfParaS4_38, + HEncDnfParaS4_39, + HEncDnfParaS4_40, + HEncDnfParaS4_41, + HEncDnfParaS4_42, + HEncDnfParaS4_43, + HEncDnfParaS4_44, + HEncDnfParaS4_45, + HEncDnfParaS4_46, + HEncDnfParaS4_47, + HEncDnfParaS4_48, + HEncDnfParaS4_49, + HEncDnfParaS4_50, + HEncDnfParaS4_51, + HEncDnfParaS4_52, + HEncDnfParaS4_53, + HEncDnfParaS4_54, + HEncDnfParaS4_55, + HEncDnfParaS4_56, + HEncDnfParaS4_57, + HEncDnfParaS4_58, + HEncDnfParaS4_59, + HEncDnfParaS4_60, + HEncDnfParaS4_61, + HEncDnfParaS4_62, + HEncDnfParaS4_63, + +/* Low latency and Input Line buffer. */ + HEncMbWrPtr, + HEncMbRdPtr, + HEncLowLatencyHwSyncMbRows, + HEncLowLatencyEn, + HEncInputBufferLoopBackEn, + HEncLowLatencyHwIntfEn, + HEncLowLatencyIrqEn, + +/* Last Fake Register for Register Counting. */ + +#ifdef __REGISTERS_ENUM_FAKE_H__ +} regName; +#endif /*__REGISTERS_ENUM_FAKE_H__*/ diff --git a/lib/vc8000nanoe/inc/reg_offset_v7.h b/lib/vc8000nanoe/inc/reg_offset_v7.h new file mode 100644 index 000000000..5c9fc99ef --- /dev/null +++ b/lib/vc8000nanoe/inc/reg_offset_v7.h @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Register offset auto generated. + * + ******************************************************************************** + */ + +#ifndef __HENC_REGISTER_OFFSET_H__ +#define __HENC_REGISTER_OFFSET_H__ + +/* IRQ Source Map. */ +#define BASE_HEncIRQ 0x4U + + +/* HW synthesis config register 2, read-only */ +#define BASE_HWFuse2 0x4a0U + +/* HEncMBRC Control */ +#define BASE_HEncMBRC 0x4a4U + +/* Segment 4 */ +#define BASE_HEncSeg4_1 0x4a8U +#define BASE_HEncSeg4_2 0x4acU +#define BASE_HEncSeg4_3 0x4b0U +#define BASE_HEncSeg4_4 0x4b4U + +/* Segment 5 */ +#define BASE_HEncSeg5_1 0x4b8U +#define BASE_HEncSeg5_2 0x4bcU +#define BASE_HEncSeg5_3 0x4c0U +#define BASE_HEncSeg5_4 0x4c4U + +/* Segment 6 */ +#define BASE_HEncSeg6_1 0x4c8U +#define BASE_HEncSeg6_2 0x4ccU +#define BASE_HEncSeg6_3 0x4d0U +#define BASE_HEncSeg6_4 0x4d4U + +/* Segment 7 */ +#define BASE_HEncSeg7_1 0x4d8U +#define BASE_HEncSeg7_2 0x4dcU +#define BASE_HEncSeg7_3 0x4e0U +#define BASE_HEncSeg7_4 0x4e4U + +/* Segment 8 */ +#define BASE_HEncSeg8_1 0x4e8U +#define BASE_HEncSeg8_2 0x4ecU +#define BASE_HEncSeg8_3 0x4f0U +#define BASE_HEncSeg8_4 0x4f4U + +/* Segment 9 */ +#define BASE_HEncSeg9_1 0x4f8U +#define BASE_HEncSeg9_2 0x4fcU +#define BASE_HEncSeg9_3 0x500U +#define BASE_HEncSeg9_4 0x504U + +/* Segment 10 */ +#define BASE_HEncSeg10_1 0x508U +#define BASE_HEncSeg10_2 0x50cU +#define BASE_HEncSeg10_3 0x510U +#define BASE_HEncSeg10_4 0x514U + +/* Segment 11 */ +#define BASE_HEncSeg11_1 0x518U +#define BASE_HEncSeg11_2 0x51cU +#define BASE_HEncSeg11_3 0x520U +#define BASE_HEncSeg11_4 0x524U + +/* Segment 12 */ +#define BASE_HEncSeg12_1 0x528U +#define BASE_HEncSeg12_2 0x52cU +#define BASE_HEncSeg12_3 0x530U +#define BASE_HEncSeg12_4 0x534U + +/* Segment 13 */ +#define BASE_HEncSeg13_1 0x538U +#define BASE_HEncSeg13_2 0x53cU +#define BASE_HEncSeg13_3 0x540U +#define BASE_HEncSeg13_4 0x544U + +/* Segment 14 */ +#define BASE_HEncSeg14_1 0x548U +#define BASE_HEncSeg14_2 0x54cU +#define BASE_HEncSeg14_3 0x550U +#define BASE_HEncSeg14_4 0x554U + +/* Segment 15 */ +#define BASE_HEncSeg15_1 0x558U +#define BASE_HEncSeg15_2 0x55cU +#define BASE_HEncSeg15_3 0x560U +#define BASE_HEncSeg15_4 0x564U + +/* Segment 16 */ +#define BASE_HEncSeg16_1 0x568U +#define BASE_HEncSeg16_2 0x56cU +#define BASE_HEncSeg16_3 0x570U +#define BASE_HEncSeg16_4 0x574U + +/* Segment 17 */ +#define BASE_HEncSeg17_1 0x578U +#define BASE_HEncSeg17_2 0x57cU +#define BASE_HEncSeg17_3 0x580U +#define BASE_HEncSeg17_4 0x584U + +/* Segment 18 */ +#define BASE_HEncSeg18_1 0x588U +#define BASE_HEncSeg18_2 0x58cU +#define BASE_HEncSeg18_3 0x590U +#define BASE_HEncSeg18_4 0x594U + +/* Segment 19 */ +#define BASE_HEncSeg19_1 0x598U +#define BASE_HEncSeg19_2 0x59cU +#define BASE_HEncSeg19_3 0x5a0U +#define BASE_HEncSeg19_4 0x5a4U + +/* Segment 20 */ +#define BASE_HEncSeg20_1 0x5a8U +#define BASE_HEncSeg20_2 0x5acU +#define BASE_HEncSeg20_3 0x5b0U +#define BASE_HEncSeg20_4 0x5b4U + +/* Segment 21 */ +#define BASE_HEncSeg21_1 0x5b8U +#define BASE_HEncSeg21_2 0x5bcU +#define BASE_HEncSeg21_3 0x5c0U +#define BASE_HEncSeg21_4 0x5c4U + +/* Segment 22 */ +#define BASE_HEncSeg22_1 0x5c8U +#define BASE_HEncSeg22_2 0x5ccU +#define BASE_HEncSeg22_3 0x5d0U +#define BASE_HEncSeg22_4 0x5d4U + +/* Segment 23 */ +#define BASE_HEncSeg23_1 0x5d8U +#define BASE_HEncSeg23_2 0x5dcU +#define BASE_HEncSeg23_3 0x5e0U +#define BASE_HEncSeg23_4 0x5e4U + +/* Segment 24 */ +#define BASE_HEncSeg24_1 0x5e8U +#define BASE_HEncSeg24_2 0x5ecU +#define BASE_HEncSeg24_3 0x5f0U +#define BASE_HEncSeg24_4 0x5f4U + +/* Segment 25 */ +#define BASE_HEncSeg25_1 0x5f8U +#define BASE_HEncSeg25_2 0x5fcU +#define BASE_HEncSeg25_3 0x600U +#define BASE_HEncSeg25_4 0x604U + +/* Segment 26 */ +#define BASE_HEncSeg26_1 0x608U +#define BASE_HEncSeg26_2 0x60cU +#define BASE_HEncSeg26_3 0x610U +#define BASE_HEncSeg26_4 0x614U + +/* Segment 27 */ +#define BASE_HEncSeg27_1 0x618U +#define BASE_HEncSeg27_2 0x61cU +#define BASE_HEncSeg27_3 0x620U +#define BASE_HEncSeg27_4 0x624U + +/* Segment 28 */ +#define BASE_HEncSeg28_1 0x628U +#define BASE_HEncSeg28_2 0x62cU +#define BASE_HEncSeg28_3 0x630U +#define BASE_HEncSeg28_4 0x634U + +/* Segment 29 */ +#define BASE_HEncSeg29_1 0x638U +#define BASE_HEncSeg29_2 0x63cU +#define BASE_HEncSeg29_3 0x640U +#define BASE_HEncSeg29_4 0x644U + +/* Segment 30 */ +#define BASE_HEncSeg30_1 0x648U +#define BASE_HEncSeg30_2 0x64cU +#define BASE_HEncSeg30_3 0x650U +#define BASE_HEncSeg30_4 0x654U + +/* Segment 31 */ +#define BASE_HEncSeg31_1 0x658U +#define BASE_HEncSeg31_2 0x65cU +#define BASE_HEncSeg31_3 0x660U +#define BASE_HEncSeg31_4 0x664U + +/* MBRC Control registers */ +#define BASE_HEncMBRcControl 0x668U +#define BASE_HEncMBQpDeltaGain 0x66cU + +/* HEncMBComplexity */ +#define BASE_HEncMBComplexity 0x670U + +/* Reference Frame Compression */ +#define BASE_HEncRfcControl 0x674U +#define BASE_HEncBaseRefLumTbl 0x678U +#define BASE_HEncBaseRefChrTbl 0x67cU +#define BASE_HEncBaseRecLumTbl 0x680U +#define BASE_HEncBaseRecChrTbl 0x684U +#define BASE_HEncBaseRefLumTbl2 0x688U +#define BASE_HEncBaseRefChrTbl2 0x68cU +#define BASE_HEncRfcChrBufLimit 0x690U + +/* Reference Management Commands */ +#define BASE_HEncRefReorderCmd 0x694U + +/* AXI Read ID for Input */ +#define BASE_HEncInputAxiId 0x698U + +/* MSB for 64bit address access. */ +#define BASE_HEncBaseRefLumTblMSB 0x69cU +#define BASE_HEncBaseRefChrTblMSB 0x6a0U +#define BASE_HEncBaseRecLumTblMSB 0x6a4U +#define BASE_HEncBaseRecChrTblMSB 0x6a8U +#define BASE_HEncBaseRefLumTbl2MSB 0x6acU +#define BASE_HEncBaseRefChrTbl2MSB 0x6b0U +#define BASE_HEncBaseStream_MSB 0x6b4U +#define BASE_HEncBaseControl_MSB 0x6b8U +#define BASE_HEncBaseRefLum_MSB 0x6bcU +#define BASE_HEncBaseRefChr_MSB 0x6c0U +#define BASE_HEncBaseRecLum_MSB 0x6c4U +#define BASE_HEncBaseRecChr_MSB 0x6c8U +#define BASE_HEncBaseInLum_MSB 0x6ccU +#define BASE_HEncBaseInCb_MSB 0x6d0U +#define BASE_HEncBaseInCr_MSB 0x6d4U +#define BASE_HEncBaseRefLum2_MSB 0x6d8U +#define BASE_HEncBaseRefChr2_MSB 0x6dcU +#define BASE_HEncH264BaseRefLum2_MSB 0x6e0U +#define BASE_HEncH264BaseRefChr2_MSB 0x6e4U +#define BASE_HEncBaseNextLum_MSB 0x6e8U +#define BASE_HEncBaseCabacCtx_MSB 0x6ecU +#define BASE_HEncBaseMvWrite_MSB 0x6f0U +#define BASE_HEncBasePartition1_MSB 0x6f4U +#define BASE_HEncBasePartition2_MSB 0x6f8U +#define BASE_HEncBaseVp8ProbCount_MSB 0x6fcU +#define BASE_HEncBaseVp8SegmentMap_MSB 0x700U +#define BASE_HEncBaseScaledOutLum_MSB 0x704U +#define BASE_HEncBasePartition3_MSB 0x708U +#define BASE_HEncBasePartition4_MSB 0x70cU + +/* Denoise Filter Control. */ +#define BASE_HEncDnfControl 0x710U +#define BASE_HEncDnfNoiseMax 0x714U +#define BASE_HEncDnfNoiseLevel 0x718U +#define BASE_HEncDnfNoisePred 0x71cU +#define BASE_HEncDnfThresholdPred 0x720U + +/* Denoise Filter Parameters. */ +#define BASE_HEncDnfParaS1G1 0x724U +#define BASE_HEncDnfParaS1G2 0x728U +#define BASE_HEncDnfParaS1G3 0x72cU +#define BASE_HEncDnfParaS1G4 0x730U +#define BASE_HEncDnfParaS2G1 0x734U +#define BASE_HEncDnfParaS2G2 0x738U +#define BASE_HEncDnfParaS2G3 0x73cU +#define BASE_HEncDnfParaS2G4 0x740U +#define BASE_HEncDnfParaS3G1 0x744U +#define BASE_HEncDnfParaS3G2 0x748U +#define BASE_HEncDnfParaS3G3 0x74cU +#define BASE_HEncDnfParaS3G4 0x750U +#define BASE_HEncDnfParaS3G5 0x754U +#define BASE_HEncDnfParaS3G6 0x758U +#define BASE_HEncDnfParaS3G7 0x75cU +#define BASE_HEncDnfParaS3G8 0x760U +#define BASE_HEncDnfParaS3G9 0x764U +#define BASE_HEncDnfParaS3G10 0x768U +#define BASE_HEncDnfParaS3G11 0x76cU +#define BASE_HEncDnfParaS3G12 0x770U +#define BASE_HEncDnfParaS3G13 0x774U +#define BASE_HEncDnfParaS3G14 0x778U +#define BASE_HEncDnfParaS3G15 0x77cU +#define BASE_HEncDnfParaS3G16 0x780U +#define BASE_HEncDnfParaS4G1 0x784U +#define BASE_HEncDnfParaS4G2 0x788U +#define BASE_HEncDnfParaS4G3 0x78cU +#define BASE_HEncDnfParaS4G4 0x790U +#define BASE_HEncDnfParaS4G5 0x794U +#define BASE_HEncDnfParaS4G6 0x798U +#define BASE_HEncDnfParaS4G7 0x79cU +#define BASE_HEncDnfParaS4G8 0x7a0U +#define BASE_HEncDnfParaS4G9 0x7a4U +#define BASE_HEncDnfParaS4G10 0x7a8U +#define BASE_HEncDnfParaS4G11 0x7acU +#define BASE_HEncDnfParaS4G12 0x7b0U +#define BASE_HEncDnfParaS4G13 0x7b4U +#define BASE_HEncDnfParaS4G14 0x7b8U +#define BASE_HEncDnfParaS4G15 0x7bcU +#define BASE_HEncDnfParaS4G16 0x7c0U + +/* Low latency and Input Line buffer. */ +#define BASE_HEncInstantInput 0x7c4U + +/* Last Fake Register for Register Counting. */ +#define BASE_HEncRegisterMax 0x7c8U + +#endif /* __HENC_REGISTER_OFFSET_H__ */ diff --git a/lib/vc8000nanoe/inc/reg_table_v7.h b/lib/vc8000nanoe/inc/reg_table_v7.h new file mode 100644 index 000000000..ad722529d --- /dev/null +++ b/lib/vc8000nanoe/inc/reg_table_v7.h @@ -0,0 +1,650 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Register table auto generated. * + * + ******************************************************************************** + */ + +/* IRQ Source Map. */ + H1REG(HEncIRQRfcBufOverflow, 0x4, 0x00000800, 11, 1, RW, "IRQ Compressed reference buffer overflow status bit."), + H1REG(HEncIRQLowLatency, 0x4, 0x00000400, 10, 0, RW, "IRQ line buffer status bit. One line buffer reading has been done."), + + +/* HW synthesis config register 2, read-only */ + H1REG(HEncHWAddress64Bits, 0x4a0, 0x80000000, 31, 0, RO, "HW Address bit width. 0=32 bits. 1=64 bits."), + H1REG(HEncHWDnfSupport, 0x4a0, 0x40000000, 30, 0, RO, "HW Denoise Support."), + H1REG(HEncHWRfcSupport, 0x4a0, 0x30000000, 28, 0, RO, "HW Reference Compression Support for Luma and Chroma."), + H1REG(HEncHWQEnhanceSupport, 0x4a0, 0x08000000, 27, 0, RO, "HW Enhancement for Quality."), + H1REG(HEncHWInstantSupport, 0x4a0, 0x04000000, 26, 0, RO, "HW Low Latency Control."), + H1REG(HEncHWSvctSupport, 0x4a0, 0x02000000, 25, 0, RO, "HW SVCT Support."), + H1REG(HEncHWAxiIdInSupport, 0x4a0, 0x01000000, 24, 0, RO, "HW AXI Read ID for Input Support."), + H1REG(HEncHWWriteOneClrIrqSupport, 0x4a0, 0x00800000, 23, 0, RO, "HW IRQ is clear in write-one way."), + H1REG(HEncHWInputLoopbackSupport, 0x4a0, 0x00400000, 22, 0, RO, "HW Input Loopback Support. not support now"), + +/* HEncMBRC Control */ + H1REG(HEncMBRCQpDeltaRange , 0x4a4, 0x07800000, 23, 0, RW, "Segment 4: Intra 16x16 mode 2 penalty"), + H1REG(HEncMBRcSliceQpOffset , 0x4a4, 0x007e0000, 17, 0, RW, "Segment 4: Intra 16x16 mode 1 penalty"), + +/* Segment 4 */ + H1REG(HEncSeg4I4PrevModeFavor , 0x4a8, 0xff000000, 24, 0, RW, "Segment 4: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg4I16Favor , 0x4a8, 0x00ffff00, 8, 0, RW, "Segment 4: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg4GoldenPenalty , 0x4a8, 0x000000ff, 0, 0, RW, "Segment 4: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg4SkipPenalty , 0x4ac, 0xff000000, 24, 0, RW, "Segment 4: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg4InterFavor , 0x4ac, 0x00ffff00, 8, 0, RW, "Segment 4: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg4SplitPenalty16x8, 0x4b0, 0x3ff00000, 20, 0, RW, "Segment 4: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg4SplitPenalty8x8 , 0x4b0, 0x000ffc00, 10, 0, RW, "Segment 4: Penalty for using 8x8 MV."), + H1REG(HEncSeg4SplitPenalty8x4 , 0x4b0, 0x000003ff, 0, 0, RW, "Segment 4: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg4DMVPenaltyQp , 0x4b4, 0x3ff00000, 20, 0, RW, "Segment 4: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg4SplitPenalty4x4 , 0x4b4, 0x000001ff, 0, 0, RW, "Segment 4: Penalty for using 4x4 MV."), + +/* Segment 5 */ + H1REG(HEncSeg5I4PrevModeFavor , 0x4b8, 0xff000000, 24, 0, RW, "Segment 5: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg5I16Favor , 0x4b8, 0x00ffff00, 8, 0, RW, "Segment 5: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg5GoldenPenalty , 0x4b8, 0x000000ff, 0, 0, RW, "Segment 5: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg5SkipPenalty , 0x4bc, 0xff000000, 24, 0, RW, "Segment 5: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg5InterFavor , 0x4bc, 0x00ffff00, 8, 0, RW, "Segment 5: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg5SplitPenalty16x8, 0x4c0, 0x3ff00000, 20, 0, RW, "Segment 5: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg5SplitPenalty8x8 , 0x4c0, 0x000ffc00, 10, 0, RW, "Segment 5: Penalty for using 8x8 MV."), + H1REG(HEncSeg5SplitPenalty8x4 , 0x4c0, 0x000003ff, 0, 0, RW, "Segment 5: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg5DMVPenaltyQp , 0x4c4, 0x3ff00000, 20, 0, RW, "Segment 5: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg5SplitPenalty4x4 , 0x4c4, 0x000001ff, 0, 0, RW, "Segment 5: Penalty for using 4x4 MV."), + +/* Segment 6 */ + H1REG(HEncSeg6I4PrevModeFavor , 0x4c8, 0xff000000, 24, 0, RW, "Segment 6: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg6I16Favor , 0x4c8, 0x00ffff00, 8, 0, RW, "Segment 6: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg6GoldenPenalty , 0x4c8, 0x000000ff, 0, 0, RW, "Segment 6: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg6SkipPenalty , 0x4cc, 0xff000000, 24, 0, RW, "Segment 6: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg6InterFavor , 0x4cc, 0x00ffff00, 8, 0, RW, "Segment 6: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg6SplitPenalty16x8, 0x4d0, 0x3ff00000, 20, 0, RW, "Segment 6: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg6SplitPenalty8x8 , 0x4d0, 0x000ffc00, 10, 0, RW, "Segment 6: Penalty for using 8x8 MV."), + H1REG(HEncSeg6SplitPenalty8x4 , 0x4d0, 0x000003ff, 0, 0, RW, "Segment 6: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg6DMVPenaltyQp , 0x4d4, 0x3ff00000, 20, 0, RW, "Segment 6: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg6SplitPenalty4x4 , 0x4d4, 0x000001ff, 0, 0, RW, "Segment 6: Penalty for using 4x4 MV."), + +/* Segment 7 */ + H1REG(HEncSeg7I4PrevModeFavor , 0x4d8, 0xff000000, 24, 0, RW, "Segment 7: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg7I16Favor , 0x4d8, 0x00ffff00, 8, 0, RW, "Segment 7: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg7GoldenPenalty , 0x4d8, 0x000000ff, 0, 0, RW, "Segment 7: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg7SkipPenalty , 0x4dc, 0xff000000, 24, 0, RW, "Segment 7: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg7InterFavor , 0x4dc, 0x00ffff00, 8, 0, RW, "Segment 7: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg7SplitPenalty16x8, 0x4e0, 0x3ff00000, 20, 0, RW, "Segment 7: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg7SplitPenalty8x8 , 0x4e0, 0x000ffc00, 10, 0, RW, "Segment 7: Penalty for using 8x8 MV."), + H1REG(HEncSeg7SplitPenalty8x4 , 0x4e0, 0x000003ff, 0, 0, RW, "Segment 7: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg7DMVPenaltyQp , 0x4e4, 0x3ff00000, 20, 0, RW, "Segment 7: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg7SplitPenalty4x4 , 0x4e4, 0x000001ff, 0, 0, RW, "Segment 7: Penalty for using 4x4 MV."), + +/* Segment 8 */ + H1REG(HEncSeg8I4PrevModeFavor , 0x4e8, 0xff000000, 24, 0, RW, "Segment 8: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg8I16Favor , 0x4e8, 0x00ffff00, 8, 0, RW, "Segment 8: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg8GoldenPenalty , 0x4e8, 0x000000ff, 0, 0, RW, "Segment 8: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg8SkipPenalty , 0x4ec, 0xff000000, 24, 0, RW, "Segment 8: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg8InterFavor , 0x4ec, 0x00ffff00, 8, 0, RW, "Segment 8: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg8SplitPenalty16x8, 0x4f0, 0x3ff00000, 20, 0, RW, "Segment 8: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg8SplitPenalty8x8 , 0x4f0, 0x000ffc00, 10, 0, RW, "Segment 8: Penalty for using 8x8 MV."), + H1REG(HEncSeg8SplitPenalty8x4 , 0x4f0, 0x000003ff, 0, 0, RW, "Segment 8: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg8DMVPenaltyQp , 0x4f4, 0x3ff00000, 20, 0, RW, "Segment 8: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg8SplitPenalty4x4 , 0x4f4, 0x000001ff, 0, 0, RW, "Segment 8: Penalty for using 4x4 MV."), + +/* Segment 9 */ + H1REG(HEncSeg9I4PrevModeFavor , 0x4f8, 0xff000000, 24, 0, RW, "Segment 9: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg9I16Favor , 0x4f8, 0x00ffff00, 8, 0, RW, "Segment 9: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg9GoldenPenalty , 0x4f8, 0x000000ff, 0, 0, RW, "Segment 9: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg9SkipPenalty , 0x4fc, 0xff000000, 24, 0, RW, "Segment 9: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg9InterFavor , 0x4fc, 0x00ffff00, 8, 0, RW, "Segment 9: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg9SplitPenalty16x8, 0x500, 0x3ff00000, 20, 0, RW, "Segment 9: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg9SplitPenalty8x8 , 0x500, 0x000ffc00, 10, 0, RW, "Segment 9: Penalty for using 8x8 MV."), + H1REG(HEncSeg9SplitPenalty8x4 , 0x500, 0x000003ff, 0, 0, RW, "Segment 9: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg9DMVPenaltyQp , 0x504, 0x3ff00000, 20, 0, RW, "Segment 9: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg9SplitPenalty4x4 , 0x504, 0x000001ff, 0, 0, RW, "Segment 9: Penalty for using 4x4 MV."), + +/* Segment 10 */ + H1REG(HEncSeg10I4PrevModeFavor , 0x508, 0xff000000, 24, 0, RW, "Segment 10: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg10I16Favor , 0x508, 0x00ffff00, 8, 0, RW, "Segment 10: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg10GoldenPenalty , 0x508, 0x000000ff, 0, 0, RW, "Segment 10: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg10SkipPenalty , 0x50c, 0xff000000, 24, 0, RW, "Segment 10: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg10InterFavor , 0x50c, 0x00ffff00, 8, 0, RW, "Segment 10: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg10SplitPenalty16x8, 0x510, 0x3ff00000, 20, 0, RW, "Segment 10: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg10SplitPenalty8x8 , 0x510, 0x000ffc00, 10, 0, RW, "Segment 10: Penalty for using 8x8 MV."), + H1REG(HEncSeg10SplitPenalty8x4 , 0x510, 0x000003ff, 0, 0, RW, "Segment 10: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg10DMVPenaltyQp , 0x514, 0x3ff00000, 20, 0, RW, "Segment 10: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg10SplitPenalty4x4 , 0x514, 0x000001ff, 0, 0, RW, "Segment 10: Penalty for using 4x4 MV."), + +/* Segment 11 */ + H1REG(HEncSeg11I4PrevModeFavor , 0x518, 0xff000000, 24, 0, RW, "Segment 11: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg11I16Favor , 0x518, 0x00ffff00, 8, 0, RW, "Segment 11: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg11GoldenPenalty , 0x518, 0x000000ff, 0, 0, RW, "Segment 11: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg11SkipPenalty , 0x51c, 0xff000000, 24, 0, RW, "Segment 11: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg11InterFavor , 0x51c, 0x00ffff00, 8, 0, RW, "Segment 11: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg11SplitPenalty16x8, 0x520, 0x3ff00000, 20, 0, RW, "Segment 11: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg11SplitPenalty8x8 , 0x520, 0x000ffc00, 10, 0, RW, "Segment 11: Penalty for using 8x8 MV."), + H1REG(HEncSeg11SplitPenalty8x4 , 0x520, 0x000003ff, 0, 0, RW, "Segment 11: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg11DMVPenaltyQp , 0x524, 0x3ff00000, 20, 0, RW, "Segment 11: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg11SplitPenalty4x4 , 0x524, 0x000001ff, 0, 0, RW, "Segment 11: Penalty for using 4x4 MV."), + +/* Segment 12 */ + H1REG(HEncSeg12I4PrevModeFavor , 0x528, 0xff000000, 24, 0, RW, "Segment 12: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg12I16Favor , 0x528, 0x00ffff00, 8, 0, RW, "Segment 12: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg12GoldenPenalty , 0x528, 0x000000ff, 0, 0, RW, "Segment 12: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg12SkipPenalty , 0x52c, 0xff000000, 24, 0, RW, "Segment 12: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg12InterFavor , 0x52c, 0x00ffff00, 8, 0, RW, "Segment 12: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg12SplitPenalty16x8, 0x530, 0x3ff00000, 20, 0, RW, "Segment 12: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg12SplitPenalty8x8 , 0x530, 0x000ffc00, 10, 0, RW, "Segment 12: Penalty for using 8x8 MV."), + H1REG(HEncSeg12SplitPenalty8x4 , 0x530, 0x000003ff, 0, 0, RW, "Segment 12: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg12DMVPenaltyQp , 0x534, 0x3ff00000, 20, 0, RW, "Segment 12: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg12SplitPenalty4x4 , 0x534, 0x000001ff, 0, 0, RW, "Segment 12: Penalty for using 4x4 MV."), + +/* Segment 13 */ + H1REG(HEncSeg13I4PrevModeFavor , 0x538, 0xff000000, 24, 0, RW, "Segment 13: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg13I16Favor , 0x538, 0x00ffff00, 8, 0, RW, "Segment 13: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg13GoldenPenalty , 0x538, 0x000000ff, 0, 0, RW, "Segment 13: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg13SkipPenalty , 0x53c, 0xff000000, 24, 0, RW, "Segment 13: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg13InterFavor , 0x53c, 0x00ffff00, 8, 0, RW, "Segment 13: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg13SplitPenalty16x8, 0x540, 0x3ff00000, 20, 0, RW, "Segment 13: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg13SplitPenalty8x8 , 0x540, 0x000ffc00, 10, 0, RW, "Segment 13: Penalty for using 8x8 MV."), + H1REG(HEncSeg13SplitPenalty8x4 , 0x540, 0x000003ff, 0, 0, RW, "Segment 13: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg13DMVPenaltyQp , 0x544, 0x3ff00000, 20, 0, RW, "Segment 13: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg13SplitPenalty4x4 , 0x544, 0x000001ff, 0, 0, RW, "Segment 13: Penalty for using 4x4 MV."), + +/* Segment 14 */ + H1REG(HEncSeg14I4PrevModeFavor , 0x548, 0xff000000, 24, 0, RW, "Segment 14: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg14I16Favor , 0x548, 0x00ffff00, 8, 0, RW, "Segment 14: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg14GoldenPenalty , 0x548, 0x000000ff, 0, 0, RW, "Segment 14: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg14SkipPenalty , 0x54c, 0xff000000, 24, 0, RW, "Segment 14: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg14InterFavor , 0x54c, 0x00ffff00, 8, 0, RW, "Segment 14: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg14SplitPenalty16x8, 0x550, 0x3ff00000, 20, 0, RW, "Segment 14: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg14SplitPenalty8x8 , 0x550, 0x000ffc00, 10, 0, RW, "Segment 14: Penalty for using 8x8 MV."), + H1REG(HEncSeg14SplitPenalty8x4 , 0x550, 0x000003ff, 0, 0, RW, "Segment 14: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg14DMVPenaltyQp , 0x554, 0x3ff00000, 20, 0, RW, "Segment 14: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg14SplitPenalty4x4 , 0x554, 0x000001ff, 0, 0, RW, "Segment 14: Penalty for using 4x4 MV."), + +/* Segment 15 */ + H1REG(HEncSeg15I4PrevModeFavor , 0x558, 0xff000000, 24, 0, RW, "Segment 15: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg15I16Favor , 0x558, 0x00ffff00, 8, 0, RW, "Segment 15: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg15GoldenPenalty , 0x558, 0x000000ff, 0, 0, RW, "Segment 15: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg15SkipPenalty , 0x55c, 0xff000000, 24, 0, RW, "Segment 15: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg15InterFavor , 0x55c, 0x00ffff00, 8, 0, RW, "Segment 15: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg15SplitPenalty16x8, 0x560, 0x3ff00000, 20, 0, RW, "Segment 15: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg15SplitPenalty8x8 , 0x560, 0x000ffc00, 10, 0, RW, "Segment 15: Penalty for using 8x8 MV."), + H1REG(HEncSeg15SplitPenalty8x4 , 0x560, 0x000003ff, 0, 0, RW, "Segment 15: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg15DMVPenaltyQp , 0x564, 0x3ff00000, 20, 0, RW, "Segment 15: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg15SplitPenalty4x4 , 0x564, 0x000001ff, 0, 0, RW, "Segment 15: Penalty for using 4x4 MV."), + +/* Segment 16 */ + H1REG(HEncSeg16I4PrevModeFavor , 0x568, 0xff000000, 24, 0, RW, "Segment 16: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg16I16Favor , 0x568, 0x00ffff00, 8, 0, RW, "Segment 16: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg16GoldenPenalty , 0x568, 0x000000ff, 0, 0, RW, "Segment 16: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg16SkipPenalty , 0x56c, 0xff000000, 24, 0, RW, "Segment 16: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg16InterFavor , 0x56c, 0x00ffff00, 8, 0, RW, "Segment 16: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg16SplitPenalty16x8, 0x570, 0x3ff00000, 20, 0, RW, "Segment 16: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg16SplitPenalty8x8 , 0x570, 0x000ffc00, 10, 0, RW, "Segment 16: Penalty for using 8x8 MV."), + H1REG(HEncSeg16SplitPenalty8x4 , 0x570, 0x000003ff, 0, 0, RW, "Segment 16: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg16DMVPenaltyQp , 0x574, 0x3ff00000, 20, 0, RW, "Segment 16: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg16SplitPenalty4x4 , 0x574, 0x000001ff, 0, 0, RW, "Segment 16: Penalty for using 4x4 MV."), + +/* Segment 17 */ + H1REG(HEncSeg17I4PrevModeFavor , 0x578, 0xff000000, 24, 0, RW, "Segment 17: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg17I16Favor , 0x578, 0x00ffff00, 8, 0, RW, "Segment 17: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg17GoldenPenalty , 0x578, 0x000000ff, 0, 0, RW, "Segment 17: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg17SkipPenalty , 0x57c, 0xff000000, 24, 0, RW, "Segment 17: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg17InterFavor , 0x57c, 0x00ffff00, 8, 0, RW, "Segment 17: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg17SplitPenalty16x8, 0x580, 0x3ff00000, 20, 0, RW, "Segment 17: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg17SplitPenalty8x8 , 0x580, 0x000ffc00, 10, 0, RW, "Segment 17: Penalty for using 8x8 MV."), + H1REG(HEncSeg17SplitPenalty8x4 , 0x580, 0x000003ff, 0, 0, RW, "Segment 17: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg17DMVPenaltyQp , 0x584, 0x3ff00000, 20, 0, RW, "Segment 17: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg17SplitPenalty4x4 , 0x584, 0x000001ff, 0, 0, RW, "Segment 17: Penalty for using 4x4 MV."), + +/* Segment 18 */ + H1REG(HEncSeg18I4PrevModeFavor , 0x588, 0xff000000, 24, 0, RW, "Segment 18: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg18I16Favor , 0x588, 0x00ffff00, 8, 0, RW, "Segment 18: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg18GoldenPenalty , 0x588, 0x000000ff, 0, 0, RW, "Segment 18: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg18SkipPenalty , 0x58c, 0xff000000, 24, 0, RW, "Segment 18: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg18InterFavor , 0x58c, 0x00ffff00, 8, 0, RW, "Segment 18: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg18SplitPenalty16x8, 0x590, 0x3ff00000, 20, 0, RW, "Segment 18: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg18SplitPenalty8x8 , 0x590, 0x000ffc00, 10, 0, RW, "Segment 18: Penalty for using 8x8 MV."), + H1REG(HEncSeg18SplitPenalty8x4 , 0x590, 0x000003ff, 0, 0, RW, "Segment 18: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg18DMVPenaltyQp , 0x594, 0x3ff00000, 20, 0, RW, "Segment 18: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg18SplitPenalty4x4 , 0x594, 0x000001ff, 0, 0, RW, "Segment 18: Penalty for using 4x4 MV."), + +/* Segment 19 */ + H1REG(HEncSeg19I4PrevModeFavor , 0x598, 0xff000000, 24, 0, RW, "Segment 19: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg19I16Favor , 0x598, 0x00ffff00, 8, 0, RW, "Segment 19: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg19GoldenPenalty , 0x598, 0x000000ff, 0, 0, RW, "Segment 19: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg19SkipPenalty , 0x59c, 0xff000000, 24, 0, RW, "Segment 19: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg19InterFavor , 0x59c, 0x00ffff00, 8, 0, RW, "Segment 19: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg19SplitPenalty16x8, 0x5a0, 0x3ff00000, 20, 0, RW, "Segment 19: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg19SplitPenalty8x8 , 0x5a0, 0x000ffc00, 10, 0, RW, "Segment 19: Penalty for using 8x8 MV."), + H1REG(HEncSeg19SplitPenalty8x4 , 0x5a0, 0x000003ff, 0, 0, RW, "Segment 19: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg19DMVPenaltyQp , 0x5a4, 0x3ff00000, 20, 0, RW, "Segment 19: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg19SplitPenalty4x4 , 0x5a4, 0x000001ff, 0, 0, RW, "Segment 19: Penalty for using 4x4 MV."), + +/* Segment 20 */ + H1REG(HEncSeg20I4PrevModeFavor , 0x5a8, 0xff000000, 24, 0, RW, "Segment 20: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg20I16Favor , 0x5a8, 0x00ffff00, 8, 0, RW, "Segment 20: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg20GoldenPenalty , 0x5a8, 0x000000ff, 0, 0, RW, "Segment 20: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg20SkipPenalty , 0x5ac, 0xff000000, 24, 0, RW, "Segment 20: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg20InterFavor , 0x5ac, 0x00ffff00, 8, 0, RW, "Segment 20: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg20SplitPenalty16x8, 0x5b0, 0x3ff00000, 20, 0, RW, "Segment 20: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg20SplitPenalty8x8 , 0x5b0, 0x000ffc00, 10, 0, RW, "Segment 20: Penalty for using 8x8 MV."), + H1REG(HEncSeg20SplitPenalty8x4 , 0x5b0, 0x000003ff, 0, 0, RW, "Segment 20: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg20DMVPenaltyQp , 0x5b4, 0x3ff00000, 20, 0, RW, "Segment 20: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg20SplitPenalty4x4 , 0x5b4, 0x000001ff, 0, 0, RW, "Segment 20: Penalty for using 4x4 MV."), + +/* Segment 21 */ + H1REG(HEncSeg21I4PrevModeFavor , 0x5b8, 0xff000000, 24, 0, RW, "Segment 21: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg21I16Favor , 0x5b8, 0x00ffff00, 8, 0, RW, "Segment 21: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg21GoldenPenalty , 0x5b8, 0x000000ff, 0, 0, RW, "Segment 21: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg21SkipPenalty , 0x5bc, 0xff000000, 24, 0, RW, "Segment 21: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg21InterFavor , 0x5bc, 0x00ffff00, 8, 0, RW, "Segment 21: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg21SplitPenalty16x8, 0x5c0, 0x3ff00000, 20, 0, RW, "Segment 21: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg21SplitPenalty8x8 , 0x5c0, 0x000ffc00, 10, 0, RW, "Segment 21: Penalty for using 8x8 MV."), + H1REG(HEncSeg21SplitPenalty8x4 , 0x5c0, 0x000003ff, 0, 0, RW, "Segment 21: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg21DMVPenaltyQp , 0x5c4, 0x3ff00000, 20, 0, RW, "Segment 21: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg21SplitPenalty4x4 , 0x5c4, 0x000001ff, 0, 0, RW, "Segment 21: Penalty for using 4x4 MV."), + +/* Segment 22 */ + H1REG(HEncSeg22I4PrevModeFavor , 0x5c8, 0xff000000, 24, 0, RW, "Segment 22: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg22I16Favor , 0x5c8, 0x00ffff00, 8, 0, RW, "Segment 22: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg22GoldenPenalty , 0x5c8, 0x000000ff, 0, 0, RW, "Segment 22: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg22SkipPenalty , 0x5cc, 0xff000000, 24, 0, RW, "Segment 22: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg22InterFavor , 0x5cc, 0x00ffff00, 8, 0, RW, "Segment 22: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg22SplitPenalty16x8, 0x5d0, 0x3ff00000, 20, 0, RW, "Segment 22: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg22SplitPenalty8x8 , 0x5d0, 0x000ffc00, 10, 0, RW, "Segment 22: Penalty for using 8x8 MV."), + H1REG(HEncSeg22SplitPenalty8x4 , 0x5d0, 0x000003ff, 0, 0, RW, "Segment 22: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg22DMVPenaltyQp , 0x5d4, 0x3ff00000, 20, 0, RW, "Segment 22: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg22SplitPenalty4x4 , 0x5d4, 0x000001ff, 0, 0, RW, "Segment 22: Penalty for using 4x4 MV."), + +/* Segment 23 */ + H1REG(HEncSeg23I4PrevModeFavor , 0x5d8, 0xff000000, 24, 0, RW, "Segment 23: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg23I16Favor , 0x5d8, 0x00ffff00, 8, 0, RW, "Segment 23: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg23GoldenPenalty , 0x5d8, 0x000000ff, 0, 0, RW, "Segment 23: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg23SkipPenalty , 0x5dc, 0xff000000, 24, 0, RW, "Segment 23: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg23InterFavor , 0x5dc, 0x00ffff00, 8, 0, RW, "Segment 23: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg23SplitPenalty16x8, 0x5e0, 0x3ff00000, 20, 0, RW, "Segment 23: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg23SplitPenalty8x8 , 0x5e0, 0x000ffc00, 10, 0, RW, "Segment 23: Penalty for using 8x8 MV."), + H1REG(HEncSeg23SplitPenalty8x4 , 0x5e0, 0x000003ff, 0, 0, RW, "Segment 23: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg23DMVPenaltyQp , 0x5e4, 0x3ff00000, 20, 0, RW, "Segment 23: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg23SplitPenalty4x4 , 0x5e4, 0x000001ff, 0, 0, RW, "Segment 23: Penalty for using 4x4 MV."), + +/* Segment 24 */ + H1REG(HEncSeg24I4PrevModeFavor , 0x5e8, 0xff000000, 24, 0, RW, "Segment 24: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg24I16Favor , 0x5e8, 0x00ffff00, 8, 0, RW, "Segment 24: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg24GoldenPenalty , 0x5e8, 0x000000ff, 0, 0, RW, "Segment 24: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg24SkipPenalty , 0x5ec, 0xff000000, 24, 0, RW, "Segment 24: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg24InterFavor , 0x5ec, 0x00ffff00, 8, 0, RW, "Segment 24: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg24SplitPenalty16x8, 0x5f0, 0x3ff00000, 20, 0, RW, "Segment 24: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg24SplitPenalty8x8 , 0x5f0, 0x000ffc00, 10, 0, RW, "Segment 24: Penalty for using 8x8 MV."), + H1REG(HEncSeg24SplitPenalty8x4 , 0x5f0, 0x000003ff, 0, 0, RW, "Segment 24: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg24DMVPenaltyQp , 0x5f4, 0x3ff00000, 20, 0, RW, "Segment 24: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg24SplitPenalty4x4 , 0x5f4, 0x000001ff, 0, 0, RW, "Segment 24: Penalty for using 4x4 MV."), + +/* Segment 25 */ + H1REG(HEncSeg25I4PrevModeFavor , 0x5f8, 0xff000000, 24, 0, RW, "Segment 25: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg25I16Favor , 0x5f8, 0x00ffff00, 8, 0, RW, "Segment 25: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg25GoldenPenalty , 0x5f8, 0x000000ff, 0, 0, RW, "Segment 25: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg25SkipPenalty , 0x5fc, 0xff000000, 24, 0, RW, "Segment 25: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg25InterFavor , 0x5fc, 0x00ffff00, 8, 0, RW, "Segment 25: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg25SplitPenalty16x8, 0x600, 0x3ff00000, 20, 0, RW, "Segment 25: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg25SplitPenalty8x8 , 0x600, 0x000ffc00, 10, 0, RW, "Segment 25: Penalty for using 8x8 MV."), + H1REG(HEncSeg25SplitPenalty8x4 , 0x600, 0x000003ff, 0, 0, RW, "Segment 25: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg25DMVPenaltyQp , 0x604, 0x3ff00000, 20, 0, RW, "Segment 25: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg25SplitPenalty4x4 , 0x604, 0x000001ff, 0, 0, RW, "Segment 25: Penalty for using 4x4 MV."), + +/* Segment 26 */ + H1REG(HEncSeg26I4PrevModeFavor , 0x608, 0xff000000, 24, 0, RW, "Segment 26: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg26I16Favor , 0x608, 0x00ffff00, 8, 0, RW, "Segment 26: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg26GoldenPenalty , 0x608, 0x000000ff, 0, 0, RW, "Segment 26: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg26SkipPenalty , 0x60c, 0xff000000, 24, 0, RW, "Segment 26: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg26InterFavor , 0x60c, 0x00ffff00, 8, 0, RW, "Segment 26: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg26SplitPenalty16x8, 0x610, 0x3ff00000, 20, 0, RW, "Segment 26: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg26SplitPenalty8x8 , 0x610, 0x000ffc00, 10, 0, RW, "Segment 26: Penalty for using 8x8 MV."), + H1REG(HEncSeg26SplitPenalty8x4 , 0x610, 0x000003ff, 0, 0, RW, "Segment 26: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg26DMVPenaltyQp , 0x614, 0x3ff00000, 20, 0, RW, "Segment 26: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg26SplitPenalty4x4 , 0x614, 0x000001ff, 0, 0, RW, "Segment 26: Penalty for using 4x4 MV."), + +/* Segment 27 */ + H1REG(HEncSeg27I4PrevModeFavor , 0x618, 0xff000000, 24, 0, RW, "Segment 27: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg27I16Favor , 0x618, 0x00ffff00, 8, 0, RW, "Segment 27: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg27GoldenPenalty , 0x618, 0x000000ff, 0, 0, RW, "Segment 27: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg27SkipPenalty , 0x61c, 0xff000000, 24, 0, RW, "Segment 27: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg27InterFavor , 0x61c, 0x00ffff00, 8, 0, RW, "Segment 27: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg27SplitPenalty16x8, 0x620, 0x3ff00000, 20, 0, RW, "Segment 27: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg27SplitPenalty8x8 , 0x620, 0x000ffc00, 10, 0, RW, "Segment 27: Penalty for using 8x8 MV."), + H1REG(HEncSeg27SplitPenalty8x4 , 0x620, 0x000003ff, 0, 0, RW, "Segment 27: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg27DMVPenaltyQp , 0x624, 0x3ff00000, 20, 0, RW, "Segment 27: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg27SplitPenalty4x4 , 0x624, 0x000001ff, 0, 0, RW, "Segment 27: Penalty for using 4x4 MV."), + +/* Segment 28 */ + H1REG(HEncSeg28I4PrevModeFavor , 0x628, 0xff000000, 24, 0, RW, "Segment 28: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg28I16Favor , 0x628, 0x00ffff00, 8, 0, RW, "Segment 28: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg28GoldenPenalty , 0x628, 0x000000ff, 0, 0, RW, "Segment 28: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg28SkipPenalty , 0x62c, 0xff000000, 24, 0, RW, "Segment 28: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg28InterFavor , 0x62c, 0x00ffff00, 8, 0, RW, "Segment 28: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg28SplitPenalty16x8, 0x630, 0x3ff00000, 20, 0, RW, "Segment 28: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg28SplitPenalty8x8 , 0x630, 0x000ffc00, 10, 0, RW, "Segment 28: Penalty for using 8x8 MV."), + H1REG(HEncSeg28SplitPenalty8x4 , 0x630, 0x000003ff, 0, 0, RW, "Segment 28: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg28DMVPenaltyQp , 0x634, 0x3ff00000, 20, 0, RW, "Segment 28: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg28SplitPenalty4x4 , 0x634, 0x000001ff, 0, 0, RW, "Segment 28: Penalty for using 4x4 MV."), + +/* Segment 29 */ + H1REG(HEncSeg29I4PrevModeFavor , 0x638, 0xff000000, 24, 0, RW, "Segment 29: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg29I16Favor , 0x638, 0x00ffff00, 8, 0, RW, "Segment 29: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg29GoldenPenalty , 0x638, 0x000000ff, 0, 0, RW, "Segment 29: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg29SkipPenalty , 0x63c, 0xff000000, 24, 0, RW, "Segment 29: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg29InterFavor , 0x63c, 0x00ffff00, 8, 0, RW, "Segment 29: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg29SplitPenalty16x8, 0x640, 0x3ff00000, 20, 0, RW, "Segment 29: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg29SplitPenalty8x8 , 0x640, 0x000ffc00, 10, 0, RW, "Segment 29: Penalty for using 8x8 MV."), + H1REG(HEncSeg29SplitPenalty8x4 , 0x640, 0x000003ff, 0, 0, RW, "Segment 29: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg29DMVPenaltyQp , 0x644, 0x3ff00000, 20, 0, RW, "Segment 29: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg29SplitPenalty4x4 , 0x644, 0x000001ff, 0, 0, RW, "Segment 29: Penalty for using 4x4 MV."), + +/* Segment 30 */ + H1REG(HEncSeg30I4PrevModeFavor , 0x648, 0xff000000, 24, 0, RW, "Segment 30: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg30I16Favor , 0x648, 0x00ffff00, 8, 0, RW, "Segment 30: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg30GoldenPenalty , 0x648, 0x000000ff, 0, 0, RW, "Segment 30: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg30SkipPenalty , 0x64c, 0xff000000, 24, 0, RW, "Segment 30: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg30InterFavor , 0x64c, 0x00ffff00, 8, 0, RW, "Segment 30: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg30SplitPenalty16x8, 0x650, 0x3ff00000, 20, 0, RW, "Segment 30: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg30SplitPenalty8x8 , 0x650, 0x000ffc00, 10, 0, RW, "Segment 30: Penalty for using 8x8 MV."), + H1REG(HEncSeg30SplitPenalty8x4 , 0x650, 0x000003ff, 0, 0, RW, "Segment 30: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg30DMVPenaltyQp , 0x654, 0x3ff00000, 20, 0, RW, "Segment 30: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg30SplitPenalty4x4 , 0x654, 0x000001ff, 0, 0, RW, "Segment 30: Penalty for using 4x4 MV."), + +/* Segment 31 */ + H1REG(HEncSeg31I4PrevModeFavor , 0x658, 0xff000000, 24, 0, RW, "Segment 31: Intra 4x4 previous mode favor for H.264"), + H1REG(HEncSeg31I16Favor , 0x658, 0x00ffff00, 8, 0, RW, "Segment 31: Intra 16x16 mode favor in intra 16x16/4x4 selection"), + H1REG(HEncSeg31GoldenPenalty , 0x658, 0x000000ff, 0, 0, RW, "Segment 31: Penalty value for second reference frame zero-mv. VP8 golden / H.264 LTR. [0..255]"), + H1REG(HEncSeg31SkipPenalty , 0x65c, 0xff000000, 24, 0, RW, "Segment 31: Skip mode (zero/nearest/near) penalty"), + H1REG(HEncSeg31InterFavor , 0x65c, 0x00ffff00, 8, 0, RW, "Segment 31: Inter MB mode favor in intra/inter selection"), + H1REG(HEncSeg31SplitPenalty16x8, 0x660, 0x3ff00000, 20, 0, RW, "Segment 31: Penalty for using 16x8 or 8x16 MV."), + H1REG(HEncSeg31SplitPenalty8x8 , 0x660, 0x000ffc00, 10, 0, RW, "Segment 31: Penalty for using 8x8 MV."), + H1REG(HEncSeg31SplitPenalty8x4 , 0x660, 0x000003ff, 0, 0, RW, "Segment 31: Penalty for using 8x4 or 4x8 MV."), + H1REG(HEncSeg31DMVPenaltyQp , 0x664, 0x3ff00000, 20, 0, RW, "Segment 31: Differential MV penalty for 1/4p ME. DMVPenaltyQp"), + H1REG(HEncSeg31SplitPenalty4x4 , 0x664, 0x000001ff, 0, 0, RW, "Segment 31: Penalty for using 4x4 MV."), + +/* MBRC Control registers */ + H1REG(HEncMBRCQpFrac , 0x668, 0xffff0000, 16, 0, RW, "fractional part of frame qp. .16 format"), + H1REG(HEncMBComplexityOffset , 0x668, 0x00000f80, 7, 0, RW, "offset of MB complexity"), + H1REG(HEncMBRCEnable , 0x668, 0x00000003, 0, 0, RW, "MB RC Enable 0 = disable 1 = enable"), + H1REG(HEncMBQpDeltaGain , 0x66c, 0x0000ffff, 0, 0, RW, "gain of MB qp delta. 8.8 format"), + +/* HEncMBComplexity */ + H1REG(HEncMBComplexityAverage , 0x670, 0xffffffff, 0, 0, RW, "average of MB complexity"), + +/* Reference Frame Compression */ + H1REG(HEncRfcLumBufLimit , 0x674, 0xfffff800, 11, 1, RW, "Limit of luma RFC buffer in unit of 64-bit. 0 indicating no limit. Send an IRQ if overflow."), + H1REG(HEncRfcIntEn , 0x674, 0x00000008, 3, 1, RW, "RFC overflow IRQ Enable. 0=Disable. 1=Enable"), + H1REG(HEncRfcLumDiscreteMode , 0x674, 0x00000004, 2, 0, RW, "Reference Compression in discrete storage mode. 0=OFF. 1=ON"), + H1REG(HEncRefChrCompress , 0x674, 0x00000002, 1, 0, RW, "Reference Frame Chroma Compression. 0=OFF. 1=ON"), + H1REG(HEncRefLumCompress , 0x674, 0x00000001, 0, 0, RW, "Reference Frame Luma Compression. 0=OFF. 1=ON"), + H1REG(HEncBaseRefLumTbl , 0x678, 0xffffffff, 0, 0, RW, "Base address for reference luma compression table"), + H1REG(HEncBaseRefChrTbl , 0x67c, 0xffffffff, 0, 0, RW, "Base address for reference chroma compression table"), + H1REG(HEncBaseRecLumTbl , 0x680, 0xffffffff, 0, 0, RW, "Base address for reconstructed luma compression table"), + H1REG(HEncBaseRecChrTbl , 0x684, 0xffffffff, 0, 0, RW, "Base address for reconstructed chroma compression table"), + H1REG(HEncBaseRefLumTbl2 , 0x688, 0xffffffff, 0, 0, RW, "Base address for second reference luma compression table"), + H1REG(HEncBaseRefChrTbl2 , 0x68c, 0xffffffff, 0, 0, RW, "Base address for second reference chroma compression table"), + H1REG(HEncRfcChrBufLimit , 0x690, 0xfffff000, 12, 1, RW, "Limit of chroma RFC buffer in unit of 64-bit. 0 indicating no limit. Send an IRQ if overflow."), + +/* Reference Management Commands */ + H1REG(HEncRefReorderFlag , 0x694, 0x80000000, 31, 1, RW, "Modification Flag of Pic Nums."), + H1REG(HEncRefReorderDiffPicNum, 0x694, 0x7c000000, 26, 1, RW, "Modification Absolute Diff Pic Nums."), + +/* AXI Read ID for Input */ + H1REG(HEncAXIReadIDInC0, 0x698, 0xff000000, 24, 1, RW, "AXI Read ID for Input Channel 0."), + H1REG(HEncAXIReadIDInC1, 0x698, 0x00ff0000, 16, 1, RW, "AXI Read ID for Input Channel 1."), + H1REG(HEncAXIReadIDInC2, 0x698, 0x0000ff00, 8, 1, RW, "AXI Read ID for Input Channel 2."), + H1REG(HEncAXIReadIDEnable, 0x698, 0x00000001, 0, 1, RW, "Enable AXI Read ID and different burst."), + +/* MSB for 64bit address access. */ + H1REG(HEncBaseRefLumTbl_MSB, 0x69c, 0xffffffff, 0, 0, RW, "Base address MSB for reference luma compression table."), + H1REG(HEncBaseRefChrTbl_MSB, 0x6a0, 0xffffffff, 0, 0, RW, "Base address MSB for reference chroma compression table"), + H1REG(HEncBaseRecLumTbl_MSB, 0x6a4, 0xffffffff, 0, 0, RW, "Base address MSB for reconstructed luma compression table"), + H1REG(HEncBaseRecChrTbl_MSB, 0x6a8, 0xffffffff, 0, 0, RW, "Base address for reconstructed chroma compression table"), + H1REG(HEncBaseRefLumTbl2_MSB, 0x6ac, 0xffffffff, 0, 0, RW, "Base address MSB for second reference luma compression table"), + H1REG(HEncBaseRefChrTbl2_MSB, 0x6b0, 0xffffffff, 0, 0, RW, "Base address MSB for second reference chroma compression table"), + H1REG(HEncBaseStream_MSB, 0x6b4, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for output stream data"), + H1REG(HEncBaseControl_MSB, 0x6b8, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for output control data"), + H1REG(HEncBaseRefLum_MSB, 0x6bc, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for reference luma"), + H1REG(HEncBaseRefChr_MSB, 0x6c0, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for reference chroma"), + H1REG(HEncBaseRecLum_MSB, 0x6c4, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for reconstructed luma"), + H1REG(HEncBaseRecChr_MSB, 0x6c8, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for reconstructed chroma"), + H1REG(HEncBaseInLum_MSB, 0x6cc, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for input picture luma"), + H1REG(HEncBaseInCb_MSB, 0x6d0, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for input picture cb"), + H1REG(HEncBaseInCr_MSB, 0x6d4, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for input picture cr"), + H1REG(HEncBaseRefLum2_MSB, 0x6d8, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for second reference luma"), + H1REG(HEncBaseRefChr2_MSB, 0x6dc, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for second reference chroma"), + H1REG(HEncH264BaseRefLum2_MSB, 0x6e0, 0xffffffff, 0, 0, RW, "high 32 bits of H264 secondary ref pic base"), + H1REG(HEncH264BaseRefChr2_MSB, 0x6e4, 0xffffffff, 0, 0, RW, "high 32 bits of H264 secondary ref pic base"), + H1REG(HEncBaseNextLum_MSB, 0x6e8, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for next pic luminance"), + H1REG(HEncBaseCabacCtx_MSB, 0x6ec, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for cabac context tables (H264) or probability tables (VP8)"), + H1REG(HEncBaseMvWrite_MSB, 0x6f0, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for MV output writing"), + H1REG(HEncBasePartition1_MSB, 0x6f4, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for VP8 1st DCT partition"), + H1REG(HEncBasePartition2_MSB, 0x6f8, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for VP8 2nd DCT partition"), + H1REG(HEncBaseVp8ProbCount_MSB, 0x6fc, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for VP8 counters for probability updates"), + H1REG(HEncBaseVp8SegmentMap_MSB, 0x700, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for VP8 segmentation map. segmentId 2-bits/macroblock"), + H1REG(HEncBaseScaledOutLum_MSB, 0x704, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for output of down-scaled encoder image in YUYV 4:2:2 format"), + H1REG(HEncBasePartition3_MSB, 0x708, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for VP8 3rd DCT partition"), + H1REG(HEncBasePartition4_MSB, 0x70c, 0xffffffff, 0, 0, RW, "high 32 bits of Base address for VP8 4th DCT partition"), + +/* Denoise Filter Control. */ + H1REG(HEncDnfEnable, 0x710, 0x80000000, 31, 0, RW, "Enable/disable the de-noise function"), + H1REG(HEncDnfStregth, 0x710, 0x07ff0000, 16, 0, RW, "Denoise filter strength"), + H1REG(HEncDnfMbNum, 0x710, 0x0000ffff, 0, 0, RW, "Number of Noisy MB"), + H1REG(HEncDnfNoiseMax, 0x714, 0x0000ffff, 0, 0, RW, "Max noise level"), + H1REG(HEncDnfNoiseLevelInvC, 0x718, 0x0fff0000, 16, 0, RW, "Noise level inverted for chroma"), + H1REG(HEncDnfNoiseLevelInvY, 0x718, 0x00000fff, 0, 0, RW, "Noise level inverted for luma"), + H1REG(HEncDnfNoisePred, 0x71c, 0xffffffff, 0, 0, RW, "calculated sigma of coding frame"), + H1REG(HEncDnfThresholdPred, 0x720, 0xffffffff, 0, 0, RW, "noise sigma for current frame"), + +/* Denoise Filter Parameters. */ + H1REG(HEncDnfParaS1_0, 0x724, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 1, No.0."), + H1REG(HEncDnfParaS1_1, 0x724, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 1, No.1."), + H1REG(HEncDnfParaS1_2, 0x724, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 1, No.2."), + H1REG(HEncDnfParaS1_3, 0x724, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 1, No.3."), + H1REG(HEncDnfParaS1_4, 0x728, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 1, No.4."), + H1REG(HEncDnfParaS1_5, 0x728, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 1, No.5."), + H1REG(HEncDnfParaS1_6, 0x728, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 1, No.6."), + H1REG(HEncDnfParaS1_7, 0x728, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 1, No.7."), + H1REG(HEncDnfParaS1_8, 0x72c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 1, No.8."), + H1REG(HEncDnfParaS1_9, 0x72c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 1, No.9."), + H1REG(HEncDnfParaS1_10, 0x72c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 1, No.10."), + H1REG(HEncDnfParaS1_11, 0x72c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 1, No.11."), + H1REG(HEncDnfParaS1_12, 0x730, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 1, No.12."), + H1REG(HEncDnfParaS1_13, 0x730, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 1, No.13."), + H1REG(HEncDnfParaS1_14, 0x730, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 1, No.14."), + H1REG(HEncDnfParaS1_15, 0x730, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 1, No.15."), + H1REG(HEncDnfParaS2_0, 0x734, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 2, No.0."), + H1REG(HEncDnfParaS2_1, 0x734, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 2, No.1."), + H1REG(HEncDnfParaS2_2, 0x734, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 2, No.2."), + H1REG(HEncDnfParaS2_3, 0x734, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 2, No.3."), + H1REG(HEncDnfParaS2_4, 0x738, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 2, No.4."), + H1REG(HEncDnfParaS2_5, 0x738, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 2, No.5."), + H1REG(HEncDnfParaS2_6, 0x738, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 2, No.6."), + H1REG(HEncDnfParaS2_7, 0x738, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 2, No.7."), + H1REG(HEncDnfParaS2_8, 0x73c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 2, No.8."), + H1REG(HEncDnfParaS2_9, 0x73c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 2, No.9."), + H1REG(HEncDnfParaS2_10, 0x73c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 2, No.10."), + H1REG(HEncDnfParaS2_11, 0x73c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 2, No.11."), + H1REG(HEncDnfParaS2_12, 0x740, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 2, No.12."), + H1REG(HEncDnfParaS2_13, 0x740, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 2, No.13."), + H1REG(HEncDnfParaS2_14, 0x740, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 2, No.14."), + H1REG(HEncDnfParaS2_15, 0x740, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 2, No.15."), + H1REG(HEncDnfParaS3_0, 0x744, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.0."), + H1REG(HEncDnfParaS3_1, 0x744, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.1."), + H1REG(HEncDnfParaS3_2, 0x744, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.2."), + H1REG(HEncDnfParaS3_3, 0x744, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.3."), + H1REG(HEncDnfParaS3_4, 0x748, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.4."), + H1REG(HEncDnfParaS3_5, 0x748, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.5."), + H1REG(HEncDnfParaS3_6, 0x748, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.6."), + H1REG(HEncDnfParaS3_7, 0x748, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.7."), + H1REG(HEncDnfParaS3_8, 0x74c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.8."), + H1REG(HEncDnfParaS3_9, 0x74c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.9."), + H1REG(HEncDnfParaS3_10, 0x74c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.10."), + H1REG(HEncDnfParaS3_11, 0x74c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.11."), + H1REG(HEncDnfParaS3_12, 0x750, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.12."), + H1REG(HEncDnfParaS3_13, 0x750, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.13."), + H1REG(HEncDnfParaS3_14, 0x750, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.14."), + H1REG(HEncDnfParaS3_15, 0x750, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.15."), + H1REG(HEncDnfParaS3_16, 0x754, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.16."), + H1REG(HEncDnfParaS3_17, 0x754, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.17."), + H1REG(HEncDnfParaS3_18, 0x754, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.18."), + H1REG(HEncDnfParaS3_19, 0x754, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.19."), + H1REG(HEncDnfParaS3_20, 0x758, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.20."), + H1REG(HEncDnfParaS3_21, 0x758, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.21."), + H1REG(HEncDnfParaS3_22, 0x758, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.22."), + H1REG(HEncDnfParaS3_23, 0x758, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.23."), + H1REG(HEncDnfParaS3_24, 0x75c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.24."), + H1REG(HEncDnfParaS3_25, 0x75c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.25."), + H1REG(HEncDnfParaS3_26, 0x75c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.26."), + H1REG(HEncDnfParaS3_27, 0x75c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.27."), + H1REG(HEncDnfParaS3_28, 0x760, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.28."), + H1REG(HEncDnfParaS3_29, 0x760, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.29."), + H1REG(HEncDnfParaS3_30, 0x760, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.30."), + H1REG(HEncDnfParaS3_31, 0x760, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.31."), + H1REG(HEncDnfParaS3_32, 0x764, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.32."), + H1REG(HEncDnfParaS3_33, 0x764, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.33."), + H1REG(HEncDnfParaS3_34, 0x764, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.34."), + H1REG(HEncDnfParaS3_35, 0x764, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.35."), + H1REG(HEncDnfParaS3_36, 0x768, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.36."), + H1REG(HEncDnfParaS3_37, 0x768, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.37."), + H1REG(HEncDnfParaS3_38, 0x768, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.38."), + H1REG(HEncDnfParaS3_39, 0x768, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.39."), + H1REG(HEncDnfParaS3_40, 0x76c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.40."), + H1REG(HEncDnfParaS3_41, 0x76c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.41."), + H1REG(HEncDnfParaS3_42, 0x76c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.42."), + H1REG(HEncDnfParaS3_43, 0x76c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.43."), + H1REG(HEncDnfParaS3_44, 0x770, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.44."), + H1REG(HEncDnfParaS3_45, 0x770, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.45."), + H1REG(HEncDnfParaS3_46, 0x770, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.46."), + H1REG(HEncDnfParaS3_47, 0x770, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.47."), + H1REG(HEncDnfParaS3_48, 0x774, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.48."), + H1REG(HEncDnfParaS3_49, 0x774, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.49."), + H1REG(HEncDnfParaS3_50, 0x774, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.50."), + H1REG(HEncDnfParaS3_51, 0x774, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.51."), + H1REG(HEncDnfParaS3_52, 0x778, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.52."), + H1REG(HEncDnfParaS3_53, 0x778, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.53."), + H1REG(HEncDnfParaS3_54, 0x778, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.54."), + H1REG(HEncDnfParaS3_55, 0x778, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.55."), + H1REG(HEncDnfParaS3_56, 0x77c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.56."), + H1REG(HEncDnfParaS3_57, 0x77c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.57."), + H1REG(HEncDnfParaS3_58, 0x77c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.58."), + H1REG(HEncDnfParaS3_59, 0x77c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.59."), + H1REG(HEncDnfParaS3_60, 0x780, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 3, No.60."), + H1REG(HEncDnfParaS3_61, 0x780, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 3, No.61."), + H1REG(HEncDnfParaS3_62, 0x780, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 3, No.62."), + H1REG(HEncDnfParaS3_63, 0x780, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 3, No.63."), + H1REG(HEncDnfParaS4_0, 0x784, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.0."), + H1REG(HEncDnfParaS4_1, 0x784, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.1."), + H1REG(HEncDnfParaS4_2, 0x784, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.2."), + H1REG(HEncDnfParaS4_3, 0x784, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.3."), + H1REG(HEncDnfParaS4_4, 0x788, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.4."), + H1REG(HEncDnfParaS4_5, 0x788, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.5."), + H1REG(HEncDnfParaS4_6, 0x788, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.6."), + H1REG(HEncDnfParaS4_7, 0x788, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.7."), + H1REG(HEncDnfParaS4_8, 0x78c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.8."), + H1REG(HEncDnfParaS4_9, 0x78c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.9."), + H1REG(HEncDnfParaS4_10, 0x78c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.10."), + H1REG(HEncDnfParaS4_11, 0x78c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.11."), + H1REG(HEncDnfParaS4_12, 0x790, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.12."), + H1REG(HEncDnfParaS4_13, 0x790, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.13."), + H1REG(HEncDnfParaS4_14, 0x790, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.14."), + H1REG(HEncDnfParaS4_15, 0x790, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.15."), + H1REG(HEncDnfParaS4_16, 0x794, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.16."), + H1REG(HEncDnfParaS4_17, 0x794, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.17."), + H1REG(HEncDnfParaS4_18, 0x794, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.18."), + H1REG(HEncDnfParaS4_19, 0x794, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.19."), + H1REG(HEncDnfParaS4_20, 0x798, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.20."), + H1REG(HEncDnfParaS4_21, 0x798, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.21."), + H1REG(HEncDnfParaS4_22, 0x798, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.22."), + H1REG(HEncDnfParaS4_23, 0x798, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.23."), + H1REG(HEncDnfParaS4_24, 0x79c, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.24."), + H1REG(HEncDnfParaS4_25, 0x79c, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.25."), + H1REG(HEncDnfParaS4_26, 0x79c, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.26."), + H1REG(HEncDnfParaS4_27, 0x79c, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.27."), + H1REG(HEncDnfParaS4_28, 0x7a0, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.28."), + H1REG(HEncDnfParaS4_29, 0x7a0, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.29."), + H1REG(HEncDnfParaS4_30, 0x7a0, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.30."), + H1REG(HEncDnfParaS4_31, 0x7a0, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.31."), + H1REG(HEncDnfParaS4_32, 0x7a4, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.32."), + H1REG(HEncDnfParaS4_33, 0x7a4, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.33."), + H1REG(HEncDnfParaS4_34, 0x7a4, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.34."), + H1REG(HEncDnfParaS4_35, 0x7a4, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.35."), + H1REG(HEncDnfParaS4_36, 0x7a8, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.36."), + H1REG(HEncDnfParaS4_37, 0x7a8, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.37."), + H1REG(HEncDnfParaS4_38, 0x7a8, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.38."), + H1REG(HEncDnfParaS4_39, 0x7a8, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.39."), + H1REG(HEncDnfParaS4_40, 0x7ac, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.40."), + H1REG(HEncDnfParaS4_41, 0x7ac, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.41."), + H1REG(HEncDnfParaS4_42, 0x7ac, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.42."), + H1REG(HEncDnfParaS4_43, 0x7ac, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.43."), + H1REG(HEncDnfParaS4_44, 0x7b0, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.44."), + H1REG(HEncDnfParaS4_45, 0x7b0, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.45."), + H1REG(HEncDnfParaS4_46, 0x7b0, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.46."), + H1REG(HEncDnfParaS4_47, 0x7b0, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.47."), + H1REG(HEncDnfParaS4_48, 0x7b4, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.48."), + H1REG(HEncDnfParaS4_49, 0x7b4, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.49."), + H1REG(HEncDnfParaS4_50, 0x7b4, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.50."), + H1REG(HEncDnfParaS4_51, 0x7b4, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.51."), + H1REG(HEncDnfParaS4_52, 0x7b8, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.52."), + H1REG(HEncDnfParaS4_53, 0x7b8, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.53."), + H1REG(HEncDnfParaS4_54, 0x7b8, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.54."), + H1REG(HEncDnfParaS4_55, 0x7b8, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.55."), + H1REG(HEncDnfParaS4_56, 0x7bc, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.56."), + H1REG(HEncDnfParaS4_57, 0x7bc, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.57."), + H1REG(HEncDnfParaS4_58, 0x7bc, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.58."), + H1REG(HEncDnfParaS4_59, 0x7bc, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.59."), + H1REG(HEncDnfParaS4_60, 0x7c0, 0x000000ff, 0, 0, WO, "Denoise Filter Parameters Set 4, No.60."), + H1REG(HEncDnfParaS4_61, 0x7c0, 0x0000ff00, 8, 0, WO, "Denoise Filter Parameters Set 4, No.61."), + H1REG(HEncDnfParaS4_62, 0x7c0, 0x00ff0000, 16, 0, WO, "Denoise Filter Parameters Set 4, No.62."), + H1REG(HEncDnfParaS4_63, 0x7c0, 0xff000000, 24, 0, WO, "Denoise Filter Parameters Set 4, No.63."), + +/* Low latency and Input Line buffer. */ + H1REG(HEncMbWrPtr, 0x7c4, 0x000001ff, 0, 0, RW, "The number of MB rows that is already filled in the input buffer"), + H1REG(HEncMbRdPtr, 0x7c4, 0x0003fe00, 9, 0, RO, "The number of MB rows that is already read out from the input buffer"), + H1REG(HEncLowLatencyHwSyncMbRows, 0x7c4, 0x07fc0000, 18, 0, RW, "The number of MB rows featched by encoder which will introduce HW shakehand happens."), + H1REG(HEncLowLatencyEn, 0x7c4, 0x08000000, 27, 1, RW, "Line Buffer Enable"), + H1REG(HEncInputBufferLoopBackEn, 0x7c4, 0x10000000, 28, 1, RW, "Input Buffer Loop Back Enable. valid only when sw_num_mb_rows_per_sync is smaller than frame size."), + H1REG(HEncLowLatencyHwIntfEn, 0x7c4, 0x20000000, 29, 1, RW, "Low Latency Hardware Interface Enable. Use hardware handshaking."), + H1REG(HEncLowLatencyIrqEn, 0x7c4, 0x40000000, 30, 1, RW, "Enable input Buffer underflow interrupt."), + +/* Last Fake Register for Register Counting. */ + H1REG(HEncRegisterAmount, 0x7c8, 0xffffffff, 0, 0, RW, "Last Fake Register for Register Counting."), + + + diff --git a/lib/vc8000nanoe/source/common/encInputLineBuffer.c b/lib/vc8000nanoe/source/common/encInputLineBuffer.c new file mode 100644 index 000000000..7c14586c6 --- /dev/null +++ b/lib/vc8000nanoe/source/common/encInputLineBuffer.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : For test/fpga_verification/example purpose. operations on Input + * line buffer. + * + ******************************************************************************** + */ +#include +#include "enccommon.h" +#include "ewl.h" +#include "encInputLineBuffer.h" +#include "H264Instance.h" + +#ifdef PCIE_FPGA_VERI_LINEBUF +/* FPGA verification. get/set register value of input-line-buffer */ +static u32 getInputLineBufReg (u32 *reg, u32 name) +{ + u32 value = (reg[lineBufRegisterDesc[name].base/4]&lineBufRegisterDesc[name].mask)>>lineBufRegisterDesc[name].lsb; + return value; +} +static void setInputLineBufReg (u32 *reg, u32 name, u32 value) +{ + reg[lineBufRegisterDesc[name].base/4]= + (reg[lineBufRegisterDesc[name].base/4] & ~(lineBufRegisterDesc[name].mask)) | + ((value << lineBufRegisterDesc[name].lsb) & lineBufRegisterDesc[name].mask); +} +#endif + +static u32 getMbLinesRdCnt (inputLineBufferCfg *cfg) +{ + u32 rdCnt = 0; +#ifdef PCIE_FPGA_VERI_LINEBUF + if (cfg->hwHandShake) + { + rdCnt = getInputLineBufReg(cfg->reg, InputlineBufRdCntr); + + /* frame end, disable hardware handshake */ + //if ((rdCnt*16) >= cfg->encHeight) + //setInputLineBufReg(cfg->reg,InputlineBufHwHandshake, 0); + } + else +#endif + if (cfg->getMbLines) + rdCnt = cfg->getMbLines(cfg->inst); + + return rdCnt; +} + +static void DumpInputLineBufReg(inputLineBufferCfg *cfg) +{ +#ifdef PCIE_FPGA_VERI_LINEBUF + u32 *reg = cfg->reg; + i32 i; + printf ("==== SRAM HW-handshake REGISTERS ====\n"); + for (i = 0; i < LINE_BUF_SWREG_AMOUNT; i ++) + printf (" %08x: %08x\n", i*4, reg[i]); + + printf (" rdCnt=%d, wrCnt=%d, depth=%d, hwMode=%d, picH=%d\n", + getInputLineBufReg(reg, InputlineBufRdCntr), + getInputLineBufReg(reg, InputlineBufWrCntr), + getInputLineBufReg(reg, InputlineBufDepth), + getInputLineBufReg(reg, InputlineBufHwHandshake), + getInputLineBufReg(reg, InputlineBufPicHeight)); +#endif +} + +static void DumpH264LowLatencyReg(inputLineBufferCfg *cfg) +{ + h264Instance_s *pEncInst = (h264Instance_s *)(cfg->inst); + + printf ("==== ASIC Low-Latency Regs: %08x. rdCnt=%d, wrCnt=%d, depth=%d, En=%d, loopBack=%d, hwMode=%d, IrqEn=%d\n", + EWLReadReg(pEncInst->asic.ewl, BASE_HEncInstantInput), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncMbRdPtr), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncMbWrPtr), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncLowLatencyHwSyncMbRows), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncLowLatencyEn), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncInputBufferLoopBackEn), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncLowLatencyHwIntfEn), + EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncLowLatencyIrqEn)); +} + +static void setMbLinesWrCnt (inputLineBufferCfg *cfg) +{ + if (cfg->hwHandShake) + { +#ifdef PCIE_FPGA_VERI_LINEBUF + setInputLineBufReg(cfg->reg,InputlineBufWrCntr,cfg->wrCnt); +#endif + } + else if (cfg->setMbLines) + cfg->setMbLines(cfg->inst, cfg->wrCnt); +} + +/*------------------------------------------------------------------------------ + copyLineBuf +------------------------------------------------------------------------------*/ +static void copyLineBuf (u8 *dst, u8 *src, i32 width, i32 height, u32 offset, u32 depth) +{ + i32 i, j; + if (dst && src) + { + for (i = 0; i < height; i ++) + { + i32 srcOff = i + offset; + i32 dstOff = (i + offset) % depth; + u32 *dst32 = (u32 *)(dst + dstOff*width); + u32 *src32 = (u32 *)(src + srcOff*width); + for (j = 0; j < (width/4); j ++) + dst32[j] = src32[j]; + } + } +} + +/*------------------------------------------------------------------------------ + writeInputLineBuf +------------------------------------------------------------------------------*/ +static void writeInputLineBuf (inputLineBufferCfg *cfg, i32 lines) +{ + u8 *lumSrc = cfg->lumSrc; + u8 *cbSrc = cfg->cbSrc; + u8 *crSrc = cfg->crSrc; + u8 *lumDst = cfg->lumBuf.buf; + u8 *cbDst = cfg->cbBuf.buf; + u8 *crDst = cfg->crBuf.buf; + u32 format = cfg->inputFormat; + u32 depth = cfg->depth; + u32 pixOnRow = cfg->pixOnRow; + u32 wrCnt = cfg->wrCnt; + u32 offset = wrCnt * 16; + u32 maxLine; + + if (!cfg->buf) + return; + + if (cfg->loopBackEn) + maxLine = depth * 16 * 2; /* ping-pong buffer */ + else + maxLine = cfg->encHeight; + + if (format == 0) + { + copyLineBuf (lumDst, lumSrc, pixOnRow, lines, offset, maxLine); + copyLineBuf (cbDst, cbSrc, pixOnRow/2, lines/2, offset/2, maxLine/2); + copyLineBuf (crDst, crSrc, pixOnRow/2, lines/2, offset/2, maxLine/2); + } + else if (format <= 2) + { + copyLineBuf (lumDst, lumSrc, pixOnRow, lines, offset, maxLine); + copyLineBuf (cbDst, cbSrc, pixOnRow, lines/2, offset/2, maxLine/2); + } + else if (format <= 10) + copyLineBuf (lumDst, lumSrc, pixOnRow*2, lines, offset, maxLine); + else + copyLineBuf (lumDst, lumSrc, pixOnRow*4, lines, offset, maxLine); +} + +/*------------------------------------------------------------------------------ + HEncInitInputLineBufSrcPtr + -Initialize src picture related pointers +------------------------------------------------------------------------------*/ +void HEncInitInputLineBufSrcPtr (inputLineBufferCfg *lineBufCfg) +{ + u32 format = lineBufCfg->inputFormat; + u32 stride = lineBufCfg->pixOnRow; + u8 *data = lineBufCfg->src; + u32 picHeight = lineBufCfg->srcHeight; + u32 verOffset = lineBufCfg->srcVerOffset; + u32 bytes; + + if (!data) + return; + + if (format <= 2) bytes = 1; + else if (format <= 10) bytes = 2; + else bytes = 4; + + lineBufCfg->lumSrc = data + verOffset * stride * bytes; + + if (format <= 2) + { + lineBufCfg->cbSrc = data + picHeight * stride; + if (format == 0) + { + lineBufCfg->crSrc = lineBufCfg->cbSrc + (picHeight/2) * (stride/2); + lineBufCfg->cbSrc += (verOffset/2) * (stride/2); + lineBufCfg->crSrc += (verOffset/2) * (stride/2); + } + else + lineBufCfg->cbSrc += (verOffset/2) * stride; + } +} + +/*------------------------------------------------------------------------------ + HEncInitInputLineBufPtr + -Initialize line buffer related pointers +------------------------------------------------------------------------------*/ +void HEncInitInputLineBufPtr (inputLineBufferCfg *lineBufCfg) +{ + u32 bufOffset = 0; +#ifdef PCIE_FPGA_VERI_LINEBUF + bufOffset = LINE_BUF_SWREG_AMOUNT*4; +#endif + + if (!lineBufCfg->buf) + return; + + lineBufCfg->lumBuf.buf = lineBufCfg->buf + bufOffset; + lineBufCfg->lumBuf.busAddress = lineBufCfg->busAddress + bufOffset; + + if (lineBufCfg->inputFormat <= 2) + { + u32 lumaBufSize; + if (lineBufCfg->loopBackEn) + lumaBufSize = lineBufCfg->pixOnRow * lineBufCfg->depth*16*2; + else + lumaBufSize = lineBufCfg->pixOnRow * lineBufCfg->encHeight; + + lineBufCfg->cbBuf.buf = lineBufCfg->lumBuf.buf+ lumaBufSize; + lineBufCfg->cbBuf.busAddress = lineBufCfg->lumBuf.busAddress + lumaBufSize; + + if (lineBufCfg->inputFormat == 0) + { + lineBufCfg->crBuf.buf = lineBufCfg->cbBuf.buf+ lumaBufSize/4; + lineBufCfg->crBuf.busAddress = lineBufCfg->cbBuf.busAddress + lumaBufSize/4; + } + } +} + +/*------------------------------------------------------------------------------ + + HEncInitInputLineBuffer + -get line buffer params for IRQ handle + -get address of input line buffer +------------------------------------------------------------------------------*/ +i32 HEncInitInputLineBuffer(inputLineBufferCfg *lineBufCfg, const void *ewl) +{ + i32 ret; + EWLLinearMem_t lineBufSRAM; + + if (lineBufCfg->depth == 0) + { + i32 mbPerRow = (lineBufCfg->encWidth + 15)/16; + if (mbPerRow & 1) + lineBufCfg->depth = 4; + else if (mbPerRow & 2) + lineBufCfg->depth = 2; + else + lineBufCfg->depth = 1; + } + + /* setup pointers of source picture */ + HEncInitInputLineBufSrcPtr (lineBufCfg); + + /* setup addresses of line buffer */ + lineBufCfg->buf = NULL; + ret = EWLGetInputLineBufferBase(ewl, &lineBufSRAM); + lineBufCfg->buf = (u8 *)(lineBufSRAM.virtualAddress); + lineBufCfg->busAddress = lineBufSRAM.busAddress; + + if (ret != EWL_OK) + return -1; + + if (!lineBufCfg->buf) + return 0; + +#ifdef PCIE_FPGA_VERI_LINEBUF + lineBufCfg->reg = (u32 *)lineBufCfg->buf; + /* clean sram registers */ + lineBufCfg->reg[0] = 0; +#endif + + if (lineBufCfg->loopBackEn) + HEncInitInputLineBufPtr(lineBufCfg); + +#if 0 + /* To test sram */ + if (lineBufSRAM.virtualAddress) + { + u32 *sram = (u32 *)(lineBufSRAM.virtualAddress + LINE_BUF_SWREG_AMOUNT); + i32 size = lineBufSRAM.size/4 - LINE_BUF_SWREG_AMOUNT; + i32 i; + //write + for (i=0; idepth*16*2, lineBufCfg->encHeight); + lineBufCfg->wrCnt = ((lines+15)/16); + if (lineBufCfg->loopBackEn) + writeInputLineBuf (lineBufCfg, lines); + +#ifdef PCIE_FPGA_VERI_LINEBUF + /* init sram regs */ + if (lineBufCfg->reg) + { + i32 i; + for (i = 0; i < LINE_BUF_SWREG_AMOUNT; i ++) + lineBufCfg->reg[i] = 0; + + if (lineBufCfg->hwHandShake) + { + setInputLineBufReg(lineBufCfg->reg, InputlineBufPicHeight, (lineBufCfg->encHeight+15)/16); + setInputLineBufReg(lineBufCfg->reg, InputlineBufDepth, lineBufCfg->depth); + setInputLineBufReg(lineBufCfg->reg, InputlineBufWrCntr, lineBufCfg->wrCnt); + setInputLineBufReg(lineBufCfg->reg, InputlineBufHwHandshake, 1); + + //DumpInputLineBufReg(lineBufCfg); + } + } +#endif + return; +} + +/*------------------------------------------------------------------------------ + An example of Line buffer Callback function + called by the encoder SW after receive "input line buffer done" interruption from HW. + Used for test/fpga_verification currently. +------------------------------------------------------------------------------*/ +void HEncInputMBLineBufDone (void *pAppData) +{ + if (pAppData) + { + inputLineBufferCfg *cfg = (inputLineBufferCfg *)pAppData; + i32 rdCnt = 0; + i32 wrCnt = cfg->wrCnt; + i32 depth = cfg->depth; + i32 height = cfg->encHeight; + i32 lines = depth * 16; + i32 offset = wrCnt * 16; + + /* get rd counter */ + rdCnt = getMbLinesRdCnt(cfg); + + /* write line buffer */ + lines = MIN(lines, height-offset); + if ((lines>0) && (cfg->wrCnt <= (rdCnt+depth))) + { + if (cfg->loopBackEn) + writeInputLineBuf (cfg, lines); + cfg->wrCnt += ((lines+15)/16); + } + + /* update write counter */ + setMbLinesWrCnt (cfg); + + printf (" #<---- Line_Buf_Done: encHeight=%d, depth=%d, rdCnt=%d, wrCnt=%d-->%d\n", + height, depth, rdCnt, wrCnt, cfg->wrCnt); + + //DumpInputLineBufReg(cfg); + //DumpH264LowLatencyReg(cfg); + } +} + diff --git a/lib/vc8000nanoe/source/common/encasiccontroller.c b/lib/vc8000nanoe/source/common/encasiccontroller.c new file mode 100644 index 000000000..3f368ef15 --- /dev/null +++ b/lib/vc8000nanoe/source/common/encasiccontroller.c @@ -0,0 +1,1245 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : ASIC low level controller + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + Include headers +------------------------------------------------------------------------------*/ + +#include "enccommon.h" +#include "encasiccontroller.h" +#include "encpreprocess.h" +#include "ewl.h" +#include "encswhwregisters.h" + +/*------------------------------------------------------------------------------ + External compiler flags +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Module defines +------------------------------------------------------------------------------*/ + +#ifdef ASIC_WAVE_TRACE_TRIGGER +extern i32 trigger_point; /* picture which will be traced */ +#endif + +/* Mask fields */ +#define mask_2b (u32)0x00000003 +#define mask_3b (u32)0x00000007 +#define mask_4b (u32)0x0000000F +#define mask_5b (u32)0x0000001F +#define mask_6b (u32)0x0000003F +#define mask_7b (u32)0x0000007F +#define mask_8b (u32)0x000000FF +#define mask_11b (u32)0x000007FF +#define mask_14b (u32)0x00003FFF +#define mask_16b (u32)0x0000FFFF + +#define HSWREG(n) ((n)*4) + +/* JPEG QUANT table order */ +static const u32 qpReorderTable[64] = + { 0, 8, 16, 24, 1, 9, 17, 25, 32, 40, 48, 56, 33, 41, 49, 57, + 2, 10, 18, 26, 3, 11, 19, 27, 34, 42, 50, 58, 35, 43, 51, 59, + 4, 12, 20, 28, 5, 13, 21, 29, 36, 44, 52, 60, 37, 45, 53, 61, + 6, 14, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + + +/* Global variables for test data trace file configuration. + * These are set in testbench and used in system model test data generation. */ +char * H1EncTraceFileConfig = NULL; +int H1EncTraceFirstFrame = 0; + +/*------------------------------------------------------------------------------ + Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Initialize empty structure with default values. +------------------------------------------------------------------------------*/ +i32 EncAsicControllerInit(asicData_s * asic) +{ + ASSERT(asic != NULL); + + /* Initialize default values from defined configuration */ + asic->regs.irqDisable = ENCH1_IRQ_DISABLE; + asic->regs.inputReadChunk = ENCH1_INPUT_READ_CHUNK; + + asic->regs.asicCfgReg = + ((ENCH1_AXI_WRITE_ID & (255)) << 24) | + ((ENCH1_AXI_READ_ID & (255)) << 16) | + ((ENCH1_OUTPUT_SWAP_16 & (1)) << 15) | + ((ENCH1_BURST_LENGTH & (63)) << 8) | + ((ENCH1_BURST_SCMD_DISABLE & (1)) << 7) | + ((ENCH1_BURST_INCR_TYPE_ENABLED & (1)) << 6) | + ((ENCH1_BURST_DATA_DISCARD_ENABLED & (1)) << 5) | + ((ENCH1_ASIC_CLOCK_GATING_ENABLED & (1)) << 4) | + ((ENCH1_OUTPUT_SWAP_32 & (1)) << 3) | + ((ENCH1_OUTPUT_SWAP_8 & (1)) << 1); + + asic->regs.recWriteBuffer = ENCH1_REC_WRITE_BUFFER & 1; + + /* Initialize default values */ + asic->regs.roundingCtrl = 0; + asic->regs.cpDistanceMbs = 0; + asic->regs.reconImageId = 0; + + /* User must set these */ + asic->regs.inputLumBase = 0; + asic->regs.inputCbBase = 0; + asic->regs.inputCrBase = 0; + + asic->internalImageLuma[0].virtualAddress = NULL; + asic->internalImageChroma[0].virtualAddress = NULL; + asic->internalImageLuma[1].virtualAddress = NULL; + asic->internalImageChroma[1].virtualAddress = NULL; + asic->internalImageLuma[2].virtualAddress = NULL; + asic->internalImageChroma[2].virtualAddress = NULL; + asic->internalImageChroma[3].virtualAddress = NULL; + asic->scaledImage.virtualAddress = NULL; + asic->sizeTbl.virtualAddress = NULL; + asic->cabacCtx.virtualAddress = NULL; + asic->mvOutput.virtualAddress = NULL; + asic->probCount.virtualAddress = NULL; + asic->segmentMap.virtualAddress = NULL; + +#ifdef ASIC_WAVE_TRACE_TRIGGER + asic->regs.vop_count = 0; +#endif + + /* get ASIC ID value */ + asic->regs.asicHwId = EncAsicGetId(asic->ewl); + +/* we do NOT reset hardware at this point because */ +/* of the multi-instance support */ + + return ENCHW_OK; +} + + +/*------------------------------------------------------------------------------ + + EncAsicSetQuantTable + + Set new jpeg quantization table to be used by ASIC + +------------------------------------------------------------------------------*/ +void EncAsicSetQuantTable(asicData_s * asic, + const u8 * lumTable, const u8 * chTable) +{ + i32 i; + + ASSERT(lumTable); + ASSERT(chTable); + + for(i = 0; i < 64; i++) + { + asic->regs.quantTable[i] = lumTable[qpReorderTable[i]]; + } + for(i = 0; i < 64; i++) + { + asic->regs.quantTable[64 + i] = chTable[qpReorderTable[i]]; + } +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +u32 EncAsicGetId(const void *ewl) +{ + return EWLReadReg(ewl, 0x0); +} + +/*------------------------------------------------------------------------------ + When the frame is successfully encoded the internal image is recycled + so that during the next frame the current internal image is read and + the new reconstructed image is written. Note that this is done for + the NEXT frame. +------------------------------------------------------------------------------*/ +#define NEXTID(currentId, maxId) ((currentId == maxId) ? 0 : currentId+1) +#define PREVID(currentId, maxId) ((currentId == 0) ? maxId : currentId-1) + +void EncAsicRecycleInternalImage(asicData_s *asic, u32 numViews, u32 viewId, + u32 anchor, u32 numRefBuffsLum, u32 numRefBuffsChr) +{ + u32 id; + ptr_t tmp; + + if (numViews == 1) + { + /* H.264 base view stream, just swap buffers */ + tmp = asic->regs.internalImageLumBaseW; + asic->regs.internalImageLumBaseW = asic->regs.internalImageLumBaseR[0]; + asic->regs.internalImageLumBaseR[0] = tmp; + + tmp = asic->regs.internalImageChrBaseW; + asic->regs.internalImageChrBaseW = asic->regs.internalImageChrBaseR[0]; + asic->regs.internalImageChrBaseR[0] = tmp; + } + else + { + /* MVC stereo stream, the buffer amount tells if the second view + * is inter-view or inter coded. This affects how the buffers + * should be swapped. */ + + if ((viewId == 0) && (anchor || (numRefBuffsLum == 1))) + { + /* Next frame is viewId=1 with inter-view prediction */ + asic->regs.internalImageLumBaseR[0] = asic->internalImageLuma[0].busAddress; + asic->regs.internalImageLumBaseW = asic->internalImageLuma[1].busAddress; + } + else if (viewId == 0) + { + /* Next frame is viewId=1 with inter prediction */ + asic->regs.internalImageLumBaseR[0] = asic->internalImageLuma[1].busAddress; + asic->regs.internalImageLumBaseW = asic->internalImageLuma[1].busAddress; + } + else + { + /* Next frame is viewId=0 with inter prediction */ + asic->regs.internalImageLumBaseR[0] = asic->internalImageLuma[0].busAddress; + asic->regs.internalImageLumBaseW = asic->internalImageLuma[0].busAddress; + } + + if (numRefBuffsChr == 2) + { + if (viewId == 0) + { + /* For inter-view prediction chroma is swapped after base view only */ + tmp = asic->regs.internalImageChrBaseW; + asic->regs.internalImageChrBaseW = asic->regs.internalImageChrBaseR[0]; + asic->regs.internalImageChrBaseR[0] = tmp; + } + } + else + { + /* For viewId==1 the anchor frame uses inter-view prediction, + * all other frames use inter-prediction. */ + if ((viewId == 0) && anchor) + id = asic->regs.reconImageId; + else + id = PREVID(asic->regs.reconImageId, 2); + + asic->regs.internalImageChrBaseR[0] = asic->internalImageChroma[id].busAddress; + asic->regs.reconImageId = id = NEXTID(asic->regs.reconImageId, 2); + asic->regs.internalImageChrBaseW = asic->internalImageChroma[id].busAddress; + } + } +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +void CheckRegisterValues(regValues_s * val) +{ + ASSERT(val->irqDisable <= 1); + ASSERT(val->rlcLimitSpace / 2 < (1 << 20)); + ASSERT(val->mbsInCol <= 511); + ASSERT(val->mbsInRow <= 511); + ASSERT(val->filterDisable <= 2); + ASSERT(val->recWriteBuffer <= 1); + ASSERT(val->recWriteDisable <= 1); + ASSERT(val->madThreshold[0] <= 63); + ASSERT(val->madThreshold[1] <= 63); + ASSERT(val->madThreshold[2] <= 63); + ASSERT(val->madQpDelta[0] >= -8 && val->madQpDelta[0] <= 7); + ASSERT(val->madQpDelta[1] >= -127 && val->madQpDelta[1] <= 127); + ASSERT(val->madQpDelta[2] >= -127 && val->madQpDelta[2] <= 127); + ASSERT(val->qp <= 63); + ASSERT(val->constrainedIntraPrediction <= 1); + ASSERT(val->roundingCtrl <= 1); + ASSERT(val->frameCodingType <= 3); + ASSERT(val->codingType <= 3); + ASSERT(val->outputStrmSize <= 0x1FFFFFF); + ASSERT(val->pixelsOnRow >= 16 && val->pixelsOnRow <= 8192); /* max input for cropping */ + ASSERT(val->xFill <= 3); + ASSERT(val->yFill <= 14 && ((val->yFill & 0x01) == 0)); + ASSERT(val->inputLumaBaseOffset <= 7); + ASSERT(val->inputChromaBaseOffset <= 7); + ASSERT(val->sliceAlphaOffset >= -6 && val->sliceAlphaOffset <= 6); + ASSERT(val->sliceBetaOffset >= -6 && val->sliceBetaOffset <= 6); + ASSERT(val->chromaQpIndexOffset >= -12 && val->chromaQpIndexOffset <= 12); + ASSERT(val->sliceSizeMbRows <= 127); + ASSERT(val->inputImageFormat <= ASIC_INPUT_P010); + ASSERT(val->inputImageRotation <= 3); + ASSERT(val->cpDistanceMbs <= 8191); + if(val->codingType == ASIC_H264) { + ASSERT(val->roi1DeltaQp >= 0 && val->roi1DeltaQp <= 15); + ASSERT(val->roi2DeltaQp >= 0 && val->roi2DeltaQp <= 15); + } + ASSERT(val->cirStart <= 65535); + ASSERT(val->cirInterval <= 65535); + ASSERT(val->intraAreaTop <= 255); + ASSERT(val->intraAreaLeft <= 255); + ASSERT(val->intraAreaBottom <= 255); + ASSERT(val->intraAreaRight <= 255); + ASSERT(val->roi1Top <= 255); + ASSERT(val->roi1Left <= 255); + ASSERT(val->roi1Bottom <= 255); + ASSERT(val->roi1Right <= 255); + ASSERT(val->roi2Top <= 255); + ASSERT(val->roi2Left <= 255); + ASSERT(val->roi2Bottom <= 255); + ASSERT(val->roi2Right <= 255); + ASSERT(val->boostQp <= 52); + ASSERT(val->boostVar1 <= 8191); + ASSERT(val->boostVar2 <= 8191); + ASSERT(val->varLimitDiv32 <= 15); + ASSERT(val->varInterFavorDiv16 <= 15); + ASSERT(val->varMultiplier <= 31); + ASSERT(val->varAdd <= 7); + ASSERT(val->pskipMode <= 1); + + (void) val; +} + +/*------------------------------------------------------------------------------ + Function name : EncAsicFrameStart + Description : + Return type : void + Argument : const void *ewl + Argument : regValues_s * val +------------------------------------------------------------------------------*/ +void EncAsicFrameStart(const void *ewl, regValues_s * val) +{ + i32 i; + u32 asicCfgReg = val->asicCfgReg; + + CheckRegisterValues(val); + + EWLmemset(val->regMirror, 0, sizeof(val->regMirror)); + +#ifdef INTERNAL_TEST + /* With internal testing use random values for burst mode. + Random value taken from squared error register of previous frame. */ + asicCfgReg = (asicCfgReg & ~0xE0) | (EWLReadReg(ewl, 0x3b0) & 0xE0); + + /* Also test both values of recon output buffer. */ + val->recWriteBuffer = val->frameNum & 1; +#endif + + /* must burst for RFC */ + if (val->refLumCompress || val->refChrCompress) + asicCfgReg &= (~0x80); + + /* encoder interrupt */ + EncAsicSetRegisterValue(val->regMirror, HEncIRQDisable, val->irqDisable); + /* clear all interrupt */ + if (EWLReadReg(ewl, BASE_HWFuse2) & HWCFGIrqClearSupport) + { + EncAsicSetRegisterValue(val->regMirror, HEncIRQRfcBufOverflow, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQLowLatency, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQFuse, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQSliceReady, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQTimeout, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQBuffer, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQReset, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQBusError, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQFrameReady, 1); + EncAsicSetRegisterValue(val->regMirror, HEncIRQ, 1); + } + + /* system configuration */ + if ( (val->inputImageFormat < ASIC_INPUT_RGB565) || + (val->inputImageFormat == ASIC_INPUT_SP_101010) || + (val->inputImageFormat == ASIC_INPUT_P010) ) /* YUV input */ + val->regMirror[2] = asicCfgReg | + ((ENCH1_INPUT_SWAP_16_YUV & (1)) << 14) | + ((ENCH1_INPUT_SWAP_32_YUV & (1)) << 2) | + (ENCH1_INPUT_SWAP_8_YUV & (1)); + else if (val->inputImageFormat < ASIC_INPUT_RGB888) /* 16-bit RGB input */ + val->regMirror[2] = asicCfgReg | + ((ENCH1_INPUT_SWAP_16_RGB16 & (1)) << 14) | + ((ENCH1_INPUT_SWAP_32_RGB16 & (1)) << 2) | + (ENCH1_INPUT_SWAP_8_RGB16 & (1)); + else /* 32-bit RGB input */ + val->regMirror[2] = asicCfgReg | + ((ENCH1_INPUT_SWAP_16_RGB32 & (1)) << 14) | + ((ENCH1_INPUT_SWAP_32_RGB32 & (1)) << 2) | + (ENCH1_INPUT_SWAP_8_RGB32 & (1)); + + EncAsicSetRegisterValue(val->regMirror, HEncScaleOutputSwap8, ENCH1_SCALE_OUTPUT_SWAP_8); + EncAsicSetRegisterValue(val->regMirror, HEncScaleOutputSwap16, ENCH1_SCALE_OUTPUT_SWAP_16); + EncAsicSetRegisterValue(val->regMirror, HEncScaleOutputSwap32, ENCH1_SCALE_OUTPUT_SWAP_32); + EncAsicSetRegisterValue(val->regMirror, HEncMvOutputSwap8, ENCH1_MV_OUTPUT_SWAP_8); + EncAsicSetRegisterValue(val->regMirror, HEncMvOutputSwap16, ENCH1_MV_OUTPUT_SWAP_16); + EncAsicSetRegisterValue(val->regMirror, HEncMvOutputSwap32, ENCH1_MV_OUTPUT_SWAP_32); + EncAsicSetRegisterValue(val->regMirror, HEncInputReadChunk, val->inputReadChunk); + EncAsicSetRegisterValue(val->regMirror, HEncTestIrq, val->traceMbTiming); + EncAsicSetRegisterValue(val->regMirror, HEncAXIDualCh, ENCH1_AXI_2CH_DISABLE); + + /* set axi read ID for DEC400 8 */ + EncAsicSetRegisterValue(val->regMirror, HEncAXIReadIDInC0, ENCH1_AXI_READ_ID_C0); + EncAsicSetRegisterValue(val->regMirror, HEncAXIReadIDInC1, ENCH1_AXI_READ_ID_C1); + EncAsicSetRegisterValue(val->regMirror, HEncAXIReadIDInC2, ENCH1_AXI_READ_ID_C2); + EncAsicSetRegisterValue(val->regMirror, HEncAXIReadIDEnable, ENCH1_AXI_READ_ID_EN); + + /* output stream buffer */ + SET_ADDR_REG(val->regMirror, HEncBaseStream, val->outputStrmBase); + + /* Video encoding output buffers and reference picture buffers */ + if(val->codingType != ASIC_JPEG) + { + SET_ADDR_REG(val->regMirror, HEncBaseControl, val->sizeTblBase); + EncAsicSetRegisterValue(val->regMirror, HEncNalSizeWrite, val->sizeTblBase != 0); + EncAsicSetRegisterValue(val->regMirror, HEncMvWrite, val->mvOutEnable); + + SET_ADDR_REG(val->regMirror, HEncBaseRefLum, val->internalImageLumBaseR[0]); + SET_ADDR_REG(val->regMirror, HEncBaseRefChr, val->internalImageChrBaseR[0]); + SET_ADDR_REG(val->regMirror, HEncBaseRecLum, val->internalImageLumBaseW); + SET_ADDR_REG(val->regMirror, HEncBaseRecChr, val->internalImageChrBaseW); + } + + /* Input picture buffers */ + SET_ADDR_REG(val->regMirror, HEncBaseInLum, val->inputLumBase); + SET_ADDR_REG(val->regMirror, HEncBaseInCb, val->inputCbBase); + SET_ADDR_REG(val->regMirror, HEncBaseInCr, val->inputCrBase); + + /* Common control register */ + if (val->lineBufferEn) + EncAsicSetRegisterValue(val->regMirror, HEncIntTimeout, 0); + else + EncAsicSetRegisterValue(val->regMirror, HEncIntTimeout, ENCH1_TIMEOUT_INTERRUPT&1); + EncAsicSetRegisterValue(val->regMirror, HEncIntSliceReady, val->sliceReadyInterrupt); + EncAsicSetRegisterValue(val->regMirror, HEncRecWriteBuffer, val->recWriteBuffer); + EncAsicSetRegisterValue(val->regMirror, HEncRecWriteDisable, val->recWriteDisable); + EncAsicSetRegisterValue(val->regMirror, HEncWidth, val->mbsInRow); + EncAsicSetRegisterValue(val->regMirror, HEncHeight, val->mbsInCol); + EncAsicSetRegisterValue(val->regMirror, HEncPictureType, val->frameCodingType); + EncAsicSetRegisterValue(val->regMirror, HEncEncodingMode, val->codingType); + EncAsicSetRegisterValue(val->regMirror, HEncRefReorderFlag, val->reorderFlag); + EncAsicSetRegisterValue(val->regMirror, HEncRefReorderDiffPicNum, val->reorderDiff); + + /* PreP control */ + EncAsicSetRegisterValue(val->regMirror, HEncChrOffset, val->inputChromaBaseOffset); + EncAsicSetRegisterValue(val->regMirror, HEncLumOffset, val->inputLumaBaseOffset); + EncAsicSetRegisterValue(val->regMirror, HEncRowLength, val->pixelsOnRow); + EncAsicSetRegisterValue(val->regMirror, HEncXFill, val->xFill); + EncAsicSetRegisterValue(val->regMirror, HEncYFill, val->yFill); + EncAsicSetRegisterValue(val->regMirror, HEncInputFormat, val->inputImageFormat); + EncAsicSetRegisterValue(val->regMirror, HEncInputRot, val->inputImageRotation); + + /* Common controls */ + EncAsicSetRegisterValue(val->regMirror, HEncCabacEnable, val->enableCabac); + EncAsicSetRegisterValue(val->regMirror, HEncIPIntra16Favor, val->pen[0][ASIC_PENALTY_I16FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncInterFavor, val->pen[0][ASIC_PENALTY_INTER_FAVOR] & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncDisableQPMV, val->disableQuarterPixelMv); + EncAsicSetRegisterValue(val->regMirror, HEncDeblocking, val->filterDisable); + EncAsicSetRegisterValue(val->regMirror, HEncSkipPenalty, val->pen[0][ASIC_PENALTY_SKIP]); + EncAsicSetRegisterValue(val->regMirror, HEncChromaSwap, val->chromaSwap); + EncAsicSetRegisterValue(val->regMirror, HEncSplitMv, val->splitMvMode); + EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty16x8, val->pen[0][ASIC_PENALTY_SPLIT16x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty8x8, val->pen[0][ASIC_PENALTY_SPLIT8x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty8x4, val->pen[0][ASIC_PENALTY_SPLIT8x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty4x4, val->pen[0][ASIC_PENALTY_SPLIT4x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSplitZeroPenalty, val->pen[0][ASIC_PENALTY_SPLIT_ZERO]); + EncAsicSetRegisterValue(val->regMirror, HEncZeroMvFavor, val->zeroMvFavorDiv2); + + /* H.264 specific control */ + if (val->codingType == ASIC_H264) + { + EncAsicSetRegisterValue(val->regMirror, HEncPicInitQp, val->picInitQp); + EncAsicSetRegisterValue(val->regMirror, HEncSliceAlpha, val->sliceAlphaOffset & mask_4b); + EncAsicSetRegisterValue(val->regMirror, HEncSliceBeta, val->sliceBetaOffset & mask_4b); + EncAsicSetRegisterValue(val->regMirror, HEncChromaQp, val->chromaQpIndexOffset & mask_5b); + EncAsicSetRegisterValue(val->regMirror, HEncIdrPicId, val->idrPicId); + EncAsicSetRegisterValue(val->regMirror, HEncConstrIP, val->constrainedIntraPrediction); + + EncAsicSetRegisterValue(val->regMirror, HEncPPSID, val->ppsId); + EncAsicSetRegisterValue(val->regMirror, HEncIPPrevModeFavor, val->pen[0][ASIC_PENALTY_I4_PREV_MODE_FAVOR]); + + EncAsicSetRegisterValue(val->regMirror, HEncSliceSize, val->sliceSizeMbRows); + EncAsicSetRegisterValue(val->regMirror, HEncTransform8x8, val->transform8x8Mode); + EncAsicSetRegisterValue(val->regMirror, HEncCabacInitIdc, val->cabacInitIdc); + EncAsicSetRegisterValue(val->regMirror, HEncInter4Restrict, val->h264Inter4x4Disabled); + EncAsicSetRegisterValue(val->regMirror, HEncStreamMode, val->h264StrmMode); + EncAsicSetRegisterValue(val->regMirror, HEncFrameNum, val->frameNum); + } + + /* JPEG specific control */ + if (val->codingType == ASIC_JPEG) + { + EncAsicSetRegisterValue(val->regMirror, HEncJpegMode, val->jpegMode); + EncAsicSetRegisterValue(val->regMirror, HEncJpegSlice, val->jpegSliceEnable); + EncAsicSetRegisterValue(val->regMirror, HEncJpegRSTInt, val->jpegRestartInterval); + EncAsicSetRegisterValue(val->regMirror, HEncJpegRST, val->jpegRestartMarker); + } + + /* stream buffer limits */ + EncAsicSetRegisterValue(val->regMirror, HEncStrmHdrRem1, val->strmStartMSB); + EncAsicSetRegisterValue(val->regMirror, HEncStrmHdrRem2, val->strmStartLSB); + EncAsicSetRegisterValue(val->regMirror, HEncStrmBufLimit, val->outputStrmSize-8); + + /* video encoding rate control regs 0x6C - 0x90, + * different register definitions for VP8 and H.264 */ + if(val->codingType != ASIC_JPEG) + { + EncAsicSetRegisterValue(val->regMirror, HEncMadQpDelta, val->madQpDelta[0] & mask_4b); + EncAsicSetRegisterValue(val->regMirror, HEncMadThreshold, val->madThreshold[0]); + EncAsicSetRegisterValue(val->regMirror, HEncMadQpDelta2, val->madQpDelta[1] & mask_8b); + EncAsicSetRegisterValue(val->regMirror, HEncMadThreshold2, val->madThreshold[1]); + EncAsicSetRegisterValue(val->regMirror, HEncMadQpDelta3, val->madQpDelta[2] & mask_8b); + EncAsicSetRegisterValue(val->regMirror, HEncMadThreshold3, val->madThreshold[2]); + + if (val->codingType == ASIC_VP8) + { + SET_ADDR_REG(val->regMirror, HEncBaseRefLum2, val->internalImageLumBaseR[1]); + SET_ADDR_REG(val->regMirror, HEncBaseRefChr2, val->internalImageChrBaseR[1]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1QuantDc, val->qpY1QuantDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1QuantAc, val->qpY1QuantAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2QuantDc, val->qpY2QuantDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2QuantAc, val->qpY2QuantAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChQuantDc, val->qpChQuantDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChQuantAc, val->qpChQuantAc[0]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1ZbinDc, val->qpY1ZbinDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1ZbinAc, val->qpY1ZbinAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2ZbinDc, val->qpY2ZbinDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2ZbinAc, val->qpY2ZbinAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChZbinDc, val->qpChZbinDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChZbinAc, val->qpChZbinAc[0]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1RoundDc, val->qpY1RoundDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1RoundAc, val->qpY1RoundAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2RoundDc, val->qpY2RoundDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2RoundAc, val->qpY2RoundAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChRoundDc, val->qpChRoundDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChRoundAc, val->qpChRoundAc[0]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1DequantDc, val->qpY1DequantDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1DequantAc, val->qpY1DequantAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2DequantDc, val->qpY2DequantDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2DequantAc, val->qpY2DequantAc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChDequantDc, val->qpChDequantDc[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8ChDequantAc, val->qpChDequantAc[0]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8MvRefIdx, val->mvRefIdx[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8MvRefIdx2, val->mvRefIdx[1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Ref2Enable, val->ref2Enable); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DeadzoneEnable, val->deadzoneEnable); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8BoolEncValue, val->boolEncValue); + EncAsicSetRegisterValue(val->regMirror, HEncVp8BoolEncValueBits, val->boolEncValueBits); + EncAsicSetRegisterValue(val->regMirror, HEncVp8BoolEncRange, val->boolEncRange); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8FilterLevel, val->filterLevel[0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8GoldenPenalty, val->pen[0][ASIC_PENALTY_GOLDEN]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8FilterSharpness, val->filterSharpness); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DctPartitionCount, val->dctPartitions); + } else { /* H.264 */ + EncAsicSetRegisterValue(val->regMirror, HEncQp, val->qp); + EncAsicSetRegisterValue(val->regMirror, HEncMaxQp, val->qpMax); + EncAsicSetRegisterValue(val->regMirror, HEncMinQp, val->qpMin); + EncAsicSetRegisterValue(val->regMirror, HEncCPDist, 0); + /* long term ref stuff */ + EncAsicSetRegisterValue(val->regMirror, HEncH264LongTermPenalty, val->pen[0][ASIC_PENALTY_GOLDEN]); + EncAsicSetRegisterValue(val->regMirror, HEncH264Ref2Enable, val->ref2Enable); + EncAsicSetRegisterValue(val->regMirror, HEncH264MvRefIdx, val->mvRefIdx[0]); + + EncAsicSetRegisterValue(val->regMirror, HEncH264MarkCurrentLongTerm, val->markCurrentLongTerm); + SET_ADDR_REG(val->regMirror, HEncH264BaseRefLum2, val->internalImageLumBaseR[1]); + SET_ADDR_REG(val->regMirror, HEncH264BaseRefChr2, val->internalImageChrBaseR[1]); + } + + /* Segment map registers for VP8 and H264. */ + EncAsicSetRegisterValue(val->regMirror, HEncVp8SegmentEnable, val->segmentEnable); + EncAsicSetRegisterValue(val->regMirror, HEncVp8SegmentMapUpdate, val->segmentMapUpdate); + SET_ADDR_REG(val->regMirror, HEncBaseVp8SegmentMap, val->segmentMapBase); + + /* Reference Frame Compression */ + EncAsicSetRegisterValue(val->regMirror, HEncRefLumCompress, val->refLumCompress); + EncAsicSetRegisterValue(val->regMirror, HEncRefChrCompress, val->refChrCompress); + if (val->refLumCompress || val->refChrCompress) + EncAsicSetRegisterValue(val->regMirror, HEncRfcIntEn, val->rfcOverflowIRQEn); + if (val->refLumCompress) + { + EncAsicSetRegisterValue(val->regMirror, HEncRfcLumBufLimit, val->rfcLumBufLimit); + EncAsicSetRegisterValue(val->regMirror, HEncRfcLumDiscreteMode, val->rfcLumDiscreteMode); + SET_ADDR_REG(val->regMirror, HEncBaseRefLumTbl, val->internalImageLumTableBaseR[0]); + SET_ADDR_REG(val->regMirror, HEncBaseRecLumTbl, val->internalImageLumTableBaseW); + SET_ADDR_REG(val->regMirror, HEncBaseRefLumTbl2, val->internalImageLumTableBaseR[1]); + } + if (val->refChrCompress) + { + EncAsicSetRegisterValue(val->regMirror, HEncRfcChrBufLimit, val->rfcChrBufLimit); + SET_ADDR_REG(val->regMirror, HEncBaseRefChrTbl, val->internalImageChrTableBaseR[0]); + SET_ADDR_REG(val->regMirror, HEncBaseRecChrTbl, val->internalImageChrTableBaseW); + SET_ADDR_REG(val->regMirror, HEncBaseRefChrTbl2, val->internalImageChrTableBaseR[1]); + } + } + + /* Stream start offset */ + EncAsicSetRegisterValue(val->regMirror, HEncStartOffset, val->firstFreeBit); + EncAsicSetRegisterValue(val->regMirror, HEncIpolFilterMode, val->ipolFilterMode); + + /* Stabilization */ + if(val->codingType != ASIC_JPEG) + { + SET_ADDR_REG(val->regMirror, HEncBaseNextLum, val->vsNextLumaBase); + EncAsicSetRegisterValue(val->regMirror, HEncStabMode, val->vsMode); + } + + EncAsicSetRegisterValue(val->regMirror, HEncDMVPenalty4p, val->pen[0][ASIC_PENALTY_DMV_4P]); + EncAsicSetRegisterValue(val->regMirror, HEncDMVPenalty1p, val->pen[0][ASIC_PENALTY_DMV_1P]); + EncAsicSetRegisterValue(val->regMirror, HEncDMVPenaltyQp, val->pen[0][ASIC_PENALTY_DMV_QP]); + + SET_ADDR_REG(val->regMirror, HEncBaseCabacCtx, val->cabacCtxBase); + SET_ADDR_REG(val->regMirror, HEncBaseMvWrite, val->mvOutputBase); + + EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffA, + val->colorConversionCoeffA & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffB, + val->colorConversionCoeffB & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffC, + val->colorConversionCoeffC & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffE, + val->colorConversionCoeffE & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffF, + val->colorConversionCoeffF & mask_16b); + + EncAsicSetRegisterValue(val->regMirror, HEncRMaskMSB, val->rMaskMsb & mask_5b); + EncAsicSetRegisterValue(val->regMirror, HEncGMaskMSB, val->gMaskMsb & mask_5b); + EncAsicSetRegisterValue(val->regMirror, HEncBMaskMSB, val->bMaskMsb & mask_5b); + + EncAsicSetRegisterValue(val->regMirror, HEncCirStart, val->cirStart); + EncAsicSetRegisterValue(val->regMirror, HEncCirInterval, val->cirInterval); + + EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaLeft, val->intraAreaLeft); + EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaRight, val->intraAreaRight); + EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaTop, val->intraAreaTop); + EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaBottom, val->intraAreaBottom); + EncAsicSetRegisterValue(val->regMirror, HEncRoi1Left, val->roi1Left); + EncAsicSetRegisterValue(val->regMirror, HEncRoi1Right, val->roi1Right); + EncAsicSetRegisterValue(val->regMirror, HEncRoi1Top, val->roi1Top); + EncAsicSetRegisterValue(val->regMirror, HEncRoi1Bottom, val->roi1Bottom); + + EncAsicSetRegisterValue(val->regMirror, HEncRoi2Left, val->roi2Left); + EncAsicSetRegisterValue(val->regMirror, HEncRoi2Right, val->roi2Right); + EncAsicSetRegisterValue(val->regMirror, HEncRoi2Top, val->roi2Top); + EncAsicSetRegisterValue(val->regMirror, HEncRoi2Bottom, val->roi2Bottom); + + /* H.264 specific */ + if (val->codingType == ASIC_H264) + { + /* Limit ROI delta QPs so that ROI area QP is always >= 0. + * ASIC doesn't check this. */ + EncAsicSetRegisterValue(val->regMirror, HEncRoi1DeltaQp, MIN((i32)val->qp, val->roi1DeltaQp)); + EncAsicSetRegisterValue(val->regMirror, HEncRoi2DeltaQp, MIN((i32)val->qp, val->roi2DeltaQp)); + + EncAsicSetRegisterValue(val->regMirror, HEncIntraSliceMap1, val->intraSliceMap1); + EncAsicSetRegisterValue(val->regMirror, HEncIntraSliceMap2, val->intraSliceMap2); + EncAsicSetRegisterValue(val->regMirror, HEncIntraSliceMap3, val->intraSliceMap3); + + /* MVC */ + EncAsicSetRegisterValue(val->regMirror, HEncMvcAnchorPicFlag, val->mvcAnchorPicFlag); + EncAsicSetRegisterValue(val->regMirror, HEncMvcPriorityId, val->mvcPriorityId); + EncAsicSetRegisterValue(val->regMirror, HEncMvcViewId, val->mvcViewId); + EncAsicSetRegisterValue(val->regMirror, HEncMvcTemporalId, val->mvcTemporalId); + EncAsicSetRegisterValue(val->regMirror, HEncMvcInterViewFlag, val->mvcInterViewFlag); + + EncAsicSetRegisterValue(val->regMirror, HEncFieldPicFlag, val->fieldPicFlag); + EncAsicSetRegisterValue(val->regMirror, HEncBottomFieldFlag, val->bottomFieldFlag); + EncAsicSetRegisterValue(val->regMirror, HEncFieldParity, val->fieldParity); + /* Boost */ + EncAsicSetRegisterValue(val->regMirror, HEncBoostQp, val->boostQp); + EncAsicSetRegisterValue(val->regMirror, HEncBoostVar1, val->boostVar1); + EncAsicSetRegisterValue(val->regMirror, HEncBoostVar2, val->boostVar2); + + /* Variane intar vs. inter favor */ + EncAsicSetRegisterValue(val->regMirror, HEncVarLimit, val->varLimitDiv32); + EncAsicSetRegisterValue(val->regMirror, HEncVarInterFavor, val->varInterFavorDiv16); + EncAsicSetRegisterValue(val->regMirror, HEncVarMultiplier, val->varMultiplier); + EncAsicSetRegisterValue(val->regMirror, HEncVarAdd, val->varAdd); + + /* Pskip coding mode */ + EncAsicSetRegisterValue(val->regMirror, HEncPskipMode, val->pskipMode); + + /* Denoise */ + EncAsicSetRegisterValue(val->regMirror, HEncDnfEnable, val->dnfEnable); + EncAsicSetRegisterValue(val->regMirror, HEncDnfNoiseMax, val->dnfNoiseLevelMax); + EncAsicSetRegisterValue(val->regMirror, HEncDnfNoiseLevelInvY, val->dnfNoiseLevelInvertY); + EncAsicSetRegisterValue(val->regMirror, HEncDnfNoiseLevelInvC, val->dnfNoiseLevelInvertC); + EncAsicSetRegisterValue(val->regMirror, HEncDnfStregth, val->dnfStrength); + #ifdef DNF_PARAM_REGS + for(i=0; i<16; i++) + { + EncAsicSetRegisterValue(val->regMirror, HEncDnfParaS1_0+i, val->dnfParamS1[i]); + } + for(i=0; i<16; i++) + { + EncAsicSetRegisterValue(val->regMirror, HEncDnfParaS2_0+i, val->dnfParamS2[i]); + } + for(i=0; i<64; i++) + { + EncAsicSetRegisterValue(val->regMirror, HEncDnfParaS3_0+i, val->dnfParamS3[i]); + } + for(i=0; i<64; i++) + { + EncAsicSetRegisterValue(val->regMirror, HEncDnfParaS4_0+i, val->dnfParamS4[i]); + } + #else + EncAsicSetRegisterValue(val->regMirror, HEncDnfBaseTable, val->dnfTable); + #endif + } + + EncAsicSetRegisterValue(val->regMirror, HEncMbWrPtr, val->mbWrPtr); + EncAsicSetRegisterValue(val->regMirror, HEncMbRdPtr, val->mbRrPtr); + EncAsicSetRegisterValue(val->regMirror, HEncLowLatencyHwSyncMbRows, val->lineBufferDepth); + EncAsicSetRegisterValue(val->regMirror, HEncLowLatencyEn, val->lineBufferEn); + EncAsicSetRegisterValue(val->regMirror, HEncLowLatencyHwIntfEn, val->lineBufferHwHandShake); + EncAsicSetRegisterValue(val->regMirror, HEncLowLatencyIrqEn, val->lineBufferIrqEnable); + EncAsicSetRegisterValue(val->regMirror, HEncInputBufferLoopBackEn, val->lineBufferLoopBackEn); + + /* VP8 specific */ + if (val->codingType == ASIC_VP8) + { + SET_ADDR_REG(val->regMirror, HEncBasePartition1, val->partitionBase[0]); + SET_ADDR_REG(val->regMirror, HEncBasePartition2, val->partitionBase[1]); + SET_ADDR_REG(val->regMirror, HEncBasePartition3, val->partitionBase[2]); + SET_ADDR_REG(val->regMirror, HEncBasePartition4, val->partitionBase[3]); + SET_ADDR_REG(val->regMirror, HEncBaseVp8ProbCount, val->probCountBase); + + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode0Penalty, val->pen[0][ASIC_PENALTY_I16MODE0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode1Penalty, val->pen[0][ASIC_PENALTY_I16MODE1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode2Penalty, val->pen[0][ASIC_PENALTY_I16MODE2]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode3Penalty, val->pen[0][ASIC_PENALTY_I16MODE3]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode0Penalty, val->pen[0][ASIC_PENALTY_I4MODE0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode1Penalty, val->pen[0][ASIC_PENALTY_I4MODE1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode2Penalty, val->pen[0][ASIC_PENALTY_I4MODE2]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode3Penalty, val->pen[0][ASIC_PENALTY_I4MODE3]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode4Penalty, val->pen[0][ASIC_PENALTY_I4MODE4]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode5Penalty, val->pen[0][ASIC_PENALTY_I4MODE5]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode6Penalty, val->pen[0][ASIC_PENALTY_I4MODE6]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode7Penalty, val->pen[0][ASIC_PENALTY_I4MODE7]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode8Penalty, val->pen[0][ASIC_PENALTY_I4MODE8]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode9Penalty, val->pen[0][ASIC_PENALTY_I4MODE9]); + + + for (i = 0; i < 3; i++) { + i32 off = (HEncVp8Seg2Y1QuantDc - HEncVp8Seg1Y1QuantDc) * i; + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1QuantDc+off, val->qpY1QuantDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1QuantAc+off, val->qpY1QuantAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2QuantDc+off, val->qpY2QuantDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2QuantAc+off, val->qpY2QuantAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChQuantDc+off, val->qpChQuantDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChQuantAc+off, val->qpChQuantAc[i+1]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1ZbinDc+off, val->qpY1ZbinDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1ZbinAc+off, val->qpY1ZbinAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2ZbinDc+off, val->qpY2ZbinDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2ZbinAc+off, val->qpY2ZbinAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChZbinDc+off, val->qpChZbinDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChZbinAc+off, val->qpChZbinAc[i+1]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1RoundDc+off, val->qpY1RoundDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1RoundAc+off, val->qpY1RoundAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2RoundDc+off, val->qpY2RoundDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2RoundAc+off, val->qpY2RoundAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChRoundDc+off, val->qpChRoundDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChRoundAc+off, val->qpChRoundAc[i+1]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1DequantDc+off, val->qpY1DequantDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1DequantAc+off, val->qpY1DequantAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2DequantDc+off, val->qpY2DequantDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2DequantAc+off, val->qpY2DequantAc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChDequantDc+off, val->qpChDequantDc[i+1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChDequantAc+off, val->qpChDequantAc[i+1]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1FilterLevel+off, val->filterLevel[i+1]); + } + + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta0, val->lfRefDelta[0] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta1, val->lfRefDelta[1] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta2, val->lfRefDelta[2] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta3, val->lfRefDelta[3] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta0, val->lfModeDelta[0] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta1, val->lfModeDelta[1] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta2, val->lfModeDelta[2] & mask_7b); + EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta3, val->lfModeDelta[3] & mask_7b); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8CostInter, val->pen[0][ASIC_PENALTY_COST_INTER]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DmvCostConst, val->pen[0][ASIC_PENALTY_DMV_COST_CONST]); + + EncAsicSetRegisterValue(val->regMirror, HEncVp8DzRateM0, val->pen[0][ASIC_PENALTY_DZ_RATE0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DzRateM1, val->pen[0][ASIC_PENALTY_DZ_RATE1]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DzRateM2, val->pen[0][ASIC_PENALTY_DZ_RATE2]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DzRateM3, val->pen[0][ASIC_PENALTY_DZ_RATE3]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DzSkipRate0, val->pen[0][ASIC_PENALTY_DZ_SKIP0]); + EncAsicSetRegisterValue(val->regMirror, HEncVp8DzSkipRate1, val->pen[0][ASIC_PENALTY_DZ_SKIP1]); + + } + + /* Mode decision penalty values for segments 1-3 */ + if(val->codingType != ASIC_JPEG) + { + for (i = 0; i < 3; i++) { + i32 off = (HEncSeg2I16Mode0Penalty - HEncSeg1I16Mode0Penalty) * i; + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode0Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode1Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode2Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE2]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode3Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE3]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode0Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode1Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode2Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE2]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode3Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE3]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode4Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode5Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE5]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode6Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE6]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode7Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE7]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode8Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode9Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE9]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Favor +off, val->pen[1+i][ASIC_PENALTY_I16FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1CostInter +off, val->pen[1+i][ASIC_PENALTY_COST_INTER]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4PrevModeFavor +off, val->pen[1+i][ASIC_PENALTY_I4_PREV_MODE_FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1InterFavor +off, val->pen[1+i][ASIC_PENALTY_INTER_FAVOR] & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SkipPenalty +off, val->pen[1+i][ASIC_PENALTY_SKIP]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1GoldenPenalty +off, val->pen[1+i][ASIC_PENALTY_GOLDEN]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty8x4 +off, val->pen[1+i][ASIC_PENALTY_SPLIT8x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty8x8 +off, val->pen[1+i][ASIC_PENALTY_SPLIT8x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty16x8+off, val->pen[1+i][ASIC_PENALTY_SPLIT16x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty4x4 +off, val->pen[1+i][ASIC_PENALTY_SPLIT4x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitZeroPenalty+off, val->pen[1+i][ASIC_PENALTY_SPLIT_ZERO]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DMVPenaltyQp +off, val->pen[1+i][ASIC_PENALTY_DMV_QP]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM0 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM1 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM2 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE2]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM3 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE3]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzSkipRate0 +off, val->pen[1+i][ASIC_PENALTY_DZ_SKIP0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzSkipRate1 +off, val->pen[1+i][ASIC_PENALTY_DZ_SKIP1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DmvCostConst +off, val->pen[1+i][ASIC_PENALTY_DMV_COST_CONST]); + } + + EncAsicSetRegisterValue(val->regMirror, HEncVp8AvgVar, val->avgVar); + EncAsicSetRegisterValue(val->regMirror, HEncVp8InvAvgVar, val->invAvgVar); + } + + if(val->codingType != ASIC_JPEG) + { + EncAsicSetRegisterValue(val->regMirror, HEncMBRCEnable, val->mbRcEnable); + //printf("val->qpfrac =0x%x\n",val->qpfrac); + EncAsicSetRegisterValue(val->regMirror, HEncMBRCQpFrac, val->qpfrac); + EncAsicSetRegisterValue(val->regMirror, HEncMBRcSliceQpOffset, val->offsetSliceQp & mask_6b); + + EncAsicSetRegisterValue(val->regMirror, HEncMBRCQpDeltaRange, val->mbQpDeltaRange); + + EncAsicSetRegisterValue(val->regMirror, HEncMBComplexityOffset, val->offsetMBComplexity); + + EncAsicSetRegisterValue(val->regMirror, HEncMBQpDeltaGain, val->qpDeltaMBGain); + + if(val->mbRcEnable) + { + for (i = 0; i < 3; i++) { + i32 off = (HEncSeg2I16Mode0Penalty - HEncSeg1I16Mode0Penalty) * i; + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode0Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode1Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode2Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE2]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Mode3Penalty +off, val->pen[1+i][ASIC_PENALTY_I16MODE3]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode0Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode1Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode2Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE2]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode3Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE3]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode4Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode5Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE5]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode6Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE6]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode7Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE7]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode8Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4Mode9Penalty +off, val->pen[1+i][ASIC_PENALTY_I4MODE9]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I16Favor +off, val->pen[1+i][ASIC_PENALTY_I16FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1CostInter +off, val->pen[1+i][ASIC_PENALTY_COST_INTER]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1I4PrevModeFavor +off, val->pen[1+i][ASIC_PENALTY_I4_PREV_MODE_FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1InterFavor +off, (val->pen[1+i][ASIC_PENALTY_INTER_FAVOR]) & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SkipPenalty +off, CLIP3(val->pen[1+i][ASIC_PENALTY_SKIP]/*+25*/,1,255)); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1GoldenPenalty +off, val->pen[1+i][ASIC_PENALTY_GOLDEN]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty8x4 +off, val->pen[1+i][ASIC_PENALTY_SPLIT8x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty8x8 +off, val->pen[1+i][ASIC_PENALTY_SPLIT8x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty16x8+off, val->pen[1+i][ASIC_PENALTY_SPLIT16x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitPenalty4x4 +off, val->pen[1+i][ASIC_PENALTY_SPLIT4x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1SplitZeroPenalty+off, val->pen[1+i][ASIC_PENALTY_SPLIT_ZERO]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DMVPenaltyQp +off, val->pen[1+i][ASIC_PENALTY_DMV_QP]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM0 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM1 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM2 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE2]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzRateM3 +off, val->pen[1+i][ASIC_PENALTY_DZ_RATE3]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzSkipRate0 +off, val->pen[1+i][ASIC_PENALTY_DZ_SKIP0]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DzSkipRate1 +off, val->pen[1+i][ASIC_PENALTY_DZ_SKIP1]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg1DmvCostConst +off, val->pen[1+i][ASIC_PENALTY_DMV_COST_CONST]); + } + + for (i = 3; i < 31; i++) { + i32 off = (HEncSeg5I4PrevModeFavor - HEncSeg4I4PrevModeFavor) * (i-3); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4I16Favor +off, val->pen[1+i][ASIC_PENALTY_I16FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4I4PrevModeFavor +off, val->pen[1+i][ASIC_PENALTY_I4_PREV_MODE_FAVOR]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4InterFavor +off, (val->pen[1+i][ASIC_PENALTY_INTER_FAVOR]) & mask_16b); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4SkipPenalty +off, CLIP3(val->pen[1+i][ASIC_PENALTY_SKIP]/*+25*/,1,255)); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4GoldenPenalty +off, val->pen[1+i][ASIC_PENALTY_GOLDEN]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4SplitPenalty8x4 +off, val->pen[1+i][ASIC_PENALTY_SPLIT8x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4SplitPenalty8x8 +off, val->pen[1+i][ASIC_PENALTY_SPLIT8x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4SplitPenalty16x8+off, val->pen[1+i][ASIC_PENALTY_SPLIT16x8]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4SplitPenalty4x4 +off, val->pen[1+i][ASIC_PENALTY_SPLIT4x4]); + EncAsicSetRegisterValue(val->regMirror, HEncSeg4DMVPenaltyQp +off, val->pen[1+i][ASIC_PENALTY_DMV_QP]); + } + } + + } + + /* Scaled output picture */ + SET_ADDR_REG(val->regMirror, HEncBaseScaledOutLum, val->scaledLumBase); + + EncAsicSetRegisterValue(val->regMirror, HEncScaleMode, val->scaledWidth > 0 ? 2 : 0); + EncAsicSetRegisterValue(val->regMirror, HEncScaledOutWidth, val->scaledWidth); + EncAsicSetRegisterValue(val->regMirror, HEncScaledOutHeight, val->scaledHeight); + EncAsicSetRegisterValue(val->regMirror, HEncScaledOutWidthRatio, val->scaledWidthRatio); + EncAsicSetRegisterValue(val->regMirror, HEncScaledOutHeightRatio, val->scaledHeightRatio); + + +#ifdef ASIC_WAVE_TRACE_TRIGGER + if(val->vop_count++ == trigger_point) + { + /* logic analyzer triggered by writing to the ID reg */ + EWLWriteReg(ewl, 0x00, ~0); + } +#endif + + /* Write regMirror to registers, 0x4 to 0xF8 */ + { + for(i = 1; i <= 62; i++) + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + } + + /* Write JPEG quantization tables to regs if needed (JPEG) */ + if(val->codingType == ASIC_JPEG) + { + for(i = 0; i < 128; i += 4) + { + /* swreg[64] to swreg[95] */ + EWLWriteReg(ewl, HSWREG(64 + (i/4)), + (val->quantTable[i ] << 24) | + (val->quantTable[i + 1] << 16) | + (val->quantTable[i + 2] << 8) | + (val->quantTable[i + 3])); + } + /* swreg[231]=0x39C to swreg[233]=0x3A4, scaler regs for dragonfly */ + if (val->asicHwId > ASIC_ID_CLOUDBERRY) { + for(i = 231; i <= 233; i++) + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + } + /* write MSB registers */ + EWLWriteReg(ewl, BASE_HEncBaseStream_MSB, val->regMirror[BASE_HEncBaseStream_MSB/4]); + EWLWriteReg(ewl, BASE_HEncBaseInLum_MSB, val->regMirror[BASE_HEncBaseInLum_MSB/4]); + EWLWriteReg(ewl, BASE_HEncBaseInCb_MSB, val->regMirror[BASE_HEncBaseInCb_MSB/4]); + EWLWriteReg(ewl, BASE_HEncBaseInCr_MSB, val->regMirror[BASE_HEncBaseInCr_MSB/4]); + + /* write input line buffer register */ + EWLWriteReg(ewl, BASE_HEncInstantInput, val->regMirror[BASE_HEncInstantInput/4]); + } + else + { + i32 i = 0; + + /* swreg[64]=0x100 to swreg[95]=0x17C, VP8 regs */ + for(i = 64; i <= 95; i++) + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + + /* Write DMV penalty tables to regs */ + for(i = 0; i < 128; i += 4) + { + /* swreg[96]=0x180 to swreg[127]=0x1FC */ + EWLWriteReg(ewl, HSWREG(96 + (i/4)), + (val->dmvPenalty[i ] << 24) | + (val->dmvPenalty[i + 1] << 16) | + (val->dmvPenalty[i + 2] << 8) | + (val->dmvPenalty[i + 3])); + } + for(i = 0; i < 128; i += 4) + { + /* swreg[128]=0x200 to swreg[159]=0x27C */ + EWLWriteReg(ewl, HSWREG(128 + (i/4)), + (val->dmvQpelPenalty[i ] << 24) | + (val->dmvQpelPenalty[i + 1] << 16) | + (val->dmvQpelPenalty[i + 2] << 8) | + (val->dmvQpelPenalty[i + 3])); + } + + /* swreg[160]=0x280 to swreg[163]=0x28C, VP8 regs */ + for(i = 160; i <= 163; i++) + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + + /* Write deadzone tables to regs when needed. */ + if ((val->asicHwId > ASIC_ID_BLUEBERRY) && val->deadzoneEnable) { + for(i = 0; i < 192; i += 4) + { + /* swreg[164]=0x290 to swreg[211]=0x34C */ + EWLWriteReg(ewl, HSWREG(164 + (i/4)), + (val->dzCoeffRate[i ] << 24) | + (val->dzCoeffRate[i + 1] << 16) | + (val->dzCoeffRate[i + 2] << 8) | + (val->dzCoeffRate[i + 3])); + } + for(i = 0; i < 64; i += 4) + { + /* swreg[212]=0x350 to swreg[227]=0x38C */ + EWLWriteReg(ewl, HSWREG(212 + (i/4)), + (val->dzEobRate[i ] << 24) | + (val->dzEobRate[i + 1] << 16) | + (val->dzEobRate[i + 2] << 8) | + (val->dzEobRate[i + 3])); + } + EWLWriteReg(ewl, HSWREG(228), val->regMirror[228]); + EWLWriteReg(ewl, HSWREG(229), val->regMirror[229]); + EWLWriteReg(ewl, HSWREG(230), val->regMirror[230]); + } + + /* swreg[231]=0x39C to swreg[238]=0x3B8, VP8 regs for dragonfly */ + if (val->asicHwId > ASIC_ID_CLOUDBERRY) { + for(i = 231; i <= 238; i++) + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + } + + /* swreg[239]=0x3BC to swreg[293]=0x490, VP8 regs for evergreen */ + if (val->asicHwId > ASIC_ID_DRAGONFLY) { + /* Write VP8 bicubic Ipol coeffs straight to regs */ + if (val->codingType == ASIC_VP8 && val->ipolFilterMode == 0) { + EWLWriteReg(ewl, HSWREG(239), (0<<29) | ( 0<<24) | (128<<16) | ( 0<<8) | ( 0<<3) | 0); + EWLWriteReg(ewl, HSWREG(240), (0<<29) | ( 6<<24) | (123<<16) | (12<<8) | ( 1<<3) | 0); + EWLWriteReg(ewl, HSWREG(241), (2<<29) | (11<<24) | (108<<16) | (36<<8) | ( 8<<3) | 1); + EWLWriteReg(ewl, HSWREG(242), (0<<29) | ( 9<<24) | ( 93<<16) | (50<<8) | ( 6<<3) | 0); + EWLWriteReg(ewl, HSWREG(243), (3<<29) | (16<<24) | ( 77<<16) | (77<<8) | (16<<3) | 3); + } else if (val->codingType == ASIC_VP8 && val->ipolFilterMode == 1) { + /* Write VP8 bilinear Ipol coeffs straight to regs */ + EWLWriteReg(ewl, HSWREG(239), (0<<29) | ( 0<<24) | (128<<16) | ( 0<<8) | ( 0<<3) | 0); + EWLWriteReg(ewl, HSWREG(240), (0<<29) | ( 0<<24) | (112<<16) | (16<<8) | ( 0<<3) | 0); + EWLWriteReg(ewl, HSWREG(241), (0<<29) | ( 0<<24) | ( 96<<16) | (32<<8) | ( 0<<3) | 0); + EWLWriteReg(ewl, HSWREG(242), (0<<29) | ( 0<<24) | ( 80<<16) | (48<<8) | ( 0<<3) | 0); + EWLWriteReg(ewl, HSWREG(243), (0<<29) | ( 0<<24) | ( 64<<16) | (64<<8) | ( 0<<3) | 0); + } else { + EWLWriteReg(ewl, HSWREG(239), 0); + EWLWriteReg(ewl, HSWREG(240), 0); + EWLWriteReg(ewl, HSWREG(241), 0); + EWLWriteReg(ewl, HSWREG(242), 0); + EWLWriteReg(ewl, HSWREG(243), 0); + } + for(i = 244; i < BASE_HWFuse2/4; i++) + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + + } + + if (val->asicHwId >= ASIC_ID_V7BASE) { + /* Skip the HWFuse2 register */ + for(i = (BASE_HWFuse2+4)/4; i < ASIC_SWREG_AMOUNT; i++) { + EWLWriteReg(ewl, HSWREG(i), val->regMirror[i]); + } + } + } + +#ifdef TRACE_REGS + EncTraceRegs(ewl, 0, 0); +#endif + + /* Register with enable bit is written last */ + val->regMirror[14] |= ASIC_STATUS_ENABLE; + + EWLEnableHW(ewl, HSWREG(14), val->regMirror[14]); +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +void EncAsicFrameContinue(const void *ewl, regValues_s * val) +{ + /* clear status bits, clear IRQ => HW restart */ + u32 status = val->regMirror[1]; + + if (!(EWLReadReg(ewl, BASE_HWFuse2)&HWCFGIrqClearSupport)) + { + status &= (~ASIC_STATUS_ALL); + status &= ~ASIC_IRQ_LINE; + } + + val->regMirror[1] = status; + + /*CheckRegisterValues(val); */ + + /* Write only registers which may be updated mid frame */ + EWLWriteReg(ewl, HSWREG(24), (val->rlcLimitSpace / 2)); + + val->regMirror[5] = val->rlcBase; + EWLWriteReg(ewl, HSWREG(5), val->regMirror[5]); + +#ifdef TRACE_REGS + EncTraceRegs(ewl, 0, EncAsicGetRegisterValue(ewl, val->regMirror, HEncMbCount)); +#endif + + /* Register with status bits is written last */ + EWLEnableHW(ewl, HSWREG(1), val->regMirror[1]); + +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +void EncAsicGetRegisters(const void *ewl, regValues_s * val) +{ + + /* HW output stream size, bits to bytes */ + val->outputStrmSize = + EncAsicGetRegisterValue(ewl, val->regMirror, HEncStrmBufLimit) / 8; + + /* Calculate frame PSNR based on the squared error. */ + val->squaredError = + EncAsicGetRegisterValue(ewl, val->regMirror, HEncSquaredError); + + if (val->squaredError) { + u32 pels; + + /* Error is calculated over 13x13 pixels on every macroblock. */ + pels = EncAsicGetRegisterValue(ewl, val->regMirror, HEncMbCount); + pels *= 13*13; + + if (pels) + val->mse_mul256 = val->squaredError < 0xFFFFFF ? + 256*val->squaredError/pels : + 256*(val->squaredError/pels); + else + val->mse_mul256 = 0; + } + + /* QP sum div2 */ + + val->qpSum = EncAsicGetRegisterValue(ewl, val->regMirror, HEncQpSum); + + val->rcMSESum = EncAsicGetRegisterValue(ewl, val->regMirror, HEncMBComplexityAverage); + /* MAD MB count*/ + val->madCount[0] = EncAsicGetRegisterValue(ewl, val->regMirror, HEncMadCount); + val->madCount[1] = EncAsicGetRegisterValue(ewl, val->regMirror, HEncMadCount2); + val->madCount[2] = EncAsicGetRegisterValue(ewl, val->regMirror, HEncMadCount3); + + val->avgVar = EncAsicGetRegisterValue(ewl, val->regMirror, HEncVp8AvgVar); + + /* Non-zero coefficient count*/ + val->rlcCount = EncAsicGetRegisterValue(ewl, val->regMirror, HEncRlcSum) * 4; + + /* Denoise */ + val->dnfNoiseLevelPred = EncAsicGetRegisterValue(ewl, val->regMirror, HEncDnfNoisePred); + val->dnfNoiseMaxPred = EncAsicGetRegisterValue(ewl, val->regMirror, HEncDnfThresholdPred); + val->dnfNoiseMbNum = EncAsicGetRegisterValue(ewl, val->regMirror, HEncDnfMbNum); + + /* get stabilization results if needed */ + if(val->vsMode != 0) + { + i32 i; + + for(i = 40; i <= 50; i++) + { + val->regMirror[i] = EWLReadReg(ewl, HSWREG(i)); + } + } + +#ifdef TRACE_REGS + EncTraceRegs(ewl, 1, EncAsicGetRegisterValue(ewl, val->regMirror, HEncMbCount)); +#endif + +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +void EncAsicStop(const void *ewl) +{ + EWLDisableHW(ewl, HSWREG(14), 0); +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +u32 EncAsicGetStatus(const void *ewl) +{ + return EWLReadReg(ewl, HSWREG(1)); +} + +/*------------------------------------------------------------------------------ + EncAsicGetMvOutput + Return encOutputMbInfo_s pointer to beginning of macroblock mbNum +------------------------------------------------------------------------------*/ +u32 * EncAsicGetMvOutput(asicData_s *asic, u32 mbNum) +{ + u32 *mvOutput = asic->mvOutput.virtualAddress; + u32 traceMbTiming = asic->regs.traceMbTiming; + + if (traceMbTiming) { /* encOutputMbInfoDebug_s */ + if (asic->regs.asicHwId <= ASIC_ID_EVERGREEN_PLUS) { + mvOutput += mbNum * 40/4; + } else { + mvOutput += mbNum * 56/4; + } + } else { /* encOutputMbInfo_s */ + if (asic->regs.asicHwId <= ASIC_ID_EVERGREEN_PLUS) { + mvOutput += mbNum * 32/4; + } else { + mvOutput += mbNum * 48/4; + } + } + + return mvOutput; +} + +/*------------------------------------------------------------------------------ + EncAsicClearStatusBit: clear IRQ status bit + when support write-one-clear method, apply new way. +------------------------------------------------------------------------------*/ +void EncAsicClearStatusBit(const void *ewl, u32 statusBit) +{ + u32 fuse2 = EWLReadReg(ewl, BASE_HWFuse2); + + if (fuse2&HWCFGIrqClearSupport) + { + EWLWriteReg(ewl, HSWREG(1), statusBit); + } + else + { + u32 status = EWLReadReg(ewl, HSWREG(1)); + status &= (~statusBit); + EWLWriteReg(ewl, HSWREG(1), status); + } + + return; +} + diff --git a/lib/vc8000nanoe/source/common/encasiccontroller.h b/lib/vc8000nanoe/source/common/encasiccontroller.h new file mode 100644 index 000000000..109460403 --- /dev/null +++ b/lib/vc8000nanoe/source/common/encasiccontroller.h @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : ASIC low level controller + * + ******************************************************************************** + */ +#ifndef __ENC_ASIC_CONTROLLER_H__ +#define __ENC_ASIC_CONTROLLER_H__ + +#include "basetype.h" +#include "enccfg.h" +#include "ewl.h" +#include "encswhwregisters.h" + +#define ASIC_STATUS_ENABLE 0x001 + +#define ASIC_H264_BYTE_STREAM 0x00 +#define ASIC_H264_NAL_UNIT 0x01 + +#define ASIC_PENALTY_UNDEFINED -1 + +#define ASIC_PENALTY_TABLE_SIZE 128 + +#if 0 +#define ASIC_FRAME_BUF_LUM_MAX 3 +#define ASIC_FRAME_BUF_CHR_MAX 4 +#else +#define ASIC_FRAME_BUF_LUM_MAX 4 /* L0/L1/L2/Recon for 4 Layers SVCT */ +#define ASIC_FRAME_BUF_CHR_MAX 4 +#endif + +typedef enum +{ + IDLE = 0, /* Initial state, both HW and SW disabled */ + HWON_SWOFF, /* HW processing, SW waiting for HW */ + HWON_SWON, /* Both HW and SW processing */ + HWOFF_SWON, /* HW is paused or disabled, SW is processing */ + DONE +} bufferState_e; + +typedef enum +{ + ASIC_VP8 = 1, + ASIC_JPEG = 2, + ASIC_H264 = 3 +} asicCodingType_e; + +typedef enum +{ + ASIC_P_16x16 = 0, + ASIC_P_16x8 = 1, + ASIC_P_8x16 = 2, + ASIC_P_8x8 = 3, + ASIC_I_4x4 = 4, + ASIC_I_16x16 = 5 +} asicMbType_e; + +typedef enum +{ + ASIC_INTER = 0, + ASIC_INTRA = 1, + ASIC_MVC = 2, + ASIC_MVC_REF_MOD = 3 +} asicFrameCodingType_e; + +enum +{ + ASIC_PENALTY_I16MODE0 = 0, + ASIC_PENALTY_I16MODE1, + ASIC_PENALTY_I16MODE2, + ASIC_PENALTY_I16MODE3, + ASIC_PENALTY_I4MODE0, + ASIC_PENALTY_I4MODE1, + ASIC_PENALTY_I4MODE2, + ASIC_PENALTY_I4MODE3, + ASIC_PENALTY_I4MODE4, + ASIC_PENALTY_I4MODE5, + ASIC_PENALTY_I4MODE6, + ASIC_PENALTY_I4MODE7, + ASIC_PENALTY_I4MODE8, + ASIC_PENALTY_I4MODE9, + ASIC_PENALTY_I16FAVOR, + ASIC_PENALTY_I4_PREV_MODE_FAVOR, + ASIC_PENALTY_COST_INTER, + ASIC_PENALTY_DMV_COST_CONST, + ASIC_PENALTY_INTER_FAVOR, + ASIC_PENALTY_SKIP, + ASIC_PENALTY_GOLDEN, + ASIC_PENALTY_SPLIT4x4, + ASIC_PENALTY_SPLIT8x4, + ASIC_PENALTY_SPLIT8x8, + ASIC_PENALTY_SPLIT16x8, + ASIC_PENALTY_SPLIT_ZERO, + ASIC_PENALTY_DMV_4P, + ASIC_PENALTY_DMV_1P, + ASIC_PENALTY_DMV_QP, + ASIC_PENALTY_DZ_RATE0, + ASIC_PENALTY_DZ_RATE1, + ASIC_PENALTY_DZ_RATE2, + ASIC_PENALTY_DZ_RATE3, + ASIC_PENALTY_DZ_SKIP0, + ASIC_PENALTY_DZ_SKIP1, + + ASIC_PENALTY_AMOUNT +}; + +typedef struct +{ + u32 irqDisable; + u32 irqInterval; + u32 traceMbTiming; + u32 inputReadChunk; + u32 mbsInCol; + u32 mbsInRow; + u32 qp; + u32 qpMin; + u32 qpMax; + u32 constrainedIntraPrediction; + u32 roundingCtrl; + u32 frameCodingType; + u32 codingType; + u32 pixelsOnRow; + u32 xFill; + u32 yFill; + u32 ppsId; + u32 idrPicId; + u32 frameNum; + u32 picInitQp; + i32 sliceAlphaOffset; + i32 sliceBetaOffset; + u32 filterDisable; + u32 transform8x8Mode; + u32 enableCabac; + u32 cabacInitIdc; + i32 chromaQpIndexOffset; + u32 chromaSwap; + u32 sliceSizeMbRows; + u32 inputImageFormat; + u32 inputImageRotation; + ptr_t outputStrmBase; + u32 outputStrmSize; + u32 firstFreeBit; + u32 strmStartMSB; + u32 strmStartLSB; + u32 rlcBase; + u32 rlcLimitSpace; + ptr_t sizeTblBase; + u32 sliceReadyInterrupt; + u32 recWriteBuffer; + u32 recWriteDisable; + u32 reorderFlag; + u32 reorderDiff; + u32 reconImageId; + ptr_t internalImageLumBaseW; + ptr_t internalImageChrBaseW; + ptr_t internalImageLumTableBaseW; + ptr_t internalImageChrTableBaseW; + ptr_t internalImageLumBaseR[2]; + ptr_t internalImageChrBaseR[2]; + ptr_t internalImageLumTableBaseR[2]; + ptr_t internalImageChrTableBaseR[2]; + u32 refLumCompress; + u32 refChrCompress; + u32 rfcLumDiscreteMode; + u32 rfcLumBufLimit; + u32 rfcChrBufLimit; + u32 rfcOverflowIRQEn; + ptr_t inputLumBase; + ptr_t inputCbBase; + ptr_t inputCrBase; + u32 cpDistanceMbs; + u32 *cpTargetResults; + const u32 *cpTarget; + const i32 *targetError; + const i32 *deltaQp; + u32 rlcCount; + u32 qpSum; + u32 h264StrmMode; /* 0 - byte stream, 1 - NAL units */ + u8 quantTable[8 * 8 * 2]; + u8 dmvPenalty[ASIC_PENALTY_TABLE_SIZE]; + u8 dmvQpelPenalty[ASIC_PENALTY_TABLE_SIZE]; + u32 ipolFilterMode; + u32 jpegMode; + u32 jpegSliceEnable; + u32 jpegRestartInterval; + u32 jpegRestartMarker; + u32 regMirror[ASIC_SWREG_AMOUNT]; + u32 inputLumaBaseOffset; + u32 inputLumaBaseOffsetVert; + u32 inputChromaBaseOffset; + u32 h264Inter4x4Disabled; + u32 disableQuarterPixelMv; + ptr_t vsNextLumaBase; + u32 vsMode; + u32 asicCfgReg; + u32 asicHwId; + i32 madQpDelta[3]; + u32 madThreshold[3]; + u32 madCount[3]; + u32 mvcAnchorPicFlag; + u32 mvcPriorityId; + u32 mvcViewId; + u32 mvcTemporalId; + u32 mvcInterViewFlag; + u32 cirStart; + u32 cirInterval; + u32 intraSliceMap1; + u32 intraSliceMap2; + u32 intraSliceMap3; + u32 intraAreaTop; + u32 intraAreaLeft; + u32 intraAreaBottom; + u32 intraAreaRight; + u32 roi1Top; + u32 roi1Left; + u32 roi1Bottom; + u32 roi1Right; + u32 roi2Top; + u32 roi2Left; + u32 roi2Bottom; + u32 roi2Right; + i32 roi1DeltaQp; + i32 roi2DeltaQp; + u32 roiUpdate; + u32 mvOutEnable; + ptr_t mvOutputBase; + ptr_t cabacCtxBase; + ptr_t probCountBase; + ptr_t segmentMapBase; + u32 colorConversionCoeffA; + u32 colorConversionCoeffB; + u32 colorConversionCoeffC; + u32 colorConversionCoeffE; + u32 colorConversionCoeffF; + u32 rMaskMsb; + u32 gMaskMsb; + u32 bMaskMsb; + ptr_t partitionBase[8]; + u32 qpY1QuantDc[4]; + u32 qpY1QuantAc[4]; + u32 qpY2QuantDc[4]; + u32 qpY2QuantAc[4]; + u32 qpChQuantDc[4]; + u32 qpChQuantAc[4]; + u32 qpY1ZbinDc[4]; + u32 qpY1ZbinAc[4]; + u32 qpY2ZbinDc[4]; + u32 qpY2ZbinAc[4]; + u32 qpChZbinDc[4]; + u32 qpChZbinAc[4]; + u32 qpY1RoundDc[4]; + u32 qpY1RoundAc[4]; + u32 qpY2RoundDc[4]; + u32 qpY2RoundAc[4]; + u32 qpChRoundDc[4]; + u32 qpChRoundAc[4]; + u32 qpY1DequantDc[4]; + u32 qpY1DequantAc[4]; + u32 qpY2DequantDc[4]; + u32 qpY2DequantAc[4]; + u32 qpChDequantDc[4]; + u32 qpChDequantAc[4]; + u32 segmentEnable; + u32 segmentMapUpdate; + u32 mvRefIdx[2]; + u32 ref2Enable; + u32 boolEncValue; + u32 boolEncValueBits; + u32 boolEncRange; + u32 dctPartitions; + u32 filterLevel[4]; + u32 filterSharpness; + u32 zeroMvFavorDiv2; + u32 splitMvMode; + i32 lfRefDelta[4]; + i32 lfModeDelta[4]; + u32 deadzoneEnable; + u8 dzCoeffRate[4*8*3*2]; /* Coeff 0&1 rate values for dead zone */ + u8 dzEobRate[4*8*2]; /* Eob token rate values for dead zone */ + u32 squaredError; + u32 mse_mul256; + ptr_t scaledLumBase; + + u32 scaledWidth; + u32 scaledHeight; + u32 scaledWidthRatio; + u32 scaledHeightRatio; + u32 avgVar; + u32 invAvgVar; + u32 fieldPicFlag; + u32 bottomFieldFlag; + u32 fieldParity; + u32 markCurrentLongTerm; + u32 boostQp; + u32 boostVar1; + u32 boostVar2; + u32 varLimitDiv32; + u32 varInterFavorDiv16; + u32 varMultiplier; + u32 varAdd; + u32 pskipMode; + + u32 pen[32][ASIC_PENALTY_AMOUNT]; /* Penalty values for four segments */ + + + u32 mbRcEnable; + i32 qpfrac; + u32 averageMBComplexity; + i32 offsetSliceQp; + u32 mbQpDeltaRange; + u32 offsetMBComplexity; + i32 qpDeltaMBGain; + u32 rcMSESum; + //u32 mbRcMap; + + /* noise reduction */ + u32 dnfEnable; + u32 dnfStrength; + ptr_t *dnfTable; + u32 dnfNoiseLevelInvertY; + u32 dnfNoiseLevelInvertC; + u32 dnfNoiseLevelMax; + u32 dnfNoiseMbNum; + u32 dnfNoiseMaxPred; + u32 dnfNoiseLevelPred; + u32 dnfParamS1[16]; + u32 dnfParamS2[16]; + u32 dnfParamS3[64]; + u32 dnfParamS4[64]; + + /* input line buffer */ + u32 mbWrPtr; + u32 mbRrPtr; + u32 lineBufferDepth; + u32 lineBufferEn; + u32 lineBufferHwHandShake; + u32 lineBufferIrqEnable; + u32 lineBufferLoopBackEn; + +#ifdef ASIC_WAVE_TRACE_TRIGGER + u32 vop_count; +#endif +} regValues_s; + +typedef struct +{ + const void *ewl; + regValues_s regs; + EWLLinearMem_t internalImageLuma[ASIC_FRAME_BUF_LUM_MAX]; + EWLLinearMem_t internalImageChroma[ASIC_FRAME_BUF_CHR_MAX]; + EWLLinearMem_t scaledImage; + EWLLinearMem_t cabacCtx; + EWLLinearMem_t mvOutput; + EWLLinearMem_t probCount; + EWLLinearMem_t segmentMap; + u32 sizeTblSize; + EWLLinearMem_t sizeTbl; + u32 traceRecon; + u32 internalImageLumSize; + u32 internalImageChrSize; + u32 irqStatus; +} asicData_s; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +i32 EncAsicControllerInit(asicData_s * asic); + +i32 EncAsicMemAlloc_V2(asicData_s * asic, u32 width, u32 height, + u32 scaledWidth, u32 scaledHeight, + u32 encodingType, u32 numRefBuffsLum, u32 numRefBuffsChr); +void EncAsicMemFree_V2(asicData_s * asic); + +/* Functions for controlling ASIC */ +void EncAsicSetQuantTable(asicData_s * asic, + const u8 * lumTable, const u8 * chTable); + +void EncAsicGetRegisters(const void *ewl, regValues_s * val); +u32 EncAsicGetStatus(const void *ewl); + +u32 EncAsicGetId(const void *ewl); + +void EncAsicFrameStart(const void *ewl, regValues_s * val); + +void EncAsicStop(const void *ewl); + +void EncAsicRecycleInternalImage(asicData_s *asic, u32 numViews, u32 viewId, + u32 anchor, u32 numRefBuffsLum, u32 numRefBuffsChr); + +i32 EncAsicCheckStatus_V2(asicData_s *asic); +u32 *EncAsicGetMvOutput(asicData_s *asic, u32 mbNum); +void EncAsicClearStatusBit(const void *ewl, u32 statusBit); + +#endif diff --git a/lib/vc8000nanoe/source/common/encasiccontroller_v2.c b/lib/vc8000nanoe/source/common/encasiccontroller_v2.c new file mode 100644 index 000000000..37b5b4323 --- /dev/null +++ b/lib/vc8000nanoe/source/common/encasiccontroller_v2.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : ASIC low level controller + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + Include headers +------------------------------------------------------------------------------*/ +#include "encpreprocess.h" +#include "encasiccontroller.h" +#include "enccommon.h" +#include "ewl.h" + +/*------------------------------------------------------------------------------ + External compiler flags +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Module defines +------------------------------------------------------------------------------*/ + +/* Mask fields */ +#define mask_2b (u32)0x00000003 +#define mask_3b (u32)0x00000007 +#define mask_4b (u32)0x0000000F +#define mask_5b (u32)0x0000001F +#define mask_6b (u32)0x0000003F +#define mask_11b (u32)0x000007FF +#define mask_14b (u32)0x00003FFF +#define mask_16b (u32)0x0000FFFF + +#define HSWREG(n) ((n)*4) + +/*------------------------------------------------------------------------------ + Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + EncAsicMemAlloc_V2 + + Allocate HW/SW shared memory + + Input: + asic asicData structure + width width of encoded image, multiple of four + height height of encoded image + type ASIC_MPEG4 / ASIC_H263 / ASIC_JPEG + numRefBuffs amount of reference luma frame buffers to be allocated + + Output: + asic base addresses point to allocated memory areas + + Return: + ENCHW_OK Success. + ENCHW_NOK Error: memory allocation failed, no memories allocated + and EWL instance released + +------------------------------------------------------------------------------*/ +i32 EncAsicMemAlloc_V2(asicData_s * asic, u32 width, u32 height, + u32 scaledWidth, u32 scaledHeight, + u32 encodingType, u32 numRefBuffsLum, u32 numRefBuffsChr) +{ + u32 mbTotal, i; + regValues_s *regs; + EWLLinearMem_t *buff = NULL; + + ASSERT(asic != NULL); + ASSERT(width != 0); + ASSERT(height != 0); + ASSERT((height % 2) == 0); + ASSERT((width % 4) == 0); + ASSERT(sizeof(encOutputMbInfoDebug_s)%8 == 0); + ASSERT(sizeof(encOutputMbInfo_s)%8 == 0); + + regs = &asic->regs; + + regs->codingType = encodingType; + + width = (width + 15) / 16; + height = (height + 15) / 16; + + mbTotal = width * height; + + /* Allocate H.264 internal memories */ + if(regs->codingType != ASIC_JPEG) + { + /* The sizes of the memories */ + u32 tableUnitNumInRow = (width + 3) / 4; + u32 internalImageRfcTableSize = tableUnitNumInRow * height * 8; + + u32 internalImageLumaTableSize = regs->refLumCompress ? internalImageRfcTableSize : 0; + u32 internalImageChromaTableSize = regs->refChrCompress ? internalImageRfcTableSize : 0; + + asic->internalImageLumSize = mbTotal * (16 * 16); + asic->internalImageChrSize = mbTotal * (2 * 8 * 8); + + ASSERT((numRefBuffsLum >= 1) && (numRefBuffsLum <= ASIC_FRAME_BUF_LUM_MAX)); + ASSERT((numRefBuffsChr >= 2) && (numRefBuffsChr <= ASIC_FRAME_BUF_CHR_MAX)); + + for (i = 0; i < numRefBuffsLum; i++) + { + if(EWLMallocRefFrm(asic->ewl, asic->internalImageLumSize + internalImageLumaTableSize, + &asic->internalImageLuma[i]) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + } + + for (i = 0; i < numRefBuffsChr; i++) + { + if(EWLMallocRefFrm(asic->ewl, asic->internalImageChrSize + internalImageChromaTableSize, + &asic->internalImageChroma[i]) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + } + + /* Set base addresses to the registers */ + regs->internalImageLumBaseW = asic->internalImageLuma[0].busAddress; + regs->internalImageChrBaseW = asic->internalImageChroma[0].busAddress; + if (numRefBuffsLum > 1) + regs->internalImageLumBaseR[0] = asic->internalImageLuma[1].busAddress; + else + regs->internalImageLumBaseR[0] = asic->internalImageLuma[0].busAddress; + regs->internalImageChrBaseR[0] = asic->internalImageChroma[1].busAddress; + + /* Optional scaled image output */ + if(scaledWidth*scaledHeight) { + if (EWLMallocRefFrm(asic->ewl, scaledWidth*scaledHeight*2, + &asic->scaledImage) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->scaledLumBase = asic->scaledImage.busAddress; + } + + /* NAL size table, table size must be 64-bit multiple, + * space for SEI, MVC prefix, filler and zero at the end of table. + * Atleast 1 macroblock row in every slice. + * Also used for VP8 partitions. */ + buff = &asic->sizeTbl; + asic->sizeTblSize = (sizeof(u32) * (height+4) + 7) & (~7); + + if(EWLMallocLinear(asic->ewl, asic->sizeTblSize, buff) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + + /* H264: CABAC context tables: all qps, intra+inter, 464 bytes/table. + * VP8: The same table is used for probability tables, 1208 bytes. */ + if (regs->codingType == ASIC_VP8) i = 8*55+8*96; + else i = 52*2*464; + + if(EWLMallocLinear(asic->ewl, i, &asic->cabacCtx) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->cabacCtxBase = asic->cabacCtx.busAddress; + + /* MV output table */ + if(EWLMallocLinear(asic->ewl, mbTotal*sizeof(encOutputMbInfoDebug_s), + &asic->mvOutput) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->mvOutputBase = asic->mvOutput.busAddress; + regs->mvOutEnable = 1; + + /* Clear mv output memory*/ + EWLmemset(asic->mvOutput.virtualAddress, 0, asic->mvOutput.size); + + if(regs->codingType == ASIC_VP8) { + /* VP8: Table of counter for probability updates. */ + if(EWLMallocLinear(asic->ewl, ASIC_VP8_PROB_COUNT_SIZE, + &asic->probCount) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->probCountBase = asic->probCount.busAddress; + + } + + /* Segmentation map, 4 bits/mb, 64-bit multiple. */ + if(EWLMallocLinear(asic->ewl, (mbTotal*4 + 63)/64*8, + &asic->segmentMap) != EWL_OK) + { + EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->segmentMapBase = asic->segmentMap.busAddress; + + EWLmemset(asic->segmentMap.virtualAddress, 0, + asic->segmentMap.size); + + } + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + EncAsicMemFree_V2 + + Free HW/SW shared memory + +------------------------------------------------------------------------------*/ +void EncAsicMemFree_V2(asicData_s * asic) +{ + i32 i; + + ASSERT(asic != NULL); + ASSERT(asic->ewl != NULL); + + for (i = 0; i < ASIC_FRAME_BUF_LUM_MAX; i++) { + if(asic->internalImageLuma[i].virtualAddress != NULL) + EWLFreeRefFrm(asic->ewl, &asic->internalImageLuma[i]); + asic->internalImageLuma[i].virtualAddress = NULL; + } + + for (i = 0; i < ASIC_FRAME_BUF_CHR_MAX; i++) { + if(asic->internalImageChroma[i].virtualAddress != NULL) + EWLFreeRefFrm(asic->ewl, &asic->internalImageChroma[i]); + asic->internalImageChroma[i].virtualAddress = NULL; + } + + if (asic->scaledImage.virtualAddress != NULL) + EWLFreeRefFrm(asic->ewl, &asic->scaledImage); + + if(asic->sizeTbl.virtualAddress != NULL) + EWLFreeLinear(asic->ewl, &asic->sizeTbl); + + if(asic->cabacCtx.virtualAddress != NULL) + EWLFreeLinear(asic->ewl, &asic->cabacCtx); + + if(asic->mvOutput.virtualAddress != NULL) + EWLFreeLinear(asic->ewl, &asic->mvOutput); + + if(asic->probCount.virtualAddress != NULL) + EWLFreeLinear(asic->ewl, &asic->probCount); + + if(asic->segmentMap.virtualAddress != NULL) + EWLFreeLinear(asic->ewl, &asic->segmentMap); + + asic->scaledImage.virtualAddress = NULL; + asic->sizeTbl.virtualAddress = NULL; + asic->cabacCtx.virtualAddress = NULL; + asic->mvOutput.virtualAddress = NULL; + asic->probCount.virtualAddress = NULL; + asic->segmentMap.virtualAddress = NULL; +} + +/*------------------------------------------------------------------------------ +------------------------------------------------------------------------------*/ +i32 EncAsicCheckStatus_V2(asicData_s * asic) +{ + i32 ret; + u32 status; + + status = EncAsicGetStatus(asic->ewl); + status &= ASIC_STATUS_ALL; + asic->irqStatus = status; + + if(status & ASIC_STATUS_ERROR) + { + /* Get registers for debugging */ + EncAsicGetRegisters(asic->ewl, &asic->regs); + + ret = ASIC_STATUS_ERROR; + + EWLReleaseHw(asic->ewl); + } + else if(status & ASIC_STATUS_HW_TIMEOUT) + { + /* Get registers for debugging */ + EncAsicGetRegisters(asic->ewl, &asic->regs); + + ret = ASIC_STATUS_HW_TIMEOUT; + + EWLReleaseHw(asic->ewl); + } + else if(status & ASIC_STATUS_FRAME_READY) + { + EncAsicGetRegisters(asic->ewl, &asic->regs); + + ret = ASIC_STATUS_FRAME_READY; + + EWLReleaseHw(asic->ewl); + } + else if(status & ASIC_STATUS_BUFF_FULL) + { + ret = ASIC_STATUS_BUFF_FULL; + /* ASIC doesn't support recovery from buffer full situation, + * at the same time with buff full ASIC also resets itself. */ + EWLReleaseHw(asic->ewl); + } + else if(status & ASIC_STATUS_HW_RESET) + { + ret = ASIC_STATUS_HW_RESET; + + EWLReleaseHw(asic->ewl); + } + else if(status & ASIC_STATUS_FUSE) + { + ret = ASIC_STATUS_FUSE; + + EWLReleaseHw(asic->ewl); + } + else if(status & ASIC_STATUS_LINE_BUFFER_DONE) + { + ret = ASIC_STATUS_LINE_BUFFER_DONE; + EncAsicClearStatusBit(asic->ewl, ASIC_STATUS_LINE_BUFFER_DONE); + } + else if(status & ASIC_STATUS_RFC_BUFF_OVERFLOW) + { + ret = ASIC_STATUS_RFC_BUFF_OVERFLOW; + EncAsicClearStatusBit(asic->ewl, ASIC_STATUS_RFC_BUFF_OVERFLOW); + } + else /* Don't check SLICE_READY status bit, it is reseted by IRQ handler */ + { + /* IRQ received but none of the status bits is high, so it must be + * slice ready. */ + ret = ASIC_STATUS_SLICE_READY; + } + + return ret; +} diff --git a/lib/vc8000nanoe/source/common/enccfg.h b/lib/vc8000nanoe/source/common/enccfg.h new file mode 100644 index 000000000..30b70ba6b --- /dev/null +++ b/lib/vc8000nanoe/source/common/enccfg.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encoder common configuration parameters + * + ******************************************************************************** + */ +#ifndef __ENCCFG_H__ +#define __ENCCFG_H__ + +#include "basetype.h" + +/* Here is defined the default values for the encoder build-time configuration. + * You can override these settings by defining the values as compiler flags + * in the Makefile. + */ + +#ifdef PCIE_FPGA_VERIFICATION +#define ENCH1_INPUT_SWAP_32_YUV 1 +#define ENCH1_INPUT_SWAP_32_RGB16 1 +#define ENCH1_INPUT_SWAP_32_RGB32 1 +#define ENCH1_OUTPUT_SWAP_32 1 +#endif + +/* The input image's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC input YUV + * 1 = 64-bit endianess */ +#ifndef ENCH1_INPUT_SWAP_32_YUV +#define ENCH1_INPUT_SWAP_32_YUV 1 +#endif + +/* The input image's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC input YUV + */ +#ifndef ENCH1_INPUT_SWAP_16_YUV +#define ENCH1_INPUT_SWAP_16_YUV 1 +#endif + +/* The input image's 8-bit swap: 0 or 1 + * This defines the byte endianess of the ASIC input YUV + */ +#ifndef ENCH1_INPUT_SWAP_8_YUV +#define ENCH1_INPUT_SWAP_8_YUV 1 +#endif + +/* The input image's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC input RGB16 + * 1 = 64-bit endianess */ +#ifndef ENCH1_INPUT_SWAP_32_RGB16 +#define ENCH1_INPUT_SWAP_32_RGB16 1 +#endif + +/* The input image's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC input RGB16 + */ +#ifndef ENCH1_INPUT_SWAP_16_RGB16 +#define ENCH1_INPUT_SWAP_16_RGB16 1 +#endif + +/* The input image's byte swap: 0 or 1 + * This defines the byte endianess of the ASIC input RGB16 + */ +#ifndef ENCH1_INPUT_SWAP_8_RGB16 +#define ENCH1_INPUT_SWAP_8_RGB16 0 +#endif + +/* The input image's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC input RGB32 + * 1 = 64-bit endianess */ +#ifndef ENCH1_INPUT_SWAP_32_RGB32 +#define ENCH1_INPUT_SWAP_32_RGB32 1 +#endif + +/* The input image's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC input RGB32 + */ +#ifndef ENCH1_INPUT_SWAP_16_RGB32 +#define ENCH1_INPUT_SWAP_16_RGB32 0 +#endif + +/* The input image's byte swap: 0 or 1 + * This defines the byte endianess of the ASIC input RGB32 + */ +#ifndef ENCH1_INPUT_SWAP_8_RGB32 +#define ENCH1_INPUT_SWAP_8_RGB32 0 +#endif + +/* ENCH1_OUTPUT_SWAP_XX define the byte endianess of the ASIC output stream. + * This MUST be configured to be the same as the native system endianess, + * because the control software relies on system endianess when reading + * the data from the memory. */ + +/* The output stream's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC output stream + * 1 = 64-bit endianess */ +#ifndef ENCH1_OUTPUT_SWAP_32 +#define ENCH1_OUTPUT_SWAP_32 1 +#endif + +/* The output stream's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC output stream. + */ +#ifndef ENCH1_OUTPUT_SWAP_16 +#define ENCH1_OUTPUT_SWAP_16 1 +#endif + +/* The output stream's 8-bit swap: 0 or 1 + * This defines the byte endianess of the ASIC output stream. + */ +#ifndef ENCH1_OUTPUT_SWAP_8 +#define ENCH1_OUTPUT_SWAP_8 1 +#endif + +/* The output down-scaled image's swapping is defined the same way as + * output stream swapping. Typically these should be the same values + * as for output stream. */ +#ifndef ENCH1_SCALE_OUTPUT_SWAP_32 +#define ENCH1_SCALE_OUTPUT_SWAP_32 ENCH1_OUTPUT_SWAP_32 +#endif +#ifndef ENCH1_SCALE_OUTPUT_SWAP_16 +#define ENCH1_SCALE_OUTPUT_SWAP_16 ENCH1_OUTPUT_SWAP_16 +#endif +#ifndef ENCH1_SCALE_OUTPUT_SWAP_8 +#define ENCH1_SCALE_OUTPUT_SWAP_8 ENCH1_OUTPUT_SWAP_8 +#endif + +/* The output MV and macroblock info swapping is defined the same way as + * output stream swapping. Typically these should be the same values + * as for output stream. */ +#ifndef ENCH1_MV_OUTPUT_SWAP_32 +#define ENCH1_MV_OUTPUT_SWAP_32 ENCH1_OUTPUT_SWAP_32 +#endif +#ifndef ENCH1_MV_OUTPUT_SWAP_16 +#define ENCH1_MV_OUTPUT_SWAP_16 ENCH1_OUTPUT_SWAP_16 +#endif +#ifndef ENCH1_MV_OUTPUT_SWAP_8 +#define ENCH1_MV_OUTPUT_SWAP_8 ENCH1_OUTPUT_SWAP_8 +#endif + +/* ASIC interrupt enable. + * This enables/disables the ASIC to generate interrupts + * If this is '1', the EWL must poll the registers to find out + * when the HW is ready. + */ +#ifndef ENCH1_IRQ_DISABLE +#define ENCH1_IRQ_DISABLE 0 +#endif + +/* ASIC bus interface configuration values */ +/* DO NOT CHANGE IF NOT FAMILIAR WITH THE CONCEPTS INVOLVED */ + +/* Burst length. This sets the maximum length of a single ASIC burst in addresses. + * Allowed values are: + * AHB {0, 4, 8, 16} ( 0 means incremental burst type INCR) + * OCP [1,63] + * AXI [1,16] + */ +#ifndef ENCH1_BURST_LENGTH +#define ENCH1_BURST_LENGTH 16 +#endif + +/* SCMD burst mode disable */ +/* 0 - enable SCMD burst mode */ +/* 1 - disable SCMD burst mode */ +#ifndef ENCH1_BURST_SCMD_DISABLE +#define ENCH1_BURST_SCMD_DISABLE 0 +#endif + +/* INCR type burst mode */ +/* 0 - enable INCR type bursts */ +/* 1 - disable INCR type and use SINGLE instead */ +#ifndef ENCH1_BURST_INCR_TYPE_ENABLED +#define ENCH1_BURST_INCR_TYPE_ENABLED 0 +#endif + +/* Data discard mode. When enabled read bursts of length 2 or 3 are converted */ +/* to BURST4 and useless data is discarded. Otherwise use INCR type for that */ +/* kind of read bursts */ +/* 0 - disable data discard */ +/* 1 - enable data discard */ +#ifndef ENCH1_BURST_DATA_DISCARD_ENABLED +#define ENCH1_BURST_DATA_DISCARD_ENABLED 0 +#endif + +/* AXI bus read and write ID values used by HW. 0 - 255 */ +#ifndef ENCH1_AXI_READ_ID +#define ENCH1_AXI_READ_ID 0 +#endif + +#define ENCH1_AXI_READ_ID_C0 1 +#define ENCH1_AXI_READ_ID_C1 2 +#define ENCH1_AXI_READ_ID_C2 3 +#ifndef ENCH1_AXI_READ_ID_EN +#define ENCH1_AXI_READ_ID_EN 1 +#endif + +#ifndef ENCH1_AXI_WRITE_ID +#define ENCH1_AXI_WRITE_ID 0 +#endif + +/* End of "ASIC bus interface configuration values" */ + +/* ASIC internal clock gating control. 0 - disabled, 1 - enabled */ +#ifndef ENCH1_ASIC_CLOCK_GATING_ENABLED +#define ENCH1_ASIC_CLOCK_GATING_ENABLED 0 +#endif + +/* ASIC timeout interrupt enable/disable */ +#ifndef ENCH1_TIMEOUT_INTERRUPT +#define ENCH1_TIMEOUT_INTERRUPT 1 +#endif + +/* H.264 slice ready interrupt enable/disable. When enabled the HW will raise */ +/* interrupt after every completed slice creating several IRQ per frame. */ +/* When disabled the HW will raise interrupt only when the frame encoding is */ +/* finished. */ +#ifndef ENCH1_SLICE_READY_INTERRUPT +#define ENCH1_SLICE_READY_INTERRUPT 1 +#endif + +/* ASIC input picture read chunk size, 0=4 MBs, 1=1 MB */ +#ifndef ENCH1_INPUT_READ_CHUNK +#define ENCH1_INPUT_READ_CHUNK 0 +#endif + +/* AXI bus dual channel disable, 0=use two channels, 1=use single channel. */ +#ifndef ENCH1_AXI_2CH_DISABLE +#define ENCH1_AXI_2CH_DISABLE 1 /* for STM Panther 0=>1 */ +#endif + +/* Reconstructed picture output writing, 0=1 MB (write burst for every MB), + 1=4MBs (write burst for every fourth MB). */ +#ifndef ENCH1_REC_WRITE_BUFFER +#define ENCH1_REC_WRITE_BUFFER 1 +#endif + +/* How often to update VP8 entropy probabilities, higher value lowers SW load. + 1=update for every frame, 2=update for every second frame, etc. */ +#ifndef ENCH1_VP8_ENTROPY_UPDATE_DISTANCE +#define ENCH1_VP8_ENTROPY_UPDATE_DISTANCE 1 +#endif + +/* ASIC RFC overflow interrupt enable/disable */ +#ifndef ENCH1_RFC_OVERFLOW_INTERRUPT +#define ENCH1_RFC_OVERFLOW_INTERRUPT 1 +#endif + +#endif diff --git a/lib/vc8000nanoe/source/common/encpreprocess.c b/lib/vc8000nanoe/source/common/encpreprocess.c new file mode 100644 index 000000000..833ea5a7f --- /dev/null +++ b/lib/vc8000nanoe/source/common/encpreprocess.c @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Preprocessor setup + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "encpreprocess.h" +#include "enccommon.h" + +/* Minimum number of frames for how often the ROI can change. + Each ROI change has to signal new segment map which uses a lot of bits, + but the more frames there is between updates the more motion can occur. */ +#ifndef H1ENC_AROI_MIN_UPDATE_FRAMES +#define H1ENC_AROI_MIN_UPDATE_FRAMES 10 +#endif + +/* Enable white balance fixing. */ +#ifndef H1ENC_AROI_WHITE_BALANCE_FIX +#define H1ENC_AROI_WHITE_BALANCE_FIX 1 +#endif + +/* Fixed threshold for skin MAD, MBs > threshold are selected. */ +#ifndef H1ENC_AROI_SKIN_MAD_THRESHOLD +#define H1ENC_AROI_SKIN_MAD_THRESHOLD 2 +#endif + +/* Filter box dimensions. BoxWidth*2+1 x BoxHeight*2+1 macroblock filter + is applied on skin map to find the skin-colored face shapes. */ +#ifndef H1ENC_AROI_FILTER_BOX_HEIGHT +#define H1ENC_AROI_FILTER_BOX_HEIGHT mbPerCol/5/2 +#endif + +#ifndef H1ENC_AROI_FILTER_BOX_WIDTH +#define H1ENC_AROI_FILTER_BOX_WIDTH mbPerCol/5*3/4/2 +#endif + +/* Threshold factor for macroblock score, all MBs >= threshold are selected. */ +#ifndef H1ENC_AROI_SCORE_THRESHOLD +#define H1ENC_AROI_SCORE_THRESHOLD 2/3*4/3 +#endif + +/* Threshold for updating ROI segment in percentage of MBs. */ +#ifndef H1ENC_AROI_UPDATE_THRESHOLD +#define H1ENC_AROI_UPDATE_THRESHOLD 70 +#endif + +/* Define this if you want to write aroi.yuv and aroi.trc + DEBUG_AROI == 1 for frame level trace, 2 for MB level trace +#define DEBUG_AROI 1 */ + +#ifdef DEBUG_AROI +#include + +void TraceAroiYuv(asicData_s * asic, preProcess_s * preProcess); +void TraceAroi(asicData_s * asic, preProcess_s * preProcess, + i32 stage, i32 value); +#endif + +void EncAdaptiveROI(asicData_s * asic, preProcess_s * preProcess); + +/*------------------------------------------------------------------------------ + EncPreProcessAlloc +------------------------------------------------------------------------------*/ +i32 EncPreProcessAlloc(preProcess_s * preProcess, i32 mbPerPicture) +{ + i32 status = ENCHW_OK; + i32 i; + + for (i = 0; i < 3; i++) { + preProcess->roiSegmentMap[i] = (u8 *)EWLcalloc(mbPerPicture, sizeof(u8)); + if (preProcess->roiSegmentMap[i] == NULL) status = ENCHW_NOK; + } + + for (i = 0; i < 2; i++) { + preProcess->skinMap[i] = (u8 *)EWLcalloc(mbPerPicture, sizeof(u8)); + if (preProcess->skinMap[i] == NULL) status = ENCHW_NOK; + } + + preProcess->mvMap = (i32 *)EWLcalloc(mbPerPicture, sizeof(i32)); + if (preProcess->mvMap == NULL) status = ENCHW_NOK; + + preProcess->scoreMap = (u8 *)EWLcalloc(mbPerPicture, sizeof(u8)); + if (preProcess->scoreMap == NULL) status = ENCHW_NOK; + + if (status != ENCHW_OK) { + EncPreProcessFree(preProcess); + return ENCHW_NOK; + } + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + EncPreProcessFree +------------------------------------------------------------------------------*/ +void EncPreProcessFree(preProcess_s * preProcess) +{ + i32 i; + + for (i = 0; i < 3; i++) { + if (preProcess->roiSegmentMap[i]) EWLfree(preProcess->roiSegmentMap[i]); + preProcess->roiSegmentMap[i] = NULL; + } + + for (i = 0; i < 2; i++) { + if (preProcess->skinMap[i]) EWLfree(preProcess->skinMap[i]); + preProcess->skinMap[i] = NULL; + } + + if (preProcess->mvMap) EWLfree(preProcess->mvMap); + preProcess->mvMap = NULL; + + if (preProcess->scoreMap) EWLfree(preProcess->scoreMap); + preProcess->scoreMap = NULL; +} + +/*------------------------------------------------------------------------------ + Module defines +------------------------------------------------------------------------------*/ + +/* Input format mapping API values to SW/HW register values. */ +static const u32 inputFormatMapping[17] = { + ASIC_INPUT_YUV420PLANAR, + ASIC_INPUT_YUV420SEMIPLANAR, + ASIC_INPUT_YUV420SEMIPLANAR, + ASIC_INPUT_YUYV422INTERLEAVED, + ASIC_INPUT_UYVY422INTERLEAVED, + ASIC_INPUT_RGB565, + ASIC_INPUT_RGB565, + ASIC_INPUT_RGB555, + ASIC_INPUT_RGB555, + ASIC_INPUT_RGB444, + ASIC_INPUT_RGB444, + ASIC_INPUT_RGB888, + ASIC_INPUT_RGB888, + ASIC_INPUT_RGB101010, + ASIC_INPUT_RGB101010, + ASIC_INPUT_SP_101010, + ASIC_INPUT_P010 +}; + +static const u32 rgbMaskBits[15][3] = { + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 15, 10, 4 }, /* RGB565 */ + { 4, 10, 15 }, /* BGR565 */ + { 14, 9, 4 }, /* RGB565 */ + { 4, 9, 14 }, /* BGR565 */ + { 11, 7, 3 }, /* RGB444 */ + { 3, 7, 11 }, /* BGR444 */ + { 23, 15, 7 }, /* RGB888 */ + { 7, 15, 23 }, /* BGR888 */ + { 29, 19, 9 }, /* RGB101010 */ + { 9, 19, 29 } /* BGR101010 */ +}; + +/*------------------------------------------------------------------------------ + + EncPreProcessCheck + + Check image size: Cropped frame _must_ fit inside of source image + + Input preProcess Pointer to preProcess_s structure. + + Return ENCHW_OK No errors. + ENCHW_NOK Error condition. + +------------------------------------------------------------------------------*/ +i32 EncPreProcessCheck(const preProcess_s * preProcess) +{ + i32 status = ENCHW_OK; + u32 tmp; + u32 width, height; + +#if 0 /* These limits apply for input stride but camstab needs the + actual pixels without padding. */ + u32 w_mask; + + /* Check width limits: lum&ch strides must be full 64-bit addresses */ + if(preProcess->inputFormat == 0) /* YUV 420 planar */ + w_mask = 0x0F; /* 16 multiple */ + else if(preProcess->inputFormat <= 1) /* YUV 420 semiplanar */ + w_mask = 0x07; /* 8 multiple */ + else if(preProcess->inputFormat <= 9) /* YUYV 422 or 16-bit RGB */ + w_mask = 0x03; /* 4 multiple */ + else /* 32-bit RGB */ + w_mask = 0x01; /* 2 multiple */ + + if(preProcess->lumWidthSrc & w_mask) + { + status = ENCHW_NOK; + } +#endif + + if(preProcess->lumHeightSrc & 0x01) + { + status = ENCHW_NOK; + } + + if(preProcess->lumWidthSrc > MAX_INPUT_IMAGE_WIDTH) + { + status = ENCHW_NOK; + } + + width = preProcess->lumWidth; + height = preProcess->lumHeight; + if(preProcess->rotation == 1 || preProcess->rotation == 2) + { + u32 tmp; + + tmp = width; + width = height; + height = tmp; + } + + /* Bottom right corner */ + tmp = preProcess->horOffsetSrc + width; + if(tmp > preProcess->lumWidthSrc) + { + status = ENCHW_NOK; + } + + tmp = preProcess->verOffsetSrc + height; + if(tmp > preProcess->lumHeightSrc) + { + status = ENCHW_NOK; + } + + return status; +} + +/*------------------------------------------------------------------------------ + + EncPreProcess + + Preform cropping + + Input asic Pointer to asicData_s structure + preProcess Pointer to preProcess_s structure. + +------------------------------------------------------------------------------*/ +void EncPreProcess(asicData_s * asic, preProcess_s * preProcess) +{ + u32 tmp; + u32 width, height; + regValues_s *regs; + u32 stride; + u32 horOffsetSrc = preProcess->horOffsetSrc; + + ASSERT(asic != NULL && preProcess != NULL); + + regs = &asic->regs; + + stride = (preProcess->lumWidthSrc + 15) & (~15); /* 16 pixel multiple stride */ + + /* When input is interlaced frame containing two fields we read the frame + with twice the width and crop the left(top) or right(bottom) field. */ + if (preProcess->interlacedFrame) { + if (preProcess->bottomField) horOffsetSrc += stride; + stride *= 2; + } + + /* cropping */ + if(preProcess->inputFormat <= 2) /* YUV 420 planar/semiplanar */ + { + /* Input image position after crop and stabilization */ + tmp = preProcess->verOffsetSrc; + tmp *= stride; + tmp += horOffsetSrc; + regs->inputLumBase += (tmp & (~7)); + regs->inputLumaBaseOffset = tmp & 7; + + if(preProcess->videoStab) + regs->vsNextLumaBase += (tmp & (~7)); + + /* Chroma */ + if(preProcess->inputFormat == 0) + { + tmp = preProcess->verOffsetSrc / 2; + tmp *= stride / 2; + tmp += horOffsetSrc / 2; + + regs->inputCbBase += (tmp & (~7)); + regs->inputCrBase += (tmp & (~7)); + regs->inputChromaBaseOffset = tmp & 7; + } + else + { + tmp = preProcess->verOffsetSrc / 2; + tmp *= stride / 2; + tmp += horOffsetSrc / 2; + tmp *= 2; + + regs->inputCbBase += (tmp & (~7)); + regs->inputChromaBaseOffset = tmp & 7; + } + } + else if(preProcess->inputFormat <= 10) /* YUV 422 / RGB 16bpp */ + { + /* Input image position after crop and stabilization */ + tmp = preProcess->verOffsetSrc; + tmp *= stride; + tmp += horOffsetSrc; + tmp *= 2; + + regs->inputLumBase += (tmp & (~7)); + regs->inputLumaBaseOffset = tmp & 7; + regs->inputChromaBaseOffset = (regs->inputLumaBaseOffset / 4) * 4; + + if(preProcess->videoStab) + regs->vsNextLumaBase += (tmp & (~7)); + } + else if(preProcess->inputFormat <= 14) /* RGB 32bpp */ + { + /* Input image position after crop and stabilization */ + tmp = preProcess->verOffsetSrc; + tmp *= stride; + tmp += horOffsetSrc; + tmp *= 4; + + regs->inputLumBase += (tmp & (~7)); + /* Note: HW does the cropping AFTER RGB to YUYV conversion + * so the offset is calculated using 16bpp */ + regs->inputLumaBaseOffset = (tmp & 7)/2; + + if(preProcess->videoStab) + regs->vsNextLumaBase += (tmp & (~7)); + } + else /* P010 planar/semi planar */ + { + /* Input image position after crop and stabilization */ + tmp = preProcess->verOffsetSrc; + tmp *= stride; + tmp += horOffsetSrc; + tmp *= 2; + + regs->inputLumBase += (tmp & (~7)); + regs->inputLumaBaseOffset = tmp & 7; + regs->inputChromaBaseOffset = (regs->inputLumaBaseOffset / 4) * 4; + + if(preProcess->videoStab) + regs->vsNextLumaBase += (tmp & (~7)); + + /* Chroma */ + tmp = preProcess->verOffsetSrc / 2; + tmp *= stride / 2; + tmp += horOffsetSrc / 2; + tmp *= 2*2; + + regs->inputCbBase += (tmp & (~7)); + regs->inputCrBase += (tmp & (~7)); + regs->inputChromaBaseOffset = tmp & 7; + } + + /* YUV subsampling, map API values into HW reg values */ + regs->inputImageFormat = inputFormatMapping[preProcess->inputFormat]; + + if (preProcess->inputFormat == 2) + regs->chromaSwap = 1; + + regs->inputImageRotation = preProcess->rotation; + + /* source image setup, size and fill */ + width = preProcess->lumWidth; + height = preProcess->lumHeight; + + /* Scaling ratio for down-scaling, fixed point 1.16, calculate from + rotated dimensions. */ + if (preProcess->scaledWidth*preProcess->scaledHeight && + preProcess->scaledOutput) { + u32 width16 = (width+15)/16*16; + u32 height16 = (height+15)/16*16; + + regs->scaledWidth = preProcess->scaledWidth; + regs->scaledHeight = preProcess->scaledHeight; + if(preProcess->rotation == 1 || preProcess->rotation == 2) { + /* Scaling factors calculated from overfilled dimensions. */ + regs->scaledWidthRatio = + (u32)(preProcess->scaledWidth << 16) / width16 + 1; + regs->scaledHeightRatio = + (u32)(preProcess->scaledHeight << 16) / height16 +1; + } else { + /* Scaling factors calculated from image pixels, round upwards. */ + regs->scaledWidthRatio = + (u32)(preProcess->scaledWidth << 16) / width + 1; + regs->scaledHeightRatio = + (u32)(preProcess->scaledHeight << 16) / height + 1; + /* Adjust horizontal scaling factor using overfilled dimensions + to avoid problems in HW implementation with pixel leftover. */ + regs->scaledWidthRatio = + ((regs->scaledWidthRatio * width16) & 0xFFF0000) / width16 + 1; + } + regs->scaledHeightRatio = MIN(65536, regs->scaledHeightRatio); + regs->scaledWidthRatio = MIN(65536, regs->scaledWidthRatio); + } else { + regs->scaledWidth = regs->scaledHeight = 0; + regs->scaledWidthRatio = regs->scaledHeightRatio = 0; + } + + /* For rotated image, swap dimensions back to normal. */ + if(preProcess->rotation == 1 || preProcess->rotation == 2) + { + u32 tmp; + + tmp = width; + width = height; + height = tmp; + } + + /* Set mandatory input parameters in asic structure */ + regs->mbsInRow = (width + 15) / 16; + regs->mbsInCol = (height + 15) / 16; + regs->pixelsOnRow = stride; + + /* Set the overfill values */ + if(width & 0x0F) + regs->xFill = (16 - (width & 0x0F)) / 4; + else + regs->xFill = 0; + + if(height & 0x0F) + regs->yFill = 16 - (height & 0x0F); + else + regs->yFill = 0; + + /* video stabilization */ + if(regs->codingType != ASIC_JPEG && preProcess->videoStab != 0) + regs->vsMode = 2; + else + regs->vsMode = 0; + + /* Adaptive Region of Interest */ + if (!preProcess->roiMapEnable) + { + /* only enable the adaptive process if Map is not enable. */ + if (preProcess->adaptiveRoi) + EncAdaptiveROI(asic, preProcess); + } + +#ifdef TRACE_PREPROCESS + EncTracePreProcess(preProcess); +#endif + + return; +} + +/*------------------------------------------------------------------------------ + + EncSetColorConversion + + Set color conversion coefficients and RGB input mask + + Input asic Pointer to asicData_s structure + preProcess Pointer to preProcess_s structure. + +------------------------------------------------------------------------------*/ +void EncSetColorConversion(preProcess_s * preProcess, asicData_s * asic) +{ + regValues_s *regs; + + ASSERT(asic != NULL && preProcess != NULL); + + regs = &asic->regs; + + switch (preProcess->colorConversionType) + { + case 0: /* BT.601 */ + default: + /* Y = 0.2989 R + 0.5866 G + 0.1145 B + * Cb = 0.5647 (B - Y) + 128 + * Cr = 0.7132 (R - Y) + 128 + */ + preProcess->colorConversionType = 0; + regs->colorConversionCoeffA = preProcess->colorConversionCoeffA = 19589; + regs->colorConversionCoeffB = preProcess->colorConversionCoeffB = 38443; + regs->colorConversionCoeffC = preProcess->colorConversionCoeffC = 7504; + regs->colorConversionCoeffE = preProcess->colorConversionCoeffE = 37008; + regs->colorConversionCoeffF = preProcess->colorConversionCoeffF = 46740; + break; + + case 1: /* BT.709 */ + /* Y = 0.2126 R + 0.7152 G + 0.0722 B + * Cb = 0.5389 (B - Y) + 128 + * Cr = 0.6350 (R - Y) + 128 + */ + regs->colorConversionCoeffA = preProcess->colorConversionCoeffA = 13933; + regs->colorConversionCoeffB = preProcess->colorConversionCoeffB = 46871; + regs->colorConversionCoeffC = preProcess->colorConversionCoeffC = 4732; + regs->colorConversionCoeffE = preProcess->colorConversionCoeffE = 35317; + regs->colorConversionCoeffF = preProcess->colorConversionCoeffF = 41615; + break; + + case 2: /* User defined */ + /* Limitations for coefficients: A+B+C <= 65536 */ + regs->colorConversionCoeffA = preProcess->colorConversionCoeffA; + regs->colorConversionCoeffB = preProcess->colorConversionCoeffB; + regs->colorConversionCoeffC = preProcess->colorConversionCoeffC; + regs->colorConversionCoeffE = preProcess->colorConversionCoeffE; + regs->colorConversionCoeffF = preProcess->colorConversionCoeffF; + } + + /* Setup masks to separate R, G and B from RGB */ + regs->rMaskMsb = rgbMaskBits[preProcess->inputFormat][0]; + regs->gMaskMsb = rgbMaskBits[preProcess->inputFormat][1]; + regs->bMaskMsb = rgbMaskBits[preProcess->inputFormat][2]; +} + +/*------------------------------------------------------------------------------ + SkinMb Determine whether MB=i matches skin color +------------------------------------------------------------------------------*/ +static u8 SkinMb(encOutputMbInfo_s * mbInfo, preProcess_s * preProcess) +{ + i32 y, cb, cr; + i32 sensitivity = preProcess->adaptiveRoiColor; + + y = mbInfo->yMean; + cb = mbInfo->cbMean + preProcess->cbComp; + cr = mbInfo->crMean + preProcess->crComp; + + /* Luma limits for skin */ + if (y < 40 || y > 220) return 0; + + /* Filter out mbs with low MAD */ + if (mbInfo->inputMad_div128 <= H1ENC_AROI_SKIN_MAD_THRESHOLD) + return 0; + + /* Skin tone region defined with five lines. */ + /* Sensitivity == color temperature -10 == 2000K (red), +10 == 6000K (blue) */ + if ((cr + cb >= 249) && + (cb >= 100-y/10-sensitivity) && + (cr + cb*3/4 <= 250) && + (cb <= 128+sensitivity/2) && + (cr - cb >= 2 + y/10 - y*sensitivity/100)) { + return 1; + } + + return 0; +} + +/*------------------------------------------------------------------------------ + GetWbCompensation Determine white balance compensation based on color of + high luminocity. +------------------------------------------------------------------------------*/ +static void GetWbCompensation(preProcess_s * preProcess, asicData_s *asic) +{ + i32 mbPerRow = preProcess->lumWidth/16; + i32 mbPerCol = preProcess->lumHeight/16; + i32 mbPerFrame = mbPerRow * mbPerCol; + i32 mb, i; + i32 yhist[256] = {0}; + i32 ymax=0, ymax_cbavg=0, ymax_cravg=0, ymax_cnt=0; + encOutputMbInfo_s *mbInfo; + + + /* Create luminance histogram and find luminance maximum. */ + for (mb = 0; mb < mbPerFrame; mb++) { + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, mb); + yhist[mbInfo->yMean]++; + } + /* Find the highest luminance values, resolution affects how many values + are needed. */ + for (i = 255; i > 150; i--) { + ymax_cnt += yhist[i]; + if (ymax_cnt > mbPerFrame/512) break; + } + ymax = MIN(i, 235); + + /* Find the average chrominance of the highest luminance macroblocks. */ + ymax_cnt=0; + for (mb = 0; mb < mbPerFrame; mb++) { + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, mb); + if (mbInfo->yMean >= ymax) { + ymax_cnt++; + ymax_cbavg += mbInfo->cbMean; + ymax_cravg += mbInfo->crMean; + } + } + if (!ymax_cnt) ymax_cnt++; + ymax_cbavg /= ymax_cnt; + ymax_cravg /= ymax_cnt; + ymax = MIN(ymax, 235); + + /* Calculate the white balance compensation. */ + preProcess->cbComp = (127-ymax_cbavg)*20/(255-ymax); + preProcess->crComp = (127-ymax_cravg)*20/(255-ymax); + + /* Don't try to compensate if low lightness. */ + if (ymax <= 150 || ymax_cnt <= mbPerFrame/512) + preProcess->cbComp = preProcess->crComp = 0; +} + +/*------------------------------------------------------------------------------ + FilterMap Perform filtering on skin map +------------------------------------------------------------------------------*/ +static void FilterMap(u8 *skinmapf, u8 *skinmap, i32 mbPerRow, i32 mbPerCol, + i32 boxw, i32 boxh) +{ + i32 mbPerFrame = mbPerRow*mbPerCol; + i32 mb, x, y, j, k; + i32 cnt; + i32 weight; + + /* Rectancular filter with given dimensions: 2*boxw+1, 2*boxh+1 */ + weight = mbPerCol*2/3; + for (mb = mbPerRow; mb < mbPerRow*boxh; mb++) + skinmapf[mb] = 0; + for (y = boxh; y < mbPerCol-boxh; y++) { + for (x = boxw; x < mbPerRow-boxw; x++) { + cnt = 0; + for (j = y-boxh; j <= y+boxh; j++) { + for (k = x-boxw; k <= x+boxw; k++) { + cnt += skinmap[j*mbPerRow+k]; + } + } + /* Weight filter based on location (MB row) */ + if (y < mbPerCol/3) + cnt *= 2*weight+y; + else + cnt *= 3*weight-y; + + skinmapf[y*mbPerRow+x] = MIN(255, cnt/mbPerCol); + } + } + for (mb = mbPerFrame-mbPerRow*boxh; mb < mbPerFrame-mbPerRow; mb++) + skinmapf[mb] = 0; +} + +/*------------------------------------------------------------------------------ + ScoreMb Score for MB=i based on skin, mv and previous roi maps +------------------------------------------------------------------------------*/ +static u8 ScoreMb(i32 i, preProcess_s * preProcess) +{ + u8 *skinmapf = preProcess->skinMap[1]; /* Skin map after filter */ + i32 *mvMap = preProcess->mvMap; + i32 motionScore = 0; + + if (preProcess->adaptiveRoiMotion < 0) { + i32 mvThreshold = -preProcess->mvFrames*preProcess->adaptiveRoiMotion; + + /* Negative motion sensitivity rules out MBs below threshold. */ + if ((preProcess->mvFrames > 2) && (mvMap[i] < mvThreshold)) return 0; + } else if (preProcess->adaptiveRoiMotion > 0) { + i32 mvThreshold = preProcess->mvFrames*preProcess->adaptiveRoiMotion; + + /* Positive motion sensitivity includes MBs above threshold. */ + if ((preProcess->mvFrames) && (mvMap[i] > mvThreshold)) + motionScore = mvMap[i]/preProcess->mvFrames; + } + + return MIN(255, skinmapf[i] + motionScore); +} + +/*------------------------------------------------------------------------------ + + EncAdaptiveROI + + Set color conversion coefficients and RGB input mask + + Input asic Pointer to asicData_s structure + preProcess Pointer to preProcess_s structure. + +------------------------------------------------------------------------------*/ +void EncAdaptiveROI(asicData_s * asic, preProcess_s * preProcess) +{ + i32 mbPerRow = preProcess->lumWidth/16; + i32 mbPerCol = preProcess->lumHeight/16; + i32 mbPerFrame = mbPerRow * mbPerCol; + i32 skinCount = 0; + i32 mapCount = 0; + i32 prevSkinCount = 0; + i32 threshold, mb; + i32 boxh, boxw; + i32 reuseMap = 0, clearMap = 0; + u8 *skinmap = preProcess->skinMap[0]; /* Skin detected mbs */ + u8 *skinmapf = preProcess->skinMap[1]; /* Skin map after filter */ + u8 *roimap; + encOutputMbInfo_s *mbInfo; + + /* Macroblock filter box dimensions. */ + preProcess->boxh = boxh = MAX(1, H1ENC_AROI_FILTER_BOX_HEIGHT); + preProcess->boxw = boxw = MAX(1, H1ENC_AROI_FILTER_BOX_WIDTH); + + ASSERT(asic); + + if (preProcess->roiCoded) { + /* The map from previous frame was coded into stream => save it */ + EWLmemcpy(preProcess->roiSegmentMap[1], + preProcess->roiSegmentMap[0], mbPerFrame); + preProcess->roiMbCount[1] = preProcess->roiMbCount[0]; + preProcess->roiCoded = 0; + } + + if (preProcess->intra) { + /* Intra frame resets segment map. AROI not used for intra frames. */ + if (preProcess->roiMbCount[1]) + EWLmemset(preProcess->roiSegmentMap[1], 0, mbPerFrame); + if (preProcess->roiMbCount[2]) + EWLmemset(preProcess->roiSegmentMap[2], 0, mbPerFrame); + if (preProcess->mvFrames) + EWLmemset(preProcess->mvMap, 0, mbPerFrame*sizeof(i32)); + preProcess->roiUpdate = 0; + preProcess->roiMbCount[1] = 0; + preProcess->roiMbCount[2] = 0; + preProcess->prevMapCount = 999; + preProcess->mvFrames = 0; +#ifdef DEBUG_AROI + TraceAroi(asic, preProcess, 9, preProcess->roiMbCount[2]); + TraceAroiYuv(asic, preProcess); +#endif + return; + } + + if (preProcess->adaptiveRoiMotion) { + preProcess->mvFrames++; + /* Cumulative sum for macroblock motion. */ + for (mb = 0; mb < mbPerFrame; mb++) { + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, mb); + preProcess->mvMap[mb] += ABS(mbInfo->mvX[0]) + ABS(mbInfo->mvY[0]); + } + } + +#ifdef DEBUG_AROI + if (preProcess->adaptiveRoiMotion) + TraceAroi(asic, preProcess, 1, 0); +#endif + + /* Force using map atleast a defined number of frames after update. */ + if (preProcess->prevMapCount < H1ENC_AROI_MIN_UPDATE_FRAMES) { + preProcess->prevMapCount++; + preProcess->roiUpdate = 0; + } else { + + /* Try to detect if the frame white balance is invalid and determine + chroma compensation to fix the white balance. */ + if (H1ENC_AROI_WHITE_BALANCE_FIX) + GetWbCompensation(preProcess, asic); + + /* Find macroblocks with skin color and motion vectors for non-skin. */ + for (mb = 0; mb < mbPerFrame; mb++) { + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, mb); + skinmap[mb] = SkinMb(mbInfo, preProcess); + if (skinmap[mb]) skinCount++; + } + +#ifdef DEBUG_AROI + TraceAroi(asic, preProcess, 0, skinCount); +#endif + + /* Filter based on found skin macroblocks. */ + FilterMap(skinmapf, skinmap, mbPerRow, mbPerCol, boxw, boxh); + + /* Threshold for macroblock scores based on filter area, adjusted + by the percentage of skin MBs / frame and motion sensitivity. */ + threshold = (boxh*2+1)*(boxw*2+1)*H1ENC_AROI_SCORE_THRESHOLD; + if (skinCount) + threshold = MAX(1, threshold - threshold*mbPerFrame/skinCount/200); + if (preProcess->adaptiveRoiMotion > 0) + threshold += preProcess->adaptiveRoiMotion; + + /* Score thresholding to create ROI segment map */ + roimap = preProcess->roiSegmentMap[0]; + for (mb = mbPerRow; mb < mbPerFrame-mbPerRow; mb++) { + preProcess->scoreMap[mb] = ScoreMb(mb, preProcess); + roimap[mb] = (preProcess->scoreMap[mb] >= threshold); + } + + /* Remove one macroblock holes in segment map */ + for (mb = mbPerRow; mb < mbPerFrame-mbPerRow; mb++) { + roimap[mb] = (roimap[mb-1] + roimap[mb] + roimap[mb+1]) > 1; + } + + /* Compare previous and new map to find out if it is worth to update */ + skinCount = mapCount = 0; + for (mb = mbPerRow; mb < mbPerFrame-mbPerRow; mb++) { + if (preProcess->roiSegmentMap[0][mb] && preProcess->roiSegmentMap[1][mb]) + mapCount++; /* Overlapping maps */ + if (preProcess->roiSegmentMap[0][mb]) + skinCount++; + } + preProcess->roiMbCount[0] = skinCount; + prevSkinCount = preProcess->roiMbCount[1]; + + /* Threshold for changing map, adjust the threshold from 80% => 95% + as more frames get coded with the same map. */ + threshold = MIN(H1ENC_AROI_UPDATE_THRESHOLD+preProcess->prevMapCount, 95); + + /* Threshold for not finding a small area to focus on */ + if (skinCount > mbPerFrame/3) { + /* New skin map is too big, we can either use the previous map or + no map at all. */ + if (mapCount >= prevSkinCount*threshold/100) reuseMap = 1; + else clearMap = 1; + } else if ((mapCount >= skinCount*threshold/100) && + (mapCount >= prevSkinCount*threshold/100)) { + reuseMap = 1; + } + + if (clearMap) { + /* Clear segment map. */ + if (preProcess->roiMbCount[0]) + EWLmemset(preProcess->roiSegmentMap[0], 0, mbPerFrame); + if (preProcess->roiMbCount[2]) + EWLmemset(preProcess->roiSegmentMap[2], 0, mbPerFrame); + if (preProcess->mvFrames) + EWLmemset(preProcess->mvMap, 0, mbPerFrame*sizeof(i32)); + preProcess->roiMbCount[0] = 0; + preProcess->roiMbCount[2] = 0; + preProcess->mvFrames = 0; + preProcess->prevMapCount = 999; + preProcess->roiUpdate = 1; + } else if (reuseMap) { + /* Reuse previous map for this frame. */ + EWLmemcpy(preProcess->roiSegmentMap[0], + preProcess->roiSegmentMap[1], mbPerFrame); + preProcess->roiMbCount[0] = preProcess->roiMbCount[1]; + preProcess->prevMapCount++; + preProcess->roiUpdate = 0; + } else { + /* New segment map for ROI. */ + preProcess->prevMapCount = 1; + + /* Reset motion map for each new ROI */ + if (preProcess->mvFrames) + EWLmemset(preProcess->mvMap, 0, mbPerFrame*sizeof(i32)); + preProcess->mvFrames = 0; + + /* Expand the new segment map with the size of filter box. */ + EWLmemset(preProcess->roiSegmentMap[2], 0, mbPerFrame); + for (mb = boxh*mbPerRow+boxw; mb < mbPerFrame-mbPerRow*boxh-boxw; mb++) { + i32 i,j; + + if (preProcess->roiSegmentMap[0][mb]) { + for (i = 0; i <= boxw; i++) { + for (j = 0; j <= boxh; j++) { + preProcess->roiSegmentMap[2][mb+j*mbPerRow+i] = 1; + preProcess->roiSegmentMap[2][mb+j*mbPerRow-i] = 1; + preProcess->roiSegmentMap[2][mb-j*mbPerRow+i] = 1; + preProcess->roiSegmentMap[2][mb-j*mbPerRow-i] = 1; + } + } + } + } + skinCount = 0; + for (mb = 0; mb < mbPerFrame; mb++) { + if (preProcess->roiSegmentMap[2][mb]) skinCount++; + } + /* Segments will be updated based on ROI MB counts */ + preProcess->roiMbCount[2] = skinCount; + preProcess->roiUpdate = 1; + } + + } + +#ifdef DEBUG_AROI + TraceAroi(asic, preProcess, 9, preProcess->roiMbCount[2]); + TraceAroiYuv(asic, preProcess); +#endif +} + +#ifdef DEBUG_AROI +/*------------------------------------------------------------------------------ + TraceAroi Write aroi.trc file with adaptive ROI information +------------------------------------------------------------------------------*/ +void TraceAroi(asicData_s * asic, preProcess_s * preProcess, i32 stage, i32 value) +{ + i32 mbPerRow = preProcess->lumWidth/16; + i32 mbPerCol = preProcess->lumHeight/16; + i32 mbPerFrame = mbPerRow * mbPerCol; + i32 mb; + static i32 frameNum = 0; + static FILE *ftrc; + + if (!ftrc) ftrc = fopen("aroi.trc", "w"); + + /* Print out the skin scores. */ + if (stage == 0) { + fprintf(ftrc, "Frame=%d skin scores, chroma compensation %d, %d\n", + frameNum, preProcess->cbComp, preProcess->crComp); + if (DEBUG_AROI > 1) for (mb = 0; mb < mbPerFrame; mb++) { + fprintf(ftrc, "%2d ", preProcess->skinMap[0][mb]); + if (mb%mbPerRow == mbPerRow-1) fprintf(ftrc, "\n"); + } + fprintf(ftrc, "Skin count: %d\n\n", value); + } + + /* Print out the motion map. */ + if (stage == 1) { + fprintf(ftrc, "Frame=%d motion map\n", frameNum); + if (DEBUG_AROI > 1) for (mb = 0; mb < mbPerFrame; mb++) { + fprintf(ftrc, "%4d ", preProcess->mvMap[mb]); + if (mb%mbPerRow == mbPerRow-1) fprintf(ftrc, "\n"); + } + } + + /* Print out the final roi, its motion and skin count. */ + if (stage == 9) { + fprintf(ftrc, "Frame=%d final roi map, box filter %dx%d\n", + frameNum, preProcess->boxw*2+1, preProcess->boxh*2+1); + fprintf(ftrc, "Frame=%d Map update %d\n", frameNum, preProcess->roiUpdate); + fprintf(ftrc, "Frame=%d MapCount=%d\n", + frameNum, preProcess->prevMapCount); + if (DEBUG_AROI > 1) for (mb = 0; mb < mbPerFrame; mb++) { + fprintf(ftrc, "%2d ", preProcess->roiSegmentMap[2][mb]); + if (mb%mbPerRow == mbPerRow-1) fprintf(ftrc, "\n"); + } + fprintf(ftrc, "Frame=%d MapSkinCount=%d (%d%%)\n", + frameNum, value, value*100/mbPerFrame); + fprintf(ftrc, "\n\n"); + frameNum++; + } +} + +/*------------------------------------------------------------------------------ + TraceAroiYuv Write aroi.yuv file with ROI edges visible +------------------------------------------------------------------------------*/ +void TraceAroiYuv(asicData_s * asic, preProcess_s * preProcess) +{ + i32 mbPerRow = preProcess->lumWidth/16; + i32 mbPerCol = preProcess->lumHeight/16; + i32 x, y, i; + i32 b=0; + u8 *roimap = preProcess->roiSegmentMap[0]; /* Current frame */ + u8 *roimape = preProcess->roiSegmentMap[2]; /* Current frame expanded */ + u8 *skinmap = preProcess->skinMap[0]; /* Skin mbs, for each frame */ + u8 *skinmapf = preProcess->skinMap[1]; /* Skin map after filter */ + u32 skincbhist[256] = {0}; + u32 skincrhist[256] = {0}; + encOutputMbInfo_s *mbInfo; + i32 lum, cb, cr, threshold; + i32 skincnt=0, skincbavg=0, skincravg=0; + i32 cbcnt,crcnt,cbmed,crmed; + static FILE *file[10] = {0}; + + /* Full resolution image with visible AROI edges. */ + if (!file[0]) file[0] = fopen("aroi.yuv", "w"); + /* One pixel per MB files for AROI stages. */ + if (!file[1]) file[1] = fopen("mb_cb.yuv", "w"); + if (!file[2]) file[2] = fopen("mb_cr.yuv", "w"); + if (!file[3]) file[3] = fopen("mb_lum.yuv", "w"); + if (!file[4]) file[4] = fopen("mb_roi1.yuv", "w"); + if (!file[5]) file[5] = fopen("mb_roi2.yuv", "w"); + if (!file[6]) file[6] = fopen("mb_roi3.yuv", "w"); + if (!file[7]) file[7] = fopen("mb_roi4.yuv", "w"); + if (!file[8]) file[8] = fopen("mb_roi5.yuv", "w"); + if (!file[9]) file[9] = fopen("mb_roi6.yuv", "w"); + + /* Chroma component */ + if (file[1]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, i); + cb = mbInfo->cbMean; + if (skinmap[i]) { skincnt++; skincbavg += cb; skincbhist[cb]++; } + fwrite(&cb, 1, 1, file[1]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[1]); + } + + /* Chroma component */ + if (file[2]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, i); + cr = mbInfo->crMean; + if (skinmap[i]) { skincravg += cr; skincrhist[cr]++; } + fwrite(&cr, 1, 1, file[2]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[2]); + } + + /* Luma component */ + if (file[3]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, i); + lum = mbInfo->yMean; + fwrite(&lum, 1, 1, file[3]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[3]); + } + + /* Average chroma value on detected skin mbs */ + if (skincnt) { + skincbavg /= skincnt; + skincravg /= skincnt; + } + + /* Median chroma value on detected skin mbs */ + crcnt=cbcnt=crmed=cbmed=0; + for (i = 0; i < 256; i++) { + cbcnt += skincbhist[i]; + crcnt += skincrhist[i]; + if (cbcnt > skincnt/2 && cbmed == 0) + cbmed = i; + if (crcnt > skincnt/2 && crmed == 0) + crmed = i; + } + + /* Detected skin mbs */ + if (file[4]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + lum = MIN(255, skinmap[i]*250); + fwrite(&lum, 1, 1, file[4]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[4]); + } + + /* Filtered skin mbs without thresholding */ + FilterMap(skinmapf, skinmap, mbPerRow, mbPerCol, + preProcess->boxw, preProcess->boxh); + if (file[5]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + lum = MIN(255, skinmapf[i]*2); + fwrite(&lum, 1, 1, file[5]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[5]); + } + + /* Filtered skin mbs with threshold */ + threshold = (preProcess->boxh*2+1)*(preProcess->boxw*2+1)*2/3*4/3; + if (file[6]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + lum = MIN(255, skinmapf[i]*2); + if (skinmapf[i] < threshold) lum=0; + fwrite(&lum, 1, 1, file[6]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[6]); + } + + /* Macroblock scores */ + if (file[7]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + lum = MIN(255, preProcess->scoreMap[i]*2); + fwrite(&lum, 1, 1, file[7]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[7]); + } + + /* Score thresholding */ + if (file[8]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + lum = MIN(255, roimap[i]*255); + fwrite(&lum, 1, 1, file[8]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[8]); + } + + /* Cumulative MV sum */ + if (file[9]) { + for (y = 0; y < mbPerCol; y++) { + for (x = 0; x < mbPerRow; x++) { + i = (y)*mbPerRow + x; + lum = MIN(255, preProcess->mvMap[i]*2); + fwrite(&lum, 1, 1, file[9]); + } + } + cr=128; + for (y = 0; y < mbPerCol*mbPerRow/2; y++) fwrite(&cr, 1, 1, file[9]); + } + + /* Reconstructed frame luma with visible ROI edges */ + if (file[0]) { + for (y = 0; y < mbPerCol*16; y++) { + for (x = 0; x < mbPerRow*16; x++) { + i32 edge = 0; + i = (y/16)*mbPerRow + x/16; + + /* Detect edges of ROI macroblocks */ + if (x > 15 && x < (mbPerRow-1)*16 && + y > 15 && y < (mbPerCol-1)*16) { + if ((x%16 == 0) && roimape[i] && (roimape[i-1] == 0)) edge = 1; + if ((x%16 == 15) && roimape[i] && (roimape[i+1] == 0)) edge = 1; + if ((y%16 == 0) && roimape[i] && (roimape[i-mbPerRow] == 0)) edge = 1; + if ((y%16 == 15) && roimape[i] && (roimape[i+mbPerRow] == 0)) edge = 1; + } + + if (edge) + fwrite(&b, 1, 1, file[0]); + else + /* Previous reconstructed frame luma */ + if (asic->regs.internalImageLumBaseR[0]) { + fwrite((u8*)(asic->regs.internalImageLumBaseR[0])+ + y*preProcess->lumWidth+x, 1, 1, file[0]); + } else { + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, i); + fwrite(&mbInfo->yMean, 1, 1, file[0]); + } + } + } + /* TBD use actual chroma, not mean */ + for (y = 0; y < mbPerCol*8; y++) { + for (x = 0; x < mbPerRow*8; x++) { + i = (y/8)*mbPerRow + x/8; + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, i); + cb = mbInfo->cbMean + preProcess->cbComp; + fwrite(&cb, 1, 1, file[0]); + } + } + for (y = 0; y < mbPerCol*8; y++) { + for (x = 0; x < mbPerRow*8; x++) { + i = (y/8)*mbPerRow + x/8; + mbInfo = (encOutputMbInfo_s *)EncAsicGetMvOutput(asic, i); + cr = mbInfo->crMean + preProcess->crComp; + fwrite(&cr, 1, 1, file[0]); + } + } + } + +} +#endif diff --git a/lib/vc8000nanoe/source/common/encpreprocess.h b/lib/vc8000nanoe/source/common/encpreprocess.h new file mode 100644 index 000000000..ddde65a8a --- /dev/null +++ b/lib/vc8000nanoe/source/common/encpreprocess.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Preprocessor setup + * + ******************************************************************************** + */ +#ifndef __ENC_PRE_PROCESS_H__ +#define __ENC_PRE_PROCESS_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "encasiccontroller.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#define ROTATE_0 0U +#define ROTATE_90R 1U /* Rotate 90 degrees clockwise */ +#define ROTATE_90L 2U /* Rotate 90 degrees counter-clockwise */ + +/* maximum input picture width set by the available bits in ASIC regs */ +#define MAX_INPUT_IMAGE_WIDTH (8192) + +typedef struct +{ + u32 lumWidthSrc; /* Source input image width */ + u32 lumHeightSrc; /* Source input image height */ + u32 lumWidth; /* Encoded image width */ + u32 lumHeight; /* Encoded image height */ + u32 scaledWidth; /* Scaled output image width */ + u32 scaledHeight; /* Scaled output image height */ + u32 horOffsetSrc; /* Encoded frame offset, reference is ... */ + u32 verOffsetSrc; /* ...top left corner of source image */ + u32 inputFormat; + u32 rotation; + u32 videoStab; + u32 scaledOutput; + u32 colorConversionType; /* 0 = bt601, 1 = bt709, 2 = user defined */ + u32 colorConversionCoeffA; + u32 colorConversionCoeffB; + u32 colorConversionCoeffC; + u32 colorConversionCoeffE; + u32 colorConversionCoeffF; + i32 roiMapEnable; + i32 adaptiveRoi; + i32 qpOffset[3]; + i32 adaptiveRoiColor; /* Color temperature -10..10 = 2000K..5000K */ + i32 adaptiveRoiMotion; /* Motion sensitivity -10..10 */ + u32 prevMapCount; /* How many frames previous map is used in. */ + u32 intra; + u32 mvFrames; /* How many frames mvMap is counted for. */ + u32 cbComp; /* Chroma compensation for white balance fix. */ + u32 crComp; + u32 boxw; /* Filter box dimensions. */ + u32 boxh; + u8 *skinMap[2]; /* Skin MBs before/after filtering */ + u8 *roiSegmentMap[3]; /* MB maps, 0=curr, 1=prev, 2=curr expanded */ + u32 roiMbCount[3]; /* Amount of MBs in each of above maps */ + i32 *mvMap; /* Motion map based on MB MVs */ + u8 *scoreMap; /* Skin + motion score for each MB */ + u32 roiUpdate; /* AROI calculation has updated roiSegmentMap[2] */ + u32 roiCoded; /* The new ROI map has been coded to stream */ + u32 interlacedFrame; /* Enable interlaced frame input */ + u32 bottomField; /* Current picture is interlaced bottom field */ +} preProcess_s; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +i32 EncPreProcessAlloc(preProcess_s * preProcess, i32 mbPerPicture); +void EncPreProcessFree(preProcess_s * preProcess); +i32 EncPreProcessCheck(const preProcess_s * preProcess); +void EncPreProcess(asicData_s * asic, preProcess_s * preProcess); +void EncSetColorConversion(preProcess_s * preProcess, asicData_s * asic); + +#endif diff --git a/lib/vc8000nanoe/source/common/encswhwregisters.c b/lib/vc8000nanoe/source/common/encswhwregisters.c new file mode 100644 index 000000000..8b1b55672 --- /dev/null +++ b/lib/vc8000nanoe/source/common/encswhwregisters.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encoder SW/HW interface register definitions + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + +------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "encswhwregisters.h" +#include "enccommon.h" +#include "ewl.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Define this to print debug info for every register write. +#define DEBUG_PRINT_REGS */ + +/*------------------------------------------------------------------------------ + + EncAsicSetRegisterValue + + Set a value into a defined register field + +------------------------------------------------------------------------------*/ +void EncAsicSetRegisterValue(u32 *regMirror, regName name, u32 value) +{ + const regField_s *field; + u32 regVal; + + field = &asicRegisterDesc[name]; + +#ifdef DEBUG_PRINT_REGS + printf("EncAsicSetRegister 0x%2x 0x%08x Value: %10d %s\n", + field->base, field->mask, value, field->description); +#endif + + /* Check that value fits in field */ + ASSERT(field->name == name); + ASSERT(((field->mask >> field->lsb) << field->lsb) == field->mask); + ASSERT((field->mask >> field->lsb) >= value); + ASSERT(field->base < ASIC_SWREG_AMOUNT*4); + + /* Clear previous value of field in register */ + regVal = regMirror[field->base/4] & ~(field->mask); + + /* Put new value of field in register */ + regMirror[field->base/4] = regVal | ((value << field->lsb) & field->mask); +} + +/*------------------------------------------------------------------------------ + + EncAsicWriteRegisterValue + + Write a value into a defined register field (write will happens actually). + +------------------------------------------------------------------------------*/ +void EncAsicWriteRegisterValue(const void *ewl, u32 *regMirror, regName name, u32 value) +{ + const regField_s *field; + u32 regVal; + + field = &asicRegisterDesc[name]; + +#ifdef DEBUG_PRINT_REGS + printf("EncAsicSetRegister 0x%2x 0x%08x Value: %10d %s\n", + field->base, field->mask, value, field->description); +#endif + + /* Check that value fits in field */ + ASSERT(field->name == name); + ASSERT(((field->mask >> field->lsb) << field->lsb) == field->mask); + ASSERT((field->mask >> field->lsb) >= value); + ASSERT(field->base < ASIC_SWREG_AMOUNT*4); + + /* Clear previous value of field in register */ + regVal = regMirror[field->base/4] & ~(field->mask); + + /* Put new value of field in register */ + regMirror[field->base/4] = regVal | ((value << field->lsb) & field->mask); + + /* write it into HW registers */ + EWLWriteReg(ewl, field->base, regMirror[field->base/4]); +} + +/*------------------------------------------------------------------------------ + + EncAsicGetRegisterValue + + Get an unsigned value from the ASIC registers + +------------------------------------------------------------------------------*/ +u32 EncAsicGetRegisterValue(const void *ewl, u32 *regMirror, regName name) +{ + const regField_s *field; + u32 value; + + field = &asicRegisterDesc[name]; + + ASSERT(field->base < ASIC_SWREG_AMOUNT*4); + + value = regMirror[field->base/4] = EWLReadReg(ewl, field->base); + value = (value & field->mask) >> field->lsb; + + return value; +} + + + diff --git a/lib/vc8000nanoe/source/h264/H264Cabac.c b/lib/vc8000nanoe/source/h264/H264Cabac.c new file mode 100644 index 000000000..6e037489d --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Cabac.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : H264 CABAC context table initialization + * + ******************************************************************************** + */ +#include "H264Cabac.h" +#include "H264CabacContext.h" +#include "enccommon.h" +#include "enccfg.h" + +/* Swap byte and/or 32-bit endianess as defined in enccfg.h. + * Input and output buffers can be the same. */ +static void SwapEndianess(u32 * bufIn, u32 * buf, u32 sizeBytes) +{ +#if (ENCH1_OUTPUT_SWAP_8 == 1) + u32 i = 0; + i32 words = sizeBytes / 4; + + ASSERT((sizeBytes % 8) == 0); + + while(words > 0) + { + u32 val = bufIn[i]; + u32 tmp = 0; + + tmp |= (val & 0xFF) << 24; + tmp |= (val & 0xFF00) << 8; + tmp |= (val & 0xFF0000) >> 8; + tmp |= (val & 0xFF000000) >> 24; + +#if(ENCH1_OUTPUT_SWAP_32 == 1) /* need this for 64-bit HW */ + { + u32 val2 = bufIn[i + 1]; + u32 tmp2 = 0; + + tmp2 |= (val2 & 0xFF) << 24; + tmp2 |= (val2 & 0xFF00) << 8; + tmp2 |= (val2 & 0xFF0000) >> 8; + tmp2 |= (val2 & 0xFF000000) >> 24; + + buf[i] = tmp2; + words--; + i++; + } +#endif + buf[i] = tmp; + words--; + i++; + } +#else /* No swapping, copy buffer if needed. */ + if (bufIn != buf) + EWLmemcpy(buf, bufIn, 52 * 2 * 464); +#endif + +} + +#ifndef H1_MEMCPY_CABAC_INIT + +#ifndef H1_PRECALC_CABAC_INIT +u32 H264CabacInit(u32 * contextTable, u32 cabac_init_idc) +{ + const i32(*ctx)[460][2]; + int i, j, qp; + u8 *table = (u8 *) contextTable; + + for(qp = 0; qp < 52; qp++) /* All QP values */ + { + for(j = 0; j < 2; j++) /* Intra/Inter */ + { + if(j == 0) + ctx = /*lint -e(545) */ &h264ContextInitIntra; + else + ctx = /*lint -e(545) */ &h264ContextInit[cabac_init_idc]; + + for(i = 0; i < 460; i++) + { + i32 m = (i32) (*ctx)[i][0]; + i32 n = (i32) (*ctx)[i][1]; + + i32 preCtxState = CLIP3(((m * (i32) qp) >> 4) + n, 1, 126); + + if(preCtxState <= 63) + { + table[qp * 464 * 2 + j * 464 + i] = + (u8) ((63 - preCtxState) << 1); + } + else + { + table[qp * 464 * 2 + j * 464 + i] = + (u8) (((preCtxState - 64) << 1) | 1); + } + } + } + } + + SwapEndianess(contextTable, contextTable, 52 * 2 * 464); + return 0; +} + +#else +u32 H264CabacInit(u32 * contextTable, u32 cabac_init_idc) +{ + SwapEndianess((u32*)preCalculatedContextTable[cabac_init_idc], + contextTable, 52 * 2 * 464); + return 0; +} +#endif + +#else +u32 H264CabacInit(u32 * contextTable, u32 cabac_init_idc) +{ + const i32(*ctx)[460][2]; + int i, j, qp; + + u8 *tempCabacTable = (u8*)EWLmalloc(52 * 2 * 464); + if(tempCabacTable == NULL) + { + return 1; + } + + for(qp = 0; qp < 52; qp++) /* All QP values */ + { + for(j = 0; j < 2; j++) /* Intra/Inter */ + { + if(j == 0) + ctx = /*lint -e(545) */ &h264ContextInitIntra; + else + ctx = /*lint -e(545) */ &h264ContextInit[cabac_init_idc]; + + for(i = 0; i < 460; i++) + { + i32 m = (i32) (*ctx)[i][0]; + i32 n = (i32) (*ctx)[i][1]; + + i32 preCtxState = CLIP3(((m * (i32) qp) >> 4) + n, 1, 126); + + if(preCtxState <= 63) + { + tempCabacTable [qp * 464 * 2 + j * 464 + i] = + (u8) ((63 - preCtxState) << 1); + } + else + { + tempCabacTable [qp * 464 * 2 + j * 464 + i] = + (u8) (((preCtxState - 64) << 1) | 1); + } + } + } + } + + SwapEndianess((u32*)tempCabacTable, (u32*)tempCabacTable, 52 * 2 * 464); + EWLmemcpy(contextTable, tempCabacTable, 52 * 2 * 464); + EWLfree(tempCabacTable); + return 0; +} +#endif diff --git a/lib/vc8000nanoe/source/h264/H264Cabac.h b/lib/vc8000nanoe/source/h264/H264Cabac.h new file mode 100644 index 000000000..9766a790a --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Cabac.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : H264 CABAC + * + ******************************************************************************** + */ + +#ifndef __H264CABAC_H__ +#define __H264CABAC_H__ + +#include "basetype.h" + +u32 H264CabacInit(u32 *contextTable, u32 cabac_init_idc); + +#endif /* __H264CABAC_H__ */ diff --git a/lib/vc8000nanoe/source/h264/H264CabacContext.h b/lib/vc8000nanoe/source/h264/H264CabacContext.h new file mode 100644 index 000000000..4350c82e2 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264CabacContext.h @@ -0,0 +1,7942 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : CABAC initialization tables + * + ******************************************************************************** + */ + +#ifndef __H264CABACCONTEXT_H__ +#define __H264CABACCONTEXT_H__ + +#include "basetype.h" + +/* m and n values for given CtxIdx */ + +/* I Slices */ +static const int h264ContextInitIntra[460][2] = { + /* 0 -> 10 */ + {20, -15}, {2, 54}, {3, 74}, {20, -15}, + {2, 54}, {3, 74}, {-28, 127}, {-23, 104}, + {-6, 53}, {-1, 54}, {7, 51}, + + /* 11 -> 23 unsused for I */ + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + + /* 24 -> 39 */ + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + + /* 40 -> 53 */ + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, + + /* 54 -> 59 */ + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, + + /* 60 -> 69 */ + {0, 41}, {0, 63}, {0, 63}, {0, 63}, + {-9, 83}, {4, 86}, {0, 97}, {-7, 72}, + {13, 41}, {3, 62}, + + /* 70 -> 87 */ + {0, 11}, {1, 55}, {0, 69}, {-17, 127}, + {-13, 102}, {0, 82}, {-7, 74}, {-21, 107}, + {-27, 127}, {-31, 127}, {-24, 127}, {-18, 95}, + {-27, 127}, {-21, 114}, {-30, 127}, {-17, 123}, + {-12, 115}, {-16, 122}, + + /* 88 -> 104 */ + {-11, 115}, {-12, 63}, {-2, 68}, {-15, 84}, + {-13, 104}, {-3, 70}, {-8, 93}, {-10, 90}, + {-30, 127}, {-1, 74}, {-6, 97}, {-7, 91}, + {-20, 127}, {-4, 56}, {-5, 82}, {-7, 76}, + {-22, 125}, + + /* 105 -> 135 */ + {-7, 93}, {-11, 87}, {-3, 77}, {-5, 71}, + {-4, 63}, {-4, 68}, {-12, 84}, {-7, 62}, + {-7, 65}, {8, 61}, {5, 56}, {-2, 66}, + {1, 64}, {0, 61}, {-2, 78}, {1, 50}, + {7, 52}, {10, 35}, {0, 44}, {11, 38}, + {1, 45}, {0, 46}, {5, 44}, {31, 17}, + {1, 51}, {7, 50}, {28, 19}, {16, 33}, + {14, 62}, {-13, 108}, {-15, 100}, + + /* 136 -> 165 */ + {-13, 101}, {-13, 91}, {-12, 94}, {-10, 88}, + {-16, 84}, {-10, 86}, {-7, 83}, {-13, 87}, + {-19, 94}, {1, 70}, {0, 72}, {-5, 74}, + {18, 59}, {-8, 102}, {-15, 100}, {0, 95}, + {-4, 75}, {2, 72}, {-11, 75}, {-3, 71}, + {15, 46}, {-13, 69}, {0, 62}, {0, 65}, + {21, 37}, {-15, 72}, {9, 57}, {16, 54}, + {0, 62}, {12, 72}, + + /* 166 -> 196 */ + {24, 0}, {15, 9}, {8, 25}, {13, 18}, + {15, 9}, {13, 19}, {10, 37}, {12, 18}, + {6, 29}, {20, 33}, {15, 30}, {4, 45}, + {1, 58}, {0, 62}, {7, 61}, {12, 38}, + {11, 45}, {15, 39}, {11, 42}, {13, 44}, + {16, 45}, {12, 41}, {10, 49}, {30, 34}, + {18, 42}, {10, 55}, {17, 51}, {17, 46}, + {0, 89}, {26, -19}, {22, -17}, + + /* 197 -> 226 */ + {26, -17}, {30, -25}, {28, -20}, {33, -23}, + {37, -27}, {33, -23}, {40, -28}, {38, -17}, + {33, -11}, {40, -15}, {41, -6}, {38, 1}, + {41, 17}, {30, -6}, {27, 3}, {26, 22}, + {37, -16}, {35, -4}, {38, -8}, {38, -3}, + {37, 3}, {38, 5}, {42, 0}, {35, 16}, + {39, 22}, {14, 48}, {27, 37}, {21, 60}, + {12, 68}, {2, 97}, + + /* 227 -> 251 */ + {-3, 71}, {-6, 42}, {-5, 50}, {-3, 54}, + {-2, 62}, {0, 58}, {1, 63}, {-2, 72}, + {-1, 74}, {-9, 91}, {-5, 67}, {-5, 27}, + {-3, 39}, {-2, 44}, {0, 46}, {-16, 64}, + {-8, 68}, {-10, 78}, {-6, 77}, {-10, 86}, + {-12, 92}, {-15, 55}, {-10, 60}, {-6, 62}, + {-4, 65}, + + /* 252 -> 275 */ + {-12, 73}, {-8, 76}, {-7, 80}, {-9, 88}, + {-17, 110}, {-11, 97}, {-20, 84}, {-11, 79}, + {-6, 73}, {-4, 74}, {-13, 86}, {-13, 96}, + {-11, 97}, {-19, 117}, {-8, 78}, {-5, 33}, + {-4, 48}, {-2, 53}, {-3, 62}, {-13, 71}, + {-10, 79}, {-12, 86}, {-13, 90}, {-14, 97}, + + /* 276 special case, bypass used */ + {0, 0}, + + /* 277 -> 307 */ + {-6, 93}, {-6, 84}, {-8, 79}, {0, 66}, + {-1, 71}, {0, 62}, {-2, 60}, {-2, 59}, + {-5, 75}, {-3, 62}, {-4, 58}, {-9, 66}, + {-1, 79}, {0, 71}, {3, 68}, {10, 44}, + {-7, 62}, {15, 36}, {14, 40}, {16, 27}, + {12, 29}, {1, 44}, {20, 36}, {18, 32}, + {5, 42}, {1, 48}, {10, 62}, {17, 46}, + {9, 64}, {-12, 104}, {-11, 97}, + + /* 308 -> 337 */ + {-16, 96}, {-7, 88}, {-8, 85}, {-7, 85}, + {-9, 85}, {-13, 88}, {4, 66}, {-3, 77}, + {-3, 76}, {-6, 76}, {10, 58}, {-1, 76}, + {-1, 83}, {-7, 99}, {-14, 95}, {2, 95}, + {0, 76}, {-5, 74}, {0, 70}, {-11, 75}, + {1, 68}, {0, 65}, {-14, 73}, {3, 62}, + {4, 62}, {-1, 68}, {-13, 75}, {11, 55}, + {5, 64}, {12, 70}, + + /* 338 -> 368 */ + {15, 6}, {6, 19}, {7, 16}, {12, 14}, + {18, 13}, {13, 11}, {13, 15}, {15, 16}, + {12, 23}, {13, 23}, {15, 20}, {14, 26}, + {14, 44}, {17, 40}, {17, 47}, {24, 17}, + {21, 21}, {25, 22}, {31, 27}, {22, 29}, + {19, 35}, {14, 50}, {10, 57}, {7, 63}, + {-2, 77}, {-4, 82}, {-3, 94}, {9, 69}, + {-12, 109}, {36, -35}, {36, -34}, + + /* 369 -> 398 */ + {32, -26}, {37, -30}, {44, -32}, {34, -18}, + {34, -15}, {40, -15}, {33, -7}, {35, -5}, + {33, 0}, {38, 2}, {33, 13}, {23, 35}, + {13, 58}, {29, -3}, {26, 0}, {22, 30}, + {31, -7}, {35, -15}, {34, -3}, {34, 3}, + {36, -1}, {34, 5}, {32, 11}, {35, 5}, + {34, 12}, {39, 11}, {30, 29}, {34, 26}, + {29, 39}, {19, 66}, + + /* 399 -> 435 */ + {31, 21}, {31, 31}, {25, 50}, + {-17, 120}, {-20, 112}, {-18, 114}, {-11, 85}, + {-15, 92}, {-14, 89}, {-26, 71}, {-15, 81}, + {-14, 80}, {0, 68}, {-14, 70}, {-24, 56}, + {-23, 68}, {-24, 50}, {-11, 74}, {23, -13}, + {26, -13}, {40, -15}, {49, -14}, {44, 3}, + {45, 6}, {44, 34}, {33, 54}, {19, 82}, + {-3, 75}, {-1, 23}, {1, 34}, {1, 43}, + {0, 54}, {-2, 55}, {0, 61}, {1, 64}, + {0, 68}, {-9, 92}, + + /* 436 -> 459 */ + {-14, 106}, {-13, 97}, {-15, 90}, {-12, 90}, + {-18, 88}, {-10, 73}, {-9, 79}, {-14, 86}, + {-10, 73}, {-10, 70}, {-10, 69}, {-5, 66}, + {-9, 64}, {-5, 58}, {2, 59}, {21, -10}, + {24, -11}, {28, -8}, {28, -1}, {29, 3}, + {29, 9}, {35, 20}, {29, 36}, {14, 67} +}; + +/* P and B Slices can have cabac_init_idc == 0, 1 or 2 */ + +static const i32 h264ContextInit[3][460][2] = { + /* cabac_init_idc == 0 */ + { + /* 0 -> 10 */ + {20, -15}, {2, 54}, {3, 74}, {20, -15}, + {2, 54}, {3, 74}, {-28, 127}, {-23, 104}, + {-6, 53}, {-1, 54}, {7, 51}, + + /* 11 -> 23 */ + {23, 33}, {23, 2}, {21, 0}, {1, 9}, + {0, 49}, {-37, 118}, {5, 57}, {-13, 78}, + {-11, 65}, {1, 62}, {12, 49}, {-4, 73}, + {17, 50}, + + /* 24 -> 39 */ + {18, 64}, {9, 43}, {29, 0}, {26, 67}, + {16, 90}, {9, 104}, {-46, 127}, {-20, 104}, + {1, 67}, {-13, 78}, {-11, 65}, {1, 62}, + {-6, 86}, {-17, 95}, {-6, 61}, {9, 45}, + + /* 40 -> 53 */ + {-3, 69}, {-6, 81}, {-11, 96}, {6, 55}, + {7, 67}, {-5, 86}, {2, 88}, {0, 58}, + {-3, 76}, {-10, 94}, {5, 54}, {4, 69}, + {-3, 81}, {0, 88}, + + /* 54 -> 59 */ + {-7, 67}, {-5, 74}, {-4, 74}, {-5, 80}, + {-7, 72}, {1, 58}, + + /* 60 -> 69 */ + {0, 41}, {0, 63}, {0, 63}, {0, 63}, + {-9, 83}, {4, 86}, {0, 97}, {-7, 72}, + {13, 41}, {3, 62}, + + /* 70 -> 87 */ + {0, 45}, {-4, 78}, {-3, 96}, {-27, 126}, + {-28, 98}, {-25, 101}, {-23, 67}, {-28, 82}, + {-20, 94}, {-16, 83}, {-22, 110}, {-21, 91}, + {-18, 102}, {-13, 93}, {-29, 127}, {-7, 92}, + {-5, 89}, {-7, 96}, {-13, 108}, {-3, 46}, + {-1, 65}, {-1, 57}, {-9, 93}, {-3, 74}, + {-9, 92}, {-8, 87}, {-23, 126}, {5, 54}, + {6, 60}, {6, 59}, {6, 69}, {-1, 48}, + {0, 68}, {-4, 69}, {-8, 88}, + + /* 105 -> 165 */ + {-2, 85}, {-6, 78}, {-1, 75}, {-7, 77}, + {2, 54}, {5, 50}, {-3, 68}, {1, 50}, + {6, 42}, {-4, 81}, {1, 63}, {-4, 70}, + {0, 67}, {2, 57}, {-2, 76}, {11, 35}, + {4, 64}, {1, 61}, {11, 35}, {18, 25}, + {12, 24}, {13, 29}, {13, 36}, {-10, 93}, + {-7, 73}, {-2, 73}, {13, 46}, {9, 49}, + {-7, 100}, {9, 53}, {2, 53}, {5, 53}, + {-2, 61}, {0, 56}, {0, 56}, {-13, 63}, + {-5, 60}, {-1, 62}, {4, 57}, {-6, 69}, + {4, 57}, {14, 39}, {4, 51}, {13, 68}, + {3, 64}, {1, 61}, {9, 63}, {7, 50}, + {16, 39}, {5, 44}, {4, 52}, {11, 48}, + {-5, 60}, {-1, 59}, {0, 59}, {22, 33}, + {5, 44}, {14, 43}, {-1, 78}, {0, 60}, + {9, 69}, + + /* 166 -> 226 */ + {11, 28}, {2, 40}, {3, 44}, {0, 49}, + {0, 46}, {2, 44}, {2, 51}, {0, 47}, + {4, 39}, {2, 62}, {6, 46}, {0, 54}, + {3, 54}, {2, 58}, {4, 63}, {6, 51}, + {6, 57}, {7, 53}, {6, 52}, {6, 55}, + {11, 45}, {14, 36}, {8, 53}, {-1, 82}, + {7, 55}, {-3, 78}, {15, 46}, {22, 31}, + {-1, 84}, {25, 7}, {30, -7}, {28, 3}, + {28, 4}, {32, 0}, {34, -1}, {30, 6}, + {30, 6}, {32, 9}, {31, 19}, {26, 27}, + {26, 30}, {37, 20}, {28, 34}, {17, 70}, + {1, 67}, {5, 59}, {9, 67}, {16, 30}, + {18, 32}, {18, 35}, {22, 29}, {24, 31}, + {23, 38}, {18, 43}, {20, 41}, {11, 63}, + {9, 59}, {9, 64}, {-1, 94}, {-2, 89}, + {-9, 108}, + + /* 227 -> 275 */ + {-6, 76}, {-2, 44}, {0, 45}, {0, 52}, + {-3, 64}, {-2, 59}, {-4, 70}, {-4, 75}, + {-8, 82}, {-17, 102}, {-9, 77}, {3, 24}, + {0, 42}, {0, 48}, {0, 55}, {-6, 59}, + {-7, 71}, {-12, 83}, {-11, 87}, {-30, 119}, + {1, 58}, {-3, 29}, {-1, 36}, {1, 38}, + {2, 43}, {-6, 55}, {0, 58}, {0, 64}, + {-3, 74}, {-10, 90}, {0, 70}, {-4, 29}, + {5, 31}, {7, 42}, {1, 59}, {-2, 58}, + {-3, 72}, {-3, 81}, {-11, 97}, {0, 58}, + {8, 5}, {10, 14}, {14, 18}, {13, 27}, + {2, 40}, {0, 58}, {-3, 70}, {-6, 79}, + {-8, 85}, + + /* 276 special case, bypass used */ + {0, 0}, + + /* 277 -> 337 */ + {-13, 106}, {-16, 106}, {-10, 87}, {-21, 114}, + {-18, 110}, {-14, 98}, {-22, 110}, {-21, 106}, + {-18, 103}, {-21, 107}, {-23, 108}, {-26, 112}, + {-10, 96}, {-12, 95}, {-5, 91}, {-9, 93}, + {-22, 94}, {-5, 86}, {9, 67}, {-4, 80}, + {-10, 85}, {-1, 70}, {7, 60}, {9, 58}, + {5, 61}, {12, 50}, {15, 50}, {18, 49}, + {17, 54}, {10, 41}, {7, 46}, {-1, 51}, + {7, 49}, {8, 52}, {9, 41}, {6, 47}, + {2, 55}, {13, 41}, {10, 44}, {6, 50}, + {5, 53}, {13, 49}, {4, 63}, {6, 64}, + {-2, 69}, {-2, 59}, {6, 70}, {10, 44}, + {9, 31}, {12, 43}, {3, 53}, {14, 34}, + {10, 38}, {-3, 52}, {13, 40}, {17, 32}, + {7, 44}, {7, 38}, {13, 50}, {10, 57}, + {26, 43}, + + /* 338 -> 398 */ + {14, 11}, {11, 14}, {9, 11}, {18, 11}, + {21, 9}, {23, -2}, {32, -15}, {32, -15}, + {34, -21}, {39, -23}, {42, -33}, {41, -31}, + {46, -28}, {38, -12}, {21, 29}, {45, -24}, + {53, -45}, {48, -26}, {65, -43}, {43, -19}, + {39, -10}, {30, 9}, {18, 26}, {20, 27}, + {0, 57}, {-14, 82}, {-5, 75}, {-19, 97}, + {-35, 125}, {27, 0}, {28, 0}, {31, -4}, + {27, 6}, {34, 8}, {30, 10}, {24, 22}, + {33, 19}, {22, 32}, {26, 31}, {21, 41}, + {26, 44}, {23, 47}, {16, 65}, {14, 71}, + {8, 60}, {6, 63}, {17, 65}, {21, 24}, + {23, 20}, {26, 23}, {27, 32}, {28, 23}, + {28, 24}, {23, 40}, {24, 32}, {28, 29}, + {23, 42}, {19, 57}, {22, 53}, {22, 61}, + {11, 86}, + + /* 399 -> 435 */ + {12, 40}, {11, 51}, {14, 59}, + {-4, 79}, {-7, 71}, {-5, 69}, {-9, 70}, + {-8, 66}, {-10, 68}, {-19, 73}, {-12, 69}, + {-16, 70}, {-15, 67}, {-20, 62}, {-19, 70}, + {-16, 66}, {-22, 65}, {-20, 63}, {9, -2}, + {26, -9}, {33, -9}, {39, -7}, {41, -2}, + {45, 3}, {49, 9}, {45, 27}, {36, 59}, + {-6, 66}, {-7, 35}, {-7, 42}, {-8, 45}, + {-5, 48}, {-12, 56}, {-6, 60}, {-5, 62}, + {-8, 66}, {-8, 76}, + + /* 436 -> 459 */ + {-5, 85}, {-6, 81}, {-10, 77}, {-7, 81}, + {-17, 80}, {-18, 73}, {-4, 74}, {-10, 83}, + {-9, 71}, {-9, 67}, {-1, 61}, {-8, 66}, + {-14, 66}, {0, 59}, {2, 59}, {21, -13}, + {33, -14}, {39, -7}, {46, -2}, {51, 2}, + {60, 6}, {61, 17}, {55, 34}, {42, 62}, + }, + + /* cabac_init_idc == 1 */ + { + /* 0 -> 10 */ + {20, -15}, {2, 54}, {3, 74}, {20, -15}, + {2, 54}, {3, 74}, {-28, 127}, {-23, 104}, + {-6, 53}, {-1, 54}, {7, 51}, + + /* 11 -> 23 */ + {22, 25}, {34, 0}, {16, 0}, {-2, 9}, + {4, 41}, {-29, 118}, {2, 65}, {-6, 71}, + {-13, 79}, {5, 52}, {9, 50}, {-3, 70}, + {10, 54}, + + /* 24 -> 39 */ + {26, 34}, {19, 22}, {40, 0}, {57, 2}, + {41, 36}, {26, 69}, {-45, 127}, {-15, 101}, + {-4, 76}, {-6, 71}, {-13, 79}, {5, 52}, + {6, 69}, {-13, 90}, {0, 52}, {8, 43}, + + /* 40 -> 53 */ + {-2, 69}, {-5, 82}, {-10, 96}, {2, 59}, + {2, 75}, {-3, 87}, {-3, 100}, {1, 56}, + {-3, 74}, {-6, 85}, {0, 59}, {-3, 81}, + {-7, 86}, {-5, 95}, + + /* 54 -> 59 */ + {-1, 66}, {-1, 77}, {1, 70}, {-2, 86}, + {-5, 72}, {0, 61}, + + /* 60 -> 69 */ + {0, 41}, {0, 63}, {0, 63}, {0, 63}, + {-9, 83}, {4, 86}, {0, 97}, {-7, 72}, + {13, 41}, {3, 62}, + + /* 70 -> 104 */ + {13, 15}, {7, 51}, {2, 80}, {-39, 127}, + {-18, 91}, {-17, 96}, {-26, 81}, {-35, 98}, + {-24, 102}, {-23, 97}, {-27, 119}, {-24, 99}, + {-21, 110}, {-18, 102}, {-36, 127}, {0, 80}, + {-5, 89}, {-7, 94}, {-4, 92}, {0, 39}, + {0, 65}, {-15, 84}, {-35, 127}, {-2, 73}, + {-12, 104}, {-9, 91}, {-31, 127}, {3, 55}, + {7, 56}, {7, 55}, {8, 61}, {-3, 53}, + {0, 68}, {-7, 74}, {-9, 88}, + + /* 105 -> 165 */ + {-13, 103}, {-13, 91}, {-9, 89}, {-14, 92}, + {-8, 76}, {-12, 87}, {-23, 110}, {-24, 105}, + {-10, 78}, {-20, 112}, {-17, 99}, {-78, 127}, + {-70, 127}, {-50, 127}, {-46, 127}, {-4, 66}, + {-5, 78}, {-4, 71}, {-8, 72}, {2, 59}, + {-1, 55}, {-7, 70}, {-6, 75}, {-8, 89}, + {-34, 119}, {-3, 75}, {32, 20}, {30, 22}, + {-44, 127}, {0, 54}, {-5, 61}, {0, 58}, + {-1, 60}, {-3, 61}, {-8, 67}, {-25, 84}, + {-14, 74}, {-5, 65}, {5, 52}, {2, 57}, + {0, 61}, {-9, 69}, {-11, 70}, {18, 55}, + {-4, 71}, {0, 58}, {7, 61}, {9, 41}, + {18, 25}, {9, 32}, {5, 43}, {9, 47}, + {0, 44}, {0, 51}, {2, 46}, {19, 38}, + {-4, 66}, {15, 38}, {12, 42}, {9, 34}, + {0, 89}, + + /* 166 -> 226 */ + {4, 45}, {10, 28}, {10, 31}, {33, -11}, + {52, -43}, {18, 15}, {28, 0}, {35, -22}, + {38, -25}, {34, 0}, {39, -18}, {32, -12}, + {102, -94}, {0, 0}, {56, -15}, {33, -4}, + {29, 10}, {37, -5}, {51, -29}, {39, -9}, + {52, -34}, {69, -58}, {67, -63}, {44, -5}, + {32, 7}, {55, -29}, {32, 1}, {0, 0}, + {27, 36}, {33, -25}, {34, -30}, {36, -28}, + {38, -28}, {38, -27}, {34, -18}, {35, -16}, + {34, -14}, {32, -8}, {37, -6}, {35, 0}, + {30, 10}, {28, 18}, {26, 25}, {29, 41}, + {0, 75}, {2, 72}, {8, 77}, {14, 35}, + {18, 31}, {17, 35}, {21, 30}, {17, 45}, + {20, 42}, {18, 45}, {27, 26}, {16, 54}, + {7, 66}, {16, 56}, {11, 73}, {10, 67}, + {-10, 116}, + + /* 227 -> 275 */ + {-23, 112}, {-15, 71}, {-7, 61}, {0, 53}, + {-5, 66}, {-11, 77}, {-9, 80}, {-9, 84}, + {-10, 87}, {-34, 127}, {-21, 101}, {-3, 39}, + {-5, 53}, {-7, 61}, {-11, 75}, {-15, 77}, + {-17, 91}, {-25, 107}, {-25, 111}, {-28, 122}, + {-11, 76}, {-10, 44}, {-10, 52}, {-10, 57}, + {-9, 58}, {-16, 72}, {-7, 69}, {-4, 69}, + {-5, 74}, {-9, 86}, {2, 66}, {-9, 34}, + {1, 32}, {11, 31}, {5, 52}, {-2, 55}, + {-2, 67}, {0, 73}, {-8, 89}, {3, 52}, + {7, 4}, {10, 8}, {17, 8}, {16, 19}, + {3, 37}, {-1, 61}, {-5, 73}, {-1, 70}, + {-4, 78}, + + /* 276 special case, bypass used */ + {0, 0}, + + /* 277 -> 337 */ + {-21, 126}, {-23, 124}, {-20, 110}, {-26, 126}, + {-25, 124}, {-17, 105}, {-27, 121}, {-27, 117}, + {-17, 102}, {-26, 117}, {-27, 116}, {-33, 122}, + {-10, 95}, {-14, 100}, {-8, 95}, {-17, 111}, + {-28, 114}, {-6, 89}, {-2, 80}, {-4, 82}, + {-9, 85}, {-8, 81}, {-1, 72}, {5, 64}, + {1, 67}, {9, 56}, {0, 69}, {1, 69}, + {7, 69}, {-7, 69}, {-6, 67}, {-16, 77}, + {-2, 64}, {2, 61}, {-6, 67}, {-3, 64}, + {2, 57}, {-3, 65}, {-3, 66}, {0, 62}, + {9, 51}, {-1, 66}, {-2, 71}, {-2, 75}, + {-1, 70}, {-9, 72}, {14, 60}, {16, 37}, + {0, 47}, {18, 35}, {11, 37}, {12, 41}, + {10, 41}, {2, 48}, {12, 41}, {13, 41}, + {0, 59}, {3, 50}, {19, 40}, {3, 66}, + {18, 50}, + + /* 338 -> 398 */ + {19, -6}, {18, -6}, {14, 0}, {26, -12}, + {31, -16}, {33, -25}, {33, -22}, {37, -28}, + {39, -30}, {42, -30}, {47, -42}, {45, -36}, + {49, -34}, {41, -17}, {32, 9}, {69, -71}, + {63, -63}, {66, -64}, {77, -74}, {54, -39}, + {52, -35}, {41, -10}, {36, 0}, {40, -1}, + {30, 14}, {28, 26}, {23, 37}, {12, 55}, + {11, 65}, {37, -33}, {39, -36}, {40, -37}, + {38, -30}, {46, -33}, {42, -30}, {40, -24}, + {49, -29}, {38, -12}, {40, -10}, {38, -3}, + {46, -5}, {31, 20}, {29, 30}, {25, 44}, + {12, 48}, {11, 49}, {26, 45}, {22, 22}, + {23, 22}, {27, 21}, {33, 20}, {26, 28}, + {30, 24}, {27, 34}, {18, 42}, {25, 39}, + {18, 50}, {12, 70}, {21, 54}, {14, 71}, + {11, 83}, + + /* 399 -> 435 */ + {25, 32}, {21, 49}, {21, 54}, + {-5, 85}, {-6, 81}, {-10, 77}, {-7, 81}, + {-17, 80}, {-18, 73}, {-4, 74}, {-10, 83}, + {-9, 71}, {-9, 67}, {-1, 61}, {-8, 66}, + {-14, 66}, {0, 59}, {2, 59}, {17, -10}, + {32, -13}, {42, -9}, {49, -5}, {53, 0}, + {64, 3}, {68, 10}, {66, 27}, {47, 57}, + {-5, 71}, {0, 24}, {-1, 36}, {-2, 42}, + {-2, 52}, {-9, 57}, {-6, 63}, {-4, 65}, + {-4, 67}, {-7, 82}, + + /* 436 -> 459 */ + {-3, 81}, {-3, 76}, {-7, 72}, {-6, 78}, + {-12, 72}, {-14, 68}, {-3, 70}, {-6, 76}, + {-5, 66}, {-5, 62}, {0, 57}, {-4, 61}, + {-9, 60}, {1, 54}, {2, 58}, {17, -10}, + {32, -13}, {42, -9}, {49, -5}, {53, 0}, + {64, 3}, {68, 10}, {66, 27}, {47, 57}, + }, + + /* cabac_init_idc == 2 */ + { + /* 0 -> 10 */ + {20, -15}, {2, 54}, {3, 74}, {20, -15}, + {2, 54}, {3, 74}, {-28, 127}, {-23, 104}, + {-6, 53}, {-1, 54}, {7, 51}, + + /* 11 -> 23 */ + {29, 16}, {25, 0}, {14, 0}, {-10, 51}, + {-3, 62}, {-27, 99}, {26, 16}, {-4, 85}, + {-24, 102}, {5, 57}, {6, 57}, {-17, 73}, + {14, 57}, + + /* 24 -> 39 */ + {20, 40}, {20, 10}, {29, 0}, {54, 0}, + {37, 42}, {12, 97}, {-32, 127}, {-22, 117}, + {-2, 74}, {-4, 85}, {-24, 102}, {5, 57}, + {-6, 93}, {-14, 88}, {-6, 44}, {4, 55}, + + /* 40 -> 53 */ + {-11, 89}, {-15, 103}, {-21, 116}, {19, 57}, + {20, 58}, {4, 84}, {6, 96}, {1, 63}, + {-5, 85}, {-13, 106}, {5, 63}, {6, 75}, + {-3, 90}, {-1, 101}, + + /* 54 -> 59 */ + {3, 55}, {-4, 79}, {-2, 75}, {-12, 97}, + {-7, 50}, {1, 60}, + + /* 60 -> 69 */ + {0, 41}, {0, 63}, {0, 63}, {0, 63}, + {-9, 83}, {4, 86}, {0, 97}, {-7, 72}, + {13, 41}, {3, 62}, + + /* 70 -> 104 */ + {7, 34}, {-9, 88}, {-20, 127}, {-36, 127}, + {-17, 91}, {-14, 95}, {-25, 84}, {-25, 86}, + {-12, 89}, {-17, 91}, {-31, 127}, {-14, 76}, + {-18, 103}, {-13, 90}, {-37, 127}, {11, 80}, + {5, 76}, {2, 84}, {5, 78}, {-6, 55}, + {4, 61}, {-14, 83}, {-37, 127}, {-5, 79}, + {-11, 104}, {-11, 91}, {-30, 127}, {0, 65}, + {-2, 79}, {0, 72}, {-4, 92}, {-6, 56}, + {3, 68}, {-8, 71}, {-13, 98}, + + /* 105 -> 165 */ + {-4, 86}, {-12, 88}, {-5, 82}, {-3, 72}, + {-4, 67}, {-8, 72}, {-16, 89}, {-9, 69}, + {-1, 59}, {5, 66}, {4, 57}, {-4, 71}, + {-2, 71}, {2, 58}, {-1, 74}, {-4, 44}, + {-1, 69}, {0, 62}, {-7, 51}, {-4, 47}, + {-6, 42}, {-3, 41}, {-6, 53}, {8, 76}, + {-9, 78}, {-11, 83}, {9, 52}, {0, 67}, + {-5, 90}, {1, 67}, {-15, 72}, {-5, 75}, + {-8, 80}, {-21, 83}, {-21, 64}, {-13, 31}, + {-25, 64}, {-29, 94}, {9, 75}, {17, 63}, + {-8, 74}, {-5, 35}, {-2, 27}, {13, 91}, + {3, 65}, {-7, 69}, {8, 77}, {-10, 66}, + {3, 62}, {-3, 68}, {-20, 81}, {0, 30}, + {1, 7}, {-3, 23}, {-21, 74}, {16, 66}, + {-23, 124}, {17, 37}, {44, -18}, {50, -34}, + {-22, 127}, + + /* 166 -> 226 */ + {4, 39}, {0, 42}, {7, 34}, {11, 29}, + {8, 31}, {6, 37}, {7, 42}, {3, 40}, + {8, 33}, {13, 43}, {13, 36}, {4, 47}, + {3, 55}, {2, 58}, {6, 60}, {8, 44}, + {11, 44}, {14, 42}, {7, 48}, {4, 56}, + {4, 52}, {13, 37}, {9, 49}, {19, 58}, + {10, 48}, {12, 45}, {0, 69}, {20, 33}, + {8, 63}, {35, -18}, {33, -25}, {28, -3}, + {24, 10}, {27, 0}, {34, -14}, {52, -44}, + {39, -24}, {19, 17}, {31, 25}, {36, 29}, + {24, 33}, {34, 15}, {30, 20}, {22, 73}, + {20, 34}, {19, 31}, {27, 44}, {19, 16}, + {15, 36}, {15, 36}, {21, 28}, {25, 21}, + {30, 20}, {31, 12}, {27, 16}, {24, 42}, + {0, 93}, {14, 56}, {15, 57}, {26, 38}, + {-24, 127}, + + /* 227 -> 275 */ + {-24, 115}, {-22, 82}, {-9, 62}, {0, 53}, + {0, 59}, {-14, 85}, {-13, 89}, {-13, 94}, + {-11, 92}, {-29, 127}, {-21, 100}, {-14, 57}, + {-12, 67}, {-11, 71}, {-10, 77}, {-21, 85}, + {-16, 88}, {-23, 104}, {-15, 98}, {-37, 127}, + {-10, 82}, {-8, 48}, {-8, 61}, {-8, 66}, + {-7, 70}, {-14, 75}, {-10, 79}, {-9, 83}, + {-12, 92}, {-18, 108}, {-4, 79}, {-22, 69}, + {-16, 75}, {-2, 58}, {1, 58}, {-13, 78}, + {-9, 83}, {-4, 81}, {-13, 99}, {-13, 81}, + {-6, 38}, {-13, 62}, {-6, 58}, {-2, 59}, + {-16, 73}, {-10, 76}, {-13, 86}, {-9, 83}, + {-10, 87}, + + /* 276 special case, bypass used */ + {0, 0}, + + /* 277 -> 337 */ + {-22, 127}, {-25, 127}, {-25, 120}, {-27, 127}, + {-19, 114}, {-23, 117}, {-25, 118}, {-26, 117}, + {-24, 113}, {-28, 118}, {-31, 120}, {-37, 124}, + {-10, 94}, {-15, 102}, {-10, 99}, {-13, 106}, + {-50, 127}, {-5, 92}, {17, 57}, {-5, 86}, + {-13, 94}, {-12, 91}, {-2, 77}, {0, 71}, + {-1, 73}, {4, 64}, {-7, 81}, {5, 64}, + {15, 57}, {1, 67}, {0, 68}, {-10, 67}, + {1, 68}, {0, 77}, {2, 64}, {0, 68}, + {-5, 78}, {7, 55}, {5, 59}, {2, 65}, + {14, 54}, {15, 44}, {5, 60}, {2, 70}, + {-2, 76}, {-18, 86}, {12, 70}, {5, 64}, + {-12, 70}, {11, 55}, {5, 56}, {0, 69}, + {2, 65}, {-6, 74}, {5, 54}, {7, 54}, + {-6, 76}, {-11, 82}, {-2, 77}, {-2, 77}, + {25, 42}, + + /* 338 -> 398 */ + {17, -13}, {16, -9}, {17, -12}, {27, -21}, + {37, -30}, {41, -40}, {42, -41}, {48, -47}, + {39, -32}, {46, -40}, {52, -51}, {46, -41}, + {52, -39}, {43, -19}, {32, 11}, {61, -55}, + {56, -46}, {62, -50}, {81, -67}, {45, -20}, + {35, -2}, {28, 15}, {34, 1}, {39, 1}, + {30, 17}, {20, 38}, {18, 45}, {15, 54}, + {0, 79}, {36, -16}, {37, -14}, {37, -17}, + {32, 1}, {34, 15}, {29, 15}, {24, 25}, + {34, 22}, {31, 16}, {35, 18}, {31, 28}, + {33, 41}, {36, 28}, {27, 47}, {21, 62}, + {18, 31}, {19, 26}, {36, 24}, {24, 23}, + {27, 16}, {24, 30}, {31, 29}, {22, 41}, + {22, 42}, {16, 60}, {15, 52}, {14, 60}, + {3, 78}, {-16, 123}, {21, 53}, {22, 56}, + {25, 61}, + + /* 399 -> 435 */ + {21, 33}, {19, 50}, {17, 61}, + {-3, 78}, {-8, 74}, {-9, 72}, {-10, 72}, + {-18, 75}, {-12, 71}, {-11, 63}, {-5, 70}, + {-17, 75}, {-14, 72}, {-16, 67}, {-8, 53}, + {-14, 59}, {-9, 52}, {-11, 68}, {9, -2}, + {30, -10}, {31, -4}, {33, -1}, {33, 7}, + {31, 12}, {37, 23}, {31, 38}, {20, 64}, + {-9, 71}, {-7, 37}, {-8, 44}, {-11, 49}, + {-10, 56}, {-12, 59}, {-8, 63}, {-9, 67}, + {-6, 68}, {-10, 79}, + + /* 436 -> 459 */ + {-3, 78}, {-8, 74}, {-9, 72}, {-10, 72}, + {-18, 75}, {-12, 71}, {-11, 63}, {-5, 70}, + {-17, 75}, {-14, 72}, {-16, 67}, {-8, 53}, + {-14, 59}, {-9, 52}, {-11, 68}, {9, -2}, + {30, -10}, {31, -4}, {33, -1}, {33, 7}, + {31, 12}, {37, 23}, {31, 38}, {20, 64}, + } +}; + +#ifdef H8290_PRECALC_CABAC_INIT +static const u8 preCalculatedContextTable[3][48256] = { +/*cabac_init_idc = 0*/ +{124,18,21,124,18,21,125,81,20,18,24,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, +44,0,0,0,39,45,67,17,44,2,104,16,11,125,77,37,21,87,125,125, +125,63,125,101,125,119,103,117,103,0,9,41,81,13,59,53,125,21,67,55, +125,14,37,25,123,59,47,27,15,0,9,41,2,3,4,14,5,1,4,29, +26,22,56,38,50,36,34,38,92,24,26,88,60,2,89,73,75,55,61,49, +41,45,39,47,61,13,17,21,8,77,73,63,23,17,23,15,34,11,2,3, +52,17,12,18,2,17,124,108,76,90,108,88,52,90,68,60,66,36,10,2, +4,50,36,48,42,38,36,44,28,58,42,16,24,34,51,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,92,124,120,82,124,124,124,124,120,116,124, +94,82,30,52,6,9,67,15,42,26,18,2,10,0,17,21,55,7,72,48, +38,34,1,9,29,27,45,57,16,6,2,3,19,25,33,49,93,67,41,31, +19,21,45,65,67,107,29,60,30,20,2,15,31,45,53,67,124,59,41,31, +5,15,2,6,8,23,2,10,5,31,15,9,38,2,54,46,72,68,38,54, +62,42,30,2,34,1,81,67,65,49,43,43,43,49,5,27,25,25,10,25, +39,71,63,63,25,21,13,23,9,3,19,2,2,9,23,16,1,13,114,88, +94,98,100,104,96,94,80,80,86,74,38,46,32,92,84,82,72,68,56,26, +12,0,27,37,61,11,91,124,124,124,124,124,124,124,124,124,124,124,122,100, +56,10,124,124,66,124,124,124,120,124,116,104,116,102,104,68,74,48,5,84, +64,26,113,97,101,43,57,51,15,35,33,9,13,14,9,26,21,124,124,124, +124,120,114,58,18,37,23,80,58,40,18,16,4,1,9,57,85,67,53,53, +49,19,31,45,19,13,11,5,1,10,8,124,124,124,124,120,108,86,54,7, +0,0,0,0,124,18,21,124,18,21,125,81,20,18,24,60,122,124,108,28, +109,12,29,3,2,28,19,26,1,40,124,7,53,81,125,81,7,29,3,2, +45,63,4,36,11,35,65,16,7,45,49,10,25,61,18,11,35,49,7,21, +21,33,17,10,44,0,0,0,39,45,67,17,44,2,36,29,65,125,69,75, +7,37,61,39,93,55,77,59,125,57,51,65,89,34,3,12,59,21,57,47, +125,18,6,8,11,30,9,11,49,43,29,23,27,18,26,9,26,42,35,0, +13,7,12,25,56,1,4,56,76,78,68,54,59,19,19,34,28,73,20,20, +20,4,14,14,0,6,2,12,11,12,48,24,9,1,4,0,26,48,38,22, +30,6,8,8,60,38,40,29,6,11,70,46,38,28,34,38,24,32,48,2, +34,18,18,10,0,24,12,20,22,16,36,54,20,37,16,29,34,64,41,112, +124,120,118,124,124,114,114,108,88,72,66,86,58,13,7,8,7,66,62,56, +68,64,50,40,44,0,8,1,61,51,89,25,38,36,22,1,8,13,23,37, +77,27,78,42,30,16,8,15,39,47,111,10,68,54,50,40,16,10,1,21, +53,13,68,64,42,8,10,17,35,67,10,116,98,90,72,46,10,13,31,43, +124,85,85,47,101,93,69,93,85,79,87,89,97,65,63,55,59,61,45,7, +33,43,13,6,10,4,26,26,28,18,44,34,24,28,22,44,32,16,44,38, +26,20,28,0,1,11,8,13,38,64,40,20,58,50,22,46,62,38,50,26, +12,40,104,98,104,104,108,124,124,124,124,124,124,124,124,124,68,124,124,124, +124,124,124,108,74,72,12,37,23,67,123,124,124,124,114,110,106,82,88,62, +64,44,38,32,3,15,6,0,3,78,86,80,62,80,78,46,62,68,42,12, +20,4,45,46,24,8,31,15,11,13,5,9,19,11,13,7,2,13,5,3, +0,124,124,124,124,124,120,108,72,8,5,56,42,36,30,14,6,2,5,25, +43,35,27,35,33,19,21,39,15,7,4,5,5,8,8,124,124,124,124,122, +114,92,58,2,0,0,0,0,124,18,21,124,18,21,123,77,22,20,24,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,44,0,0,0,37,45,67,15,44,2,104,16, +11,123,75,37,19,83,123,123,123,59,123,97,123,115,101,115,101,2,7,39, +79,11,57,51,123,19,65,53,123,16,35,23,119,57,45,25,13,2,7,39, +4,1,4,14,3,1,4,27,26,22,56,38,50,36,34,38,90,24,26,86, +58,2,87,71,73,53,59,47,39,43,37,45,57,13,17,19,6,75,71,63, +21,17,21,13,34,9,2,3,50,15,12,16,2,17,124,108,76,90,108,88, +52,90,68,58,66,36,10,2,4,50,36,48,42,38,34,44,28,56,40,16, +22,32,51,124,124,124,124,124,124,124,124,124,124,124,124,124,120,88,124,118, +80,124,124,124,124,116,112,122,90,78,30,50,4,9,67,13,44,28,20,4, +10,0,15,19,53,5,74,50,40,34,0,7,27,25,43,55,18,8,4,1, +17,23,31,47,89,65,37,29,17,19,43,63,65,103,27,62,32,22,4,13, +29,43,51,65,124,57,39,29,5,13,2,8,10,21,4,12,3,29,15,9, +38,4,54,46,70,68,38,52,60,42,30,2,32,1,79,65,63,47,41,41, +41,47,5,25,23,23,10,23,37,69,61,63,25,19,13,21,9,3,17,2, +2,7,21,16,1,13,114,88,94,98,98,104,96,94,80,80,86,74,38,44, +30,90,82,80,70,66,54,26,12,0,25,35,59,11,89,124,124,124,124,124, +124,124,124,124,124,122,118,96,54,10,124,124,64,124,124,124,116,124,112,100, +112,98,100,66,70,46,7,82,62,24,109,93,97,41,55,49,11,33,31,9, +11,18,5,30,19,124,124,124,124,116,110,54,14,39,21,82,58,40,18,18, +4,1,9,55,83,65,51,51,45,17,29,43,17,11,9,3,0,12,8,124, +124,124,124,118,106,82,52,7,0,0,0,0,124,18,21,124,18,21,123,77, +22,20,24,58,120,124,108,28,103,12,27,1,2,28,17,24,3,40,124,9, +55,81,121,77,7,27,1,2,43,59,6,36,9,33,63,16,7,43,49,10, +23,59,18,11,33,49,5,19,19,31,15,10,44,0,0,0,37,45,67,15, +44,2,36,27,63,121,65,71,3,33,57,37,89,51,73,57,123,55,49,63, +87,36,1,14,57,19,55,45,121,18,6,8,11,32,9,9,47,41,27,21, +25,18,26,7,26,42,33,0,11,7,12,23,56,1,4,56,74,78,68,54, +57,17,17,34,28,71,20,20,20,6,14,14,2,8,4,12,9,12,48,24, +9,1,4,0,26,46,38,22,30,8,10,8,58,38,40,27,6,11,70,46, +38,28,34,38,24,32,48,2,34,18,18,10,0,24,12,20,22,16,36,54, +20,35,16,27,34,62,39,110,124,118,116,122,124,112,112,104,86,70,64,82, +56,15,7,8,7,64,60,54,66,62,48,38,42,0,8,1,59,49,87,23, +40,36,22,0,10,11,21,35,73,25,78,42,30,16,10,13,37,45,107,10, +70,56,50,40,18,10,1,19,51,13,70,64,42,8,12,15,33,65,10,116, +98,90,72,46,10,11,29,41,124,83,83,45,97,89,67,89,81,75,83,85, +93,63,61,53,57,57,43,7,31,41,11,6,10,4,26,26,26,16,44,34, +26,28,22,44,32,16,44,38,26,20,28,0,1,9,10,13,38,64,40,20, +58,50,24,46,60,38,50,26,12,38,104,98,104,102,106,124,124,124,124,124, +124,124,124,124,66,124,124,124,124,124,124,106,72,70,12,35,21,63,117,124, +124,124,112,106,104,80,84,60,62,42,36,30,5,15,6,0,5,76,84,78, +60,78,76,44,60,66,40,10,18,2,45,46,24,8,29,13,9,11,3,7, +15,9,11,5,6,9,3,0,4,124,124,124,124,124,116,102,68,4,3,58, +44,38,32,16,8,4,3,23,41,33,25,33,29,15,19,37,13,5,6,3, +3,8,8,124,124,124,124,116,108,86,52,1,0,0,0,0,124,18,21,124, +18,21,119,75,22,20,24,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,44,0,0,0, +35,45,67,15,42,2,104,16,11,121,73,37,19,81,119,119,121,57,119,95, +119,113,99,113,99,4,7,37,77,11,57,49,119,19,65,53,121,16,35,23, +117,57,43,25,13,2,7,37,4,1,2,14,3,1,4,27,26,22,54,38, +48,36,34,38,86,24,26,82,56,0,85,69,71,51,57,45,37,41,37,43, +55,13,17,19,4,75,69,63,21,17,19,13,32,7,2,3,48,13,10,14, +2,19,120,106,74,88,106,86,50,88,68,56,64,36,10,2,4,48,34,46, +40,36,32,42,26,52,38,14,20,30,51,124,124,124,124,124,124,124,124,124, +124,124,124,124,116,82,124,114,76,124,124,124,124,112,108,116,86,74,28,46, +2,11,67,13,44,28,20,4,10,0,15,19,51,5,74,50,40,34,2,7, +25,25,41,53,20,10,4,1,15,23,31,45,87,63,35,27,17,19,41,61, +63,101,27,62,32,22,4,11,27,41,49,63,124,57,39,29,5,13,2,8, +10,21,4,12,1,29,15,9,36,4,52,44,68,66,38,50,58,42,30,0, +30,3,77,63,61,47,41,41,39,45,5,25,23,23,8,23,37,69,59,63, +25,19,13,19,9,3,15,2,2,7,19,14,1,15,112,88,94,96,96,102, +94,92,78,78,84,72,36,42,28,86,80,76,66,64,52,24,10,0,25,35, +59,13,87,124,124,124,124,124,124,124,124,124,124,118,114,92,52,8,124,120, +62,124,124,124,112,120,108,96,108,94,96,62,66,42,9,78,58,20,107,91, +95,39,53,47,7,31,29,9,9,20,3,32,17,124,124,124,124,110,104,48, +10,41,21,82,58,40,18,18,4,1,9,53,81,63,49,49,43,15,27,41, +15,9,7,3,2,12,8,124,124,124,122,114,102,78,48,9,0,0,0,0, +124,18,21,124,18,21,119,75,22,20,24,56,118,122,108,28,99,12,25,0, +2,26,17,22,5,38,120,13,57,83,115,75,7,25,0,2,43,57,6,34, +9,33,61,16,7,43,49,10,23,57,18,11,33,49,5,19,19,31,15,10, +44,0,0,0,35,45,67,15,42,2,36,27,63,117,61,67,1,29,55,35, +87,49,71,55,119,55,49,63,85,36,1,14,55,19,53,45,119,18,6,8, +11,32,9,9,47,41,27,21,25,18,26,7,26,42,33,0,11,7,12,23, +54,1,4,54,72,76,66,52,55,17,17,32,26,71,18,20,20,6,14,14, +4,8,4,12,9,12,46,24,11,1,4,1,26,44,38,22,28,8,10,8, +56,38,38,27,6,13,68,46,38,28,34,38,24,32,48,2,34,18,18,10, +0,24,12,20,22,16,34,52,18,35,16,27,32,60,39,106,124,114,112,118, +120,108,108,100,82,66,60,78,52,17,7,8,9,62,58,52,64,58,46,36, +40,1,6,3,59,49,85,23,40,36,22,0,10,11,21,35,71,23,78,42, +30,16,10,13,35,43,103,10,70,56,50,40,18,10,1,19,49,13,70,64, +42,8,12,15,33,63,10,114,96,88,70,46,10,11,29,41,124,81,81,43, +95,87,65,87,79,73,81,83,89,61,59,53,55,55,43,9,31,39,11,6, +8,4,24,24,24,14,42,34,26,28,20,42,32,16,42,36,26,20,26,0, +1,9,10,13,36,62,38,20,56,48,24,44,58,38,50,24,10,34,102,96, +102,100,104,124,124,124,124,124,124,124,124,124,64,124,124,124,124,124,124,102, +70,68,12,33,21,61,113,120,120,124,108,102,100,76,80,58,58,40,32,28, +7,17,4,0,7,74,82,74,56,74,72,42,56,62,38,8,16,0,47,44, +22,6,29,13,9,9,3,5,13,7,9,3,8,7,1,2,6,124,124,124, +124,120,110,96,62,0,3,58,44,38,32,18,8,4,3,23,41,33,23,33, +27,13,19,35,11,3,6,3,1,8,8,124,124,124,120,110,100,78,46,7, +0,0,0,0,124,18,21,124,18,21,115,71,24,20,22,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,44,0,0,0,35,45,67,13,40,2,104,16,11,119,71,37, +17,79,115,115,117,55,115,93,115,111,97,111,97,6,7,35,75,11,55,49, +115,19,63,51,119,16,35,21,113,55,41,25,13,2,7,35,6,0,2,14, +3,1,4,27,26,20,54,38,46,36,34,38,82,24,24,78,54,1,83,67, +69,49,55,45,35,41,35,41,53,13,17,19,2,73,67,63,21,17,17,13, +30,5,2,3,46,11,10,12,2,21,118,104,74,86,104,84,50,86,66,54, +62,36,10,2,2,46,32,44,38,34,30,40,26,48,36,14,18,28,51,124, +124,124,124,124,124,124,124,124,124,124,124,124,110,78,124,110,74,124,122,124, +118,108,102,112,82,68,26,42,0,13,67,13,46,28,20,4,10,0,15,19, +51,5,74,50,40,34,4,5,25,23,41,51,22,10,6,1,13,21,29,45, +85,61,33,25,15,19,39,59,61,99,25,62,32,22,4,9,27,39,47,61, +124,55,37,27,5,13,2,8,10,21,4,12,1,29,15,9,36,6,50,42, +66,64,38,48,56,42,30,0,28,3,75,61,59,45,39,39,39,43,5,25, +23,21,8,23,37,67,57,63,25,19,13,17,9,3,13,2,2,7,17,12, +1,17,110,86,92,94,94,100,92,90,76,76,82,70,34,40,26,84,78,74, +62,60,50,22,10,1,25,35,59,13,85,124,124,124,124,124,124,124,124,124, +124,114,108,88,48,6,122,118,58,124,124,120,108,116,104,92,104,90,90,58, +62,38,11,74,54,18,105,89,93,37,51,45,5,29,27,9,7,24,0,36, +15,124,124,124,124,104,98,42,6,43,21,82,58,40,18,18,4,1,9,53, +79,61,47,47,41,15,27,39,15,9,7,3,2,12,8,124,124,124,118,110, +98,74,44,11,0,0,0,0,124,18,21,124,18,21,115,71,24,20,22,52, +114,120,108,28,95,12,23,2,2,24,17,20,7,38,116,15,59,83,109,73, +7,23,2,2,41,55,8,34,9,31,59,14,9,43,49,10,23,57,18,11, +33,49,3,19,19,31,13,10,44,0,0,0,35,45,67,13,40,2,36,27, +63,113,57,65,2,25,53,33,83,47,69,53,115,53,49,61,83,36,1,14, +55,19,53,43,115,18,4,6,13,32,9,9,45,41,25,21,23,18,26,7, +26,40,33,0,11,7,12,23,52,1,4,52,70,74,64,50,55,15,17,30, +26,69,18,20,20,6,14,14,6,8,4,12,7,12,44,24,13,1,4,1, +24,42,38,22,26,8,10,8,52,38,36,27,6,13,66,46,38,28,34,38, +24,32,48,2,32,18,18,10,0,22,10,18,20,14,32,50,18,35,14,27, +30,56,39,104,124,110,108,114,116,104,104,96,78,64,58,74,48,19,7,8, +9,60,56,50,60,56,42,34,38,3,6,3,59,49,85,21,40,36,22,0, +10,11,21,33,69,23,78,42,30,16,12,11,33,41,99,10,70,56,50,40, +20,10,1,19,49,13,70,64,40,8,12,15,33,61,10,114,96,86,68,46, +10,11,27,39,124,79,79,43,93,85,63,83,77,71,79,79,87,61,57,53, +55,51,43,9,31,39,11,4,8,4,22,22,22,12,42,32,26,26,20,42, +30,16,40,36,24,20,24,0,3,9,10,15,36,62,36,20,54,48,24,42, +56,36,48,22,10,32,100,94,102,98,102,122,124,124,124,124,124,124,124,124, +62,124,124,124,124,124,124,98,68,66,12,31,21,59,109,116,116,124,104,98, +96,74,76,54,56,38,30,24,9,19,4,1,9,72,78,72,52,70,68,38, +54,58,34,6,12,3,49,42,20,4,29,11,9,9,1,5,11,5,7,1, +10,5,0,6,8,124,124,124,124,116,104,90,56,3,1,60,46,40,32,20, +10,4,1,21,41,31,23,31,25,11,19,35,11,3,6,1,0,8,8,124, +124,124,114,104,92,70,38,11,0,0,0,0,124,18,21,124,18,21,113,69, +24,20,22,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,44,0,0,0,33,47,67,13, +38,2,104,16,11,117,69,37,17,75,113,111,115,53,113,89,111,109,97,109, +97,6,7,33,73,11,55,47,111,19,63,51,117,16,33,21,111,55,41,25, +11,2,7,35,6,0,0,12,3,1,4,27,26,20,52,38,46,36,34,36, +78,24,24,74,52,3,81,65,67,47,55,43,33,39,35,39,51,13,17,17, +0,73,65,63,21,17,17,13,28,3,2,3,42,9,8,10,2,23,114,102, +72,84,102,82,48,84,66,50,60,34,10,2,2,44,32,42,38,32,28,38, +24,44,34,12,16,26,51,124,124,124,124,124,124,124,124,124,124,124,124,118, +106,72,124,108,70,124,118,124,114,102,98,106,78,64,24,40,3,15,67,13, +46,30,20,4,10,0,15,19,49,3,76,50,40,34,6,5,23,23,39,51, +24,12,6,1,13,21,29,43,83,61,31,25,15,19,37,57,61,97,25,64, +32,22,4,7,25,39,45,59,124,55,37,27,5,13,2,8,10,19,4,12, +0,29,15,9,34,6,48,40,64,62,38,44,54,40,30,1,26,5,75,61, +57,45,39,39,37,41,7,25,23,21,6,23,37,67,55,63,25,17,13,17, +9,3,11,2,0,7,15,12,3,19,108,86,92,92,92,98,90,88,74,74, +80,68,32,38,24,80,74,70,58,58,48,20,8,1,25,35,59,15,85,124, +124,124,124,124,124,124,124,124,120,110,104,84,46,4,118,114,56,124,124,116, +104,110,100,88,100,86,86,54,58,34,13,70,50,14,103,87,91,37,49,43, +1,27,25,9,5,26,2,38,15,124,124,124,124,98,92,36,2,45,21,82, +58,40,18,18,4,1,9,51,77,59,45,47,39,13,25,37,13,7,5,1, +4,14,8,124,124,124,114,106,94,70,40,13,0,0,0,0,124,18,21,124, +18,21,113,69,24,20,22,50,112,116,108,28,89,10,21,2,2,22,17,18, +9,36,112,19,61,85,103,71,7,21,2,2,41,53,8,32,9,31,59,14, +9,41,49,10,23,55,16,13,33,49,3,17,19,29,13,10,44,0,0,0, +33,47,67,13,38,2,36,27,63,111,55,61,4,23,51,31,81,43,67,51, +111,53,47,61,81,36,1,14,53,19,51,43,113,16,4,6,13,32,9,9, +45,41,25,21,23,18,24,7,26,40,33,0,11,7,12,23,52,3,4,52, +68,72,62,48,53,15,17,28,24,69,16,20,18,6,14,14,8,10,4,10, +7,10,42,22,15,1,4,3,24,40,36,20,26,10,10,8,50,36,34,27, +6,15,66,46,38,28,34,38,24,32,46,2,32,18,18,10,1,22,10,18, +20,14,32,48,16,35,14,27,28,54,39,100,124,106,104,110,112,100,100,92, +74,60,54,68,44,21,7,6,11,58,54,48,58,52,40,32,34,3,4,5, +59,49,83,21,40,36,22,0,10,11,21,33,67,21,78,42,30,16,12,11, +33,41,95,10,70,56,50,40,20,10,1,19,47,13,70,62,40,8,12,15, +33,61,10,112,94,84,66,46,10,11,27,39,124,77,77,41,89,83,61,81, +73,69,75,77,83,59,57,51,53,49,41,11,31,37,11,4,6,2,20,20, +20,10,40,32,26,26,18,40,30,16,38,34,24,18,22,1,3,9,10,15, +34,60,34,20,52,46,24,40,54,36,48,20,8,28,98,94,100,96,98,120, +124,124,124,124,124,124,124,124,58,124,124,124,124,124,124,94,66,62,12,29, +19,57,105,114,112,120,102,94,92,70,72,52,52,34,26,22,11,21,2,1, +11,68,76,68,50,66,64,36,50,54,32,4,10,5,49,40,20,2,29,11, +7,7,1,3,9,5,5,0,12,3,2,8,10,124,124,124,122,110,98,84, +50,9,1,60,46,40,34,20,10,6,1,21,39,31,21,31,23,9,19,33, +9,1,6,1,2,8,8,124,124,122,108,98,84,62,32,17,0,0,0,0, +124,18,21,124,18,21,109,65,24,20,20,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, +44,0,0,0,33,47,67,11,36,2,104,16,11,115,67,37,15,73,109,107, +111,51,109,87,107,107,95,107,95,8,7,31,71,11,53,45,107,19,63,49, +113,18,33,19,109,53,39,25,11,4,5,33,8,2,0,12,3,1,4,27, +26,18,50,38,44,36,34,36,74,24,22,72,50,5,79,63,65,45,53,41, +31,37,33,37,49,13,17,17,1,71,63,63,19,17,15,13,26,1,2,3, +40,7,8,8,2,23,112,100,72,82,100,80,46,84,66,48,58,34,10,2, +0,44,30,40,36,30,26,38,22,40,32,10,14,24,51,124,124,124,124,124, +124,124,124,124,124,124,124,114,102,68,120,104,66,124,114,120,110,98,94,100, +74,58,22,36,5,15,67,13,46,30,20,4,10,0,15,19,49,3,76,50, +40,34,8,3,21,23,37,49,26,14,6,0,11,19,27,43,81,59,27,23, +15,17,35,55,59,95,23,64,34,22,4,5,23,37,43,57,124,55,37,25, +5,13,2,8,10,19,4,14,0,29,15,9,32,8,46,38,62,62,38,42, +52,40,30,3,24,5,73,59,55,43,37,37,37,39,7,25,23,21,4,23, +37,65,53,63,25,17,13,15,9,3,9,2,0,7,13,10,3,19,106,86, +90,92,90,96,88,86,74,72,78,66,30,36,22,78,72,68,54,56,46,18, +6,3,25,33,59,15,83,124,124,124,124,124,124,124,124,120,116,106,100,80, +42,2,114,110,54,122,124,112,100,106,96,84,96,82,80,50,54,30,15,66, +46,12,101,83,89,35,47,41,2,25,23,9,3,30,6,42,13,124,124,124, +124,94,86,32,1,47,21,82,58,40,18,18,4,1,9,51,75,57,43,45, +37,11,25,35,11,5,3,1,4,14,8,124,124,124,112,102,90,66,36,15, +0,0,0,0,124,18,21,124,18,21,109,65,24,20,20,46,108,114,108,28, +85,10,19,4,2,22,15,16,11,36,108,23,63,85,97,67,7,19,4,2, +41,51,8,32,9,31,57,14,11,41,49,10,23,53,16,13,33,49,1,17, +17,29,11,10,44,0,0,0,33,47,67,11,36,2,36,25,63,107,51,59, +8,19,47,29,79,41,65,49,107,51,47,59,79,36,1,14,53,19,51,41, +109,16,4,6,13,32,9,7,43,41,25,21,21,18,24,7,26,40,31,0, +9,7,12,23,50,3,4,50,66,72,60,46,51,13,17,26,24,67,16,20, +18,6,14,14,10,10,4,10,7,10,40,22,17,1,4,3,22,38,36,20, +24,10,10,8,48,36,32,27,6,15,64,46,38,28,34,38,24,32,46,2, +32,18,18,10,1,22,10,16,20,14,30,46,16,35,12,27,26,52,39,98, +122,104,102,106,108,96,96,88,70,56,50,64,42,23,7,6,11,56,52,46, +56,50,36,30,32,5,4,5,59,49,83,21,40,36,22,0,10,9,19,31, +65,21,78,42,30,16,12,9,31,39,91,10,70,56,50,40,20,10,1,19, +45,13,72,62,38,8,12,15,33,59,10,112,92,82,64,46,10,11,27,37, +124,75,75,39,87,81,59,79,71,67,73,73,79,57,55,51,53,47,41,11, +29,35,11,2,6,2,20,18,18,8,38,30,26,24,18,40,30,16,36,32, +24,18,20,1,3,9,10,15,32,60,34,20,50,44,24,38,52,34,46,18, +6,24,96,92,100,94,96,116,124,124,124,124,124,124,124,124,56,124,124,124, +124,124,122,90,64,60,12,27,19,55,101,110,110,116,98,90,88,68,68,50, +48,32,22,18,13,23,2,1,13,66,72,64,46,64,62,32,48,52,28,2, +8,7,51,40,18,0,27,9,7,7,0,1,7,3,3,2,16,1,4,10, +14,124,124,124,116,106,92,78,44,13,1,62,48,42,34,22,10,6,0,19, +39,31,19,29,21,7,17,31,9,1,6,0,4,8,8,124,124,116,102,92, +78,54,24,23,0,0,0,0,124,18,23,124,18,23,105,63,26,20,20,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,44,0,0,0,31,47,67,11,36,0,104,16, +11,113,67,37,15,71,105,103,109,49,105,85,103,105,93,105,93,10,7,29, +71,9,53,45,103,19,61,49,111,18,33,19,105,53,37,23,11,4,5,31, +8,2,1,12,3,1,4,27,26,18,50,38,42,36,34,36,70,24,22,68, +48,7,79,61,65,45,51,41,29,37,33,37,45,13,17,17,3,71,61,63, +19,17,13,11,24,1,2,3,38,5,6,6,2,25,108,98,70,82,98,80, +46,82,64,46,56,34,10,2,0,42,28,38,34,30,24,36,22,36,30,10, +12,22,51,124,124,124,124,124,124,124,124,124,124,124,124,108,96,62,116,100, +64,124,108,114,104,94,88,96,68,54,20,32,7,17,67,11,48,30,22,4, +10,0,15,19,47,3,76,52,40,34,10,3,21,21,37,47,28,14,8,0, +9,19,27,41,79,57,25,21,13,17,35,55,57,91,23,64,34,22,6,5, +23,35,43,55,124,53,35,25,5,13,2,8,10,19,6,14,2,29,15,11, +32,8,44,36,60,60,38,40,50,40,30,3,22,7,71,57,53,43,37,37, +35,39,7,23,21,19,4,23,37,65,51,63,25,17,13,13,9,3,7,0, +0,7,13,8,3,21,104,84,90,90,88,96,88,84,72,72,76,64,28,34, +20,74,70,64,50,52,42,16,6,3,25,33,57,17,81,124,124,124,124,124, +124,124,124,116,110,102,94,76,40,2,112,108,50,118,124,108,96,102,92,80, +90,78,76,46,50,28,19,62,42,8,99,81,87,33,45,39,4,23,21,9, +1,32,8,44,11,124,124,124,118,88,82,26,5,51,19,82,58,40,18,18, +4,1,9,49,73,57,41,43,35,11,23,33,11,5,3,1,6,14,8,124, +124,122,108,100,88,60,34,17,0,0,0,0,124,18,23,124,18,23,105,63, +26,20,20,44,106,112,108,28,81,10,19,6,2,20,15,14,13,34,106,25, +65,87,91,65,7,19,6,2,39,49,10,30,7,29,55,12,11,41,49,10, +21,53,16,13,31,49,1,17,17,29,11,10,44,0,0,0,31,47,67,11, +36,0,36,25,61,103,47,55,10,15,45,27,75,39,63,49,105,51,47,59, +79,38,1,14,51,17,49,41,107,16,2,4,15,32,9,7,43,41,23,21, +21,18,24,5,26,38,31,0,9,7,12,23,48,3,4,48,64,70,60,46, +51,13,17,26,22,67,14,20,18,6,14,14,10,10,4,10,5,10,38,22, +17,3,4,5,22,36,36,20,22,10,10,8,44,36,30,27,6,17,62,46, +36,28,34,38,24,32,46,2,30,18,16,10,1,20,8,16,18,12,28,44, +14,35,12,25,24,48,39,94,118,100,98,102,104,92,92,84,66,54,48,60, +38,25,7,6,13,54,50,44,52,46,34,28,30,7,2,7,59,49,81,19, +40,36,22,2,10,9,19,31,63,19,76,42,30,16,14,9,29,37,87,10, +72,56,50,40,22,10,1,17,45,13,72,62,38,8,12,13,31,57,10,110, +92,80,64,46,10,9,25,37,124,75,73,39,85,79,57,75,69,65,71,71, +77,57,53,51,51,43,41,13,29,35,11,2,4,2,18,16,16,6,38,30, +26,24,16,38,28,16,36,32,22,18,20,1,5,9,10,17,32,58,32,18, +48,44,26,38,50,34,46,18,6,22,94,90,98,92,94,114,124,124,124,124, +124,124,124,122,54,124,124,124,124,124,118,86,62,58,12,25,19,51,95,106, +106,112,94,86,84,64,64,46,46,30,20,16,15,25,0,3,15,64,70,62, +42,60,58,30,44,48,26,1,4,11,53,38,16,1,27,9,7,5,0,1, +3,1,1,4,18,2,6,14,16,124,124,120,112,100,88,72,40,17,0,62, +48,42,34,24,12,6,0,19,39,29,19,29,19,5,17,31,7,0,6,0, +6,8,8,124,124,112,96,84,70,48,18,27,0,0,0,0,124,18,23,124, +18,23,101,59,26,20,18,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,44,0,0,0, +31,47,67,9,34,0,104,16,11,111,65,37,13,67,103,99,105,47,103,81, +99,103,91,103,93,12,7,27,69,9,51,43,99,19,61,47,109,18,31,17, +103,51,37,23,9,4,5,29,10,4,1,10,3,1,4,27,26,16,48,38, +42,36,34,34,66,24,20,64,46,9,77,59,63,43,49,39,27,35,31,35, +43,13,17,15,5,69,59,63,19,17,13,11,22,0,2,3,34,3,6,4, +2,27,106,96,70,80,96,78,44,80,64,44,54,34,10,2,1,40,28,36, +34,28,22,34,20,32,28,8,10,20,51,124,124,124,124,124,124,124,124,124, +124,120,122,104,92,58,112,98,60,124,104,110,100,88,84,90,64,48,18,30, +11,19,67,11,48,32,22,4,10,0,15,19,47,1,78,52,40,34,12,1, +19,21,35,45,30,16,8,0,7,17,25,41,77,57,23,21,13,17,33,53, +57,89,21,66,34,22,6,3,21,33,41,53,124,53,35,23,5,13,2,8, +10,17,6,14,2,29,15,11,30,10,42,34,58,58,38,38,48,38,30,5, +20,7,69,57,51,41,35,35,35,37,7,23,21,19,2,23,37,63,49,63, +25,15,13,13,9,3,5,0,0,7,11,8,5,23,102,84,88,88,86,94, +86,82,70,70,74,62,26,32,18,72,66,62,46,50,40,14,4,5,25,33, +57,17,79,124,124,124,124,124,124,124,122,112,106,98,90,72,36,0,108,104, +48,114,124,104,92,98,88,76,86,74,70,42,46,24,21,58,38,6,97,79, +85,33,43,37,8,21,19,9,0,36,12,48,11,124,124,122,112,82,76,20, +9,53,19,82,58,40,18,18,4,1,9,49,71,55,39,41,33,9,23,31, +9,3,1,0,6,16,8,124,124,118,104,96,84,56,30,19,0,0,0,0, +124,18,23,124,18,23,101,59,26,20,18,40,102,108,108,28,75,8,17,6, +2,18,15,12,15,34,102,29,67,87,85,63,7,17,6,2,39,47,10,30, +7,29,55,12,13,39,49,10,21,51,14,13,31,49,0,15,17,27,9,10, +44,0,0,0,31,47,67,9,34,0,36,25,61,101,43,53,14,11,43,25, +73,35,61,47,101,49,45,57,77,38,1,14,51,17,49,39,103,14,2,4, +15,32,9,7,41,41,23,21,19,18,22,5,26,38,31,0,9,7,12,23, +48,3,4,48,62,68,58,44,49,11,17,24,22,65,14,20,16,6,14,14, +12,12,4,10,5,10,36,22,19,3,4,5,20,34,34,20,22,12,10,8, +42,34,28,27,6,17,62,46,36,28,34,38,24,32,46,2,30,18,16,10, +1,20,8,14,18,12,28,42,14,35,10,25,22,46,39,92,114,96,94,98, +100,88,88,80,62,50,44,54,34,27,7,4,13,52,48,42,50,44,30,26, +28,7,2,7,59,49,81,19,40,36,22,2,10,9,19,29,61,19,76,42, +30,16,14,7,27,37,83,10,72,56,50,40,22,10,1,17,43,13,72,60, +36,8,12,13,31,57,10,110,90,78,62,46,10,9,25,35,124,73,71,37, +81,77,55,73,65,63,67,67,73,55,51,49,51,41,39,13,29,33,11,0, +4,0,16,14,14,4,36,28,26,22,16,38,28,16,34,30,22,16,18,1, +5,9,10,17,30,58,30,18,46,42,26,36,48,32,44,16,4,18,92,90, +98,90,90,110,124,124,124,124,124,124,124,118,50,124,124,124,124,124,112,82, +60,56,12,23,17,49,91,104,102,108,92,82,80,62,60,44,42,26,16,12, +17,27,0,3,17,60,66,58,40,56,54,26,42,44,22,3,2,13,53,36, +16,3,27,7,5,5,2,0,1,0,0,6,20,4,8,16,18,124,122,116, +106,96,82,66,34,21,0,64,50,44,36,26,12,8,2,17,37,29,17,27, +17,3,17,29,7,0,6,2,8,8,8,124,124,106,90,78,62,40,10,33, +0,0,0,0,124,16,23,124,16,23,99,57,26,20,18,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,44,0,0,0,29,49,67,9,32,0,104,16,11,109,63,37, +13,65,99,95,103,45,99,79,97,101,91,101,91,12,7,25,67,9,51,43, +97,19,61,47,107,18,31,17,101,51,35,23,9,4,5,29,10,4,3,10, +3,1,4,27,26,16,46,38,40,36,34,34,62,24,20,60,44,11,75,57, +61,41,49,39,25,35,31,33,41,13,17,15,9,69,57,63,19,19,11,11, +20,2,2,3,32,1,4,2,2,29,102,94,68,78,94,76,42,78,62,40, +52,32,10,2,1,38,26,34,32,26,20,32,18,28,24,6,8,18,51,124, +124,124,124,124,124,124,124,124,122,116,116,98,86,52,108,94,56,122,100,104, +94,84,78,84,60,44,16,26,13,21,69,11,48,32,22,4,10,0,15,19, +45,1,78,52,40,34,14,1,19,21,35,45,32,16,8,0,7,17,25,39, +75,55,21,19,13,17,31,51,55,87,21,66,34,22,6,1,21,33,39,53, +124,53,35,23,5,13,2,8,10,17,6,14,4,29,15,11,28,10,40,32, +56,56,38,34,44,38,30,7,18,9,69,55,49,41,35,35,33,35,9,23, +21,19,0,23,37,63,49,65,25,15,13,11,9,3,5,0,1,7,9,6, +5,25,100,82,88,86,82,92,84,80,68,68,72,60,24,30,16,68,64,58, +42,46,38,12,2,5,25,33,57,19,79,124,124,124,124,124,124,122,116,108, +102,94,84,68,34,1,104,100,44,110,122,98,86,92,82,72,82,68,66,38, +40,20,23,54,34,2,95,77,83,31,41,37,10,19,19,9,0,38,14,50, +9,124,124,116,106,76,70,14,13,55,19,82,58,40,18,18,4,1,9,47, +71,53,37,41,31,9,21,31,9,3,1,0,8,16,6,124,124,114,100,92, +80,52,26,21,0,0,0,0,124,16,23,124,16,23,99,57,26,20,18,38, +100,106,108,28,71,8,15,8,2,16,15,10,19,32,98,33,69,89,81,61, +7,15,8,2,39,45,10,28,7,29,53,10,13,39,51,10,21,51,14,15, +31,49,0,15,17,27,9,10,44,0,0,0,29,49,67,9,32,0,36,25, +61,97,41,49,16,9,41,23,71,33,59,45,97,49,45,57,75,38,1,14, +49,17,47,39,101,14,0,2,17,32,9,7,41,41,23,21,19,16,22,5, +26,36,31,0,9,7,10,23,46,5,4,46,58,66,56,42,49,11,17,22, +20,65,12,18,16,6,14,14,14,12,4,8,5,8,34,20,21,3,4,7, +20,32,34,18,20,12,10,8,38,34,26,27,6,19,60,44,36,28,34,36, +22,32,44,0,28,18,16,8,3,18,6,14,16,10,26,40,12,35,10,25, +20,42,39,88,110,92,90,94,94,84,84,76,58,46,40,50,30,29,7,4, +15,50,44,38,46,40,28,22,24,9,0,9,59,49,79,19,40,36,22,2, +10,9,19,29,59,17,76,42,30,16,14,7,27,35,81,10,72,56,50,38, +22,10,1,17,43,13,72,60,36,8,12,13,31,55,10,108,88,76,60,44, +10,9,25,35,124,71,69,37,79,75,55,71,63,61,65,65,71,55,51,49, +49,39,39,15,29,33,11,0,2,0,14,12,10,2,34,28,26,22,14,36, +26,14,32,28,20,16,16,3,7,9,10,19,28,56,28,18,44,40,26,34, +46,32,44,14,2,14,90,88,96,86,88,108,124,124,124,124,124,124,124,112, +48,124,124,124,124,122,108,78,56,52,12,23,17,47,87,100,98,104,88,76, +76,58,56,40,38,24,12,10,19,29,1,5,19,58,64,54,36,52,50,24, +38,40,20,5,1,17,55,34,14,5,27,7,5,3,2,0,0,0,2,8, +22,6,10,18,20,122,118,112,102,90,76,60,28,27,0,64,50,44,36,26, +12,8,2,17,37,29,17,27,15,1,17,29,5,2,6,2,8,8,6,124, +122,102,84,72,54,32,4,39,0,0,0,0,124,16,23,124,16,23,95,55, +28,20,18,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,44,0,0,0,27,49,67,9, +30,0,104,16,11,107,61,37,13,63,95,91,99,41,95,77,93,99,89,99, +89,14,5,23,65,9,49,41,93,19,59,47,103,20,31,17,97,51,33,23, +9,6,3,27,10,4,3,10,1,1,4,25,26,16,46,38,38,36,34,34, +58,24,20,58,42,11,73,55,59,39,47,37,23,33,31,31,39,13,17,15, +11,67,55,63,17,19,9,11,18,4,2,3,30,0,2,0,2,29,100,92, +68,76,92,74,42,78,62,38,50,32,10,2,1,38,24,32,30,24,18,32, +18,26,22,6,6,16,51,124,124,124,124,124,124,124,124,124,118,112,112,92, +82,46,106,90,54,118,96,100,90,80,74,80,56,40,16,22,15,21,69,11, +50,32,22,6,10,0,13,19,43,1,78,52,42,34,16,0,17,19,33,43, +34,18,10,2,5,15,25,37,73,53,17,17,11,15,29,49,53,85,19,66, +36,24,6,0,19,31,37,51,124,51,33,21,5,13,2,10,12,17,6,16, +6,29,15,11,28,10,38,32,54,56,38,32,42,38,30,7,16,11,67,53, +47,41,33,35,31,33,9,23,21,17,0,23,37,63,47,65,25,15,13,9, +9,3,3,0,1,7,7,4,5,25,98,82,88,86,80,90,82,78,68,66, +70,60,24,28,14,66,62,54,38,44,36,12,2,5,23,31,57,21,77,124, +124,124,124,124,124,118,112,104,98,90,80,64,32,3,100,98,42,106,118,94, +82,88,78,68,78,64,62,36,36,16,25,50,30,1,93,73,79,29,39,35, +14,17,17,9,2,42,16,54,7,124,124,112,100,72,64,10,17,57,19,82, +58,40,18,20,4,1,9,45,69,51,35,39,27,7,19,29,7,1,0,0, +10,16,6,124,122,112,98,88,76,48,22,21,0,0,0,0,124,16,23,124, +16,23,95,55,28,20,18,36,98,104,108,28,67,8,13,10,2,16,13,8, +21,30,94,35,71,91,75,57,7,13,10,2,37,43,12,26,7,27,51,10, +13,39,51,10,21,49,14,15,31,49,0,15,15,27,9,10,44,0,0,0, +27,49,67,9,30,0,36,23,61,93,37,45,18,5,37,21,67,31,55,43, +93,49,45,57,73,38,1,14,47,17,45,37,99,14,0,2,17,32,9,5, +39,39,21,21,19,16,22,5,26,36,29,0,7,7,10,21,44,5,4,44, +56,66,54,40,47,11,15,20,18,65,10,18,16,8,14,14,16,12,4,8, +3,8,34,20,23,3,4,9,20,30,34,18,18,12,10,8,36,34,26,27, +6,21,58,44,36,28,34,36,22,32,44,0,28,18,16,8,3,18,6,14, +16,10,24,40,12,35,10,25,18,40,39,84,108,90,88,90,90,82,82,72, +54,44,38,46,28,31,7,4,17,48,42,36,44,38,26,20,22,11,1,11, +59,47,77,17,42,36,22,2,12,7,17,27,57,15,76,42,30,16,16,7, +25,33,77,10,72,56,50,38,24,10,1,17,41,13,74,60,36,8,14,13, +31,53,10,108,88,76,58,44,10,9,23,33,124,69,67,35,77,71,53,67, +61,57,63,63,67,53,49,49,47,35,39,17,27,31,11,0,0,0,14,10, +8,0,34,28,26,22,14,34,26,14,30,28,20,16,14,3,7,7,12,19, +28,54,28,18,44,40,26,32,44,32,44,12,2,12,90,86,94,84,86,106, +120,120,124,124,124,124,124,108,46,124,124,124,124,116,104,76,54,50,12,21, +17,45,83,96,96,100,84,72,74,56,52,38,36,22,10,8,21,29,1,5, +21,56,62,52,32,50,48,22,36,38,18,7,3,19,57,34,12,5,25,7, +5,1,4,2,2,2,4,10,26,8,12,22,24,120,116,108,98,84,70,54, +22,31,2,64,50,46,36,28,14,8,4,15,37,27,15,27,13,2,15,27, +3,4,6,4,10,8,6,124,118,98,80,66,48,24,1,43,0,0,0,0, +124,16,23,124,16,23,91,51,28,20,16,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, +44,0,0,0,27,49,67,7,28,0,104,16,11,105,59,37,11,59,93,87, +97,39,93,73,89,97,87,97,89,16,5,21,63,9,49,39,89,19,59,45, +101,20,29,15,95,49,33,23,7,6,3,25,12,6,5,8,1,1,4,25, +26,14,44,38,38,36,34,32,54,24,18,54,40,13,71,53,57,37,45,35, +21,31,29,29,37,13,17,13,13,67,53,63,17,19,9,11,16,6,2,3, +26,2,2,1,2,31,96,90,66,74,90,72,40,76,62,36,48,32,10,2, +3,36,24,30,30,22,16,30,16,22,20,4,4,14,51,124,124,124,124,124, +124,124,124,124,114,108,106,88,78,42,102,88,50,112,92,96,86,74,70,74, +52,34,14,20,19,23,69,11,50,34,22,6,10,0,13,19,43,0,80,52, +42,34,18,0,15,19,31,41,36,20,10,2,3,15,23,37,71,53,15,17, +11,15,27,47,53,83,19,68,36,24,6,2,17,29,35,49,124,51,33,21, +5,13,2,10,12,15,6,16,6,29,15,11,26,12,36,30,52,54,38,30, +40,36,30,9,14,11,65,53,45,39,33,33,31,31,9,23,21,17,1,23, +37,61,45,65,25,13,13,9,9,3,1,0,1,7,5,4,7,27,96,82, +86,84,78,88,80,76,66,64,68,58,22,26,12,62,58,52,34,42,34,10, +0,7,23,31,57,21,75,124,124,124,124,124,120,114,106,100,94,86,76,60, +28,5,96,94,40,102,114,90,78,84,74,64,74,60,56,32,32,12,27,46, +26,3,91,71,77,29,37,33,18,15,15,9,4,44,20,56,7,124,120,106, +94,66,58,4,21,59,19,82,58,40,18,20,4,1,9,45,67,49,33,37, +25,5,19,27,5,0,2,2,10,18,6,120,118,108,94,84,72,44,18,23, +0,0,0,0,124,16,23,124,16,23,91,51,28,20,16,32,94,100,108,28, +61,6,11,10,2,14,13,6,23,30,90,39,73,91,69,55,7,11,10,2, +37,41,12,26,7,27,51,10,15,37,51,10,21,47,12,15,31,49,2,13, +15,25,7,10,44,0,0,0,27,49,67,7,28,0,36,23,61,91,33,43, +22,1,35,19,65,27,53,41,89,47,43,55,71,38,1,14,47,17,45,37, +95,12,0,2,17,32,9,5,39,39,21,21,17,16,20,5,26,36,29,0, +7,7,10,21,44,5,4,44,54,64,52,38,45,9,15,18,18,63,10,18, +14,8,14,14,18,14,4,8,3,8,32,20,25,3,4,9,18,28,32,18, +18,14,10,8,34,32,24,27,6,21,58,44,36,28,34,36,22,32,44,0, +28,18,16,8,3,18,6,12,16,10,24,38,10,35,8,25,16,38,39,82, +104,86,84,86,86,78,78,68,50,40,34,40,24,33,7,2,17,46,40,34, +42,34,22,18,20,11,1,11,59,47,77,17,42,36,22,2,12,7,17,27, +55,15,76,42,30,16,16,5,23,33,73,10,72,56,50,38,24,10,1,17, +39,13,74,58,34,8,14,13,31,53,10,106,86,74,56,44,10,9,23,33, +124,67,65,33,73,69,51,65,57,55,59,59,63,51,47,47,47,33,37,17, +27,29,11,1,0,1,12,8,6,1,32,26,26,20,12,34,26,14,28,26, +20,14,12,3,7,7,12,19,26,54,26,18,42,38,26,30,42,30,42,10, +0,8,88,86,94,82,82,102,116,116,124,124,124,124,124,104,42,118,124,118, +124,112,98,72,52,48,12,19,15,43,79,94,92,96,82,68,70,52,48,36, +32,18,6,4,23,31,3,5,23,52,58,48,30,46,44,18,32,34,14,9, +5,21,57,32,12,7,25,5,3,1,4,4,4,4,6,12,28,10,14,24, +26,120,112,104,92,80,64,48,16,35,2,66,52,46,38,30,14,10,4,15, +35,27,13,25,11,4,15,25,3,4,6,4,12,8,6,124,114,92,74,60, +40,16,9,49,0,0,0,0,124,16,25,124,16,25,87,49,30,20,16,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,44,0,0,0,25,49,67,7,28,1,104,16, +11,103,59,37,11,57,89,83,93,37,89,71,85,95,85,95,87,18,5,19, +63,7,47,39,85,19,57,45,99,20,29,15,91,49,31,21,7,6,3,23, +12,6,5,8,1,1,4,25,26,14,44,38,36,36,34,32,50,24,18,50, +38,15,71,51,57,37,43,35,19,31,29,29,33,13,17,13,15,65,51,63, +17,19,7,9,14,6,2,3,24,4,0,3,2,33,94,88,66,74,88,72, +40,74,60,34,46,32,10,2,3,34,22,28,28,22,14,28,16,18,18,4, +2,12,51,124,124,124,124,124,124,124,124,124,108,104,102,82,72,36,98,84, +48,108,86,90,80,70,64,70,46,30,12,16,21,25,69,9,52,34,24,6, +10,0,13,19,41,0,80,54,42,34,20,2,15,17,31,39,38,20,12,2, +1,13,23,35,69,51,13,15,9,15,27,47,51,79,17,68,36,24,8,2, +17,27,35,47,124,49,31,19,5,13,2,10,12,15,8,16,8,29,15,13, +26,12,34,28,50,52,38,28,38,36,30,9,12,13,63,51,43,39,31,33, +29,31,9,21,19,15,1,23,37,61,43,65,25,13,13,7,9,3,0,1, +1,7,5,2,7,29,94,80,86,82,76,88,80,74,64,64,66,56,20,24, +10,60,56,48,30,38,30,8,0,7,23,31,55,23,73,124,124,124,124,124, +116,110,102,96,88,82,70,56,26,5,94,92,36,98,108,86,74,80,70,60, +68,56,52,28,28,10,31,42,22,7,89,69,75,27,35,31,20,13,13,9, +6,48,22,60,5,122,118,102,88,60,54,1,25,63,17,82,58,40,18,20, +4,1,9,43,65,49,31,35,23,5,17,25,5,0,2,2,12,18,6,118, +116,104,90,82,70,38,16,25,0,0,0,0,124,16,25,124,16,25,87,49, +30,20,16,30,92,98,108,28,57,6,11,12,2,12,13,4,25,28,88,41, +75,93,63,53,7,11,12,2,35,39,14,24,5,25,49,8,15,37,51,10, +19,47,12,15,29,49,2,13,15,25,7,10,44,0,0,0,25,49,67,7, +28,1,36,23,59,87,29,39,24,2,33,17,61,25,51,41,87,47,43,55, +71,40,1,14,45,15,43,35,93,12,1,0,19,32,9,5,37,39,19,21, +17,16,20,3,26,34,29,0,7,7,10,21,42,5,4,42,52,62,52,38, +45,9,15,18,16,63,8,18,14,8,14,14,18,14,4,8,1,8,30,20, +25,5,4,11,18,26,32,18,16,14,10,8,30,32,22,27,6,23,56,44, +34,28,34,36,22,32,44,0,26,18,14,8,3,16,4,12,14,8,22,36, +10,35,8,23,14,34,39,78,100,82,80,82,82,74,74,64,46,38,32,36, +20,35,7,2,19,44,38,32,38,32,20,16,18,13,3,13,59,47,75,15, +42,36,22,4,12,7,17,25,53,13,74,42,30,16,18,5,21,31,69,10, +74,56,50,38,26,10,1,15,39,13,74,58,34,8,14,11,29,51,10,106, +86,72,56,44,10,7,21,31,124,67,63,33,71,67,49,61,55,53,57,57, +61,51,45,47,45,29,37,19,27,29,11,1,1,1,10,6,4,3,32,26, +26,20,12,32,24,14,28,26,18,14,12,3,9,7,12,21,26,52,24,16, +40,38,28,30,40,30,42,10,0,6,86,84,92,80,80,100,112,112,122,120, +124,124,120,98,40,114,124,112,124,106,94,68,50,46,12,17,15,39,73,90, +88,92,78,64,66,50,44,32,30,16,4,2,25,33,3,7,25,50,56,46, +26,42,40,16,30,30,12,13,9,25,59,30,10,9,25,5,3,0,6,4, +8,6,8,14,30,14,16,28,28,118,110,100,88,74,60,42,12,39,4,66, +52,48,38,32,16,10,6,13,35,25,13,25,9,6,15,25,1,6,6,6, +14,8,6,124,110,88,68,52,32,10,15,53,0,0,0,0,124,16,25,124, +16,25,85,45,30,20,14,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,44,0,0,0, +25,51,67,5,26,1,104,16,11,101,57,37,9,55,85,79,91,35,85,69, +81,93,85,93,85,18,5,17,61,7,47,37,81,19,57,43,97,20,29,13, +89,47,29,21,7,6,3,23,14,8,7,8,1,1,4,25,26,12,42,38, +34,36,34,32,46,24,16,46,36,17,69,49,55,35,43,33,17,29,27,27, +31,13,17,13,17,65,49,63,17,19,5,9,12,8,2,3,22,6,0,5, +2,35,90,86,64,72,86,70,38,72,60,30,44,30,10,2,5,32,20,26, +26,20,12,26,14,14,16,2,0,10,51,124,124,122,124,124,124,124,124,122, +104,100,96,78,68,32,94,80,44,104,82,86,76,66,60,64,42,24,10,12, +23,27,69,9,52,34,24,6,10,0,13,19,41,0,80,54,42,34,22,2, +13,17,29,39,40,22,12,2,1,13,21,35,67,49,11,13,9,15,25,45, +49,77,17,68,36,24,8,4,15,27,33,45,124,49,31,19,5,13,2,10, +12,15,8,16,8,29,15,13,24,14,32,26,48,50,38,24,36,36,30,11, +10,13,63,49,41,37,31,31,29,29,11,21,19,15,3,23,37,59,41,65, +25,13,13,5,9,3,2,1,3,7,3,0,7,31,92,80,84,80,74,86, +78,72,62,62,64,54,18,22,8,56,54,46,26,36,28,6,1,9,23,31, +55,23,73,124,124,124,124,124,112,106,96,92,84,78,66,52,22,7,90,88, +34,94,104,82,70,74,66,56,64,52,46,24,24,6,33,38,18,9,87,67, +73,25,33,29,24,11,11,9,8,50,26,62,3,118,114,96,82,54,48,7, +29,65,17,82,58,40,18,20,4,1,9,43,63,47,29,35,21,3,17,23, +3,2,4,2,12,18,6,116,112,100,86,78,66,34,12,27,0,0,0,0, +124,16,25,124,16,25,85,45,30,20,14,26,88,96,108,28,53,6,9,14, +2,10,13,2,27,28,84,45,77,93,57,51,7,9,14,2,35,37,14,24, +5,25,47,8,17,37,51,10,19,45,12,17,29,49,4,13,15,25,5,10, +44,0,0,0,25,51,67,5,26,1,36,23,59,83,27,37,28,4,31,15, +59,23,49,39,83,45,43,53,69,40,1,14,45,15,43,35,89,12,1,0, +19,32,9,5,37,39,19,21,15,16,20,3,26,34,29,0,7,7,10,21, +40,7,4,40,50,60,50,36,43,7,15,16,16,61,8,18,14,8,14,14, +20,14,4,6,1,6,28,18,27,5,4,11,16,24,32,16,14,14,10,8, +28,32,20,27,6,23,54,44,34,28,34,36,22,32,42,0,26,18,14,8, +5,16,4,10,14,8,20,34,8,35,6,23,12,32,39,76,96,78,76,78, +78,70,70,60,42,34,28,32,16,37,7,2,19,42,36,30,36,28,16,14, +14,15,3,13,59,47,75,15,42,36,22,4,12,7,17,25,51,13,74,42, +30,16,18,3,21,29,65,10,74,56,50,38,26,10,1,15,37,13,74,58, +32,8,14,11,29,49,10,104,84,70,54,44,10,7,21,31,124,65,61,31, +69,65,47,59,53,51,55,53,57,49,45,47,45,27,37,19,27,27,11,3, +1,1,8,4,2,5,30,24,26,18,10,32,24,14,26,24,18,14,10,5, +9,7,12,21,24,52,22,16,38,36,28,28,38,28,40,8,1,2,84,82, +92,78,78,96,108,108,118,114,124,124,114,94,38,108,124,106,116,100,88,64, +48,42,12,15,15,37,69,86,84,88,74,60,62,46,40,30,26,14,0,1, +27,35,5,7,27,48,52,42,22,38,36,12,26,26,8,15,11,27,61,28, +8,11,25,3,3,0,6,6,10,6,10,16,32,16,18,30,30,118,106,96, +82,70,54,36,6,45,4,68,54,48,38,32,16,10,6,13,35,25,11,23, +7,8,15,23,1,6,6,6,16,8,6,122,106,82,62,46,24,2,23,59, +0,0,0,0,124,16,25,124,16,25,81,43,30,20,14,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,44,0,0,0,23,51,67,5,24,1,104,16,11,99,55,37, +9,51,83,75,87,33,83,65,77,91,83,91,85,20,5,15,59,7,45,35, +77,19,57,43,93,22,27,13,87,47,29,21,5,8,1,21,14,8,7,6, +1,1,4,25,26,12,40,38,34,36,34,30,42,24,16,44,34,19,67,47, +53,33,41,31,15,27,27,25,29,13,17,11,19,63,47,63,15,19,5,9, +10,10,2,3,18,8,1,7,2,35,88,84,64,70,84,68,36,72,60,28, +42,30,10,2,5,32,20,24,26,18,10,26,12,10,14,0,1,8,51,122, +124,118,124,122,120,120,120,118,100,96,92,72,64,26,90,78,40,98,78,82, +72,60,56,58,38,20,8,10,27,27,69,9,52,36,24,6,10,0,13,19, +39,2,82,54,42,34,24,4,11,17,27,37,42,24,12,4,0,11,21,33, +65,49,7,13,9,13,23,43,49,75,15,70,38,24,8,6,13,25,31,43, +124,49,31,17,5,13,2,10,12,13,8,18,10,29,15,13,22,14,30,24, +46,50,38,22,34,34,30,13,8,15,61,49,39,37,29,31,27,27,11,21, +19,15,5,23,37,59,39,65,25,11,13,5,9,3,4,1,3,7,1,0, +9,31,90,80,84,80,72,84,76,70,62,60,62,52,16,20,6,54,50,42, +22,34,26,4,3,9,23,29,55,25,71,124,124,124,124,120,108,102,92,88, +80,74,62,48,20,9,86,84,32,90,100,78,66,70,62,52,60,48,42,20, +20,2,35,34,14,13,85,63,71,25,31,27,28,9,9,9,10,54,28,66, +3,116,110,92,76,50,42,11,33,67,17,82,58,40,18,20,4,1,9,41, +61,45,27,33,19,1,15,21,1,4,6,4,14,20,6,112,110,98,84,74, +62,30,8,29,0,0,0,0,124,16,25,124,16,25,81,43,30,20,14,24, +86,92,108,28,47,4,7,14,2,10,11,0,29,26,80,49,79,95,51,47, +7,7,14,2,35,35,14,22,5,25,47,8,17,35,51,10,19,43,10,17, +29,49,4,11,13,23,5,10,44,0,0,0,23,51,67,5,24,1,36,21, +59,81,23,33,30,8,27,13,57,19,47,37,79,45,41,53,67,40,1,14, +43,15,41,33,87,10,1,0,19,32,9,3,35,39,19,21,15,16,18,3, +26,34,27,0,5,7,10,21,40,7,4,40,48,60,48,34,41,7,15,14, +14,61,6,18,12,8,14,14,22,16,4,6,1,6,26,18,29,5,4,13, +16,22,30,16,14,16,10,8,26,30,18,27,6,25,54,44,34,28,34,36, +22,32,42,0,26,18,14,8,5,16,4,10,14,8,20,32,8,35,6,23, +10,30,39,72,92,76,74,74,74,66,66,56,38,30,24,26,14,39,7,0, +21,40,34,28,34,26,14,12,12,15,5,15,59,47,73,15,42,36,22,4, +12,5,15,23,49,11,74,42,30,16,18,3,19,29,61,10,74,56,50,38, +26,10,1,15,35,13,76,56,32,8,14,11,29,49,10,104,82,68,52,44, +10,7,21,29,124,63,59,29,65,63,45,57,49,49,51,51,53,47,43,45, +43,25,35,21,25,25,11,3,3,3,8,2,0,7,28,24,26,18,10,30, +24,14,24,22,18,12,8,5,9,7,12,21,22,50,22,16,36,34,28,26, +36,28,40,6,3,1,82,82,90,76,74,94,104,104,114,110,124,122,108,90, +34,102,124,100,108,96,84,60,46,40,12,13,13,35,65,84,82,84,72,56, +58,44,36,28,22,10,3,3,29,37,5,7,29,44,50,38,20,36,34,10, +24,24,6,17,13,29,61,28,8,13,23,3,1,2,8,8,12,8,12,18, +36,18,20,32,34,116,102,92,78,64,48,30,0,49,4,68,54,50,40,34, +16,12,8,11,33,25,9,23,5,10,13,21,0,8,6,8,18,8,6,118, +102,78,56,40,18,5,29,65,0,0,0,0,122,16,25,122,16,25,77,39, +32,20,12,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,44,0,0,0,23,51,67,3, +22,1,104,16,11,97,53,37,7,49,79,71,85,31,79,63,73,89,81,89, +83,22,5,13,57,7,45,35,73,19,55,41,91,22,27,11,83,45,27,21, +5,8,1,19,16,10,9,6,1,1,4,25,26,10,40,38,32,36,34,30, +38,24,14,40,32,21,65,45,51,31,39,31,13,27,25,23,27,13,17,11, +21,63,45,63,15,19,3,9,8,12,2,3,16,10,1,9,2,37,84,82, +62,68,82,66,36,70,58,26,40,30,10,2,7,30,18,22,24,16,8,24, +12,6,12,0,3,6,51,120,122,116,124,118,116,116,116,112,94,92,86,68, +58,22,86,74,38,94,74,76,66,56,50,54,34,14,6,6,29,29,69,9, +54,36,24,6,10,0,13,19,39,2,82,54,42,34,26,4,11,15,27,35, +44,24,14,4,2,11,19,33,63,47,5,11,7,13,21,41,47,73,15,70, +38,24,8,8,13,23,29,41,124,47,29,17,5,13,2,10,12,13,8,18, +10,29,15,13,22,16,28,22,44,48,38,20,32,34,30,13,6,15,59,47, +37,35,29,29,27,25,11,21,19,13,5,23,37,57,37,65,25,11,13,3, +9,3,6,1,3,7,0,1,9,33,88,78,82,78,70,82,74,68,60,58, +60,50,14,18,4,50,48,40,18,30,24,2,3,11,23,29,55,25,69,124, +124,122,122,114,104,98,86,84,76,70,56,44,16,11,82,82,28,86,96,74, +62,66,58,48,56,44,36,16,16,1,37,30,10,15,83,61,69,23,29,25, +30,7,7,9,12,56,32,68,1,112,108,86,70,44,36,17,37,69,17,82, +58,40,18,20,4,1,9,41,59,43,25,31,17,1,15,19,1,4,6,4, +14,20,6,110,106,94,80,70,58,26,4,31,0,0,0,0,122,16,25,122, +16,25,77,39,32,20,12,20,82,90,108,28,43,4,5,16,2,8,11,1, +31,26,76,51,81,95,45,45,7,5,16,2,33,33,16,22,5,23,45,6, +19,35,51,10,19,43,10,17,29,49,6,11,13,23,3,10,44,0,0,0, +23,51,67,3,22,1,36,21,59,77,19,31,34,12,25,11,53,17,45,35, +75,43,41,51,65,40,1,14,43,15,41,33,83,10,3,1,21,32,9,3, +35,39,17,21,13,16,18,3,26,32,27,0,5,7,10,21,38,7,4,38, +46,58,46,32,41,5,15,12,14,59,6,18,12,8,14,14,24,16,4,6, +0,6,24,18,31,5,4,13,14,20,30,16,12,16,10,8,22,30,16,27, +6,25,52,44,34,28,34,36,22,32,42,0,24,18,14,8,5,14,2,8, +12,6,18,30,6,35,4,23,8,26,39,70,88,72,70,70,70,62,62,52, +34,28,22,22,10,41,7,0,21,38,32,26,30,22,10,10,10,17,5,15, +59,47,73,13,42,36,22,4,12,5,15,23,47,11,74,42,30,16,20,1, +17,27,57,10,74,56,50,38,28,10,1,15,35,13,76,56,30,8,14,11, +29,47,10,102,82,66,50,44,10,7,19,29,124,61,57,29,63,61,43,53, +47,47,49,47,51,47,41,45,43,21,35,21,25,25,11,5,3,3,6,0, +1,9,28,22,26,16,8,30,22,14,22,22,16,12,6,5,11,7,12,23, +22,50,20,16,34,34,28,24,34,26,38,4,3,3,80,80,90,74,72,90, +100,100,110,104,120,118,102,84,32,96,124,94,100,90,78,56,44,38,12,11, +13,33,61,80,78,80,68,52,54,40,32,24,20,8,5,7,31,39,7,9, +31,42,46,36,16,32,30,6,20,20,2,19,17,33,63,26,6,15,23,1, +1,2,8,8,14,10,14,20,38,20,22,36,36,116,100,88,72,60,42,24, +5,53,6,70,56,50,40,36,18,12,8,11,33,23,9,21,3,12,13,21, +0,8,6,8,20,8,6,116,98,72,50,34,10,13,37,69,0,0,0,0, +120,16,25,120,16,25,73,37,32,20,12,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, +44,0,0,0,21,51,67,3,20,1,104,16,11,95,51,37,7,47,75,67, +81,29,75,61,69,87,79,87,81,24,5,11,55,7,43,33,69,19,55,41, +89,22,27,11,81,45,25,21,5,8,1,17,16,10,9,6,1,1,4,25, +26,10,38,38,30,36,34,30,34,24,14,36,30,23,63,43,49,29,37,29, +11,25,25,21,25,13,17,11,23,61,43,63,15,19,1,9,6,14,2,3, +14,12,3,11,2,39,82,80,62,66,80,64,34,68,58,24,38,30,10,2, +7,28,16,20,22,14,6,22,10,2,10,1,5,4,51,116,120,112,120,114, +112,112,112,108,90,88,82,62,54,16,82,70,34,90,70,72,62,52,46,48, +30,10,4,2,31,31,69,9,54,36,24,6,10,0,13,19,37,2,82,54, +42,34,28,6,9,15,25,33,46,26,14,4,4,9,19,31,61,45,3,9, +7,13,19,39,45,71,13,70,38,24,8,10,11,21,27,39,124,47,29,15, +5,13,2,10,12,13,8,18,12,29,15,13,20,16,26,20,42,46,38,18, +30,34,30,15,4,17,57,45,35,35,27,29,25,23,11,21,19,13,7,23, +37,57,35,65,25,11,13,1,9,3,8,1,3,7,2,3,9,35,86,78, +82,76,68,80,72,66,58,56,58,48,12,16,2,48,46,36,14,28,22,0, +5,11,23,29,55,27,67,124,124,118,118,108,100,94,82,80,72,66,52,40, +14,13,78,78,26,82,92,70,58,62,54,44,52,40,32,12,12,5,39,26, +6,19,81,59,67,21,27,23,34,5,5,9,14,60,34,72,0,110,104,82, +64,38,30,23,41,71,17,82,58,40,18,20,4,1,9,39,57,41,23,29, +15,0,13,17,0,6,8,4,16,20,6,108,104,90,76,66,54,22,0,33, +0,0,0,0,120,16,25,120,16,25,73,37,32,20,12,18,80,88,108,28, +39,4,3,18,2,6,11,3,33,24,72,55,83,97,39,43,7,3,18,2, +33,31,16,20,5,23,43,6,19,35,51,10,19,41,10,17,29,49,6,11, +13,23,3,10,44,0,0,0,21,51,67,3,20,1,36,21,59,73,15,27, +36,16,23,9,51,15,43,33,71,43,41,51,63,40,1,14,41,15,39,31, +81,10,3,1,21,32,9,3,33,39,17,21,13,16,18,3,26,32,27,0, +5,7,10,21,36,7,4,36,44,56,44,30,39,5,15,10,12,59,4,18, +12,8,14,14,26,16,4,6,0,6,22,18,33,5,4,15,14,18,30,16, +10,16,10,8,20,30,14,27,6,27,50,44,34,28,34,36,22,32,42,0, +24,18,14,8,5,14,2,8,12,6,16,28,6,35,4,23,6,24,39,66, +84,68,66,66,66,58,58,48,30,24,18,18,6,43,7,0,23,36,30,24, +28,20,8,8,8,19,7,17,59,47,71,13,42,36,22,4,12,5,15,21, +45,9,74,42,30,16,20,1,15,25,53,10,74,56,50,38,28,10,1,15, +33,13,76,56,30,8,14,11,29,45,10,102,80,64,48,44,10,7,19,27, +124,59,55,27,61,59,41,51,45,45,47,45,47,45,39,45,41,19,35,23, +25,23,11,5,5,3,4,1,3,11,26,22,26,16,8,28,22,14,20,20, +16,12,4,5,11,7,12,23,20,48,18,16,32,32,28,22,32,26,38,2, +5,7,78,78,88,72,70,88,96,96,106,100,114,112,96,80,30,90,118,88, +92,84,74,52,42,36,12,9,13,31,57,76,74,76,64,48,50,38,28,22, +16,6,9,9,33,41,7,9,33,40,44,32,12,28,26,4,18,16,0,21, +19,35,65,24,4,17,23,1,1,4,10,10,16,12,16,22,40,22,24,38, +38,114,96,84,68,54,36,18,11,57,6,70,56,52,40,38,18,12,10,9, +33,23,7,21,1,14,13,19,2,10,6,10,22,8,6,114,94,68,44,28, +2,21,43,75,0,0,0,0,116,14,27,116,14,27,71,35,32,20,10,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,44,0,0,0,21,53,67,3,18,3,104,14, +11,93,51,37,7,45,73,65,79,27,73,59,67,85,79,85,81,24,5,11, +55,7,43,33,67,19,55,41,87,22,27,11,79,45,25,21,5,8,1,17, +16,10,11,4,1,3,4,25,24,8,36,38,28,34,34,28,30,22,12,32, +28,25,63,43,49,29,37,29,9,25,25,21,23,15,17,11,27,61,43,63, +15,21,1,9,4,14,2,3,10,12,5,13,2,41,78,78,60,64,78,62, +32,66,56,20,36,28,8,2,9,26,14,18,20,12,4,20,8,1,6,3, +9,0,51,112,116,108,116,110,106,106,106,102,84,82,76,56,48,10,78,66, +30,84,64,66,56,46,40,42,24,4,2,1,35,33,71,9,54,36,24,6, +10,1,13,19,37,2,82,54,42,34,30,6,9,15,25,33,46,26,14,4, +4,9,19,31,59,45,1,9,7,13,19,39,45,69,13,70,38,24,8,10, +11,21,27,39,124,47,29,15,5,13,2,10,12,13,8,18,12,29,15,15, +18,16,24,18,40,44,36,14,26,32,28,17,0,19,57,45,33,35,27,29, +25,23,13,21,19,13,9,23,37,57,35,67,25,11,13,1,11,3,8,3, +5,7,2,5,11,37,84,76,80,74,64,78,70,64,56,54,56,46,10,12, +1,44,42,32,10,24,18,1,7,13,23,29,55,29,67,124,122,114,112,102, +94,88,76,74,66,60,46,34,10,15,74,74,22,78,86,64,52,56,48,40, +46,34,26,8,6,9,43,22,2,23,79,57,65,21,27,23,36,5,5,9, +14,62,36,74,0,106,100,76,56,32,24,29,47,75,17,82,56,38,18,20, +4,3,9,39,57,41,23,29,13,0,13,17,0,6,8,4,16,20,4,104, +100,86,72,62,50,16,3,35,0,0,0,0,116,14,27,116,14,27,71,35, +32,20,10,14,76,84,106,28,35,2,3,18,0,4,11,7,37,22,68,59, +85,99,35,41,9,3,18,0,33,29,16,18,5,23,43,4,21,35,53,10, +19,41,8,19,29,49,6,11,13,23,3,8,44,0,0,0,21,53,67,3, +18,3,36,21,59,71,13,25,38,18,21,7,49,13,41,33,69,43,41,51, +63,40,1,14,41,15,39,31,79,8,5,3,23,32,9,3,33,39,17,21, +13,14,16,3,24,30,27,1,5,7,8,21,34,9,2,34,40,54,42,28, +39,5,15,8,10,59,2,16,10,8,14,14,26,16,4,4,0,4,20,16, +35,7,2,17,12,16,28,14,8,16,10,8,16,28,12,27,6,29,48,42, +32,28,34,34,20,32,40,1,22,18,12,6,7,12,0,6,10,4,14,26, +4,35,2,23,4,20,39,62,80,64,62,62,60,54,54,44,26,20,14,12, +2,47,9,1,25,34,26,20,24,16,4,4,4,21,9,19,59,47,71,13, +42,36,22,4,12,5,15,21,43,9,72,42,30,16,20,1,15,25,51,8, +74,56,48,36,28,10,1,15,33,13,76,54,28,6,14,11,29,45,10,100, +78,62,46,42,10,7,19,27,124,59,53,27,59,57,41,49,43,43,45,43, +45,45,39,45,41,17,35,25,25,23,11,7,7,5,2,3,7,15,24,20, +26,14,6,26,20,12,18,18,14,10,2,7,13,7,12,25,18,46,16,14, +30,30,28,20,28,24,36,0,7,11,76,76,86,68,66,84,92,92,100,94, +108,106,90,74,26,84,110,82,82,78,68,48,38,32,12,9,13,29,53,72, +70,72,60,42,46,34,22,18,12,2,13,13,35,43,9,11,37,36,40,28, +8,24,22,0,14,12,3,25,23,39,67,22,2,19,23,1,1,4,10,10, +18,12,18,22,42,24,26,40,40,112,92,78,62,48,30,10,17,63,6,70, +56,52,40,38,18,12,10,9,33,23,7,21,0,16,13,19,2,10,6,10, +22,8,4,110,88,62,38,20,5,29,51,81,0,0,0,0,114,14,27,114, +14,27,67,31,34,22,10,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,44,0,0,0, +19,53,67,1,18,3,104,14,11,89,49,37,5,41,69,61,75,23,69,55, +63,81,77,83,79,26,3,9,53,5,41,31,63,17,53,39,83,24,25,9, +75,43,23,19,3,10,0,15,18,12,11,4,0,3,4,23,24,8,36,38, +28,34,34,28,28,22,12,30,26,25,61,41,47,27,35,27,7,23,23,19, +19,15,17,9,29,59,41,63,13,21,0,7,4,16,2,3,8,14,5,15, +2,41,76,78,60,64,78,62,32,66,56,18,36,28,8,2,9,26,14,18, +20,12,2,20,8,3,4,3,11,1,51,110,114,106,114,108,102,102,102,98, +80,78,72,52,44,6,76,64,28,80,60,62,52,42,36,38,20,0,2,3, +37,33,71,7,56,38,26,8,10,1,11,17,35,4,84,56,44,34,32,8, +7,13,23,31,48,28,16,6,6,7,17,29,55,43,2,7,5,11,17,37, +43,65,11,72,40,26,10,12,9,19,25,37,124,45,27,13,5,11,2,12, +14,11,10,20,14,27,15,15,18,18,24,18,38,44,36,12,24,32,28,17, +1,19,55,43,31,33,25,27,23,21,13,19,17,11,9,21,35,55,33,67, +25,9,13,0,11,3,10,3,5,5,4,5,11,37,84,76,80,74,62,78, +70,64,56,54,56,46,10,10,3,42,40,30,8,22,16,1,7,13,21,27, +53,29,65,120,118,110,108,98,90,84,72,70,62,56,42,30,8,15,72,72, +20,76,82,60,48,52,44,36,42,30,22,6,2,11,45,20,0,25,75,53, +61,19,25,21,40,3,3,9,16,66,40,78,2,104,98,72,50,28,20,33, +51,77,15,84,56,38,18,22,4,3,9,37,55,39,21,27,9,2,11,15, +2,8,10,6,18,22,4,102,98,84,70,60,48,12,5,35,0,0,0,0, +114,14,27,114,14,27,67,31,34,22,10,12,74,82,106,28,29,2,1,20, +0,4,9,9,39,22,66,61,87,99,29,37,9,1,20,0,31,25,18,18, +3,21,41,4,21,33,53,10,17,39,8,19,27,49,8,9,11,21,1,8, +44,0,0,0,19,53,67,1,18,3,36,19,57,67,9,21,42,22,17,5, +45,9,37,31,65,41,39,49,61,42,0,16,39,13,37,29,75,8,5,3, +23,34,9,1,31,37,15,19,11,14,16,1,24,30,25,1,3,7,8,19, +34,9,2,34,38,54,42,28,37,3,13,8,10,57,2,16,10,10,14,14, +28,18,6,4,2,4,20,16,35,7,2,17,12,14,28,14,8,18,12,8, +14,28,12,25,6,29,48,42,32,28,34,34,20,32,40,1,22,18,12,6, +7,12,0,6,10,4,14,26,4,33,2,21,4,18,37,60,78,62,60,58, +56,52,52,40,24,18,12,8,0,49,9,1,25,32,24,18,22,14,2,2, +2,21,9,19,57,45,69,11,44,36,22,6,14,3,13,19,39,7,72,42, +30,16,22,0,13,23,47,8,76,58,48,36,30,10,1,13,31,13,78,54, +28,6,16,9,27,43,10,100,78,62,46,42,10,5,17,25,124,57,51,25, +55,53,39,45,39,39,41,39,41,43,37,43,39,13,33,25,23,21,9,7, +7,5,2,3,9,17,24,20,28,14,6,26,20,12,18,18,14,10,2,7, +13,5,14,25,18,46,16,14,30,30,30,20,26,24,36,0,7,13,76,76, +86,66,64,82,88,88,96,90,104,102,86,70,24,80,104,76,74,74,64,46, +36,30,12,7,11,25,47,70,68,70,58,38,44,32,18,16,10,0,15,15, +37,43,9,11,39,34,38,26,6,22,20,1,12,10,5,27,25,41,67,22, +2,19,21,0,0,6,12,12,22,14,20,24,46,28,28,44,44,112,90,74, +58,44,26,4,21,67,8,72,58,54,42,40,20,14,12,7,31,21,5,19, +4,20,11,17,4,12,8,12,24,8,4,108,84,58,34,14,11,35,57,85, +0,0,0,0,112,14,27,112,14,27,63,29,34,22,10,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,44,0,0,0,17,53,67,1,16,3,104,14,11,87,47,37, +5,39,65,57,73,21,65,53,59,79,75,81,77,28,3,7,51,5,41,29, +59,17,53,39,81,24,25,9,73,43,21,19,3,10,0,13,18,12,13,4, +0,3,4,23,24,8,34,38,26,34,34,28,24,22,12,26,24,27,59,39, +45,25,33,25,5,21,23,17,17,15,17,9,31,59,39,63,13,21,2,7, +2,18,2,3,6,16,7,17,2,43,72,76,58,62,76,60,30,64,56,16, +34,28,8,2,9,24,12,16,18,10,0,18,6,7,2,5,13,3,51,106, +112,102,110,104,98,98,98,92,76,74,66,46,40,0,72,60,24,76,56,58, +48,38,32,32,16,3,0,7,39,35,71,7,56,38,26,8,10,1,11,17, +33,4,84,56,44,34,34,8,5,13,21,29,50,30,16,6,8,7,17,27, +53,41,4,5,5,11,15,35,41,63,11,72,40,26,10,14,7,17,23,35, +124,45,27,13,5,11,2,12,14,11,10,20,16,27,15,15,16,18,22,16, +36,42,36,10,22,32,28,19,3,21,53,41,29,33,25,27,21,19,13,19, +17,11,11,21,35,55,31,67,25,9,13,2,11,3,12,3,5,5,6,7, +11,39,82,76,80,72,60,76,68,62,54,52,54,44,8,8,5,38,38,26, +4,20,14,3,9,13,21,27,53,31,63,116,114,106,104,92,86,80,66,66, +58,52,38,26,6,17,68,68,18,72,78,56,44,48,40,32,38,26,18,2, +1,15,47,16,3,29,73,51,59,17,23,19,44,1,1,9,18,68,42,80, +4,102,94,66,44,22,14,39,55,79,15,84,56,38,18,22,4,3,9,35, +53,37,19,25,7,4,9,13,4,10,12,6,20,22,4,100,94,80,66,56, +44,8,9,37,0,0,0,0,112,14,27,112,14,27,63,29,34,22,10,10, +72,80,106,28,25,2,0,22,0,2,9,11,41,20,62,65,89,101,23,35, +9,0,22,0,31,23,18,16,3,21,39,4,21,33,53,10,17,37,8,19, +27,49,8,9,11,21,1,8,44,0,0,0,17,53,67,1,16,3,36,19, +57,63,5,17,44,26,15,3,43,7,35,29,61,41,39,49,59,42,0,16, +37,13,35,29,73,8,5,3,23,34,9,1,31,37,15,19,11,14,16,1, +24,30,25,1,3,7,8,19,32,9,2,32,36,52,40,26,35,3,13,6, +8,57,0,16,10,10,14,14,30,18,6,4,2,4,18,16,37,7,2,19, +12,12,28,14,6,18,12,8,12,28,10,25,6,31,46,42,32,28,34,34, +20,32,40,1,22,18,12,6,7,12,0,6,10,4,12,24,2,33,2,21, +2,16,37,56,74,58,56,54,52,48,48,36,20,14,8,4,3,51,9,1, +27,30,22,16,20,10,0,0,0,23,11,21,57,45,67,11,44,36,22,6, +14,3,13,19,37,5,72,42,30,16,22,0,11,21,43,8,76,58,48,36, +30,10,1,13,29,13,78,54,28,6,16,9,27,41,10,98,76,60,44,42, +10,5,17,25,124,55,49,23,53,51,37,43,37,37,39,37,37,41,35,43, +37,11,33,27,23,19,9,7,9,5,0,5,11,19,22,20,28,14,4,24, +20,12,16,16,14,10,0,7,13,5,14,25,16,44,14,14,28,28,30,18, +24,24,36,1,9,17,74,74,84,64,62,80,84,84,92,86,98,96,80,66, +22,74,98,70,66,68,60,42,34,28,12,5,11,23,43,66,64,66,54,34, +40,28,14,14,6,1,19,17,39,45,11,11,41,32,36,22,2,18,16,3, +8,6,7,29,27,43,69,20,0,21,21,0,0,8,12,14,24,16,22,26, +48,30,30,46,46,110,86,70,54,38,20,1,27,71,8,72,58,54,42,42, +20,14,12,7,31,21,3,19,6,22,11,15,6,14,8,12,26,8,4,106, +80,54,28,8,19,43,63,91,0,0,0,0,110,14,27,110,14,27,59,25, +36,22,8,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,44,0,0,0,17,53,67,0, +14,3,104,14,11,85,45,37,3,37,61,53,69,19,61,51,55,77,73,79, +75,30,3,5,49,5,39,29,55,17,51,37,79,24,25,7,69,41,19,19, +3,10,0,11,20,14,13,4,0,3,4,23,24,6,34,38,24,34,34,28, +20,22,10,22,22,29,57,37,43,23,31,25,3,21,21,15,15,15,17,9, +33,57,37,63,13,21,4,7,0,20,2,3,4,18,7,19,2,45,70,74, +58,60,74,58,30,62,54,14,32,28,8,2,11,22,10,14,16,8,1,16, +6,11,0,5,15,5,51,104,108,100,106,100,94,94,94,88,70,70,62,42, +34,3,68,56,22,72,52,52,42,34,26,28,12,9,1,11,41,37,71,7, +58,38,26,8,10,1,11,17,33,4,84,56,44,34,36,10,5,11,21,27, +52,30,18,6,10,5,15,27,51,39,6,3,3,11,13,33,39,61,9,72, +40,26,10,16,7,15,21,33,124,43,25,11,5,11,2,12,14,11,10,20, +16,27,15,15,16,20,20,14,34,40,36,8,20,32,28,19,5,21,51,39, +27,31,23,25,21,17,13,19,17,9,11,21,35,53,29,67,25,9,13,4, +11,3,14,3,5,5,8,9,11,41,80,74,78,70,58,74,66,60,52,50, +52,42,6,6,7,36,36,24,0,16,12,5,9,15,21,27,53,31,61,112, +110,102,100,86,82,76,62,62,54,48,32,22,2,19,64,66,14,68,74,52, +40,44,36,28,34,22,12,1,5,19,49,12,7,31,71,49,57,15,21,17, +46,0,0,9,20,72,46,84,6,98,92,62,38,16,8,45,59,81,15,84, +56,38,18,22,4,3,9,35,51,35,17,23,5,4,9,11,4,10,12,6, +20,22,4,98,92,76,62,52,40,4,13,39,0,0,0,0,110,14,27,110, +14,27,59,25,36,22,8,6,68,78,106,28,21,2,2,24,0,0,9,13, +43,20,58,67,91,101,17,33,9,2,24,0,29,21,20,16,3,19,37,2, +23,33,53,10,17,37,8,19,27,49,10,9,11,21,0,8,44,0,0,0, +17,53,67,0,14,3,36,19,57,59,1,15,48,30,13,1,39,5,33,27, +57,39,39,47,57,42,0,16,37,13,35,27,69,8,7,5,25,34,9,1, +29,37,13,19,9,14,16,1,24,28,25,1,3,7,8,19,30,9,2,30, +34,50,38,24,35,1,13,4,8,55,0,16,10,10,14,14,32,18,6,4, +4,4,16,16,39,7,2,19,10,10,28,14,4,18,12,8,8,28,8,25, +6,31,44,42,32,28,34,34,20,32,40,1,20,18,12,6,7,10,1,4, +8,2,10,22,2,33,0,21,0,12,37,54,70,54,52,50,48,44,44,32, +16,12,6,0,7,53,9,1,27,28,20,14,16,8,3,1,1,25,11,21, +57,45,67,9,44,36,22,6,14,3,13,17,35,5,72,42,30,16,24,2, +9,19,39,8,76,58,48,36,32,10,1,13,29,13,78,54,26,6,16,9, +27,39,10,98,76,58,42,42,10,5,15,23,124,53,47,23,51,49,35,39, +35,35,37,33,35,41,33,43,37,7,33,27,23,19,9,9,9,5,1,7, +13,21,22,18,28,12,4,24,18,12,14,16,12,10,1,7,15,5,14,27, +16,44,12,14,26,28,30,16,22,22,34,3,9,19,72,72,84,62,60,76, +80,80,88,80,94,92,74,60,20,68,92,64,58,62,54,38,32,26,12,3, +11,21,39,62,60,62,50,30,36,26,10,10,4,3,21,21,41,47,11,13, +43,30,32,20,1,14,12,7,6,2,11,31,31,47,71,18,1,23,21,2, +0,8,14,14,26,18,24,28,50,32,32,50,48,110,84,66,48,34,14,7, +33,75,10,74,60,56,42,44,22,14,14,5,31,19,3,17,8,24,11,15, +6,14,8,14,28,8,4,104,76,48,22,2,27,51,71,95,0,0,0,0, +106,14,27,106,14,27,57,23,36,22,8,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, +44,0,0,0,15,55,67,0,12,3,104,14,11,83,43,37,3,33,59,49, +67,17,59,47,51,75,73,77,75,30,3,3,47,5,39,27,51,17,51,37, +77,24,23,7,67,41,19,19,1,10,0,11,20,14,15,2,0,3,4,23, +24,6,32,38,24,34,34,26,16,22,10,18,20,31,55,35,41,21,31,23, +1,19,21,13,13,15,17,7,35,57,35,63,13,21,4,7,1,22,2,3, +0,20,9,21,2,47,66,72,56,58,72,56,28,60,54,10,30,26,8,2, +11,20,10,12,16,6,3,14,4,15,1,7,17,7,51,100,106,96,102,96, +90,88,90,82,66,66,56,36,30,9,64,54,18,66,48,48,38,28,22,22, +8,13,3,13,45,39,71,7,58,40,26,8,10,1,11,17,31,6,86,56, +44,34,38,10,3,11,19,27,54,32,18,6,10,5,15,25,49,39,8,3, +3,11,11,31,39,59,9,74,40,26,10,18,5,15,19,31,124,43,25,11, +5,11,2,12,14,9,10,20,18,27,15,15,14,20,18,12,32,38,36,4, +18,30,28,21,7,23,51,39,25,31,23,25,19,15,15,19,17,9,13,21, +35,53,27,67,25,7,13,4,11,3,16,3,7,5,10,9,13,43,78,74, +78,68,56,72,64,58,50,48,50,40,4,4,9,32,32,20,3,14,10,7, +11,15,21,27,53,33,61,106,104,98,94,80,78,72,56,58,50,44,28,18, +0,21,60,62,12,64,70,48,36,38,32,24,30,18,8,5,9,23,51,8, +11,35,69,47,55,15,19,15,50,2,2,9,22,74,48,86,6,96,88,56, +32,10,2,51,63,83,15,84,56,38,18,22,4,3,9,33,49,33,15,23, +3,6,7,9,6,12,14,8,22,24,4,94,88,72,58,48,36,0,17,41, +0,0,0,0,106,14,27,106,14,27,57,23,36,22,8,4,66,74,106,28, +15,0,4,24,0,1,9,15,45,18,54,71,93,103,11,31,9,4,24,0, +29,19,20,14,3,19,37,2,23,31,53,10,17,35,6,21,27,49,10,7, +11,19,0,8,44,0,0,0,15,55,67,0,12,3,36,19,57,57,0,11, +50,32,11,0,37,1,31,25,53,39,37,47,55,42,0,16,35,13,33,27, +67,6,7,5,25,34,9,1,29,37,13,19,9,14,14,1,24,28,25,1, +3,7,8,19,30,11,2,30,32,48,36,22,33,1,13,2,6,55,1,16, +8,10,14,14,34,20,6,2,4,2,14,14,41,7,2,21,10,8,26,12, +4,20,12,8,6,26,6,25,6,33,44,42,32,28,34,34,20,32,38,1, +20,18,12,6,9,10,1,4,8,2,10,20,0,33,0,21,1,10,37,50, +66,50,48,46,44,40,40,28,12,8,2,5,11,55,9,3,29,26,18,12, +14,4,5,3,5,25,13,23,57,45,65,9,44,36,22,6,14,3,13,17, +33,3,72,42,30,16,24,2,9,19,35,8,76,58,48,36,32,10,1,13, +27,13,78,52,26,6,16,9,27,39,10,96,74,56,40,42,10,5,15,23, +124,51,45,21,47,47,33,37,31,33,33,31,31,39,33,41,35,5,31,29, +23,17,9,9,11,7,3,9,15,23,20,18,28,12,2,22,18,12,12,14, +12,8,3,9,15,5,14,27,14,42,10,14,24,26,30,14,20,22,34,5, +11,23,70,72,82,60,56,74,76,76,84,76,88,86,68,56,16,62,84,58, +50,58,50,34,30,22,12,1,9,19,35,60,56,58,48,26,32,22,6,8, +0,7,25,23,43,49,13,13,45,26,30,16,3,10,8,9,2,1,13,33, +33,49,71,16,1,25,21,2,2,10,14,16,28,18,26,30,52,34,34,52, +50,108,80,62,44,28,8,13,39,81,10,74,60,56,44,44,22,16,14,5, +29,19,1,17,10,26,11,13,8,16,8,14,30,8,4,100,72,44,16,3, +35,59,77,101,0,0,0,0,104,14,27,104,14,27,53,19,36,22,6,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,44,0,0,0,15,55,67,2,10,3,104,14, +11,81,41,37,1,31,55,45,63,15,55,45,47,73,71,75,73,32,3,1, +45,5,37,25,47,17,51,35,73,26,23,5,65,39,17,19,1,12,2,9, +22,16,15,2,0,3,4,23,24,4,30,38,22,34,34,26,12,22,8,16, +18,33,53,33,39,19,29,21,0,17,19,11,11,15,17,7,37,55,33,63, +11,21,6,7,3,24,2,3,1,22,9,23,2,47,64,70,56,56,70,54, +26,60,54,8,28,26,8,2,13,20,8,10,14,4,5,14,2,19,3,9, +19,9,51,96,104,92,98,94,86,84,86,78,62,62,52,32,26,13,60,50, +14,62,44,44,34,24,18,16,4,19,5,17,47,39,71,7,58,40,26,8, +10,1,11,17,31,6,86,56,44,34,40,12,1,11,17,25,56,34,18,8, +12,3,13,25,47,37,12,1,3,9,9,29,37,57,7,74,42,26,10,20, +3,13,17,29,124,43,25,9,5,11,2,12,14,9,10,22,18,27,15,15, +12,22,16,10,30,38,36,2,16,30,28,23,9,23,49,37,23,29,21,23, +19,13,15,19,17,9,15,21,35,51,25,67,25,7,13,6,11,3,18,3, +7,5,12,11,13,43,76,74,76,68,54,70,62,56,50,46,48,38,2,2, +11,30,30,18,7,12,8,9,13,17,21,25,53,33,59,102,100,94,90,76, +74,68,52,54,46,40,24,14,3,23,56,58,10,60,66,44,32,34,28,20, +26,14,2,9,13,27,53,4,15,37,67,43,53,13,17,13,54,4,4,9, +24,78,52,90,8,92,84,52,26,6,3,55,67,85,15,84,56,38,18,22, +4,3,9,33,47,31,13,21,1,8,7,7,8,14,16,8,22,24,4,92, +86,70,56,44,32,3,21,43,0,0,0,0,104,14,27,104,14,27,53,19, +36,22,6,0,62,72,106,28,11,0,6,26,0,1,7,17,47,18,50,75, +95,103,5,27,9,6,26,0,29,17,20,14,3,19,35,2,25,31,53,10, +17,33,6,21,27,49,12,7,9,19,2,8,44,0,0,0,15,55,67,2, +10,3,36,17,57,53,4,9,54,36,7,2,35,0,29,23,49,37,37,45, +53,42,0,16,35,13,33,25,63,6,7,5,25,34,9,0,27,37,13,19, +7,14,14,1,24,28,23,1,1,7,8,19,28,11,2,28,30,48,34,20, +31,0,13,0,6,53,1,16,8,10,14,14,36,20,6,2,4,2,12,14, +43,7,2,21,8,6,26,12,2,20,12,8,4,26,4,25,6,33,42,42, +32,28,34,34,20,32,38,1,20,18,12,6,9,10,1,2,8,2,8,18, +0,33,1,21,3,8,37,48,62,48,46,42,40,36,36,24,8,4,1,9, +13,57,9,3,29,24,16,10,12,2,9,5,7,27,13,23,57,45,65,9, +44,36,22,6,14,1,11,15,31,3,72,42,30,16,24,4,7,17,31,8, +76,58,48,36,32,10,1,13,25,13,80,52,24,6,16,9,27,37,10,96, +72,54,38,42,10,5,15,21,124,49,43,19,45,45,31,35,29,31,31,27, +27,37,31,41,35,3,31,29,21,15,9,11,11,7,3,11,17,25,18,16, +28,10,2,22,18,12,10,12,12,8,5,9,15,5,14,27,12,42,10,14, +22,24,30,12,18,20,32,7,13,27,68,70,82,58,54,70,72,72,80,70, +82,82,62,52,14,56,78,52,42,52,44,30,28,20,12,0,9,17,31,56, +54,54,44,22,28,20,2,6,3,9,29,27,45,51,13,13,47,24,26,12, +7,8,6,13,0,3,17,35,35,51,73,16,3,27,19,4,2,10,16,18, +30,20,28,32,56,36,36,54,54,108,76,58,38,24,2,19,45,85,10,76, +62,58,44,46,22,16,16,3,29,19,0,15,12,28,9,11,8,16,8,16, +32,8,4,98,68,38,10,9,41,67,85,107,0,0,0,0,102,14,29,102, +14,29,49,17,38,22,6,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,44,0,0,0, +13,55,67,2,10,5,104,14,11,79,41,37,1,29,51,41,61,13,51,43, +43,71,69,73,71,34,3,0,45,3,37,25,43,17,49,35,71,26,23,5, +61,39,15,17,1,12,2,7,22,16,17,2,0,3,4,23,24,4,30,38, +20,34,34,26,8,22,8,12,16,35,53,31,39,19,27,21,2,17,19,11, +7,15,17,7,39,55,31,63,11,21,8,5,5,24,2,3,3,24,11,25, +2,49,60,68,54,56,68,54,26,58,52,6,26,26,8,2,13,18,6,8, +12,4,7,12,2,23,5,9,21,11,51,94,100,90,94,90,82,80,82,72, +56,58,46,26,20,19,56,46,12,58,38,38,28,20,12,12,1,23,7,21, +49,41,71,5,60,40,28,8,10,1,11,17,29,6,86,58,44,34,42,12, +1,9,17,23,58,34,20,8,14,3,13,23,45,35,14,0,1,9,9,29, +35,53,7,74,42,26,12,20,3,11,17,27,124,41,23,9,5,11,2,12, +14,9,12,22,20,27,15,17,12,22,14,8,28,36,36,0,14,30,28,23, +11,25,47,35,21,29,21,23,17,13,15,17,15,7,15,21,35,51,23,67, +25,7,13,8,11,3,20,5,7,5,12,13,13,45,74,72,76,66,52,70, +62,54,48,46,46,36,0,0,13,26,28,14,11,8,4,11,13,17,21,25, +51,35,57,98,96,90,86,70,70,64,46,50,40,36,18,10,5,23,54,56, +6,56,60,40,28,30,24,16,20,10,1,13,17,29,57,0,19,41,65,41, +51,11,15,11,56,6,6,9,26,80,54,92,10,90,82,46,20,0,7,61, +71,89,13,84,56,38,18,22,4,3,9,31,45,31,11,19,0,8,5,5, +8,14,16,8,24,24,4,90,82,66,52,42,30,9,23,45,0,0,0,0, +102,14,29,102,14,29,49,17,38,22,6,1,60,70,106,28,7,0,6,28, +0,3,7,19,49,16,48,77,97,105,0,25,9,6,28,0,27,15,22,12, +1,17,33,0,25,31,53,10,15,33,6,21,25,49,12,7,9,19,2,8, +44,0,0,0,13,55,67,2,10,5,36,17,55,49,8,5,56,40,5,4, +31,2,27,23,47,37,37,45,53,44,0,16,33,11,31,25,61,6,9,7, +27,34,9,0,27,37,11,19,7,14,14,0,24,26,23,1,1,7,8,19, +26,11,2,26,28,46,34,20,31,0,13,0,4,53,3,16,8,10,14,14, +36,20,6,2,6,2,10,14,43,9,2,23,8,4,26,12,0,20,12,8, +0,26,2,25,6,35,40,42,30,28,34,34,20,32,38,1,18,18,10,6, +9,8,3,2,6,0,6,16,1,33,1,19,5,4,37,44,58,44,42,38, +36,32,32,20,4,2,3,13,17,59,9,3,31,22,14,8,8,1,11,7, +9,29,15,25,57,45,63,7,44,36,22,8,14,1,11,15,29,1,70,42, +30,16,26,4,5,15,27,8,78,58,48,36,34,10,1,11,25,13,80,52, +24,6,16,7,25,35,10,94,72,52,38,42,10,3,13,21,124,49,41,19, +43,43,29,31,27,29,29,25,25,37,29,41,33,0,31,31,21,15,9,11, +13,7,5,13,19,27,18,16,28,10,0,20,16,12,10,12,10,8,5,9, +17,5,14,29,12,40,8,12,20,24,32,12,16,20,32,7,13,29,66,68, +80,56,52,68,68,68,76,66,78,76,56,46,12,52,72,46,34,46,40,26, +26,18,12,2,9,13,25,52,50,50,40,18,24,16,1,2,5,11,31,29, +47,53,15,15,49,22,24,10,11,4,2,15,3,7,19,39,39,55,75,14, +5,29,19,4,2,12,16,18,34,22,30,34,58,40,38,58,56,106,74,54, +34,18,1,25,49,89,12,76,62,58,44,48,24,16,16,3,29,17,0,15, +14,30,9,11,10,18,8,16,34,8,4,96,64,34,4,17,49,73,91,111, +0,0,0,0,100,14,29,100,14,29,45,13,38,22,4,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,44,0,0,0,13,55,67,4,8,5,104,14,11,77,39,37, +0,25,49,37,57,11,49,39,39,69,67,71,71,36,3,2,43,3,35,23, +39,17,49,33,69,26,21,3,59,37,15,17,0,12,2,5,24,18,17,0, +0,3,4,23,24,2,28,38,20,34,34,24,4,22,6,8,14,37,51,29, +37,17,25,19,4,15,17,9,5,15,17,5,41,53,29,63,11,21,8,5, +7,26,2,3,7,26,11,27,2,51,58,66,54,54,66,52,24,56,52,4, +24,26,8,2,15,16,6,6,12,2,9,10,0,27,7,11,23,13,51,90, +98,86,90,86,78,74,78,68,52,54,42,22,16,23,52,44,8,52,34,34, +24,14,8,6,5,29,9,23,53,43,71,5,60,42,28,8,10,1,11,17, +29,8,88,58,44,34,44,14,0,9,15,21,60,36,20,8,16,1,11,23, +43,35,16,0,1,9,7,27,35,51,5,76,42,26,12,22,1,9,15,25, +124,41,23,7,5,11,2,12,14,7,12,22,20,27,15,17,10,24,12,6, +26,34,36,1,12,28,28,25,13,25,45,35,19,27,19,21,17,11,15,17, +15,7,17,21,35,49,21,67,25,5,13,8,11,3,22,5,7,5,14,13, +15,47,72,72,74,64,50,68,60,52,46,44,44,34,1,1,15,24,24,12, +15,6,2,13,15,19,21,25,51,35,55,94,92,86,80,64,66,60,42,46, +36,32,14,6,9,25,50,52,4,52,56,36,24,26,20,12,16,6,7,17, +21,33,59,3,23,43,63,39,49,11,13,9,60,8,8,9,28,84,58,96, +10,86,78,42,14,5,13,67,75,91,13,84,56,38,18,22,4,3,9,31, +43,29,9,17,2,10,5,3,10,16,18,10,24,26,4,86,80,62,48,38, +26,13,27,47,0,0,0,0,100,14,29,100,14,29,45,13,38,22,4,5, +56,66,106,28,1,1,8,28,0,5,7,21,51,16,44,81,99,105,6,23, +9,8,28,0,27,13,22,12,1,17,33,0,27,29,53,10,15,31,4,21, +25,49,14,5,9,17,4,8,44,0,0,0,13,55,67,4,8,5,36,17, +55,47,12,3,60,44,3,6,29,6,25,21,43,35,35,43,51,44,0,16, +33,11,31,23,57,4,9,7,27,34,9,0,25,37,11,19,5,14,12,0, +24,26,23,1,1,7,8,19,26,11,2,26,26,44,32,18,29,2,13,1, +4,51,3,16,6,10,14,14,38,22,6,2,6,2,8,14,45,9,2,23, +6,2,24,12,0,22,12,8,1,24,0,25,6,35,40,42,30,28,34,34, +20,32,38,1,18,18,10,6,9,8,3,0,6,0,6,14,1,33,3,19, +7,2,37,42,54,40,38,34,32,28,28,16,0,1,7,19,21,61,9,5, +31,20,12,6,6,3,15,9,11,29,15,25,57,45,63,7,44,36,22,8, +14,1,11,13,27,1,70,42,30,16,26,6,3,15,23,8,78,58,48,36, +34,10,1,11,23,13,80,50,22,6,16,7,25,35,10,94,70,50,36,42, +10,3,13,19,124,47,39,17,39,41,27,29,23,27,25,21,21,35,27,39, +33,2,29,31,21,13,9,13,13,9,7,15,21,29,16,14,28,8,0,20, +16,12,8,10,10,6,7,9,17,5,14,29,10,40,6,12,18,22,32,10, +14,18,30,9,15,33,64,68,80,54,48,64,64,64,72,60,72,72,50,42, +8,46,64,40,26,42,34,22,24,16,12,4,7,11,21,50,46,46,38,14, +20,14,5,0,9,15,35,33,49,55,15,15,51,18,20,6,13,0,1,19, +5,11,23,41,41,57,75,12,5,31,19,6,4,12,18,20,36,24,32,36, +60,42,40,60,58,106,70,50,28,14,7,31,55,93,12,78,64,60,46,50, +24,18,18,1,27,17,2,13,16,32,9,9,10,18,8,18,36,8,4,92, +60,28,1,23,57,81,99,117,0,0,0,0,96,12,29,96,12,29,43,11, +38,22,4,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,44,0,0,0,11,57,67,4, +6,5,104,14,11,75,37,37,0,23,45,33,55,9,45,37,37,67,67,69, +69,36,3,4,41,3,35,23,37,17,49,33,67,26,21,3,57,37,13,17, +0,12,2,5,24,18,19,0,0,3,4,23,24,2,26,38,18,34,34,24, +0,22,6,4,12,39,49,27,35,15,25,19,6,15,17,7,3,15,17,5, +45,53,27,63,11,23,10,5,9,28,2,3,9,28,13,29,2,53,54,64, +52,52,64,50,22,54,50,0,22,24,8,2,15,14,4,4,10,0,11,8, +1,31,11,13,25,15,51,86,94,82,86,82,74,70,74,62,46,50,36,16, +10,29,48,40,4,48,30,28,18,10,2,0,9,33,11,27,55,45,73,5, +60,42,28,8,10,1,11,17,27,8,88,58,44,34,46,14,0,9,15,21, +62,36,20,8,16,1,11,21,41,33,18,2,1,9,5,25,33,49,5,76, +42,26,12,24,1,9,13,25,124,41,23,7,5,11,2,12,14,7,12,22, +22,27,15,17,8,24,10,4,24,32,36,5,8,28,28,27,15,27,45,33, +17,27,19,21,15,9,17,17,15,7,19,21,35,49,21,69,25,5,13,10, +11,3,22,5,9,5,16,15,15,49,70,70,74,62,46,66,58,50,44,42, +42,32,3,3,17,20,22,8,19,2,0,15,17,19,21,25,51,37,55,88, +86,82,76,58,60,54,36,42,32,28,8,2,11,27,46,48,0,48,52,30, +18,20,14,8,12,0,11,21,27,37,61,7,27,47,61,37,47,9,11,9, +62,10,8,9,28,86,60,98,12,84,74,36,8,11,19,73,79,93,13,84, +56,38,18,22,4,3,9,29,43,27,7,17,4,10,3,3,10,16,18,10, +26,26,2,84,76,58,44,34,22,17,31,49,0,0,0,0,96,12,29,96, +12,29,43,11,38,22,4,7,54,64,106,28,2,1,10,30,0,7,7,23, +55,14,40,85,101,107,10,21,9,10,30,0,27,11,22,10,1,17,31,1, +27,29,55,10,15,31,4,23,25,49,14,5,9,17,4,8,44,0,0,0, +11,57,67,4,6,5,36,17,55,43,14,0,62,46,1,8,27,8,23,19, +39,35,35,43,49,44,0,16,31,11,29,23,55,4,11,9,29,34,9,0, +25,37,11,19,5,12,12,0,24,24,23,1,1,7,6,19,24,13,2,24, +22,42,30,16,29,2,13,3,2,51,5,14,6,10,14,14,40,22,6,0, +6,0,6,12,47,9,2,25,6,0,24,10,1,22,12,8,5,24,1,25, +6,37,38,40,30,28,34,32,18,32,36,3,16,18,10,4,11,6,5,0, +4,1,4,12,3,33,3,19,9,1,37,38,50,36,34,30,26,24,24,12, +3,5,11,23,25,63,9,5,33,18,8,2,2,7,17,13,15,31,17,27, +57,45,61,7,44,36,22,8,14,1,11,13,25,0,70,42,30,16,26,6, +3,13,21,8,78,58,48,34,34,10,1,11,23,13,80,50,22,6,16,7, +25,33,10,92,68,48,34,40,10,3,13,19,124,45,37,17,37,39,27,27, +21,25,23,19,19,35,27,39,31,4,29,33,21,13,9,13,15,9,9,17, +25,31,14,14,28,8,1,18,14,10,6,8,8,6,9,11,19,5,14,31, +8,38,4,12,16,20,32,8,12,18,30,11,17,37,62,66,78,50,46,62, +60,60,66,56,66,66,44,36,6,40,58,34,18,36,30,18,20,12,12,4, +7,9,17,46,42,42,34,8,16,10,9,3,13,17,39,35,51,57,17,17, +53,16,18,2,17,3,5,21,9,15,25,43,45,61,77,10,7,33,19,6, +4,14,18,20,38,24,34,38,62,44,42,62,60,104,66,46,24,8,13,37, +61,99,12,78,64,60,46,50,24,18,18,1,27,17,2,13,18,34,9,9, +12,20,8,18,36,8,2,90,56,24,7,29,65,89,105,123,0,0,0,0, +94,12,29,94,12,29,39,9,40,22,4,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, +44,0,0,0,9,57,67,4,4,5,104,14,11,73,35,37,0,21,41,29, +51,5,41,35,33,65,65,67,67,38,1,6,39,3,33,21,33,17,47,33, +63,28,21,3,53,37,11,17,0,14,4,3,24,18,19,0,2,3,4,21, +24,2,26,38,16,34,34,24,3,22,6,2,10,39,47,25,33,13,23,17, +8,13,17,5,1,15,17,5,47,51,25,63,9,23,12,5,11,30,2,3, +11,30,15,31,2,53,52,62,52,50,62,48,22,54,50,1,20,24,8,2, +15,14,2,2,8,1,13,8,1,33,13,13,27,17,51,84,92,80,84,80, +70,66,70,58,42,46,32,10,6,35,46,36,2,44,26,24,14,6,1,3, +13,37,11,31,57,45,73,5,62,42,28,10,10,1,9,17,25,8,88,58, +46,34,48,16,2,7,13,19,64,38,22,10,18,0,11,19,39,31,22,4, +0,7,3,23,31,47,3,76,44,28,12,26,0,7,11,23,124,39,21,5, +5,11,2,14,16,7,12,24,24,27,15,17,8,24,8,4,22,32,36,7, +6,28,28,27,17,29,43,31,15,27,17,21,13,7,17,17,15,5,19,21, +35,49,19,69,25,5,13,12,11,3,24,5,9,5,18,17,15,49,68,70, +74,62,44,64,56,48,44,40,40,32,3,5,19,18,20,4,23,0,1,15, +17,19,19,23,51,39,53,84,82,78,72,54,56,50,32,38,28,24,4,1, +13,29,42,46,1,44,48,26,14,16,10,4,8,3,15,23,31,41,63,11, +31,51,59,33,43,7,9,7,66,12,10,9,30,90,62,102,14,82,72,32, +2,15,25,77,83,95,13,84,56,38,18,24,4,3,9,27,41,25,5,15, +8,12,1,1,12,18,20,10,28,26,2,82,74,56,42,30,18,21,35,49, +0,0,0,0,94,12,29,94,12,29,39,9,40,22,4,9,52,62,106,28, +6,1,12,32,0,7,5,25,57,12,36,87,103,109,16,17,9,12,32,0, +25,9,24,8,1,15,29,1,27,29,55,10,15,29,4,23,25,49,14,5, +7,17,4,8,44,0,0,0,9,57,67,4,4,5,36,15,55,39,18,4, +64,50,2,10,23,10,19,17,35,35,35,43,47,44,0,16,29,11,27,21, +53,4,11,9,29,34,9,2,23,35,9,19,5,12,12,0,24,24,21,1, +0,7,6,17,22,13,2,22,20,42,28,14,27,2,11,5,0,51,7,14, +6,12,14,14,42,22,6,0,8,0,6,12,49,9,2,27,6,1,24,10, +3,22,12,8,7,24,1,25,6,39,36,40,30,28,34,32,18,32,36,3, +16,18,10,4,11,6,5,0,4,1,2,12,3,33,3,19,11,3,37,34, +48,34,32,26,22,22,22,8,7,7,13,27,27,65,9,5,35,16,6,0, +0,9,19,15,17,33,19,29,57,43,59,5,46,36,22,8,16,0,9,11, +23,2,70,42,30,16,28,6,1,11,17,8,78,58,48,34,36,10,1,11, +21,13,82,50,22,6,18,7,25,31,10,92,68,48,32,40,10,3,11,17, +124,43,35,15,35,35,25,23,19,21,21,17,15,33,25,39,29,8,29,35, +19,11,9,13,17,9,9,19,27,33,14,14,28,8,1,16,14,10,4,8, +8,6,11,11,19,3,16,31,8,36,4,12,16,20,32,6,10,18,30,13, +17,39,62,64,76,48,44,60,56,56,62,52,62,60,40,32,4,34,52,28, +10,30,26,16,18,10,12,6,7,7,13,42,40,38,30,4,14,8,13,5, +15,19,41,37,53,57,17,17,55,14,16,0,21,5,7,23,11,17,27,45, +47,63,79,10,9,33,17,6,4,16,20,22,40,26,36,40,66,46,44,66, +64,102,64,42,20,2,19,43,67,103,14,78,64,62,46,52,26,18,20,0, +27,15,4,13,20,38,7,7,14,22,8,20,38,8,2,88,52,20,11,35, +71,97,111,125,0,0,0,0,92,12,29,92,12,29,35,5,40,22,2,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,44,0,0,0,9,57,67,6,2,5,104,14, +11,71,33,37,2,17,39,25,49,3,39,31,29,63,63,65,67,40,1,8, +37,3,33,19,29,17,47,31,61,28,19,1,51,35,11,17,2,14,4,1, +26,20,21,1,2,3,4,21,24,0,24,38,16,34,34,22,7,22,4,1, +8,41,45,23,31,11,21,15,10,11,15,3,0,15,17,3,49,51,23,63, +9,23,12,5,13,32,2,3,15,32,15,33,2,55,48,60,50,48,60,46, +20,52,50,3,18,24,8,2,17,12,2,0,8,3,15,6,3,37,15,15, +29,19,51,80,90,76,80,76,66,60,66,52,38,42,26,6,2,39,42,34, +1,38,22,20,10,0,5,9,17,43,13,33,61,47,73,5,62,44,28,10, +10,1,9,17,25,10,90,58,46,34,50,16,4,7,11,17,66,40,22,10, +20,0,9,19,37,31,24,4,0,7,1,21,31,45,3,78,44,28,12,28, +2,5,9,21,124,39,21,5,5,11,2,14,16,5,12,24,24,27,15,17, +6,26,6,2,20,30,36,9,4,26,28,29,19,29,41,31,13,25,17,19, +13,5,17,17,15,5,21,21,35,47,17,69,25,3,13,12,11,3,26,5, +9,5,20,17,17,51,66,70,72,60,42,62,54,46,42,38,38,30,5,7, +21,14,16,2,27,1,3,17,19,21,19,23,51,39,51,80,78,74,66,48, +52,46,26,34,24,20,0,5,17,31,38,42,3,40,44,22,10,12,6,0, +4,7,21,27,35,45,65,15,35,53,57,31,41,7,7,5,70,14,12,9, +32,92,66,104,14,78,68,26,3,21,31,83,87,97,13,84,56,38,18,24, +4,3,9,27,39,23,3,13,10,14,1,0,14,20,22,12,28,28,2,78, +70,52,38,26,14,25,39,51,0,0,0,0,92,12,29,92,12,29,35,5, +40,22,2,13,48,58,106,28,12,3,14,32,0,9,5,27,59,12,32,91, +105,109,22,15,9,14,32,0,25,7,24,8,1,15,29,1,29,27,55,10, +15,27,2,23,25,49,16,3,7,15,6,8,44,0,0,0,9,57,67,6, +2,5,36,15,55,37,22,6,68,54,4,12,21,14,17,15,31,33,33,41, +45,44,0,16,29,11,27,21,49,2,11,9,29,34,9,2,23,35,9,19, +3,12,10,0,24,24,21,1,0,7,6,17,22,13,2,22,18,40,26,12, +25,4,11,7,0,49,7,14,4,12,14,14,44,24,6,0,8,0,4,12, +51,9,2,27,4,3,22,10,3,24,12,8,9,22,3,25,6,39,36,40, +30,28,34,32,18,32,36,3,16,18,10,4,11,6,5,1,4,1,2,10, +5,33,5,19,13,5,37,32,44,30,28,22,18,18,18,4,11,11,17,33, +31,67,9,7,35,14,4,1,1,13,23,17,19,33,19,29,57,43,59,5, +46,36,22,8,16,0,9,11,21,2,70,42,30,16,28,8,0,11,13,8, +78,58,48,34,36,10,1,11,19,13,82,48,20,6,18,7,25,31,10,90, +66,46,30,40,10,3,11,17,124,41,33,13,31,33,23,21,15,19,17,13, +11,31,23,37,29,10,27,35,19,9,9,15,17,11,11,21,29,35,12,12, +28,6,3,16,14,10,2,6,8,4,13,11,19,3,16,31,6,36,2,12, +14,18,32,4,8,16,28,15,19,43,60,64,76,46,40,56,52,52,58,46, +56,56,34,28,0,28,44,22,2,26,20,12,16,8,12,8,5,5,9,40, +36,34,28,0,10,4,17,7,19,23,45,41,55,59,19,17,57,10,12,3, +23,9,11,27,15,21,31,47,49,65,79,8,9,35,17,8,6,16,20,24, +42,28,38,42,68,48,46,68,66,102,60,38,14,1,25,49,73,107,14,80, +66,62,48,54,26,20,20,0,25,15,6,11,22,40,7,5,14,22,8,20, +40,8,2,84,48,14,17,41,79,105,119,125,0,0,0,0,90,12,31,90, +12,31,31,3,42,22,2,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,44,0,0,0, +7,57,67,6,2,7,104,14,11,69,33,37,2,15,35,21,45,1,35,29, +25,61,61,63,65,42,1,10,37,1,31,19,25,17,45,31,59,28,19,1, +47,35,9,15,2,14,4,0,26,20,21,1,2,3,4,21,24,0,24,38, +14,34,34,22,11,22,4,5,6,43,45,21,31,11,19,15,12,11,15,3, +4,15,17,3,51,49,21,63,9,23,14,3,15,32,2,3,17,34,17,35, +2,57,46,58,50,48,58,46,20,50,48,5,16,24,8,2,17,10,0,1, +6,3,17,4,3,41,17,15,31,21,51,78,86,74,76,72,62,56,62,48, +32,38,22,0,3,45,38,30,3,34,16,14,4,3,11,13,23,47,15,37, +63,49,73,3,64,44,30,10,10,1,9,17,23,10,90,60,46,34,52,18, +4,5,11,15,68,40,24,10,22,2,9,17,35,29,26,6,2,7,1,21, +29,41,1,78,44,28,14,28,2,3,9,19,124,37,19,3,5,11,2,14, +16,5,14,24,26,27,15,19,6,26,4,0,18,28,36,11,2,26,28,29, +21,31,39,29,11,25,15,19,11,5,17,15,13,3,21,21,35,47,15,69, +25,3,13,14,11,3,28,7,9,5,20,19,17,53,64,68,72,58,40,62, +54,44,40,38,36,28,7,9,23,12,14,1,31,5,7,19,19,21,19,23, +49,41,49,76,74,70,62,42,48,42,22,30,18,16,5,9,19,31,36,40, +7,36,38,18,6,8,2,3,1,11,25,31,39,47,69,19,39,57,55,29, +39,5,5,3,72,16,14,9,34,96,68,108,16,76,66,22,9,27,35,89, +91,101,11,84,56,38,18,24,4,3,9,25,37,23,1,11,12,14,0,2, +14,20,22,12,30,28,2,76,68,48,34,24,12,31,41,53,0,0,0,0, +90,12,31,90,12,31,31,3,42,22,2,15,46,56,106,28,16,3,14,34, +0,11,5,29,61,10,30,93,107,111,28,13,9,14,34,0,23,5,26,6, +0,13,27,3,29,27,55,10,13,27,2,23,23,49,16,3,7,15,6,8, +44,0,0,0,7,57,67,6,2,7,36,15,53,33,26,10,70,58,6,14, +17,16,15,15,29,33,33,41,45,46,0,16,27,9,25,19,47,2,13,11, +31,34,9,2,21,35,7,19,3,12,10,2,24,22,21,1,0,7,6,17, +20,13,2,20,16,38,26,12,25,4,11,7,1,49,9,14,4,12,14,14, +44,24,6,0,10,0,2,12,51,11,2,29,4,5,22,10,5,24,12,8, +13,22,5,25,6,41,34,40,28,28,34,32,18,32,36,3,14,18,8,4, +11,4,7,1,2,3,0,8,5,33,5,17,15,9,37,28,40,26,24,18, +14,14,14,0,15,13,19,37,35,69,9,7,37,12,2,3,5,15,25,19, +21,35,21,31,57,43,57,3,46,36,22,10,16,0,9,9,19,4,68,42, +30,16,30,8,2,9,9,8,80,58,48,34,38,10,1,9,19,13,82,48, +20,6,18,5,23,29,10,90,66,44,30,40,10,1,9,15,124,41,31,13, +29,31,21,17,13,17,15,11,9,31,21,37,27,14,27,37,19,9,9,15, +19,11,13,23,31,37,12,12,28,6,3,14,12,10,2,6,6,4,13,11, +21,3,16,33,6,34,0,10,12,18,34,4,6,16,28,15,19,45,58,62, +74,44,38,54,48,48,54,42,52,50,28,22,1,24,38,16,5,20,16,8, +14,6,12,10,5,1,3,36,32,30,24,3,6,2,21,11,21,25,47,43, +57,61,19,19,59,8,10,5,27,13,15,29,17,25,33,51,53,69,81,6, +11,37,17,8,6,18,22,24,46,30,40,44,70,52,48,72,68,100,58,34, +10,7,29,55,77,111,16,80,66,64,48,56,28,20,22,2,25,13,6,11, +24,42,7,5,16,24,8,22,42,8,2,82,44,10,23,49,87,111,125,125, +0,0,0,0,86,12,31,86,12,31,29,0,42,22,0,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,44,0,0,0,7,59,67,8,0,7,104,14,11,67,31,37, +4,13,31,17,43,0,31,27,21,59,61,61,63,42,1,12,35,1,31,17, +21,17,45,29,57,28,19,0,45,33,7,15,2,14,4,0,28,22,23,1, +2,3,4,21,24,1,22,38,12,34,34,22,15,22,2,9,4,45,43,19, +29,9,19,13,14,9,13,1,6,15,17,3,53,49,19,63,9,23,16,3, +17,34,2,3,19,36,17,37,2,59,42,56,48,46,56,44,18,48,48,9, +14,22,8,2,19,8,1,3,4,5,19,2,5,45,19,17,33,23,51,74, +84,70,72,68,58,52,58,42,28,34,16,3,7,49,34,26,7,30,12,10, +0,7,15,19,27,53,17,41,65,51,73,3,64,44,30,10,10,1,9,17, +23,10,90,60,46,34,54,18,6,5,9,15,70,42,24,10,22,2,7,17, +33,27,28,8,2,7,0,19,27,39,1,78,44,28,14,30,4,3,7,17, +124,37,19,3,5,11,2,14,16,5,14,24,26,27,15,19,4,28,2,1, +16,26,36,15,0,26,28,31,23,31,39,27,9,23,15,17,11,3,19,15, +13,3,23,21,35,45,13,69,25,3,13,16,11,3,30,7,11,5,22,21, +17,55,62,68,70,56,38,60,52,42,38,36,34,26,9,11,25,8,12,3, +35,7,9,21,21,23,19,23,49,41,49,70,68,66,58,36,44,38,16,26, +14,12,9,13,23,33,32,36,9,32,34,14,2,2,1,7,5,15,31,35, +43,51,71,23,43,59,53,27,37,3,3,1,76,18,16,9,36,98,72,110, +18,72,62,16,15,33,41,95,95,103,11,84,56,38,18,24,4,3,9,25, +35,21,0,11,14,16,0,4,16,22,24,12,30,28,2,74,64,44,30,20, +8,35,45,55,0,0,0,0,86,12,31,86,12,31,29,0,42,22,0,19, +42,54,106,28,20,3,16,36,0,13,5,31,63,10,26,97,109,111,34,11, +9,16,36,0,23,3,26,6,0,13,25,3,31,27,55,10,13,25,2,25, +23,49,18,3,7,15,8,8,44,0,0,0,7,59,67,8,0,7,36,15, +53,29,28,12,74,60,8,16,15,18,13,13,25,31,33,39,43,46,0,16, +27,9,25,19,43,2,13,11,31,34,9,2,21,35,7,19,1,12,10,2, +24,22,21,1,0,7,6,17,18,15,2,18,14,36,24,10,23,6,11,9, +1,47,9,14,4,12,14,14,46,24,6,1,10,1,0,10,53,11,2,29, +2,7,22,8,7,24,12,8,15,22,7,25,6,41,32,40,28,28,34,32, +18,32,34,3,14,18,8,4,13,4,7,3,2,3,1,6,7,33,7,17, +17,11,37,26,36,22,20,14,10,10,10,3,19,17,23,41,39,71,9,7, +37,10,0,5,7,19,29,21,25,37,21,31,57,43,57,3,46,36,22,10, +16,0,9,9,17,4,68,42,30,16,30,10,2,7,5,8,80,58,48,34, +38,10,1,9,17,13,82,48,18,6,18,5,23,27,10,88,64,42,28,40, +10,1,9,15,124,39,29,11,27,29,19,15,11,15,13,7,5,29,21,37, +27,16,27,37,19,7,9,17,19,11,15,25,33,39,10,10,28,4,5,14, +12,10,0,4,6,4,15,13,21,3,16,33,4,34,1,10,10,16,34,2, +4,14,26,17,21,49,56,60,74,42,36,50,44,44,50,36,46,46,22,18, +3,18,32,10,13,14,10,4,12,2,12,12,5,0,0,32,28,26,20,7, +2,1,25,13,25,27,51,47,59,63,21,19,61,6,6,9,31,17,19,33, +21,29,37,53,55,71,83,4,13,39,17,10,6,18,22,26,48,30,42,46, +72,54,50,74,70,100,54,30,4,11,35,61,83,117,16,82,68,64,48,56, +28,20,22,2,25,13,8,9,26,44,7,3,16,24,8,22,44,8,2,80, +40,4,29,55,95,119,125,125,0,0,0,0,84,12,31,84,12,31,25,2, +42,22,0,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,44,0,0,0,5,59,67,8, +1,7,104,14,11,65,29,37,4,9,29,13,39,2,29,23,17,57,59,59, +63,44,1,14,33,1,29,15,17,17,45,29,53,30,17,0,43,33,7,15, +4,16,6,2,28,22,23,3,2,3,4,21,24,1,20,38,12,34,34,20, +19,22,2,11,2,47,41,17,27,7,17,11,16,7,13,0,8,15,17,1, +55,47,17,63,7,23,16,3,19,36,2,3,23,38,19,39,2,59,40,54, +48,44,54,42,16,48,48,11,12,22,8,2,19,8,1,5,4,7,21,2, +7,49,21,19,35,25,51,70,82,66,68,66,54,46,54,38,24,30,12,9, +11,55,30,24,11,24,8,6,3,13,19,25,31,57,19,43,69,51,73,3, +64,46,30,10,10,1,9,17,21,12,92,60,46,34,56,20,8,5,7,13, +72,44,24,12,24,4,7,15,31,27,32,8,2,5,2,17,27,37,0,80, +46,28,14,32,6,1,5,15,124,37,19,1,5,11,2,14,16,3,14,26, +28,27,15,19,2,28,0,3,14,26,36,17,1,24,28,33,25,33,37,27, +7,23,13,17,9,1,19,15,13,3,25,21,35,45,11,69,25,1,13,16, +11,3,32,7,11,5,24,21,19,55,60,68,70,56,36,58,50,40,38,34, +32,24,11,13,27,6,8,7,39,9,11,23,23,23,19,21,49,43,47,66, +64,62,52,32,40,34,12,22,10,8,13,17,25,35,28,32,11,28,30,10, +1,1,5,11,9,19,35,39,47,55,73,27,47,63,51,23,35,3,1,0, +80,20,18,9,38,102,74,114,18,70,58,12,21,37,47,99,99,105,11,84, +56,38,18,24,4,3,9,23,33,19,2,9,16,18,2,6,18,24,26,14, +32,30,2,70,62,42,28,16,4,39,49,57,0,0,0,0,84,12,31,84, +12,31,25,2,42,22,0,21,40,50,106,28,26,5,18,36,0,13,3,33, +65,8,22,101,111,113,40,7,9,18,36,0,23,1,26,4,0,13,25,3, +31,25,55,10,13,23,0,25,23,49,18,1,5,13,8,8,44,0,0,0, +5,59,67,8,1,7,36,13,53,27,32,16,76,64,12,18,13,22,11,11, +21,31,31,39,41,46,0,16,25,9,23,17,41,0,13,11,31,34,9,4, +19,35,7,19,1,12,8,2,24,22,19,1,2,7,6,17,18,15,2,18, +12,36,22,8,21,6,11,11,3,47,11,14,2,12,14,14,48,26,6,1, +10,1,1,10,55,11,2,31,2,9,20,8,7,26,12,8,17,20,9,25, +6,43,32,40,28,28,34,32,18,32,34,3,14,18,8,4,13,4,7,3, +2,3,1,4,7,33,7,17,19,13,37,22,32,20,18,10,6,6,6,7, +23,21,27,47,41,73,9,9,39,8,1,7,9,21,31,23,27,37,23,33, +57,43,55,3,46,36,22,10,16,2,7,7,15,6,68,42,30,16,30,10, +4,7,1,8,80,58,48,34,38,10,1,9,15,13,84,46,18,6,18,5, +23,27,10,88,62,40,26,40,10,1,9,13,124,37,27,9,23,27,17,13, +7,13,9,5,1,27,19,35,25,18,25,39,17,5,9,17,21,13,15,27, +35,41,8,10,28,4,5,12,12,10,1,2,6,2,17,13,21,3,16,33, +2,32,1,10,8,14,34,0,2,14,26,19,23,53,54,60,72,40,32,48, +40,40,46,32,40,40,16,14,7,12,24,4,21,10,6,0,10,0,12,14, +3,2,4,30,26,22,18,11,1,3,29,15,29,31,55,49,61,65,21,19, +63,2,4,13,33,19,21,35,23,31,39,55,57,73,83,4,13,41,15,10, +8,20,24,28,50,32,44,48,76,56,52,76,74,98,50,26,0,17,41,67, +89,121,16,82,68,66,50,58,28,22,24,4,23,13,10,9,28,46,5,1, +18,26,8,24,46,8,2,76,36,0,35,61,101,125,125,125,0,0,0,0, +82,12,31,82,12,31,21,6,44,22,1,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, +44,0,0,0,5,59,67,10,3,7,104,14,11,63,27,37,6,7,25,9, +37,4,25,21,13,55,57,57,61,46,1,16,31,1,29,15,13,17,43,27, +51,30,17,2,39,31,5,15,4,16,6,4,30,24,25,3,2,3,4,21, +24,3,20,38,10,34,34,20,23,22,0,15,0,49,39,15,25,5,15,11, +18,7,11,2,10,15,17,1,57,47,15,63,7,23,18,3,21,38,2,3, +25,40,19,41,2,61,36,52,46,42,52,40,16,46,46,13,10,22,8,2, +21,6,3,7,2,9,23,0,7,53,23,19,37,27,51,68,78,64,64,62, +50,42,50,32,18,26,6,13,17,59,26,20,13,20,4,0,9,17,25,29, +35,63,21,47,71,53,73,3,66,46,30,10,10,1,9,17,21,12,92,60, +46,34,58,20,8,3,7,11,74,44,26,12,26,4,5,15,29,25,34,10, +4,5,4,15,25,35,0,80,46,28,14,34,6,0,3,13,124,35,17,1, +5,11,2,14,16,3,14,26,28,27,15,19,2,30,1,5,12,24,36,19, +3,24,28,33,27,33,35,25,5,21,13,15,9,0,19,15,13,1,25,21, +35,43,9,69,25,1,13,18,11,3,34,7,11,5,26,23,19,57,58,66, +68,54,34,56,48,38,36,32,30,22,13,15,29,2,6,9,43,13,13,25, +23,25,19,21,49,43,45,62,60,58,48,26,36,30,6,18,6,4,19,21, +29,37,24,30,15,24,26,6,5,5,9,15,13,23,41,43,51,59,75,31, +51,65,49,21,33,1,0,2,82,22,20,9,40,104,78,116,20,66,56,6, +27,43,53,105,103,107,11,84,56,38,18,24,4,3,9,23,31,17,4,7, +18,18,2,8,18,24,26,14,32,30,2,68,58,38,24,12,0,43,53,59, +0,0,0,0,82,12,31,82,12,31,21,6,44,22,1,25,36,48,106,28, +30,5,20,38,0,15,3,35,67,8,18,103,113,113,46,5,9,20,38,0, +21,0,28,4,0,11,23,5,33,25,55,10,13,23,0,25,23,49,20,1, +5,13,10,8,44,0,0,0,5,59,67,10,3,7,36,13,53,23,36,18, +80,68,14,20,9,24,9,9,17,29,31,37,39,46,0,16,25,9,23,17, +37,0,15,13,33,34,9,4,19,35,5,19,0,12,8,2,24,20,19,1, +2,7,6,17,16,15,2,16,10,34,20,6,21,8,11,13,3,45,11,14, +2,12,14,14,50,26,6,1,12,1,3,10,57,11,2,31,0,11,20,8, +9,26,12,8,21,20,11,25,6,43,30,40,28,28,34,32,18,32,34,3, +12,18,8,4,13,2,9,5,0,5,3,2,9,33,9,17,21,17,37,20, +28,16,14,6,2,2,2,11,27,23,29,51,45,75,9,9,39,6,3,9, +13,25,35,25,29,39,23,33,57,43,55,1,46,36,22,10,16,2,7,7, +13,6,68,42,30,16,32,12,6,5,2,8,80,58,48,34,40,10,1,9, +15,13,84,46,16,6,18,5,23,25,10,86,62,38,24,40,10,1,7,13, +124,35,25,9,21,25,15,9,5,11,7,1,0,27,17,35,25,22,25,39, +17,5,9,19,21,13,17,29,37,43,8,8,28,2,7,12,10,10,3,2, +4,2,19,13,23,3,16,35,2,32,3,10,6,14,34,1,0,12,24,21, +23,55,52,58,72,38,30,44,36,36,42,26,36,36,10,8,9,6,18,1, +29,4,0,3,8,1,12,16,3,4,8,26,22,18,14,15,5,7,33,19, +31,33,57,53,63,67,23,21,65,0,0,15,37,23,25,39,27,35,43,57, +61,77,85,2,15,43,15,12,8,20,24,28,52,34,46,50,78,58,54,80, +76,98,48,22,5,21,47,73,95,125,18,84,70,66,50,60,30,22,24,4, +23,11,10,7,30,48,5,1,18,26,8,24,48,8,2,74,32,5,41,67, +109,125,125,125,0,0,0,0,80,12,31,80,12,31,17,8,44,22,1,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,44,0,0,0,3,59,67,10,5,7,104,14, +11,61,25,37,6,5,21,5,33,6,21,19,9,53,55,55,59,48,1,18, +29,1,27,13,9,17,43,27,49,30,17,2,37,31,3,15,4,16,6,6, +30,24,25,3,2,3,4,21,24,3,18,38,8,34,34,20,27,22,0,19, +1,51,37,13,23,3,13,9,20,5,11,4,12,15,17,1,59,45,13,63, +7,23,20,3,23,40,2,3,27,42,21,43,2,63,34,50,46,40,50,38, +14,44,46,15,8,22,8,2,21,4,5,9,0,11,25,1,9,57,25,21, +39,29,51,64,76,60,60,58,46,38,46,28,14,22,2,19,21,65,22,16, +17,16,0,3,13,21,29,35,39,67,23,51,73,55,73,3,66,46,30,10, +10,1,9,17,19,12,92,60,46,34,60,22,10,3,5,9,76,46,26,12, +28,6,5,13,27,23,36,12,4,5,6,13,23,33,2,80,46,28,14,36, +8,2,1,11,124,35,17,0,5,11,2,14,16,3,14,26,30,27,15,19, +0,30,3,7,10,22,36,21,5,24,28,35,29,35,33,23,3,21,11,15, +7,2,19,15,13,1,27,21,35,43,7,69,25,1,13,20,11,3,36,7, +11,5,28,25,19,59,56,66,68,52,32,54,46,36,34,30,28,20,15,17, +31,0,4,13,47,15,15,27,25,25,19,21,49,45,43,58,56,54,44,20, +32,26,2,14,2,0,23,25,31,39,20,26,17,20,22,2,9,9,13,19, +17,27,45,47,55,63,77,35,55,69,47,19,31,0,2,4,86,24,22,9, +42,108,80,120,22,64,52,2,33,49,59,111,107,109,11,84,56,38,18,24, +4,3,9,21,29,15,6,5,20,20,4,10,20,26,28,14,34,30,2,66, +56,34,20,8,3,47,57,61,0,0,0,0,80,12,31,80,12,31,17,8, +44,22,1,27,34,46,106,28,34,5,22,40,0,17,3,37,69,6,14,107, +115,115,52,3,9,22,40,0,21,2,28,2,0,11,21,5,33,25,55,10, +13,21,0,25,23,49,20,1,5,13,10,8,44,0,0,0,3,59,67,10, +5,7,36,13,53,19,40,22,82,72,16,22,7,26,7,7,13,29,31,37, +37,46,0,16,23,9,21,15,35,0,15,13,33,34,9,4,17,35,5,19, +0,12,8,2,24,20,19,1,2,7,6,17,14,15,2,14,8,32,18,4, +19,8,11,15,5,45,13,14,2,12,14,14,52,26,6,1,12,1,5,10, +59,11,2,33,0,13,20,8,11,26,12,8,23,20,13,25,6,45,28,40, +28,28,34,32,18,32,34,3,12,18,8,4,13,2,9,5,0,5,5,0, +9,33,9,17,23,19,37,16,24,12,10,2,1,1,1,15,31,27,33,55, +49,77,9,9,41,4,5,11,15,27,37,27,31,41,25,35,57,43,53,1, +46,36,22,10,16,2,7,5,11,8,68,42,30,16,32,12,8,3,6,8, +80,58,48,34,40,10,1,9,13,13,84,46,16,6,18,5,23,23,10,86, +60,36,22,40,10,1,7,11,124,33,23,7,19,23,13,7,3,9,5,0, +4,25,15,35,23,24,25,41,17,3,9,19,23,13,19,31,39,45,6,8, +28,2,7,10,10,10,5,0,4,2,21,13,23,3,16,35,0,30,5,10, +4,12,34,3,1,12,24,23,25,59,50,56,70,36,28,42,32,32,38,22, +30,30,4,4,11,0,12,7,37,1,3,7,6,3,12,18,3,6,12,22, +18,14,10,19,9,9,37,21,35,35,61,55,65,69,23,21,67,1,1,19, +41,27,29,41,29,39,45,59,63,79,87,0,17,45,15,12,8,22,26,30, +54,36,48,52,80,60,56,82,78,96,44,18,9,27,53,79,101,125,18,84, +70,68,50,62,30,22,26,6,23,11,12,7,32,50,5,0,20,28,8,26, +50,8,2,72,28,9,47,73,117,125,125,125,0,0,0,0,76,10,33,76, +10,33,15,10,44,22,3,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,44,0,0,0, +3,61,67,10,7,9,104,12,11,59,25,37,6,3,19,3,31,8,19,17, +7,51,55,53,59,48,1,18,29,1,27,13,7,17,43,27,47,30,17,2, +35,31,3,15,4,16,6,6,30,24,27,5,2,5,4,21,22,5,16,38, +6,32,34,18,31,20,1,23,3,53,37,13,23,3,13,9,22,5,11,4, +14,17,17,1,63,45,13,63,7,25,20,3,25,40,2,3,31,42,23,45, +2,65,30,48,44,38,48,36,12,42,44,19,6,20,6,2,23,2,7,11, +1,13,27,3,11,61,29,23,43,33,51,60,72,56,56,54,40,32,40,22, +8,16,3,25,27,71,18,12,21,10,5,9,19,27,35,41,45,73,25,55, +77,57,75,3,66,46,30,10,10,3,9,17,19,12,92,60,46,34,62,22, +10,3,5,9,76,46,26,12,28,6,5,13,25,23,38,12,4,5,6,13, +23,31,2,80,46,28,14,36,8,2,1,11,124,35,17,0,5,11,2,14, +16,3,14,26,30,27,15,21,1,30,5,9,8,20,34,25,9,22,26,37, +33,37,33,23,1,21,11,15,7,2,21,15,13,1,29,21,35,43,7,71, +25,1,13,20,13,3,36,9,13,5,28,27,21,61,54,64,66,50,28,52, +44,34,32,28,26,18,17,21,35,3,0,17,51,19,19,29,27,27,19,21, +49,47,43,52,50,50,38,14,26,20,3,8,3,5,29,31,35,41,16,22, +21,16,16,3,15,15,19,23,23,33,51,51,61,67,81,39,59,73,45,17, +29,0,2,4,88,24,22,9,42,110,82,122,22,60,48,3,41,55,65,117, +113,113,11,84,54,36,18,24,4,5,9,21,29,15,6,5,22,20,4,10, +20,26,28,14,34,30,0,62,52,30,16,4,7,53,61,63,0,0,0,0, +76,10,33,76,10,33,15,10,44,22,3,31,30,42,104,28,38,7,22,40, +1,19,3,41,73,4,10,111,117,117,56,1,11,22,40,1,21,4,28,0, +0,11,21,7,35,25,57,10,13,21,1,27,23,49,20,1,5,13,10,6, +44,0,0,0,3,61,67,10,7,9,36,13,53,17,42,24,84,74,18,24, +5,28,5,7,11,29,31,37,37,46,0,16,23,9,21,15,33,1,17,15, +35,34,9,4,17,35,5,19,0,10,6,2,22,18,19,3,2,7,4,17, +12,17,0,12,4,30,16,2,19,8,11,17,7,45,15,12,0,12,14,14, +52,26,6,3,12,3,7,8,61,13,0,35,1,15,18,6,13,26,12,8, +27,18,15,25,6,47,26,38,26,28,34,30,16,32,32,5,10,18,6,2, +15,0,11,7,1,7,7,1,11,33,11,17,25,23,37,12,20,8,6,1, +7,5,5,19,35,31,37,61,53,81,11,11,43,2,9,15,19,31,41,31, +35,43,27,37,57,43,53,1,46,36,22,10,16,2,7,5,9,8,66,42, +30,16,32,12,8,3,8,6,80,58,46,32,40,10,1,9,13,13,84,44, +14,4,18,5,23,23,10,84,58,34,20,38,10,1,7,11,124,33,21,7, +17,21,13,5,1,7,3,2,6,25,15,35,23,26,25,43,17,3,9,21, +25,15,21,33,43,49,4,6,28,0,9,8,8,8,7,1,2,0,23,15, +25,3,16,37,1,28,7,8,2,10,34,5,5,10,22,25,27,63,48,54, +68,32,24,38,28,28,32,16,24,24,1,1,15,5,4,13,47,7,9,11, +2,7,12,18,3,8,16,18,14,10,6,25,13,13,43,25,39,39,65,59, +67,71,25,23,71,5,5,23,45,31,33,45,33,43,49,63,67,83,89,1, +19,47,15,12,8,22,26,30,56,36,50,52,82,62,58,84,80,94,40,12, +15,33,59,87,107,125,18,84,70,68,50,62,30,22,26,6,23,11,12,7, +34,52,5,0,20,28,8,26,50,8,0,68,22,15,53,81,125,125,125,125, +0,0,0,0,74,10,33,74,10,33,11,14,46,24,3,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,44,0,0,0,1,61,67,12,7,9,104,12,11,55,23,37, +8,0,15,0,27,12,15,13,3,47,53,51,57,50,0,20,27,0,25,11, +3,15,41,25,43,32,15,4,31,29,1,13,6,18,8,8,32,26,27,5, +4,5,4,19,22,5,16,38,6,32,34,18,33,20,1,25,5,53,35,11, +21,1,11,7,24,3,9,6,18,17,17,0,65,43,11,63,5,25,22,1, +25,42,2,3,33,44,23,47,2,65,28,48,44,38,48,36,12,42,44,21, +6,20,6,2,23,2,7,11,1,13,29,3,11,63,31,23,45,35,51,58, +70,54,54,52,36,28,36,18,4,12,7,29,31,75,16,10,23,6,9,13, +23,31,39,45,49,77,25,57,79,57,75,1,68,48,32,12,10,3,7,15, +17,14,94,62,48,34,64,24,12,1,3,7,78,48,28,14,30,8,3,11, +21,21,42,14,6,3,8,11,21,27,4,82,48,30,16,38,10,4,0,9, +124,33,15,2,5,9,2,16,18,1,16,28,32,25,15,21,1,32,5,9, +6,20,34,27,11,22,26,37,35,37,31,21,0,19,9,13,5,4,21,13, +11,0,29,19,33,41,5,71,25,0,13,22,13,3,38,9,13,3,30,27, +21,61,54,64,66,50,26,52,44,34,32,28,26,18,17,23,37,5,1,19, +53,21,21,29,27,27,17,19,47,47,41,48,46,46,34,10,22,16,7,4, +7,9,33,35,37,41,14,20,23,14,12,7,19,19,23,27,27,37,55,53, +65,69,83,41,61,75,41,13,25,2,4,6,92,26,24,9,44,114,86,124, +24,58,46,7,47,59,69,121,117,115,9,86,54,36,18,26,4,5,9,19, +27,13,8,3,26,22,6,12,22,28,30,16,36,32,0,60,50,28,14,2, +9,57,63,63,0,0,0,0,74,10,33,74,10,33,11,14,46,24,3,33, +28,40,104,28,44,7,24,42,1,19,1,43,75,4,8,113,119,117,62,2, +11,24,42,1,19,8,30,0,2,9,19,7,35,23,57,10,11,19,1,27, +21,49,22,0,3,11,12,6,44,0,0,0,1,61,67,12,7,9,36,11, +51,13,46,28,88,78,22,26,1,32,1,5,7,27,29,35,35,48,2,18, +21,7,19,13,29,1,17,15,35,36,9,6,15,33,3,17,2,10,6,4, +22,18,17,3,4,7,4,15,12,17,0,12,2,30,16,2,17,10,9,17, +7,43,15,12,0,14,14,14,54,28,8,3,14,3,7,8,61,13,0,35, +1,17,18,6,13,28,14,8,29,18,15,23,6,47,26,38,26,28,34,30, +16,32,32,5,10,18,6,2,15,0,11,7,1,7,7,1,11,31,11,15, +25,25,35,10,18,6,4,5,11,7,7,23,37,33,39,65,55,83,11,11, +43,0,11,17,21,33,43,33,37,43,27,37,55,41,51,0,48,36,22,12, +18,4,5,3,5,10,66,42,30,16,34,14,10,1,12,6,82,60,46,32, +42,10,1,7,11,13,86,44,14,4,20,3,21,21,10,84,58,34,20,38, +10,0,5,9,124,31,19,5,13,17,11,1,2,3,0,6,10,23,13,33, +21,30,23,43,15,1,7,21,25,15,21,33,45,51,4,6,30,0,9,8, +8,8,7,1,2,0,23,15,25,1,18,37,1,28,7,8,2,10,36,5, +7,10,22,25,27,65,48,54,68,30,22,36,24,24,28,12,20,20,5,5, +17,9,1,19,55,11,13,13,0,9,12,20,1,12,22,16,12,8,4,29, +15,15,47,27,41,41,67,61,69,71,25,23,73,7,7,25,47,33,35,47, +35,45,51,65,69,85,89,1,19,47,13,14,10,24,28,32,60,38,52,54, +86,66,60,88,84,94,38,8,19,37,63,93,111,125,20,86,72,70,52,64, +32,24,28,8,21,9,14,5,38,56,3,2,22,30,10,28,52,8,0,66, +18,19,57,87,125,125,125,125,0,0,0,0,72,10,33,72,10,33,7,16, +46,24,3,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,44,0,0,0,0,61,67,12, +9,9,104,12,11,53,21,37,8,2,11,4,25,14,11,11,0,45,51,49, +55,52,0,22,25,0,25,9,0,15,41,25,41,32,15,4,29,29,0,13, +6,18,8,10,32,26,29,5,4,5,4,19,22,5,14,38,4,32,34,18, +37,20,1,29,7,55,33,9,19,0,9,5,26,1,9,8,20,17,17,0, +67,43,9,63,5,25,24,1,27,44,2,3,35,46,25,49,2,67,24,46, +42,36,46,34,10,40,44,23,4,20,6,2,23,0,9,13,3,15,31,5, +13,67,33,25,47,37,51,54,68,50,50,48,32,24,32,12,0,8,13,35, +35,81,12,6,27,2,13,17,27,35,43,51,53,81,27,61,81,59,75,1, +68,48,32,12,10,3,7,15,15,14,94,62,48,34,66,24,14,1,1,5, +80,50,28,14,32,8,3,9,19,19,44,16,6,3,10,9,19,25,4,82, +48,30,16,40,12,6,2,7,124,33,15,2,5,9,2,16,18,1,16,28, +34,25,15,21,3,32,7,11,4,18,34,29,13,22,26,39,37,39,29,19, +2,19,9,13,3,6,21,13,11,0,31,19,33,41,3,71,25,0,13,24, +13,3,40,9,13,3,32,29,21,63,52,64,66,48,24,50,42,32,30,26, +24,16,19,25,39,9,3,23,57,23,23,31,29,27,17,19,47,49,39,44, +42,42,30,4,18,12,13,0,11,13,37,39,39,43,10,16,25,10,8,11, +23,23,27,31,31,41,59,57,69,73,85,45,65,79,39,11,23,4,6,8, +96,28,26,9,46,116,88,124,26,56,42,13,53,65,75,125,121,117,9,86, +54,36,18,26,4,5,9,17,25,11,10,1,28,24,8,14,24,30,32,16, +38,32,0,58,46,24,10,1,13,61,67,65,0,0,0,0,72,10,33,72, +10,33,7,16,46,24,3,35,26,38,104,28,48,7,26,44,1,21,1,45, +77,2,4,117,121,119,68,4,11,26,44,1,19,10,30,1,2,9,17,7, +35,23,57,10,11,17,1,27,21,49,22,0,3,11,12,6,44,0,0,0, +0,61,67,12,9,9,36,11,51,9,50,32,90,82,24,28,0,34,0,3, +3,27,29,35,33,48,2,18,19,7,17,13,27,1,17,15,35,36,9,6, +15,33,3,17,2,10,6,4,22,18,17,3,4,7,4,15,10,17,0,10, +0,28,14,0,15,10,9,19,9,43,17,12,0,14,14,14,56,28,8,3, +14,3,9,8,63,13,0,37,1,19,18,6,15,28,14,8,31,18,17,23, +6,49,24,38,26,28,34,30,16,32,32,5,10,18,6,2,15,0,11,7, +1,7,9,3,13,31,11,15,27,27,35,6,14,2,0,9,15,11,11,27, +41,37,43,69,59,85,11,11,45,1,13,19,23,37,45,35,39,45,29,39, +55,41,49,0,48,36,22,12,18,4,5,3,3,12,66,42,30,16,34,14, +12,0,16,6,82,60,46,32,42,10,1,7,9,13,86,44,14,4,20,3, +21,19,10,82,56,32,18,38,10,0,5,9,124,29,17,3,11,15,9,0, +4,1,2,8,14,21,11,33,19,32,23,45,15,0,7,21,27,15,23,35, +47,53,2,6,30,0,11,6,8,8,9,3,2,0,25,15,25,1,18,37, +3,26,9,8,0,8,36,7,9,10,22,27,29,69,46,52,66,28,20,34, +20,20,24,8,14,14,11,9,19,15,7,25,63,17,17,17,1,11,12,22, +1,14,26,12,8,4,0,33,19,19,51,29,45,43,71,63,71,73,27,23, +75,9,9,29,51,37,39,49,39,49,53,67,71,87,91,3,21,49,13,14, +10,26,28,34,62,40,54,56,88,68,62,90,86,92,34,4,23,43,69,99, +117,125,20,86,72,70,52,66,32,24,28,8,21,9,16,5,40,58,3,4, +24,32,10,28,54,8,0,64,14,23,63,93,125,125,125,125,0,0,0,0, +70,10,33,70,10,33,3,20,48,24,5,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, +44,0,0,0,0,61,67,14,11,9,104,12,11,51,19,37,10,4,7,8, +21,16,7,9,4,43,49,47,53,54,0,24,23,0,23,9,4,15,39,23, +39,32,15,6,25,27,2,13,6,18,8,12,34,28,29,5,4,5,4,19, +22,7,14,38,2,32,34,18,41,20,3,33,9,57,31,7,17,2,7,5, +28,1,7,10,22,17,17,0,69,41,7,63,5,25,26,1,29,46,2,3, +37,48,25,51,2,69,22,44,42,34,44,32,10,38,42,25,2,20,6,2, +25,1,11,15,5,17,33,7,13,71,35,25,49,39,51,52,64,48,46,44, +28,20,28,8,5,4,17,39,41,85,8,2,29,1,17,23,33,39,49,55, +57,87,29,65,83,61,75,1,70,48,32,12,10,3,7,15,15,14,94,62, +48,34,68,26,14,0,1,3,82,50,30,14,34,10,1,9,17,17,46,18, +8,3,12,7,17,23,6,82,48,30,16,42,12,8,4,5,124,31,13,4, +5,9,2,16,18,1,16,28,34,25,15,21,3,34,9,13,2,16,34,31, +15,22,26,39,39,39,27,17,4,17,7,11,3,8,21,13,11,2,31,19, +33,39,1,71,25,0,13,26,13,3,42,9,13,3,34,31,21,65,50,62, +64,46,22,48,40,30,28,24,22,14,21,27,41,11,5,25,61,27,25,33, +29,29,17,19,47,49,37,40,38,38,26,1,14,8,17,3,15,17,43,43, +43,45,6,14,29,6,4,15,27,27,31,35,35,45,65,61,73,77,87,49, +69,81,37,9,21,6,8,10,98,30,28,9,48,120,92,124,28,52,40,17, +59,71,81,125,125,119,9,86,54,36,18,26,4,5,9,17,23,9,12,0, +30,24,8,16,24,30,32,16,38,32,0,56,44,20,6,5,17,65,71,67, +0,0,0,0,70,10,33,70,10,33,3,20,48,24,5,39,22,36,104,28, +52,7,28,46,1,23,1,47,79,2,0,119,123,119,74,6,11,28,46,1, +17,12,32,1,2,7,15,9,37,23,57,10,11,17,1,27,21,49,24,0, +3,11,14,6,44,0,0,0,0,61,67,14,11,9,36,11,51,5,54,34, +94,86,26,30,4,36,2,1,0,25,29,33,31,48,2,18,19,7,17,11, +23,1,19,17,37,36,9,6,13,33,1,17,4,10,6,4,22,16,17,3, +4,7,4,15,8,17,0,8,1,26,12,1,15,12,9,21,9,41,17,12, +0,14,14,14,58,28,8,3,16,3,11,8,65,13,0,37,3,21,18,6, +17,28,14,8,35,18,19,23,6,49,22,38,26,28,34,30,16,32,32,5, +8,18,6,2,15,1,13,9,3,9,11,5,13,31,13,15,29,31,35,4, +10,1,3,13,19,15,15,31,45,39,45,73,63,87,11,11,45,3,15,21, +27,39,49,37,41,47,29,39,55,41,49,2,48,36,22,12,18,4,5,1, +1,12,66,42,30,16,36,16,14,2,20,6,82,60,46,32,44,10,1,7, +9,13,86,44,12,4,20,3,21,17,10,82,56,30,16,38,10,0,3,7, +124,27,15,3,9,13,7,4,6,0,4,12,16,21,9,33,19,36,23,45, +15,0,7,23,27,15,25,37,49,55,2,4,30,1,11,6,6,8,11,3, +0,0,27,15,27,1,18,39,3,26,11,8,1,8,36,9,11,8,20,29, +29,71,44,50,66,26,18,30,16,16,20,2,10,10,17,15,21,21,13,31, +71,23,23,21,3,13,12,24,1,16,30,8,4,0,3,37,23,21,55,33, +47,45,73,67,73,75,27,25,77,11,13,31,55,41,43,53,41,53,57,69, +75,91,93,5,23,51,13,16,10,26,30,34,64,42,56,58,90,70,64,94, +88,92,32,0,29,47,75,105,123,125,22,88,74,72,52,68,34,24,30,10, +21,7,16,3,42,60,3,4,24,32,10,30,56,8,0,62,10,29,69,99, +125,125,125,125,0,0,0,0,66,10,33,66,10,33,1,22,48,24,5,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,44,0,0,0,2,63,67,14,13,9,104,12, +11,49,17,37,10,8,5,12,19,18,5,5,8,41,49,45,53,54,0,26, +21,0,23,7,8,15,39,23,37,32,13,6,23,27,2,13,8,18,8,12, +34,28,31,7,4,5,4,19,22,7,12,38,2,32,34,16,45,20,3,37, +11,59,29,5,15,4,7,3,30,0,7,12,24,17,17,2,71,41,5,63, +5,25,26,1,31,48,2,3,41,50,27,53,2,71,18,42,40,32,42,30, +8,36,42,29,0,18,6,2,25,3,11,17,5,19,35,9,15,75,37,27, +51,41,51,48,62,44,42,40,24,14,24,2,9,0,23,45,45,91,4,0, +33,7,21,27,37,45,53,61,61,91,31,67,87,63,75,1,70,50,32,12, +10,3,7,15,13,16,96,62,48,34,70,26,16,0,0,3,84,52,30,14, +34,10,1,7,15,17,48,18,8,3,14,5,17,21,6,84,48,30,16,44, +14,8,6,3,124,31,13,4,5,9,2,16,18,0,16,28,36,25,15,21, +5,34,11,15,0,14,34,35,17,20,26,41,41,41,27,17,6,17,7,11, +1,10,23,13,11,2,33,19,33,39,0,71,25,2,13,26,13,3,44,9, +15,3,36,31,23,67,48,62,64,44,20,46,38,28,26,22,20,12,23,29, +43,15,9,29,65,29,27,35,31,29,17,19,47,51,37,34,32,34,20,7, +10,4,23,7,19,21,47,47,45,47,2,10,31,2,0,19,31,33,35,39, +39,49,69,65,77,81,89,53,73,85,35,7,19,6,10,12,102,32,30,9, +50,122,94,124,28,50,36,23,65,77,87,125,125,121,9,86,54,36,18,26, +4,5,9,15,21,7,14,0,32,26,10,18,26,32,34,18,40,34,0,52, +40,16,2,9,21,69,75,69,0,0,0,0,66,10,33,66,10,33,1,22, +48,24,5,41,20,32,104,28,58,9,30,46,1,25,1,49,81,0,3,123, +125,121,80,8,11,30,46,1,17,14,32,3,2,7,15,9,37,21,57,10, +11,15,3,29,21,49,24,2,3,9,14,6,44,0,0,0,2,63,67,14, +13,9,36,11,51,3,56,38,96,88,28,32,6,40,4,0,4,25,27,33, +29,48,2,18,17,7,15,11,21,3,19,17,37,36,9,6,13,33,1,17, +4,10,4,4,22,16,17,3,4,7,4,15,8,19,0,8,3,24,10,3, +13,12,9,23,11,41,19,12,1,14,14,14,60,30,8,5,16,5,13,6, +67,13,0,39,3,23,16,4,17,30,14,8,37,16,21,23,6,51,22,38, +26,28,34,30,16,32,30,5,8,18,6,2,17,1,13,9,3,9,11,7, +15,31,13,15,31,33,35,0,6,5,7,17,23,19,19,35,49,43,49,79, +67,89,11,13,47,5,17,23,29,43,51,39,45,47,31,41,55,41,47,2, +48,36,22,12,18,4,5,1,0,14,66,42,30,16,36,16,14,2,24,6, +82,60,46,32,44,10,1,7,7,13,86,42,12,4,20,3,21,17,10,80, +54,28,14,38,10,0,3,7,124,25,13,1,5,11,5,6,10,2,8,14, +20,19,9,31,17,38,21,47,15,2,7,23,29,17,27,39,51,57,0,4, +30,1,13,4,6,8,13,5,0,1,29,17,27,1,18,39,5,24,13,8, +3,6,36,11,13,8,20,31,31,75,42,50,64,24,14,28,12,12,16,1, +4,4,23,19,25,27,21,37,79,27,27,25,5,17,12,26,0,18,34,6, +0,3,5,41,27,25,59,35,51,49,77,69,75,77,29,25,79,15,15,35, +57,45,47,55,45,57,59,71,77,93,93,7,23,53,13,16,12,28,30,36, +66,42,58,60,92,72,66,96,90,90,28,3,33,53,81,111,125,125,22,88, +74,72,54,68,34,26,30,10,19,7,18,3,44,62,3,6,26,34,10,30, +58,8,0,58,6,33,75,105,125,125,125,125,0,0,0,0,64,10,33,64, +10,33,2,26,48,24,7,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,44,0,0,0, +2,63,67,16,15,9,104,12,11,47,15,37,12,10,1,16,15,20,1,3, +12,39,47,43,51,56,0,28,19,0,21,5,12,15,39,21,33,34,13,8, +21,25,4,13,8,20,10,14,36,30,31,7,4,5,4,19,22,9,10,38, +0,32,34,16,49,20,5,39,13,61,27,3,13,6,5,1,32,2,5,14, +26,17,17,2,73,39,3,63,3,25,28,1,33,50,2,3,43,52,27,55, +2,71,16,40,40,30,40,28,6,36,42,31,1,18,6,2,27,3,13,19, +7,21,37,9,17,79,39,29,53,43,51,44,60,40,38,38,20,10,20,1, +13,3,27,49,49,95,0,3,37,11,25,31,41,49,57,67,65,97,33,71, +89,63,75,1,70,50,32,12,10,3,7,15,13,16,96,62,48,34,72,28, +18,0,2,1,86,54,30,16,36,12,0,7,13,15,52,20,8,1,16,3, +15,19,8,84,50,30,16,46,16,10,8,1,124,31,13,6,5,9,2,16, +18,0,16,30,36,25,15,21,7,36,13,17,1,14,34,37,19,20,26,43, +43,41,25,15,8,15,5,9,1,12,23,13,11,2,35,19,33,37,2,71, +25,2,13,28,13,3,46,9,15,3,38,33,23,67,46,62,62,44,18,44, +36,26,26,20,18,10,25,31,45,17,11,31,69,31,29,37,33,31,17,17, +47,51,35,30,28,30,16,11,6,0,27,11,23,25,51,51,49,49,1,6, +33,1,3,23,35,37,39,43,43,53,75,69,81,85,91,57,77,87,33,3, +17,8,12,14,106,34,32,9,52,124,98,124,30,46,32,27,71,81,93,125, +125,123,9,86,54,36,18,26,4,5,9,15,19,5,16,2,34,28,10,20, +28,34,36,18,40,34,0,50,38,14,0,13,25,73,79,71,0,0,0,0, +64,10,33,64,10,33,2,26,48,24,7,45,16,30,104,28,62,9,32,48, +1,25,0,51,83,0,7,125,125,121,86,12,11,32,48,1,17,16,32,3, +2,7,13,9,39,21,57,10,11,13,3,29,21,49,26,2,1,9,16,6, +44,0,0,0,2,63,67,16,15,9,36,9,51,0,60,40,100,92,32,34, +8,42,6,2,8,23,27,31,27,48,2,18,17,7,15,9,17,3,19,17, +37,36,9,8,11,33,1,17,6,10,4,4,22,16,15,3,6,7,4,15, +6,19,0,6,5,24,8,5,11,14,9,25,11,39,19,12,1,14,14,14, +62,30,8,5,16,5,15,6,69,13,0,39,5,25,16,4,19,30,14,8, +39,16,23,23,6,51,20,38,26,28,34,30,16,32,30,5,8,18,6,2, +17,1,13,11,3,9,13,9,15,31,15,15,33,35,35,1,2,7,9,21, +27,23,23,39,53,47,53,83,69,91,11,13,47,7,19,25,31,45,55,41, +47,49,31,41,55,41,47,2,48,36,22,12,18,6,3,0,2,14,66,42, +30,16,36,18,16,4,28,6,82,60,46,32,44,10,1,7,5,13,88,42, +10,4,20,3,21,15,10,80,52,26,12,38,10,0,3,5,124,23,11,0, +3,9,3,8,12,4,10,18,24,17,7,31,17,40,21,47,13,4,7,25, +29,17,27,41,53,59,1,2,30,3,13,4,6,8,15,7,0,1,31,17, +27,1,18,39,7,24,13,8,5,4,36,13,15,6,18,33,33,79,40,48, +64,22,12,24,8,8,12,7,1,0,29,23,27,33,27,43,87,33,33,29, +7,19,12,28,0,20,38,2,1,7,9,45,31,27,63,37,55,51,81,73, +77,79,29,25,81,17,19,39,61,47,49,59,47,59,63,73,79,95,95,7, +25,55,11,18,12,28,32,38,68,44,60,62,96,74,68,98,94,90,24,7, +39,57,87,117,125,125,22,90,76,74,54,70,34,26,32,12,19,7,20,1, +46,64,1,8,26,34,10,32,60,8,0,56,2,39,81,111,125,125,125,125, +0,0,0,0,62,10,35,62,10,35,6,28,50,24,7,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,44,0,0,0,4,63,67,16,15,11,104,12,11,45,15,37, +12,12,2,20,13,22,2,1,16,37,45,41,49,58,0,30,19,2,21,5, +16,15,37,21,31,34,13,8,17,25,6,11,8,20,10,16,36,30,33,7, +4,5,4,19,22,9,10,38,1,32,34,16,53,20,5,43,15,63,27,1, +13,6,3,1,34,2,5,14,30,17,17,2,75,39,1,63,3,25,30,0, +35,50,2,3,45,54,29,57,2,73,12,38,38,30,38,28,6,34,40,33, +3,18,6,2,27,5,15,21,9,21,39,11,17,83,41,29,55,45,51,42, +56,38,34,34,16,6,16,7,19,7,33,55,55,101,3,7,39,15,31,37, +47,53,63,71,71,101,35,75,91,65,75,0,72,50,34,12,10,3,7,15, +11,16,96,64,48,34,74,28,18,2,2,0,88,54,32,16,38,12,0,5, +11,13,54,22,10,1,16,3,13,15,8,84,50,30,18,46,16,12,8,0, +124,29,11,6,5,9,2,16,18,0,18,30,38,25,15,23,7,36,15,19, +3,12,34,39,21,20,26,43,45,43,23,13,10,15,5,9,0,12,23,11, +9,4,35,19,33,37,4,71,25,2,13,30,13,3,48,11,15,3,38,35, +23,69,44,60,62,42,16,44,36,24,24,20,16,8,27,33,47,21,13,35, +73,35,33,39,33,31,17,17,45,53,33,26,24,26,12,17,2,3,33,15, +29,29,57,55,51,49,3,4,37,5,9,27,39,41,43,47,49,57,79,73, +85,87,95,61,81,91,31,1,15,10,14,16,108,36,34,9,54,124,100,124, +32,44,30,33,77,87,97,125,125,125,7,86,54,36,18,26,4,5,9,13, +17,5,18,4,36,28,12,22,28,34,36,18,42,34,0,48,34,10,3,15, +27,79,81,73,0,0,0,0,62,10,35,62,10,35,6,28,50,24,7,47, +14,28,104,28,66,9,32,50,1,27,0,53,85,1,9,125,125,123,92,14, +11,32,50,1,15,18,34,5,4,5,11,11,39,21,57,10,9,13,3,29, +19,49,26,2,1,9,16,6,44,0,0,0,4,63,67,16,15,11,36,9, +49,4,64,44,102,96,34,36,12,44,8,2,10,23,27,31,27,50,2,18, +15,5,13,9,15,3,21,19,39,36,9,8,11,33,0,17,6,10,4,6, +22,14,15,3,6,7,4,15,4,19,0,4,7,22,8,5,11,14,9,25, +13,39,21,12,1,14,14,14,62,30,8,5,18,5,17,6,69,15,0,41, +5,27,16,4,21,30,14,8,43,16,25,23,6,53,18,38,24,28,34,30, +16,32,30,5,6,18,4,2,17,3,15,11,5,11,15,11,17,31,15,13, +35,39,35,5,1,11,13,25,31,27,27,43,57,49,55,87,73,93,11,13, +49,9,21,27,35,49,57,43,49,51,33,43,55,41,45,4,48,36,22,14, +18,6,3,0,4,16,64,42,30,16,38,18,18,6,32,6,84,60,46,32, +46,10,1,5,5,13,88,42,10,4,20,1,19,13,10,78,52,24,12,38, +10,2,1,5,124,23,9,0,1,7,1,12,14,6,12,20,26,17,5,31, +15,44,21,49,13,4,7,25,31,17,29,43,55,61,1,2,30,3,15,2, +4,8,15,7,1,1,31,17,29,1,18,41,7,22,15,6,7,4,38,13, +17,6,18,33,33,81,38,46,62,20,10,22,4,4,8,11,5,5,35,29, +29,37,33,49,95,39,37,33,9,21,12,30,0,24,44,1,5,11,13,49, +35,31,67,41,57,53,83,75,79,81,31,27,83,19,21,41,65,51,53,61, +51,63,65,77,83,99,97,9,27,57,11,18,12,30,32,38,72,46,62,64, +98,78,70,102,96,88,22,11,43,63,91,123,125,125,24,90,76,74,54,72, +36,26,32,12,19,5,20,1,48,66,1,8,28,36,10,32,62,8,0,54, +1,43,87,119,125,125,125,125,0,0,0,0,60,10,35,60,10,35,10,32, +50,24,9,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,44,0,0,0,4,63,67,18, +17,11,104,12,11,43,13,37,14,16,4,24,9,24,4,2,20,35,43,39, +49,60,0,32,17,2,19,3,20,15,37,19,29,34,11,10,15,23,6,11, +10,20,10,18,38,32,33,9,4,5,4,19,22,11,8,38,1,32,34,14, +57,20,7,47,17,65,25,0,11,8,1,0,36,4,3,16,32,17,17,4, +77,37,0,63,3,25,30,0,37,52,2,3,49,56,29,59,2,75,10,36, +38,28,36,26,4,32,40,35,5,18,6,2,29,7,15,23,9,23,41,13, +19,87,43,31,57,47,51,38,54,34,30,30,12,0,12,11,23,11,37,59, +59,105,7,9,43,21,35,41,51,59,67,77,75,107,37,77,95,67,75,0, +72,52,34,12,10,3,7,15,11,18,98,64,48,34,76,30,20,2,4,2, +90,56,32,16,40,14,2,5,9,13,56,22,10,1,18,1,13,13,10,86, +50,30,18,48,18,14,10,2,124,29,11,8,5,9,2,16,18,2,18,30, +38,25,15,23,9,38,17,21,5,10,34,41,23,18,26,45,47,43,21,13, +12,13,3,7,0,14,23,11,9,4,37,19,33,35,6,71,25,4,13,30, +13,3,50,11,15,3,40,35,25,71,42,60,60,40,14,42,34,22,22,18, +14,6,29,35,49,23,17,37,77,37,35,41,35,33,17,17,45,53,31,22, +20,22,6,23,1,7,37,19,33,33,61,59,55,51,7,0,39,9,13,31, +43,45,47,51,53,61,85,77,89,91,97,65,85,93,29,0,13,10,16,18, +112,38,36,9,56,124,104,124,32,40,26,37,83,93,103,125,125,125,7,86, +54,36,18,26,4,5,9,13,15,3,20,6,38,30,12,24,30,36,38,20, +42,36,0,44,32,6,7,19,31,83,85,75,0,0,0,0,60,10,35,60, +10,35,10,32,50,24,9,51,10,24,104,28,72,11,34,50,1,29,0,55, +87,1,13,125,125,123,98,16,11,34,50,1,15,20,34,5,4,5,11,11, +41,19,57,10,9,11,5,29,19,49,28,4,1,7,18,6,44,0,0,0, +4,63,67,18,17,11,36,9,49,6,68,46,106,100,36,38,14,48,10,4, +14,21,25,29,25,50,2,18,15,5,13,7,11,5,21,19,39,36,9,8, +9,33,0,17,8,10,2,6,22,14,15,3,6,7,4,15,4,19,0,4, +9,20,6,7,9,16,9,27,13,37,21,12,3,14,14,14,64,32,8,5, +18,5,19,6,71,15,0,41,7,29,14,4,21,32,14,8,45,14,27,23, +6,53,18,38,24,28,34,30,16,32,30,5,6,18,4,2,17,3,15,13, +5,11,15,13,17,31,17,13,37,41,35,7,5,15,17,29,35,31,31,47, +61,53,59,93,77,95,11,15,49,11,23,29,37,51,61,45,51,51,33,43, +55,41,45,4,48,36,22,14,18,6,3,2,6,16,64,42,30,16,38,20, +20,6,36,6,84,60,46,32,46,10,1,5,3,13,88,40,8,4,20,1, +19,13,10,78,50,22,10,38,10,2,1,3,124,21,7,2,2,5,0,14, +18,8,16,24,30,15,3,29,15,46,19,49,13,6,7,27,31,19,31,45, +57,63,3,0,30,5,15,2,4,8,17,9,1,3,33,17,29,1,18,41, +9,22,17,6,9,2,38,15,19,4,16,35,35,85,36,46,62,18,6,18, +0,0,4,17,11,9,41,33,33,43,41,55,103,43,43,37,11,23,12,32, +2,26,48,3,9,15,15,53,39,33,71,43,61,57,87,79,81,83,31,27, +85,23,25,45,67,55,57,65,53,67,69,79,85,101,97,11,27,59,11,20, +14,30,34,40,74,48,64,66,100,80,72,104,98,88,18,15,49,67,97,125, +125,125,24,92,78,76,56,74,36,28,34,14,17,5,22,0,50,68,1,10, +28,36,10,34,64,8,0,50,5,49,93,125,125,125,125,125,0,0,0,0, +56,8,35,56,8,35,12,34,50,24,9,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, +44,0,0,0,6,65,67,18,19,11,104,12,11,41,11,37,14,18,8,28, +7,26,8,4,22,33,43,37,47,60,0,34,15,2,19,3,22,15,37,19, +27,34,11,10,13,23,8,11,10,20,10,18,38,32,35,9,4,5,4,19, +22,11,6,38,3,32,34,14,61,20,7,51,19,67,23,2,9,10,1,0, +38,4,3,18,34,17,17,4,81,37,2,63,3,27,32,0,39,54,2,3, +51,58,31,61,2,77,6,34,36,26,34,24,2,30,38,39,7,16,6,2, +29,9,17,25,11,25,43,15,21,91,47,33,59,49,51,34,50,30,26,26, +8,3,8,17,29,15,43,65,65,111,11,13,47,25,39,47,57,63,73,83, +79,111,39,81,97,69,77,0,72,52,34,12,10,3,7,15,9,18,98,64, +48,34,78,30,20,2,4,2,92,56,32,16,40,14,2,3,7,11,58,24, +10,1,20,0,11,11,10,86,50,30,18,50,18,14,12,2,124,29,11,8, +5,9,2,16,18,2,18,30,40,25,15,23,11,38,19,23,7,8,34,45, +27,18,26,47,49,45,21,11,14,13,3,7,2,16,25,11,9,4,39,19, +33,35,6,73,25,4,13,32,13,3,50,11,17,3,42,37,25,73,40,58, +60,38,10,40,32,20,20,16,12,4,31,37,51,27,19,41,81,41,37,43, +37,33,17,17,45,55,31,16,14,18,2,29,7,13,43,23,37,37,67,63, +57,53,11,3,43,13,17,37,49,51,53,55,57,67,89,81,95,95,99,69, +89,97,27,2,11,12,18,18,114,40,36,9,56,124,106,124,34,38,22,43, +89,99,109,125,125,125,7,86,54,36,18,26,4,5,9,11,15,1,22,6, +40,30,14,24,30,36,38,20,44,36,1,42,28,2,11,23,35,87,89,77, +0,0,0,0,56,8,35,56,8,35,12,34,50,24,9,53,8,22,104,28, +76,11,36,52,1,31,0,57,91,3,17,125,125,125,102,18,11,36,52,1, +15,22,34,7,4,5,9,13,41,19,59,10,9,11,5,31,19,49,28,4, +1,7,18,6,44,0,0,0,6,65,67,18,19,11,36,9,49,10,70,50, +108,102,38,40,16,50,12,6,18,21,25,29,23,50,2,18,13,5,11,7, +9,5,23,21,41,36,9,8,9,33,0,17,8,8,2,6,22,12,15,3, +6,7,2,15,2,21,0,2,13,18,4,9,9,16,9,29,15,37,23,10, +3,14,14,14,66,32,8,7,18,7,21,4,73,15,0,43,7,31,14,2, +23,32,14,8,49,14,29,23,6,55,16,36,24,28,34,28,14,32,28,7, +4,18,4,0,19,5,17,13,7,13,17,15,19,31,17,13,39,45,35,11, +9,19,21,33,41,35,35,51,65,57,63,97,81,97,11,15,51,13,27,33, +41,55,63,49,55,53,35,45,55,41,43,4,48,36,22,14,18,6,3,2, +8,18,64,42,30,16,38,20,20,8,38,6,84,60,46,30,46,10,1,5, +3,13,88,40,8,4,20,1,19,11,10,76,48,20,8,36,10,2,1,3, +124,19,5,2,4,3,0,16,20,10,18,26,32,15,3,29,13,48,19,51, +13,6,7,27,33,19,33,47,61,65,5,0,30,5,17,0,2,6,19,11, +3,3,35,19,31,1,18,43,11,20,19,6,11,0,38,17,21,4,16,37, +37,89,34,44,60,14,4,16,3,3,1,21,17,15,47,39,35,49,47,61, +111,49,47,41,15,27,12,32,2,28,52,7,13,19,19,59,43,37,75,47, +65,59,91,81,83,85,33,29,87,25,27,49,71,59,61,67,57,71,71,81, +89,105,99,13,29,61,11,20,14,32,34,40,76,48,66,68,102,82,74,106, +100,86,14,19,53,73,103,125,125,125,24,92,78,76,56,74,36,28,34,14, +17,5,22,0,52,70,1,10,30,38,10,34,64,8,1,48,9,53,99,125, +125,125,125,125,0,0,0,0,54,8,35,54,8,35,16,36,52,24,9,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,44,0,0,0,8,65,67,18,21,11,104,12, +11,39,9,37,14,20,12,32,3,30,12,6,26,31,41,35,45,62,2,36, +13,2,17,1,26,15,35,19,23,36,11,10,9,23,10,11,10,22,12,20, +38,32,35,9,6,5,4,17,22,11,6,38,5,32,34,14,65,20,7,53, +21,67,21,4,7,12,0,2,40,6,3,20,36,17,17,4,83,35,4,63, +1,27,34,0,41,56,2,3,53,60,33,63,2,77,4,32,36,24,32,22, +2,30,38,41,9,16,6,2,29,9,19,27,13,27,45,15,21,93,49,33, +61,51,51,32,48,28,24,24,4,7,4,21,33,19,47,71,69,117,13,17, +49,29,43,51,61,67,77,87,83,115,39,85,99,69,77,0,74,52,34,14, +10,3,5,15,7,18,98,64,50,34,80,32,22,4,6,4,94,58,34,18, +42,16,2,1,5,9,62,26,12,0,22,2,9,9,12,86,52,32,18,52, +20,16,14,4,124,27,9,10,5,9,2,18,20,2,18,32,42,25,15,23, +11,38,21,23,9,8,34,47,29,18,26,47,51,47,19,9,16,13,1,7, +4,18,25,11,9,6,39,19,33,35,8,73,25,4,13,34,13,3,52,11, +17,3,44,39,25,73,38,58,60,38,8,38,30,18,20,14,10,4,31,39, +53,29,21,45,85,43,39,43,37,33,15,15,45,57,29,12,10,14,1,33, +11,17,47,27,41,41,71,67,59,55,15,5,45,17,21,41,53,55,57,59, +61,71,93,83,99,99,101,73,93,101,25,6,7,14,20,20,118,42,38,9, +58,124,108,124,36,36,20,47,95,103,115,125,125,125,7,86,54,36,18,28, +4,5,9,9,13,0,24,8,44,32,16,26,32,38,40,20,46,36,1,40, +26,0,13,27,39,91,93,77,0,0,0,0,54,8,35,54,8,35,16,36, +52,24,9,55,6,20,104,28,80,11,38,54,1,31,2,59,93,5,21,125, +125,125,108,22,11,38,54,1,13,24,36,9,4,3,7,13,41,19,59,10, +9,9,5,31,19,49,28,4,0,7,18,6,44,0,0,0,8,65,67,18, +21,11,36,7,49,14,74,54,110,106,42,42,20,52,16,8,22,21,25,29, +21,50,2,18,11,5,9,5,7,5,23,21,41,36,9,10,7,31,2,17, +8,8,2,6,22,12,13,3,8,7,2,13,0,21,0,0,15,18,2,11, +7,16,7,31,17,37,25,10,3,16,14,14,68,32,8,7,20,7,21,4, +75,15,0,45,7,33,14,2,25,32,14,8,51,14,29,23,6,57,14,36, +24,28,34,28,14,32,28,7,4,18,4,0,19,5,17,13,7,13,19,15, +19,31,17,13,41,47,35,15,11,21,23,37,45,37,37,55,69,59,65,101, +83,99,11,15,53,15,29,35,43,57,65,51,57,55,37,47,55,39,41,6, +50,36,22,14,20,8,1,4,10,20,64,42,30,16,40,20,22,10,42,6, +84,60,46,30,48,10,1,5,1,13,90,40,8,4,22,1,19,9,10,76, +48,20,6,36,10,2,0,1,124,17,3,4,6,0,2,20,22,14,20,28, +36,13,1,29,11,52,19,53,11,8,7,27,35,19,33,49,63,67,5,0, +30,5,17,1,2,6,21,11,3,3,37,19,31,0,20,43,11,18,19,6, +11,0,38,19,23,4,16,39,37,91,34,42,58,12,2,14,7,7,5,25, +21,21,51,43,37,55,53,67,119,55,51,43,17,29,12,34,2,30,56,11, +15,23,23,63,45,39,79,49,67,61,93,83,85,85,33,29,89,27,29,51, +75,61,63,69,59,73,73,83,91,107,101,13,31,61,9,20,14,34,36,42, +78,50,68,70,106,84,76,110,104,84,12,23,57,79,109,125,125,125,26,92, +78,78,56,76,38,28,36,16,17,3,24,0,54,74,0,12,32,40,10,36, +66,8,1,46,13,57,103,125,125,125,125,125,0,0,0,0,52,8,35,52, +8,35,20,40,52,24,11,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,44,0,0,0, +8,65,67,20,23,11,104,12,11,37,7,37,16,24,14,36,1,32,14,10, +30,29,39,33,45,64,2,38,11,2,17,0,30,15,35,17,21,36,9,12, +7,21,10,11,12,22,12,22,40,34,37,11,6,5,4,17,22,13,4,38, +5,32,34,12,69,20,9,57,23,69,19,6,5,14,2,4,42,8,1,22, +38,17,17,6,85,35,6,63,1,27,34,0,43,58,2,3,57,62,33,65, +2,79,0,30,34,22,30,20,0,28,38,43,11,16,6,2,31,11,19,29, +13,29,47,17,23,97,51,35,63,53,51,28,46,24,20,20,0,13,0,27, +37,23,53,75,73,121,17,19,53,35,47,55,65,73,81,93,87,121,41,87, +103,71,77,0,74,54,34,14,10,3,5,15,7,20,100,64,50,34,82,32, +24,4,8,6,96,60,34,18,44,16,4,1,3,9,64,26,12,0,24,4, +9,7,12,88,52,32,18,54,22,18,16,6,124,27,9,10,5,9,2,18, +20,4,18,32,42,25,15,23,13,40,23,25,11,6,34,49,31,16,26,49, +53,47,17,9,18,11,1,5,4,20,25,11,9,6,41,19,33,33,10,73, +25,6,13,34,13,3,54,11,17,3,46,39,27,75,36,58,58,36,6,36, +28,16,18,12,8,2,33,41,55,33,25,47,89,45,41,45,39,35,15,15, +45,57,27,8,6,10,7,39,15,21,53,31,45,45,75,71,63,57,19,9, +47,21,25,45,57,59,61,63,65,75,99,87,103,103,103,77,97,103,23,8, +5,14,22,22,122,44,40,9,60,124,112,124,36,32,16,53,101,109,121,125, +125,125,7,86,54,36,18,28,4,5,9,9,11,2,26,10,46,34,16,28, +34,40,42,22,46,38,1,36,22,3,17,31,43,95,97,79,0,0,0,0, +52,8,35,52,8,35,20,40,52,24,11,59,2,16,104,28,86,13,40,54, +1,33,2,61,95,5,25,125,125,125,114,24,11,40,54,1,13,26,36,9, +4,3,7,13,43,17,59,10,9,7,7,31,19,49,30,6,0,5,20,6, +44,0,0,0,8,65,67,20,23,11,36,7,49,16,78,56,114,110,44,44, +22,56,18,10,26,19,23,27,19,50,2,18,11,5,9,5,3,7,23,21, +41,36,9,10,7,31,2,17,10,8,0,6,22,12,13,3,8,7,2,13, +0,21,0,0,17,16,0,13,5,18,7,33,17,35,25,10,5,16,14,14, +70,34,8,7,20,7,23,4,77,15,0,45,9,35,12,2,25,34,14,8, +53,12,31,23,6,57,14,36,24,28,34,28,14,32,28,7,4,18,4,0, +19,5,17,15,7,13,19,17,21,31,19,13,43,49,35,17,15,25,27,41, +49,41,41,59,73,63,69,107,87,101,11,17,53,17,31,37,45,61,69,53, +59,55,37,47,55,39,41,6,50,36,22,14,20,8,1,4,12,20,64,42, +30,16,40,22,24,10,46,6,84,60,46,30,48,10,1,5,0,13,90,38, +6,4,22,1,19,9,10,74,46,18,4,36,10,2,0,1,124,15,1,6, +10,2,4,22,26,16,24,32,40,11,0,27,11,54,17,53,11,10,7,29, +35,21,35,51,65,69,7,1,30,7,19,1,2,6,23,13,3,5,39,19, +31,0,20,43,13,18,21,6,13,1,38,21,25,2,14,41,39,95,32,42, +58,10,1,10,11,11,9,31,27,25,57,47,41,61,61,73,125,59,57,47, +19,31,12,36,4,32,60,13,19,27,25,67,49,43,83,51,71,65,97,87, +87,87,35,29,91,31,33,55,77,65,67,73,63,77,77,85,93,109,101,15, +31,63,9,22,16,34,36,44,80,52,70,72,108,86,78,112,106,84,8,27, +63,83,115,125,125,125,26,94,80,78,58,78,38,30,36,16,15,3,26,2, +56,76,0,14,32,40,10,36,68,8,1,42,17,63,109,125,125,125,125,125, +0,0,0,0,50,8,37,50,8,37,24,42,54,24,11,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,44,0,0,0,10,65,67,20,23,13,104,12,11,35,7,37, +16,26,18,40,2,34,18,12,34,27,37,31,43,66,2,40,11,4,15,0, +34,15,33,17,19,36,9,12,3,21,12,9,12,22,12,24,40,34,37,11, +6,5,4,17,22,13,4,38,7,32,34,12,73,20,9,61,25,71,19,8, +5,14,4,4,44,8,1,22,42,17,17,6,87,33,8,63,1,27,36,2, +45,58,2,3,59,64,35,67,2,81,1,28,34,22,28,20,0,26,36,45, +13,16,6,2,31,13,21,31,15,29,49,19,23,101,53,35,65,55,51,26, +42,22,16,16,3,17,3,31,43,27,57,81,79,125,21,23,55,39,53,61, +71,77,87,97,93,125,43,91,105,73,77,2,76,54,36,14,10,3,5,15, +5,20,100,66,50,34,84,34,24,6,8,8,98,60,36,18,46,18,4,0, +1,7,66,28,14,0,24,4,7,3,14,88,52,32,20,54,22,20,16,8, +124,25,7,12,5,9,2,18,20,4,20,32,44,25,15,25,13,40,25,27, +13,4,34,51,33,16,26,49,55,49,15,7,20,11,0,5,6,20,25,9, +7,8,41,19,33,33,12,73,25,6,13,36,13,3,56,13,17,3,46,41, +27,77,34,56,58,34,4,36,28,14,16,12,6,0,35,43,57,35,27,51, +93,49,45,47,39,35,15,15,43,59,25,4,2,6,11,45,19,25,57,35, +51,49,81,75,65,57,21,11,51,25,31,49,61,63,65,67,71,79,103,91, +107,105,107,81,101,107,21,10,3,16,24,24,124,46,42,9,62,124,114,124, +38,30,14,57,107,115,125,125,125,125,5,86,54,36,18,28,4,5,9,7, +9,2,28,12,48,34,18,30,34,40,42,22,48,38,1,34,20,7,21,33, +45,101,99,81,0,0,0,0,50,8,37,50,8,37,24,42,54,24,11,61, +0,14,104,28,90,13,40,56,1,35,2,63,97,7,27,125,125,125,120,26, +11,40,56,1,11,28,38,11,6,1,5,15,43,17,59,10,7,7,7,31, +17,49,30,6,0,5,20,6,44,0,0,0,10,65,67,20,23,13,36,7, +47,20,82,60,116,114,46,46,26,58,20,10,28,19,23,27,19,52,2,18, +9,3,7,3,1,7,25,23,43,36,9,10,5,31,4,17,10,8,0,8, +22,10,13,3,8,7,2,13,1,21,0,1,19,14,0,13,5,18,7,33, +19,35,27,10,5,16,14,14,70,34,8,7,22,7,25,4,77,17,0,47, +9,37,12,2,27,34,14,8,57,12,33,23,6,59,12,36,22,28,34,28, +14,32,28,7,2,18,2,0,19,7,19,15,9,15,21,19,21,31,19,11, +45,53,35,21,19,29,31,45,53,45,45,63,77,65,71,111,91,103,11,17, +55,19,33,39,49,63,71,55,61,57,39,49,55,39,39,8,50,36,22,16, +20,8,1,6,14,22,62,42,30,16,42,22,26,12,50,6,86,60,46,30, +50,10,1,3,0,13,90,38,6,4,22,0,17,7,10,74,46,16,4,36, +10,4,2,0,124,15,0,6,12,4,6,26,28,18,26,34,42,11,2,27, +9,58,17,55,11,10,7,29,37,21,37,53,67,71,7,1,30,7,19,3, +0,6,23,13,5,5,39,19,33,0,20,45,13,16,23,4,15,1,40,21, +27,2,14,41,39,97,30,40,56,8,3,8,15,15,13,35,31,31,63,53, +43,65,67,79,125,65,61,51,21,33,12,38,4,36,66,17,23,31,29,71, +53,45,87,55,73,67,99,89,89,89,35,31,93,33,35,57,81,69,71,75, +65,81,79,89,97,113,103,17,33,65,9,22,16,36,38,44,84,54,72,74, +110,90,80,116,108,82,6,31,67,89,119,125,125,125,28,94,80,80,58,80, +40,30,38,18,15,1,26,2,58,78,0,14,34,42,10,38,70,8,1,40, +21,67,115,125,125,125,125,125,0,0,0,0,46,8,37,46,8,37,26,46, +54,24,13,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,44,0,0,0,10,67,67,22, +25,13,104,12,11,33,5,37,18,28,22,44,4,36,22,14,38,25,37,29, +41,66,2,42,9,4,15,2,38,15,33,15,17,36,9,14,1,19,14,9, +12,22,12,24,42,36,39,11,6,5,4,17,22,15,2,38,9,32,34,12, +77,20,11,65,27,73,17,10,3,16,4,6,46,10,0,24,44,17,17,6, +89,33,10,63,1,27,38,2,47,60,2,3,61,66,35,69,2,83,5,26, +32,20,26,18,1,24,36,49,15,14,6,2,33,15,23,33,17,31,51,21, +25,105,55,37,67,57,51,22,40,18,12,12,7,21,7,37,47,31,63,85, +83,125,25,27,59,43,57,65,75,81,91,103,97,125,45,95,107,75,77,2, +76,54,36,14,10,3,5,15,5,20,100,66,50,34,86,34,26,6,10,8, +100,62,36,18,46,18,6,0,0,5,68,30,14,0,26,6,5,1,14,88, +52,32,20,56,24,20,18,10,124,25,7,12,5,9,2,18,20,4,20,32, +44,25,15,25,15,42,27,29,15,2,34,55,35,16,26,51,57,49,15,5, +22,9,0,3,6,22,27,9,7,8,43,19,33,31,14,73,25,6,13,38, +13,3,58,13,19,3,48,43,27,79,32,56,56,32,2,34,26,12,14,10, +4,1,37,45,59,39,29,53,97,51,47,49,41,37,15,15,43,59,25,1, +3,2,15,51,23,29,63,39,55,53,85,79,69,59,25,15,53,29,35,53, +65,69,69,71,75,83,109,95,111,109,109,85,105,109,19,12,1,18,26,26, +124,48,44,9,64,124,118,124,40,26,10,63,113,121,125,125,125,125,5,86, +54,36,18,28,4,5,9,7,7,4,30,12,50,36,18,32,36,42,44,22, +48,38,1,32,16,11,25,37,49,105,103,83,0,0,0,0,46,8,37,46, +8,37,26,46,54,24,13,65,3,12,104,28,94,13,42,58,1,37,2,65, +99,7,31,125,125,125,124,28,11,42,58,1,11,30,38,11,6,1,3,15, +45,17,59,10,7,5,7,33,17,49,32,6,0,5,22,6,44,0,0,0, +10,67,67,22,25,13,36,7,47,24,84,62,120,116,48,48,28,60,22,12, +32,17,23,25,17,52,2,18,9,3,7,3,2,7,25,23,43,36,9,10, +5,31,4,17,12,8,0,8,22,10,13,3,8,7,2,13,3,23,0,3, +21,12,1,15,3,20,7,35,19,33,27,10,5,16,14,14,72,34,8,9, +22,9,27,2,79,17,0,47,11,39,12,0,29,34,14,8,59,12,35,23, +6,59,10,36,22,28,34,28,14,32,26,7,2,18,2,0,21,7,19,17, +9,15,23,21,23,31,21,11,47,55,35,23,23,33,35,49,57,49,49,67, +81,69,75,115,95,105,11,17,55,21,35,41,51,67,75,57,65,59,39,49, +55,39,39,8,50,36,22,16,20,8,1,6,16,22,62,42,30,16,42,24, +26,14,54,6,86,60,46,30,50,10,1,3,2,13,90,38,4,4,22,0, +17,5,10,72,44,14,2,36,10,4,2,0,124,13,2,8,14,6,8,28, +30,20,28,38,46,9,2,27,9,60,17,55,11,12,7,31,37,21,39,55, +69,73,9,3,30,9,21,3,0,6,25,15,5,5,41,21,33,0,20,45, +15,16,25,4,17,3,40,23,29,0,12,43,41,101,28,38,56,6,5,4, +19,19,17,41,37,35,69,57,45,71,73,85,125,71,67,55,23,37,12,40, +4,38,70,21,27,35,33,75,57,49,91,57,77,69,103,93,91,91,37,31, +95,35,39,61,85,73,75,79,69,85,83,91,99,115,105,19,35,67,9,24, +16,36,38,46,86,54,74,76,112,92,82,118,110,82,2,35,73,93,125,125, +125,125,28,96,82,80,58,80,40,30,38,18,15,1,28,4,60,80,0,16, +34,42,10,38,72,8,1,38,25,73,121,125,125,125,125,125,0,0,0,0, +44,8,37,44,8,37,30,48,54,24,13,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, +44,0,0,0,12,67,67,22,27,13,104,12,11,31,3,37,18,32,24,48, +8,38,24,18,42,23,35,27,41,68,2,44,7,4,13,4,42,15,33,15, +13,38,7,14,0,19,14,9,14,24,14,26,42,36,39,13,6,5,4,17, +22,15,0,38,9,32,34,10,81,20,11,67,29,75,15,12,1,18,6,8, +48,12,0,26,46,17,17,8,91,31,12,63,0,27,38,2,49,62,2,3, +65,68,37,71,2,83,7,24,32,18,24,16,3,24,36,51,17,14,6,2, +33,15,23,35,17,33,53,21,27,109,57,39,69,59,51,18,38,14,8,10, +11,27,11,41,51,35,67,91,87,125,29,29,63,49,61,69,79,87,95,109, +101,125,47,97,111,75,77,2,76,56,36,14,10,3,5,15,3,22,102,66, +50,34,88,36,28,6,12,10,102,64,36,20,48,20,6,2,2,5,72,30, +14,2,28,8,5,0,16,90,54,32,20,58,26,22,20,12,124,25,7,14, +5,9,2,18,20,6,20,34,46,25,15,25,17,42,29,31,17,2,34,57, +37,14,26,53,59,51,13,5,24,9,2,3,8,24,27,9,7,8,45,19, +33,31,16,73,25,8,13,38,13,3,60,13,19,3,50,43,29,79,30,56, +56,32,0,32,24,10,14,8,2,3,39,47,61,41,33,57,101,53,49,51, +43,37,15,13,43,61,23,5,7,1,21,55,27,33,67,43,59,57,89,83, +71,61,29,19,55,33,39,57,69,73,73,75,79,87,113,99,115,113,111,89, +109,113,17,16,0,18,28,28,124,50,46,9,66,124,120,124,40,24,6,67, +119,125,125,125,125,125,5,86,54,36,18,28,4,5,9,5,5,6,32,14, +52,38,20,34,38,44,46,24,50,40,1,28,14,13,27,41,53,109,107,85, +0,0,0,0,44,8,37,44,8,37,30,48,54,24,13,67,5,8,104,28, +100,15,44,58,1,37,4,67,101,9,35,125,125,125,124,32,11,44,58,1, +11,32,38,13,6,1,3,15,45,15,59,10,7,3,9,33,17,49,32,8, +2,3,22,6,44,0,0,0,12,67,67,22,27,13,36,5,47,26,88,66, +122,120,52,50,30,64,24,14,36,17,21,25,15,52,2,18,7,3,5,1, +4,9,25,23,43,36,9,12,3,31,4,17,12,8,1,8,22,10,11,3, +10,7,2,13,3,23,0,3,23,12,3,17,1,20,7,37,21,33,29,10, +7,16,14,14,74,36,8,9,22,9,29,2,81,17,0,49,11,41,10,0, +29,36,14,8,61,10,37,23,6,61,10,36,22,28,34,28,14,32,26,7, +2,18,2,0,21,7,19,17,9,15,23,23,23,31,21,11,49,57,35,27, +27,35,37,53,61,53,53,71,85,73,79,121,97,107,11,19,57,23,37,43, +53,69,77,59,67,59,41,51,55,39,37,8,50,36,22,16,20,10,0,8, +18,24,62,42,30,16,42,24,28,14,58,6,86,60,46,30,50,10,1,3, +4,13,92,36,4,4,22,0,17,5,10,72,42,12,0,36,10,4,2,2, +124,11,4,10,18,8,10,30,34,22,32,40,50,7,4,25,7,62,15,57, +9,14,7,31,39,23,39,57,71,75,11,3,30,9,21,5,0,6,27,17, +5,7,43,21,33,0,20,45,17,14,25,4,19,5,40,25,31,0,12,45, +43,105,26,38,54,4,9,2,23,23,21,45,43,41,75,61,49,77,81,91, +125,75,71,59,25,39,12,42,6,40,74,23,29,39,35,79,61,51,95,59, +81,73,107,95,93,93,37,31,97,39,41,65,87,75,77,81,71,87,85,93, +101,117,105,19,35,69,7,24,18,38,40,48,88,56,76,78,116,94,84,120, +114,80,1,39,77,99,125,125,125,125,28,96,82,82,60,82,40,32,40,20, +13,1,30,4,62,82,2,18,36,44,10,40,74,8,1,34,29,77,125,125, +125,125,125,125,0,0,0,0,42,8,37,42,8,37,34,52,56,24,15,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,44,0,0,0,12,67,67,24,29,13,104,12, +11,29,1,37,20,34,28,52,10,40,28,20,46,21,33,25,39,70,2,46, +5,4,13,4,46,15,31,13,11,38,7,16,4,17,16,9,14,24,14,28, +44,38,41,13,6,5,4,17,22,17,0,38,11,32,34,10,85,20,13,71, +31,77,13,14,0,20,8,8,50,12,2,28,48,17,17,8,93,31,14,63, +0,27,40,2,51,64,2,3,67,70,37,73,2,85,11,22,30,16,22,14, +3,22,34,53,19,14,6,2,35,17,25,37,19,35,55,23,27,113,59,39, +71,61,51,16,34,12,4,6,15,31,15,47,57,39,73,95,93,125,33,33, +65,53,65,75,85,91,101,113,105,125,49,101,113,77,77,2,78,56,36,14, +10,3,5,15,3,22,102,66,50,34,90,36,28,8,12,12,104,64,38,20, +50,20,8,2,4,3,74,32,16,2,30,10,3,2,16,90,54,32,20,60, +26,24,22,14,124,23,5,14,5,9,2,18,20,6,20,34,46,25,15,25, +17,44,31,33,19,0,34,59,39,14,26,53,61,51,11,3,26,7,2,1, +8,26,27,9,7,10,45,19,33,29,18,73,25,8,13,40,13,3,62,13, +19,3,52,45,29,81,28,54,54,30,1,30,22,8,12,6,0,5,41,49, +63,45,35,59,105,57,51,53,43,39,15,13,43,61,21,9,11,5,25,61, +31,37,73,47,63,61,95,87,75,63,33,21,59,37,43,61,73,77,77,79, +83,91,119,103,119,117,113,93,113,115,15,18,2,20,30,30,124,52,48,9, +68,124,124,124,42,20,4,73,125,125,125,125,125,125,5,86,54,36,18,28, +4,5,9,5,3,8,34,16,54,38,20,36,38,44,46,24,50,40,1,26, +10,17,31,45,57,113,111,87,0,0,0,0,42,8,37,42,8,37,34,52, +56,24,15,71,9,6,104,28,104,15,46,60,1,39,4,69,103,9,39,125, +125,125,124,34,11,46,60,1,9,34,40,13,6,0,1,17,47,15,59,10, +7,3,9,33,17,49,34,8,2,3,24,6,44,0,0,0,12,67,67,24, +29,13,36,5,47,30,92,68,124,124,54,52,34,66,26,16,40,15,21,23, +13,52,2,18,7,3,5,1,8,9,27,25,45,36,9,12,3,31,6,17, +14,8,1,8,22,8,11,3,10,7,2,13,5,23,0,5,25,10,5,19, +1,22,7,39,21,31,29,10,7,16,14,14,76,36,8,9,24,9,31,2, +83,17,0,49,13,43,10,0,31,36,14,8,65,10,39,23,6,61,8,36, +22,28,34,28,14,32,26,7,0,18,2,0,21,9,21,19,11,17,25,25, +25,31,23,11,51,61,35,29,31,39,41,57,65,57,57,75,89,75,81,125, +101,109,11,19,57,25,39,45,57,73,81,61,69,61,41,51,55,39,37,10, +50,36,22,16,20,10,0,8,20,24,62,42,30,16,44,26,30,16,62,6, +86,60,46,30,52,10,1,3,4,13,92,36,2,4,22,0,17,3,10,70, +42,10,1,36,10,4,4,2,124,9,6,10,20,10,12,34,36,24,34,44, +52,7,6,25,7,66,15,57,9,14,7,33,39,23,41,59,73,77,11,5, +30,11,23,5,1,6,29,17,7,7,45,21,35,0,20,47,17,14,27,4, +21,5,40,27,33,1,10,47,43,107,24,36,54,2,11,1,27,27,25,51, +47,45,81,67,51,83,87,97,125,81,77,63,27,41,12,44,6,42,78,27, +33,43,39,83,65,55,99,63,83,75,109,99,95,95,39,33,99,41,45,67, +91,79,81,85,75,91,89,95,105,121,107,21,37,71,7,26,18,38,40,48, +90,58,78,80,118,96,86,124,116,80,3,43,83,103,125,125,125,125,30,98, +84,82,60,84,42,32,40,20,13,0,30,6,64,84,2,18,36,44,10,40, +76,8,1,32,33,83,125,125,125,125,125,125,0,0,0,0,40,8,37,40, +8,37,38,54,56,24,15,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,44,0,0,0, +14,67,67,24,31,13,104,12,11,27,0,37,20,36,32,56,14,42,32,22, +50,19,31,23,37,72,2,48,3,4,11,6,50,15,31,13,9,38,7,16, +6,17,18,9,14,24,14,30,44,38,41,13,6,5,4,17,22,17,1,38, +13,32,34,10,89,20,13,75,33,79,11,16,2,22,10,10,52,14,2,30, +50,17,17,8,95,29,16,63,0,27,42,2,53,66,2,3,69,72,39,75, +2,87,13,20,30,14,20,12,5,20,34,55,21,14,6,2,35,19,27,39, +21,37,57,25,29,117,61,41,73,63,51,12,32,8,0,2,19,35,19,51, +61,43,77,101,97,125,37,37,69,57,69,79,89,95,105,119,109,125,51,105, +115,79,77,2,78,56,36,14,10,3,5,15,1,22,102,66,50,34,92,38, +30,8,14,14,106,66,38,20,52,22,8,4,6,1,76,34,16,2,32,12, +1,4,18,90,54,32,20,62,28,26,24,16,124,23,5,16,5,9,2,18, +20,6,20,34,48,25,15,25,19,44,33,35,21,1,34,61,41,14,26,55, +63,53,9,1,28,7,4,1,10,28,27,9,7,10,47,19,33,29,20,73, +25,8,13,42,13,3,64,13,19,3,54,47,29,83,26,54,54,28,3,28, +20,6,10,4,1,7,43,51,65,47,37,63,109,59,53,55,45,39,15,13, +43,63,19,13,15,9,29,67,35,41,77,51,67,65,99,91,77,65,37,25, +61,41,47,65,77,81,81,83,87,95,123,107,123,121,115,97,117,119,13,20, +4,22,32,32,124,54,50,9,70,124,124,124,44,18,0,77,125,125,125,125, +125,125,5,86,54,36,18,28,4,5,9,3,1,10,36,18,56,40,22,38, +40,46,48,24,52,40,1,24,8,21,35,49,61,117,115,89,0,0,0,0, +40,8,37,40,8,37,38,54,56,24,15,73,11,4,104,28,108,15,48,62, +1,41,4,71,105,11,43,125,125,125,124,36,11,48,62,1,9,36,40,15, +6,0,0,17,47,15,59,10,7,1,9,33,17,49,34,8,2,3,24,6, +44,0,0,0,14,67,67,24,31,13,36,5,47,34,96,72,124,124,56,54, +36,68,28,18,44,15,21,23,11,52,2,18,5,3,3,0,10,9,27,25, +45,36,9,12,1,31,6,17,14,8,1,8,22,8,11,3,10,7,2,13, +7,23,0,7,27,8,7,21,0,22,7,41,23,31,31,10,7,16,14,14, +78,36,8,9,24,9,33,2,85,17,0,51,13,45,10,0,33,36,14,8, +67,10,41,23,6,63,6,36,22,28,34,28,14,32,26,7,0,18,2,0, +21,9,21,19,11,17,27,27,25,31,23,11,53,63,35,33,35,43,45,61, +69,61,61,79,93,79,85,125,105,111,11,19,59,27,41,47,59,75,83,63, +71,63,43,53,55,39,35,10,50,36,22,16,20,10,0,10,22,26,62,42, +30,16,44,26,32,18,66,6,86,60,46,30,52,10,1,3,6,13,92,36, +2,4,22,0,17,1,10,70,40,8,3,36,10,4,4,4,124,7,8,12, +22,12,14,36,38,26,36,46,56,5,8,25,5,68,15,59,9,16,7,33, +41,23,43,61,75,79,13,5,30,11,23,7,1,6,31,19,7,7,47,21, +35,0,20,47,19,12,29,4,23,7,40,29,35,1,10,49,45,111,22,34, +52,0,13,3,31,31,29,55,53,51,87,71,53,89,93,103,125,87,81,67, +29,43,12,46,6,44,82,31,37,47,43,87,69,57,103,65,87,77,113,101, +97,97,39,33,101,43,47,71,95,83,85,87,77,95,91,97,107,123,109,23, +39,73,7,26,18,40,42,50,92,60,80,82,120,98,88,124,118,78,7,47, +87,109,125,125,125,125,30,98,84,84,60,86,42,32,42,22,13,0,32,6, +66,86,2,20,38,46,10,42,78,8,1,30,37,87,125,125,125,125,125,125, +0,0,0,0,36,6,39,36,6,39,40,56,56,24,17,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,44,0,0,0,14,69,67,24,33,15,104,10,11,25,0,37, +20,38,34,58,16,44,34,24,52,17,31,21,37,72,2,48,3,4,11,6, +52,15,31,13,7,38,7,16,8,17,18,9,14,24,14,30,44,38,43,15, +6,7,4,17,20,19,3,38,15,30,34,8,93,18,15,79,35,81,11,16, +2,22,10,10,54,14,2,30,52,19,17,8,99,29,16,63,0,29,42,2, +55,66,2,3,73,72,41,77,2,89,17,18,28,12,18,10,7,18,32,59, +23,12,4,2,37,21,29,41,23,39,59,27,31,121,65,43,77,67,51,8, +28,4,3,1,25,41,25,57,67,49,83,107,103,125,41,41,73,63,75,85, +95,101,111,125,115,125,53,109,119,81,79,2,78,56,36,14,10,5,5,15, +1,22,102,66,50,34,94,38,30,8,14,14,106,66,38,20,52,22,8,4, +8,1,78,34,16,2,32,12,1,6,18,90,54,32,20,62,28,26,24,16, +124,23,5,16,5,9,2,18,20,6,20,34,48,25,15,27,21,44,35,37, +23,3,32,65,45,12,24,57,67,55,9,1,30,7,4,1,10,28,29,9, +7,10,49,19,33,29,20,75,25,8,13,42,15,3,64,15,21,3,54,49, +31,85,24,52,52,26,7,26,18,4,8,2,3,9,45,55,69,51,41,67, +113,63,57,57,47,41,15,13,43,65,19,19,21,13,35,73,41,47,83,57, +73,71,105,97,81,67,41,29,65,45,53,71,83,87,87,87,93,101,125,111, +125,125,119,101,121,123,11,22,6,22,32,32,124,54,50,9,70,124,124,124, +44,14,3,83,125,125,125,125,125,125,5,86,52,34,18,28,4,7,9,3, +1,10,36,18,58,40,22,38,40,46,48,24,52,40,3,20,4,25,39,53, +65,123,119,91,0,0,0,0,36,6,39,36,6,39,40,56,56,24,17,77, +15,0,102,28,112,17,48,62,3,43,4,75,109,13,47,125,125,125,124,38, +13,48,62,3,9,38,40,17,6,0,0,19,49,15,61,10,7,1,11,35, +17,49,34,8,2,3,24,4,44,0,0,0,14,69,67,24,33,15,36,5, +47,36,98,74,124,124,58,56,38,70,30,18,46,15,21,23,11,52,2,18, +5,3,3,0,12,11,29,27,47,36,9,12,1,31,6,17,14,6,3,8, +20,6,11,5,10,7,0,13,9,25,1,9,31,6,9,23,0,22,7,43, +25,31,33,8,9,16,14,14,78,36,8,11,24,11,35,0,87,19,1,53, +15,47,8,1,35,36,14,8,71,8,43,23,6,65,4,34,20,28,34,26, +12,32,24,9,1,18,0,1,23,11,23,21,13,19,29,29,27,31,25,11, +55,67,35,37,39,47,49,65,75,65,65,83,97,83,89,125,109,115,13,21, +61,29,45,51,63,79,87,67,75,65,45,55,55,39,35,10,50,36,22,16, +20,10,0,10,24,26,60,42,30,16,44,26,32,18,68,4,86,60,44,28, +52,10,1,3,6,13,92,34,0,2,22,0,17,1,10,68,38,6,5,34, +10,4,4,4,124,7,10,12,24,14,14,38,40,28,38,48,58,5,8,25, +5,70,15,61,9,16,7,35,43,25,45,63,79,83,15,7,30,13,25,9, +3,4,33,21,9,9,49,23,37,0,20,49,21,10,31,2,25,9,40,31, +39,3,8,51,47,115,20,32,50,3,17,7,35,35,35,61,59,57,93,77, +57,95,101,109,125,93,87,71,33,47,12,46,6,46,86,35,41,51,47,93, +73,61,109,69,91,81,117,105,99,99,41,35,105,47,51,75,99,87,89,91, +81,99,95,101,111,125,111,25,41,75,7,26,18,40,42,50,94,60,82,82, +122,100,90,124,120,76,11,53,93,115,125,125,125,125,30,98,84,84,60,86, +42,32,42,22,13,0,32,6,68,88,2,20,38,46,10,42,78,8,3,26, +43,93,125,125,125,125,125,125,0,0,0,0,34,6,39,34,6,39,44,60, +58,26,17,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,44,0,0,0,16,69,67,26, +33,15,104,10,11,21,2,37,22,42,38,62,20,48,38,28,56,13,29,19, +35,74,4,50,1,6,9,8,56,13,29,11,3,40,5,18,12,15,20,7, +16,26,16,32,46,40,43,15,8,7,4,15,20,19,3,38,15,30,34,8, +95,18,15,81,37,81,9,18,4,24,12,12,56,16,4,32,56,19,17,10, +101,27,18,63,2,29,44,4,55,68,2,3,75,74,41,79,2,89,19,18, +28,12,18,10,7,18,32,61,23,12,4,2,37,21,29,41,23,39,61,27, +31,123,67,43,79,69,51,6,26,2,5,3,29,45,29,61,71,53,87,111, +107,125,43,43,75,67,79,89,99,105,115,125,119,125,53,111,121,81,79,4, +80,58,38,16,10,5,3,13,0,24,104,68,52,34,96,40,32,10,16,16, +108,68,40,22,54,24,10,6,12,0,82,36,18,4,34,14,0,10,20,92, +56,34,22,64,30,28,26,18,124,21,3,18,5,7,2,20,22,8,22,36, +50,23,15,27,21,46,35,37,25,3,32,67,47,12,24,57,69,55,7,0, +32,5,6,0,12,30,29,7,5,12,49,17,31,27,22,75,25,10,13,44, +15,3,66,15,21,1,56,49,31,85,24,52,52,26,9,26,18,4,8,2, +3,9,45,57,71,53,43,69,115,65,59,57,47,41,13,11,41,65,17,23, +25,17,39,77,45,51,87,61,77,75,109,101,83,67,43,31,67,47,57,75, +87,91,91,91,97,105,125,113,125,125,121,103,123,125,7,26,10,24,34,34, +124,56,52,9,72,124,124,124,46,12,5,87,125,125,125,125,125,125,3,88, +52,34,18,30,4,7,9,1,0,12,38,20,62,42,24,40,42,48,50,26, +54,42,3,18,2,27,41,55,67,125,121,91,0,0,0,0,34,6,39,34, +6,39,44,60,58,26,17,79,17,1,102,28,118,17,50,64,3,43,6,77, +111,13,49,125,125,125,124,42,13,50,64,3,7,42,42,17,8,2,2,19, +49,13,61,10,5,0,11,35,15,49,36,10,4,1,26,4,44,0,0,0, +16,69,67,26,33,15,36,3,45,40,102,78,124,124,62,58,42,74,34,20, +50,13,19,21,9,54,4,20,3,1,1,2,16,11,29,27,47,38,9,14, +0,29,8,15,16,6,3,10,20,6,9,5,12,7,0,11,9,25,1,9, +33,6,9,23,2,24,5,43,25,29,33,8,9,18,14,14,80,38,10,11, +26,11,35,0,87,19,1,53,15,49,8,1,35,38,16,8,73,8,43,21, +6,65,4,34,20,28,34,26,12,32,24,9,1,18,0,1,23,11,23,21, +13,19,29,29,27,29,25,9,55,69,33,39,41,49,51,69,79,67,67,87, +99,85,91,125,111,117,13,21,61,31,47,53,65,81,89,69,77,65,45,55, +53,37,33,12,52,36,22,18,22,12,2,12,28,28,60,42,30,16,46,28, +34,20,72,4,88,62,44,28,54,10,1,1,8,13,94,34,0,2,24,2, +15,0,10,68,38,6,5,34,10,6,6,6,124,5,12,14,28,18,16,42, +44,32,42,52,62,3,10,23,3,74,13,61,7,18,5,35,43,25,45,63, +81,85,15,7,32,13,25,9,3,4,33,21,9,9,49,23,37,2,22,49, +21,10,31,2,25,9,42,31,41,3,8,51,47,117,20,32,50,5,19,9, +39,39,39,65,63,61,97,81,59,99,107,115,125,97,91,73,35,49,12,48, +8,50,92,37,43,53,49,97,75,63,113,71,93,83,119,107,101,99,41,35, +107,49,53,77,101,89,91,93,83,101,97,103,113,125,111,25,41,75,5,28, +20,42,44,52,98,62,84,84,124,104,92,124,124,76,13,57,97,119,125,125, +125,125,32,100,86,86,62,88,44,34,44,24,11,2,34,8,72,92,4,22, +40,48,12,44,80,8,3,24,47,97,125,125,125,125,125,125,0,0,0,0, +32,6,39,32,6,39,48,62,58,26,17,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, +44,0,0,0,18,69,67,26,35,15,104,10,11,19,4,37,22,44,42,66, +22,50,42,30,60,11,27,17,33,76,4,52,0,6,9,10,60,13,29,11, +1,40,5,18,14,15,22,7,16,26,16,34,46,40,45,15,8,7,4,15, +20,19,5,38,17,30,34,8,99,18,15,85,39,83,7,20,6,26,14,14, +58,18,4,34,58,19,17,10,103,27,20,63,2,29,46,4,57,70,2,3, +77,76,43,81,2,91,23,16,26,10,16,8,9,16,32,63,25,12,4,2, +37,23,31,43,25,41,63,29,33,125,69,45,81,71,51,2,24,1,9,7, +33,49,33,67,75,57,93,117,111,125,47,47,79,71,83,93,103,109,119,125, +123,125,55,115,123,83,79,4,80,58,38,16,10,5,3,13,2,24,104,68, +52,34,98,40,34,10,18,18,110,70,40,22,56,24,10,8,14,2,84,38, +18,4,36,16,2,12,20,92,56,34,22,66,32,30,28,20,124,21,3,18, +5,7,2,20,22,8,22,36,52,23,15,27,23,46,37,39,27,5,32,69, +49,12,24,59,71,57,5,2,34,5,6,0,14,32,29,7,5,12,51,17, +31,27,24,75,25,10,13,46,15,3,68,15,21,1,58,51,31,87,22,52, +52,24,11,24,16,2,6,0,5,11,47,59,73,57,45,73,119,67,61,59, +49,41,13,11,41,67,15,27,29,21,43,83,49,55,93,65,81,79,113,105, +85,69,47,35,69,51,61,79,91,95,95,95,101,109,125,117,125,125,123,107, +125,125,5,28,12,26,36,36,124,58,54,9,74,124,124,124,48,10,9,93, +125,125,125,125,125,125,3,88,52,34,18,30,4,7,9,0,2,14,40,22, +64,44,26,42,44,50,52,26,56,42,3,16,1,31,45,59,71,125,125,93, +0,0,0,0,32,6,39,32,6,39,48,62,58,26,17,81,19,3,102,28, +122,17,52,66,3,45,6,79,113,15,53,125,125,125,124,44,13,52,66,3, +7,44,42,19,8,2,4,19,49,13,61,10,5,2,11,35,15,49,36,10, +4,1,26,4,44,0,0,0,18,69,67,26,35,15,36,3,45,44,106,82, +124,124,64,60,44,76,36,22,54,13,19,21,7,54,4,20,1,1,0,2, +18,11,29,27,47,38,9,14,0,29,8,15,16,6,3,10,20,6,9,5, +12,7,0,11,11,25,1,11,35,4,11,25,4,24,5,45,27,29,35,8, +9,18,14,14,82,38,10,11,26,11,37,0,89,19,1,55,15,51,8,1, +37,38,16,8,75,8,45,21,6,67,2,34,20,28,34,26,12,32,24,9, +1,18,0,1,23,11,23,21,13,19,31,31,29,29,25,9,57,71,33,43, +45,53,55,73,83,71,71,91,103,89,95,125,115,119,13,21,63,33,49,55, +67,85,91,71,79,67,47,57,53,37,31,12,52,36,22,18,22,12,2,12, +30,30,60,42,30,16,46,28,36,22,76,4,88,62,44,28,54,10,1,1, +10,13,94,34,0,2,24,2,15,2,10,66,36,4,7,34,10,6,6,6, +124,3,14,16,30,20,18,44,46,34,44,54,66,1,12,23,1,76,13,63, +7,20,5,35,45,25,47,65,83,87,17,7,32,13,27,11,3,4,35,23, +9,9,51,23,37,2,22,49,23,8,33,2,27,11,42,33,43,3,8,53, +49,121,18,30,48,7,21,11,43,43,43,69,69,67,103,85,61,105,113,121, +125,103,95,77,37,51,12,50,8,52,96,41,47,57,53,101,79,67,117,73, +97,85,123,109,103,101,43,35,109,51,55,81,105,93,95,95,87,105,99,105, +115,125,113,27,43,77,5,28,20,44,44,54,100,64,86,86,124,106,94,124, +124,74,17,61,101,125,125,125,125,125,32,100,86,86,62,90,44,34,44,24, +11,2,36,8,74,94,4,24,42,50,12,44,82,8,3,22,51,101,125,125, +125,125,125,125,0,0,0,0,30,6,39,30,6,39,52,66,60,26,19,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,44,0,0,0,18,69,67,28,37,15,104,10, +11,17,6,37,24,46,46,70,26,52,46,32,64,9,25,15,31,78,4,54, +2,6,7,10,64,13,27,9,0,40,5,20,18,13,24,7,16,26,16,36, +48,42,45,15,8,7,4,15,20,21,5,38,19,30,34,8,103,18,17,89, +41,85,5,22,8,28,16,14,60,18,6,36,60,19,17,10,105,25,22,63, +2,29,48,4,59,72,2,3,79,78,43,83,2,93,25,14,26,8,14,6, +9,14,30,65,27,12,4,2,39,25,33,45,27,43,65,31,33,125,71,45, +83,73,51,0,20,3,13,11,37,53,37,71,81,61,97,121,117,125,51,51, +81,75,87,99,109,113,125,125,125,125,57,119,125,85,79,4,82,58,38,16, +10,5,3,13,2,24,104,68,52,34,100,42,34,12,18,20,112,70,42,22, +58,26,12,8,16,4,86,40,20,4,38,18,4,14,22,92,56,34,22,68, +32,32,30,22,124,19,1,20,5,7,2,20,22,8,22,36,52,23,15,27, +23,48,39,41,29,7,32,71,51,12,24,59,73,57,3,4,36,3,8,2, +14,34,29,7,5,14,51,17,31,25,26,75,25,10,13,48,15,3,70,15, +21,1,60,53,31,89,20,50,50,22,13,22,14,0,4,1,7,13,49,61, +75,59,47,75,123,71,63,61,49,43,13,11,41,67,13,31,33,25,47,89, +53,59,97,69,85,83,119,109,89,71,51,37,73,55,65,83,95,99,99,99, +105,113,125,121,125,125,125,111,125,125,3,30,14,28,38,38,124,60,56,9, +76,124,124,124,50,6,11,97,125,125,125,125,125,125,3,88,52,34,18,30, +4,7,9,0,4,16,42,24,66,44,26,44,44,50,52,26,56,42,3,14, +3,35,49,63,75,125,125,95,0,0,0,0,30,6,39,30,6,39,52,66, +60,26,19,85,23,5,102,28,124,17,54,68,3,47,6,81,115,15,57,125, +125,125,124,46,13,54,68,3,5,46,44,19,8,4,6,21,51,13,61,10, +5,2,11,35,15,49,38,10,4,1,28,4,44,0,0,0,18,69,67,28, +37,15,36,3,45,48,110,84,124,124,66,62,48,78,38,24,58,11,19,19, +5,54,4,20,1,1,0,4,22,11,31,29,49,38,9,14,2,29,10,15, +18,6,3,10,20,4,9,5,12,7,0,11,13,25,1,13,37,2,13,27, +4,26,5,47,27,27,35,8,9,18,14,14,84,38,10,11,28,11,39,0, +91,19,1,55,17,53,8,1,39,38,16,8,79,8,47,21,6,67,0,34, +20,28,34,26,12,32,24,9,3,18,0,1,23,13,25,23,15,21,33,33, +29,29,27,9,59,75,33,45,49,57,59,77,87,75,75,95,107,91,97,125, +119,121,13,21,63,35,51,57,71,87,95,73,81,69,47,57,53,37,31,14, +52,36,22,18,22,12,2,14,32,30,60,42,30,16,48,30,38,24,80,4, +88,62,44,28,56,10,1,1,10,13,94,34,1,2,24,2,15,4,10,66, +36,2,9,34,10,6,8,8,124,1,16,16,32,22,20,48,48,36,46,58, +68,1,14,23,1,80,13,63,7,20,5,37,45,25,49,67,85,89,17,9, +32,15,27,11,5,4,37,23,11,9,53,23,39,2,22,51,23,8,35,2, +29,11,42,35,45,5,6,55,49,123,16,28,48,9,23,15,47,47,47,75, +73,71,109,91,63,111,119,125,125,109,101,81,39,53,12,52,8,54,100,45, +51,61,57,105,83,69,121,77,99,87,125,113,105,103,43,37,111,53,59,83, +109,97,99,99,89,109,103,107,119,125,115,29,45,79,5,30,20,44,46,54, +102,66,88,88,124,108,96,124,124,74,19,65,107,125,125,125,125,125,34,102, +88,88,62,92,46,34,46,26,11,4,36,10,76,96,4,24,42,50,12,46, +84,8,3,20,55,107,125,125,125,125,125,125,0,0,0,0}, +/*cabac_init_idc = 1*/ +{124,18,21,124,18,21,125,81,20,18,24,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, +44,0,0,0,39,45,67,17,44,2,104,16,11,125,77,37,21,87,125,125, +125,63,125,101,125,119,103,117,103,0,9,41,81,13,59,53,125,21,67,55, +125,14,37,25,123,59,47,27,15,0,9,41,2,3,4,14,5,1,4,29, +26,22,56,38,50,36,34,38,92,24,26,88,60,2,89,73,75,55,61,49, +41,45,39,47,61,13,17,21,8,77,73,63,23,17,23,15,34,11,2,3, +52,17,12,18,2,17,124,108,76,90,108,88,52,90,68,60,66,36,10,2, +4,50,36,48,42,38,36,44,28,58,42,16,24,34,51,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,92,124,120,82,124,124,124,124,120,116,124, +94,82,30,52,6,9,67,15,42,26,18,2,10,0,17,21,55,7,72,48, +38,34,1,9,29,27,45,57,16,6,2,3,19,25,33,49,93,67,41,31, +19,21,45,65,67,107,29,60,30,20,2,15,31,45,53,67,124,59,41,31, +5,15,2,6,8,23,2,10,5,31,15,9,38,2,54,46,72,68,38,54, +62,42,30,2,34,1,81,67,65,49,43,43,43,49,5,27,25,25,10,25, +39,71,63,63,25,21,13,23,9,3,19,2,2,9,23,16,1,13,114,88, +94,98,100,104,96,94,80,80,86,74,38,46,32,92,84,82,72,68,56,26, +12,0,27,37,61,11,91,124,124,124,124,124,124,124,124,124,124,124,122,100, +56,10,124,124,66,124,124,124,120,124,116,104,116,102,104,68,74,48,5,84, +64,26,113,97,101,43,57,51,15,35,33,9,13,14,9,26,21,124,124,124, +124,120,114,58,18,37,23,80,58,40,18,16,4,1,9,57,85,67,53,53, +49,19,31,45,19,13,11,5,1,10,8,124,124,124,124,120,108,86,54,7, +0,0,0,0,124,18,21,124,18,21,125,81,20,18,24,76,124,124,108,44, +109,3,15,31,22,26,13,18,58,82,124,122,54,11,125,75,25,15,31,22, +11,53,22,40,11,37,65,8,23,47,73,14,21,43,8,35,45,63,5,27, +13,45,17,4,44,0,0,0,39,45,67,17,44,2,96,24,33,125,55,65, +35,69,77,67,111,71,93,77,125,33,51,61,57,48,3,41,125,19,81,55, +125,16,14,16,4,20,9,21,49,79,55,51,57,25,47,93,83,29,97,71, +125,125,125,125,5,29,15,17,8,16,13,23,51,111,23,86,82,125,18,4, +10,6,4,7,41,21,3,22,12,4,11,13,16,15,10,4,44,76,62,40, +32,38,24,34,50,5,50,42,58,51,36,70,64,124,124,96,124,124,124,124, +124,124,124,124,124,124,106,124,124,124,124,124,124,124,112,124,124,124,54,124, +124,124,124,124,124,124,124,124,124,124,106,90,76,44,23,17,27,56,64,56, +66,36,42,36,74,18,5,14,19,7,105,97,15,4,20,5,27,33,41,47, +125,75,48,20,4,23,27,55,87,95,117,25,38,22,12,10,17,11,11,21, +45,5,58,62,64,22,16,7,19,51,22,118,110,110,88,52,4,19,13,29, +124,125,121,93,125,121,83,115,107,77,107,105,117,63,73,63,95,101,51,33, +37,43,35,17,1,7,14,11,11,11,11,7,27,1,4,7,1,12,3,5, +2,24,5,15,23,13,17,6,52,32,56,52,44,44,30,44,44,8,26,46, +5,26,124,124,124,124,124,124,124,124,124,124,124,124,124,124,108,124,124,124, +124,124,124,124,124,124,98,74,52,16,3,124,124,124,124,124,124,124,124,124, +124,124,124,86,66,38,30,28,36,82,82,84,86,70,78,58,42,48,26,13, +18,15,39,62,28,18,43,35,27,35,33,19,21,39,15,7,4,5,5,8, +8,124,124,124,124,124,120,106,72,12,15,78,54,42,22,12,0,3,7,37, +35,25,17,29,17,9,13,25,5,2,12,4,6,18,10,124,124,124,124,124, +120,106,72,12,0,0,0,0,124,18,21,124,18,21,123,77,22,20,24,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,44,0,0,0,37,45,67,15,44,2,104,16, +11,123,75,37,19,83,123,123,123,59,123,97,123,115,101,115,101,2,7,39, +79,11,57,51,123,19,65,53,123,16,35,23,119,57,45,25,13,2,7,39, +4,1,4,14,3,1,4,27,26,22,56,38,50,36,34,38,90,24,26,86, +58,2,87,71,73,53,59,47,39,43,37,45,57,13,17,19,6,75,71,63, +21,17,21,13,34,9,2,3,50,15,12,16,2,17,124,108,76,90,108,88, +52,90,68,58,66,36,10,2,4,50,36,48,42,38,34,44,28,56,40,16, +22,32,51,124,124,124,124,124,124,124,124,124,124,124,124,124,120,88,124,118, +80,124,124,124,124,116,112,122,90,78,30,50,4,9,67,13,44,28,20,4, +10,0,15,19,53,5,74,50,40,34,0,7,27,25,43,55,18,8,4,1, +17,23,31,47,89,65,37,29,17,19,43,63,65,103,27,62,32,22,4,13, +29,43,51,65,124,57,39,29,5,13,2,8,10,21,4,12,3,29,15,9, +38,4,54,46,70,68,38,52,60,42,30,2,32,1,79,65,63,47,41,41, +41,47,5,25,23,23,10,23,37,69,61,63,25,19,13,21,9,3,17,2, +2,7,21,16,1,13,114,88,94,98,98,104,96,94,80,80,86,74,38,44, +30,90,82,80,70,66,54,26,12,0,25,35,59,11,89,124,124,124,124,124, +124,124,124,124,124,122,118,96,54,10,124,124,64,124,124,124,116,124,112,100, +112,98,100,66,70,46,7,82,62,24,109,93,97,41,55,49,11,33,31,9, +11,18,5,30,19,124,124,124,124,116,110,54,14,39,21,82,58,40,18,18, +4,1,9,55,83,65,51,51,45,17,29,43,17,11,9,3,0,12,8,124, +124,124,124,118,106,82,52,7,0,0,0,0,124,18,21,124,18,21,123,77, +22,20,24,74,122,124,110,44,105,3,13,29,22,26,11,18,56,80,122,116, +50,13,121,73,23,13,29,22,11,51,22,40,9,35,63,8,23,45,71,14, +19,41,8,33,43,61,3,25,13,43,15,4,44,0,0,0,37,45,67,15, +44,2,96,24,33,121,51,61,31,63,73,63,107,67,89,73,121,33,49,59, +55,48,3,39,121,17,79,53,123,16,14,16,4,22,9,19,47,77,53,49, +55,23,45,89,79,27,93,67,117,117,119,121,3,27,13,15,8,18,11,21, +49,105,21,82,80,121,18,6,10,8,6,5,37,19,1,22,12,4,9,11, +14,13,10,4,44,74,62,40,32,38,24,34,48,3,50,42,58,51,36,70, +64,124,124,94,124,124,124,122,124,124,124,124,124,124,104,124,124,124,124,124, +124,124,108,124,120,124,52,124,124,124,124,124,124,124,124,124,124,122,104,88, +74,42,23,17,27,56,62,54,64,34,40,34,72,16,5,12,19,7,103,93, +13,6,20,3,25,31,39,45,121,71,50,22,6,21,25,51,83,91,113,23, +40,24,14,12,15,9,9,19,43,5,60,62,64,22,18,5,19,49,22,118, +110,108,86,52,6,17,11,27,124,121,117,89,121,117,79,111,103,73,103,101, +111,61,71,61,91,97,49,31,35,41,33,15,1,7,14,11,11,11,9,5, +25,0,4,5,0,12,1,3,2,24,3,13,21,11,15,6,50,32,54,52, +44,44,30,44,44,8,26,44,5,24,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,104,124,124,124,124,124,124,124,122,124,96,72,50,16,3,124, +124,124,124,124,124,124,124,124,124,124,124,84,64,36,30,28,34,80,80,82, +82,68,76,56,40,46,24,13,16,15,39,60,26,16,41,33,25,33,29,15, +19,37,13,5,6,3,3,8,8,124,124,124,124,120,112,98,64,8,13,78, +56,44,24,14,2,1,5,35,33,23,15,27,15,7,11,23,3,4,12,6, +8,18,10,124,124,124,124,120,112,98,64,8,0,0,0,0,124,18,21,124, +18,21,119,75,22,20,24,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,44,0,0,0, +35,45,67,15,42,2,104,16,11,121,73,37,19,81,119,119,121,57,119,95, +119,113,99,113,99,4,7,37,77,11,57,49,119,19,65,53,121,16,35,23, +117,57,43,25,13,2,7,37,4,1,2,14,3,1,4,27,26,22,54,38, +48,36,34,38,86,24,26,82,56,0,85,69,71,51,57,45,37,41,37,43, +55,13,17,19,4,75,69,63,21,17,19,13,32,7,2,3,48,13,10,14, +2,19,120,106,74,88,106,86,50,88,68,56,64,36,10,2,4,48,34,46, +40,36,32,42,26,52,38,14,20,30,51,124,124,124,124,124,124,124,124,124, +124,124,124,124,116,82,124,114,76,124,124,124,124,112,108,116,86,74,28,46, +2,11,67,13,44,28,20,4,10,0,15,19,51,5,74,50,40,34,2,7, +25,25,41,53,20,10,4,1,15,23,31,45,87,63,35,27,17,19,41,61, +63,101,27,62,32,22,4,11,27,41,49,63,124,57,39,29,5,13,2,8, +10,21,4,12,1,29,15,9,36,4,52,44,68,66,38,50,58,42,30,0, +30,3,77,63,61,47,41,41,39,45,5,25,23,23,8,23,37,69,59,63, +25,19,13,19,9,3,15,2,2,7,19,14,1,15,112,88,94,96,96,102, +94,92,78,78,84,72,36,42,28,86,80,76,66,64,52,24,10,0,25,35, +59,13,87,124,124,124,124,124,124,124,124,124,124,118,114,92,52,8,124,120, +62,124,124,124,112,120,108,96,108,94,96,62,66,42,9,78,58,20,107,91, +95,39,53,47,7,31,29,9,9,20,3,32,17,124,124,124,124,110,104,48, +10,41,21,82,58,40,18,18,4,1,9,53,81,63,49,49,43,15,27,41, +15,9,7,3,2,12,8,124,124,124,122,114,102,78,48,9,0,0,0,0, +124,18,21,124,18,21,119,75,22,20,24,72,118,122,110,44,101,3,13,27, +22,24,11,16,52,78,116,108,44,17,115,71,23,13,27,22,11,49,22,38, +9,35,61,8,23,45,71,14,19,41,8,33,43,61,3,25,13,43,15,4, +44,0,0,0,35,45,67,15,42,2,94,24,33,117,49,59,27,59,71,61, +103,65,87,71,117,33,49,59,55,48,3,37,117,17,77,51,119,16,14,16, +2,22,9,19,45,75,51,47,53,23,43,87,77,25,91,65,107,109,113,115, +3,27,13,15,8,18,11,21,49,101,21,78,76,115,18,6,10,8,6,5, +33,17,1,22,12,4,7,9,12,13,10,4,42,72,60,40,30,38,24,34, +46,3,48,40,56,51,36,68,62,124,124,92,120,124,124,118,124,124,124,124, +124,124,100,124,124,124,124,124,124,124,104,124,116,124,48,124,124,124,124,124, +124,124,124,124,124,118,100,84,70,38,23,17,29,54,60,52,62,32,38,32, +68,14,5,10,21,9,101,91,11,6,20,3,23,29,37,43,117,69,50,22, +6,19,23,49,79,87,109,21,42,26,16,14,13,9,9,19,41,5,62,62, +62,22,18,5,19,49,22,118,108,106,84,52,6,17,11,27,124,119,115,87, +117,113,77,107,99,71,99,97,107,59,69,61,89,93,49,31,35,39,33,15, +1,7,12,11,11,11,9,5,23,0,4,5,0,12,1,3,2,22,3,13, +21,11,13,4,48,32,52,50,42,42,30,42,42,8,26,42,5,22,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,100,124,124,124,124,124,124,124, +118,118,92,68,48,14,5,124,124,124,124,124,124,124,124,124,124,124,124,80, +60,32,28,26,30,78,78,78,78,64,72,52,38,42,22,15,14,17,41,56, +24,14,41,33,23,33,27,13,19,35,11,3,6,3,1,8,8,124,124,124, +124,114,104,90,56,2,13,78,56,44,24,16,2,1,5,35,33,23,15,27, +13,5,11,23,3,4,12,6,10,18,10,124,124,124,124,114,104,90,56,2, +0,0,0,0,124,18,21,124,18,21,115,71,24,20,22,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,44,0,0,0,35,45,67,13,40,2,104,16,11,119,71,37, +17,79,115,115,117,55,115,93,115,111,97,111,97,6,7,35,75,11,55,49, +115,19,63,51,119,16,35,21,113,55,41,25,13,2,7,35,6,0,2,14, +3,1,4,27,26,20,54,38,46,36,34,38,82,24,24,78,54,1,83,67, +69,49,55,45,35,41,35,41,53,13,17,19,2,73,67,63,21,17,17,13, +30,5,2,3,46,11,10,12,2,21,118,104,74,86,104,84,50,86,66,54, +62,36,10,2,2,46,32,44,38,34,30,40,26,48,36,14,18,28,51,124, +124,124,124,124,124,124,124,124,124,124,124,124,110,78,124,110,74,124,122,124, +118,108,102,112,82,68,26,42,0,13,67,13,46,28,20,4,10,0,15,19, +51,5,74,50,40,34,4,5,25,23,41,51,22,10,6,1,13,21,29,45, +85,61,33,25,15,19,39,59,61,99,25,62,32,22,4,9,27,39,47,61, +124,55,37,27,5,13,2,8,10,21,4,12,1,29,15,9,36,6,50,42, +66,64,38,48,56,42,30,0,28,3,75,61,59,45,39,39,39,43,5,25, +23,21,8,23,37,67,57,63,25,19,13,17,9,3,13,2,2,7,17,12, +1,17,110,86,92,94,94,100,92,90,76,76,82,70,34,40,26,84,78,74, +62,60,50,22,10,1,25,35,59,13,85,124,124,124,124,124,124,124,124,124, +124,114,108,88,48,6,122,118,58,124,124,120,108,116,104,92,104,90,90,58, +62,38,11,74,54,18,105,89,93,37,51,45,5,29,27,9,7,24,0,36, +15,124,124,124,124,104,98,42,6,43,21,82,58,40,18,18,4,1,9,53, +79,61,47,47,41,15,27,39,15,9,7,3,2,12,8,124,124,124,118,110, +98,74,44,11,0,0,0,0,124,18,21,124,18,21,115,71,24,20,22,68, +114,120,110,44,97,3,11,25,22,24,11,16,50,76,112,102,40,19,109,69, +23,11,25,22,13,47,22,38,9,35,61,8,23,45,71,14,19,39,8,33, +41,61,3,25,13,43,15,4,44,0,0,0,35,45,67,13,40,2,92,22, +33,111,47,57,25,55,67,57,99,61,85,69,113,33,49,57,55,48,3,35, +113,17,75,51,115,16,12,14,2,22,9,17,45,73,49,47,51,21,41,83, +73,25,89,63,97,99,107,109,3,27,13,13,8,18,9,19,47,97,21,74, +72,109,18,6,10,8,6,3,31,15,1,22,12,4,7,7,10,13,10,2, +42,70,60,40,30,38,24,34,44,3,46,38,56,51,36,68,62,124,124,90, +116,124,124,114,124,124,124,124,124,122,96,124,124,124,124,124,124,120,100,124, +112,124,44,124,124,124,124,124,124,124,124,124,124,114,96,80,68,34,23,17, +29,52,58,50,60,30,36,30,64,12,7,8,23,9,101,87,9,8,20,3, +21,29,37,43,113,67,50,22,8,17,21,47,77,85,105,19,42,26,16,14, +11,7,9,19,41,5,62,62,60,22,18,5,19,47,22,116,108,104,82,52, +6,17,11,27,124,117,111,85,115,111,75,103,95,69,97,93,103,59,67,59, +87,89,47,31,35,39,31,15,1,7,12,11,11,13,7,3,21,0,4,3, +0,12,1,3,2,22,3,13,21,11,13,2,46,32,50,48,40,42,30,40, +40,8,26,40,5,20,124,124,122,124,124,124,124,124,124,124,124,124,124,124, +96,124,124,124,124,124,124,124,114,114,88,64,44,12,7,124,124,124,124,124, +124,124,124,124,124,118,120,76,56,30,26,24,28,74,74,74,74,62,68,48, +36,40,20,17,12,19,43,54,22,12,41,31,23,31,25,11,19,35,11,3, +6,1,0,8,8,124,124,124,118,108,96,82,48,3,13,78,56,44,24,16, +4,1,5,33,33,23,13,25,11,3,11,21,3,4,12,6,10,18,10,124, +124,124,118,108,96,82,48,3,0,0,0,0,124,18,21,124,18,21,113,69, +24,20,22,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,44,0,0,0,33,47,67,13, +38,2,104,16,11,117,69,37,17,75,113,111,115,53,113,89,111,109,97,109, +97,6,7,33,73,11,55,47,111,19,63,51,117,16,33,21,111,55,41,25, +11,2,7,35,6,0,0,12,3,1,4,27,26,20,52,38,46,36,34,36, +78,24,24,74,52,3,81,65,67,47,55,43,33,39,35,39,51,13,17,17, +0,73,65,63,21,17,17,13,28,3,2,3,42,9,8,10,2,23,114,102, +72,84,102,82,48,84,66,50,60,34,10,2,2,44,32,42,38,32,28,38, +24,44,34,12,16,26,51,124,124,124,124,124,124,124,124,124,124,124,124,118, +106,72,124,108,70,124,118,124,114,102,98,106,78,64,24,40,3,15,67,13, +46,30,20,4,10,0,15,19,49,3,76,50,40,34,6,5,23,23,39,51, +24,12,6,1,13,21,29,43,83,61,31,25,15,19,37,57,61,97,25,64, +32,22,4,7,25,39,45,59,124,55,37,27,5,13,2,8,10,19,4,12, +0,29,15,9,34,6,48,40,64,62,38,44,54,40,30,1,26,5,75,61, +57,45,39,39,37,41,7,25,23,21,6,23,37,67,55,63,25,17,13,17, +9,3,11,2,0,7,15,12,3,19,108,86,92,92,92,98,90,88,74,74, +80,68,32,38,24,80,74,70,58,58,48,20,8,1,25,35,59,15,85,124, +124,124,124,124,124,124,124,124,120,110,104,84,46,4,118,114,56,124,124,116, +104,110,100,88,100,86,86,54,58,34,13,70,50,14,103,87,91,37,49,43, +1,27,25,9,5,26,2,38,15,124,124,124,124,98,92,36,2,45,21,82, +58,40,18,18,4,1,9,51,77,59,45,47,39,13,25,37,13,7,5,1, +4,14,8,124,124,124,114,106,94,70,40,13,0,0,0,0,124,18,21,124, +18,21,113,69,24,20,22,66,110,118,110,42,93,3,11,23,20,22,11,14, +46,74,106,94,34,23,103,67,23,11,23,20,13,45,22,36,9,33,59,8, +23,45,71,14,19,39,8,33,41,59,3,25,13,43,13,4,44,0,0,0, +33,47,67,13,38,2,90,22,33,107,45,55,21,51,65,55,97,59,81,67, +109,33,47,57,55,48,3,33,109,17,75,49,111,16,12,14,0,22,9,17, +43,71,47,45,49,21,41,81,71,23,87,61,87,91,101,103,3,25,13,13, +8,18,9,19,47,93,21,70,68,105,18,8,10,8,6,3,27,13,0,20, +12,4,5,7,8,13,10,2,40,68,58,38,28,38,24,34,42,3,44,36, +54,51,34,66,60,124,124,88,112,124,124,110,124,124,124,124,124,118,92,118, +124,124,124,124,124,114,96,124,108,124,42,124,124,124,124,124,124,124,124,124, +120,110,92,76,64,30,23,17,31,50,56,48,56,28,32,28,62,10,7,6, +23,11,99,85,7,8,20,1,21,27,35,41,109,63,50,24,8,17,19,45, +73,81,103,19,44,28,18,16,9,7,9,17,39,5,64,62,60,20,18,5, +19,47,22,116,106,102,80,52,6,15,11,27,124,113,109,83,111,107,73,101, +93,67,93,91,99,57,65,59,85,87,47,31,35,37,31,15,3,7,10,11, +11,13,7,3,19,0,4,3,0,12,1,3,2,20,3,13,21,11,11,0, +44,32,48,48,38,40,30,38,38,8,26,38,5,18,124,124,120,124,124,124, +124,124,124,124,124,124,124,124,92,124,124,124,124,124,124,124,108,108,84,60, +42,10,7,124,124,124,124,124,124,124,124,124,124,114,114,72,52,26,24,24, +24,72,72,72,70,58,64,46,34,36,18,19,8,21,43,50,18,8,39,31, +21,31,23,9,19,33,9,1,6,1,2,8,8,124,124,124,112,100,88,72, +40,9,11,78,56,44,24,18,4,1,5,33,33,23,13,25,11,1,11,21, +1,6,12,6,12,18,10,124,124,124,112,100,88,72,40,9,0,0,0,0, +124,18,21,124,18,21,109,65,24,20,20,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, +44,0,0,0,33,47,67,11,36,2,104,16,11,115,67,37,15,73,109,107, +111,51,109,87,107,107,95,107,95,8,7,31,71,11,53,45,107,19,63,49, +113,18,33,19,109,53,39,25,11,4,5,33,8,2,0,12,3,1,4,27, +26,18,50,38,44,36,34,36,74,24,22,72,50,5,79,63,65,45,53,41, +31,37,33,37,49,13,17,17,1,71,63,63,19,17,15,13,26,1,2,3, +40,7,8,8,2,23,112,100,72,82,100,80,46,84,66,48,58,34,10,2, +0,44,30,40,36,30,26,38,22,40,32,10,14,24,51,124,124,124,124,124, +124,124,124,124,124,124,124,114,102,68,120,104,66,124,114,120,110,98,94,100, +74,58,22,36,5,15,67,13,46,30,20,4,10,0,15,19,49,3,76,50, +40,34,8,3,21,23,37,49,26,14,6,0,11,19,27,43,81,59,27,23, +15,17,35,55,59,95,23,64,34,22,4,5,23,37,43,57,124,55,37,25, +5,13,2,8,10,19,4,14,0,29,15,9,32,8,46,38,62,62,38,42, +52,40,30,3,24,5,73,59,55,43,37,37,37,39,7,25,23,21,4,23, +37,65,53,63,25,17,13,15,9,3,9,2,0,7,13,10,3,19,106,86, +90,92,90,96,88,86,74,72,78,66,30,36,22,78,72,68,54,56,46,18, +6,3,25,33,59,15,83,124,124,124,124,124,124,124,124,120,116,106,100,80, +42,2,114,110,54,122,124,112,100,106,96,84,96,82,80,50,54,30,15,66, +46,12,101,83,89,35,47,41,2,25,23,9,3,30,6,42,13,124,124,124, +124,94,86,32,1,47,21,82,58,40,18,18,4,1,9,51,75,57,43,45, +37,11,25,35,11,5,3,1,4,14,8,124,124,124,112,102,90,66,36,15, +0,0,0,0,124,18,21,124,18,21,109,65,24,20,20,64,106,116,110,42, +89,3,11,21,20,22,11,12,42,72,102,88,30,27,97,65,21,11,21,20, +13,43,22,36,9,33,57,8,23,45,71,14,19,39,8,33,39,59,3,25, +13,43,13,4,44,0,0,0,33,47,67,11,36,2,88,20,33,101,43,53, +17,47,61,51,93,55,79,65,103,33,47,55,53,48,3,31,105,17,73,49, +107,16,10,12,0,22,9,15,43,69,45,45,47,19,39,77,67,21,83,59, +77,83,95,97,1,25,11,11,8,18,7,19,45,89,21,66,64,99,18,8, +10,8,6,1,25,11,0,20,12,4,5,5,6,11,10,0,40,66,58,38, +28,38,24,34,40,1,42,36,54,51,34,64,58,124,124,86,110,124,124,106, +124,124,124,124,122,114,88,114,124,120,124,124,124,110,92,124,104,124,38,124, +124,124,124,124,124,124,124,122,116,106,88,74,60,26,23,17,31,48,54,46, +54,26,30,26,58,8,9,4,25,13,97,81,5,10,20,1,19,27,35,39, +105,61,50,24,10,15,17,43,71,79,99,17,46,30,20,16,7,5,7,17, +39,5,64,62,58,20,18,5,19,45,22,114,104,100,78,52,6,15,11,25, +124,111,105,79,107,105,71,97,89,65,89,87,95,55,63,57,83,83,47,31, +33,37,29,15,3,7,10,11,11,15,5,3,17,0,4,3,0,12,1,3, +2,20,3,13,21,11,11,1,42,32,46,46,38,38,30,38,36,8,26,36, +5,16,124,124,118,124,124,124,124,124,124,124,124,124,124,124,88,124,124,124, +124,124,124,122,104,104,80,58,38,10,9,124,124,124,124,124,124,124,124,124, +122,110,108,68,48,24,24,22,20,70,68,68,66,54,60,42,32,34,16,19, +6,23,45,48,16,6,39,31,19,29,21,7,17,31,9,1,6,0,4,8, +8,124,124,118,106,94,80,64,32,15,11,78,56,44,24,18,4,0,3,31, +33,23,11,25,9,0,11,21,1,6,12,8,12,18,10,124,124,118,106,94, +80,64,32,15,0,0,0,0,124,18,23,124,18,23,105,63,26,20,20,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,44,0,0,0,31,47,67,11,36,0,104,16, +11,113,67,37,15,71,105,103,109,49,105,85,103,105,93,105,93,10,7,29, +71,9,53,45,103,19,61,49,111,18,33,19,105,53,37,23,11,4,5,31, +8,2,1,12,3,1,4,27,26,18,50,38,42,36,34,36,70,24,22,68, +48,7,79,61,65,45,51,41,29,37,33,37,45,13,17,17,3,71,61,63, +19,17,13,11,24,1,2,3,38,5,6,6,2,25,108,98,70,82,98,80, +46,82,64,46,56,34,10,2,0,42,28,38,34,30,24,36,22,36,30,10, +12,22,51,124,124,124,124,124,124,124,124,124,124,124,124,108,96,62,116,100, +64,124,108,114,104,94,88,96,68,54,20,32,7,17,67,11,48,30,22,4, +10,0,15,19,47,3,76,52,40,34,10,3,21,21,37,47,28,14,8,0, +9,19,27,41,79,57,25,21,13,17,35,55,57,91,23,64,34,22,6,5, +23,35,43,55,124,53,35,25,5,13,2,8,10,19,6,14,2,29,15,11, +32,8,44,36,60,60,38,40,50,40,30,3,22,7,71,57,53,43,37,37, +35,39,7,23,21,19,4,23,37,65,51,63,25,17,13,13,9,3,7,0, +0,7,13,8,3,21,104,84,90,90,88,96,88,84,72,72,76,64,28,34, +20,74,70,64,50,52,42,16,6,3,25,33,57,17,81,124,124,124,124,124, +124,124,124,116,110,102,94,76,40,2,112,108,50,118,124,108,96,102,92,80, +90,78,76,46,50,28,19,62,42,8,99,81,87,33,45,39,4,23,21,9, +1,32,8,44,11,124,124,124,118,88,82,26,5,51,19,82,58,40,18,18, +4,1,9,49,73,57,41,43,35,11,23,33,11,5,3,1,6,14,8,124, +124,122,108,100,88,60,34,17,0,0,0,0,124,18,23,124,18,23,105,63, +26,20,20,60,102,114,110,42,87,3,9,21,20,20,9,12,40,68,96,80, +24,29,93,63,21,9,21,20,15,43,22,34,9,33,57,8,23,43,69,14, +17,37,8,31,39,59,3,25,13,43,13,4,44,0,0,0,31,47,67,11, +36,0,88,20,33,97,41,51,15,41,59,49,89,53,77,63,99,33,47,55, +53,48,3,29,99,17,71,47,103,14,10,12,1,24,9,15,41,69,45,43, +45,19,37,75,65,21,81,57,67,73,89,91,1,25,11,11,8,18,7,17, +45,85,19,62,60,93,18,8,10,8,8,1,21,9,0,20,12,4,3,3, +4,11,10,0,38,64,56,38,26,38,24,34,36,1,40,34,52,51,34,64, +58,124,124,84,106,124,124,102,124,124,124,124,114,110,86,110,124,116,124,124, +124,104,88,124,100,124,34,124,124,124,124,124,124,124,124,118,112,100,84,70, +58,24,23,17,33,46,52,44,52,24,28,24,54,6,9,2,27,13,97,79, +3,10,20,1,17,25,33,39,101,59,52,24,10,13,15,41,67,75,95,15, +46,30,20,18,5,5,7,17,37,5,66,62,56,20,18,5,19,45,20,114, +104,98,76,50,6,15,11,25,124,109,103,77,105,101,69,93,85,63,87,83, +91,55,61,57,81,79,45,31,33,35,29,15,3,7,8,11,11,15,5,1, +15,0,4,1,2,12,0,1,2,18,3,13,21,11,9,3,40,32,44,44, +36,38,30,36,36,8,24,32,7,14,124,124,116,124,124,124,124,124,124,124, +124,124,124,124,84,124,124,124,124,124,124,116,100,98,76,54,36,8,11,124, +124,124,124,124,124,124,124,122,116,104,102,64,46,20,22,20,18,66,66,64, +62,52,56,38,30,30,14,21,4,25,47,44,14,4,39,29,19,29,19,5, +17,31,7,0,6,0,6,8,8,124,124,114,100,88,72,56,24,21,11,78, +56,44,24,20,6,0,3,31,31,21,11,23,7,2,9,19,1,6,12,8, +14,18,10,124,124,114,100,88,72,56,24,21,0,0,0,0,124,18,23,124, +18,23,101,59,26,20,18,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,44,0,0,0, +31,47,67,9,34,0,104,16,11,111,65,37,13,67,103,99,105,47,103,81, +99,103,91,103,93,12,7,27,69,9,51,43,99,19,61,47,109,18,31,17, +103,51,37,23,9,4,5,29,10,4,1,10,3,1,4,27,26,16,48,38, +42,36,34,34,66,24,20,64,46,9,77,59,63,43,49,39,27,35,31,35, +43,13,17,15,5,69,59,63,19,17,13,11,22,0,2,3,34,3,6,4, +2,27,106,96,70,80,96,78,44,80,64,44,54,34,10,2,1,40,28,36, +34,28,22,34,20,32,28,8,10,20,51,124,124,124,124,124,124,124,124,124, +124,120,122,104,92,58,112,98,60,124,104,110,100,88,84,90,64,48,18,30, +11,19,67,11,48,32,22,4,10,0,15,19,47,1,78,52,40,34,12,1, +19,21,35,45,30,16,8,0,7,17,25,41,77,57,23,21,13,17,33,53, +57,89,21,66,34,22,6,3,21,33,41,53,124,53,35,23,5,13,2,8, +10,17,6,14,2,29,15,11,30,10,42,34,58,58,38,38,48,38,30,5, +20,7,69,57,51,41,35,35,35,37,7,23,21,19,2,23,37,63,49,63, +25,15,13,13,9,3,5,0,0,7,11,8,5,23,102,84,88,88,86,94, +86,82,70,70,74,62,26,32,18,72,66,62,46,50,40,14,4,5,25,33, +57,17,79,124,124,124,124,124,124,124,122,112,106,98,90,72,36,0,108,104, +48,114,124,104,92,98,88,76,86,74,70,42,46,24,21,58,38,6,97,79, +85,33,43,37,8,21,19,9,0,36,12,48,11,124,124,122,112,82,76,20, +9,53,19,82,58,40,18,18,4,1,9,49,71,55,39,41,33,9,23,31, +9,3,1,0,6,16,8,124,124,118,104,96,84,56,30,19,0,0,0,0, +124,18,23,124,18,23,101,59,26,20,18,58,98,112,110,42,83,3,9,19, +18,20,9,10,36,66,92,74,20,33,87,61,21,9,19,18,15,41,22,34, +9,31,55,8,23,43,69,14,17,37,8,31,37,57,3,25,13,43,11,4, +44,0,0,0,31,47,67,9,34,0,86,18,33,91,39,49,11,37,55,45, +87,49,73,61,95,33,45,53,53,48,3,27,95,17,69,47,99,14,8,10, +1,24,9,13,41,67,43,43,43,17,35,71,61,19,79,55,57,65,83,85, +1,23,11,9,8,18,5,17,43,81,19,58,56,87,18,10,10,8,8,0, +19,7,2,18,12,4,3,3,2,11,10,1,38,62,56,36,26,38,24,34, +34,1,38,32,52,51,34,62,56,120,124,82,102,124,124,98,124,122,124,124, +108,106,82,104,124,110,124,124,124,98,84,124,96,124,32,124,124,124,124,124, +124,124,124,114,106,96,80,66,54,20,23,17,33,44,50,42,48,22,26,22, +52,4,11,0,27,15,95,75,1,12,20,0,17,25,33,37,97,55,52,26, +12,13,13,39,65,73,91,15,48,32,22,18,3,3,7,15,37,5,66,62, +56,18,18,5,19,43,20,112,102,96,74,50,6,13,11,25,124,105,99,75, +101,99,67,91,83,61,83,81,87,53,59,55,79,75,45,31,33,35,27,15, +5,7,8,11,11,17,3,1,13,0,4,1,2,12,0,1,2,18,3,13, +21,11,9,5,38,32,42,44,34,36,30,34,34,8,24,30,7,12,122,124, +114,124,124,124,124,124,124,124,124,124,124,124,80,124,124,124,124,124,124,112, +96,94,72,50,32,6,11,124,124,124,124,124,124,124,124,118,112,100,96,60, +42,18,20,20,14,64,62,62,58,48,52,36,28,28,12,23,0,27,47,42, +10,0,37,29,17,27,17,3,17,29,7,0,6,2,8,8,8,124,124,108, +94,80,64,48,16,27,9,78,56,44,24,20,6,0,3,29,31,21,9,23, +5,4,9,19,0,8,12,8,14,18,10,124,124,108,94,80,64,48,16,27, +0,0,0,0,124,16,23,124,16,23,99,57,26,20,18,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,44,0,0,0,29,49,67,9,32,0,104,16,11,109,63,37, +13,65,99,95,103,45,99,79,97,101,91,101,91,12,7,25,67,9,51,43, +97,19,61,47,107,18,31,17,101,51,35,23,9,4,5,29,10,4,3,10, +3,1,4,27,26,16,46,38,40,36,34,34,62,24,20,60,44,11,75,57, +61,41,49,39,25,35,31,33,41,13,17,15,9,69,57,63,19,19,11,11, +20,2,2,3,32,1,4,2,2,29,102,94,68,78,94,76,42,78,62,40, +52,32,10,2,1,38,26,34,32,26,20,32,18,28,24,6,8,18,51,124, +124,124,124,124,124,124,124,124,122,116,116,98,86,52,108,94,56,122,100,104, +94,84,78,84,60,44,16,26,13,21,69,11,48,32,22,4,10,0,15,19, +45,1,78,52,40,34,14,1,19,21,35,45,32,16,8,0,7,17,25,39, +75,55,21,19,13,17,31,51,55,87,21,66,34,22,6,1,21,33,39,53, +124,53,35,23,5,13,2,8,10,17,6,14,4,29,15,11,28,10,40,32, +56,56,38,34,44,38,30,7,18,9,69,55,49,41,35,35,33,35,9,23, +21,19,0,23,37,63,49,65,25,15,13,11,9,3,5,0,1,7,9,6, +5,25,100,82,88,86,82,92,84,80,68,68,72,60,24,30,16,68,64,58, +42,46,38,12,2,5,25,33,57,19,79,124,124,124,124,124,124,122,116,108, +102,94,84,68,34,1,104,100,44,110,122,98,86,92,82,72,82,68,66,38, +40,20,23,54,34,2,95,77,83,31,41,37,10,19,19,9,0,38,14,50, +9,124,124,116,106,76,70,14,13,55,19,82,58,40,18,18,4,1,9,47, +71,53,37,41,31,9,21,31,9,3,1,0,8,16,6,124,124,114,100,92, +80,52,26,21,0,0,0,0,124,16,23,124,16,23,99,57,26,20,18,54, +92,110,110,40,79,5,9,17,18,18,9,8,32,64,86,66,14,37,81,59, +21,9,17,18,17,39,22,32,9,31,55,6,25,43,69,14,17,37,8,31, +37,57,3,25,13,43,11,4,44,0,0,0,29,49,67,9,32,0,84,18, +35,87,37,47,9,33,53,43,83,47,71,59,91,33,45,53,53,48,3,25, +91,17,69,45,95,14,8,10,3,24,9,13,39,65,41,41,43,17,35,69, +59,19,77,53,49,57,77,81,1,23,11,9,6,18,5,17,43,77,19,54, +52,83,18,10,10,8,8,0,15,7,2,18,10,4,1,1,1,11,10,1, +36,58,54,36,24,38,24,32,32,1,36,30,50,51,32,60,54,116,124,78, +98,124,124,92,124,118,124,124,100,102,78,100,124,106,124,124,124,92,80,124, +92,124,28,124,124,124,124,124,124,124,120,110,102,92,76,62,50,16,23,19, +35,42,46,40,46,20,22,18,48,2,11,1,29,17,95,73,0,12,20,0, +15,23,31,37,93,53,52,26,12,11,11,37,61,69,89,13,48,32,22,20, +1,3,7,15,35,7,68,62,54,18,18,5,19,43,20,112,100,94,72,50, +6,13,11,25,124,103,97,73,99,95,65,87,79,59,81,77,83,53,59,55, +77,73,45,31,33,33,27,15,5,7,6,11,11,17,3,1,11,0,2,1, +2,10,0,1,2,16,3,13,21,11,7,7,36,32,38,42,32,34,28,32, +32,8,24,28,7,8,120,120,112,124,124,124,124,124,124,124,124,124,124,120, +76,124,124,124,124,124,124,106,90,88,68,46,30,4,13,124,124,124,124,124, +124,124,124,112,106,94,90,56,38,14,18,18,10,60,60,58,54,44,48,32, +24,24,8,25,1,29,49,38,8,1,37,29,17,27,15,1,17,29,5,2, +6,2,8,8,6,124,120,102,88,74,56,38,6,33,9,78,56,44,24,22, +6,0,3,29,31,21,9,23,5,4,9,19,0,8,12,8,16,18,8,124, +120,102,88,74,56,38,6,33,0,0,0,0,124,16,23,124,16,23,95,55, +28,20,18,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,44,0,0,0,27,49,67,9, +30,0,104,16,11,107,61,37,13,63,95,91,99,41,95,77,93,99,89,99, +89,14,5,23,65,9,49,41,93,19,59,47,103,20,31,17,97,51,33,23, +9,6,3,27,10,4,3,10,1,1,4,25,26,16,46,38,38,36,34,34, +58,24,20,58,42,11,73,55,59,39,47,37,23,33,31,31,39,13,17,15, +11,67,55,63,17,19,9,11,18,4,2,3,30,0,2,0,2,29,100,92, +68,76,92,74,42,78,62,38,50,32,10,2,1,38,24,32,30,24,18,32, +18,26,22,6,6,16,51,124,124,124,124,124,124,124,124,124,118,112,112,92, +82,46,106,90,54,118,96,100,90,80,74,80,56,40,16,22,15,21,69,11, +50,32,22,6,10,0,13,19,43,1,78,52,42,34,16,0,17,19,33,43, +34,18,10,2,5,15,25,37,73,53,17,17,11,15,29,49,53,85,19,66, +36,24,6,0,19,31,37,51,124,51,33,21,5,13,2,10,12,17,6,16, +6,29,15,11,28,10,38,32,54,56,38,32,42,38,30,7,16,11,67,53, +47,41,33,35,31,33,9,23,21,17,0,23,37,63,47,65,25,15,13,9, +9,3,3,0,1,7,7,4,5,25,98,82,88,86,80,90,82,78,68,66, +70,60,24,28,14,66,62,54,38,44,36,12,2,5,23,31,57,21,77,124, +124,124,124,124,124,118,112,104,98,90,80,64,32,3,100,98,42,106,118,94, +82,88,78,68,78,64,62,36,36,16,25,50,30,1,93,73,79,29,39,35, +14,17,17,9,2,42,16,54,7,124,124,112,100,72,64,10,17,57,19,82, +58,40,18,20,4,1,9,45,69,51,35,39,27,7,19,29,7,1,0,0, +10,16,6,124,122,112,98,88,76,48,22,21,0,0,0,0,124,16,23,124, +16,23,95,55,28,20,18,52,88,108,112,40,75,5,7,15,18,16,9,8, +30,62,82,58,8,39,75,57,19,7,15,18,17,37,22,32,7,31,53,6, +25,43,69,14,17,35,8,31,37,57,3,25,13,41,11,4,44,0,0,0, +27,49,67,9,30,0,82,18,35,83,33,45,5,29,49,41,79,43,69,55, +85,33,45,53,51,48,3,23,87,15,67,43,91,14,8,10,3,24,9,13, +37,63,39,39,41,15,33,67,55,17,73,51,39,47,69,75,0,23,9,7, +6,18,5,15,41,71,19,50,50,77,18,10,10,8,8,2,11,5,2,18, +10,4,0,0,3,9,10,1,34,56,52,36,22,38,24,32,30,0,34,30, +48,51,32,60,54,112,124,76,96,124,124,88,120,114,124,124,94,98,74,96, +124,102,124,124,124,88,76,124,88,124,24,124,124,124,124,124,124,120,116,106, +98,88,74,60,48,12,23,19,35,42,44,38,44,18,20,16,44,0,11,3, +31,17,93,71,2,12,20,0,13,21,29,35,87,51,52,26,12,9,9,35, +57,65,85,11,50,34,24,22,0,3,5,15,33,7,70,62,52,18,20,3, +19,41,20,112,100,92,70,50,6,13,11,23,124,101,95,69,95,91,63,83, +75,57,77,73,79,51,57,53,75,69,43,29,31,31,25,15,5,7,4,11, +11,17,3,0,9,2,2,0,2,10,0,1,2,14,3,11,19,11,5,7, +34,32,36,40,32,34,28,32,30,8,24,26,7,6,118,118,112,122,124,124, +124,124,124,124,124,124,124,114,72,124,124,124,124,124,124,100,86,84,66,44, +28,4,15,124,124,124,124,124,124,124,124,108,102,90,86,52,34,10,18,16, +8,58,58,54,50,42,46,28,22,20,6,25,3,29,51,34,6,3,37,27, +15,27,13,2,15,27,3,4,6,4,10,8,6,124,116,98,82,68,48,30, +1,39,9,78,56,46,26,24,8,2,1,29,31,21,9,21,3,6,9,17, +0,8,12,10,18,18,8,124,116,98,82,68,48,30,1,39,0,0,0,0, +124,16,23,124,16,23,91,51,28,20,16,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, +44,0,0,0,27,49,67,7,28,0,104,16,11,105,59,37,11,59,93,87, +97,39,93,73,89,97,87,97,89,16,5,21,63,9,49,39,89,19,59,45, +101,20,29,15,95,49,33,23,7,6,3,25,12,6,5,8,1,1,4,25, +26,14,44,38,38,36,34,32,54,24,18,54,40,13,71,53,57,37,45,35, +21,31,29,29,37,13,17,13,13,67,53,63,17,19,9,11,16,6,2,3, +26,2,2,1,2,31,96,90,66,74,90,72,40,76,62,36,48,32,10,2, +3,36,24,30,30,22,16,30,16,22,20,4,4,14,51,124,124,124,124,124, +124,124,124,124,114,108,106,88,78,42,102,88,50,112,92,96,86,74,70,74, +52,34,14,20,19,23,69,11,50,34,22,6,10,0,13,19,43,0,80,52, +42,34,18,0,15,19,31,41,36,20,10,2,3,15,23,37,71,53,15,17, +11,15,27,47,53,83,19,68,36,24,6,2,17,29,35,49,124,51,33,21, +5,13,2,10,12,15,6,16,6,29,15,11,26,12,36,30,52,54,38,30, +40,36,30,9,14,11,65,53,45,39,33,33,31,31,9,23,21,17,1,23, +37,61,45,65,25,13,13,9,9,3,1,0,1,7,5,4,7,27,96,82, +86,84,78,88,80,76,66,64,68,58,22,26,12,62,58,52,34,42,34,10, +0,7,23,31,57,21,75,124,124,124,124,124,120,114,106,100,94,86,76,60, +28,5,96,94,40,102,114,90,78,84,74,64,74,60,56,32,32,12,27,46, +26,3,91,71,77,29,37,33,18,15,15,9,4,44,20,56,7,124,120,106, +94,66,58,4,21,59,19,82,58,40,18,20,4,1,9,45,67,49,33,37, +25,5,19,27,5,0,2,2,10,18,6,120,118,108,94,84,72,44,18,23, +0,0,0,0,124,16,23,124,16,23,91,51,28,20,16,50,84,106,112,40, +71,5,7,13,16,16,9,6,26,60,76,52,4,43,69,55,19,7,13,16, +17,35,22,30,7,29,51,6,25,43,69,14,17,35,8,31,35,55,3,25, +13,41,9,4,44,0,0,0,27,49,67,7,28,0,80,16,35,77,31,43, +1,25,47,37,77,41,65,53,81,33,43,51,51,48,3,21,83,15,65,43, +87,14,6,8,5,24,9,11,37,61,37,39,39,15,31,63,53,15,71,49, +29,39,63,69,0,21,9,7,6,18,3,15,41,67,19,46,46,71,18,12, +10,8,8,2,9,3,4,16,10,4,0,0,5,9,10,3,34,54,52,34, +22,38,24,32,28,0,32,28,48,51,32,58,52,108,124,74,92,124,124,84, +114,110,124,124,86,94,70,90,122,96,124,124,124,82,72,116,84,124,22,124, +124,124,124,124,120,116,112,102,92,84,70,56,44,8,23,19,37,40,42,36, +40,16,18,14,42,1,13,5,31,19,91,67,4,14,20,2,13,21,29,33, +83,47,52,28,14,9,7,33,55,63,81,11,52,36,26,22,2,1,5,13, +33,7,70,62,52,16,20,3,19,41,20,110,98,90,68,50,6,11,11,23, +124,97,91,67,91,89,61,81,73,55,73,71,75,49,55,53,73,65,43,29, +31,31,25,15,7,7,4,11,11,19,1,0,7,2,2,0,2,10,0,1, +2,14,3,11,19,11,5,9,32,32,34,40,30,32,28,30,28,8,24,24, +7,4,116,116,110,118,120,124,124,124,124,124,124,124,124,110,68,124,124,124, +124,124,124,96,82,78,62,40,24,2,15,124,124,124,124,124,124,124,124,104, +96,86,80,48,30,8,16,16,4,56,54,52,46,38,42,26,20,18,4,27, +7,31,51,32,2,7,35,27,13,25,11,4,15,25,3,4,6,4,12,8, +6,124,112,92,76,60,40,22,9,45,7,78,56,46,26,24,8,2,1,27, +31,21,7,21,1,8,9,17,2,10,12,10,18,18,8,124,112,92,76,60, +40,22,9,45,0,0,0,0,124,16,25,124,16,25,87,49,30,20,16,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,44,0,0,0,25,49,67,7,28,1,104,16, +11,103,59,37,11,57,89,83,93,37,89,71,85,95,85,95,87,18,5,19, +63,7,47,39,85,19,57,45,99,20,29,15,91,49,31,21,7,6,3,23, +12,6,5,8,1,1,4,25,26,14,44,38,36,36,34,32,50,24,18,50, +38,15,71,51,57,37,43,35,19,31,29,29,33,13,17,13,15,65,51,63, +17,19,7,9,14,6,2,3,24,4,0,3,2,33,94,88,66,74,88,72, +40,74,60,34,46,32,10,2,3,34,22,28,28,22,14,28,16,18,18,4, +2,12,51,124,124,124,124,124,124,124,124,124,108,104,102,82,72,36,98,84, +48,108,86,90,80,70,64,70,46,30,12,16,21,25,69,9,52,34,24,6, +10,0,13,19,41,0,80,54,42,34,20,2,15,17,31,39,38,20,12,2, +1,13,23,35,69,51,13,15,9,15,27,47,51,79,17,68,36,24,8,2, +17,27,35,47,124,49,31,19,5,13,2,10,12,15,8,16,8,29,15,13, +26,12,34,28,50,52,38,28,38,36,30,9,12,13,63,51,43,39,31,33, +29,31,9,21,19,15,1,23,37,61,43,65,25,13,13,7,9,3,0,1, +1,7,5,2,7,29,94,80,86,82,76,88,80,74,64,64,66,56,20,24, +10,60,56,48,30,38,30,8,0,7,23,31,55,23,73,124,124,124,124,124, +116,110,102,96,88,82,70,56,26,5,94,92,36,98,108,86,74,80,70,60, +68,56,52,28,28,10,31,42,22,7,89,69,75,27,35,31,20,13,13,9, +6,48,22,60,5,122,118,102,88,60,54,1,25,63,17,82,58,40,18,20, +4,1,9,43,65,49,31,35,23,5,17,25,5,0,2,2,12,18,6,118, +116,104,90,82,70,38,16,25,0,0,0,0,124,16,25,124,16,25,87,49, +30,20,16,46,80,104,112,40,69,5,5,13,16,14,7,6,24,56,72,44, +1,45,65,53,19,5,13,16,19,35,22,30,7,29,51,6,25,41,67,14, +15,33,8,29,35,55,3,25,13,41,9,4,44,0,0,0,25,49,67,7, +28,1,80,16,35,73,29,41,0,19,43,35,73,37,63,51,77,33,43,51, +51,48,3,19,77,15,63,41,83,12,6,8,5,26,9,11,35,61,37,37, +37,13,29,61,49,15,69,47,19,29,57,63,0,21,9,5,6,18,3,13, +39,63,17,42,42,65,18,12,10,8,10,4,5,1,4,16,10,4,2,2, +7,9,10,3,32,52,50,34,20,38,24,32,24,0,30,26,46,51,32,58, +52,104,124,72,88,122,124,80,110,106,124,124,80,90,68,86,114,92,124,124, +124,76,68,110,80,124,18,124,124,124,124,124,116,110,108,98,88,78,66,52, +42,6,23,19,37,38,40,34,38,14,16,12,38,3,13,7,33,19,91,65, +6,14,20,2,11,19,27,33,79,45,54,28,14,7,5,31,51,59,77,9, +52,36,26,24,4,1,5,13,31,7,72,62,50,16,20,3,19,39,18,110, +98,88,66,48,6,11,11,23,124,95,89,65,89,85,59,77,69,53,71,67, +71,49,53,51,71,61,41,29,31,29,23,15,7,7,2,11,11,19,1,2, +5,2,2,2,4,10,2,0,2,12,3,11,19,11,3,11,30,32,32,38, +28,32,28,28,28,8,22,20,9,2,112,114,108,116,116,124,124,124,124,124, +124,124,124,104,64,124,124,124,124,124,124,90,78,74,58,36,22,0,17,124, +124,124,124,124,124,120,118,98,92,80,74,44,28,4,14,14,2,52,52,48, +42,36,38,22,18,14,2,29,9,33,53,28,0,9,35,25,13,25,9,6, +15,25,1,6,6,6,14,8,6,124,108,88,70,54,32,14,17,51,7,78, +56,46,26,26,10,2,1,27,29,19,7,19,0,10,7,15,2,10,12,10, +20,18,8,124,108,88,70,54,32,14,17,51,0,0,0,0,124,16,25,124, +16,25,85,45,30,20,14,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,44,0,0,0, +25,51,67,5,26,1,104,16,11,101,57,37,9,55,85,79,91,35,85,69, +81,93,85,93,85,18,5,17,61,7,47,37,81,19,57,43,97,20,29,13, +89,47,29,21,7,6,3,23,14,8,7,8,1,1,4,25,26,12,42,38, +34,36,34,32,46,24,16,46,36,17,69,49,55,35,43,33,17,29,27,27, +31,13,17,13,17,65,49,63,17,19,5,9,12,8,2,3,22,6,0,5, +2,35,90,86,64,72,86,70,38,72,60,30,44,30,10,2,5,32,20,26, +26,20,12,26,14,14,16,2,0,10,51,124,124,122,124,124,124,124,124,122, +104,100,96,78,68,32,94,80,44,104,82,86,76,66,60,64,42,24,10,12, +23,27,69,9,52,34,24,6,10,0,13,19,41,0,80,54,42,34,22,2, +13,17,29,39,40,22,12,2,1,13,21,35,67,49,11,13,9,15,25,45, +49,77,17,68,36,24,8,4,15,27,33,45,124,49,31,19,5,13,2,10, +12,15,8,16,8,29,15,13,24,14,32,26,48,50,38,24,36,36,30,11, +10,13,63,49,41,37,31,31,29,29,11,21,19,15,3,23,37,59,41,65, +25,13,13,5,9,3,2,1,3,7,3,0,7,31,92,80,84,80,74,86, +78,72,62,62,64,54,18,22,8,56,54,46,26,36,28,6,1,9,23,31, +55,23,73,124,124,124,124,124,112,106,96,92,84,78,66,52,22,7,90,88, +34,94,104,82,70,74,66,56,64,52,46,24,24,6,33,38,18,9,87,67, +73,25,33,29,24,11,11,9,8,50,26,62,3,118,114,96,82,54,48,7, +29,65,17,82,58,40,18,20,4,1,9,43,63,47,29,35,21,3,17,23, +3,2,4,2,12,18,6,116,112,100,86,78,66,34,12,27,0,0,0,0, +124,16,25,124,16,25,85,45,30,20,14,44,76,102,112,38,65,5,5,11, +16,14,7,4,20,54,66,38,5,49,59,51,19,5,11,16,19,33,22,28, +7,29,49,6,25,41,67,14,15,33,8,29,33,55,3,25,13,41,9,4, +44,0,0,0,25,51,67,5,26,1,78,14,35,67,27,39,4,15,41,31, +69,35,61,49,73,33,43,49,51,48,3,17,73,15,63,41,79,12,4,6, +7,26,9,9,35,59,35,37,35,13,29,57,47,13,67,45,9,21,51,57, +0,21,9,5,6,18,1,13,39,59,17,38,38,61,18,12,10,8,10,4, +3,0,4,16,10,4,2,4,9,9,10,5,32,50,50,34,20,38,24,32, +22,0,28,24,46,51,30,56,50,100,124,70,84,118,120,76,104,102,124,124, +72,86,64,82,108,86,116,124,124,70,64,102,76,124,14,124,124,124,124,124, +112,106,104,94,84,74,62,48,38,2,23,19,39,36,38,32,36,12,12,10, +34,5,15,9,35,21,89,61,8,16,20,2,9,19,27,31,75,43,54,28, +16,5,3,29,49,57,75,7,54,38,28,24,6,0,5,13,31,7,72,62, +48,16,20,3,19,39,18,108,96,86,64,48,6,11,11,23,124,93,85,63, +85,83,57,73,65,51,67,63,67,47,51,51,69,59,41,29,31,29,23,15, +7,7,2,11,11,21,0,2,3,2,2,2,4,10,2,0,2,12,3,11, +19,11,3,13,28,32,30,36,26,30,28,26,26,8,22,18,9,0,110,112, +106,112,112,124,122,124,124,124,124,124,122,100,60,124,124,124,124,124,118,86, +72,68,54,32,18,1,19,124,124,124,124,124,124,114,112,94,86,76,68,40, +24,2,12,12,1,50,48,44,38,32,34,18,16,12,0,31,11,35,55,26, +1,11,35,25,11,23,7,8,15,23,1,6,6,6,16,8,6,122,104,82, +64,48,24,4,25,57,7,78,56,46,26,26,10,2,1,25,29,19,5,19, +0,12,7,15,2,10,12,10,20,18,8,122,104,82,64,48,24,4,25,57, +0,0,0,0,124,16,25,124,16,25,81,43,30,20,14,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,44,0,0,0,23,51,67,5,24,1,104,16,11,99,55,37, +9,51,83,75,87,33,83,65,77,91,83,91,85,20,5,15,59,7,45,35, +77,19,57,43,93,22,27,13,87,47,29,21,5,8,1,21,14,8,7,6, +1,1,4,25,26,12,40,38,34,36,34,30,42,24,16,44,34,19,67,47, +53,33,41,31,15,27,27,25,29,13,17,11,19,63,47,63,15,19,5,9, +10,10,2,3,18,8,1,7,2,35,88,84,64,70,84,68,36,72,60,28, +42,30,10,2,5,32,20,24,26,18,10,26,12,10,14,0,1,8,51,122, +124,118,124,122,120,120,120,118,100,96,92,72,64,26,90,78,40,98,78,82, +72,60,56,58,38,20,8,10,27,27,69,9,52,36,24,6,10,0,13,19, +39,2,82,54,42,34,24,4,11,17,27,37,42,24,12,4,0,11,21,33, +65,49,7,13,9,13,23,43,49,75,15,70,38,24,8,6,13,25,31,43, +124,49,31,17,5,13,2,10,12,13,8,18,10,29,15,13,22,14,30,24, +46,50,38,22,34,34,30,13,8,15,61,49,39,37,29,31,27,27,11,21, +19,15,5,23,37,59,39,65,25,11,13,5,9,3,4,1,3,7,1,0, +9,31,90,80,84,80,72,84,76,70,62,60,62,52,16,20,6,54,50,42, +22,34,26,4,3,9,23,29,55,25,71,124,124,124,124,120,108,102,92,88, +80,74,62,48,20,9,86,84,32,90,100,78,66,70,62,52,60,48,42,20, +20,2,35,34,14,13,85,63,71,25,31,27,28,9,9,9,10,54,28,66, +3,116,110,92,76,50,42,11,33,67,17,82,58,40,18,20,4,1,9,41, +61,45,27,33,19,1,15,21,1,4,6,4,14,20,6,112,110,98,84,74, +62,30,8,29,0,0,0,0,124,16,25,124,16,25,81,43,30,20,14,42, +72,100,112,38,61,5,5,9,14,12,7,2,16,52,62,30,11,53,53,49, +17,5,9,14,19,31,22,28,7,27,47,6,25,41,67,14,15,33,8,29, +33,53,3,25,13,41,7,4,44,0,0,0,23,51,67,5,24,1,76,14, +35,63,25,37,8,11,37,29,67,31,57,47,67,33,41,49,49,48,3,15, +69,15,61,39,75,12,4,6,7,26,9,9,33,57,33,35,33,11,27,55, +43,11,63,43,0,13,45,51,2,19,7,3,6,18,1,13,37,55,17,34, +34,55,18,14,10,8,10,6,0,2,6,14,10,4,4,4,11,7,10,5, +30,48,48,32,18,38,24,32,20,2,26,24,44,51,30,54,48,96,124,68, +82,114,116,72,100,98,124,124,66,82,60,76,102,82,110,124,124,66,60,96, +72,124,12,124,124,124,122,120,108,102,100,90,78,70,58,46,34,1,23,19, +39,34,36,30,32,10,10,8,32,7,15,11,35,23,87,59,10,16,20,4, +9,17,25,29,71,39,54,30,16,5,1,27,45,53,71,7,56,40,30,26, +8,0,3,11,29,7,74,62,48,14,20,3,19,37,18,108,94,84,62,48, +6,9,11,21,124,89,83,59,81,79,55,71,63,49,63,61,63,45,49,49, +67,55,41,29,29,27,21,15,9,7,0,11,11,21,0,2,1,2,2,2, +4,10,2,0,2,10,3,11,19,11,1,15,26,32,28,36,26,28,28,26, +24,8,22,16,9,1,108,110,104,108,108,124,118,122,124,118,124,124,116,94, +56,124,124,124,124,118,112,80,68,64,50,30,16,1,19,124,124,124,124,118, +118,110,106,90,82,72,62,36,20,1,12,12,5,48,46,42,34,28,30,16, +14,8,1,31,15,37,55,22,5,15,33,25,9,23,5,10,13,21,0,8, +6,8,18,8,6,120,100,76,58,40,16,3,33,63,5,78,56,46,26,28, +10,4,0,25,29,19,5,19,2,14,7,15,4,12,12,12,22,18,8,120, +100,76,58,40,16,3,33,63,0,0,0,0,122,16,25,122,16,25,77,39, +32,20,12,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,44,0,0,0,23,51,67,3, +22,1,104,16,11,97,53,37,7,49,79,71,85,31,79,63,73,89,81,89, +83,22,5,13,57,7,45,35,73,19,55,41,91,22,27,11,83,45,27,21, +5,8,1,19,16,10,9,6,1,1,4,25,26,10,40,38,32,36,34,30, +38,24,14,40,32,21,65,45,51,31,39,31,13,27,25,23,27,13,17,11, +21,63,45,63,15,19,3,9,8,12,2,3,16,10,1,9,2,37,84,82, +62,68,82,66,36,70,58,26,40,30,10,2,7,30,18,22,24,16,8,24, +12,6,12,0,3,6,51,120,122,116,124,118,116,116,116,112,94,92,86,68, +58,22,86,74,38,94,74,76,66,56,50,54,34,14,6,6,29,29,69,9, +54,36,24,6,10,0,13,19,39,2,82,54,42,34,26,4,11,15,27,35, +44,24,14,4,2,11,19,33,63,47,5,11,7,13,21,41,47,73,15,70, +38,24,8,8,13,23,29,41,124,47,29,17,5,13,2,10,12,13,8,18, +10,29,15,13,22,16,28,22,44,48,38,20,32,34,30,13,6,15,59,47, +37,35,29,29,27,25,11,21,19,13,5,23,37,57,37,65,25,11,13,3, +9,3,6,1,3,7,0,1,9,33,88,78,82,78,70,82,74,68,60,58, +60,50,14,18,4,50,48,40,18,30,24,2,3,11,23,29,55,25,69,124, +124,122,122,114,104,98,86,84,76,70,56,44,16,11,82,82,28,86,96,74, +62,66,58,48,56,44,36,16,16,1,37,30,10,15,83,61,69,23,29,25, +30,7,7,9,12,56,32,68,1,112,108,86,70,44,36,17,37,69,17,82, +58,40,18,20,4,1,9,41,59,43,25,31,17,1,15,19,1,4,6,4, +14,20,6,110,106,94,80,70,58,26,4,31,0,0,0,0,122,16,25,122, +16,25,77,39,32,20,12,38,68,98,112,38,57,5,3,7,14,12,7,2, +14,50,56,24,15,55,47,47,17,3,7,14,21,29,22,26,7,27,47,6, +25,41,67,14,15,31,8,29,31,53,3,25,13,41,7,4,44,0,0,0, +23,51,67,3,22,1,74,12,35,57,23,35,10,7,35,25,63,29,55,45, +63,33,41,47,49,48,3,13,65,15,59,39,71,12,2,4,9,26,9,7, +33,55,31,35,31,11,25,51,41,11,61,41,10,3,39,45,2,19,7,3, +6,18,0,11,37,51,17,30,30,49,18,14,10,8,10,6,2,4,6,14, +10,4,4,6,13,7,10,7,30,46,48,32,18,38,24,32,18,2,24,22, +44,51,30,54,48,92,122,66,78,110,110,68,94,94,124,124,58,78,56,72, +96,76,104,122,124,60,56,88,68,124,8,120,124,120,116,114,104,98,96,86, +74,66,54,42,32,5,23,19,41,32,34,28,30,8,8,6,28,9,17,13, +37,23,87,55,12,18,20,4,7,17,25,29,67,37,54,30,18,3,0,25, +43,51,67,5,56,40,30,26,10,2,3,11,29,7,74,62,46,14,20,3, +19,37,18,106,94,82,60,48,6,9,11,21,124,87,79,57,79,77,53,67, +59,47,61,57,59,45,47,49,65,51,39,29,29,27,21,15,9,7,0,11, +11,23,2,4,0,2,2,4,4,10,2,0,2,10,3,11,19,11,1,17, +24,32,26,34,24,28,28,24,22,8,22,14,9,3,106,108,102,106,104,120, +114,118,118,114,124,120,110,90,52,124,124,124,124,110,106,76,64,58,46,26, +12,3,21,124,124,124,120,112,114,104,100,84,76,66,56,32,16,3,10,10, +7,44,42,38,30,26,26,12,12,6,3,33,17,39,57,20,7,17,33,23, +9,21,3,12,13,21,0,8,6,8,20,8,6,118,96,72,52,34,8,11, +41,69,5,78,56,46,26,28,12,4,0,23,29,19,3,17,4,16,7,13, +4,12,12,12,22,18,8,118,96,72,52,34,8,11,41,69,0,0,0,0, +120,16,25,120,16,25,73,37,32,20,12,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, +44,0,0,0,21,51,67,3,20,1,104,16,11,95,51,37,7,47,75,67, +81,29,75,61,69,87,79,87,81,24,5,11,55,7,43,33,69,19,55,41, +89,22,27,11,81,45,25,21,5,8,1,17,16,10,9,6,1,1,4,25, +26,10,38,38,30,36,34,30,34,24,14,36,30,23,63,43,49,29,37,29, +11,25,25,21,25,13,17,11,23,61,43,63,15,19,1,9,6,14,2,3, +14,12,3,11,2,39,82,80,62,66,80,64,34,68,58,24,38,30,10,2, +7,28,16,20,22,14,6,22,10,2,10,1,5,4,51,116,120,112,120,114, +112,112,112,108,90,88,82,62,54,16,82,70,34,90,70,72,62,52,46,48, +30,10,4,2,31,31,69,9,54,36,24,6,10,0,13,19,37,2,82,54, +42,34,28,6,9,15,25,33,46,26,14,4,4,9,19,31,61,45,3,9, +7,13,19,39,45,71,13,70,38,24,8,10,11,21,27,39,124,47,29,15, +5,13,2,10,12,13,8,18,12,29,15,13,20,16,26,20,42,46,38,18, +30,34,30,15,4,17,57,45,35,35,27,29,25,23,11,21,19,13,7,23, +37,57,35,65,25,11,13,1,9,3,8,1,3,7,2,3,9,35,86,78, +82,76,68,80,72,66,58,56,58,48,12,16,2,48,46,36,14,28,22,0, +5,11,23,29,55,27,67,124,124,118,118,108,100,94,82,80,72,66,52,40, +14,13,78,78,26,82,92,70,58,62,54,44,52,40,32,12,12,5,39,26, +6,19,81,59,67,21,27,23,34,5,5,9,14,60,34,72,0,110,104,82, +64,38,30,23,41,71,17,82,58,40,18,20,4,1,9,39,57,41,23,29, +15,0,13,17,0,6,8,4,16,20,6,108,104,90,76,66,54,22,0,33, +0,0,0,0,120,16,25,120,16,25,73,37,32,20,12,36,64,96,112,38, +53,5,3,5,14,10,7,0,10,48,52,16,21,59,41,45,17,3,5,14, +21,27,22,26,7,27,45,6,25,41,67,14,15,31,8,29,31,53,3,25, +13,41,7,4,44,0,0,0,21,51,67,3,20,1,72,12,35,53,21,33, +14,3,31,23,59,25,53,43,59,33,41,47,49,48,3,11,61,15,57,37, +67,12,2,4,9,26,9,7,31,53,29,33,29,9,23,49,37,9,59,39, +20,4,33,39,2,19,7,1,6,18,0,11,35,47,17,26,26,43,18,14, +10,8,10,8,6,6,6,14,10,4,6,8,15,7,10,7,28,44,46,32, +16,38,24,32,16,2,22,20,42,51,30,52,46,88,116,64,74,106,106,64, +90,90,124,124,52,74,52,68,90,72,98,114,124,54,52,82,64,124,4,116, +124,116,112,110,100,94,92,82,70,62,50,38,28,9,23,19,41,30,32,26, +28,6,6,4,24,11,17,15,39,25,85,53,14,18,20,4,5,15,23,27, +63,35,54,30,18,1,2,23,39,47,63,3,58,42,32,28,12,2,3,11, +27,7,76,62,44,14,20,3,19,35,18,106,92,80,58,48,6,9,11,21, +124,85,77,55,75,73,51,63,55,45,57,53,55,43,45,47,63,47,39,29, +29,25,19,15,9,7,1,11,11,23,2,4,2,2,2,4,4,10,2,0, +2,8,3,11,19,11,0,19,22,32,24,32,22,26,28,22,20,8,22,12, +9,5,104,106,100,102,100,116,110,114,114,108,122,114,104,84,48,124,124,124, +124,104,100,70,60,54,42,22,10,5,23,124,124,124,116,106,108,100,94,80, +72,62,50,28,12,7,8,8,11,42,40,34,26,22,22,8,10,2,5,35, +19,41,59,16,9,19,33,23,7,21,1,14,13,19,2,10,6,10,22,8, +6,116,92,66,46,28,0,19,49,75,5,78,56,46,26,30,12,4,0,23, +29,19,3,17,6,18,7,13,4,12,12,12,24,18,8,116,92,66,46,28, +0,19,49,75,0,0,0,0,116,14,27,116,14,27,71,35,32,20,10,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,44,0,0,0,21,53,67,3,18,3,104,14, +11,93,51,37,7,45,73,65,79,27,73,59,67,85,79,85,81,24,5,11, +55,7,43,33,67,19,55,41,87,22,27,11,79,45,25,21,5,8,1,17, +16,10,11,4,1,3,4,25,24,8,36,38,28,34,34,28,30,22,12,32, +28,25,63,43,49,29,37,29,9,25,25,21,23,15,17,11,27,61,43,63, +15,21,1,9,4,14,2,3,10,12,5,13,2,41,78,78,60,64,78,62, +32,66,56,20,36,28,8,2,9,26,14,18,20,12,4,20,8,1,6,3, +9,0,51,112,116,108,116,110,106,106,106,102,84,82,76,56,48,10,78,66, +30,84,64,66,56,46,40,42,24,4,2,1,35,33,71,9,54,36,24,6, +10,1,13,19,37,2,82,54,42,34,30,6,9,15,25,33,46,26,14,4, +4,9,19,31,59,45,1,9,7,13,19,39,45,69,13,70,38,24,8,10, +11,21,27,39,124,47,29,15,5,13,2,10,12,13,8,18,12,29,15,15, +18,16,24,18,40,44,36,14,26,32,28,17,0,19,57,45,33,35,27,29, +25,23,13,21,19,13,9,23,37,57,35,67,25,11,13,1,11,3,8,3, +5,7,2,5,11,37,84,76,80,74,64,78,70,64,56,54,56,46,10,12, +1,44,42,32,10,24,18,1,7,13,23,29,55,29,67,124,122,114,112,102, +94,88,76,74,66,60,46,34,10,15,74,74,22,78,86,64,52,56,48,40, +46,34,26,8,6,9,43,22,2,23,79,57,65,21,27,23,36,5,5,9, +14,62,36,74,0,106,100,76,56,32,24,29,47,75,17,82,56,38,18,20, +4,3,9,39,57,41,23,29,13,0,13,17,0,6,8,4,16,20,4,104, +100,86,72,62,50,16,3,35,0,0,0,0,116,14,27,116,14,27,71,35, +32,20,10,32,58,94,112,36,51,7,3,5,12,8,7,1,6,44,46,8, +27,63,37,45,17,3,5,12,23,27,22,24,7,27,45,4,27,41,67,12, +15,31,8,29,31,53,3,25,15,41,7,4,44,0,0,0,21,53,67,3, +18,3,70,10,37,49,19,31,16,0,29,21,57,23,51,41,55,33,41,47, +49,48,3,11,57,15,57,37,65,10,0,2,11,26,9,7,31,53,29,33, +29,9,23,47,35,9,57,37,28,12,27,35,2,19,7,1,4,18,0,11, +35,43,17,22,22,39,18,14,10,8,10,8,8,6,6,12,8,4,6,8, +19,7,10,9,26,40,44,30,14,38,24,30,12,2,20,18,40,51,28,50, +44,82,108,60,70,100,100,58,84,86,110,124,44,68,48,62,82,66,90,104, +118,48,48,74,60,124,0,110,118,110,106,104,94,88,86,78,64,56,46,34, +24,13,23,21,43,28,28,22,24,2,2,0,20,13,19,17,41,27,85,51, +14,18,20,4,5,15,23,27,59,33,54,30,18,1,2,21,37,45,61,3, +58,42,32,28,14,2,3,11,27,9,76,60,42,12,20,3,19,35,16,104, +90,76,56,46,6,9,11,21,124,83,75,53,73,71,49,61,53,43,55,51, +51,43,45,47,61,45,39,29,29,25,19,15,11,9,3,11,13,25,2,4, +4,2,0,4,4,8,2,0,2,6,3,11,19,11,0,21,20,32,20,30, +20,24,26,20,18,8,20,8,11,9,100,102,98,98,96,110,104,108,108,102, +116,108,96,78,44,124,124,122,120,96,92,64,54,48,38,18,6,7,25,118, +120,120,110,100,102,94,86,74,66,56,44,24,8,11,6,6,15,38,36,30, +20,18,18,4,6,1,9,37,23,43,61,12,13,23,33,23,7,21,0,16, +13,19,2,10,6,10,22,8,4,112,88,60,38,20,7,29,59,81,5,78, +56,46,26,30,12,4,0,23,29,19,3,17,6,18,7,13,4,12,12,12, +24,16,6,112,88,60,38,20,7,29,59,81,0,0,0,0,114,14,27,114, +14,27,67,31,34,22,10,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,44,0,0,0, +19,53,67,1,18,3,104,14,11,89,49,37,5,41,69,61,75,23,69,55, +63,81,77,83,79,26,3,9,53,5,41,31,63,17,53,39,83,24,25,9, +75,43,23,19,3,10,0,15,18,12,11,4,0,3,4,23,24,8,36,38, +28,34,34,28,28,22,12,30,26,25,61,41,47,27,35,27,7,23,23,19, +19,15,17,9,29,59,41,63,13,21,0,7,4,16,2,3,8,14,5,15, +2,41,76,78,60,64,78,62,32,66,56,18,36,28,8,2,9,26,14,18, +20,12,2,20,8,3,4,3,11,1,51,110,114,106,114,108,102,102,102,98, +80,78,72,52,44,6,76,64,28,80,60,62,52,42,36,38,20,0,2,3, +37,33,71,7,56,38,26,8,10,1,11,17,35,4,84,56,44,34,32,8, +7,13,23,31,48,28,16,6,6,7,17,29,55,43,2,7,5,11,17,37, +43,65,11,72,40,26,10,12,9,19,25,37,124,45,27,13,5,11,2,12, +14,11,10,20,14,27,15,15,18,18,24,18,38,44,36,12,24,32,28,17, +1,19,55,43,31,33,25,27,23,21,13,19,17,11,9,21,35,55,33,67, +25,9,13,0,11,3,10,3,5,5,4,5,11,37,84,76,80,74,62,78, +70,64,56,54,56,46,10,10,3,42,40,30,8,22,16,1,7,13,21,27, +53,29,65,120,118,110,108,98,90,84,72,70,62,56,42,30,8,15,72,72, +20,76,82,60,48,52,44,36,42,30,22,6,2,11,45,20,0,25,75,53, +61,19,25,21,40,3,3,9,16,66,40,78,2,104,98,72,50,28,20,33, +51,77,15,84,56,38,18,22,4,3,9,37,55,39,21,27,9,2,11,15, +2,8,10,6,18,22,4,102,98,84,70,60,48,12,5,35,0,0,0,0, +114,14,27,114,14,27,67,31,34,22,10,30,54,92,114,36,47,7,1,3, +12,8,5,1,4,42,42,2,31,65,31,43,15,1,3,12,23,25,22,24, +5,25,43,4,27,39,65,12,13,29,8,27,29,51,1,23,15,39,5,4, +44,0,0,0,19,53,67,1,18,3,70,10,37,43,15,27,20,6,25,17, +53,19,47,37,49,33,39,45,47,48,3,9,51,13,55,35,61,10,0,2, +11,28,9,5,29,51,27,31,27,7,21,43,31,7,53,33,38,22,19,29, +4,17,5,0,4,20,2,9,33,37,15,18,20,33,18,16,10,10,12,10, +12,8,8,12,8,4,8,10,21,5,10,9,26,38,44,30,14,38,24,30, +10,4,20,18,40,51,28,50,44,78,102,58,68,96,96,54,80,82,98,124, +38,64,46,58,76,62,84,96,110,44,44,68,56,124,1,106,114,106,102,100, +90,84,82,74,60,52,44,32,22,15,23,21,43,28,26,20,22,0,0,1, +18,15,19,19,41,27,83,47,16,20,20,6,3,13,21,25,53,29,56,32, +20,0,4,17,33,41,57,1,60,44,34,30,16,4,1,9,25,9,78,60, +42,12,22,1,19,33,16,104,90,74,54,46,8,7,9,19,124,79,71,49, +69,67,45,57,49,39,51,47,45,41,43,45,57,41,37,27,27,23,17,13, +11,9,3,11,13,25,4,6,6,4,0,6,6,8,4,2,2,6,1,9, +17,9,2,21,18,32,18,30,20,24,26,20,18,8,20,6,11,11,98,100, +98,96,94,106,100,104,104,98,112,104,90,74,40,122,120,114,112,90,86,60, +50,44,36,16,4,7,25,114,116,116,106,96,98,90,80,70,62,52,40,22, +6,13,6,6,17,36,34,28,16,16,16,2,4,3,11,37,25,43,61,10, +15,25,31,21,5,19,4,20,11,17,4,12,8,12,24,8,4,110,84,56, +32,14,15,37,67,85,3,78,58,48,28,32,14,6,2,21,27,17,1,15, +8,20,5,11,6,14,12,14,26,16,6,110,84,56,32,14,15,37,67,85, +0,0,0,0,112,14,27,112,14,27,63,29,34,22,10,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,44,0,0,0,17,53,67,1,16,3,104,14,11,87,47,37, +5,39,65,57,73,21,65,53,59,79,75,81,77,28,3,7,51,5,41,29, +59,17,53,39,81,24,25,9,73,43,21,19,3,10,0,13,18,12,13,4, +0,3,4,23,24,8,34,38,26,34,34,28,24,22,12,26,24,27,59,39, +45,25,33,25,5,21,23,17,17,15,17,9,31,59,39,63,13,21,2,7, +2,18,2,3,6,16,7,17,2,43,72,76,58,62,76,60,30,64,56,16, +34,28,8,2,9,24,12,16,18,10,0,18,6,7,2,5,13,3,51,106, +112,102,110,104,98,98,98,92,76,74,66,46,40,0,72,60,24,76,56,58, +48,38,32,32,16,3,0,7,39,35,71,7,56,38,26,8,10,1,11,17, +33,4,84,56,44,34,34,8,5,13,21,29,50,30,16,6,8,7,17,27, +53,41,4,5,5,11,15,35,41,63,11,72,40,26,10,14,7,17,23,35, +124,45,27,13,5,11,2,12,14,11,10,20,16,27,15,15,16,18,22,16, +36,42,36,10,22,32,28,19,3,21,53,41,29,33,25,27,21,19,13,19, +17,11,11,21,35,55,31,67,25,9,13,2,11,3,12,3,5,5,6,7, +11,39,82,76,80,72,60,76,68,62,54,52,54,44,8,8,5,38,38,26, +4,20,14,3,9,13,21,27,53,31,63,116,114,106,104,92,86,80,66,66, +58,52,38,26,6,17,68,68,18,72,78,56,44,48,40,32,38,26,18,2, +1,15,47,16,3,29,73,51,59,17,23,19,44,1,1,9,18,68,42,80, +4,102,94,66,44,22,14,39,55,79,15,84,56,38,18,22,4,3,9,35, +53,37,19,25,7,4,9,13,4,10,12,6,20,22,4,100,94,80,66,56, +44,8,9,37,0,0,0,0,112,14,27,112,14,27,63,29,34,22,10,28, +50,90,114,36,43,7,1,1,12,6,5,3,0,40,36,5,37,69,25,41, +15,1,1,12,23,23,22,22,5,25,41,4,27,39,65,12,13,29,8,27, +29,51,1,23,15,39,5,4,44,0,0,0,17,53,67,1,16,3,68,10, +37,39,13,25,24,10,23,15,49,17,45,35,45,33,39,45,47,48,3,7, +47,13,53,33,57,10,0,2,13,28,9,5,27,49,25,29,25,7,19,41, +29,5,51,31,48,30,13,23,4,17,5,0,4,20,2,9,33,33,15,14, +16,27,18,16,10,10,12,10,16,10,8,12,8,4,10,12,23,5,10,9, +24,36,42,30,12,38,24,30,8,4,18,16,38,51,28,48,42,74,96,56, +64,92,92,50,76,78,86,124,30,60,42,54,70,58,78,88,102,38,40,62, +52,124,5,102,110,102,98,96,86,80,78,70,56,48,40,28,18,19,23,21, +45,26,24,18,20,1,1,3,14,17,19,21,43,29,81,45,18,20,20,6, +1,11,19,23,49,27,56,32,20,2,6,15,29,37,53,0,62,46,36,32, +18,4,1,9,23,9,80,60,40,12,22,1,19,33,16,104,88,72,52,46, +8,7,9,19,124,77,69,47,65,63,43,53,45,37,47,43,41,39,41,45, +55,37,37,27,27,21,17,13,11,9,5,11,13,25,4,6,8,4,0,6, +6,8,4,2,2,4,1,9,17,9,4,23,16,32,16,28,18,22,26,18, +16,8,20,4,11,13,96,98,96,92,90,102,96,100,100,92,106,98,84,68, +36,114,112,106,102,84,80,54,46,38,32,12,2,9,27,110,112,110,102,90, +92,84,74,66,56,48,34,18,2,17,4,4,21,34,32,24,12,12,12,1, +2,7,13,39,27,45,63,6,17,27,31,21,3,19,6,22,11,15,6,14, +8,12,26,8,4,108,80,50,26,8,23,45,75,91,3,78,58,48,28,34, +14,6,2,21,27,17,1,15,10,22,5,11,6,14,12,14,28,16,6,108, +80,50,26,8,23,45,75,91,0,0,0,0,110,14,27,110,14,27,59,25, +36,22,8,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,44,0,0,0,17,53,67,0, +14,3,104,14,11,85,45,37,3,37,61,53,69,19,61,51,55,77,73,79, +75,30,3,5,49,5,39,29,55,17,51,37,79,24,25,7,69,41,19,19, +3,10,0,11,20,14,13,4,0,3,4,23,24,6,34,38,24,34,34,28, +20,22,10,22,22,29,57,37,43,23,31,25,3,21,21,15,15,15,17,9, +33,57,37,63,13,21,4,7,0,20,2,3,4,18,7,19,2,45,70,74, +58,60,74,58,30,62,54,14,32,28,8,2,11,22,10,14,16,8,1,16, +6,11,0,5,15,5,51,104,108,100,106,100,94,94,94,88,70,70,62,42, +34,3,68,56,22,72,52,52,42,34,26,28,12,9,1,11,41,37,71,7, +58,38,26,8,10,1,11,17,33,4,84,56,44,34,36,10,5,11,21,27, +52,30,18,6,10,5,15,27,51,39,6,3,3,11,13,33,39,61,9,72, +40,26,10,16,7,15,21,33,124,43,25,11,5,11,2,12,14,11,10,20, +16,27,15,15,16,20,20,14,34,40,36,8,20,32,28,19,5,21,51,39, +27,31,23,25,21,17,13,19,17,9,11,21,35,53,29,67,25,9,13,4, +11,3,14,3,5,5,8,9,11,41,80,74,78,70,58,74,66,60,52,50, +52,42,6,6,7,36,36,24,0,16,12,5,9,15,21,27,53,31,61,112, +110,102,100,86,82,76,62,62,54,48,32,22,2,19,64,66,14,68,74,52, +40,44,36,28,34,22,12,1,5,19,49,12,7,31,71,49,57,15,21,17, +46,0,0,9,20,72,46,84,6,98,92,62,38,16,8,45,59,81,15,84, +56,38,18,22,4,3,9,35,51,35,17,23,5,4,9,11,4,10,12,6, +20,22,4,98,92,76,62,52,40,4,13,39,0,0,0,0,110,14,27,110, +14,27,59,25,36,22,8,24,46,88,114,36,39,7,0,0,12,6,5,3, +1,38,32,11,41,71,19,39,15,0,0,12,25,21,22,22,5,25,41,4, +27,39,65,12,13,27,8,27,27,51,1,23,15,39,5,4,44,0,0,0, +17,53,67,0,14,3,66,8,37,33,11,23,26,14,19,11,45,13,43,33, +41,33,39,43,47,48,3,5,43,13,51,33,53,10,1,0,13,28,9,3, +27,47,23,29,23,5,17,37,25,5,49,29,58,40,7,17,4,17,5,2, +4,20,4,7,31,29,15,10,12,21,18,16,10,10,12,12,18,12,8,12, +8,4,10,14,25,5,10,11,24,34,42,30,12,38,24,30,6,4,16,14, +38,51,28,48,42,70,90,54,60,88,86,46,70,74,72,124,24,56,38,50, +64,52,72,80,94,32,36,54,48,124,9,98,106,98,92,90,82,76,74,66, +52,44,36,24,16,23,23,21,45,24,22,16,18,3,3,5,10,19,21,23, +45,29,81,41,20,22,20,6,0,11,19,23,45,25,56,32,22,4,8,13, +27,35,49,2,62,46,36,32,20,6,1,9,23,9,80,60,38,12,22,1, +19,31,16,102,88,70,50,46,8,7,9,19,124,75,65,45,63,61,41,49, +41,35,45,39,37,39,39,43,53,33,35,27,27,21,15,13,11,9,5,11, +13,27,6,8,10,4,0,8,6,8,4,2,2,4,1,9,17,9,4,25, +14,32,14,26,16,22,26,16,14,8,20,2,11,15,94,96,94,90,86,98, +92,96,94,88,100,92,78,64,32,106,104,98,92,76,74,50,42,34,28,8, +1,11,29,106,106,106,96,84,88,80,68,60,52,42,28,14,1,19,2,2, +23,30,28,20,8,10,8,5,0,9,15,41,29,47,65,4,19,29,31,19, +3,17,8,24,11,15,6,14,8,14,28,8,4,106,76,46,20,2,31,53, +83,97,3,78,58,48,28,34,16,6,2,19,27,17,0,13,12,24,5,9, +6,14,12,14,28,16,6,106,76,46,20,2,31,53,83,97,0,0,0,0, +106,14,27,106,14,27,57,23,36,22,8,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, +44,0,0,0,15,55,67,0,12,3,104,14,11,83,43,37,3,33,59,49, +67,17,59,47,51,75,73,77,75,30,3,3,47,5,39,27,51,17,51,37, +77,24,23,7,67,41,19,19,1,10,0,11,20,14,15,2,0,3,4,23, +24,6,32,38,24,34,34,26,16,22,10,18,20,31,55,35,41,21,31,23, +1,19,21,13,13,15,17,7,35,57,35,63,13,21,4,7,1,22,2,3, +0,20,9,21,2,47,66,72,56,58,72,56,28,60,54,10,30,26,8,2, +11,20,10,12,16,6,3,14,4,15,1,7,17,7,51,100,106,96,102,96, +90,88,90,82,66,66,56,36,30,9,64,54,18,66,48,48,38,28,22,22, +8,13,3,13,45,39,71,7,58,40,26,8,10,1,11,17,31,6,86,56, +44,34,38,10,3,11,19,27,54,32,18,6,10,5,15,25,49,39,8,3, +3,11,11,31,39,59,9,74,40,26,10,18,5,15,19,31,124,43,25,11, +5,11,2,12,14,9,10,20,18,27,15,15,14,20,18,12,32,38,36,4, +18,30,28,21,7,23,51,39,25,31,23,25,19,15,15,19,17,9,13,21, +35,53,27,67,25,7,13,4,11,3,16,3,7,5,10,9,13,43,78,74, +78,68,56,72,64,58,50,48,50,40,4,4,9,32,32,20,3,14,10,7, +11,15,21,27,53,33,61,106,104,98,94,80,78,72,56,58,50,44,28,18, +0,21,60,62,12,64,70,48,36,38,32,24,30,18,8,5,9,23,51,8, +11,35,69,47,55,15,19,15,50,2,2,9,22,74,48,86,6,96,88,56, +32,10,2,51,63,83,15,84,56,38,18,22,4,3,9,33,49,33,15,23, +3,6,7,9,6,12,14,8,22,24,4,94,88,72,58,48,36,0,17,41, +0,0,0,0,106,14,27,106,14,27,57,23,36,22,8,22,42,86,114,34, +35,7,0,2,10,4,5,5,5,36,26,19,47,75,13,37,15,0,2,10, +25,19,22,20,5,23,39,4,27,39,65,12,13,27,8,27,27,49,1,23, +15,39,3,4,44,0,0,0,15,55,67,0,12,3,64,8,37,29,9,21, +30,18,17,9,43,11,39,31,37,33,37,43,47,48,3,3,39,13,51,31, +49,10,1,0,15,28,9,3,25,45,21,27,21,5,17,35,23,3,47,27, +68,48,1,11,4,15,5,2,4,20,4,7,31,25,15,6,8,17,18,18, +10,10,12,12,22,14,10,10,8,4,12,14,27,5,10,11,22,32,40,28, +10,38,24,30,4,4,14,12,36,51,26,46,40,66,82,52,56,84,82,42, +66,70,60,124,16,52,34,44,58,48,64,70,86,26,32,48,44,124,11,94, +102,92,88,86,78,72,70,62,46,40,32,20,12,27,23,21,47,22,20,14, +14,5,7,7,8,21,21,25,45,31,79,39,22,22,20,8,0,9,17,21, +41,21,56,34,22,4,10,11,23,31,47,2,64,48,38,34,22,6,1,7, +21,9,82,60,38,10,22,1,19,31,16,102,86,68,48,46,8,5,9,19, +124,71,63,43,59,57,39,47,39,33,41,37,33,37,37,43,51,31,35,27, +27,19,15,13,13,9,7,11,13,27,6,8,12,4,0,8,6,8,4,2, +2,2,1,9,17,9,6,27,12,32,12,26,14,20,26,14,12,8,20,0, +11,17,92,94,92,86,82,94,88,90,90,82,94,86,72,58,28,96,96,90, +82,70,66,44,36,28,24,4,3,13,29,100,102,100,92,78,82,74,62,56, +46,38,22,10,5,23,0,2,27,28,26,18,4,6,4,7,1,13,17,43, +33,49,65,0,23,33,29,19,1,17,10,26,11,13,8,16,8,14,30,8, +4,104,72,40,14,5,39,63,91,103,1,78,58,48,28,36,16,6,2,19, +27,17,0,13,12,26,5,9,8,16,12,14,30,16,6,104,72,40,14,5, +39,63,91,103,0,0,0,0,104,14,27,104,14,27,53,19,36,22,6,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,44,0,0,0,15,55,67,2,10,3,104,14, +11,81,41,37,1,31,55,45,63,15,55,45,47,73,71,75,73,32,3,1, +45,5,37,25,47,17,51,35,73,26,23,5,65,39,17,19,1,12,2,9, +22,16,15,2,0,3,4,23,24,4,30,38,22,34,34,26,12,22,8,16, +18,33,53,33,39,19,29,21,0,17,19,11,11,15,17,7,37,55,33,63, +11,21,6,7,3,24,2,3,1,22,9,23,2,47,64,70,56,56,70,54, +26,60,54,8,28,26,8,2,13,20,8,10,14,4,5,14,2,19,3,9, +19,9,51,96,104,92,98,94,86,84,86,78,62,62,52,32,26,13,60,50, +14,62,44,44,34,24,18,16,4,19,5,17,47,39,71,7,58,40,26,8, +10,1,11,17,31,6,86,56,44,34,40,12,1,11,17,25,56,34,18,8, +12,3,13,25,47,37,12,1,3,9,9,29,37,57,7,74,42,26,10,20, +3,13,17,29,124,43,25,9,5,11,2,12,14,9,10,22,18,27,15,15, +12,22,16,10,30,38,36,2,16,30,28,23,9,23,49,37,23,29,21,23, +19,13,15,19,17,9,15,21,35,51,25,67,25,7,13,6,11,3,18,3, +7,5,12,11,13,43,76,74,76,68,54,70,62,56,50,46,48,38,2,2, +11,30,30,18,7,12,8,9,13,17,21,25,53,33,59,102,100,94,90,76, +74,68,52,54,46,40,24,14,3,23,56,58,10,60,66,44,32,34,28,20, +26,14,2,9,13,27,53,4,15,37,67,43,53,13,17,13,54,4,4,9, +24,78,52,90,8,92,84,52,26,6,3,55,67,85,15,84,56,38,18,22, +4,3,9,33,47,31,13,21,1,8,7,7,8,14,16,8,22,24,4,92, +86,70,56,44,32,3,21,43,0,0,0,0,104,14,27,104,14,27,53,19, +36,22,6,20,38,84,114,34,31,7,0,4,10,4,5,7,9,34,22,25, +51,79,7,35,13,0,4,10,25,17,22,20,5,23,37,4,27,39,65,12, +13,27,8,27,25,49,1,23,15,39,3,4,44,0,0,0,15,55,67,2, +10,3,62,6,37,23,7,19,34,22,13,5,39,7,37,29,31,33,37,41, +45,48,3,1,35,13,49,31,45,10,3,1,15,28,9,1,25,43,19,27, +19,3,15,31,19,1,43,25,78,56,4,5,6,15,3,4,4,20,6,7, +29,21,15,2,4,11,18,18,10,10,12,14,24,16,10,10,8,4,12,16, +29,3,10,13,22,30,40,28,10,38,24,30,2,6,12,12,36,51,26,44, +38,62,76,50,54,80,78,38,60,66,48,124,10,48,30,40,52,42,58,62, +78,22,28,40,40,124,15,90,98,88,84,82,74,68,66,58,42,36,28,18, +8,31,23,21,47,20,18,12,12,7,9,9,4,23,23,27,47,33,77,35, +24,24,20,8,2,9,17,19,37,19,56,34,24,6,12,9,21,29,43,4, +66,50,40,34,24,8,0,7,21,9,82,60,36,10,22,1,19,29,16,100, +84,66,46,46,8,5,9,17,124,69,59,39,55,55,37,43,35,31,37,33, +29,35,35,41,49,27,35,27,25,19,13,13,13,9,7,11,13,29,8,8, +14,4,0,8,6,8,4,2,2,2,1,9,17,9,6,29,10,32,10,24, +14,18,26,14,10,8,20,1,11,19,90,92,90,82,78,90,84,86,84,76, +88,80,66,54,24,88,88,82,72,64,60,40,32,24,20,2,7,13,31,96, +96,96,88,72,76,70,56,52,42,34,16,6,9,25,0,0,31,26,22,14, +0,2,0,11,3,15,19,43,35,51,67,1,25,35,29,19,0,15,12,28, +9,11,8,16,8,16,32,8,4,102,68,34,8,11,47,71,99,109,1,78, +58,48,28,36,16,8,4,17,27,17,2,13,14,28,5,9,8,16,12,16, +30,16,6,102,68,34,8,11,47,71,99,109,0,0,0,0,102,14,29,102, +14,29,49,17,38,22,6,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,44,0,0,0, +13,55,67,2,10,5,104,14,11,79,41,37,1,29,51,41,61,13,51,43, +43,71,69,73,71,34,3,0,45,3,37,25,43,17,49,35,71,26,23,5, +61,39,15,17,1,12,2,7,22,16,17,2,0,3,4,23,24,4,30,38, +20,34,34,26,8,22,8,12,16,35,53,31,39,19,27,21,2,17,19,11, +7,15,17,7,39,55,31,63,11,21,8,5,5,24,2,3,3,24,11,25, +2,49,60,68,54,56,68,54,26,58,52,6,26,26,8,2,13,18,6,8, +12,4,7,12,2,23,5,9,21,11,51,94,100,90,94,90,82,80,82,72, +56,58,46,26,20,19,56,46,12,58,38,38,28,20,12,12,1,23,7,21, +49,41,71,5,60,40,28,8,10,1,11,17,29,6,86,58,44,34,42,12, +1,9,17,23,58,34,20,8,14,3,13,23,45,35,14,0,1,9,9,29, +35,53,7,74,42,26,12,20,3,11,17,27,124,41,23,9,5,11,2,12, +14,9,12,22,20,27,15,17,12,22,14,8,28,36,36,0,14,30,28,23, +11,25,47,35,21,29,21,23,17,13,15,17,15,7,15,21,35,51,23,67, +25,7,13,8,11,3,20,5,7,5,12,13,13,45,74,72,76,66,52,70, +62,54,48,46,46,36,0,0,13,26,28,14,11,8,4,11,13,17,21,25, +51,35,57,98,96,90,86,70,70,64,46,50,40,36,18,10,5,23,54,56, +6,56,60,40,28,30,24,16,20,10,1,13,17,29,57,0,19,41,65,41, +51,11,15,11,56,6,6,9,26,80,54,92,10,90,82,46,20,0,7,61, +71,89,13,84,56,38,18,22,4,3,9,31,45,31,11,19,0,8,5,5, +8,14,16,8,24,24,4,90,82,66,52,42,30,9,23,45,0,0,0,0, +102,14,29,102,14,29,49,17,38,22,6,16,34,82,114,34,29,7,2,4, +10,2,3,7,11,30,16,33,57,81,3,33,13,2,4,10,27,17,22,18, +5,23,37,4,27,37,63,12,11,25,8,25,25,49,1,23,15,39,3,4, +44,0,0,0,13,55,67,2,10,5,62,6,37,19,5,17,36,28,11,3, +35,5,35,27,27,33,37,41,45,48,3,0,29,13,47,29,41,8,3,1, +17,30,9,1,23,43,19,25,17,3,13,29,17,1,41,23,88,66,10,0, +6,15,3,4,4,20,6,5,29,17,13,1,0,5,18,18,10,10,14,14, +28,18,10,10,8,4,14,18,31,3,10,13,20,28,38,28,8,38,24,30, +1,6,10,10,34,51,26,44,38,58,70,48,50,74,72,34,56,62,34,124, +2,44,28,36,44,38,52,54,68,16,24,34,36,124,19,86,94,84,78,76, +70,62,62,54,38,30,24,14,6,33,23,21,49,18,16,10,10,9,11,11, +0,25,23,29,49,33,77,33,26,24,20,8,4,7,15,19,33,17,58,34, +24,8,14,7,17,25,39,6,66,50,40,36,26,8,0,7,19,9,84,60, +34,10,22,1,19,29,14,100,84,64,44,44,8,5,9,17,124,67,57,37, +53,51,35,39,31,29,35,29,25,35,33,41,47,23,33,27,25,17,13,13, +13,9,9,11,13,29,8,10,16,4,0,10,8,8,6,4,2,0,1,9, +17,9,8,31,8,32,8,22,12,18,26,12,10,8,18,5,13,21,86,90, +88,80,74,86,80,82,80,72,82,76,60,48,20,80,80,74,64,56,54,34, +28,18,16,1,9,15,33,92,92,90,82,66,72,64,50,46,36,28,10,2, +11,29,1,1,33,22,20,10,3,0,3,15,5,19,21,45,37,53,69,5, +27,37,29,17,0,15,14,30,9,11,10,18,8,16,34,8,4,100,64,30, +2,17,55,79,107,115,1,78,58,48,28,38,18,8,4,17,25,15,2,11, +16,30,3,7,8,16,12,16,32,16,6,100,64,30,2,17,55,79,107,115, +0,0,0,0,100,14,29,100,14,29,45,13,38,22,4,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,44,0,0,0,13,55,67,4,8,5,104,14,11,77,39,37, +0,25,49,37,57,11,49,39,39,69,67,71,71,36,3,2,43,3,35,23, +39,17,49,33,69,26,21,3,59,37,15,17,0,12,2,5,24,18,17,0, +0,3,4,23,24,2,28,38,20,34,34,24,4,22,6,8,14,37,51,29, +37,17,25,19,4,15,17,9,5,15,17,5,41,53,29,63,11,21,8,5, +7,26,2,3,7,26,11,27,2,51,58,66,54,54,66,52,24,56,52,4, +24,26,8,2,15,16,6,6,12,2,9,10,0,27,7,11,23,13,51,90, +98,86,90,86,78,74,78,68,52,54,42,22,16,23,52,44,8,52,34,34, +24,14,8,6,5,29,9,23,53,43,71,5,60,42,28,8,10,1,11,17, +29,8,88,58,44,34,44,14,0,9,15,21,60,36,20,8,16,1,11,23, +43,35,16,0,1,9,7,27,35,51,5,76,42,26,12,22,1,9,15,25, +124,41,23,7,5,11,2,12,14,7,12,22,20,27,15,17,10,24,12,6, +26,34,36,1,12,28,28,25,13,25,45,35,19,27,19,21,17,11,15,17, +15,7,17,21,35,49,21,67,25,5,13,8,11,3,22,5,7,5,14,13, +15,47,72,72,74,64,50,68,60,52,46,44,44,34,1,1,15,24,24,12, +15,6,2,13,15,19,21,25,51,35,55,94,92,86,80,64,66,60,42,46, +36,32,14,6,9,25,50,52,4,52,56,36,24,26,20,12,16,6,7,17, +21,33,59,3,23,43,63,39,49,11,13,9,60,8,8,9,28,84,58,96, +10,86,78,42,14,5,13,67,75,91,13,84,56,38,18,22,4,3,9,31, +43,29,9,17,2,10,5,3,10,16,18,10,24,26,4,86,80,62,48,38, +26,13,27,47,0,0,0,0,100,14,29,100,14,29,45,13,38,22,4,14, +30,80,114,34,25,7,2,6,8,2,3,9,15,28,12,39,61,85,2,31, +13,2,6,8,27,15,22,18,5,21,35,4,27,37,63,12,11,25,8,25, +23,47,1,23,15,39,1,4,44,0,0,0,13,55,67,4,8,5,60,4, +37,13,3,15,40,32,7,0,33,1,31,25,23,33,35,39,45,48,3,2, +25,13,45,29,37,8,5,3,17,30,9,0,23,41,17,25,15,1,11,25, +13,0,39,21,98,74,16,6,6,13,3,6,4,20,8,5,27,13,13,5, +3,0,18,20,10,10,14,16,30,20,12,8,8,4,14,18,33,3,10,15, +20,26,38,26,8,38,24,30,3,6,8,8,34,51,26,42,36,54,64,46, +46,70,68,30,50,58,22,124,3,40,24,30,38,32,46,44,60,10,20,26, +32,124,21,82,90,80,74,72,66,58,58,50,32,26,20,10,2,37,23,21, +49,16,14,8,6,11,13,13,1,27,25,31,49,35,75,29,28,26,20,10, +4,7,15,17,29,13,58,36,26,8,16,5,15,23,35,6,68,52,42,36, +28,10,0,5,19,9,84,60,34,8,22,1,19,27,14,98,82,62,42,44, +8,3,9,17,124,63,53,35,49,49,33,37,29,27,31,27,21,33,31,39, +45,19,33,27,25,17,11,13,15,9,9,11,13,31,10,10,18,4,0,10, +8,8,6,4,2,0,1,9,17,9,8,33,6,32,6,22,10,16,26,10, +8,8,18,7,13,23,84,88,86,76,70,82,76,76,74,66,76,70,54,44, +16,70,72,66,54,50,48,30,24,14,12,5,13,17,33,86,86,86,78,60, +66,60,44,42,32,24,4,1,15,31,3,1,37,20,16,8,7,3,7,17, +7,21,23,47,41,55,69,7,31,41,27,17,2,13,16,32,9,9,10,18, +8,18,36,8,4,98,60,24,3,25,63,87,115,121,0,78,58,48,28,38, +18,8,4,15,25,15,4,11,18,32,3,7,10,18,12,16,32,16,6,98, +60,24,3,25,63,87,115,121,0,0,0,0,96,12,29,96,12,29,43,11, +38,22,4,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,44,0,0,0,11,57,67,4, +6,5,104,14,11,75,37,37,0,23,45,33,55,9,45,37,37,67,67,69, +69,36,3,4,41,3,35,23,37,17,49,33,67,26,21,3,57,37,13,17, +0,12,2,5,24,18,19,0,0,3,4,23,24,2,26,38,18,34,34,24, +0,22,6,4,12,39,49,27,35,15,25,19,6,15,17,7,3,15,17,5, +45,53,27,63,11,23,10,5,9,28,2,3,9,28,13,29,2,53,54,64, +52,52,64,50,22,54,50,0,22,24,8,2,15,14,4,4,10,0,11,8, +1,31,11,13,25,15,51,86,94,82,86,82,74,70,74,62,46,50,36,16, +10,29,48,40,4,48,30,28,18,10,2,0,9,33,11,27,55,45,73,5, +60,42,28,8,10,1,11,17,27,8,88,58,44,34,46,14,0,9,15,21, +62,36,20,8,16,1,11,21,41,33,18,2,1,9,5,25,33,49,5,76, +42,26,12,24,1,9,13,25,124,41,23,7,5,11,2,12,14,7,12,22, +22,27,15,17,8,24,10,4,24,32,36,5,8,28,28,27,15,27,45,33, +17,27,19,21,15,9,17,17,15,7,19,21,35,49,21,69,25,5,13,10, +11,3,22,5,9,5,16,15,15,49,70,70,74,62,46,66,58,50,44,42, +42,32,3,3,17,20,22,8,19,2,0,15,17,19,21,25,51,37,55,88, +86,82,76,58,60,54,36,42,32,28,8,2,11,27,46,48,0,48,52,30, +18,20,14,8,12,0,11,21,27,37,61,7,27,47,61,37,47,9,11,9, +62,10,8,9,28,86,60,98,12,84,74,36,8,11,19,73,79,93,13,84, +56,38,18,22,4,3,9,29,43,27,7,17,4,10,3,3,10,16,18,10, +26,26,2,84,76,58,44,34,22,17,31,49,0,0,0,0,96,12,29,96, +12,29,43,11,38,22,4,10,24,78,114,32,21,9,2,8,8,0,3,11, +19,26,6,47,67,89,8,29,13,2,8,8,29,13,22,16,5,21,35,2, +29,37,63,12,11,25,8,25,23,47,1,23,15,39,1,4,44,0,0,0, +11,57,67,4,6,5,58,4,39,9,1,13,42,36,5,2,29,0,29,23, +19,33,35,39,45,48,3,4,21,13,45,27,33,8,5,3,19,30,9,0, +21,39,15,23,15,1,11,23,11,0,37,19,106,82,22,10,6,13,3,6, +2,20,8,5,27,9,13,9,7,4,18,20,10,10,14,16,34,20,12,8, +6,4,16,20,37,3,10,15,18,22,36,26,6,38,24,28,5,6,6,6, +32,51,24,40,34,50,56,42,42,66,62,24,46,54,8,124,11,36,20,26, +32,28,38,36,52,4,16,20,28,124,25,78,84,74,68,66,60,54,52,46, +28,22,16,6,1,41,23,23,51,14,10,6,4,13,17,17,5,29,25,33, +51,37,75,27,30,26,20,10,6,5,13,17,25,11,58,36,26,10,18,3, +11,19,33,8,68,52,42,38,30,10,0,5,17,11,86,60,32,8,22,1, +19,27,14,98,80,60,40,44,8,3,9,17,124,61,51,33,47,45,31,33, +25,25,29,23,17,33,31,39,43,17,33,27,25,15,11,13,15,9,11,11, +13,31,10,10,20,4,1,10,8,6,6,4,2,1,1,9,17,9,10,35, +4,32,2,20,8,14,24,8,6,8,18,9,13,27,82,84,84,72,66,78, +72,72,70,60,70,64,48,38,12,62,64,56,44,42,40,24,18,8,8,9, +15,19,35,82,82,80,72,54,60,54,38,36,26,18,1,5,19,35,5,3, +41,16,14,4,11,7,11,21,11,25,27,49,43,57,71,11,33,43,27,17, +2,13,18,34,9,9,12,20,8,18,36,8,2,96,56,18,9,31,71,97, +125,125,0,78,58,48,28,40,18,8,4,15,25,15,4,11,18,32,3,7, +10,18,12,16,34,16,4,96,56,18,9,31,71,97,125,125,0,0,0,0, +94,12,29,94,12,29,39,9,40,22,4,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, +44,0,0,0,9,57,67,4,4,5,104,14,11,73,35,37,0,21,41,29, +51,5,41,35,33,65,65,67,67,38,1,6,39,3,33,21,33,17,47,33, +63,28,21,3,53,37,11,17,0,14,4,3,24,18,19,0,2,3,4,21, +24,2,26,38,16,34,34,24,3,22,6,2,10,39,47,25,33,13,23,17, +8,13,17,5,1,15,17,5,47,51,25,63,9,23,12,5,11,30,2,3, +11,30,15,31,2,53,52,62,52,50,62,48,22,54,50,1,20,24,8,2, +15,14,2,2,8,1,13,8,1,33,13,13,27,17,51,84,92,80,84,80, +70,66,70,58,42,46,32,10,6,35,46,36,2,44,26,24,14,6,1,3, +13,37,11,31,57,45,73,5,62,42,28,10,10,1,9,17,25,8,88,58, +46,34,48,16,2,7,13,19,64,38,22,10,18,0,11,19,39,31,22,4, +0,7,3,23,31,47,3,76,44,28,12,26,0,7,11,23,124,39,21,5, +5,11,2,14,16,7,12,24,24,27,15,17,8,24,8,4,22,32,36,7, +6,28,28,27,17,29,43,31,15,27,17,21,13,7,17,17,15,5,19,21, +35,49,19,69,25,5,13,12,11,3,24,5,9,5,18,17,15,49,68,70, +74,62,44,64,56,48,44,40,40,32,3,5,19,18,20,4,23,0,1,15, +17,19,19,23,51,39,53,84,82,78,72,54,56,50,32,38,28,24,4,1, +13,29,42,46,1,44,48,26,14,16,10,4,8,3,15,23,31,41,63,11, +31,51,59,33,43,7,9,7,66,12,10,9,30,90,62,102,14,82,72,32, +2,15,25,77,83,95,13,84,56,38,18,24,4,3,9,27,41,25,5,15, +8,12,1,1,12,18,20,10,28,26,2,82,74,56,42,30,18,21,35,49, +0,0,0,0,94,12,29,94,12,29,39,9,40,22,4,8,20,76,116,32, +17,9,4,10,8,1,3,11,21,24,2,55,73,91,14,27,11,4,10,8, +29,11,22,16,3,21,33,2,29,37,63,12,11,23,8,25,23,47,1,23, +15,37,1,4,44,0,0,0,9,57,67,4,4,5,56,4,39,5,2,11, +46,40,1,4,25,4,27,19,13,33,35,39,43,48,3,6,17,11,43,25, +29,8,5,3,19,30,9,0,19,37,13,21,13,0,9,21,7,2,33,17, +116,92,30,16,8,13,1,8,2,20,8,3,25,3,13,13,9,10,18,20, +10,10,14,18,38,22,12,8,6,4,18,22,39,1,10,15,16,20,34,26, +4,38,24,28,7,8,4,6,30,51,24,40,34,46,50,40,40,62,58,20, +42,50,3,124,17,32,16,22,26,24,32,28,44,0,12,14,24,124,29,74, +80,70,64,62,56,50,48,42,24,18,14,4,3,45,23,23,51,14,8,4, +2,15,19,19,9,31,25,35,53,37,73,25,32,26,20,10,8,3,11,15, +19,9,58,36,26,12,20,1,7,15,29,10,70,54,44,40,32,10,2,5, +15,11,88,60,30,8,24,0,19,25,14,98,80,58,38,44,8,3,9,15, +124,59,49,29,43,41,29,29,21,23,25,19,13,31,29,37,41,13,31,25, +23,13,9,13,15,9,13,11,13,31,10,12,22,6,1,12,8,6,6,4, +2,3,1,7,15,9,12,35,2,32,0,18,8,14,24,8,4,8,18,11, +13,29,80,82,84,70,62,74,68,68,66,56,64,58,42,32,8,54,56,48, +34,36,34,18,14,4,6,11,17,19,37,78,78,76,68,50,56,50,32,32, +22,14,5,9,23,39,5,5,43,14,12,0,15,9,13,25,13,29,29,49, +45,57,73,15,35,45,27,15,4,13,20,38,7,7,14,22,8,20,38,8, +2,94,52,14,15,37,79,105,125,125,0,78,58,50,30,42,20,10,6,15, +25,15,4,9,20,34,3,5,10,18,12,18,36,16,4,94,52,14,15,37, +79,105,125,125,0,0,0,0,92,12,29,92,12,29,35,5,40,22,2,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,44,0,0,0,9,57,67,6,2,5,104,14, +11,71,33,37,2,17,39,25,49,3,39,31,29,63,63,65,67,40,1,8, +37,3,33,19,29,17,47,31,61,28,19,1,51,35,11,17,2,14,4,1, +26,20,21,1,2,3,4,21,24,0,24,38,16,34,34,22,7,22,4,1, +8,41,45,23,31,11,21,15,10,11,15,3,0,15,17,3,49,51,23,63, +9,23,12,5,13,32,2,3,15,32,15,33,2,55,48,60,50,48,60,46, +20,52,50,3,18,24,8,2,17,12,2,0,8,3,15,6,3,37,15,15, +29,19,51,80,90,76,80,76,66,60,66,52,38,42,26,6,2,39,42,34, +1,38,22,20,10,0,5,9,17,43,13,33,61,47,73,5,62,44,28,10, +10,1,9,17,25,10,90,58,46,34,50,16,4,7,11,17,66,40,22,10, +20,0,9,19,37,31,24,4,0,7,1,21,31,45,3,78,44,28,12,28, +2,5,9,21,124,39,21,5,5,11,2,14,16,5,12,24,24,27,15,17, +6,26,6,2,20,30,36,9,4,26,28,29,19,29,41,31,13,25,17,19, +13,5,17,17,15,5,21,21,35,47,17,69,25,3,13,12,11,3,26,5, +9,5,20,17,17,51,66,70,72,60,42,62,54,46,42,38,38,30,5,7, +21,14,16,2,27,1,3,17,19,21,19,23,51,39,51,80,78,74,66,48, +52,46,26,34,24,20,0,5,17,31,38,42,3,40,44,22,10,12,6,0, +4,7,21,27,35,45,65,15,35,53,57,31,41,7,7,5,70,14,12,9, +32,92,66,104,14,78,68,26,3,21,31,83,87,97,13,84,56,38,18,24, +4,3,9,27,39,23,3,13,10,14,1,0,14,20,22,12,28,28,2,78, +70,52,38,26,14,25,39,51,0,0,0,0,92,12,29,92,12,29,35,5, +40,22,2,6,16,74,116,32,13,9,4,12,6,1,3,13,25,22,3,61, +77,95,20,25,11,4,12,6,29,9,22,14,3,19,31,2,29,37,63,12, +11,23,8,25,21,45,1,23,15,37,0,4,44,0,0,0,9,57,67,6, +2,5,54,2,39,0,4,9,50,44,0,8,23,6,23,17,9,33,33,37, +43,48,3,8,13,11,41,25,25,8,7,5,21,30,9,2,19,35,11,21, +11,0,7,17,5,4,31,15,124,100,36,22,8,11,1,8,2,20,10,3, +25,0,13,17,13,16,18,22,10,10,14,18,40,24,14,6,6,4,18,22, +41,1,10,17,16,18,34,24,4,38,24,28,9,8,2,4,30,51,24,38, +32,42,44,38,36,58,54,16,36,46,15,124,25,28,12,16,20,18,26,18, +36,5,8,6,20,124,31,70,76,66,60,58,52,46,44,38,18,14,10,0, +7,49,23,23,53,12,6,2,1,17,21,21,11,33,27,37,53,39,71,21, +34,28,20,12,8,3,11,13,15,5,58,38,28,12,22,0,5,13,25,10, +72,56,46,40,34,12,2,3,15,11,88,60,30,6,24,0,19,25,14,96, +78,56,36,44,8,1,9,15,124,55,45,27,39,39,27,27,19,21,21,17, +9,29,27,37,39,9,31,25,23,13,9,13,17,9,13,11,13,33,12,12, +24,6,1,12,8,6,6,4,2,3,1,7,15,9,12,37,0,32,1,18, +6,12,24,6,2,8,18,13,13,31,78,80,82,66,58,70,64,62,60,50, +58,52,36,28,4,44,48,40,24,30,28,14,10,1,2,15,21,21,37,72, +72,70,64,44,50,44,26,28,16,10,11,13,27,41,7,5,47,12,8,1, +19,13,17,27,15,31,31,51,49,59,73,17,39,49,25,15,6,11,22,40, +7,5,14,22,8,20,40,8,2,92,48,8,21,45,87,113,125,125,2,78, +58,50,30,42,20,10,6,13,25,15,6,9,22,36,3,5,12,20,12,18, +36,16,4,92,48,8,21,45,87,113,125,125,0,0,0,0,90,12,31,90, +12,31,31,3,42,22,2,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,44,0,0,0, +7,57,67,6,2,7,104,14,11,69,33,37,2,15,35,21,45,1,35,29, +25,61,61,63,65,42,1,10,37,1,31,19,25,17,45,31,59,28,19,1, +47,35,9,15,2,14,4,0,26,20,21,1,2,3,4,21,24,0,24,38, +14,34,34,22,11,22,4,5,6,43,45,21,31,11,19,15,12,11,15,3, +4,15,17,3,51,49,21,63,9,23,14,3,15,32,2,3,17,34,17,35, +2,57,46,58,50,48,58,46,20,50,48,5,16,24,8,2,17,10,0,1, +6,3,17,4,3,41,17,15,31,21,51,78,86,74,76,72,62,56,62,48, +32,38,22,0,3,45,38,30,3,34,16,14,4,3,11,13,23,47,15,37, +63,49,73,3,64,44,30,10,10,1,9,17,23,10,90,60,46,34,52,18, +4,5,11,15,68,40,24,10,22,2,9,17,35,29,26,6,2,7,1,21, +29,41,1,78,44,28,14,28,2,3,9,19,124,37,19,3,5,11,2,14, +16,5,14,24,26,27,15,19,6,26,4,0,18,28,36,11,2,26,28,29, +21,31,39,29,11,25,15,19,11,5,17,15,13,3,21,21,35,47,15,69, +25,3,13,14,11,3,28,7,9,5,20,19,17,53,64,68,72,58,40,62, +54,44,40,38,36,28,7,9,23,12,14,1,31,5,7,19,19,21,19,23, +49,41,49,76,74,70,62,42,48,42,22,30,18,16,5,9,19,31,36,40, +7,36,38,18,6,8,2,3,1,11,25,31,39,47,69,19,39,57,55,29, +39,5,5,3,72,16,14,9,34,96,68,108,16,76,66,22,9,27,35,89, +91,101,11,84,56,38,18,24,4,3,9,25,37,23,1,11,12,14,0,2, +14,20,22,12,30,28,2,76,68,48,34,24,12,31,41,53,0,0,0,0, +90,12,31,90,12,31,31,3,42,22,2,2,12,72,116,32,11,9,6,12, +6,3,1,13,27,18,7,69,83,97,24,23,11,6,12,6,31,9,22,14, +3,19,31,2,29,35,61,12,9,21,8,23,21,45,1,23,15,37,0,4, +44,0,0,0,7,57,67,6,2,7,54,2,39,4,6,7,52,50,4,10, +19,10,21,15,5,33,33,37,43,48,3,10,7,11,39,23,21,6,7,5, +21,32,9,2,17,35,11,19,9,2,5,15,1,4,29,13,124,110,42,28, +8,11,1,10,2,20,10,1,23,4,11,21,17,22,18,22,10,10,16,20, +44,26,14,6,6,4,20,24,43,1,10,17,14,16,32,24,2,38,24,28, +13,8,0,2,28,51,24,38,32,38,38,36,32,52,48,12,32,42,29,124, +31,24,10,12,12,14,20,10,26,11,4,0,16,124,35,66,72,62,54,52, +48,40,40,34,14,8,6,3,9,51,23,23,53,10,4,0,3,19,23,23, +15,35,27,39,55,39,71,19,36,28,20,12,10,1,9,13,11,3,60,38, +28,14,24,2,1,9,21,12,72,56,46,42,36,12,2,3,13,11,90,60, +28,6,24,0,19,23,12,96,78,54,34,42,8,1,9,15,124,53,43,25, +37,35,25,23,15,19,19,13,5,29,25,35,37,5,29,25,23,11,7,13, +17,9,15,11,13,33,12,14,26,6,1,14,10,6,8,6,2,5,1,7, +15,9,14,39,1,32,3,16,4,12,24,4,2,8,16,17,15,33,74,78, +80,64,54,66,60,58,56,46,52,48,30,22,0,36,40,32,16,22,22,8, +6,5,1,19,23,23,39,68,68,66,58,38,46,40,20,22,12,4,17,17, +29,45,9,7,49,8,6,5,23,15,21,31,17,35,33,53,51,61,75,21, +41,51,25,13,6,11,24,42,7,5,16,24,8,22,42,8,2,90,44,4, +27,51,95,121,125,125,2,78,58,50,30,44,22,10,6,13,23,13,6,7, +24,38,1,3,12,20,12,18,38,16,4,90,44,4,27,51,95,121,125,125, +0,0,0,0,86,12,31,86,12,31,29,0,42,22,0,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,44,0,0,0,7,59,67,8,0,7,104,14,11,67,31,37, +4,13,31,17,43,0,31,27,21,59,61,61,63,42,1,12,35,1,31,17, +21,17,45,29,57,28,19,0,45,33,7,15,2,14,4,0,28,22,23,1, +2,3,4,21,24,1,22,38,12,34,34,22,15,22,2,9,4,45,43,19, +29,9,19,13,14,9,13,1,6,15,17,3,53,49,19,63,9,23,16,3, +17,34,2,3,19,36,17,37,2,59,42,56,48,46,56,44,18,48,48,9, +14,22,8,2,19,8,1,3,4,5,19,2,5,45,19,17,33,23,51,74, +84,70,72,68,58,52,58,42,28,34,16,3,7,49,34,26,7,30,12,10, +0,7,15,19,27,53,17,41,65,51,73,3,64,44,30,10,10,1,9,17, +23,10,90,60,46,34,54,18,6,5,9,15,70,42,24,10,22,2,7,17, +33,27,28,8,2,7,0,19,27,39,1,78,44,28,14,30,4,3,7,17, +124,37,19,3,5,11,2,14,16,5,14,24,26,27,15,19,4,28,2,1, +16,26,36,15,0,26,28,31,23,31,39,27,9,23,15,17,11,3,19,15, +13,3,23,21,35,45,13,69,25,3,13,16,11,3,30,7,11,5,22,21, +17,55,62,68,70,56,38,60,52,42,38,36,34,26,9,11,25,8,12,3, +35,7,9,21,21,23,19,23,49,41,49,70,68,66,58,36,44,38,16,26, +14,12,9,13,23,33,32,36,9,32,34,14,2,2,1,7,5,15,31,35, +43,51,71,23,43,59,53,27,37,3,3,1,76,18,16,9,36,98,72,110, +18,72,62,16,15,33,41,95,95,103,11,84,56,38,18,24,4,3,9,25, +35,21,0,11,14,16,0,4,16,22,24,12,30,28,2,74,64,44,30,20, +8,35,45,55,0,0,0,0,86,12,31,86,12,31,29,0,42,22,0,0, +8,70,116,30,7,9,6,14,6,3,1,15,31,16,13,75,87,101,30,21, +11,6,14,6,31,7,22,12,3,19,29,2,29,35,61,12,9,21,8,23, +19,45,1,23,15,37,0,4,44,0,0,0,7,59,67,8,0,7,52,0, +39,10,8,5,56,54,6,14,15,12,19,13,1,33,33,35,43,48,3,12, +3,11,39,23,17,6,9,7,23,32,9,4,17,33,9,19,7,2,5,11, +0,6,27,11,124,118,48,34,8,11,1,10,2,20,12,1,23,8,11,25, +21,26,18,22,10,10,16,20,46,28,14,6,6,4,20,26,45,1,10,19, +14,14,32,24,2,38,24,28,15,8,1,0,28,51,22,36,30,34,30,34, +28,48,44,8,26,38,41,124,39,20,6,8,6,8,12,2,18,17,0,7, +12,124,39,62,68,56,50,48,44,36,36,30,10,4,2,7,13,55,23,23, +55,8,2,1,5,21,27,25,19,37,29,41,57,41,69,15,38,30,20,12, +12,1,9,11,7,1,60,38,30,16,26,4,0,7,19,14,74,58,48,42, +38,14,2,3,13,11,90,60,26,6,24,0,19,23,12,94,76,52,32,42, +8,1,9,15,124,51,39,23,33,33,23,19,11,17,15,9,1,27,23,35, +35,3,29,25,23,11,7,13,17,9,15,11,13,35,14,14,28,6,1,14, +10,6,8,6,2,5,1,7,15,9,14,41,3,32,5,14,2,10,24,2, +0,8,16,19,15,35,72,76,78,60,50,62,56,54,50,40,46,42,24,18, +3,28,32,24,6,16,14,4,0,11,5,23,27,25,41,64,62,60,54,32, +40,34,14,18,6,0,23,21,33,47,11,9,53,6,2,9,27,19,25,35, +19,37,35,55,53,63,77,23,43,53,25,13,8,9,26,44,7,3,16,24, +8,22,44,8,2,88,40,1,33,57,103,125,125,125,2,78,58,50,30,44, +22,10,6,11,23,13,8,7,24,40,1,3,12,20,12,18,38,16,4,88, +40,1,33,57,103,125,125,125,0,0,0,0,84,12,31,84,12,31,25,2, +42,22,0,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,44,0,0,0,5,59,67,8, +1,7,104,14,11,65,29,37,4,9,29,13,39,2,29,23,17,57,59,59, +63,44,1,14,33,1,29,15,17,17,45,29,53,30,17,0,43,33,7,15, +4,16,6,2,28,22,23,3,2,3,4,21,24,1,20,38,12,34,34,20, +19,22,2,11,2,47,41,17,27,7,17,11,16,7,13,0,8,15,17,1, +55,47,17,63,7,23,16,3,19,36,2,3,23,38,19,39,2,59,40,54, +48,44,54,42,16,48,48,11,12,22,8,2,19,8,1,5,4,7,21,2, +7,49,21,19,35,25,51,70,82,66,68,66,54,46,54,38,24,30,12,9, +11,55,30,24,11,24,8,6,3,13,19,25,31,57,19,43,69,51,73,3, +64,46,30,10,10,1,9,17,21,12,92,60,46,34,56,20,8,5,7,13, +72,44,24,12,24,4,7,15,31,27,32,8,2,5,2,17,27,37,0,80, +46,28,14,32,6,1,5,15,124,37,19,1,5,11,2,14,16,3,14,26, +28,27,15,19,2,28,0,3,14,26,36,17,1,24,28,33,25,33,37,27, +7,23,13,17,9,1,19,15,13,3,25,21,35,45,11,69,25,1,13,16, +11,3,32,7,11,5,24,21,19,55,60,68,70,56,36,58,50,40,38,34, +32,24,11,13,27,6,8,7,39,9,11,23,23,23,19,21,49,43,47,66, +64,62,52,32,40,34,12,22,10,8,13,17,25,35,28,32,11,28,30,10, +1,1,5,11,9,19,35,39,47,55,73,27,47,63,51,23,35,3,1,0, +80,20,18,9,38,102,74,114,18,70,58,12,21,37,47,99,99,105,11,84, +56,38,18,24,4,3,9,23,33,19,2,9,16,18,2,6,18,24,26,14, +32,30,2,70,62,42,28,16,4,39,49,57,0,0,0,0,84,12,31,84, +12,31,25,2,42,22,0,1,4,68,116,30,3,9,6,16,4,5,1,17, +35,14,17,83,93,105,36,19,9,6,16,4,31,5,22,12,3,17,27,2, +29,35,61,12,9,21,8,23,19,43,1,23,15,37,2,4,44,0,0,0, +5,59,67,8,1,7,50,0,39,14,10,3,60,58,10,16,13,16,15,11, +4,33,31,35,41,48,3,14,0,11,37,21,13,6,9,7,23,32,9,4, +15,31,7,17,5,4,3,9,4,8,23,9,124,124,54,40,10,9,0,12, +2,20,12,1,21,12,11,29,25,32,18,24,10,10,16,22,50,30,16,4, +6,4,22,26,47,0,10,19,12,12,30,22,0,38,24,28,17,10,3,0, +26,51,22,34,28,30,24,32,26,44,40,4,22,34,53,124,45,16,2,2, +0,4,6,7,10,21,3,13,8,124,41,58,64,52,46,44,40,32,32,26, +4,0,1,9,17,59,23,23,55,6,0,3,9,23,29,27,21,39,29,43, +57,43,67,13,40,30,20,14,12,0,7,9,3,2,60,40,30,16,28,6, +4,3,15,14,76,60,50,44,40,14,4,1,11,11,92,60,26,4,24,0, +19,21,12,94,74,50,30,42,8,0,9,13,124,47,37,19,29,29,21,17, +9,15,11,7,2,25,21,33,33,0,29,25,21,9,5,13,19,9,17,11, +13,35,14,14,30,6,1,14,10,6,8,6,2,7,1,7,15,9,16,43, +5,32,7,14,2,8,24,2,1,8,16,21,15,37,70,74,76,56,46,58, +52,48,46,34,40,36,18,12,7,18,24,16,3,10,8,1,3,15,9,25, +29,25,41,58,58,56,50,26,34,30,8,14,2,3,29,25,37,51,11,9, +57,4,0,11,31,23,29,37,21,41,37,55,57,65,77,27,47,57,23,13, +10,9,28,46,5,1,18,26,8,24,46,8,2,86,36,7,39,65,111,125, +125,125,4,78,58,50,30,46,22,12,8,11,23,13,8,7,26,42,1,3, +14,22,12,20,40,16,4,86,36,7,39,65,111,125,125,125,0,0,0,0, +82,12,31,82,12,31,21,6,44,22,1,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, +44,0,0,0,5,59,67,10,3,7,104,14,11,63,27,37,6,7,25,9, +37,4,25,21,13,55,57,57,61,46,1,16,31,1,29,15,13,17,43,27, +51,30,17,2,39,31,5,15,4,16,6,4,30,24,25,3,2,3,4,21, +24,3,20,38,10,34,34,20,23,22,0,15,0,49,39,15,25,5,15,11, +18,7,11,2,10,15,17,1,57,47,15,63,7,23,18,3,21,38,2,3, +25,40,19,41,2,61,36,52,46,42,52,40,16,46,46,13,10,22,8,2, +21,6,3,7,2,9,23,0,7,53,23,19,37,27,51,68,78,64,64,62, +50,42,50,32,18,26,6,13,17,59,26,20,13,20,4,0,9,17,25,29, +35,63,21,47,71,53,73,3,66,46,30,10,10,1,9,17,21,12,92,60, +46,34,58,20,8,3,7,11,74,44,26,12,26,4,5,15,29,25,34,10, +4,5,4,15,25,35,0,80,46,28,14,34,6,0,3,13,124,35,17,1, +5,11,2,14,16,3,14,26,28,27,15,19,2,30,1,5,12,24,36,19, +3,24,28,33,27,33,35,25,5,21,13,15,9,0,19,15,13,1,25,21, +35,43,9,69,25,1,13,18,11,3,34,7,11,5,26,23,19,57,58,66, +68,54,34,56,48,38,36,32,30,22,13,15,29,2,6,9,43,13,13,25, +23,25,19,21,49,43,45,62,60,58,48,26,36,30,6,18,6,4,19,21, +29,37,24,30,15,24,26,6,5,5,9,15,13,23,41,43,51,59,75,31, +51,65,49,21,33,1,0,2,82,22,20,9,40,104,78,116,20,66,56,6, +27,43,53,105,103,107,11,84,56,38,18,24,4,3,9,23,31,17,4,7, +18,18,2,8,18,24,26,14,32,30,2,68,58,38,24,12,0,43,53,59, +0,0,0,0,82,12,31,82,12,31,21,6,44,22,1,5,0,66,116,30, +0,9,8,18,4,5,1,17,37,12,23,89,97,107,42,17,9,8,18,4, +33,3,22,10,3,17,27,2,29,35,61,12,9,19,8,23,17,43,1,23, +15,37,2,4,44,0,0,0,5,59,67,10,3,7,48,1,39,20,12,1, +62,62,12,20,9,18,13,9,8,33,31,33,41,48,3,16,4,11,35,21, +9,6,11,9,25,32,9,6,15,29,5,17,3,4,1,5,6,8,21,7, +124,124,60,46,10,9,0,12,2,20,14,0,21,16,11,33,29,38,18,24, +10,10,16,22,52,32,16,4,6,4,22,28,49,0,10,21,12,10,30,22, +0,38,24,28,19,10,5,1,26,51,22,34,28,26,18,30,22,40,34,0, +16,30,67,124,53,12,1,1,5,1,0,15,2,27,7,21,4,124,45,54, +60,48,40,38,36,28,28,22,0,3,5,13,19,63,23,23,57,4,1,5, +11,25,31,29,25,41,31,45,59,43,67,9,42,32,20,14,14,0,7,9, +0,4,60,40,32,18,30,8,6,1,11,16,76,60,50,44,42,16,4,1, +11,11,92,60,24,4,24,0,19,21,12,92,74,48,28,42,8,0,9,13, +124,45,33,17,27,27,19,13,5,13,9,3,6,25,19,33,31,4,27,25, +21,9,5,13,19,9,17,11,13,37,16,16,32,6,1,16,10,6,8,6, +2,7,1,7,15,9,16,45,7,32,9,12,0,8,24,0,3,8,16,23, +15,39,68,72,74,54,42,54,48,44,40,30,34,30,12,8,11,10,16,8, +13,2,2,5,7,21,13,29,33,27,43,54,52,50,44,20,30,24,2,8, +3,9,35,29,41,53,13,11,59,0,3,15,35,25,33,41,23,43,39,57, +59,67,79,29,49,59,23,11,10,7,30,48,5,1,18,26,8,24,48,8, +2,84,32,11,45,71,119,125,125,125,4,78,58,50,30,46,24,12,8,9, +23,13,10,5,28,44,1,1,14,22,12,20,40,16,4,84,32,11,45,71, +119,125,125,125,0,0,0,0,80,12,31,80,12,31,17,8,44,22,1,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,44,0,0,0,3,59,67,10,5,7,104,14, +11,61,25,37,6,5,21,5,33,6,21,19,9,53,55,55,59,48,1,18, +29,1,27,13,9,17,43,27,49,30,17,2,37,31,3,15,4,16,6,6, +30,24,25,3,2,3,4,21,24,3,18,38,8,34,34,20,27,22,0,19, +1,51,37,13,23,3,13,9,20,5,11,4,12,15,17,1,59,45,13,63, +7,23,20,3,23,40,2,3,27,42,21,43,2,63,34,50,46,40,50,38, +14,44,46,15,8,22,8,2,21,4,5,9,0,11,25,1,9,57,25,21, +39,29,51,64,76,60,60,58,46,38,46,28,14,22,2,19,21,65,22,16, +17,16,0,3,13,21,29,35,39,67,23,51,73,55,73,3,66,46,30,10, +10,1,9,17,19,12,92,60,46,34,60,22,10,3,5,9,76,46,26,12, +28,6,5,13,27,23,36,12,4,5,6,13,23,33,2,80,46,28,14,36, +8,2,1,11,124,35,17,0,5,11,2,14,16,3,14,26,30,27,15,19, +0,30,3,7,10,22,36,21,5,24,28,35,29,35,33,23,3,21,11,15, +7,2,19,15,13,1,27,21,35,43,7,69,25,1,13,20,11,3,36,7, +11,5,28,25,19,59,56,66,68,52,32,54,46,36,34,30,28,20,15,17, +31,0,4,13,47,15,15,27,25,25,19,21,49,45,43,58,56,54,44,20, +32,26,2,14,2,0,23,25,31,39,20,26,17,20,22,2,9,9,13,19, +17,27,45,47,55,63,77,35,55,69,47,19,31,0,2,4,86,24,22,9, +42,108,80,120,22,64,52,2,33,49,59,111,107,109,11,84,56,38,18,24, +4,3,9,21,29,15,6,5,20,20,4,10,20,26,28,14,34,30,2,66, +56,34,20,8,3,47,57,61,0,0,0,0,80,12,31,80,12,31,17,8, +44,22,1,7,3,64,116,30,4,9,8,20,4,7,1,19,41,10,27,97, +103,111,48,15,9,8,20,4,33,1,22,10,3,17,25,2,29,35,61,12, +9,19,8,23,17,43,1,23,15,37,2,4,44,0,0,0,3,59,67,10, +5,7,46,1,39,24,14,0,66,66,16,22,5,22,11,7,12,33,31,33, +41,48,3,18,8,11,33,19,5,6,11,9,25,32,9,6,13,27,3,15, +1,6,0,3,10,10,19,5,124,124,66,52,10,9,0,14,2,20,14,0, +19,20,11,37,33,44,18,24,10,10,16,24,56,34,16,4,6,4,24,30, +51,0,10,21,10,8,28,22,1,38,24,28,21,10,7,3,24,51,22,32, +26,22,12,28,18,36,30,3,12,26,79,124,59,8,5,5,11,5,5,23, +5,33,11,27,0,124,49,50,56,44,36,34,32,24,24,18,3,7,9,17, +23,67,23,23,57,2,3,7,13,27,33,31,29,43,31,47,61,45,65,7, +44,32,20,14,16,2,5,7,4,6,60,40,32,20,32,10,10,2,7,18, +78,62,52,46,44,16,4,1,9,11,94,60,22,4,24,0,19,19,12,92, +72,46,26,42,8,0,9,13,124,43,31,15,23,23,17,9,1,11,5,0, +10,23,17,31,29,8,27,25,21,7,3,13,19,9,19,11,13,37,16,16, +34,6,1,16,10,6,8,6,2,9,1,7,15,9,18,47,9,32,11,10, +1,6,24,1,5,8,16,25,15,41,66,70,72,50,38,50,44,40,36,24, +28,24,6,2,15,2,8,0,23,3,3,11,11,25,17,33,35,29,45,50, +48,46,40,14,24,20,3,4,7,13,41,33,45,57,15,13,63,1,5,19, +39,29,37,45,25,47,41,59,61,69,81,33,51,61,23,11,12,7,32,50, +5,0,20,28,8,26,50,8,2,82,28,17,51,77,125,125,125,125,4,78, +58,50,30,48,24,12,8,9,23,13,10,5,30,46,1,1,14,22,12,20, +42,16,4,82,28,17,51,77,125,125,125,125,0,0,0,0,76,10,33,76, +10,33,15,10,44,22,3,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,44,0,0,0, +3,61,67,10,7,9,104,12,11,59,25,37,6,3,19,3,31,8,19,17, +7,51,55,53,59,48,1,18,29,1,27,13,7,17,43,27,47,30,17,2, +35,31,3,15,4,16,6,6,30,24,27,5,2,5,4,21,22,5,16,38, +6,32,34,18,31,20,1,23,3,53,37,13,23,3,13,9,22,5,11,4, +14,17,17,1,63,45,13,63,7,25,20,3,25,40,2,3,31,42,23,45, +2,65,30,48,44,38,48,36,12,42,44,19,6,20,6,2,23,2,7,11, +1,13,27,3,11,61,29,23,43,33,51,60,72,56,56,54,40,32,40,22, +8,16,3,25,27,71,18,12,21,10,5,9,19,27,35,41,45,73,25,55, +77,57,75,3,66,46,30,10,10,3,9,17,19,12,92,60,46,34,62,22, +10,3,5,9,76,46,26,12,28,6,5,13,25,23,38,12,4,5,6,13, +23,31,2,80,46,28,14,36,8,2,1,11,124,35,17,0,5,11,2,14, +16,3,14,26,30,27,15,21,1,30,5,9,8,20,34,25,9,22,26,37, +33,37,33,23,1,21,11,15,7,2,21,15,13,1,29,21,35,43,7,71, +25,1,13,20,13,3,36,9,13,5,28,27,21,61,54,64,66,50,28,52, +44,34,32,28,26,18,17,21,35,3,0,17,51,19,19,29,27,27,19,21, +49,47,43,52,50,50,38,14,26,20,3,8,3,5,29,31,35,41,16,22, +21,16,16,3,15,15,19,23,23,33,51,51,61,67,81,39,59,73,45,17, +29,0,2,4,88,24,22,9,42,110,82,122,22,60,48,3,41,55,65,117, +113,113,11,84,54,36,18,24,4,5,9,21,29,15,6,5,22,20,4,10, +20,26,28,14,34,30,0,62,52,30,16,4,7,53,61,63,0,0,0,0, +76,10,33,76,10,33,15,10,44,22,3,11,9,62,116,28,6,11,8,20, +2,9,1,21,45,6,33,105,109,115,52,15,9,8,20,2,35,1,22,8, +3,17,25,0,31,35,61,10,9,19,8,23,17,43,1,23,17,37,2,4, +44,0,0,0,3,61,67,10,7,9,44,3,41,28,16,2,68,70,18,24, +3,24,9,5,16,33,31,33,41,48,3,18,12,11,33,19,3,4,13,11, +27,32,9,6,13,27,3,15,1,6,0,1,12,10,17,3,124,124,72,56, +10,9,0,14,0,20,14,0,19,24,11,41,37,48,18,24,10,10,16,24, +58,34,16,2,4,4,24,30,55,0,10,23,8,4,26,20,3,38,24,26, +25,10,9,5,22,51,20,30,24,16,4,24,14,30,24,9,6,22,93,124, +67,2,9,11,19,11,13,33,15,39,15,35,3,124,53,44,50,38,30,28, +26,18,18,14,9,13,13,21,27,71,23,25,59,0,7,11,17,31,37,35, +33,45,33,49,63,47,65,5,44,32,20,14,16,2,5,7,8,8,60,40, +32,20,32,12,12,4,5,18,78,62,52,46,46,16,4,1,9,13,94,58, +20,2,24,0,19,19,10,90,70,42,24,40,8,0,9,13,124,41,29,13, +21,21,15,7,0,9,3,2,14,23,17,31,27,10,27,25,21,7,3,13, +21,11,21,11,15,39,16,16,36,6,3,16,10,4,8,6,2,11,1,7, +15,9,18,49,11,32,15,8,3,4,22,3,7,8,14,29,17,45,62,66, +70,46,34,44,38,34,30,18,22,18,1,3,19,7,0,9,33,11,11,17, +17,31,21,37,39,31,47,44,42,40,34,8,18,14,11,1,13,19,47,37, +49,61,17,15,67,5,9,23,45,33,41,49,29,51,45,61,65,71,83,37, +55,65,23,11,12,7,34,52,5,0,20,28,8,26,50,8,0,78,24,23, +59,85,125,125,125,125,4,78,58,50,30,48,24,12,8,9,23,13,10,5, +30,46,1,1,14,22,12,20,42,14,2,78,24,23,59,85,125,125,125,125, +0,0,0,0,74,10,33,74,10,33,11,14,46,24,3,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,44,0,0,0,1,61,67,12,7,9,104,12,11,55,23,37, +8,0,15,0,27,12,15,13,3,47,53,51,57,50,0,20,27,0,25,11, +3,15,41,25,43,32,15,4,31,29,1,13,6,18,8,8,32,26,27,5, +4,5,4,19,22,5,16,38,6,32,34,18,33,20,1,25,5,53,35,11, +21,1,11,7,24,3,9,6,18,17,17,0,65,43,11,63,5,25,22,1, +25,42,2,3,33,44,23,47,2,65,28,48,44,38,48,36,12,42,44,21, +6,20,6,2,23,2,7,11,1,13,29,3,11,63,31,23,45,35,51,58, +70,54,54,52,36,28,36,18,4,12,7,29,31,75,16,10,23,6,9,13, +23,31,39,45,49,77,25,57,79,57,75,1,68,48,32,12,10,3,7,15, +17,14,94,62,48,34,64,24,12,1,3,7,78,48,28,14,30,8,3,11, +21,21,42,14,6,3,8,11,21,27,4,82,48,30,16,38,10,4,0,9, +124,33,15,2,5,9,2,16,18,1,16,28,32,25,15,21,1,32,5,9, +6,20,34,27,11,22,26,37,35,37,31,21,0,19,9,13,5,4,21,13, +11,0,29,19,33,41,5,71,25,0,13,22,13,3,38,9,13,3,30,27, +21,61,54,64,66,50,26,52,44,34,32,28,26,18,17,23,37,5,1,19, +53,21,21,29,27,27,17,19,47,47,41,48,46,46,34,10,22,16,7,4, +7,9,33,35,37,41,14,20,23,14,12,7,19,19,23,27,27,37,55,53, +65,69,83,41,61,75,41,13,25,2,4,6,92,26,24,9,44,114,86,124, +24,58,46,7,47,59,69,121,117,115,9,86,54,36,18,26,4,5,9,19, +27,13,8,3,26,22,6,12,22,28,30,16,36,32,0,60,50,28,14,2, +9,57,63,63,0,0,0,0,74,10,33,74,10,33,11,14,46,24,3,13, +13,60,118,28,10,11,10,22,2,9,0,21,47,4,37,111,113,117,58,13, +7,10,22,2,35,0,22,8,1,15,23,0,31,33,59,10,7,17,8,21, +15,41,0,21,17,35,4,4,44,0,0,0,1,61,67,12,7,9,44,3, +41,34,20,6,72,76,22,28,0,28,5,1,22,33,29,31,39,48,3,20, +18,9,31,17,0,4,13,11,27,34,9,8,11,25,1,13,0,8,2,2, +16,12,13,0,124,124,80,62,12,7,2,16,0,22,16,2,17,30,9,45, +39,54,18,26,10,12,18,26,62,36,18,2,4,4,26,32,57,2,10,23, +8,2,26,20,3,38,24,26,27,12,9,5,22,51,20,30,24,12,1,22, +12,26,20,13,2,18,105,124,73,1,11,15,25,15,19,41,23,43,19,41, +7,124,55,40,46,34,26,24,22,14,14,10,13,17,15,23,29,73,23,25, +59,0,9,13,19,33,39,37,35,47,33,51,63,47,63,1,46,34,20,16, +18,4,3,5,14,12,62,42,34,22,34,16,16,8,1,20,80,64,54,48, +48,18,6,0,7,13,96,58,20,2,26,2,19,17,10,90,70,40,22,40, +10,2,7,11,124,37,25,9,17,17,11,3,4,5,0,6,20,21,15,29, +23,14,25,23,19,5,1,11,21,11,21,11,15,39,18,18,38,8,3,18, +12,4,10,8,2,11,0,5,13,7,20,49,13,32,17,8,3,4,22,3, +7,8,14,31,17,47,60,64,70,44,32,40,34,30,26,14,18,14,7,7, +23,15,5,17,41,17,17,21,21,35,23,39,41,31,47,40,38,36,30,4, +14,10,17,5,17,23,51,39,51,63,17,15,69,7,11,25,49,35,43,51, +31,53,47,61,67,71,83,39,57,67,21,9,14,5,38,56,3,2,22,30, +10,28,52,8,0,76,20,27,65,91,125,125,125,125,6,78,60,52,32,50, +26,14,10,7,21,11,12,3,32,48,0,0,16,24,12,22,44,14,2,76, +20,27,65,91,125,125,125,125,0,0,0,0,72,10,33,72,10,33,7,16, +46,24,3,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,44,0,0,0,0,61,67,12, +9,9,104,12,11,53,21,37,8,2,11,4,25,14,11,11,0,45,51,49, +55,52,0,22,25,0,25,9,0,15,41,25,41,32,15,4,29,29,0,13, +6,18,8,10,32,26,29,5,4,5,4,19,22,5,14,38,4,32,34,18, +37,20,1,29,7,55,33,9,19,0,9,5,26,1,9,8,20,17,17,0, +67,43,9,63,5,25,24,1,27,44,2,3,35,46,25,49,2,67,24,46, +42,36,46,34,10,40,44,23,4,20,6,2,23,0,9,13,3,15,31,5, +13,67,33,25,47,37,51,54,68,50,50,48,32,24,32,12,0,8,13,35, +35,81,12,6,27,2,13,17,27,35,43,51,53,81,27,61,81,59,75,1, +68,48,32,12,10,3,7,15,15,14,94,62,48,34,66,24,14,1,1,5, +80,50,28,14,32,8,3,9,19,19,44,16,6,3,10,9,19,25,4,82, +48,30,16,40,12,6,2,7,124,33,15,2,5,9,2,16,18,1,16,28, +34,25,15,21,3,32,7,11,4,18,34,29,13,22,26,39,37,39,29,19, +2,19,9,13,3,6,21,13,11,0,31,19,33,41,3,71,25,0,13,24, +13,3,40,9,13,3,32,29,21,63,52,64,66,48,24,50,42,32,30,26, +24,16,19,25,39,9,3,23,57,23,23,31,29,27,17,19,47,49,39,44, +42,42,30,4,18,12,13,0,11,13,37,39,39,43,10,16,25,10,8,11, +23,23,27,31,31,41,59,57,69,73,85,45,65,79,39,11,23,4,6,8, +96,28,26,9,46,116,88,124,26,56,42,13,53,65,75,125,121,117,9,86, +54,36,18,26,4,5,9,17,25,11,10,1,28,24,8,14,24,30,32,16, +38,32,0,58,46,24,10,1,13,61,67,65,0,0,0,0,72,10,33,72, +10,33,7,16,46,24,3,15,17,58,118,28,14,11,10,24,2,11,0,23, +51,2,43,119,119,121,64,11,7,10,24,2,35,2,22,6,1,15,21,0, +31,33,59,10,7,17,8,21,15,41,0,21,17,35,4,4,44,0,0,0, +0,61,67,12,9,9,42,3,41,38,22,8,76,80,24,30,4,30,3,0, +26,33,29,31,39,48,3,22,22,9,29,15,4,4,13,11,29,34,9,8, +9,23,0,11,2,8,4,4,18,14,11,2,124,124,86,68,12,7,2,16, +0,22,16,2,17,34,9,49,43,60,18,26,10,12,18,26,66,38,18,2, +4,4,28,34,59,2,10,23,6,0,24,20,5,38,24,26,29,12,11,7, +20,51,20,28,22,8,7,20,8,22,16,17,1,14,117,124,81,5,15,19, +31,19,25,49,31,49,23,47,11,124,59,36,42,30,22,20,18,10,10,6, +17,21,19,27,33,77,23,25,61,1,11,15,21,35,41,39,39,49,33,53, +65,49,61,0,48,34,20,16,20,6,1,3,18,14,62,42,34,24,36,18, +20,12,2,22,82,66,56,50,50,18,6,0,5,13,98,58,18,2,26,2, +19,17,10,90,68,38,20,40,10,2,7,11,124,35,23,7,13,13,9,0, +8,3,4,10,24,19,13,29,21,18,25,23,19,3,1,11,21,11,23,11, +15,39,18,18,40,8,3,18,12,4,10,8,2,13,0,5,13,7,22,51, +15,32,19,6,5,2,22,5,9,8,14,33,17,49,58,62,68,40,28,36, +30,26,22,8,12,8,13,13,27,23,13,25,51,23,23,27,25,41,27,43, +43,33,49,36,34,30,26,1,8,4,23,9,23,27,57,43,55,67,19,17, +73,9,13,29,53,39,47,55,33,57,49,63,69,73,85,43,59,69,21,9, +16,5,40,58,3,4,24,32,10,28,54,8,0,74,16,33,71,97,125,125, +125,125,6,78,60,52,32,52,26,14,10,7,21,11,12,3,34,50,0,0, +16,24,12,22,46,14,2,74,16,33,71,97,125,125,125,125,0,0,0,0, +70,10,33,70,10,33,3,20,48,24,5,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, +44,0,0,0,0,61,67,14,11,9,104,12,11,51,19,37,10,4,7,8, +21,16,7,9,4,43,49,47,53,54,0,24,23,0,23,9,4,15,39,23, +39,32,15,6,25,27,2,13,6,18,8,12,34,28,29,5,4,5,4,19, +22,7,14,38,2,32,34,18,41,20,3,33,9,57,31,7,17,2,7,5, +28,1,7,10,22,17,17,0,69,41,7,63,5,25,26,1,29,46,2,3, +37,48,25,51,2,69,22,44,42,34,44,32,10,38,42,25,2,20,6,2, +25,1,11,15,5,17,33,7,13,71,35,25,49,39,51,52,64,48,46,44, +28,20,28,8,5,4,17,39,41,85,8,2,29,1,17,23,33,39,49,55, +57,87,29,65,83,61,75,1,70,48,32,12,10,3,7,15,15,14,94,62, +48,34,68,26,14,0,1,3,82,50,30,14,34,10,1,9,17,17,46,18, +8,3,12,7,17,23,6,82,48,30,16,42,12,8,4,5,124,31,13,4, +5,9,2,16,18,1,16,28,34,25,15,21,3,34,9,13,2,16,34,31, +15,22,26,39,39,39,27,17,4,17,7,11,3,8,21,13,11,2,31,19, +33,39,1,71,25,0,13,26,13,3,42,9,13,3,34,31,21,65,50,62, +64,46,22,48,40,30,28,24,22,14,21,27,41,11,5,25,61,27,25,33, +29,29,17,19,47,49,37,40,38,38,26,1,14,8,17,3,15,17,43,43, +43,45,6,14,29,6,4,15,27,27,31,35,35,45,65,61,73,77,87,49, +69,81,37,9,21,6,8,10,98,30,28,9,48,120,92,124,28,52,40,17, +59,71,81,125,125,119,9,86,54,36,18,26,4,5,9,17,23,9,12,0, +30,24,8,16,24,30,32,16,38,32,0,56,44,20,6,5,17,65,71,67, +0,0,0,0,70,10,33,70,10,33,3,20,48,24,5,19,21,56,118,28, +18,11,12,26,2,11,0,23,53,0,47,125,123,123,70,9,7,12,26,2, +37,4,22,6,1,15,21,0,31,33,59,10,7,15,8,21,13,41,0,21, +17,35,4,4,44,0,0,0,0,61,67,14,11,9,40,5,41,44,24,10, +78,84,28,34,8,34,1,2,30,33,29,29,39,48,3,24,26,9,27,15, +8,4,15,13,29,34,9,10,9,21,2,11,4,10,6,8,22,14,9,4, +124,124,92,74,12,7,2,18,0,22,18,4,15,38,9,53,47,66,18,26, +10,12,18,28,68,40,18,2,4,4,28,36,61,2,10,25,6,1,24,20, +5,38,24,26,31,12,13,9,20,51,20,28,22,4,13,18,4,18,10,21, +7,10,125,124,87,9,19,23,37,25,31,57,39,55,27,55,15,124,63,32, +38,26,16,14,14,6,6,2,21,25,23,31,35,81,23,25,61,3,13,17, +23,37,43,41,43,51,35,55,67,49,61,4,50,36,20,16,22,6,1,3, +22,16,62,42,36,26,38,20,22,14,6,24,82,66,56,50,52,20,6,0, +5,13,98,58,16,2,26,2,19,15,10,88,68,36,18,40,10,2,7,11, +124,33,19,5,11,11,7,4,12,1,6,14,28,19,11,27,19,22,23,23, +19,3,0,11,21,11,23,11,15,41,20,20,42,8,3,20,12,4,10,8, +2,13,0,5,13,7,22,53,17,32,21,4,7,2,22,7,11,8,14,35, +17,51,56,60,66,38,24,32,26,22,16,4,6,2,19,17,31,31,21,33, +61,31,29,31,29,45,31,47,47,35,51,32,28,26,20,7,4,0,29,15, +27,33,63,47,59,69,21,19,75,13,17,33,57,41,51,59,35,59,51,65, +71,75,87,45,61,71,21,7,16,3,42,60,3,4,24,32,10,30,56,8, +0,72,12,37,77,103,125,125,125,125,6,78,60,52,32,52,28,14,10,5, +21,11,14,1,36,52,0,2,16,24,12,22,46,14,2,72,12,37,77,103, +125,125,125,125,0,0,0,0,66,10,33,66,10,33,1,22,48,24,5,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,44,0,0,0,2,63,67,14,13,9,104,12, +11,49,17,37,10,8,5,12,19,18,5,5,8,41,49,45,53,54,0,26, +21,0,23,7,8,15,39,23,37,32,13,6,23,27,2,13,8,18,8,12, +34,28,31,7,4,5,4,19,22,7,12,38,2,32,34,16,45,20,3,37, +11,59,29,5,15,4,7,3,30,0,7,12,24,17,17,2,71,41,5,63, +5,25,26,1,31,48,2,3,41,50,27,53,2,71,18,42,40,32,42,30, +8,36,42,29,0,18,6,2,25,3,11,17,5,19,35,9,15,75,37,27, +51,41,51,48,62,44,42,40,24,14,24,2,9,0,23,45,45,91,4,0, +33,7,21,27,37,45,53,61,61,91,31,67,87,63,75,1,70,50,32,12, +10,3,7,15,13,16,96,62,48,34,70,26,16,0,0,3,84,52,30,14, +34,10,1,7,15,17,48,18,8,3,14,5,17,21,6,84,48,30,16,44, +14,8,6,3,124,31,13,4,5,9,2,16,18,0,16,28,36,25,15,21, +5,34,11,15,0,14,34,35,17,20,26,41,41,41,27,17,6,17,7,11, +1,10,23,13,11,2,33,19,33,39,0,71,25,2,13,26,13,3,44,9, +15,3,36,31,23,67,48,62,64,44,20,46,38,28,26,22,20,12,23,29, +43,15,9,29,65,29,27,35,31,29,17,19,47,51,37,34,32,34,20,7, +10,4,23,7,19,21,47,47,45,47,2,10,31,2,0,19,31,33,35,39, +39,49,69,65,77,81,89,53,73,85,35,7,19,6,10,12,102,32,30,9, +50,122,94,124,28,50,36,23,65,77,87,125,125,121,9,86,54,36,18,26, +4,5,9,15,21,7,14,0,32,26,10,18,26,32,34,18,40,34,0,52, +40,16,2,9,21,69,75,69,0,0,0,0,66,10,33,66,10,33,1,22, +48,24,5,21,25,54,118,26,22,11,12,28,0,13,0,25,57,1,53,125, +125,125,76,7,7,12,28,0,37,6,22,4,1,13,19,0,31,33,59,10, +7,15,8,21,13,39,0,21,17,35,6,4,44,0,0,0,2,63,67,14, +13,9,38,5,41,48,26,12,82,88,30,36,10,36,2,4,34,33,27,29, +39,48,3,26,30,9,27,13,12,4,15,13,31,34,9,10,7,19,4,9, +6,10,6,10,24,16,7,6,124,124,98,80,12,5,2,18,0,22,18,4, +15,42,9,57,51,70,18,28,10,12,18,28,72,42,20,0,4,4,30,36, +63,2,10,25,4,3,22,18,7,38,24,26,33,12,15,11,18,51,18,26, +20,0,21,16,0,14,6,25,11,6,125,124,95,13,23,29,43,29,39,67, +47,61,31,61,19,124,65,28,34,20,12,10,10,2,2,1,27,29,27,35, +39,85,23,25,63,5,15,19,27,39,47,43,45,53,35,57,67,51,59,6, +52,36,20,18,22,8,0,1,26,20,62,44,36,26,40,22,26,18,8,24, +84,68,58,52,54,20,6,2,3,13,100,58,16,0,26,2,19,15,10,88, +66,34,16,40,10,4,7,11,124,29,17,3,7,7,5,6,14,0,10,16, +32,17,9,27,17,24,23,23,19,1,0,11,23,11,25,11,15,41,20,20, +44,8,3,20,12,4,10,8,2,15,0,5,13,7,24,55,19,32,23,4, +9,0,22,9,13,8,14,37,17,53,54,58,64,34,20,28,22,16,12,1, +0,3,25,23,35,41,29,41,71,37,37,37,35,51,35,51,49,37,51,26, +24,20,16,13,1,5,35,19,33,37,69,51,63,73,23,19,79,15,19,35, +61,45,55,61,37,63,53,67,75,77,87,49,65,75,19,7,18,3,44,62, +3,6,26,34,10,30,58,8,0,70,8,43,83,111,125,125,125,125,8,78, +60,52,32,54,28,14,10,5,21,11,14,1,36,54,0,2,18,26,12,22, +48,14,2,70,8,43,83,111,125,125,125,125,0,0,0,0,64,10,33,64, +10,33,2,26,48,24,7,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,44,0,0,0, +2,63,67,16,15,9,104,12,11,47,15,37,12,10,1,16,15,20,1,3, +12,39,47,43,51,56,0,28,19,0,21,5,12,15,39,21,33,34,13,8, +21,25,4,13,8,20,10,14,36,30,31,7,4,5,4,19,22,9,10,38, +0,32,34,16,49,20,5,39,13,61,27,3,13,6,5,1,32,2,5,14, +26,17,17,2,73,39,3,63,3,25,28,1,33,50,2,3,43,52,27,55, +2,71,16,40,40,30,40,28,6,36,42,31,1,18,6,2,27,3,13,19, +7,21,37,9,17,79,39,29,53,43,51,44,60,40,38,38,20,10,20,1, +13,3,27,49,49,95,0,3,37,11,25,31,41,49,57,67,65,97,33,71, +89,63,75,1,70,50,32,12,10,3,7,15,13,16,96,62,48,34,72,28, +18,0,2,1,86,54,30,16,36,12,0,7,13,15,52,20,8,1,16,3, +15,19,8,84,50,30,16,46,16,10,8,1,124,31,13,6,5,9,2,16, +18,0,16,30,36,25,15,21,7,36,13,17,1,14,34,37,19,20,26,43, +43,41,25,15,8,15,5,9,1,12,23,13,11,2,35,19,33,37,2,71, +25,2,13,28,13,3,46,9,15,3,38,33,23,67,46,62,62,44,18,44, +36,26,26,20,18,10,25,31,45,17,11,31,69,31,29,37,33,31,17,17, +47,51,35,30,28,30,16,11,6,0,27,11,23,25,51,51,49,49,1,6, +33,1,3,23,35,37,39,43,43,53,75,69,81,85,91,57,77,87,33,3, +17,8,12,14,106,34,32,9,52,124,98,124,30,46,32,27,71,81,93,125, +125,123,9,86,54,36,18,26,4,5,9,15,19,5,16,2,34,28,10,20, +28,34,36,18,40,34,0,50,38,14,0,13,25,73,79,71,0,0,0,0, +64,10,33,64,10,33,2,26,48,24,7,23,29,52,118,26,26,11,12,30, +0,13,0,27,61,3,57,125,125,125,82,5,5,12,30,0,37,8,22,4, +1,13,17,0,31,33,59,10,7,15,8,21,11,39,0,21,17,35,6,4, +44,0,0,0,2,63,67,16,15,9,36,7,41,54,28,14,86,92,34,40, +14,40,4,6,40,33,27,27,37,48,3,28,34,9,25,13,16,4,17,15, +31,34,9,12,7,17,6,9,8,12,8,14,28,18,3,8,124,124,104,86, +14,5,4,20,0,22,20,4,13,46,9,61,55,76,18,28,10,12,18,30, +74,44,20,0,4,4,30,38,65,4,10,27,4,5,22,18,7,38,24,26, +35,14,17,11,18,51,18,24,18,3,27,14,1,10,2,29,17,2,125,124, +101,17,27,33,49,35,45,75,55,65,35,69,23,124,69,24,30,16,8,6, +6,1,1,5,31,33,31,37,43,89,23,25,63,7,17,21,29,41,49,45, +49,55,37,59,69,53,57,10,54,38,20,18,24,8,0,0,30,22,62,44, +38,28,42,24,28,20,12,26,86,70,60,52,56,22,8,2,3,13,100,58, +14,0,26,2,19,13,10,86,64,32,14,40,10,4,7,9,124,27,13,0, +3,5,3,10,18,2,14,20,36,15,7,25,15,28,23,23,17,1,2,11, +23,11,25,11,15,43,22,20,46,8,3,20,12,4,10,8,2,15,0,5, +13,7,24,57,21,32,25,2,9,1,22,9,15,8,14,39,17,55,52,56, +62,30,16,24,18,12,6,7,5,9,31,27,39,49,37,49,81,43,43,41, +39,55,39,53,53,37,53,22,18,16,12,19,7,9,41,23,37,41,75,55, +67,75,23,21,83,17,23,39,65,49,59,65,39,65,55,67,77,79,89,51, +67,77,19,7,20,1,46,64,1,8,26,34,10,32,60,8,0,68,4,49, +89,117,125,125,125,125,8,78,60,52,32,54,28,16,12,3,21,11,16,1, +38,56,0,2,18,26,12,24,48,14,2,68,4,49,89,117,125,125,125,125, +0,0,0,0,62,10,35,62,10,35,6,28,50,24,7,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,44,0,0,0,4,63,67,16,15,11,104,12,11,45,15,37, +12,12,2,20,13,22,2,1,16,37,45,41,49,58,0,30,19,2,21,5, +16,15,37,21,31,34,13,8,17,25,6,11,8,20,10,16,36,30,33,7, +4,5,4,19,22,9,10,38,1,32,34,16,53,20,5,43,15,63,27,1, +13,6,3,1,34,2,5,14,30,17,17,2,75,39,1,63,3,25,30,0, +35,50,2,3,45,54,29,57,2,73,12,38,38,30,38,28,6,34,40,33, +3,18,6,2,27,5,15,21,9,21,39,11,17,83,41,29,55,45,51,42, +56,38,34,34,16,6,16,7,19,7,33,55,55,101,3,7,39,15,31,37, +47,53,63,71,71,101,35,75,91,65,75,0,72,50,34,12,10,3,7,15, +11,16,96,64,48,34,74,28,18,2,2,0,88,54,32,16,38,12,0,5, +11,13,54,22,10,1,16,3,13,15,8,84,50,30,18,46,16,12,8,0, +124,29,11,6,5,9,2,16,18,0,18,30,38,25,15,23,7,36,15,19, +3,12,34,39,21,20,26,43,45,43,23,13,10,15,5,9,0,12,23,11, +9,4,35,19,33,37,4,71,25,2,13,30,13,3,48,11,15,3,38,35, +23,69,44,60,62,42,16,44,36,24,24,20,16,8,27,33,47,21,13,35, +73,35,33,39,33,31,17,17,45,53,33,26,24,26,12,17,2,3,33,15, +29,29,57,55,51,49,3,4,37,5,9,27,39,41,43,47,49,57,79,73, +85,87,95,61,81,91,31,1,15,10,14,16,108,36,34,9,54,124,100,124, +32,44,30,33,77,87,97,125,125,125,7,86,54,36,18,26,4,5,9,13, +17,5,18,4,36,28,12,22,28,34,36,18,42,34,0,48,34,10,3,15, +27,79,81,73,0,0,0,0,62,10,35,62,10,35,6,28,50,24,7,27, +33,50,118,26,28,11,14,30,0,15,2,27,63,7,63,125,125,125,86,3, +5,14,30,0,39,8,22,2,1,13,17,0,31,31,57,10,5,13,8,19, +11,39,0,21,17,35,6,4,44,0,0,0,4,63,67,16,15,11,36,7, +41,58,30,16,88,98,36,42,18,42,6,8,44,33,27,27,37,48,3,30, +40,9,23,11,20,2,17,15,33,36,9,12,5,17,6,7,10,12,10,16, +30,18,1,10,124,124,110,92,14,5,4,20,0,22,20,6,13,50,7,65, +59,82,18,28,10,12,20,30,78,46,20,0,4,4,32,40,67,4,10,27, +2,7,20,18,9,38,24,26,39,14,19,13,16,51,18,24,18,7,33,12, +5,4,3,33,21,1,125,124,109,21,29,37,57,39,51,83,65,71,39,75, +27,124,73,20,26,12,2,0,2,7,5,9,35,39,35,41,45,91,23,25, +65,9,19,23,31,43,51,47,53,57,37,61,71,53,57,12,56,38,20,18, +26,10,2,0,34,24,64,44,38,30,44,26,32,24,16,28,86,70,60,54, +58,22,8,2,1,13,102,58,12,0,26,2,19,13,8,86,64,30,12,38, +10,4,7,9,124,25,11,2,1,1,1,14,22,4,16,24,40,15,5,25, +13,32,21,23,17,0,2,11,23,11,27,11,15,43,22,22,48,8,3,22, +14,4,12,10,2,17,0,5,13,7,26,59,23,32,27,0,11,1,22,11, +15,8,12,43,19,57,48,54,60,28,12,20,14,8,2,11,11,13,37,33, +43,57,45,57,89,51,49,47,43,61,43,57,55,39,55,18,14,10,6,25, +11,15,47,29,43,47,81,59,69,79,25,23,85,21,25,43,69,51,63,69, +41,69,57,69,79,81,91,55,69,79,19,5,20,1,48,66,1,8,28,36, +10,32,62,8,0,66,0,53,95,123,125,125,125,125,8,78,60,52,32,56, +30,16,12,3,19,9,16,0,40,58,2,4,18,26,12,24,50,14,2,66, +0,53,95,123,125,125,125,125,0,0,0,0,60,10,35,60,10,35,10,32, +50,24,9,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,44,0,0,0,4,63,67,18, +17,11,104,12,11,43,13,37,14,16,4,24,9,24,4,2,20,35,43,39, +49,60,0,32,17,2,19,3,20,15,37,19,29,34,11,10,15,23,6,11, +10,20,10,18,38,32,33,9,4,5,4,19,22,11,8,38,1,32,34,14, +57,20,7,47,17,65,25,0,11,8,1,0,36,4,3,16,32,17,17,4, +77,37,0,63,3,25,30,0,37,52,2,3,49,56,29,59,2,75,10,36, +38,28,36,26,4,32,40,35,5,18,6,2,29,7,15,23,9,23,41,13, +19,87,43,31,57,47,51,38,54,34,30,30,12,0,12,11,23,11,37,59, +59,105,7,9,43,21,35,41,51,59,67,77,75,107,37,77,95,67,75,0, +72,52,34,12,10,3,7,15,11,18,98,64,48,34,76,30,20,2,4,2, +90,56,32,16,40,14,2,5,9,13,56,22,10,1,18,1,13,13,10,86, +50,30,18,48,18,14,10,2,124,29,11,8,5,9,2,16,18,2,18,30, +38,25,15,23,9,38,17,21,5,10,34,41,23,18,26,45,47,43,21,13, +12,13,3,7,0,14,23,11,9,4,37,19,33,35,6,71,25,4,13,30, +13,3,50,11,15,3,40,35,25,71,42,60,60,40,14,42,34,22,22,18, +14,6,29,35,49,23,17,37,77,37,35,41,35,33,17,17,45,53,31,22, +20,22,6,23,1,7,37,19,33,33,61,59,55,51,7,0,39,9,13,31, +43,45,47,51,53,61,85,77,89,91,97,65,85,93,29,0,13,10,16,18, +112,38,36,9,56,124,104,124,32,40,26,37,83,93,103,125,125,125,7,86, +54,36,18,26,4,5,9,13,15,3,20,6,38,30,12,24,30,36,38,20, +42,36,0,44,32,6,7,19,31,83,85,75,0,0,0,0,60,10,35,60, +10,35,10,32,50,24,9,29,37,48,118,26,32,11,14,32,1,15,2,29, +67,9,67,125,125,125,92,1,5,14,32,1,39,10,22,2,1,11,15,0, +31,31,57,10,5,13,8,19,9,37,0,21,17,35,8,4,44,0,0,0, +4,63,67,18,17,11,34,9,41,64,32,18,92,102,40,46,20,46,10,10, +48,33,25,25,37,48,3,32,44,9,21,11,24,2,19,17,33,36,9,14, +5,15,8,7,12,14,12,20,34,20,0,12,124,124,116,98,14,3,4,22, +0,22,22,6,11,54,7,69,63,88,18,30,10,12,20,32,80,48,22,1, +4,4,32,40,69,4,10,29,2,9,20,16,9,38,24,26,41,14,21,15, +16,51,18,22,16,11,39,10,9,0,7,37,27,5,125,124,115,25,33,43, +63,45,57,93,73,77,43,83,31,124,75,16,22,8,1,3,1,11,9,13, +41,43,39,45,49,95,23,25,65,11,21,25,35,45,53,49,55,59,39,63, +71,55,55,16,58,40,20,20,26,10,2,2,38,28,64,46,40,30,46,28, +34,26,20,28,88,72,62,54,60,24,8,4,1,13,102,58,12,1,26,2, +19,11,8,84,62,28,10,38,10,6,7,9,124,21,7,4,2,0,0,16, +24,6,20,26,44,13,3,23,11,36,21,23,17,0,4,11,25,11,27,11, +15,45,24,22,50,8,3,22,14,4,12,10,2,17,0,5,13,7,26,61, +25,32,29,0,13,3,22,13,17,8,12,45,19,59,46,52,58,24,8,16, +10,2,3,17,17,19,43,37,47,67,53,65,99,57,55,51,47,65,47,61, +59,41,55,12,8,6,2,31,17,19,53,33,47,51,87,63,73,81,27,23, +89,23,29,45,73,55,67,71,43,71,59,71,83,83,91,57,73,83,17,5, +22,0,50,68,1,10,28,36,10,34,64,8,0,64,3,59,101,125,125,125, +125,125,10,78,60,52,32,56,30,16,12,1,19,9,18,0,42,60,2,4, +20,28,12,24,50,14,2,64,3,59,101,125,125,125,125,125,0,0,0,0, +56,8,35,56,8,35,12,34,50,24,9,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, +44,0,0,0,6,65,67,18,19,11,104,12,11,41,11,37,14,18,8,28, +7,26,8,4,22,33,43,37,47,60,0,34,15,2,19,3,22,15,37,19, +27,34,11,10,13,23,8,11,10,20,10,18,38,32,35,9,4,5,4,19, +22,11,6,38,3,32,34,14,61,20,7,51,19,67,23,2,9,10,1,0, +38,4,3,18,34,17,17,4,81,37,2,63,3,27,32,0,39,54,2,3, +51,58,31,61,2,77,6,34,36,26,34,24,2,30,38,39,7,16,6,2, +29,9,17,25,11,25,43,15,21,91,47,33,59,49,51,34,50,30,26,26, +8,3,8,17,29,15,43,65,65,111,11,13,47,25,39,47,57,63,73,83, +79,111,39,81,97,69,77,0,72,52,34,12,10,3,7,15,9,18,98,64, +48,34,78,30,20,2,4,2,92,56,32,16,40,14,2,3,7,11,58,24, +10,1,20,0,11,11,10,86,50,30,18,50,18,14,12,2,124,29,11,8, +5,9,2,16,18,2,18,30,40,25,15,23,11,38,19,23,7,8,34,45, +27,18,26,47,49,45,21,11,14,13,3,7,2,16,25,11,9,4,39,19, +33,35,6,73,25,4,13,32,13,3,50,11,17,3,42,37,25,73,40,58, +60,38,10,40,32,20,20,16,12,4,31,37,51,27,19,41,81,41,37,43, +37,33,17,17,45,55,31,16,14,18,2,29,7,13,43,23,37,37,67,63, +57,53,11,3,43,13,17,37,49,51,53,55,57,67,89,81,95,95,99,69, +89,97,27,2,11,12,18,18,114,40,36,9,56,124,106,124,34,38,22,43, +89,99,109,125,125,125,7,86,54,36,18,26,4,5,9,11,15,1,22,6, +40,30,14,24,30,36,38,20,44,36,1,42,28,2,11,23,35,87,89,77, +0,0,0,0,56,8,35,56,8,35,12,34,50,24,9,33,43,46,118,24, +36,13,14,34,1,17,2,31,71,11,73,125,125,125,98,0,5,14,34,1, +41,12,22,0,1,11,15,1,33,31,57,10,5,13,8,19,9,37,0,21, +17,35,8,4,44,0,0,0,6,65,67,18,19,11,32,9,43,68,34,20, +94,106,42,48,24,48,12,12,52,33,25,25,37,48,3,34,48,9,21,9, +28,2,19,17,35,36,9,14,3,13,10,5,12,14,12,22,36,20,2,14, +124,124,122,102,14,3,4,22,1,22,22,6,11,58,7,73,67,92,18,30, +10,12,20,32,84,48,22,1,2,4,34,42,73,4,10,29,0,13,18,16, +11,38,24,24,43,14,23,17,14,51,16,20,14,15,47,6,13,3,13,43, +31,9,125,124,123,29,37,47,69,49,65,101,81,83,47,89,35,124,79,12, +16,2,7,9,7,15,15,17,45,47,43,49,53,99,23,27,67,13,25,27, +37,47,57,53,59,61,39,65,73,57,55,18,60,40,20,20,28,12,4,2, +42,30,64,46,40,32,48,30,38,30,22,30,88,72,62,56,62,24,8,4, +0,15,104,58,10,1,26,2,19,11,8,84,60,26,8,38,10,6,7,9, +124,19,5,6,4,4,2,20,28,8,22,30,48,13,3,23,9,38,21,23, +17,2,4,11,25,11,29,11,15,45,24,22,52,8,5,22,14,2,12,10, +2,19,0,5,13,7,28,63,27,32,33,1,15,5,20,15,19,8,12,47, +19,63,44,48,56,20,4,12,6,1,7,23,23,25,49,43,51,75,61,75, +109,65,63,57,53,71,51,65,61,43,57,8,4,0,3,37,23,25,59,39, +53,57,93,67,77,85,29,25,93,27,31,49,77,59,71,75,47,75,63,73, +85,85,93,61,75,85,17,5,22,0,52,70,1,10,30,38,10,34,64,8, +1,62,7,65,107,125,125,125,125,125,10,78,60,52,32,58,30,16,12,1, +19,9,18,0,42,60,2,4,20,28,12,24,52,14,0,62,7,65,107,125, +125,125,125,125,0,0,0,0,54,8,35,54,8,35,16,36,52,24,9,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,44,0,0,0,8,65,67,18,21,11,104,12, +11,39,9,37,14,20,12,32,3,30,12,6,26,31,41,35,45,62,2,36, +13,2,17,1,26,15,35,19,23,36,11,10,9,23,10,11,10,22,12,20, +38,32,35,9,6,5,4,17,22,11,6,38,5,32,34,14,65,20,7,53, +21,67,21,4,7,12,0,2,40,6,3,20,36,17,17,4,83,35,4,63, +1,27,34,0,41,56,2,3,53,60,33,63,2,77,4,32,36,24,32,22, +2,30,38,41,9,16,6,2,29,9,19,27,13,27,45,15,21,93,49,33, +61,51,51,32,48,28,24,24,4,7,4,21,33,19,47,71,69,117,13,17, +49,29,43,51,61,67,77,87,83,115,39,85,99,69,77,0,74,52,34,14, +10,3,5,15,7,18,98,64,50,34,80,32,22,4,6,4,94,58,34,18, +42,16,2,1,5,9,62,26,12,0,22,2,9,9,12,86,52,32,18,52, +20,16,14,4,124,27,9,10,5,9,2,18,20,2,18,32,42,25,15,23, +11,38,21,23,9,8,34,47,29,18,26,47,51,47,19,9,16,13,1,7, +4,18,25,11,9,6,39,19,33,35,8,73,25,4,13,34,13,3,52,11, +17,3,44,39,25,73,38,58,60,38,8,38,30,18,20,14,10,4,31,39, +53,29,21,45,85,43,39,43,37,33,15,15,45,57,29,12,10,14,1,33, +11,17,47,27,41,41,71,67,59,55,15,5,45,17,21,41,53,55,57,59, +61,71,93,83,99,99,101,73,93,101,25,6,7,14,20,20,118,42,38,9, +58,124,108,124,36,36,20,47,95,103,115,125,125,125,7,86,54,36,18,28, +4,5,9,9,13,0,24,8,44,32,16,26,32,38,40,20,46,36,1,40, +26,0,13,27,39,91,93,77,0,0,0,0,54,8,35,54,8,35,16,36, +52,24,9,35,47,44,120,24,40,13,16,36,1,19,2,31,73,13,77,125, +125,125,104,2,3,16,36,1,41,14,22,0,0,11,13,1,33,31,57,10, +5,11,8,19,9,37,0,21,17,33,8,4,44,0,0,0,8,65,67,18, +21,11,30,9,43,72,38,22,98,110,46,50,28,52,14,16,58,33,25,25, +35,48,3,36,52,7,19,7,32,2,19,17,35,36,9,14,1,11,12,3, +14,16,14,24,40,22,6,16,124,124,124,108,16,3,6,24,1,22,22,8, +9,64,7,77,69,98,18,30,10,12,20,34,88,50,22,1,2,4,36,44, +75,6,10,29,1,15,16,16,13,38,24,24,45,16,25,17,12,51,16,20, +14,19,53,4,15,7,17,47,35,13,125,124,125,33,41,51,75,53,71,109, +89,87,51,95,39,124,83,8,12,1,11,13,11,19,19,21,49,51,45,51, +55,103,23,27,67,13,27,29,39,49,59,55,63,63,39,67,75,57,53,20, +62,40,20,20,30,14,6,4,48,32,64,46,40,34,50,32,42,34,26,32, +90,74,64,58,64,24,10,4,2,15,106,58,8,1,28,4,19,9,8,84, +60,24,6,38,10,6,7,7,124,17,3,10,8,8,4,24,32,10,26,34, +52,11,1,21,7,42,19,21,15,4,6,11,25,11,31,11,15,45,24,24, +54,10,5,24,14,2,12,10,2,21,0,3,11,7,30,63,29,32,35,3, +15,5,20,15,21,8,12,49,19,65,42,46,56,18,0,8,2,5,11,27, +29,31,55,49,55,83,69,83,119,71,69,63,57,75,53,67,63,43,59,4, +0,3,7,41,27,29,65,43,57,61,97,71,81,89,29,27,95,29,33,53, +81,61,73,79,49,79,65,73,87,85,95,65,77,87,17,3,24,0,54,74, +0,12,32,40,10,36,66,8,1,60,11,69,113,125,125,125,125,125,10,78, +60,54,34,60,32,18,14,1,19,9,18,2,44,62,2,6,20,28,12,26, +54,14,0,60,11,69,113,125,125,125,125,125,0,0,0,0,52,8,35,52, +8,35,20,40,52,24,11,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,44,0,0,0, +8,65,67,20,23,11,104,12,11,37,7,37,16,24,14,36,1,32,14,10, +30,29,39,33,45,64,2,38,11,2,17,0,30,15,35,17,21,36,9,12, +7,21,10,11,12,22,12,22,40,34,37,11,6,5,4,17,22,13,4,38, +5,32,34,12,69,20,9,57,23,69,19,6,5,14,2,4,42,8,1,22, +38,17,17,6,85,35,6,63,1,27,34,0,43,58,2,3,57,62,33,65, +2,79,0,30,34,22,30,20,0,28,38,43,11,16,6,2,31,11,19,29, +13,29,47,17,23,97,51,35,63,53,51,28,46,24,20,20,0,13,0,27, +37,23,53,75,73,121,17,19,53,35,47,55,65,73,81,93,87,121,41,87, +103,71,77,0,74,54,34,14,10,3,5,15,7,20,100,64,50,34,82,32, +24,4,8,6,96,60,34,18,44,16,4,1,3,9,64,26,12,0,24,4, +9,7,12,88,52,32,18,54,22,18,16,6,124,27,9,10,5,9,2,18, +20,4,18,32,42,25,15,23,13,40,23,25,11,6,34,49,31,16,26,49, +53,47,17,9,18,11,1,5,4,20,25,11,9,6,41,19,33,33,10,73, +25,6,13,34,13,3,54,11,17,3,46,39,27,75,36,58,58,36,6,36, +28,16,18,12,8,2,33,41,55,33,25,47,89,45,41,45,39,35,15,15, +45,57,27,8,6,10,7,39,15,21,53,31,45,45,75,71,63,57,19,9, +47,21,25,45,57,59,61,63,65,75,99,87,103,103,103,77,97,103,23,8, +5,14,22,22,122,44,40,9,60,124,112,124,36,32,16,53,101,109,121,125, +125,125,7,86,54,36,18,28,4,5,9,9,11,2,26,10,46,34,16,28, +34,40,42,22,46,38,1,36,22,3,17,31,43,95,97,79,0,0,0,0, +52,8,35,52,8,35,20,40,52,24,11,37,51,42,120,24,44,13,16,38, +3,19,2,33,77,15,83,125,125,125,110,4,3,16,38,3,41,16,22,1, +0,9,11,1,33,31,57,10,5,11,8,19,7,35,0,21,17,33,10,4, +44,0,0,0,8,65,67,20,23,11,28,11,43,78,40,24,102,114,48,54, +30,54,18,18,62,33,23,23,35,48,3,38,56,7,17,7,36,2,21,19, +37,36,9,16,1,9,14,3,16,16,16,28,42,24,8,18,124,124,124,114, +16,1,6,24,1,22,24,8,9,68,7,81,73,104,18,32,10,12,20,34, +90,52,24,3,2,4,36,44,77,6,10,31,1,17,16,14,13,38,24,24, +47,16,27,19,12,51,16,18,12,23,59,2,19,11,21,51,41,17,125,124, +125,37,45,57,81,59,77,119,97,93,55,103,43,124,85,4,8,5,15,17, +15,23,23,25,55,55,49,55,59,107,23,27,69,15,29,31,43,51,61,57, +65,65,41,69,75,59,51,24,64,42,20,22,30,14,6,6,52,36,64,48, +42,34,52,34,44,36,30,32,92,76,66,58,66,26,10,6,2,15,106,58, +8,3,28,4,19,9,8,82,58,22,4,38,10,8,7,7,124,13,0,12, +12,10,6,26,34,12,30,36,56,9,0,21,5,46,19,21,15,4,6,11, +27,11,31,11,15,47,26,24,56,10,5,24,14,2,12,10,2,21,0,3, +11,7,30,65,31,32,37,3,17,7,20,17,23,8,12,51,19,67,40,44, +54,14,3,4,1,11,17,33,35,37,61,53,59,93,77,91,125,77,75,67, +61,81,57,71,67,45,59,1,5,9,11,47,33,35,71,47,63,65,103,75, +85,91,31,27,99,31,37,55,85,65,77,81,51,81,67,75,91,87,95,67, +81,91,15,3,26,2,56,76,0,14,32,40,10,36,68,8,1,58,15,75, +119,125,125,125,125,125,12,78,60,54,34,60,32,18,14,0,19,9,20,2, +46,64,2,6,22,30,12,26,54,14,0,58,15,75,119,125,125,125,125,125, +0,0,0,0,50,8,37,50,8,37,24,42,54,24,11,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,44,0,0,0,10,65,67,20,23,13,104,12,11,35,7,37, +16,26,18,40,2,34,18,12,34,27,37,31,43,66,2,40,11,4,15,0, +34,15,33,17,19,36,9,12,3,21,12,9,12,22,12,24,40,34,37,11, +6,5,4,17,22,13,4,38,7,32,34,12,73,20,9,61,25,71,19,8, +5,14,4,4,44,8,1,22,42,17,17,6,87,33,8,63,1,27,36,2, +45,58,2,3,59,64,35,67,2,81,1,28,34,22,28,20,0,26,36,45, +13,16,6,2,31,13,21,31,15,29,49,19,23,101,53,35,65,55,51,26, +42,22,16,16,3,17,3,31,43,27,57,81,79,125,21,23,55,39,53,61, +71,77,87,97,93,125,43,91,105,73,77,2,76,54,36,14,10,3,5,15, +5,20,100,66,50,34,84,34,24,6,8,8,98,60,36,18,46,18,4,0, +1,7,66,28,14,0,24,4,7,3,14,88,52,32,20,54,22,20,16,8, +124,25,7,12,5,9,2,18,20,4,20,32,44,25,15,25,13,40,25,27, +13,4,34,51,33,16,26,49,55,49,15,7,20,11,0,5,6,20,25,9, +7,8,41,19,33,33,12,73,25,6,13,36,13,3,56,13,17,3,46,41, +27,77,34,56,58,34,4,36,28,14,16,12,6,0,35,43,57,35,27,51, +93,49,45,47,39,35,15,15,43,59,25,4,2,6,11,45,19,25,57,35, +51,49,81,75,65,57,21,11,51,25,31,49,61,63,65,67,71,79,103,91, +107,105,107,81,101,107,21,10,3,16,24,24,124,46,42,9,62,124,114,124, +38,30,14,57,107,115,125,125,125,125,5,86,54,36,18,28,4,5,9,7, +9,2,28,12,48,34,18,30,34,40,42,22,48,38,1,34,20,7,21,33, +45,101,99,81,0,0,0,0,50,8,37,50,8,37,24,42,54,24,11,41, +55,40,120,24,46,13,18,38,3,21,4,33,79,19,87,125,125,125,114,6, +3,18,38,3,43,16,22,1,0,9,11,1,33,29,55,10,3,9,8,17, +7,35,0,21,17,33,10,4,44,0,0,0,10,65,67,20,23,13,28,11, +43,82,42,26,104,120,52,56,34,58,20,20,66,33,23,23,35,48,3,40, +62,7,15,5,40,0,21,19,37,38,9,16,0,9,14,1,18,18,18,30, +46,24,10,20,124,124,124,120,16,1,6,26,1,22,24,10,7,72,5,85, +77,110,18,32,10,12,22,36,94,54,24,3,2,4,38,46,79,6,10,31, +3,19,14,14,15,38,24,24,51,16,29,21,10,51,16,18,12,27,65,0, +23,17,27,55,45,21,125,124,125,41,47,61,89,63,83,125,107,99,59,109, +47,124,89,0,4,9,21,23,19,29,27,29,59,61,53,59,61,109,23,27, +69,17,31,33,45,53,63,59,69,67,41,71,77,59,51,26,66,42,20,22, +32,16,8,6,56,38,66,48,42,36,54,36,48,40,34,34,92,76,66,60, +68,26,10,6,4,15,108,58,6,3,28,4,19,7,6,82,58,20,2,36, +10,8,7,7,124,11,2,14,14,14,8,30,38,14,32,40,60,9,2,19, +3,50,17,21,15,6,8,11,27,11,33,11,15,47,26,26,58,10,5,26, +16,2,14,12,2,23,0,3,11,7,32,67,33,32,39,5,19,7,20,19, +23,8,10,55,21,69,36,42,52,12,7,0,5,15,21,37,41,41,67,59, +63,101,85,99,125,85,81,73,65,85,61,75,69,47,61,5,9,13,17,53, +37,39,77,53,67,71,109,79,87,95,33,29,101,35,39,59,89,67,81,85, +53,85,69,77,93,89,97,71,83,93,15,1,26,2,58,78,0,14,34,42, +10,38,70,8,1,56,19,79,125,125,125,125,125,125,12,78,60,54,34,62, +34,18,14,0,17,7,20,4,48,66,4,8,22,30,12,26,56,14,0,56, +19,79,125,125,125,125,125,125,0,0,0,0,46,8,37,46,8,37,26,46, +54,24,13,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,44,0,0,0,10,67,67,22, +25,13,104,12,11,33,5,37,18,28,22,44,4,36,22,14,38,25,37,29, +41,66,2,42,9,4,15,2,38,15,33,15,17,36,9,14,1,19,14,9, +12,22,12,24,42,36,39,11,6,5,4,17,22,15,2,38,9,32,34,12, +77,20,11,65,27,73,17,10,3,16,4,6,46,10,0,24,44,17,17,6, +89,33,10,63,1,27,38,2,47,60,2,3,61,66,35,69,2,83,5,26, +32,20,26,18,1,24,36,49,15,14,6,2,33,15,23,33,17,31,51,21, +25,105,55,37,67,57,51,22,40,18,12,12,7,21,7,37,47,31,63,85, +83,125,25,27,59,43,57,65,75,81,91,103,97,125,45,95,107,75,77,2, +76,54,36,14,10,3,5,15,5,20,100,66,50,34,86,34,26,6,10,8, +100,62,36,18,46,18,6,0,0,5,68,30,14,0,26,6,5,1,14,88, +52,32,20,56,24,20,18,10,124,25,7,12,5,9,2,18,20,4,20,32, +44,25,15,25,15,42,27,29,15,2,34,55,35,16,26,51,57,49,15,5, +22,9,0,3,6,22,27,9,7,8,43,19,33,31,14,73,25,6,13,38, +13,3,58,13,19,3,48,43,27,79,32,56,56,32,2,34,26,12,14,10, +4,1,37,45,59,39,29,53,97,51,47,49,41,37,15,15,43,59,25,1, +3,2,15,51,23,29,63,39,55,53,85,79,69,59,25,15,53,29,35,53, +65,69,69,71,75,83,109,95,111,109,109,85,105,109,19,12,1,18,26,26, +124,48,44,9,64,124,118,124,40,26,10,63,113,121,125,125,125,125,5,86, +54,36,18,28,4,5,9,7,7,4,30,12,50,36,18,32,36,42,44,22, +48,38,1,32,16,11,25,37,49,105,103,83,0,0,0,0,46,8,37,46, +8,37,26,46,54,24,13,43,59,38,120,22,50,13,18,40,3,21,4,35, +83,21,93,125,125,125,120,8,3,18,40,3,43,18,22,3,0,9,9,1, +33,29,55,10,3,9,8,17,5,35,0,21,17,33,10,4,44,0,0,0, +10,67,67,22,25,13,26,13,43,88,44,28,108,124,54,60,38,60,22,22, +70,33,23,21,35,48,3,42,66,7,15,5,44,0,23,21,39,38,9,18, +0,7,16,1,20,18,18,34,48,26,12,22,124,124,124,124,16,1,6,26, +1,22,26,10,7,76,5,89,81,114,18,32,10,12,22,36,96,56,24,3, +2,4,38,48,81,6,10,33,3,21,14,14,15,38,24,24,53,16,31,23, +10,51,14,16,10,31,73,1,27,21,31,59,51,25,125,124,125,45,51,65, +95,69,91,125,115,105,63,117,51,124,93,3,0,15,25,27,23,33,31,33, +63,65,57,63,65,113,23,27,71,19,33,35,47,55,67,61,73,69,43,73, +79,61,49,30,68,44,20,22,34,16,8,8,60,40,66,48,44,38,56,38, +50,42,36,36,94,78,68,60,70,28,10,6,4,15,108,58,4,3,28,4, +19,7,6,80,56,18,0,36,10,8,7,7,124,9,6,16,18,16,10,34, +42,16,36,44,64,7,4,19,1,52,17,21,15,6,8,11,27,11,33,11, +15,49,28,26,60,10,5,26,16,2,14,12,2,23,0,3,11,7,32,69, +35,32,41,7,21,9,20,21,25,8,10,57,21,71,34,40,50,8,11,3, +9,19,27,43,47,47,73,63,67,109,93,107,125,91,89,77,71,91,65,79, +73,49,63,9,15,19,21,59,43,45,83,57,73,75,115,83,91,97,35,31, +105,37,43,63,93,71,85,89,55,87,71,79,95,91,99,73,85,95,15,1, +28,4,60,80,0,16,34,42,10,38,72,8,1,54,23,85,125,125,125,125, +125,125,12,78,60,54,34,62,34,18,14,2,17,7,22,4,48,68,4,8, +22,30,12,26,56,14,0,54,23,85,125,125,125,125,125,125,0,0,0,0, +44,8,37,44,8,37,30,48,54,24,13,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, +44,0,0,0,12,67,67,22,27,13,104,12,11,31,3,37,18,32,24,48, +8,38,24,18,42,23,35,27,41,68,2,44,7,4,13,4,42,15,33,15, +13,38,7,14,0,19,14,9,14,24,14,26,42,36,39,13,6,5,4,17, +22,15,0,38,9,32,34,10,81,20,11,67,29,75,15,12,1,18,6,8, +48,12,0,26,46,17,17,8,91,31,12,63,0,27,38,2,49,62,2,3, +65,68,37,71,2,83,7,24,32,18,24,16,3,24,36,51,17,14,6,2, +33,15,23,35,17,33,53,21,27,109,57,39,69,59,51,18,38,14,8,10, +11,27,11,41,51,35,67,91,87,125,29,29,63,49,61,69,79,87,95,109, +101,125,47,97,111,75,77,2,76,56,36,14,10,3,5,15,3,22,102,66, +50,34,88,36,28,6,12,10,102,64,36,20,48,20,6,2,2,5,72,30, +14,2,28,8,5,0,16,90,54,32,20,58,26,22,20,12,124,25,7,14, +5,9,2,18,20,6,20,34,46,25,15,25,17,42,29,31,17,2,34,57, +37,14,26,53,59,51,13,5,24,9,2,3,8,24,27,9,7,8,45,19, +33,31,16,73,25,8,13,38,13,3,60,13,19,3,50,43,29,79,30,56, +56,32,0,32,24,10,14,8,2,3,39,47,61,41,33,57,101,53,49,51, +43,37,15,13,43,61,23,5,7,1,21,55,27,33,67,43,59,57,89,83, +71,61,29,19,55,33,39,57,69,73,73,75,79,87,113,99,115,113,111,89, +109,113,17,16,0,18,28,28,124,50,46,9,66,124,120,124,40,24,6,67, +119,125,125,125,125,125,5,86,54,36,18,28,4,5,9,5,5,6,32,14, +52,38,20,34,38,44,46,24,50,40,1,28,14,13,27,41,53,109,107,85, +0,0,0,0,44,8,37,44,8,37,30,48,54,24,13,45,63,36,120,22, +54,13,18,42,5,23,4,37,87,23,97,125,125,125,124,10,1,18,42,5, +43,20,22,3,0,7,7,1,33,29,55,10,3,9,8,17,5,33,0,21, +17,33,12,4,44,0,0,0,12,67,67,22,27,13,24,13,43,92,46,30, +112,124,58,62,40,64,26,24,76,33,21,21,33,48,3,44,70,7,13,3, +48,0,23,21,39,38,9,18,2,5,18,0,22,20,20,36,52,28,16,24, +124,124,124,124,18,0,8,28,1,22,26,10,5,80,5,93,85,120,18,34, +10,12,22,38,100,58,26,5,2,4,40,48,83,8,10,33,5,23,12,12, +17,38,24,24,55,18,33,23,8,51,14,14,8,35,79,3,29,25,35,63, +55,29,125,124,125,49,55,71,101,73,97,125,123,109,67,123,55,124,95,7, +3,19,29,31,27,37,35,37,69,69,61,65,69,117,23,27,71,21,35,37, +51,57,69,63,75,71,43,75,79,63,47,32,70,44,20,24,34,18,10,10, +64,44,66,50,44,38,58,40,54,46,40,36,96,80,70,62,72,28,12,8, +6,15,110,58,4,5,28,4,19,5,6,80,54,16,1,36,10,10,7,5, +124,5,8,20,22,20,12,36,44,18,40,46,68,5,6,17,0,56,17,21, +13,8,10,11,29,11,35,11,15,49,28,26,62,10,5,26,16,2,14,12, +2,25,0,3,11,7,34,71,37,32,43,7,21,11,20,21,27,8,10,59, +21,73,32,38,48,4,15,7,13,25,31,49,53,53,79,69,71,119,101,115, +125,97,95,83,75,95,69,81,75,49,63,15,19,23,25,65,49,49,89,61, +77,79,121,87,95,101,35,31,109,39,45,65,97,75,89,91,57,91,73,79, +99,93,99,77,89,99,13,1,30,4,62,82,2,18,36,44,10,40,74,8, +1,52,27,91,125,125,125,125,125,125,14,78,60,54,34,64,34,20,16,2, +17,7,22,4,50,70,4,8,24,32,12,28,58,14,0,52,27,91,125,125, +125,125,125,125,0,0,0,0,42,8,37,42,8,37,34,52,56,24,15,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,44,0,0,0,12,67,67,24,29,13,104,12, +11,29,1,37,20,34,28,52,10,40,28,20,46,21,33,25,39,70,2,46, +5,4,13,4,46,15,31,13,11,38,7,16,4,17,16,9,14,24,14,28, +44,38,41,13,6,5,4,17,22,17,0,38,11,32,34,10,85,20,13,71, +31,77,13,14,0,20,8,8,50,12,2,28,48,17,17,8,93,31,14,63, +0,27,40,2,51,64,2,3,67,70,37,73,2,85,11,22,30,16,22,14, +3,22,34,53,19,14,6,2,35,17,25,37,19,35,55,23,27,113,59,39, +71,61,51,16,34,12,4,6,15,31,15,47,57,39,73,95,93,125,33,33, +65,53,65,75,85,91,101,113,105,125,49,101,113,77,77,2,78,56,36,14, +10,3,5,15,3,22,102,66,50,34,90,36,28,8,12,12,104,64,38,20, +50,20,8,2,4,3,74,32,16,2,30,10,3,2,16,90,54,32,20,60, +26,24,22,14,124,23,5,14,5,9,2,18,20,6,20,34,46,25,15,25, +17,44,31,33,19,0,34,59,39,14,26,53,61,51,11,3,26,7,2,1, +8,26,27,9,7,10,45,19,33,29,18,73,25,8,13,40,13,3,62,13, +19,3,52,45,29,81,28,54,54,30,1,30,22,8,12,6,0,5,41,49, +63,45,35,59,105,57,51,53,43,39,15,13,43,61,21,9,11,5,25,61, +31,37,73,47,63,61,95,87,75,63,33,21,59,37,43,61,73,77,77,79, +83,91,119,103,119,117,113,93,113,115,15,18,2,20,30,30,124,52,48,9, +68,124,124,124,42,20,4,73,125,125,125,125,125,125,5,86,54,36,18,28, +4,5,9,5,3,8,34,16,54,38,20,36,38,44,46,24,50,40,1,26, +10,17,31,45,57,113,111,87,0,0,0,0,42,8,37,42,8,37,34,52, +56,24,15,49,67,34,120,22,58,13,20,44,5,23,4,37,89,25,103,125, +125,125,124,12,1,20,44,5,45,22,22,5,0,7,7,1,33,29,55,10, +3,7,8,17,3,33,0,21,17,33,12,4,44,0,0,0,12,67,67,24, +29,13,22,15,43,98,48,32,114,124,60,66,44,66,28,26,80,33,21,19, +33,48,3,46,74,7,11,3,52,0,25,23,41,38,9,20,2,3,20,0, +24,20,22,40,54,28,18,26,124,124,124,124,18,0,8,28,1,22,28,12, +5,84,5,97,89,124,18,34,10,12,22,38,102,60,26,5,2,4,40,50, +85,8,10,35,5,25,12,12,17,38,24,24,57,18,35,25,8,51,14,14, +8,39,85,5,33,29,41,67,61,33,125,124,125,53,59,75,107,79,103,125, +125,115,71,125,59,124,99,11,7,23,35,37,31,41,39,41,73,73,65,69, +71,121,23,27,73,23,37,39,53,59,71,65,79,73,45,77,81,63,47,36, +72,46,20,24,36,18,10,10,68,46,66,50,46,40,60,42,56,48,44,38, +96,80,70,62,74,30,12,8,6,15,110,58,2,5,28,4,19,5,6,78, +54,14,3,36,10,10,7,5,124,3,12,22,24,22,14,40,48,20,42,50, +72,5,8,17,2,60,15,21,13,8,10,11,29,11,35,11,15,51,30,28, +64,10,5,28,16,2,14,12,2,25,0,3,11,7,34,73,39,32,45,9, +23,11,20,23,29,8,10,61,21,75,30,36,46,2,19,11,17,29,37,53, +59,59,85,73,75,125,109,123,125,105,101,87,79,101,73,85,79,51,65,19, +25,29,31,71,53,55,95,67,83,85,125,91,99,103,37,33,111,43,49,69, +101,77,93,95,59,93,75,81,101,95,101,79,91,101,13,0,30,6,64,84, +2,18,36,44,10,40,76,8,1,50,31,95,125,125,125,125,125,125,14,78, +60,54,34,64,36,20,16,4,17,7,24,6,52,72,4,10,24,32,12,28, +58,14,0,50,31,95,125,125,125,125,125,125,0,0,0,0,40,8,37,40, +8,37,38,54,56,24,15,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,44,0,0,0, +14,67,67,24,31,13,104,12,11,27,0,37,20,36,32,56,14,42,32,22, +50,19,31,23,37,72,2,48,3,4,11,6,50,15,31,13,9,38,7,16, +6,17,18,9,14,24,14,30,44,38,41,13,6,5,4,17,22,17,1,38, +13,32,34,10,89,20,13,75,33,79,11,16,2,22,10,10,52,14,2,30, +50,17,17,8,95,29,16,63,0,27,42,2,53,66,2,3,69,72,39,75, +2,87,13,20,30,14,20,12,5,20,34,55,21,14,6,2,35,19,27,39, +21,37,57,25,29,117,61,41,73,63,51,12,32,8,0,2,19,35,19,51, +61,43,77,101,97,125,37,37,69,57,69,79,89,95,105,119,109,125,51,105, +115,79,77,2,78,56,36,14,10,3,5,15,1,22,102,66,50,34,92,38, +30,8,14,14,106,66,38,20,52,22,8,4,6,1,76,34,16,2,32,12, +1,4,18,90,54,32,20,62,28,26,24,16,124,23,5,16,5,9,2,18, +20,6,20,34,48,25,15,25,19,44,33,35,21,1,34,61,41,14,26,55, +63,53,9,1,28,7,4,1,10,28,27,9,7,10,47,19,33,29,20,73, +25,8,13,42,13,3,64,13,19,3,54,47,29,83,26,54,54,28,3,28, +20,6,10,4,1,7,43,51,65,47,37,63,109,59,53,55,45,39,15,13, +43,63,19,13,15,9,29,67,35,41,77,51,67,65,99,91,77,65,37,25, +61,41,47,65,77,81,81,83,87,95,123,107,123,121,115,97,117,119,13,20, +4,22,32,32,124,54,50,9,70,124,124,124,44,18,0,77,125,125,125,125, +125,125,5,86,54,36,18,28,4,5,9,3,1,10,36,18,56,40,22,38, +40,46,48,24,52,40,1,24,8,21,35,49,61,117,115,89,0,0,0,0, +40,8,37,40,8,37,38,54,56,24,15,51,71,32,120,22,62,13,20,46, +5,25,4,39,93,27,107,125,125,125,124,14,1,20,46,5,45,24,22,5, +0,7,5,1,33,29,55,10,3,7,8,17,3,33,0,21,17,33,12,4, +44,0,0,0,14,67,67,24,31,13,20,15,43,102,50,34,118,124,64,68, +48,70,30,28,84,33,21,19,33,48,3,48,78,7,9,1,56,0,25,23, +41,38,9,20,4,1,22,2,26,22,24,42,58,30,20,28,124,124,124,124, +18,0,8,30,1,22,28,12,3,88,5,101,93,124,18,34,10,12,22,40, +106,62,26,5,2,4,42,52,87,8,10,35,7,27,10,12,19,38,24,24, +59,18,37,27,6,51,14,12,6,43,91,7,37,33,45,71,65,37,125,124, +125,57,63,79,113,83,109,125,125,121,75,125,63,124,103,15,11,27,39,41, +35,45,43,45,77,77,69,73,75,125,23,27,73,25,39,41,55,61,73,67, +83,75,45,79,83,65,45,38,74,46,20,24,38,20,12,12,72,48,66,50, +46,42,62,44,60,52,48,40,98,82,72,64,76,30,12,8,8,15,112,58, +0,5,28,4,19,3,6,78,52,12,5,36,10,10,7,5,124,1,14,24, +28,26,16,44,52,22,46,54,76,3,10,15,4,64,15,21,13,10,12,11, +29,11,37,11,15,51,30,28,66,10,5,28,16,2,14,12,2,27,0,3, +11,7,36,75,41,32,47,11,25,13,20,25,31,8,10,63,21,77,28,34, +44,1,23,15,21,33,41,59,65,65,91,79,79,125,117,125,125,111,107,93, +83,105,77,89,81,53,67,23,29,33,35,77,59,59,101,71,87,89,125,95, +103,107,39,35,115,45,51,73,105,81,97,99,61,97,77,83,103,97,103,83, +93,103,13,0,32,6,66,86,2,20,38,46,10,42,78,8,1,48,35,101, +125,125,125,125,125,125,14,78,60,54,34,66,36,20,16,4,17,7,24,6, +54,74,4,10,24,32,12,28,60,14,0,48,35,101,125,125,125,125,125,125, +0,0,0,0,36,6,39,36,6,39,40,56,56,24,17,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,44,0,0,0,14,69,67,24,33,15,104,10,11,25,0,37, +20,38,34,58,16,44,34,24,52,17,31,21,37,72,2,48,3,4,11,6, +52,15,31,13,7,38,7,16,8,17,18,9,14,24,14,30,44,38,43,15, +6,7,4,17,20,19,3,38,15,30,34,8,93,18,15,79,35,81,11,16, +2,22,10,10,54,14,2,30,52,19,17,8,99,29,16,63,0,29,42,2, +55,66,2,3,73,72,41,77,2,89,17,18,28,12,18,10,7,18,32,59, +23,12,4,2,37,21,29,41,23,39,59,27,31,121,65,43,77,67,51,8, +28,4,3,1,25,41,25,57,67,49,83,107,103,125,41,41,73,63,75,85, +95,101,111,125,115,125,53,109,119,81,79,2,78,56,36,14,10,5,5,15, +1,22,102,66,50,34,94,38,30,8,14,14,106,66,38,20,52,22,8,4, +8,1,78,34,16,2,32,12,1,6,18,90,54,32,20,62,28,26,24,16, +124,23,5,16,5,9,2,18,20,6,20,34,48,25,15,27,21,44,35,37, +23,3,32,65,45,12,24,57,67,55,9,1,30,7,4,1,10,28,29,9, +7,10,49,19,33,29,20,75,25,8,13,42,15,3,64,15,21,3,54,49, +31,85,24,52,52,26,7,26,18,4,8,2,3,9,45,55,69,51,41,67, +113,63,57,57,47,41,15,13,43,65,19,19,21,13,35,73,41,47,83,57, +73,71,105,97,81,67,41,29,65,45,53,71,83,87,87,87,93,101,125,111, +125,125,119,101,121,123,11,22,6,22,32,32,124,54,50,9,70,124,124,124, +44,14,3,83,125,125,125,125,125,125,5,86,52,34,18,28,4,7,9,3, +1,10,36,18,58,40,22,38,40,46,48,24,52,40,3,20,4,25,39,53, +65,123,119,91,0,0,0,0,36,6,39,36,6,39,40,56,56,24,17,55, +77,30,120,20,64,15,20,46,7,27,4,41,97,31,113,125,125,125,124,14, +1,20,46,7,47,24,22,7,0,7,5,3,35,29,55,8,3,7,8,17, +3,33,0,21,19,33,12,4,44,0,0,0,14,69,67,24,33,15,18,17, +45,106,52,36,120,124,66,70,50,72,32,30,88,33,21,19,33,48,3,48, +82,7,9,1,58,1,27,25,43,38,9,20,4,1,22,2,26,22,24,44, +60,30,22,30,124,124,124,124,18,0,8,30,3,22,28,12,3,92,5,105, +97,124,18,34,10,12,22,40,108,62,26,7,0,4,42,52,91,8,10,37, +9,31,8,10,21,38,24,22,63,18,39,29,4,51,12,10,4,49,99,11, +41,39,51,77,71,41,125,124,125,63,67,85,121,89,117,125,125,125,79,125, +67,124,107,21,17,33,45,47,41,51,49,49,83,83,73,77,79,125,23,29, +75,27,43,45,59,65,77,71,87,77,47,81,85,67,45,40,74,46,20,24, +38,20,12,12,76,50,66,50,46,42,62,46,62,54,50,40,98,82,72,64, +78,30,12,8,8,17,112,56,1,7,28,4,19,3,4,76,50,8,7,34, +10,10,7,5,124,0,16,26,30,28,18,46,54,24,48,56,80,3,10,15, +6,66,15,21,13,10,12,11,31,13,39,11,17,53,30,28,68,10,7,28, +16,0,14,12,2,29,0,3,11,7,36,77,43,32,51,13,27,15,18,27, +33,8,8,67,23,81,24,30,42,5,27,21,27,39,47,65,71,71,99,85, +83,125,125,125,125,119,115,99,89,111,81,93,85,55,69,29,35,39,41,83, +65,65,109,77,93,95,125,99,107,111,41,37,119,49,55,77,111,85,101,103, +65,101,81,85,107,99,105,87,97,107,13,0,32,6,68,88,2,20,38,46, +10,42,78,8,3,44,39,107,125,125,125,125,125,125,14,78,60,54,34,66, +36,20,16,4,17,7,24,6,54,74,4,10,24,32,12,28,60,12,1,44, +39,107,125,125,125,125,125,125,0,0,0,0,34,6,39,34,6,39,44,60, +58,26,17,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,44,0,0,0,16,69,67,26, +33,15,104,10,11,21,2,37,22,42,38,62,20,48,38,28,56,13,29,19, +35,74,4,50,1,6,9,8,56,13,29,11,3,40,5,18,12,15,20,7, +16,26,16,32,46,40,43,15,8,7,4,15,20,19,3,38,15,30,34,8, +95,18,15,81,37,81,9,18,4,24,12,12,56,16,4,32,56,19,17,10, +101,27,18,63,2,29,44,4,55,68,2,3,75,74,41,79,2,89,19,18, +28,12,18,10,7,18,32,61,23,12,4,2,37,21,29,41,23,39,61,27, +31,123,67,43,79,69,51,6,26,2,5,3,29,45,29,61,71,53,87,111, +107,125,43,43,75,67,79,89,99,105,115,125,119,125,53,111,121,81,79,4, +80,58,38,16,10,5,3,13,0,24,104,68,52,34,96,40,32,10,16,16, +108,68,40,22,54,24,10,6,12,0,82,36,18,4,34,14,0,10,20,92, +56,34,22,64,30,28,26,18,124,21,3,18,5,7,2,20,22,8,22,36, +50,23,15,27,21,46,35,37,25,3,32,67,47,12,24,57,69,55,7,0, +32,5,6,0,12,30,29,7,5,12,49,17,31,27,22,75,25,10,13,44, +15,3,66,15,21,1,56,49,31,85,24,52,52,26,9,26,18,4,8,2, +3,9,45,57,71,53,43,69,115,65,59,57,47,41,13,11,41,65,17,23, +25,17,39,77,45,51,87,61,77,75,109,101,83,67,43,31,67,47,57,75, +87,91,91,91,97,105,125,113,125,125,121,103,123,125,7,26,10,24,34,34, +124,56,52,9,72,124,124,124,46,12,5,87,125,125,125,125,125,125,3,88, +52,34,18,30,4,7,9,1,0,12,38,20,62,42,24,40,42,48,50,26, +54,42,3,18,2,27,41,55,67,125,121,91,0,0,0,0,34,6,39,34, +6,39,44,60,58,26,17,57,81,28,122,20,68,15,22,48,7,27,6,41, +99,33,117,125,125,125,124,16,0,22,48,7,47,26,22,7,2,5,3,3, +35,27,53,8,1,5,8,15,1,31,2,19,19,31,14,4,44,0,0,0, +16,69,67,26,33,15,18,17,45,112,56,40,124,124,70,74,54,76,36,34, +94,33,19,17,31,48,3,50,88,5,7,0,62,1,27,25,43,40,9,22, +6,0,24,4,28,24,26,48,64,32,26,34,124,124,124,124,20,2,10,32, +3,24,30,14,1,98,3,109,99,124,18,36,10,14,24,42,112,64,28,7, +0,4,44,54,93,10,10,37,9,33,8,10,21,38,24,22,65,20,39,29, +4,51,12,10,4,53,105,13,43,43,55,81,75,45,125,124,125,67,69,89, +125,93,123,125,125,125,83,125,71,124,109,25,21,37,49,51,45,55,53,53, +87,87,75,79,81,125,23,29,75,27,45,47,61,67,79,73,89,79,47,83, +85,67,43,44,76,48,20,26,40,22,14,14,82,54,68,52,48,44,64,50, +66,58,54,42,100,84,74,66,80,32,14,10,10,17,114,56,1,7,30,6, +19,1,4,76,50,6,9,34,12,12,5,3,124,4,20,30,34,32,22,50, +58,28,52,60,86,1,12,13,10,70,13,19,11,12,14,9,31,13,39,11, +17,53,32,30,70,12,7,30,18,0,16,14,2,29,2,1,9,5,38,77, +45,32,53,13,27,15,18,27,33,8,8,69,23,83,22,28,42,7,29,25, +31,43,51,69,75,75,105,89,87,125,125,125,125,125,121,103,93,115,83,95, +87,55,69,33,39,43,45,87,69,69,115,81,97,99,125,101,109,113,41,37, +121,51,57,79,115,87,103,105,67,103,83,85,109,99,105,89,99,109,11,2, +34,8,72,92,4,22,40,48,12,44,80,8,3,42,43,111,125,125,125,125, +125,125,16,78,62,56,36,68,38,22,18,6,15,5,26,8,56,76,6,12, +26,34,12,30,62,12,1,42,43,111,125,125,125,125,125,125,0,0,0,0, +32,6,39,32,6,39,48,62,58,26,17,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, +44,0,0,0,18,69,67,26,35,15,104,10,11,19,4,37,22,44,42,66, +22,50,42,30,60,11,27,17,33,76,4,52,0,6,9,10,60,13,29,11, +1,40,5,18,14,15,22,7,16,26,16,34,46,40,45,15,8,7,4,15, +20,19,5,38,17,30,34,8,99,18,15,85,39,83,7,20,6,26,14,14, +58,18,4,34,58,19,17,10,103,27,20,63,2,29,46,4,57,70,2,3, +77,76,43,81,2,91,23,16,26,10,16,8,9,16,32,63,25,12,4,2, +37,23,31,43,25,41,63,29,33,125,69,45,81,71,51,2,24,1,9,7, +33,49,33,67,75,57,93,117,111,125,47,47,79,71,83,93,103,109,119,125, +123,125,55,115,123,83,79,4,80,58,38,16,10,5,3,13,2,24,104,68, +52,34,98,40,34,10,18,18,110,70,40,22,56,24,10,8,14,2,84,38, +18,4,36,16,2,12,20,92,56,34,22,66,32,30,28,20,124,21,3,18, +5,7,2,20,22,8,22,36,52,23,15,27,23,46,37,39,27,5,32,69, +49,12,24,59,71,57,5,2,34,5,6,0,14,32,29,7,5,12,51,17, +31,27,24,75,25,10,13,46,15,3,68,15,21,1,58,51,31,87,22,52, +52,24,11,24,16,2,6,0,5,11,47,59,73,57,45,73,119,67,61,59, +49,41,13,11,41,67,15,27,29,21,43,83,49,55,93,65,81,79,113,105, +85,69,47,35,69,51,61,79,91,95,95,95,101,109,125,117,125,125,123,107, +125,125,5,28,12,26,36,36,124,58,54,9,74,124,124,124,48,10,9,93, +125,125,125,125,125,125,3,88,52,34,18,30,4,7,9,0,2,14,40,22, +64,44,26,42,44,50,52,26,56,42,3,16,1,31,45,59,71,125,125,93, +0,0,0,0,32,6,39,32,6,39,48,62,58,26,17,59,85,26,122,20, +72,15,22,50,7,29,6,43,103,35,123,125,125,125,124,18,0,22,50,7, +47,28,22,9,2,5,1,3,35,27,53,8,1,5,8,15,1,31,2,19, +19,31,14,4,44,0,0,0,18,69,67,26,35,15,16,17,45,116,58,42, +124,124,72,76,58,78,38,36,98,33,19,17,31,48,3,52,92,5,5,2, +66,1,27,25,45,40,9,22,8,2,26,6,30,24,28,50,66,34,28,36, +124,124,124,124,20,2,10,32,3,24,30,14,1,102,3,113,103,124,18,36, +10,14,24,42,116,66,28,7,0,4,46,56,95,10,10,37,11,35,6,10, +23,38,24,22,67,20,41,31,2,51,12,8,2,57,111,15,47,47,59,85, +79,49,125,124,125,71,73,93,125,97,125,125,125,125,87,125,75,124,113,29, +25,41,53,55,49,59,57,57,91,91,79,83,85,125,23,29,77,29,47,49, +63,69,81,75,93,81,47,85,87,69,41,46,78,48,20,26,42,24,16,16, +86,56,68,52,48,46,66,52,70,62,58,44,102,86,76,68,82,32,14,10, +12,17,116,56,3,7,30,6,19,1,4,76,48,4,11,34,12,12,5,3, +124,6,22,32,38,36,24,54,62,30,56,64,90,0,14,13,12,74,13,19, +11,14,14,9,31,13,41,11,17,53,32,30,72,12,7,30,18,0,16,14, +2,31,2,1,9,5,40,79,47,32,55,15,29,17,18,29,35,8,8,71, +23,85,20,26,40,11,33,29,35,47,55,75,81,81,111,95,91,125,125,125, +125,125,125,109,97,121,87,99,89,57,71,37,43,49,49,93,75,75,121,85, +103,103,125,105,113,117,43,39,125,53,59,83,119,91,107,109,69,107,85,87, +111,101,107,93,101,111,11,2,36,8,74,94,4,24,42,50,12,44,82,8, +3,40,47,117,125,125,125,125,125,125,16,78,62,56,36,70,38,22,18,6, +15,5,26,8,58,78,6,12,26,34,12,30,64,12,1,40,47,117,125,125, +125,125,125,125,0,0,0,0,30,6,39,30,6,39,52,66,60,26,19,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,44,0,0,0,18,69,67,28,37,15,104,10, +11,17,6,37,24,46,46,70,26,52,46,32,64,9,25,15,31,78,4,54, +2,6,7,10,64,13,27,9,0,40,5,20,18,13,24,7,16,26,16,36, +48,42,45,15,8,7,4,15,20,21,5,38,19,30,34,8,103,18,17,89, +41,85,5,22,8,28,16,14,60,18,6,36,60,19,17,10,105,25,22,63, +2,29,48,4,59,72,2,3,79,78,43,83,2,93,25,14,26,8,14,6, +9,14,30,65,27,12,4,2,39,25,33,45,27,43,65,31,33,125,71,45, +83,73,51,0,20,3,13,11,37,53,37,71,81,61,97,121,117,125,51,51, +81,75,87,99,109,113,125,125,125,125,57,119,125,85,79,4,82,58,38,16, +10,5,3,13,2,24,104,68,52,34,100,42,34,12,18,20,112,70,42,22, +58,26,12,8,16,4,86,40,20,4,38,18,4,14,22,92,56,34,22,68, +32,32,30,22,124,19,1,20,5,7,2,20,22,8,22,36,52,23,15,27, +23,48,39,41,29,7,32,71,51,12,24,59,73,57,3,4,36,3,8,2, +14,34,29,7,5,14,51,17,31,25,26,75,25,10,13,48,15,3,70,15, +21,1,60,53,31,89,20,50,50,22,13,22,14,0,4,1,7,13,49,61, +75,59,47,75,123,71,63,61,49,43,13,11,41,67,13,31,33,25,47,89, +53,59,97,69,85,83,119,109,89,71,51,37,73,55,65,83,95,99,99,99, +105,113,125,121,125,125,125,111,125,125,3,30,14,28,38,38,124,60,56,9, +76,124,124,124,50,6,11,97,125,125,125,125,125,125,3,88,52,34,18,30, +4,7,9,0,4,16,42,24,66,44,26,44,44,50,52,26,56,42,3,14, +3,35,49,63,75,125,125,95,0,0,0,0,30,6,39,30,6,39,52,66, +60,26,19,63,89,24,122,20,76,15,24,52,7,29,6,43,105,37,125,125, +125,125,124,20,0,24,52,7,49,30,22,9,2,5,1,3,35,27,53,8, +1,3,8,15,0,31,2,19,19,31,14,4,44,0,0,0,18,69,67,28, +37,15,14,19,45,122,60,44,124,124,76,80,62,82,40,38,102,33,19,15, +31,48,3,54,96,5,3,2,70,1,29,27,45,40,9,24,8,4,28,6, +32,26,30,54,70,34,30,38,124,124,124,124,20,2,10,34,3,24,32,16, +0,106,3,117,107,124,18,36,10,14,24,44,118,68,28,7,0,4,46,58, +97,10,10,39,11,37,6,10,23,38,24,22,69,20,43,33,2,51,12,8, +2,61,117,17,51,51,65,89,85,53,125,124,125,75,77,97,125,103,125,125, +125,125,91,125,79,124,117,33,29,45,59,61,53,63,61,61,95,95,83,87, +87,125,23,29,77,31,49,51,65,71,83,77,97,83,49,87,89,69,41,50, +80,50,20,26,44,24,16,16,90,58,68,52,50,48,68,54,72,64,62,46, +102,86,76,68,84,34,14,10,12,17,116,56,5,7,30,6,19,0,4,74, +48,2,13,34,12,12,5,3,124,8,26,34,40,38,26,58,66,32,58,68, +94,0,16,11,14,78,11,19,11,14,16,9,31,13,41,11,17,55,34,32, +74,12,7,32,18,0,16,14,2,31,2,1,9,5,40,81,49,32,57,17, +31,17,18,31,37,8,8,73,23,87,18,24,38,13,37,33,39,51,61,79, +87,87,117,99,95,125,125,125,125,125,125,113,101,125,91,103,93,59,73,41, +49,53,55,99,79,79,125,91,107,109,125,109,117,119,45,41,125,57,63,87, +123,93,111,113,71,109,87,89,113,103,109,95,103,113,11,4,36,10,76,96, +4,24,42,50,12,46,84,8,3,38,51,121,125,125,125,125,125,125,16,78, +62,56,36,70,40,22,18,8,15,5,28,10,60,80,6,14,26,34,12,30, +64,12,1,38,51,121,125,125,125,125,125,125,0,0,0,0}, +/*cabac_init_idc = 2*/ +{124,18,21,124,18,21,125,81,20,18,24,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, +44,0,0,0,39,45,67,17,44,2,104,16,11,125,77,37,21,87,125,125, +125,63,125,101,125,119,103,117,103,0,9,41,81,13,59,53,125,21,67,55, +125,14,37,25,123,59,47,27,15,0,9,41,2,3,4,14,5,1,4,29, +26,22,56,38,50,36,34,38,92,24,26,88,60,2,89,73,75,55,61,49, +41,45,39,47,61,13,17,21,8,77,73,63,23,17,23,15,34,11,2,3, +52,17,12,18,2,17,124,108,76,90,108,88,52,90,68,60,66,36,10,2, +4,50,36,48,42,38,36,44,28,58,42,16,24,34,51,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,92,124,120,82,124,124,124,124,120,116,124, +94,82,30,52,6,9,67,15,42,26,18,2,10,0,17,21,55,7,72,48, +38,34,1,9,29,27,45,57,16,6,2,3,19,25,33,49,93,67,41,31, +19,21,45,65,67,107,29,60,30,20,2,15,31,45,53,67,124,59,41,31, +5,15,2,6,8,23,2,10,5,31,15,9,38,2,54,46,72,68,38,54, +62,42,30,2,34,1,81,67,65,49,43,43,43,49,5,27,25,25,10,25, +39,71,63,63,25,21,13,23,9,3,19,2,2,9,23,16,1,13,114,88, +94,98,100,104,96,94,80,80,86,74,38,46,32,92,84,82,72,68,56,26, +12,0,27,37,61,11,91,124,124,124,124,124,124,124,124,124,124,124,122,100, +56,10,124,124,66,124,124,124,120,124,116,104,116,102,104,68,74,48,5,84, +64,26,113,97,101,43,57,51,15,35,33,9,13,14,9,26,21,124,124,124, +124,120,114,58,18,37,23,80,58,40,18,16,4,1,9,57,85,67,53,53, +49,19,31,45,19,13,11,5,1,10,8,124,124,124,124,120,108,86,54,7, +0,0,0,0,124,18,21,124,18,21,125,81,20,18,24,94,124,124,24,2, +71,94,43,77,12,12,19,12,46,106,124,124,42,67,125,107,21,43,77,12, +59,49,38,16,51,79,105,12,10,41,65,0,43,85,0,23,53,75,16,31, +23,67,26,6,44,0,0,0,39,45,67,17,44,2,58,49,125,125,55,63, +41,45,51,55,125,25,79,53,125,33,25,41,29,16,4,39,125,31,81,55, +125,3,31,17,57,14,9,15,69,45,49,37,17,7,17,51,11,8,5,12, +15,15,10,21,38,11,2,24,32,42,44,20,25,29,39,22,7,53,7,17, +23,33,39,1,64,1,61,23,0,21,56,72,55,3,11,27,5,2,9,35, +66,112,80,21,5,121,52,124,124,125,48,42,58,68,64,52,42,46,60,40, +54,32,16,10,6,38,38,42,30,14,22,52,28,10,30,36,11,60,0,124, +124,124,106,124,124,124,124,92,76,68,60,96,86,19,58,64,38,94,54,54, +70,84,86,102,94,42,59,14,12,50,125,103,37,2,20,8,43,51,61,57, +125,73,12,7,15,27,43,49,81,69,125,37,30,4,5,13,23,31,39,57, +89,31,11,23,10,10,29,39,35,71,35,50,2,10,8,19,25,45,39,47, +124,125,125,113,125,101,107,109,107,99,109,113,121,61,77,71,85,125,57,12, +45,61,55,27,15,19,1,35,1,12,7,9,7,9,27,1,9,29,16,8, +3,18,38,6,13,25,45,13,1,13,16,14,11,3,21,18,18,25,37,27, +27,42,124,124,124,124,124,124,124,124,124,124,124,124,124,124,104,124,124,124, +124,124,124,96,124,124,92,50,36,18,31,124,124,124,124,96,96,76,82,94, +90,70,44,70,32,2,64,74,78,80,94,66,68,44,42,6,22,6,29,119, +20,14,4,60,26,4,29,21,17,17,23,15,0,13,23,17,7,20,8,22, +9,124,124,124,124,112,102,80,50,1,15,52,38,28,14,8,0,7,9,31, +29,21,17,17,23,15,0,13,23,17,7,20,8,22,9,124,124,124,124,112, +102,80,50,1,0,0,0,0,124,18,21,124,18,21,123,77,22,20,24,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,44,0,0,0,37,45,67,15,44,2,104,16, +11,123,75,37,19,83,123,123,123,59,123,97,123,115,101,115,101,2,7,39, +79,11,57,51,123,19,65,53,123,16,35,23,119,57,45,25,13,2,7,39, +4,1,4,14,3,1,4,27,26,22,56,38,50,36,34,38,90,24,26,86, +58,2,87,71,73,53,59,47,39,43,37,45,57,13,17,19,6,75,71,63, +21,17,21,13,34,9,2,3,50,15,12,16,2,17,124,108,76,90,108,88, +52,90,68,58,66,36,10,2,4,50,36,48,42,38,34,44,28,56,40,16, +22,32,51,124,124,124,124,124,124,124,124,124,124,124,124,124,120,88,124,118, +80,124,124,124,124,116,112,122,90,78,30,50,4,9,67,13,44,28,20,4, +10,0,15,19,53,5,74,50,40,34,0,7,27,25,43,55,18,8,4,1, +17,23,31,47,89,65,37,29,17,19,43,63,65,103,27,62,32,22,4,13, +29,43,51,65,124,57,39,29,5,13,2,8,10,21,4,12,3,29,15,9, +38,4,54,46,70,68,38,52,60,42,30,2,32,1,79,65,63,47,41,41, +41,47,5,25,23,23,10,23,37,69,61,63,25,19,13,21,9,3,17,2, +2,7,21,16,1,13,114,88,94,98,98,104,96,94,80,80,86,74,38,44, +30,90,82,80,70,66,54,26,12,0,25,35,59,11,89,124,124,124,124,124, +124,124,124,124,124,122,118,96,54,10,124,124,64,124,124,124,116,124,112,100, +112,98,100,66,70,46,7,82,62,24,109,93,97,41,55,49,11,33,31,9, +11,18,5,30,19,124,124,124,124,116,110,54,14,39,21,82,58,40,18,18, +4,1,9,55,83,65,51,51,45,17,29,43,17,11,9,3,0,12,8,124, +124,124,124,118,106,82,52,7,0,0,0,0,124,18,21,124,18,21,123,77, +22,20,24,92,124,124,26,4,67,92,41,73,12,12,15,12,44,104,124,120, +38,67,123,103,19,41,73,12,57,47,40,16,49,77,101,10,8,41,65,0, +41,83,0,23,51,73,16,29,21,65,28,6,44,0,0,0,37,45,67,15, +44,2,58,47,123,121,51,61,37,41,49,51,123,23,75,51,121,33,25,41, +29,18,4,37,121,29,79,53,123,3,29,17,55,16,9,13,67,43,47,35, +15,5,15,49,9,10,5,12,13,13,10,19,40,9,2,26,34,44,46,22, +25,27,37,22,7,51,7,15,21,31,35,2,66,2,57,23,1,19,58,74, +55,3,9,27,3,2,7,31,66,112,82,17,7,117,50,124,124,123,48,42, +58,68,64,52,42,46,60,40,54,32,16,10,6,38,38,42,30,14,22,52, +28,8,30,36,11,58,0,124,124,124,104,124,124,124,124,90,74,64,58,92, +84,21,56,62,36,92,54,54,68,82,84,100,92,40,59,14,12,48,123,99, +33,4,20,8,41,49,59,55,123,69,14,5,13,25,39,47,77,67,121,35, +32,6,3,11,21,29,37,55,85,29,7,21,12,10,27,37,33,69,33,52, +4,12,10,17,23,43,37,45,124,123,123,109,123,97,103,105,103,95,105,109, +115,59,75,69,83,119,55,10,43,59,53,25,15,17,1,33,1,12,7,9, +5,9,27,1,9,27,16,8,3,18,38,6,13,23,41,13,1,11,16,14, +11,3,19,18,18,23,35,25,25,40,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,100,124,124,124,124,124,124,94,120,120,90,48,34,18,31,124, +124,124,120,92,94,74,78,92,86,68,40,66,30,0,62,72,74,78,92,64, +66,42,40,4,22,6,29,117,18,12,2,58,24,2,27,19,15,15,19,13, +2,11,19,15,5,22,10,24,7,124,124,124,124,108,100,76,48,3,13,54, +40,30,16,10,2,5,7,29,27,19,15,15,19,13,2,11,19,15,5,22, +10,24,7,124,124,124,124,108,100,76,48,3,0,0,0,0,124,18,21,124, +18,21,119,75,22,20,24,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,44,0,0,0, +35,45,67,15,42,2,104,16,11,121,73,37,19,81,119,119,121,57,119,95, +119,113,99,113,99,4,7,37,77,11,57,49,119,19,65,53,121,16,35,23, +117,57,43,25,13,2,7,37,4,1,2,14,3,1,4,27,26,22,54,38, +48,36,34,38,86,24,26,82,56,0,85,69,71,51,57,45,37,41,37,43, +55,13,17,19,4,75,69,63,21,17,19,13,32,7,2,3,48,13,10,14, +2,19,120,106,74,88,106,86,50,88,68,56,64,36,10,2,4,48,34,46, +40,36,32,42,26,52,38,14,20,30,51,124,124,124,124,124,124,124,124,124, +124,124,124,124,116,82,124,114,76,124,124,124,124,112,108,116,86,74,28,46, +2,11,67,13,44,28,20,4,10,0,15,19,51,5,74,50,40,34,2,7, +25,25,41,53,20,10,4,1,15,23,31,45,87,63,35,27,17,19,41,61, +63,101,27,62,32,22,4,11,27,41,49,63,124,57,39,29,5,13,2,8, +10,21,4,12,1,29,15,9,36,4,52,44,68,66,38,50,58,42,30,0, +30,3,77,63,61,47,41,41,39,45,5,25,23,23,8,23,37,69,59,63, +25,19,13,19,9,3,15,2,2,7,19,14,1,15,112,88,94,96,96,102, +94,92,78,78,84,72,36,42,28,86,80,76,66,64,52,24,10,0,25,35, +59,13,87,124,124,124,124,124,124,124,124,124,124,118,114,92,52,8,124,120, +62,124,124,124,112,120,108,96,108,94,96,62,66,42,9,78,58,20,107,91, +95,39,53,47,7,31,29,9,9,20,3,32,17,124,124,124,124,110,104,48, +10,41,21,82,58,40,18,18,4,1,9,53,81,63,49,49,43,15,27,41, +15,9,7,3,2,12,8,124,124,124,122,114,102,78,48,9,0,0,0,0, +124,18,21,124,18,21,119,75,22,20,24,88,120,124,28,4,63,88,41,71, +12,12,13,10,42,102,120,114,34,69,119,101,19,41,71,12,57,45,40,16, +47,75,99,8,6,41,65,0,41,81,0,23,51,73,16,29,21,63,28,6, +44,0,0,0,35,45,67,15,42,2,58,45,121,117,49,59,33,37,47,49, +119,21,73,49,117,35,25,41,29,18,4,35,117,29,77,51,119,3,29,17, +55,16,9,13,65,43,45,35,15,5,15,47,7,10,5,12,13,13,10,19, +40,9,2,26,34,44,46,22,27,25,35,20,7,51,7,13,21,31,33,4, +68,6,53,25,3,19,58,74,57,3,9,29,1,2,7,29,66,112,82,15, +9,115,48,124,124,121,48,42,58,66,62,52,42,46,58,38,52,32,16,10, +6,36,36,40,30,14,22,50,26,6,28,34,11,56,1,124,124,124,100,120, +124,124,124,88,70,60,54,88,80,23,54,60,32,90,52,52,66,78,80,96, +88,36,59,12,10,44,121,97,31,6,20,8,39,47,57,53,119,67,16,3, +11,23,37,45,75,65,117,33,32,6,3,11,19,27,35,53,83,29,5,19, +12,10,25,35,33,67,31,52,6,12,10,15,21,41,35,43,124,121,119,105, +119,95,101,101,99,93,101,105,111,57,73,67,81,113,55,8,43,57,51,25, +15,17,1,33,1,10,7,9,3,9,27,1,9,27,16,8,3,16,36,6, +13,23,39,15,1,9,14,14,11,3,19,18,18,23,33,25,25,36,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,96,124,124,124,124,124,122,90, +116,116,86,46,32,16,31,124,124,124,116,88,90,70,74,88,82,64,36,62, +26,1,60,70,70,74,88,60,62,40,38,2,20,4,29,115,16,10,1,56, +22,0,27,19,13,13,17,11,4,11,17,13,3,22,12,26,5,124,124,124, +120,104,96,72,44,5,11,54,40,32,18,12,2,3,7,27,27,19,13,13, +17,11,4,11,17,13,3,22,12,26,5,124,124,124,120,104,96,72,44,5, +0,0,0,0,124,18,21,124,18,21,115,71,24,20,22,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,44,0,0,0,35,45,67,13,40,2,104,16,11,119,71,37, +17,79,115,115,117,55,115,93,115,111,97,111,97,6,7,35,75,11,55,49, +115,19,63,51,119,16,35,21,113,55,41,25,13,2,7,35,6,0,2,14, +3,1,4,27,26,20,54,38,46,36,34,38,82,24,24,78,54,1,83,67, +69,49,55,45,35,41,35,41,53,13,17,19,2,73,67,63,21,17,17,13, +30,5,2,3,46,11,10,12,2,21,118,104,74,86,104,84,50,86,66,54, +62,36,10,2,2,46,32,44,38,34,30,40,26,48,36,14,18,28,51,124, +124,124,124,124,124,124,124,124,124,124,124,124,110,78,124,110,74,124,122,124, +118,108,102,112,82,68,26,42,0,13,67,13,46,28,20,4,10,0,15,19, +51,5,74,50,40,34,4,5,25,23,41,51,22,10,6,1,13,21,29,45, +85,61,33,25,15,19,39,59,61,99,25,62,32,22,4,9,27,39,47,61, +124,55,37,27,5,13,2,8,10,21,4,12,1,29,15,9,36,6,50,42, +66,64,38,48,56,42,30,0,28,3,75,61,59,45,39,39,39,43,5,25, +23,21,8,23,37,67,57,63,25,19,13,17,9,3,13,2,2,7,17,12, +1,17,110,86,92,94,94,100,92,90,76,76,82,70,34,40,26,84,78,74, +62,60,50,22,10,1,25,35,59,13,85,124,124,124,124,124,124,124,124,124, +124,114,108,88,48,6,122,118,58,124,124,120,108,116,104,92,104,90,90,58, +62,38,11,74,54,18,105,89,93,37,51,45,5,29,27,9,7,24,0,36, +15,124,124,124,124,104,98,42,6,43,21,82,58,40,18,18,4,1,9,53, +79,61,47,47,41,15,27,39,15,9,7,3,2,12,8,124,124,124,118,110, +98,74,44,11,0,0,0,0,124,18,21,124,18,21,115,71,24,20,22,84, +118,122,28,4,59,86,41,67,12,10,11,8,40,100,116,106,30,71,115,97, +19,41,67,12,55,43,42,16,45,73,97,6,4,41,67,0,41,79,0,25, +51,73,16,29,21,61,30,6,44,0,0,0,35,45,67,13,40,2,56,45, +119,113,47,57,31,35,45,47,115,19,71,47,113,37,25,41,29,20,4,33, +113,29,75,49,115,3,29,17,55,18,9,11,63,43,43,35,15,5,13,45, +7,10,5,12,13,13,10,19,40,9,2,28,34,46,46,24,27,25,33,20, +7,51,7,11,21,29,31,6,70,8,49,25,5,17,58,74,59,3,7,29, +1,2,7,27,66,112,82,13,11,111,46,124,124,117,48,42,56,64,62,50, +40,46,58,36,50,32,16,10,4,36,34,38,28,14,22,48,26,4,28,32, +11,54,1,124,124,122,98,116,124,124,124,86,66,56,52,84,76,27,52,58, +28,88,50,50,64,76,76,92,84,34,59,10,8,42,117,93,27,6,20,8, +37,45,55,51,115,65,18,1,9,23,35,43,71,63,113,33,34,8,1,9, +17,27,35,51,81,29,1,17,12,10,23,35,33,65,29,54,8,14,10,13, +21,39,35,43,124,117,117,103,115,93,97,99,97,89,97,101,107,57,71,67, +79,107,55,6,43,55,49,25,15,17,1,31,1,8,7,9,3,9,27,1, +9,27,14,8,3,14,34,6,13,23,37,17,1,7,12,14,11,3,17,18, +16,21,31,25,25,34,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +92,124,124,124,124,124,118,86,112,110,82,44,30,14,31,124,124,124,112,84, +86,68,70,84,78,60,32,58,22,3,58,68,66,72,84,58,58,36,34,0, +18,2,29,113,14,6,3,54,20,1,27,17,13,13,15,9,6,11,15,11, +1,24,14,26,3,124,124,124,116,100,92,68,40,7,11,56,42,34,18,14, +4,3,5,27,27,17,13,13,15,9,6,11,15,11,1,24,14,26,3,124, +124,124,116,100,92,68,40,7,0,0,0,0,124,18,21,124,18,21,113,69, +24,20,22,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,44,0,0,0,33,47,67,13, +38,2,104,16,11,117,69,37,17,75,113,111,115,53,113,89,111,109,97,109, +97,6,7,33,73,11,55,47,111,19,63,51,117,16,33,21,111,55,41,25, +11,2,7,35,6,0,0,12,3,1,4,27,26,20,52,38,46,36,34,36, +78,24,24,74,52,3,81,65,67,47,55,43,33,39,35,39,51,13,17,17, +0,73,65,63,21,17,17,13,28,3,2,3,42,9,8,10,2,23,114,102, +72,84,102,82,48,84,66,50,60,34,10,2,2,44,32,42,38,32,28,38, +24,44,34,12,16,26,51,124,124,124,124,124,124,124,124,124,124,124,124,118, +106,72,124,108,70,124,118,124,114,102,98,106,78,64,24,40,3,15,67,13, +46,30,20,4,10,0,15,19,49,3,76,50,40,34,6,5,23,23,39,51, +24,12,6,1,13,21,29,43,83,61,31,25,15,19,37,57,61,97,25,64, +32,22,4,7,25,39,45,59,124,55,37,27,5,13,2,8,10,19,4,12, +0,29,15,9,34,6,48,40,64,62,38,44,54,40,30,1,26,5,75,61, +57,45,39,39,37,41,7,25,23,21,6,23,37,67,55,63,25,17,13,17, +9,3,11,2,0,7,15,12,3,19,108,86,92,92,92,98,90,88,74,74, +80,68,32,38,24,80,74,70,58,58,48,20,8,1,25,35,59,15,85,124, +124,124,124,124,124,124,124,124,120,110,104,84,46,4,118,114,56,124,124,116, +104,110,100,88,100,86,86,54,58,34,13,70,50,14,103,87,91,37,49,43, +1,27,25,9,5,26,2,38,15,124,124,124,124,98,92,36,2,45,21,82, +58,40,18,18,4,1,9,51,77,59,45,47,39,13,25,37,13,7,5,1, +4,14,8,124,124,124,114,106,94,70,40,13,0,0,0,0,124,18,21,124, +18,21,113,69,24,20,22,80,114,120,30,4,57,82,41,65,10,10,9,6, +36,96,112,100,24,73,111,95,19,41,65,10,55,41,42,14,45,71,93,4, +0,43,67,0,39,77,1,25,51,73,16,29,21,61,30,6,44,0,0,0, +33,47,67,13,38,2,56,43,117,109,45,55,27,31,45,45,111,17,69,45, +107,37,27,41,31,20,2,31,107,27,75,49,111,3,29,17,55,18,9,11, +61,43,43,33,15,5,13,43,5,10,7,10,13,13,10,19,40,9,2,28, +34,46,46,24,29,23,33,18,7,49,7,9,19,29,27,10,72,12,45,27, +7,17,60,74,61,3,7,31,0,2,7,25,66,112,82,9,13,109,44,124, +124,115,46,42,56,64,60,50,40,46,56,34,48,30,16,10,4,34,34,36, +28,12,20,46,24,2,26,30,11,50,3,124,124,118,94,114,124,124,124,84, +62,50,48,80,72,29,48,56,26,86,48,48,60,72,72,88,82,30,59,8, +6,38,115,91,25,8,20,8,35,43,53,51,111,61,20,1,9,21,31,41, +69,61,107,31,34,8,1,9,15,25,33,51,79,29,0,15,12,10,21,33, +33,63,27,54,10,14,10,11,19,37,33,41,124,115,113,99,113,91,95,95, +93,87,95,97,101,55,69,65,77,101,53,4,41,53,49,25,15,17,3,31, +3,6,7,9,1,9,27,1,9,25,14,6,3,12,32,4,13,23,35,19, +3,7,12,12,11,3,17,16,16,21,31,25,25,30,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,88,124,124,124,124,124,114,82,108,106,78,40, +28,12,31,124,124,124,108,80,82,64,66,80,74,56,28,52,20,7,56,66, +60,68,82,54,54,34,32,1,16,0,29,111,10,4,7,50,18,3,27,17, +11,11,13,9,6,9,13,9,0,24,16,28,3,124,124,120,112,96,88,62, +36,11,9,56,42,34,20,14,4,1,5,25,27,17,11,11,13,9,6,9, +13,9,0,24,16,28,3,124,124,120,112,96,88,62,36,11,0,0,0,0, +124,18,21,124,18,21,109,65,24,20,20,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, +44,0,0,0,33,47,67,11,36,2,104,16,11,115,67,37,15,73,109,107, +111,51,109,87,107,107,95,107,95,8,7,31,71,11,53,45,107,19,63,49, +113,18,33,19,109,53,39,25,11,4,5,33,8,2,0,12,3,1,4,27, +26,18,50,38,44,36,34,36,74,24,22,72,50,5,79,63,65,45,53,41, +31,37,33,37,49,13,17,17,1,71,63,63,19,17,15,13,26,1,2,3, +40,7,8,8,2,23,112,100,72,82,100,80,46,84,66,48,58,34,10,2, +0,44,30,40,36,30,26,38,22,40,32,10,14,24,51,124,124,124,124,124, +124,124,124,124,124,124,124,114,102,68,120,104,66,124,114,120,110,98,94,100, +74,58,22,36,5,15,67,13,46,30,20,4,10,0,15,19,49,3,76,50, +40,34,8,3,21,23,37,49,26,14,6,0,11,19,27,43,81,59,27,23, +15,17,35,55,59,95,23,64,34,22,4,5,23,37,43,57,124,55,37,25, +5,13,2,8,10,19,4,14,0,29,15,9,32,8,46,38,62,62,38,42, +52,40,30,3,24,5,73,59,55,43,37,37,37,39,7,25,23,21,4,23, +37,65,53,63,25,17,13,15,9,3,9,2,0,7,13,10,3,19,106,86, +90,92,90,96,88,86,74,72,78,66,30,36,22,78,72,68,54,56,46,18, +6,3,25,33,59,15,83,124,124,124,124,124,124,124,124,120,116,106,100,80, +42,2,114,110,54,122,124,112,100,106,96,84,96,82,80,50,54,30,15,66, +46,12,101,83,89,35,47,41,2,25,23,9,3,30,6,42,13,124,124,124, +124,94,86,32,1,47,21,82,58,40,18,18,4,1,9,51,75,57,43,45, +37,11,25,35,11,5,3,1,4,14,8,124,124,124,112,102,90,66,36,15, +0,0,0,0,124,18,21,124,18,21,109,65,24,20,20,76,112,118,32,4, +53,78,39,61,10,10,7,4,34,94,108,94,20,73,107,93,19,39,61,10, +55,39,42,14,43,69,91,2,1,43,67,0,39,75,1,25,51,73,16,27, +21,59,32,6,44,0,0,0,33,47,67,11,36,2,54,43,113,103,43,53, +25,29,43,43,107,15,67,43,103,39,27,41,31,20,2,29,103,27,73,47, +107,3,29,17,53,18,9,9,59,41,41,33,15,3,11,41,5,10,7,10, +11,13,10,19,42,9,2,30,36,46,46,24,29,23,31,18,7,49,7,7, +19,27,25,12,74,14,41,27,9,15,60,74,63,3,5,31,2,2,7,21, +66,112,82,7,15,105,42,124,124,113,46,42,54,62,60,50,38,46,56,32, +46,30,16,10,4,34,32,34,26,12,20,44,24,0,24,30,11,48,3,124, +124,116,92,110,124,124,124,82,58,46,46,76,68,31,46,54,22,84,46,46, +58,70,68,84,78,28,59,6,4,34,111,87,23,8,20,8,33,41,51,49, +107,59,22,0,7,19,29,39,65,59,103,29,36,10,0,7,13,23,33,49, +77,27,2,13,12,10,19,33,31,61,25,54,12,14,10,9,17,35,33,39, +124,113,111,97,109,89,91,93,89,83,91,93,97,53,67,63,75,95,53,2, +41,51,47,25,15,17,3,29,3,4,7,9,0,9,27,1,9,25,12,6, +3,10,30,4,13,23,33,19,3,5,10,12,11,3,17,16,14,21,29,25, +25,28,124,124,124,124,124,124,124,124,124,124,124,124,124,124,84,124,124,124, +124,124,110,80,104,100,74,38,26,10,31,124,124,124,104,76,78,62,62,76, +70,52,24,48,16,9,54,64,56,66,78,52,50,32,30,3,14,1,29,109, +8,2,9,48,16,5,27,15,11,9,11,7,8,9,11,7,2,26,18,28, +1,124,124,116,108,92,84,58,32,13,9,58,44,36,22,16,6,1,5,23, +27,15,11,9,11,7,8,9,11,7,2,26,18,28,1,124,124,116,108,92, +84,58,32,13,0,0,0,0,124,18,23,124,18,23,105,63,26,20,20,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,44,0,0,0,31,47,67,11,36,0,104,16, +11,113,67,37,15,71,105,103,109,49,105,85,103,105,93,105,93,10,7,29, +71,9,53,45,103,19,61,49,111,18,33,19,105,53,37,23,11,4,5,31, +8,2,1,12,3,1,4,27,26,18,50,38,42,36,34,36,70,24,22,68, +48,7,79,61,65,45,51,41,29,37,33,37,45,13,17,17,3,71,61,63, +19,17,13,11,24,1,2,3,38,5,6,6,2,25,108,98,70,82,98,80, +46,82,64,46,56,34,10,2,0,42,28,38,34,30,24,36,22,36,30,10, +12,22,51,124,124,124,124,124,124,124,124,124,124,124,124,108,96,62,116,100, +64,124,108,114,104,94,88,96,68,54,20,32,7,17,67,11,48,30,22,4, +10,0,15,19,47,3,76,52,40,34,10,3,21,21,37,47,28,14,8,0, +9,19,27,41,79,57,25,21,13,17,35,55,57,91,23,64,34,22,6,5, +23,35,43,55,124,53,35,25,5,13,2,8,10,19,6,14,2,29,15,11, +32,8,44,36,60,60,38,40,50,40,30,3,22,7,71,57,53,43,37,37, +35,39,7,23,21,19,4,23,37,65,51,63,25,17,13,13,9,3,7,0, +0,7,13,8,3,21,104,84,90,90,88,96,88,84,72,72,76,64,28,34, +20,74,70,64,50,52,42,16,6,3,25,33,57,17,81,124,124,124,124,124, +124,124,124,116,110,102,94,76,40,2,112,108,50,118,124,108,96,102,92,80, +90,78,76,46,50,28,19,62,42,8,99,81,87,33,45,39,4,23,21,9, +1,32,8,44,11,124,124,124,118,88,82,26,5,51,19,82,58,40,18,18, +4,1,9,49,73,57,41,43,35,11,23,33,11,5,3,1,6,14,8,124, +124,122,108,100,88,60,34,17,0,0,0,0,124,18,23,124,18,23,105,63, +26,20,20,74,108,116,32,6,49,76,39,59,10,8,5,2,32,92,106,86, +16,75,103,89,19,39,59,10,53,37,44,14,41,67,89,1,3,43,69,0, +39,75,1,27,49,73,14,27,21,57,32,6,44,0,0,0,31,47,67,11, +36,0,54,41,111,99,41,51,21,25,41,41,103,13,65,43,99,41,27,41, +31,22,2,27,99,27,71,45,103,3,29,17,53,20,11,9,59,41,39,33, +13,3,11,39,3,10,7,10,11,13,10,19,42,9,2,30,36,48,48,26, +31,21,29,16,7,49,7,5,19,27,23,14,74,18,39,29,11,15,60,74, +63,5,5,33,2,0,5,19,66,112,84,5,17,103,40,124,124,109,46,42, +54,60,58,48,38,44,54,32,46,30,14,10,2,32,30,32,26,12,20,44, +22,3,24,28,11,46,5,124,124,112,88,106,124,124,124,78,54,42,42,72, +64,35,44,50,18,80,44,44,56,66,64,80,74,24,59,4,2,32,109,85, +19,10,20,8,31,41,51,47,105,57,24,2,5,19,27,37,63,57,99,29, +36,10,0,7,11,23,31,47,75,27,6,11,12,10,19,31,31,61,25,56, +12,16,10,7,17,35,31,39,124,109,107,93,105,85,89,89,87,81,87,89, +93,53,65,63,75,89,53,0,41,51,45,25,15,17,3,29,3,2,7,9, +0,9,27,1,9,25,12,6,3,8,28,4,13,23,31,21,3,3,8,12, +11,3,15,16,14,19,27,25,25,24,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,80,124,124,124,124,124,104,76,100,96,70,36,24,8,31,124, +124,124,100,72,76,58,58,72,64,48,20,44,12,11,52,60,52,62,74,48, +46,28,26,5,12,3,31,107,6,1,13,46,12,7,25,15,9,9,9,5, +10,9,9,5,4,26,20,30,0,124,124,112,104,88,80,54,28,15,7,58, +44,38,22,18,6,0,3,23,25,15,9,9,9,5,10,9,9,5,4,26, +20,30,0,124,124,112,104,88,80,54,28,15,0,0,0,0,124,18,23,124, +18,23,101,59,26,20,18,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,44,0,0,0, +31,47,67,9,34,0,104,16,11,111,65,37,13,67,103,99,105,47,103,81, +99,103,91,103,93,12,7,27,69,9,51,43,99,19,61,47,109,18,31,17, +103,51,37,23,9,4,5,29,10,4,1,10,3,1,4,27,26,16,48,38, +42,36,34,34,66,24,20,64,46,9,77,59,63,43,49,39,27,35,31,35, +43,13,17,15,5,69,59,63,19,17,13,11,22,0,2,3,34,3,6,4, +2,27,106,96,70,80,96,78,44,80,64,44,54,34,10,2,1,40,28,36, +34,28,22,34,20,32,28,8,10,20,51,124,124,124,124,124,124,124,124,124, +124,120,122,104,92,58,112,98,60,124,104,110,100,88,84,90,64,48,18,30, +11,19,67,11,48,32,22,4,10,0,15,19,47,1,78,52,40,34,12,1, +19,21,35,45,30,16,8,0,7,17,25,41,77,57,23,21,13,17,33,53, +57,89,21,66,34,22,6,3,21,33,41,53,124,53,35,23,5,13,2,8, +10,17,6,14,2,29,15,11,30,10,42,34,58,58,38,38,48,38,30,5, +20,7,69,57,51,41,35,35,35,37,7,23,21,19,2,23,37,63,49,63, +25,15,13,13,9,3,5,0,0,7,11,8,5,23,102,84,88,88,86,94, +86,82,70,70,74,62,26,32,18,72,66,62,46,50,40,14,4,5,25,33, +57,17,79,124,124,124,124,124,124,124,122,112,106,98,90,72,36,0,108,104, +48,114,124,104,92,98,88,76,86,74,70,42,46,24,21,58,38,6,97,79, +85,33,43,37,8,21,19,9,0,36,12,48,11,124,124,122,112,82,76,20, +9,53,19,82,58,40,18,18,4,1,9,49,71,55,39,41,33,9,23,31, +9,3,1,0,6,16,8,124,124,118,104,96,84,56,30,19,0,0,0,0, +124,18,23,124,18,23,101,59,26,20,18,70,106,114,34,6,47,72,39,55, +8,8,3,0,30,90,102,80,10,77,99,87,19,39,55,8,53,35,44,14, +41,65,85,3,5,43,69,0,37,73,3,27,49,73,14,27,21,55,34,6, +44,0,0,0,31,47,67,9,34,0,52,41,109,95,39,49,19,23,39,39, +99,11,63,41,93,41,29,41,33,22,2,25,93,25,71,45,99,3,29,17, +53,20,11,7,57,41,37,31,13,3,9,37,3,10,9,10,11,13,10,19, +42,9,2,32,36,48,48,26,31,21,29,16,7,47,7,3,17,25,19,18, +76,20,35,29,13,13,62,74,65,5,3,33,4,0,5,17,66,112,84,1, +19,99,38,124,124,107,46,42,52,60,58,48,36,44,54,30,44,30,14,10, +2,32,30,30,24,12,20,42,22,5,22,26,11,44,5,124,124,108,86,104, +124,124,124,76,50,38,40,68,60,37,42,48,16,78,42,42,52,64,60,76, +72,22,59,2,0,28,105,81,17,10,20,8,29,39,49,47,101,53,26,4, +5,17,23,35,59,55,93,27,38,12,2,5,9,21,31,45,73,27,8,9, +12,10,17,31,31,59,23,56,14,16,10,5,15,33,31,37,124,107,105,91, +103,83,85,87,83,77,83,85,87,51,63,61,73,83,51,1,39,49,43,25, +15,17,3,27,5,0,7,9,2,9,27,1,9,23,10,4,3,6,26,2, +13,23,29,23,5,1,8,10,11,3,15,14,12,19,27,25,25,22,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,76,124,124,124,124,124,100,72, +96,90,66,34,22,6,31,124,122,124,96,68,72,56,54,68,60,44,16,40, +10,15,50,58,48,60,72,46,42,26,24,7,10,5,31,105,2,3,15,42, +10,9,25,13,9,7,7,3,10,7,7,3,6,28,22,30,0,124,120,108, +100,84,76,48,24,17,7,60,46,38,24,20,8,0,3,21,25,13,9,7, +7,3,10,7,7,3,6,28,22,30,0,124,120,108,100,84,76,48,24,17, +0,0,0,0,124,16,23,124,16,23,99,57,26,20,18,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,44,0,0,0,29,49,67,9,32,0,104,16,11,109,63,37, +13,65,99,95,103,45,99,79,97,101,91,101,91,12,7,25,67,9,51,43, +97,19,61,47,107,18,31,17,101,51,35,23,9,4,5,29,10,4,3,10, +3,1,4,27,26,16,46,38,40,36,34,34,62,24,20,60,44,11,75,57, +61,41,49,39,25,35,31,33,41,13,17,15,9,69,57,63,19,19,11,11, +20,2,2,3,32,1,4,2,2,29,102,94,68,78,94,76,42,78,62,40, +52,32,10,2,1,38,26,34,32,26,20,32,18,28,24,6,8,18,51,124, +124,124,124,124,124,124,124,124,122,116,116,98,86,52,108,94,56,122,100,104, +94,84,78,84,60,44,16,26,13,21,69,11,48,32,22,4,10,0,15,19, +45,1,78,52,40,34,14,1,19,21,35,45,32,16,8,0,7,17,25,39, +75,55,21,19,13,17,31,51,55,87,21,66,34,22,6,1,21,33,39,53, +124,53,35,23,5,13,2,8,10,17,6,14,4,29,15,11,28,10,40,32, +56,56,38,34,44,38,30,7,18,9,69,55,49,41,35,35,33,35,9,23, +21,19,0,23,37,63,49,65,25,15,13,11,9,3,5,0,1,7,9,6, +5,25,100,82,88,86,82,92,84,80,68,68,72,60,24,30,16,68,64,58, +42,46,38,12,2,5,25,33,57,19,79,124,124,124,124,124,124,122,116,108, +102,94,84,68,34,1,104,100,44,110,122,98,86,92,82,72,82,68,66,38, +40,20,23,54,34,2,95,77,83,31,41,37,10,19,19,9,0,38,14,50, +9,124,124,116,106,76,70,14,13,55,19,82,58,40,18,18,4,1,9,47, +71,53,37,41,31,9,21,31,9,3,1,0,8,16,6,124,124,114,100,92, +80,52,26,21,0,0,0,0,124,16,23,124,16,23,99,57,26,20,18,66, +102,112,34,6,43,68,39,53,8,6,1,1,26,86,98,72,6,79,95,85, +19,39,53,8,53,35,44,12,39,63,83,5,9,45,71,0,37,71,3,29, +49,73,14,27,21,55,34,6,44,0,0,0,29,49,67,9,32,0,52,39, +107,91,37,49,15,19,39,37,95,11,61,39,89,43,29,43,33,22,0,25, +89,25,69,43,97,3,29,17,53,20,11,7,55,41,37,31,13,3,9,35, +1,10,9,8,11,13,8,19,42,9,2,32,36,48,48,26,33,19,27,14, +7,47,7,1,17,25,17,20,78,24,31,31,15,13,62,74,67,5,3,35, +4,0,5,15,66,112,84,0,21,97,36,118,124,105,44,42,52,58,56,46, +36,44,52,28,42,28,14,8,0,30,28,28,24,10,18,40,20,7,20,24, +11,40,7,124,124,104,82,100,120,124,124,74,46,32,36,62,56,41,38,46, +12,76,40,40,50,60,56,72,68,18,59,0,1,24,103,79,15,12,20,8, +29,37,47,45,97,51,26,4,3,17,21,33,57,53,89,27,38,12,2,5, +9,21,29,45,71,27,10,7,12,10,15,29,31,57,21,56,16,16,10,3, +15,31,29,37,124,105,101,87,99,81,83,83,81,75,81,81,83,51,61,61, +71,77,51,3,39,47,43,25,15,17,5,27,5,1,7,9,2,9,27,3, +9,23,10,4,5,4,24,2,15,23,27,25,5,1,6,10,11,5,15,14, +12,19,25,25,25,18,124,124,124,124,124,124,124,124,124,124,124,124,124,122, +72,124,124,124,124,122,96,68,90,86,62,30,18,4,31,122,118,124,92,62, +68,52,48,64,56,40,12,34,6,17,46,56,42,56,68,42,38,22,20,9, +8,7,31,103,0,7,19,40,8,11,25,13,7,7,5,3,12,7,5,3, +8,28,22,32,2,122,116,104,96,80,72,44,20,21,5,60,46,40,24,20, +8,2,3,21,25,13,7,7,5,3,12,7,5,3,8,28,22,32,2,122, +116,104,96,80,72,44,20,21,0,0,0,0,124,16,23,124,16,23,95,55, +28,20,18,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,44,0,0,0,27,49,67,9, +30,0,104,16,11,107,61,37,13,63,95,91,99,41,95,77,93,99,89,99, +89,14,5,23,65,9,49,41,93,19,59,47,103,20,31,17,97,51,33,23, +9,6,3,27,10,4,3,10,1,1,4,25,26,16,46,38,38,36,34,34, +58,24,20,58,42,11,73,55,59,39,47,37,23,33,31,31,39,13,17,15, +11,67,55,63,17,19,9,11,18,4,2,3,30,0,2,0,2,29,100,92, +68,76,92,74,42,78,62,38,50,32,10,2,1,38,24,32,30,24,18,32, +18,26,22,6,6,16,51,124,124,124,124,124,124,124,124,124,118,112,112,92, +82,46,106,90,54,118,96,100,90,80,74,80,56,40,16,22,15,21,69,11, +50,32,22,6,10,0,13,19,43,1,78,52,42,34,16,0,17,19,33,43, +34,18,10,2,5,15,25,37,73,53,17,17,11,15,29,49,53,85,19,66, +36,24,6,0,19,31,37,51,124,51,33,21,5,13,2,10,12,17,6,16, +6,29,15,11,28,10,38,32,54,56,38,32,42,38,30,7,16,11,67,53, +47,41,33,35,31,33,9,23,21,17,0,23,37,63,47,65,25,15,13,9, +9,3,3,0,1,7,7,4,5,25,98,82,88,86,80,90,82,78,68,66, +70,60,24,28,14,66,62,54,38,44,36,12,2,5,23,31,57,21,77,124, +124,124,124,124,124,118,112,104,98,90,80,64,32,3,100,98,42,106,118,94, +82,88,78,68,78,64,62,36,36,16,25,50,30,1,93,73,79,29,39,35, +14,17,17,9,2,42,16,54,7,124,124,112,100,72,64,10,17,57,19,82, +58,40,18,20,4,1,9,45,69,51,35,39,27,7,19,29,7,1,0,0, +10,16,6,124,122,112,98,88,76,48,22,21,0,0,0,0,124,16,23,124, +16,23,95,55,28,20,18,62,98,112,36,6,39,66,37,49,8,6,0,1, +24,84,94,66,2,79,91,81,17,37,49,8,51,33,46,12,37,61,81,7, +11,45,71,0,37,69,3,29,49,73,14,25,19,53,34,6,44,0,0,0, +27,49,67,9,30,0,52,37,103,85,35,47,11,15,37,35,91,9,57,37, +85,45,29,43,33,24,0,23,85,25,67,41,93,3,27,17,51,22,11,5, +53,39,35,31,13,1,7,33,0,10,9,8,9,11,8,19,44,9,2,32, +38,50,48,28,33,17,25,12,7,47,7,0,17,23,15,22,80,28,27,33, +17,11,62,76,69,5,3,35,6,0,5,11,66,112,84,2,23,95,34,114, +124,101,44,42,52,56,56,46,36,44,52,26,40,28,14,8,0,30,26,28, +24,10,18,38,18,9,20,24,11,38,7,124,124,102,80,96,116,124,124,72, +42,28,34,58,54,43,36,44,8,74,38,38,48,56,54,68,64,16,59,0, +3,22,99,75,11,14,20,8,27,35,45,43,93,49,28,6,1,15,19,31, +55,51,85,25,40,14,4,5,7,19,27,43,67,25,14,5,14,10,13,27, +29,55,19,58,18,18,12,1,13,29,27,35,124,101,97,83,95,79,81,79, +77,71,77,77,79,49,59,59,69,69,51,5,39,45,41,23,15,17,5,27, +5,3,7,9,4,9,27,3,9,23,10,4,5,4,22,2,15,21,23,25, +5,0,4,10,11,5,13,14,12,17,23,23,23,14,124,124,124,124,124,124, +124,124,124,124,124,124,124,116,68,124,124,124,124,116,92,66,86,82,60,28, +16,2,31,118,114,120,88,58,64,50,44,60,52,36,8,30,2,19,44,54, +38,54,64,40,34,20,18,11,6,7,31,101,1,9,23,38,6,13,25,11, +5,5,1,1,14,7,3,1,10,30,24,34,4,120,114,100,92,76,68,40, +16,23,3,60,48,42,26,22,10,4,1,19,25,11,5,5,1,1,14,7, +3,1,10,30,24,34,4,120,114,100,92,76,68,40,16,23,0,0,0,0, +124,16,23,124,16,23,91,51,28,20,16,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, +44,0,0,0,27,49,67,7,28,0,104,16,11,105,59,37,11,59,93,87, +97,39,93,73,89,97,87,97,89,16,5,21,63,9,49,39,89,19,59,45, +101,20,29,15,95,49,33,23,7,6,3,25,12,6,5,8,1,1,4,25, +26,14,44,38,38,36,34,32,54,24,18,54,40,13,71,53,57,37,45,35, +21,31,29,29,37,13,17,13,13,67,53,63,17,19,9,11,16,6,2,3, +26,2,2,1,2,31,96,90,66,74,90,72,40,76,62,36,48,32,10,2, +3,36,24,30,30,22,16,30,16,22,20,4,4,14,51,124,124,124,124,124, +124,124,124,124,114,108,106,88,78,42,102,88,50,112,92,96,86,74,70,74, +52,34,14,20,19,23,69,11,50,34,22,6,10,0,13,19,43,0,80,52, +42,34,18,0,15,19,31,41,36,20,10,2,3,15,23,37,71,53,15,17, +11,15,27,47,53,83,19,68,36,24,6,2,17,29,35,49,124,51,33,21, +5,13,2,10,12,15,6,16,6,29,15,11,26,12,36,30,52,54,38,30, +40,36,30,9,14,11,65,53,45,39,33,33,31,31,9,23,21,17,1,23, +37,61,45,65,25,13,13,9,9,3,1,0,1,7,5,4,7,27,96,82, +86,84,78,88,80,76,66,64,68,58,22,26,12,62,58,52,34,42,34,10, +0,7,23,31,57,21,75,124,124,124,124,124,120,114,106,100,94,86,76,60, +28,5,96,94,40,102,114,90,78,84,74,64,74,60,56,32,32,12,27,46, +26,3,91,71,77,29,37,33,18,15,15,9,4,44,20,56,7,124,120,106, +94,66,58,4,21,59,19,82,58,40,18,20,4,1,9,45,67,49,33,37, +25,5,19,27,5,0,2,2,10,18,6,120,118,108,94,84,72,44,18,23, +0,0,0,0,124,16,23,124,16,23,91,51,28,20,16,58,96,110,38,6, +37,62,37,47,6,6,2,3,22,82,90,60,3,81,87,79,17,37,47,6, +51,31,46,12,37,59,77,9,13,45,71,0,35,67,5,29,49,73,14,25, +19,51,36,6,44,0,0,0,27,49,67,7,28,0,50,37,101,81,33,45, +9,13,35,33,87,7,55,35,79,45,31,43,35,24,0,21,79,23,67,41, +89,3,27,17,51,22,11,5,51,39,33,29,13,1,7,31,0,10,11,8, +9,11,8,19,44,9,2,34,38,50,48,28,35,17,25,12,7,45,7,2, +15,23,11,26,82,30,23,33,19,11,64,76,71,5,1,37,8,0,5,9, +66,112,84,6,25,91,32,108,124,99,44,42,50,56,54,46,34,44,50,24, +38,28,14,8,0,28,26,26,22,10,18,36,18,11,18,22,11,36,9,120, +124,98,76,94,112,124,124,70,38,24,30,54,50,45,34,42,6,72,36,36, +44,54,50,64,62,12,59,1,5,18,97,73,9,14,20,8,25,33,43,43, +89,45,30,8,1,13,15,29,51,49,79,23,40,14,4,3,5,17,27,41, +65,25,16,3,14,10,11,27,29,53,17,58,20,18,12,0,11,27,27,33, +124,99,95,81,93,77,77,77,73,69,73,73,73,47,57,57,67,63,49,7, +37,43,39,23,15,17,5,25,7,5,7,9,6,9,27,3,9,21,8,2, +5,2,20,0,15,21,21,27,7,2,4,8,11,5,13,12,10,17,23,23, +23,12,124,124,124,124,124,124,124,124,124,124,124,124,124,112,64,124,124,124, +124,110,88,62,82,76,56,26,14,0,31,114,108,114,84,54,60,46,40,56, +48,32,4,26,0,23,42,52,34,50,62,36,30,18,16,13,4,9,31,99, +5,11,25,34,4,15,25,11,5,3,0,0,14,5,1,0,12,30,26,34, +4,120,110,96,88,72,64,34,12,25,3,62,48,42,28,24,10,4,1,17, +25,11,5,3,0,0,14,5,1,0,12,30,26,34,4,120,110,96,88,72, +64,34,12,25,0,0,0,0,124,16,25,124,16,25,87,49,30,20,16,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,44,0,0,0,25,49,67,7,28,1,104,16, +11,103,59,37,11,57,89,83,93,37,89,71,85,95,85,95,87,18,5,19, +63,7,47,39,85,19,57,45,99,20,29,15,91,49,31,21,7,6,3,23, +12,6,5,8,1,1,4,25,26,14,44,38,36,36,34,32,50,24,18,50, +38,15,71,51,57,37,43,35,19,31,29,29,33,13,17,13,15,65,51,63, +17,19,7,9,14,6,2,3,24,4,0,3,2,33,94,88,66,74,88,72, +40,74,60,34,46,32,10,2,3,34,22,28,28,22,14,28,16,18,18,4, +2,12,51,124,124,124,124,124,124,124,124,124,108,104,102,82,72,36,98,84, +48,108,86,90,80,70,64,70,46,30,12,16,21,25,69,9,52,34,24,6, +10,0,13,19,41,0,80,54,42,34,20,2,15,17,31,39,38,20,12,2, +1,13,23,35,69,51,13,15,9,15,27,47,51,79,17,68,36,24,8,2, +17,27,35,47,124,49,31,19,5,13,2,10,12,15,8,16,8,29,15,13, +26,12,34,28,50,52,38,28,38,36,30,9,12,13,63,51,43,39,31,33, +29,31,9,21,19,15,1,23,37,61,43,65,25,13,13,7,9,3,0,1, +1,7,5,2,7,29,94,80,86,82,76,88,80,74,64,64,66,56,20,24, +10,60,56,48,30,38,30,8,0,7,23,31,55,23,73,124,124,124,124,124, +116,110,102,96,88,82,70,56,26,5,94,92,36,98,108,86,74,80,70,60, +68,56,52,28,28,10,31,42,22,7,89,69,75,27,35,31,20,13,13,9, +6,48,22,60,5,122,118,102,88,60,54,1,25,63,17,82,58,40,18,20, +4,1,9,43,65,49,31,35,23,5,17,25,5,0,2,2,12,18,6,118, +116,104,90,82,70,38,16,25,0,0,0,0,124,16,25,124,16,25,87,49, +30,20,16,56,92,108,38,8,33,60,37,43,6,4,4,5,20,80,88,52, +7,83,83,75,17,37,43,6,49,29,48,12,35,57,75,13,15,45,73,0, +35,67,5,31,47,73,12,25,19,49,36,6,44,0,0,0,25,49,67,7, +28,1,50,35,99,77,31,43,5,9,33,31,83,5,53,35,75,47,31,43, +35,26,0,19,75,23,65,39,85,3,27,17,51,24,13,3,51,39,31,29, +11,1,5,29,2,10,11,8,9,11,8,19,44,9,2,34,38,52,50,30, +35,15,23,10,7,45,7,4,15,21,9,28,82,34,21,35,21,9,64,76, +71,7,1,37,8,1,3,7,66,112,86,8,27,89,30,102,124,95,44,42, +50,54,54,44,34,42,50,24,38,28,12,8,1,28,24,24,22,10,18,36, +16,15,18,20,11,34,9,114,124,94,74,90,108,124,122,66,34,20,28,50, +46,49,32,38,2,68,34,34,42,50,46,60,58,10,59,3,7,16,93,69, +5,16,20,8,23,33,43,41,87,43,32,10,0,13,13,27,49,47,75,23, +42,16,6,3,3,17,25,39,63,25,20,1,14,10,11,25,29,53,17,60, +20,20,12,2,11,27,25,33,124,95,91,77,89,73,75,73,71,65,69,69, +69,47,55,57,67,57,49,9,37,43,37,23,15,17,5,25,7,7,7,9, +6,9,27,3,9,21,8,2,5,0,18,0,15,21,19,29,7,4,2,8, +11,5,11,12,10,15,21,23,23,8,124,122,124,124,124,124,124,124,124,124, +124,124,124,106,60,124,124,124,124,106,82,58,78,72,52,24,12,1,31,110, +104,110,80,50,58,44,36,52,42,28,0,22,3,25,40,48,30,48,58,34, +26,14,12,15,2,11,33,97,7,15,29,32,0,17,23,9,3,3,2,2, +16,5,0,2,14,32,28,36,6,118,106,92,84,68,60,30,8,27,1,62, +50,44,28,26,12,6,0,17,23,9,3,3,2,2,16,5,0,2,14,32, +28,36,6,118,106,92,84,68,60,30,8,27,0,0,0,0,124,16,25,124, +16,25,85,45,30,20,14,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,44,0,0,0, +25,51,67,5,26,1,104,16,11,101,57,37,9,55,85,79,91,35,85,69, +81,93,85,93,85,18,5,17,61,7,47,37,81,19,57,43,97,20,29,13, +89,47,29,21,7,6,3,23,14,8,7,8,1,1,4,25,26,12,42,38, +34,36,34,32,46,24,16,46,36,17,69,49,55,35,43,33,17,29,27,27, +31,13,17,13,17,65,49,63,17,19,5,9,12,8,2,3,22,6,0,5, +2,35,90,86,64,72,86,70,38,72,60,30,44,30,10,2,5,32,20,26, +26,20,12,26,14,14,16,2,0,10,51,124,124,122,124,124,124,124,124,122, +104,100,96,78,68,32,94,80,44,104,82,86,76,66,60,64,42,24,10,12, +23,27,69,9,52,34,24,6,10,0,13,19,41,0,80,54,42,34,22,2, +13,17,29,39,40,22,12,2,1,13,21,35,67,49,11,13,9,15,25,45, +49,77,17,68,36,24,8,4,15,27,33,45,124,49,31,19,5,13,2,10, +12,15,8,16,8,29,15,13,24,14,32,26,48,50,38,24,36,36,30,11, +10,13,63,49,41,37,31,31,29,29,11,21,19,15,3,23,37,59,41,65, +25,13,13,5,9,3,2,1,3,7,3,0,7,31,92,80,84,80,74,86, +78,72,62,62,64,54,18,22,8,56,54,46,26,36,28,6,1,9,23,31, +55,23,73,124,124,124,124,124,112,106,96,92,84,78,66,52,22,7,90,88, +34,94,104,82,70,74,66,56,64,52,46,24,24,6,33,38,18,9,87,67, +73,25,33,29,24,11,11,9,8,50,26,62,3,118,114,96,82,54,48,7, +29,65,17,82,58,40,18,20,4,1,9,43,63,47,29,35,21,3,17,23, +3,2,4,2,12,18,6,116,112,100,86,78,66,34,12,27,0,0,0,0, +124,16,25,124,16,25,85,45,30,20,14,52,90,106,40,8,29,56,37,41, +6,4,6,7,16,76,84,46,11,85,79,73,17,37,41,6,49,27,48,10, +33,55,73,15,19,47,73,0,35,65,5,31,47,73,12,25,19,49,38,6, +44,0,0,0,25,51,67,5,26,1,48,35,97,73,29,41,3,7,33,29, +79,3,51,33,71,49,31,43,35,26,1,17,71,23,63,37,81,3,27,17, +51,24,13,3,49,39,31,29,11,1,5,27,2,10,11,6,9,11,8,19, +44,9,2,36,38,52,50,30,37,15,21,10,7,45,7,6,15,21,7,30, +84,36,17,35,23,9,64,76,73,7,0,39,10,1,3,5,66,112,86,10, +29,85,28,96,120,93,42,42,48,52,52,44,32,42,48,22,36,26,12,8, +1,26,22,22,20,8,16,34,16,17,16,18,11,30,11,110,124,90,70,86, +104,124,116,64,30,14,24,46,42,51,28,36,1,66,32,32,40,48,42,56, +54,6,59,5,9,12,91,67,3,16,20,8,21,31,41,39,83,41,34,10, +2,11,11,25,45,45,71,21,42,16,6,1,1,15,25,39,61,25,22,0, +14,10,9,25,29,51,15,60,22,20,12,4,9,25,25,31,124,93,89,75, +85,71,71,71,67,63,67,65,65,45,53,55,65,51,49,11,37,41,37,23, +15,17,7,23,7,9,7,9,8,9,27,3,9,21,6,2,5,1,16,0, +15,21,17,31,7,4,0,8,11,5,11,12,8,15,19,23,23,6,124,120, +124,124,124,124,124,124,124,124,124,124,124,100,56,124,124,124,124,100,78,54, +74,66,48,20,10,3,31,104,100,106,76,46,54,40,32,48,38,24,3,16, +7,27,38,46,24,44,54,30,22,12,10,17,0,13,33,95,9,17,31,30, +1,19,23,9,3,1,4,2,18,5,2,4,16,32,30,36,8,118,102,88, +80,64,56,26,4,31,1,64,50,46,30,26,12,6,0,15,23,9,3,1, +4,2,18,5,2,4,16,32,30,36,8,118,102,88,80,64,56,26,4,31, +0,0,0,0,124,16,25,124,16,25,81,43,30,20,14,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,44,0,0,0,23,51,67,5,24,1,104,16,11,99,55,37, +9,51,83,75,87,33,83,65,77,91,83,91,85,20,5,15,59,7,45,35, +77,19,57,43,93,22,27,13,87,47,29,21,5,8,1,21,14,8,7,6, +1,1,4,25,26,12,40,38,34,36,34,30,42,24,16,44,34,19,67,47, +53,33,41,31,15,27,27,25,29,13,17,11,19,63,47,63,15,19,5,9, +10,10,2,3,18,8,1,7,2,35,88,84,64,70,84,68,36,72,60,28, +42,30,10,2,5,32,20,24,26,18,10,26,12,10,14,0,1,8,51,122, +124,118,124,122,120,120,120,118,100,96,92,72,64,26,90,78,40,98,78,82, +72,60,56,58,38,20,8,10,27,27,69,9,52,36,24,6,10,0,13,19, +39,2,82,54,42,34,24,4,11,17,27,37,42,24,12,4,0,11,21,33, +65,49,7,13,9,13,23,43,49,75,15,70,38,24,8,6,13,25,31,43, +124,49,31,17,5,13,2,10,12,13,8,18,10,29,15,13,22,14,30,24, +46,50,38,22,34,34,30,13,8,15,61,49,39,37,29,31,27,27,11,21, +19,15,5,23,37,59,39,65,25,11,13,5,9,3,4,1,3,7,1,0, +9,31,90,80,84,80,72,84,76,70,62,60,62,52,16,20,6,54,50,42, +22,34,26,4,3,9,23,29,55,25,71,124,124,124,124,120,108,102,92,88, +80,74,62,48,20,9,86,84,32,90,100,78,66,70,62,52,60,48,42,20, +20,2,35,34,14,13,85,63,71,25,31,27,28,9,9,9,10,54,28,66, +3,116,110,92,76,50,42,11,33,67,17,82,58,40,18,20,4,1,9,41, +61,45,27,33,19,1,15,21,1,4,6,4,14,20,6,112,110,98,84,74, +62,30,8,29,0,0,0,0,124,16,25,124,16,25,81,43,30,20,14,48, +86,104,42,8,27,52,35,37,4,4,8,9,14,74,80,40,17,85,75,71, +17,35,37,4,49,25,48,10,33,53,69,17,21,47,73,0,33,63,7,31, +47,73,12,23,19,47,38,6,44,0,0,0,23,51,67,5,24,1,48,33, +93,67,27,39,0,3,31,27,75,1,49,31,65,49,33,43,37,26,1,15, +65,21,63,37,77,3,27,17,49,24,13,1,47,37,29,27,11,0,3,25, +4,10,13,6,7,11,8,19,46,9,2,36,40,52,50,30,37,13,21,8, +7,43,7,8,13,19,3,34,86,40,13,37,25,7,66,76,75,7,0,39, +12,1,3,1,66,112,86,14,31,83,26,92,114,91,42,42,48,52,52,44, +32,42,48,20,34,26,12,8,1,26,22,20,20,8,16,32,14,19,14,18, +11,28,11,106,124,88,68,84,100,124,112,62,26,10,22,42,38,53,26,34, +3,64,30,30,36,44,38,52,52,4,59,7,11,8,87,63,1,18,20,8, +19,29,39,39,79,37,36,12,2,9,7,23,43,43,65,19,44,18,8,1, +0,13,23,37,59,23,24,2,14,10,7,23,27,49,13,60,24,20,12,6, +7,23,23,29,124,91,85,71,83,69,69,67,63,59,63,61,59,43,51,53, +63,45,47,13,35,39,35,23,15,17,7,23,9,11,7,9,10,9,27,3, +9,19,6,0,5,3,14,1,15,21,15,31,9,6,0,6,11,5,11,10, +8,15,19,23,23,2,124,118,124,124,124,124,124,124,124,124,124,124,120,96, +52,124,124,124,124,94,74,52,70,62,44,18,8,5,31,100,94,100,72,42, +50,38,28,44,34,20,7,12,9,31,36,44,20,42,52,28,18,10,8,19, +1,15,33,93,13,19,35,26,3,21,23,7,1,0,6,4,18,3,4,6, +18,34,32,38,8,116,98,84,76,60,52,20,0,33,0,64,52,46,32,28, +14,8,0,13,23,7,1,0,6,4,18,3,4,6,18,34,32,38,8,116, +98,84,76,60,52,20,0,33,0,0,0,0,122,16,25,122,16,25,77,39, +32,20,12,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,44,0,0,0,23,51,67,3, +22,1,104,16,11,97,53,37,7,49,79,71,85,31,79,63,73,89,81,89, +83,22,5,13,57,7,45,35,73,19,55,41,91,22,27,11,83,45,27,21, +5,8,1,19,16,10,9,6,1,1,4,25,26,10,40,38,32,36,34,30, +38,24,14,40,32,21,65,45,51,31,39,31,13,27,25,23,27,13,17,11, +21,63,45,63,15,19,3,9,8,12,2,3,16,10,1,9,2,37,84,82, +62,68,82,66,36,70,58,26,40,30,10,2,7,30,18,22,24,16,8,24, +12,6,12,0,3,6,51,120,122,116,124,118,116,116,116,112,94,92,86,68, +58,22,86,74,38,94,74,76,66,56,50,54,34,14,6,6,29,29,69,9, +54,36,24,6,10,0,13,19,39,2,82,54,42,34,26,4,11,15,27,35, +44,24,14,4,2,11,19,33,63,47,5,11,7,13,21,41,47,73,15,70, +38,24,8,8,13,23,29,41,124,47,29,17,5,13,2,10,12,13,8,18, +10,29,15,13,22,16,28,22,44,48,38,20,32,34,30,13,6,15,59,47, +37,35,29,29,27,25,11,21,19,13,5,23,37,57,37,65,25,11,13,3, +9,3,6,1,3,7,0,1,9,33,88,78,82,78,70,82,74,68,60,58, +60,50,14,18,4,50,48,40,18,30,24,2,3,11,23,29,55,25,69,124, +124,122,122,114,104,98,86,84,76,70,56,44,16,11,82,82,28,86,96,74, +62,66,58,48,56,44,36,16,16,1,37,30,10,15,83,61,69,23,29,25, +30,7,7,9,12,56,32,68,1,112,108,86,70,44,36,17,37,69,17,82, +58,40,18,20,4,1,9,41,59,43,25,31,17,1,15,19,1,4,6,4, +14,20,6,110,106,94,80,70,58,26,4,31,0,0,0,0,122,16,25,122, +16,25,77,39,32,20,12,44,84,102,42,8,23,50,35,35,4,2,10,11, +12,72,76,32,21,87,71,67,17,35,35,4,47,23,50,10,31,51,67,19, +23,47,75,0,33,61,7,33,47,73,12,23,19,45,40,6,44,0,0,0, +23,51,67,3,22,1,46,33,91,63,25,37,2,1,29,25,71,0,47,29, +61,51,33,43,37,28,1,13,61,21,61,35,73,3,27,17,49,26,13,1, +45,37,27,27,11,0,3,23,4,10,13,6,7,11,8,19,46,9,2,38, +40,54,50,32,39,13,19,8,7,43,7,10,13,19,1,36,88,42,9,37, +27,7,66,76,77,7,2,41,12,1,3,0,66,112,86,16,33,79,24,86, +108,87,42,42,46,50,50,42,30,42,46,18,32,26,12,8,3,24,20,18, +18,8,16,30,14,21,14,16,11,26,13,102,120,84,64,80,96,124,106,60, +22,6,18,38,34,57,24,32,7,62,28,28,34,42,34,48,48,0,59,9, +13,6,85,61,2,18,20,8,17,27,37,37,75,35,38,14,4,9,5,21, +39,41,61,19,44,18,8,0,2,13,23,35,57,23,28,4,14,10,5,23, +27,47,11,62,26,22,12,8,7,21,23,29,124,87,83,69,79,67,65,65, +61,57,59,57,55,43,49,53,61,39,47,15,35,37,33,23,15,17,7,21, +9,13,7,9,10,9,27,3,9,19,4,0,5,5,12,1,15,21,13,33, +9,8,1,6,11,5,9,10,6,13,17,23,23,0,124,116,122,122,122,124, +124,124,122,124,124,124,114,90,48,124,120,118,120,88,70,48,66,56,40,16, +6,7,31,96,90,96,68,38,46,34,24,40,30,16,11,8,13,33,34,42, +16,38,48,24,14,6,4,21,3,17,33,91,15,23,37,24,5,23,23,7, +1,0,8,6,20,3,6,8,20,34,34,38,10,116,94,80,72,56,48,16, +3,35,0,66,52,48,32,30,14,8,2,13,23,7,1,0,8,6,20,3, +6,8,20,34,34,38,10,116,94,80,72,56,48,16,3,35,0,0,0,0, +120,16,25,120,16,25,73,37,32,20,12,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, +44,0,0,0,21,51,67,3,20,1,104,16,11,95,51,37,7,47,75,67, +81,29,75,61,69,87,79,87,81,24,5,11,55,7,43,33,69,19,55,41, +89,22,27,11,81,45,25,21,5,8,1,17,16,10,9,6,1,1,4,25, +26,10,38,38,30,36,34,30,34,24,14,36,30,23,63,43,49,29,37,29, +11,25,25,21,25,13,17,11,23,61,43,63,15,19,1,9,6,14,2,3, +14,12,3,11,2,39,82,80,62,66,80,64,34,68,58,24,38,30,10,2, +7,28,16,20,22,14,6,22,10,2,10,1,5,4,51,116,120,112,120,114, +112,112,112,108,90,88,82,62,54,16,82,70,34,90,70,72,62,52,46,48, +30,10,4,2,31,31,69,9,54,36,24,6,10,0,13,19,37,2,82,54, +42,34,28,6,9,15,25,33,46,26,14,4,4,9,19,31,61,45,3,9, +7,13,19,39,45,71,13,70,38,24,8,10,11,21,27,39,124,47,29,15, +5,13,2,10,12,13,8,18,12,29,15,13,20,16,26,20,42,46,38,18, +30,34,30,15,4,17,57,45,35,35,27,29,25,23,11,21,19,13,7,23, +37,57,35,65,25,11,13,1,9,3,8,1,3,7,2,3,9,35,86,78, +82,76,68,80,72,66,58,56,58,48,12,16,2,48,46,36,14,28,22,0, +5,11,23,29,55,27,67,124,124,118,118,108,100,94,82,80,72,66,52,40, +14,13,78,78,26,82,92,70,58,62,54,44,52,40,32,12,12,5,39,26, +6,19,81,59,67,21,27,23,34,5,5,9,14,60,34,72,0,110,104,82, +64,38,30,23,41,71,17,82,58,40,18,20,4,1,9,39,57,41,23,29, +15,0,13,17,0,6,8,4,16,20,6,108,104,90,76,66,54,22,0,33, +0,0,0,0,120,16,25,120,16,25,73,37,32,20,12,40,80,100,44,8, +19,46,35,31,4,2,12,13,10,70,72,26,25,89,67,65,17,35,31,4, +47,21,50,10,29,49,65,21,25,47,75,0,33,59,7,33,47,73,12,23, +19,43,40,6,44,0,0,0,21,51,67,3,20,1,46,31,89,59,23,35, +6,2,27,23,67,2,45,27,57,53,33,43,37,28,1,11,57,21,59,33, +69,3,27,17,49,26,13,0,43,37,25,27,11,0,1,21,6,10,13,6, +7,11,8,19,46,9,2,38,40,54,50,32,39,11,17,6,7,43,7,12, +13,17,0,38,90,46,5,39,29,5,66,76,79,7,2,41,14,1,3,2, +66,112,86,18,35,77,22,80,102,85,42,42,46,48,50,42,30,42,46,16, +30,26,12,8,3,24,18,16,18,8,16,28,12,23,12,14,11,24,13,98, +116,80,62,76,92,118,102,58,18,2,16,34,30,59,22,30,11,60,26,26, +32,38,30,44,44,1,59,11,15,2,81,57,4,20,20,8,15,25,35,35, +71,33,40,16,6,7,3,19,37,39,57,17,46,20,10,0,4,11,21,33, +55,23,30,6,14,10,3,21,27,45,9,62,28,22,12,10,5,19,21,27, +124,85,79,65,75,65,63,61,57,53,55,53,51,41,47,51,59,33,47,17, +35,35,31,23,15,17,7,21,9,15,7,9,12,9,27,3,9,19,4,0, +5,7,10,1,15,21,11,35,9,10,3,6,11,5,9,10,6,13,15,23, +23,3,122,114,120,118,118,124,124,124,118,120,124,122,108,84,44,122,114,110, +110,82,66,44,62,52,36,14,4,9,31,92,86,92,64,34,42,32,20,36, +26,12,15,4,17,35,32,40,12,36,44,22,10,4,2,23,5,19,33,89, +17,25,41,22,7,25,23,5,0,2,10,8,22,3,8,10,22,36,36,40, +12,114,90,76,68,52,44,12,7,37,2,66,54,50,34,32,16,10,2,11, +23,5,0,2,10,8,22,3,8,10,22,36,36,40,12,114,90,76,68,52, +44,12,7,37,0,0,0,0,116,14,27,116,14,27,71,35,32,20,10,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,44,0,0,0,21,53,67,3,18,3,104,14, +11,93,51,37,7,45,73,65,79,27,73,59,67,85,79,85,81,24,5,11, +55,7,43,33,67,19,55,41,87,22,27,11,79,45,25,21,5,8,1,17, +16,10,11,4,1,3,4,25,24,8,36,38,28,34,34,28,30,22,12,32, +28,25,63,43,49,29,37,29,9,25,25,21,23,15,17,11,27,61,43,63, +15,21,1,9,4,14,2,3,10,12,5,13,2,41,78,78,60,64,78,62, +32,66,56,20,36,28,8,2,9,26,14,18,20,12,4,20,8,1,6,3, +9,0,51,112,116,108,116,110,106,106,106,102,84,82,76,56,48,10,78,66, +30,84,64,66,56,46,40,42,24,4,2,1,35,33,71,9,54,36,24,6, +10,1,13,19,37,2,82,54,42,34,30,6,9,15,25,33,46,26,14,4, +4,9,19,31,59,45,1,9,7,13,19,39,45,69,13,70,38,24,8,10, +11,21,27,39,124,47,29,15,5,13,2,10,12,13,8,18,12,29,15,15, +18,16,24,18,40,44,36,14,26,32,28,17,0,19,57,45,33,35,27,29, +25,23,13,21,19,13,9,23,37,57,35,67,25,11,13,1,11,3,8,3, +5,7,2,5,11,37,84,76,80,74,64,78,70,64,56,54,56,46,10,12, +1,44,42,32,10,24,18,1,7,13,23,29,55,29,67,124,122,114,112,102, +94,88,76,74,66,60,46,34,10,15,74,74,22,78,86,64,52,56,48,40, +46,34,26,8,6,9,43,22,2,23,79,57,65,21,27,23,36,5,5,9, +14,62,36,74,0,106,100,76,56,32,24,29,47,75,17,82,56,38,18,20, +4,3,9,39,57,41,23,29,13,0,13,17,0,6,8,4,16,20,4,104, +100,86,72,62,50,16,3,35,0,0,0,0,116,14,27,116,14,27,71,35, +32,20,10,36,76,98,44,8,17,42,35,29,2,0,14,15,6,66,68,18, +31,91,63,63,17,35,29,2,47,21,50,8,29,49,63,25,29,49,77,1, +33,59,9,35,47,73,10,23,19,43,40,4,44,0,0,0,21,53,67,3, +18,3,44,31,87,55,21,35,8,4,27,21,65,2,43,27,53,55,35,45, +39,28,3,11,53,21,59,33,67,3,27,17,49,26,15,0,43,37,25,27, +11,0,1,19,6,10,15,4,7,11,6,19,46,9,2,38,40,54,50,32, +41,11,17,4,7,43,9,12,13,17,2,40,90,48,3,41,33,5,66,76, +81,9,2,43,14,3,3,4,66,110,86,20,37,75,18,74,94,83,40,42, +44,46,48,40,28,40,44,14,28,24,10,6,5,22,16,14,16,6,14,26, +10,27,10,12,11,20,15,92,110,76,58,72,86,110,96,54,14,3,12,28, +26,63,18,26,15,56,24,24,28,34,26,40,40,5,59,13,17,1,79,55, +6,20,20,8,15,25,35,35,69,31,40,16,6,7,1,17,35,39,53,17, +46,20,10,0,4,11,21,33,53,23,32,8,14,8,3,21,27,45,9,62, +28,22,12,12,5,19,21,27,124,83,77,63,73,63,61,59,55,51,53,51, +47,41,47,51,59,27,47,21,35,35,31,23,15,17,9,21,11,17,9,9, +12,11,27,5,9,19,2,1,7,9,8,3,17,21,9,37,11,10,5,4, +11,7,9,8,4,13,15,23,23,7,118,112,116,114,112,124,124,124,112,114, +124,116,100,78,40,114,106,102,98,76,60,40,56,46,32,10,0,11,31,86, +80,86,60,28,38,28,14,32,20,8,21,1,21,39,28,36,6,32,40,18, +6,0,1,25,7,21,35,87,21,29,45,18,11,29,23,5,0,2,12,8, +22,3,10,10,24,36,36,40,12,112,86,72,62,46,40,6,11,41,2,66, +54,50,34,32,16,10,2,11,23,5,0,2,12,8,22,3,10,10,24,36, +36,40,12,112,86,72,62,46,40,6,11,41,0,0,0,0,114,14,27,114, +14,27,67,31,34,22,10,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,44,0,0,0, +19,53,67,1,18,3,104,14,11,89,49,37,5,41,69,61,75,23,69,55, +63,81,77,83,79,26,3,9,53,5,41,31,63,17,53,39,83,24,25,9, +75,43,23,19,3,10,0,15,18,12,11,4,0,3,4,23,24,8,36,38, +28,34,34,28,28,22,12,30,26,25,61,41,47,27,35,27,7,23,23,19, +19,15,17,9,29,59,41,63,13,21,0,7,4,16,2,3,8,14,5,15, +2,41,76,78,60,64,78,62,32,66,56,18,36,28,8,2,9,26,14,18, +20,12,2,20,8,3,4,3,11,1,51,110,114,106,114,108,102,102,102,98, +80,78,72,52,44,6,76,64,28,80,60,62,52,42,36,38,20,0,2,3, +37,33,71,7,56,38,26,8,10,1,11,17,35,4,84,56,44,34,32,8, +7,13,23,31,48,28,16,6,6,7,17,29,55,43,2,7,5,11,17,37, +43,65,11,72,40,26,10,12,9,19,25,37,124,45,27,13,5,11,2,12, +14,11,10,20,14,27,15,15,18,18,24,18,38,44,36,12,24,32,28,17, +1,19,55,43,31,33,25,27,23,21,13,19,17,11,9,21,35,55,33,67, +25,9,13,0,11,3,10,3,5,5,4,5,11,37,84,76,80,74,62,78, +70,64,56,54,56,46,10,10,3,42,40,30,8,22,16,1,7,13,21,27, +53,29,65,120,118,110,108,98,90,84,72,70,62,56,42,30,8,15,72,72, +20,76,82,60,48,52,44,36,42,30,22,6,2,11,45,20,0,25,75,53, +61,19,25,21,40,3,3,9,16,66,40,78,2,104,98,72,50,28,20,33, +51,77,15,84,56,38,18,22,4,3,9,37,55,39,21,27,9,2,11,15, +2,8,10,6,18,22,4,102,98,84,70,60,48,12,5,35,0,0,0,0, +114,14,27,114,14,27,67,31,34,22,10,34,74,98,46,10,13,40,33,25, +2,0,18,15,4,64,66,12,35,91,59,59,15,33,25,2,45,19,52,8, +27,47,59,27,31,49,77,1,31,57,9,35,45,71,10,21,17,41,42,4, +44,0,0,0,19,53,67,1,18,3,44,29,83,49,17,33,12,8,25,17, +61,4,39,25,47,55,35,45,39,30,3,9,47,19,57,31,63,3,25,17, +47,28,15,2,41,35,23,25,9,2,0,17,8,12,15,4,5,9,6,17, +48,7,2,40,42,56,52,34,41,9,15,4,7,41,9,14,11,15,6,44, +92,52,0,41,35,3,68,78,81,9,4,43,16,3,1,8,66,110,88,24, +39,71,16,70,88,79,40,42,44,46,48,40,28,40,44,14,28,24,10,6, +5,22,16,14,16,6,14,26,10,29,10,12,11,18,15,88,106,74,56,70, +82,104,92,52,12,7,10,24,24,65,16,24,17,54,24,24,26,32,24,38, +38,7,59,13,17,3,75,51,10,22,20,8,13,23,33,33,65,27,42,18, +8,5,2,15,31,37,47,15,48,22,12,2,6,9,19,31,49,21,36,10, +16,8,1,19,25,43,7,64,30,24,14,14,3,17,19,25,124,79,73,59, +69,59,57,55,51,47,49,47,41,39,45,49,57,19,45,23,33,33,29,21, +15,15,9,19,11,17,9,9,14,11,27,5,9,17,2,1,7,9,8,3, +17,19,5,37,11,12,5,4,11,7,7,8,4,11,13,21,21,9,116,110, +114,112,108,120,120,118,108,110,118,112,94,74,36,108,100,96,88,72,56,38, +52,42,30,8,1,11,31,82,76,82,56,24,36,26,10,30,16,6,25,5, +23,41,26,34,2,30,38,16,4,1,3,27,7,21,35,85,23,31,47,16, +13,31,21,3,2,4,16,10,24,1,14,12,26,38,38,42,14,112,84,70, +58,42,38,2,13,43,4,68,56,52,36,34,18,12,4,9,21,3,2,4, +16,10,24,1,14,12,26,38,38,42,14,112,84,70,58,42,38,2,13,43, +0,0,0,0,112,14,27,112,14,27,63,29,34,22,10,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,44,0,0,0,17,53,67,1,16,3,104,14,11,87,47,37, +5,39,65,57,73,21,65,53,59,79,75,81,77,28,3,7,51,5,41,29, +59,17,53,39,81,24,25,9,73,43,21,19,3,10,0,13,18,12,13,4, +0,3,4,23,24,8,34,38,26,34,34,28,24,22,12,26,24,27,59,39, +45,25,33,25,5,21,23,17,17,15,17,9,31,59,39,63,13,21,2,7, +2,18,2,3,6,16,7,17,2,43,72,76,58,62,76,60,30,64,56,16, +34,28,8,2,9,24,12,16,18,10,0,18,6,7,2,5,13,3,51,106, +112,102,110,104,98,98,98,92,76,74,66,46,40,0,72,60,24,76,56,58, +48,38,32,32,16,3,0,7,39,35,71,7,56,38,26,8,10,1,11,17, +33,4,84,56,44,34,34,8,5,13,21,29,50,30,16,6,8,7,17,27, +53,41,4,5,5,11,15,35,41,63,11,72,40,26,10,14,7,17,23,35, +124,45,27,13,5,11,2,12,14,11,10,20,16,27,15,15,16,18,22,16, +36,42,36,10,22,32,28,19,3,21,53,41,29,33,25,27,21,19,13,19, +17,11,11,21,35,55,31,67,25,9,13,2,11,3,12,3,5,5,6,7, +11,39,82,76,80,72,60,76,68,62,54,52,54,44,8,8,5,38,38,26, +4,20,14,3,9,13,21,27,53,31,63,116,114,106,104,92,86,80,66,66, +58,52,38,26,6,17,68,68,18,72,78,56,44,48,40,32,38,26,18,2, +1,15,47,16,3,29,73,51,59,17,23,19,44,1,1,9,18,68,42,80, +4,102,94,66,44,22,14,39,55,79,15,84,56,38,18,22,4,3,9,35, +53,37,19,25,7,4,9,13,4,10,12,6,20,22,4,100,94,80,66,56, +44,8,9,37,0,0,0,0,112,14,27,112,14,27,63,29,34,22,10,30, +70,96,48,10,9,36,33,23,2,0,20,17,2,62,62,6,39,93,55,57, +15,33,23,2,45,17,52,8,25,45,57,29,33,49,77,1,31,55,9,35, +45,71,10,21,17,39,42,4,44,0,0,0,17,53,67,1,16,3,44,27, +81,45,15,31,16,12,23,15,57,6,37,23,43,57,35,45,39,30,3,7, +43,19,55,29,59,3,25,17,47,28,15,2,39,35,21,25,9,2,0,15, +10,12,15,4,5,9,6,17,48,7,2,40,42,56,52,34,43,7,13,2, +7,41,9,16,11,15,8,46,94,56,4,43,37,3,68,78,83,9,4,45, +18,3,1,10,66,110,88,26,41,69,14,64,82,77,40,42,44,44,46,40, +28,40,42,12,26,24,10,6,5,20,14,12,16,6,14,24,8,31,8,10, +11,16,17,84,102,70,52,66,78,98,88,50,8,11,6,20,20,67,14,22, +21,52,22,22,24,28,20,34,34,11,59,15,19,7,73,49,12,24,20,8, +11,21,31,31,61,25,44,20,10,3,4,13,29,35,43,13,48,22,12,2, +8,7,17,29,47,21,38,12,16,8,0,17,25,41,5,64,32,24,14,16, +1,15,17,23,124,77,69,55,65,57,55,51,47,45,45,43,37,37,43,47, +55,13,45,25,33,31,27,21,15,15,9,19,11,19,9,9,16,11,27,5, +9,17,2,1,7,11,6,3,17,19,3,39,11,14,7,4,11,7,7,8, +4,11,11,21,21,13,114,108,112,108,104,114,114,112,104,104,112,106,88,68, +32,100,92,88,78,66,52,34,48,38,26,6,3,13,31,78,72,78,52,20, +32,22,6,26,12,2,29,9,27,43,24,32,1,26,34,12,0,3,5,29, +9,23,35,83,25,33,51,14,15,33,21,3,4,6,18,12,26,1,16,14, +28,38,40,44,16,110,80,66,54,38,34,1,17,45,6,68,56,54,38,36, +18,14,4,7,21,3,4,6,18,12,26,1,16,14,28,38,40,44,16,110, +80,66,54,38,34,1,17,45,0,0,0,0,110,14,27,110,14,27,59,25, +36,22,8,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,44,0,0,0,17,53,67,0, +14,3,104,14,11,85,45,37,3,37,61,53,69,19,61,51,55,77,73,79, +75,30,3,5,49,5,39,29,55,17,51,37,79,24,25,7,69,41,19,19, +3,10,0,11,20,14,13,4,0,3,4,23,24,6,34,38,24,34,34,28, +20,22,10,22,22,29,57,37,43,23,31,25,3,21,21,15,15,15,17,9, +33,57,37,63,13,21,4,7,0,20,2,3,4,18,7,19,2,45,70,74, +58,60,74,58,30,62,54,14,32,28,8,2,11,22,10,14,16,8,1,16, +6,11,0,5,15,5,51,104,108,100,106,100,94,94,94,88,70,70,62,42, +34,3,68,56,22,72,52,52,42,34,26,28,12,9,1,11,41,37,71,7, +58,38,26,8,10,1,11,17,33,4,84,56,44,34,36,10,5,11,21,27, +52,30,18,6,10,5,15,27,51,39,6,3,3,11,13,33,39,61,9,72, +40,26,10,16,7,15,21,33,124,43,25,11,5,11,2,12,14,11,10,20, +16,27,15,15,16,20,20,14,34,40,36,8,20,32,28,19,5,21,51,39, +27,31,23,25,21,17,13,19,17,9,11,21,35,53,29,67,25,9,13,4, +11,3,14,3,5,5,8,9,11,41,80,74,78,70,58,74,66,60,52,50, +52,42,6,6,7,36,36,24,0,16,12,5,9,15,21,27,53,31,61,112, +110,102,100,86,82,76,62,62,54,48,32,22,2,19,64,66,14,68,74,52, +40,44,36,28,34,22,12,1,5,19,49,12,7,31,71,49,57,15,21,17, +46,0,0,9,20,72,46,84,6,98,92,62,38,16,8,45,59,81,15,84, +56,38,18,22,4,3,9,35,51,35,17,23,5,4,9,11,4,10,12,6, +20,22,4,98,92,76,62,52,40,4,13,39,0,0,0,0,110,14,27,110, +14,27,59,25,36,22,8,26,68,94,48,10,5,34,33,19,2,1,22,19, +0,60,58,1,43,95,51,53,15,33,19,2,43,15,54,8,23,43,55,31, +35,49,79,1,31,53,9,37,45,71,10,21,17,37,44,4,44,0,0,0, +17,53,67,0,14,3,42,27,79,41,13,29,18,14,21,13,53,8,35,21, +39,59,35,45,39,32,3,5,39,19,53,27,55,3,25,17,47,30,15,4, +37,35,19,25,9,2,2,13,10,12,15,4,5,9,6,17,48,7,2,42, +42,58,52,36,43,7,11,2,7,41,9,18,11,13,10,48,96,58,8,43, +39,1,68,78,85,9,6,45,18,3,1,12,66,110,88,28,43,65,12,58, +76,73,40,42,42,42,46,38,26,40,42,10,24,24,10,6,7,20,12,10, +14,6,14,22,8,33,8,8,11,14,17,80,98,66,50,62,74,92,82,48, +4,15,4,16,16,71,12,20,25,50,20,20,22,26,16,30,30,13,59,17, +21,9,69,45,16,24,20,8,9,19,29,29,57,23,46,22,12,3,6,11, +25,33,39,13,50,24,14,4,10,7,17,27,45,21,42,14,16,8,2,17, +25,39,3,66,34,26,14,18,1,13,17,23,124,73,67,53,61,55,51,49, +45,41,41,39,33,37,41,47,53,7,45,27,33,29,25,21,15,15,9,17, +11,21,9,9,16,11,27,5,9,17,0,1,7,13,4,3,17,19,1,41, +11,16,9,4,11,7,5,8,2,9,9,21,21,15,112,106,110,104,100,110, +110,106,98,98,106,100,82,62,28,92,86,80,68,60,48,30,44,32,22,4, +5,15,31,74,68,74,48,16,28,20,2,22,8,1,33,13,31,45,22,30, +5,24,30,10,3,7,9,31,11,25,35,81,27,37,53,12,17,35,21,1, +4,6,20,14,28,1,18,16,30,40,42,44,18,110,76,62,50,34,30,5, +21,47,6,70,58,56,38,38,20,14,6,7,21,1,4,6,20,14,28,1, +18,16,30,40,42,44,18,110,76,62,50,34,30,5,21,47,0,0,0,0, +106,14,27,106,14,27,57,23,36,22,8,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, +44,0,0,0,15,55,67,0,12,3,104,14,11,83,43,37,3,33,59,49, +67,17,59,47,51,75,73,77,75,30,3,3,47,5,39,27,51,17,51,37, +77,24,23,7,67,41,19,19,1,10,0,11,20,14,15,2,0,3,4,23, +24,6,32,38,24,34,34,26,16,22,10,18,20,31,55,35,41,21,31,23, +1,19,21,13,13,15,17,7,35,57,35,63,13,21,4,7,1,22,2,3, +0,20,9,21,2,47,66,72,56,58,72,56,28,60,54,10,30,26,8,2, +11,20,10,12,16,6,3,14,4,15,1,7,17,7,51,100,106,96,102,96, +90,88,90,82,66,66,56,36,30,9,64,54,18,66,48,48,38,28,22,22, +8,13,3,13,45,39,71,7,58,40,26,8,10,1,11,17,31,6,86,56, +44,34,38,10,3,11,19,27,54,32,18,6,10,5,15,25,49,39,8,3, +3,11,11,31,39,59,9,74,40,26,10,18,5,15,19,31,124,43,25,11, +5,11,2,12,14,9,10,20,18,27,15,15,14,20,18,12,32,38,36,4, +18,30,28,21,7,23,51,39,25,31,23,25,19,15,15,19,17,9,13,21, +35,53,27,67,25,7,13,4,11,3,16,3,7,5,10,9,13,43,78,74, +78,68,56,72,64,58,50,48,50,40,4,4,9,32,32,20,3,14,10,7, +11,15,21,27,53,33,61,106,104,98,94,80,78,72,56,58,50,44,28,18, +0,21,60,62,12,64,70,48,36,38,32,24,30,18,8,5,9,23,51,8, +11,35,69,47,55,15,19,15,50,2,2,9,22,74,48,86,6,96,88,56, +32,10,2,51,63,83,15,84,56,38,18,22,4,3,9,33,49,33,15,23, +3,6,7,9,6,12,14,8,22,24,4,94,88,72,58,48,36,0,17,41, +0,0,0,0,106,14,27,106,14,27,57,23,36,22,8,22,64,92,50,10, +3,30,33,17,0,1,24,21,3,56,54,7,49,97,47,51,15,33,17,0, +43,13,54,6,23,41,51,33,39,51,79,1,29,51,11,37,45,71,10,21, +17,37,44,4,44,0,0,0,15,55,67,0,12,3,42,25,77,37,11,27, +22,18,21,11,49,10,33,19,33,59,37,45,41,32,5,3,33,17,53,27, +51,3,25,17,47,30,15,4,35,35,19,23,9,2,2,11,12,12,17,2, +5,9,6,17,48,7,2,42,42,58,52,36,45,5,11,0,7,39,9,20, +9,13,14,52,98,62,12,45,41,1,70,78,87,9,6,47,20,3,1,14, +66,110,88,32,45,63,10,52,70,71,38,42,42,42,44,38,26,40,40,8, +22,22,10,6,7,18,12,8,14,4,12,20,6,35,6,6,11,10,19,76, +94,62,46,60,70,84,78,46,0,21,0,12,12,73,8,18,27,48,18,18, +18,22,12,26,28,17,59,19,23,13,67,43,18,26,20,8,7,17,27,29, +53,19,48,22,12,1,10,9,23,31,33,11,50,24,14,4,12,5,15,27, +43,21,44,16,16,8,4,15,25,37,1,66,36,26,14,20,0,11,15,21, +124,71,63,49,59,53,49,45,41,39,39,35,27,35,39,45,51,1,43,29, +31,27,25,21,15,15,11,17,13,23,9,9,18,11,27,5,9,15,0,3, +7,15,2,5,17,19,0,43,13,16,9,2,11,7,5,6,2,9,9,21, +21,19,110,104,108,102,94,104,104,100,94,92,98,94,74,58,24,84,78,72, +58,54,44,26,40,28,18,0,7,17,31,68,62,68,44,12,24,16,1,18, +4,5,37,19,33,49,20,28,11,20,28,6,7,9,11,33,13,27,35,79, +31,39,57,8,19,37,21,1,6,8,22,14,28,0,20,18,32,40,44,46, +18,108,72,58,46,30,26,11,25,51,8,70,58,56,40,38,20,16,6,5, +21,1,6,8,22,14,28,0,20,18,32,40,44,46,18,108,72,58,46,30, +26,11,25,51,0,0,0,0,104,14,27,104,14,27,53,19,36,22,6,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,44,0,0,0,15,55,67,2,10,3,104,14, +11,81,41,37,1,31,55,45,63,15,55,45,47,73,71,75,73,32,3,1, +45,5,37,25,47,17,51,35,73,26,23,5,65,39,17,19,1,12,2,9, +22,16,15,2,0,3,4,23,24,4,30,38,22,34,34,26,12,22,8,16, +18,33,53,33,39,19,29,21,0,17,19,11,11,15,17,7,37,55,33,63, +11,21,6,7,3,24,2,3,1,22,9,23,2,47,64,70,56,56,70,54, +26,60,54,8,28,26,8,2,13,20,8,10,14,4,5,14,2,19,3,9, +19,9,51,96,104,92,98,94,86,84,86,78,62,62,52,32,26,13,60,50, +14,62,44,44,34,24,18,16,4,19,5,17,47,39,71,7,58,40,26,8, +10,1,11,17,31,6,86,56,44,34,40,12,1,11,17,25,56,34,18,8, +12,3,13,25,47,37,12,1,3,9,9,29,37,57,7,74,42,26,10,20, +3,13,17,29,124,43,25,9,5,11,2,12,14,9,10,22,18,27,15,15, +12,22,16,10,30,38,36,2,16,30,28,23,9,23,49,37,23,29,21,23, +19,13,15,19,17,9,15,21,35,51,25,67,25,7,13,6,11,3,18,3, +7,5,12,11,13,43,76,74,76,68,54,70,62,56,50,46,48,38,2,2, +11,30,30,18,7,12,8,9,13,17,21,25,53,33,59,102,100,94,90,76, +74,68,52,54,46,40,24,14,3,23,56,58,10,60,66,44,32,34,28,20, +26,14,2,9,13,27,53,4,15,37,67,43,53,13,17,13,54,4,4,9, +24,78,52,90,8,92,84,52,26,6,3,55,67,85,15,84,56,38,18,22, +4,3,9,33,47,31,13,21,1,8,7,7,8,14,16,8,22,24,4,92, +86,70,56,44,32,3,21,43,0,0,0,0,104,14,27,104,14,27,53,19, +36,22,6,18,62,90,52,10,0,26,31,13,0,1,26,23,5,54,50,13, +53,97,43,49,15,31,13,0,43,11,54,6,21,39,49,35,41,51,79,1, +29,49,11,37,45,71,10,19,17,35,46,4,44,0,0,0,15,55,67,2, +10,3,40,25,73,31,9,25,24,20,19,9,45,12,31,17,29,61,37,45, +41,32,5,1,29,17,51,25,47,3,25,17,45,30,15,6,33,33,17,23, +9,4,4,9,12,12,17,2,3,9,6,17,50,7,2,44,44,58,52,36, +45,5,9,0,7,39,9,22,9,11,16,54,100,64,16,45,43,0,70,78, +89,9,8,47,22,3,1,18,66,110,88,34,47,59,8,48,64,69,38,42, +40,40,44,38,24,40,40,6,20,22,10,6,7,18,10,6,12,4,12,18, +6,37,4,6,11,8,19,72,90,60,44,56,66,78,72,44,3,25,1,8, +8,75,6,16,31,46,16,16,16,20,8,22,24,19,59,21,25,17,63,39, +20,26,20,8,5,15,25,27,49,17,50,24,14,0,12,7,19,29,29,9, +52,26,16,6,14,3,15,25,41,19,46,18,16,8,6,15,23,35,0,66, +38,26,14,22,2,9,15,19,124,69,61,47,55,51,45,43,37,35,35,31, +23,33,37,43,49,4,43,31,31,25,23,21,15,15,11,15,13,25,9,9, +20,11,27,5,9,15,1,3,7,17,0,5,17,19,2,43,13,18,11,2, +11,7,5,6,0,9,7,21,21,21,108,102,106,98,90,100,98,94,88,86, +92,88,68,52,20,76,72,64,48,48,40,24,36,22,14,1,9,19,31,64, +58,64,40,8,20,14,5,14,0,9,41,23,37,51,18,26,15,18,24,4, +11,11,13,35,15,29,35,77,33,41,59,6,21,39,21,0,6,10,24,16, +30,0,22,20,34,42,46,46,20,108,68,54,42,26,22,15,29,53,8,72, +60,58,42,40,22,16,6,3,21,0,6,10,24,16,30,0,22,20,34,42, +46,46,20,108,68,54,42,26,22,15,29,53,0,0,0,0,102,14,29,102, +14,29,49,17,38,22,6,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,44,0,0,0, +13,55,67,2,10,5,104,14,11,79,41,37,1,29,51,41,61,13,51,43, +43,71,69,73,71,34,3,0,45,3,37,25,43,17,49,35,71,26,23,5, +61,39,15,17,1,12,2,7,22,16,17,2,0,3,4,23,24,4,30,38, +20,34,34,26,8,22,8,12,16,35,53,31,39,19,27,21,2,17,19,11, +7,15,17,7,39,55,31,63,11,21,8,5,5,24,2,3,3,24,11,25, +2,49,60,68,54,56,68,54,26,58,52,6,26,26,8,2,13,18,6,8, +12,4,7,12,2,23,5,9,21,11,51,94,100,90,94,90,82,80,82,72, +56,58,46,26,20,19,56,46,12,58,38,38,28,20,12,12,1,23,7,21, +49,41,71,5,60,40,28,8,10,1,11,17,29,6,86,58,44,34,42,12, +1,9,17,23,58,34,20,8,14,3,13,23,45,35,14,0,1,9,9,29, +35,53,7,74,42,26,12,20,3,11,17,27,124,41,23,9,5,11,2,12, +14,9,12,22,20,27,15,17,12,22,14,8,28,36,36,0,14,30,28,23, +11,25,47,35,21,29,21,23,17,13,15,17,15,7,15,21,35,51,23,67, +25,7,13,8,11,3,20,5,7,5,12,13,13,45,74,72,76,66,52,70, +62,54,48,46,46,36,0,0,13,26,28,14,11,8,4,11,13,17,21,25, +51,35,57,98,96,90,86,70,70,64,46,50,40,36,18,10,5,23,54,56, +6,56,60,40,28,30,24,16,20,10,1,13,17,29,57,0,19,41,65,41, +51,11,15,11,56,6,6,9,26,80,54,92,10,90,82,46,20,0,7,61, +71,89,13,84,56,38,18,22,4,3,9,31,45,31,11,19,0,8,5,5, +8,14,16,8,24,24,4,90,82,66,52,42,30,9,23,45,0,0,0,0, +102,14,29,102,14,29,49,17,38,22,6,16,58,88,52,12,4,24,31,11, +0,3,28,25,7,52,48,21,57,99,39,45,15,31,11,0,41,9,56,6, +19,37,47,39,43,51,81,1,29,49,11,39,43,71,8,19,17,33,46,4, +44,0,0,0,13,55,67,2,10,5,40,23,71,27,7,23,28,24,17,7, +41,14,29,17,25,63,37,45,41,34,5,0,25,17,49,23,43,3,25,17, +45,32,17,6,33,33,15,23,7,4,4,7,14,12,17,2,3,9,6,17, +50,7,2,44,44,60,54,38,47,3,7,1,7,39,9,24,9,11,18,56, +100,68,18,47,45,0,70,78,89,11,8,49,22,5,0,20,66,110,90,36, +49,57,6,42,58,65,38,42,40,38,42,36,24,38,38,6,20,22,8,6, +9,16,8,4,12,4,12,18,4,41,4,4,11,6,21,66,86,56,40,52, +62,72,68,40,7,29,5,4,4,79,4,12,35,42,14,14,14,16,4,18, +20,23,59,23,27,19,61,37,24,28,20,8,3,15,25,25,47,15,52,26, +16,0,14,5,17,27,25,9,52,26,16,6,16,3,13,23,39,19,50,20, +16,8,6,13,23,35,0,68,38,28,14,24,2,9,13,19,124,65,57,43, +51,47,43,39,35,33,31,27,19,33,35,43,49,10,43,33,31,25,21,21, +15,15,11,15,13,27,9,9,20,11,27,5,9,15,1,3,7,19,1,5, +17,19,4,45,13,20,13,2,11,7,3,6,0,7,5,21,21,25,106,100, +104,94,86,94,94,88,84,80,86,82,62,46,16,70,64,56,38,44,34,20, +32,18,10,3,11,21,31,60,54,60,36,4,18,10,9,10,5,13,45,27, +41,53,16,22,19,14,20,0,15,15,17,37,17,31,37,75,35,45,63,4, +25,41,19,0,8,10,26,18,32,0,24,22,36,42,48,48,22,106,64,50, +38,22,18,19,33,55,10,72,60,60,42,42,22,18,8,3,19,0,8,10, +26,18,32,0,24,22,36,42,48,48,22,106,64,50,38,22,18,19,33,55, +0,0,0,0,100,14,29,100,14,29,45,13,38,22,4,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,44,0,0,0,13,55,67,4,8,5,104,14,11,77,39,37, +0,25,49,37,57,11,49,39,39,69,67,71,71,36,3,2,43,3,35,23, +39,17,49,33,69,26,21,3,59,37,15,17,0,12,2,5,24,18,17,0, +0,3,4,23,24,2,28,38,20,34,34,24,4,22,6,8,14,37,51,29, +37,17,25,19,4,15,17,9,5,15,17,5,41,53,29,63,11,21,8,5, +7,26,2,3,7,26,11,27,2,51,58,66,54,54,66,52,24,56,52,4, +24,26,8,2,15,16,6,6,12,2,9,10,0,27,7,11,23,13,51,90, +98,86,90,86,78,74,78,68,52,54,42,22,16,23,52,44,8,52,34,34, +24,14,8,6,5,29,9,23,53,43,71,5,60,42,28,8,10,1,11,17, +29,8,88,58,44,34,44,14,0,9,15,21,60,36,20,8,16,1,11,23, +43,35,16,0,1,9,7,27,35,51,5,76,42,26,12,22,1,9,15,25, +124,41,23,7,5,11,2,12,14,7,12,22,20,27,15,17,10,24,12,6, +26,34,36,1,12,28,28,25,13,25,45,35,19,27,19,21,17,11,15,17, +15,7,17,21,35,49,21,67,25,5,13,8,11,3,22,5,7,5,14,13, +15,47,72,72,74,64,50,68,60,52,46,44,44,34,1,1,15,24,24,12, +15,6,2,13,15,19,21,25,51,35,55,94,92,86,80,64,66,60,42,46, +36,32,14,6,9,25,50,52,4,52,56,36,24,26,20,12,16,6,7,17, +21,33,59,3,23,43,63,39,49,11,13,9,60,8,8,9,28,84,58,96, +10,86,78,42,14,5,13,67,75,91,13,84,56,38,18,22,4,3,9,31, +43,29,9,17,2,10,5,3,10,16,18,10,24,26,4,86,80,62,48,38, +26,13,27,47,0,0,0,0,100,14,29,100,14,29,45,13,38,22,4,12, +56,86,54,12,6,20,31,7,1,3,30,27,9,50,44,27,63,101,35,43, +15,31,7,1,41,7,56,6,19,35,43,41,45,51,81,1,27,47,13,39, +43,71,8,19,17,31,48,4,44,0,0,0,13,55,67,4,8,5,38,23, +69,23,5,21,30,26,15,5,37,16,27,15,19,63,39,45,43,34,5,2, +19,15,49,23,39,3,25,17,45,32,17,8,31,33,13,21,7,4,6,5, +14,12,19,2,3,9,6,17,50,7,2,46,44,60,54,38,47,3,7,1, +7,37,9,26,7,9,22,60,102,70,22,47,47,2,72,78,91,11,10,49, +24,5,0,22,66,110,90,40,51,53,4,36,52,63,38,42,38,38,42,36, +22,38,38,4,18,22,8,6,9,16,8,2,10,4,12,16,4,43,2,2, +11,4,21,62,82,52,38,50,58,66,62,38,11,33,7,0,0,81,2,10, +37,40,12,12,10,14,0,14,18,25,59,25,29,23,57,33,26,28,20,8, +1,13,23,25,43,11,54,28,16,2,18,3,13,25,19,7,54,28,18,8, +18,1,13,21,37,19,52,22,16,8,8,13,23,33,2,68,40,28,14,26, +4,7,13,17,124,63,55,41,49,45,39,37,31,29,27,23,13,31,33,41, +47,16,41,35,29,23,19,21,15,15,11,13,15,29,9,9,22,11,27,5, +9,13,3,5,7,21,3,7,17,19,6,47,15,22,13,0,11,7,3,4, +1,7,5,21,21,27,104,98,102,92,80,90,88,82,78,74,80,76,56,42, +12,62,58,48,28,38,30,16,28,12,6,5,13,23,31,56,48,54,32,0, +14,8,13,6,9,17,49,31,43,57,14,20,23,12,18,1,19,17,19,39, +19,33,37,73,39,47,65,0,27,43,19,2,8,12,28,20,32,2,26,24, +38,44,50,48,22,106,60,46,34,18,14,25,37,57,10,74,62,60,44,44, +24,18,8,1,19,2,8,12,28,20,32,2,26,24,38,44,50,48,22,106, +60,46,34,18,14,25,37,57,0,0,0,0,96,12,29,96,12,29,43,11, +38,22,4,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,44,0,0,0,11,57,67,4, +6,5,104,14,11,75,37,37,0,23,45,33,55,9,45,37,37,67,67,69, +69,36,3,4,41,3,35,23,37,17,49,33,67,26,21,3,57,37,13,17, +0,12,2,5,24,18,19,0,0,3,4,23,24,2,26,38,18,34,34,24, +0,22,6,4,12,39,49,27,35,15,25,19,6,15,17,7,3,15,17,5, +45,53,27,63,11,23,10,5,9,28,2,3,9,28,13,29,2,53,54,64, +52,52,64,50,22,54,50,0,22,24,8,2,15,14,4,4,10,0,11,8, +1,31,11,13,25,15,51,86,94,82,86,82,74,70,74,62,46,50,36,16, +10,29,48,40,4,48,30,28,18,10,2,0,9,33,11,27,55,45,73,5, +60,42,28,8,10,1,11,17,27,8,88,58,44,34,46,14,0,9,15,21, +62,36,20,8,16,1,11,21,41,33,18,2,1,9,5,25,33,49,5,76, +42,26,12,24,1,9,13,25,124,41,23,7,5,11,2,12,14,7,12,22, +22,27,15,17,8,24,10,4,24,32,36,5,8,28,28,27,15,27,45,33, +17,27,19,21,15,9,17,17,15,7,19,21,35,49,21,69,25,5,13,10, +11,3,22,5,9,5,16,15,15,49,70,70,74,62,46,66,58,50,44,42, +42,32,3,3,17,20,22,8,19,2,0,15,17,19,21,25,51,37,55,88, +86,82,76,58,60,54,36,42,32,28,8,2,11,27,46,48,0,48,52,30, +18,20,14,8,12,0,11,21,27,37,61,7,27,47,61,37,47,9,11,9, +62,10,8,9,28,86,60,98,12,84,74,36,8,11,19,73,79,93,13,84, +56,38,18,22,4,3,9,29,43,27,7,17,4,10,3,3,10,16,18,10, +26,26,2,84,76,58,44,34,22,17,31,49,0,0,0,0,96,12,29,96, +12,29,43,11,38,22,4,8,52,84,54,12,10,16,31,5,1,5,32,29, +13,46,40,35,67,103,31,41,15,31,5,1,41,7,56,4,17,33,41,43, +49,53,83,1,27,45,13,41,43,71,8,19,17,31,48,4,44,0,0,0, +11,57,67,4,6,5,38,21,67,19,3,21,34,30,15,3,33,16,25,13, +15,65,39,47,43,34,7,2,15,15,47,21,37,3,25,17,45,32,17,8, +29,33,13,21,7,4,6,3,16,12,19,0,3,9,4,17,50,7,2,46, +44,60,54,38,49,1,5,3,7,37,9,28,7,9,24,62,104,74,26,49, +49,2,72,78,93,11,10,51,24,5,0,24,66,110,90,42,53,51,2,30, +44,61,36,42,38,36,40,34,22,38,36,2,16,20,8,4,11,14,6,0, +10,2,10,14,2,45,0,0,11,0,23,58,78,48,34,46,52,58,58,36, +15,39,11,5,3,85,1,8,41,38,10,10,8,10,3,10,14,29,59,27, +31,27,55,31,28,30,20,8,1,11,21,23,39,9,54,28,18,2,20,1, +11,23,15,7,54,28,18,8,18,1,11,21,35,19,54,24,16,8,10,11, +23,31,4,68,42,28,14,28,4,5,11,17,124,61,51,37,45,43,37,33, +29,27,25,19,9,31,31,41,45,22,41,37,29,21,19,21,15,15,13,13, +15,31,9,9,22,11,27,7,9,13,3,5,9,23,5,7,19,19,8,49, +15,22,15,0,11,9,3,4,1,7,3,21,21,31,102,96,100,88,76,84, +82,76,74,68,72,70,48,36,8,54,50,40,18,32,26,12,22,8,2,9, +17,25,31,50,44,50,28,5,10,4,19,2,13,21,53,37,47,59,10,18, +29,8,14,5,23,21,23,41,21,35,37,71,41,51,69,1,29,45,19,2, +10,12,30,20,34,2,28,24,40,44,50,50,24,104,56,42,30,14,10,29, +41,61,12,74,62,62,44,44,24,20,8,1,19,2,10,12,30,20,34,2, +28,24,40,44,50,50,24,104,56,42,30,14,10,29,41,61,0,0,0,0, +94,12,29,94,12,29,39,9,40,22,4,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, +44,0,0,0,9,57,67,4,4,5,104,14,11,73,35,37,0,21,41,29, +51,5,41,35,33,65,65,67,67,38,1,6,39,3,33,21,33,17,47,33, +63,28,21,3,53,37,11,17,0,14,4,3,24,18,19,0,2,3,4,21, +24,2,26,38,16,34,34,24,3,22,6,2,10,39,47,25,33,13,23,17, +8,13,17,5,1,15,17,5,47,51,25,63,9,23,12,5,11,30,2,3, +11,30,15,31,2,53,52,62,52,50,62,48,22,54,50,1,20,24,8,2, +15,14,2,2,8,1,13,8,1,33,13,13,27,17,51,84,92,80,84,80, +70,66,70,58,42,46,32,10,6,35,46,36,2,44,26,24,14,6,1,3, +13,37,11,31,57,45,73,5,62,42,28,10,10,1,9,17,25,8,88,58, +46,34,48,16,2,7,13,19,64,38,22,10,18,0,11,19,39,31,22,4, +0,7,3,23,31,47,3,76,44,28,12,26,0,7,11,23,124,39,21,5, +5,11,2,14,16,7,12,24,24,27,15,17,8,24,8,4,22,32,36,7, +6,28,28,27,17,29,43,31,15,27,17,21,13,7,17,17,15,5,19,21, +35,49,19,69,25,5,13,12,11,3,24,5,9,5,18,17,15,49,68,70, +74,62,44,64,56,48,44,40,40,32,3,5,19,18,20,4,23,0,1,15, +17,19,19,23,51,39,53,84,82,78,72,54,56,50,32,38,28,24,4,1, +13,29,42,46,1,44,48,26,14,16,10,4,8,3,15,23,31,41,63,11, +31,51,59,33,43,7,9,7,66,12,10,9,30,90,62,102,14,82,72,32, +2,15,25,77,83,95,13,84,56,38,18,24,4,3,9,27,41,25,5,15, +8,12,1,1,12,18,20,10,28,26,2,82,74,56,42,30,18,21,35,49, +0,0,0,0,94,12,29,94,12,29,39,9,40,22,4,4,48,84,56,12, +14,14,29,1,1,5,34,29,15,44,36,41,71,103,27,37,13,29,1,1, +39,5,58,4,15,31,39,45,51,53,83,1,27,43,13,41,43,71,8,17, +15,29,48,4,44,0,0,0,9,57,67,4,4,5,38,19,63,13,1,19, +38,34,13,1,29,18,21,11,11,67,39,47,43,36,7,4,11,15,45,19, +33,3,23,17,43,34,17,10,27,31,11,21,7,6,8,1,18,12,19,0, +1,7,4,17,52,7,2,46,46,62,54,40,49,0,3,5,7,37,9,30, +7,7,26,64,106,78,30,51,51,4,72,80,95,11,10,51,26,5,0,28, +66,110,90,44,55,49,0,26,38,57,36,42,38,34,40,34,22,38,36,0, +14,20,8,4,11,14,4,0,10,2,10,12,0,47,0,0,11,1,23,54, +74,46,32,42,48,52,54,34,19,43,13,9,5,87,3,6,45,36,8,8, +6,6,5,6,10,31,59,27,33,29,51,27,32,32,20,8,0,9,19,21, +35,7,56,30,20,4,22,0,9,21,11,5,56,30,20,8,20,0,9,19, +31,17,58,26,18,8,12,9,21,29,6,70,44,30,16,30,6,3,9,15, +124,57,47,33,41,41,35,29,25,23,21,15,5,29,29,39,43,30,41,39, +29,19,17,19,15,15,13,13,15,33,9,9,24,11,27,7,9,13,3,5, +9,23,7,7,19,17,12,49,15,24,17,0,11,9,1,4,1,5,1,19, +19,35,100,94,98,84,72,78,78,70,70,64,66,66,42,30,4,46,44,34, +8,26,22,10,18,4,0,11,19,27,31,46,40,46,24,9,6,2,23,1, +17,25,57,41,51,61,8,16,33,6,10,7,27,23,25,43,23,35,37,69, +43,53,73,3,31,47,19,4,12,14,34,22,36,2,30,26,42,46,52,52, +26,102,54,38,26,10,6,33,45,63,14,74,64,64,46,46,26,22,10,0, +19,4,12,14,34,22,36,2,30,26,42,46,52,52,26,102,54,38,26,10, +6,33,45,63,0,0,0,0,92,12,29,92,12,29,35,5,40,22,2,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,44,0,0,0,9,57,67,6,2,5,104,14, +11,71,33,37,2,17,39,25,49,3,39,31,29,63,63,65,67,40,1,8, +37,3,33,19,29,17,47,31,61,28,19,1,51,35,11,17,2,14,4,1, +26,20,21,1,2,3,4,21,24,0,24,38,16,34,34,22,7,22,4,1, +8,41,45,23,31,11,21,15,10,11,15,3,0,15,17,3,49,51,23,63, +9,23,12,5,13,32,2,3,15,32,15,33,2,55,48,60,50,48,60,46, +20,52,50,3,18,24,8,2,17,12,2,0,8,3,15,6,3,37,15,15, +29,19,51,80,90,76,80,76,66,60,66,52,38,42,26,6,2,39,42,34, +1,38,22,20,10,0,5,9,17,43,13,33,61,47,73,5,62,44,28,10, +10,1,9,17,25,10,90,58,46,34,50,16,4,7,11,17,66,40,22,10, +20,0,9,19,37,31,24,4,0,7,1,21,31,45,3,78,44,28,12,28, +2,5,9,21,124,39,21,5,5,11,2,14,16,5,12,24,24,27,15,17, +6,26,6,2,20,30,36,9,4,26,28,29,19,29,41,31,13,25,17,19, +13,5,17,17,15,5,21,21,35,47,17,69,25,3,13,12,11,3,26,5, +9,5,20,17,17,51,66,70,72,60,42,62,54,46,42,38,38,30,5,7, +21,14,16,2,27,1,3,17,19,21,19,23,51,39,51,80,78,74,66,48, +52,46,26,34,24,20,0,5,17,31,38,42,3,40,44,22,10,12,6,0, +4,7,21,27,35,45,65,15,35,53,57,31,41,7,7,5,70,14,12,9, +32,92,66,104,14,78,68,26,3,21,31,83,87,97,13,84,56,38,18,24, +4,3,9,27,39,23,3,13,10,14,1,0,14,20,22,12,28,28,2,78, +70,52,38,26,14,25,39,51,0,0,0,0,92,12,29,92,12,29,35,5, +40,22,2,0,46,82,58,12,16,10,29,0,3,5,36,31,17,42,32,47, +77,105,23,35,13,29,0,3,39,3,58,4,15,29,35,47,53,53,83,1, +25,41,15,41,43,71,8,17,15,27,50,4,44,0,0,0,9,57,67,6, +2,5,36,19,61,9,0,17,40,36,11,0,25,20,19,9,5,67,41,47, +45,36,7,6,5,13,45,19,29,3,23,17,43,34,17,10,25,31,9,19, +7,6,8,0,18,12,21,0,1,7,4,17,52,7,2,48,46,62,54,40, +51,0,3,5,7,35,9,32,5,7,30,68,108,80,34,51,53,4,74,80, +97,11,12,53,28,5,0,30,66,110,90,48,57,45,1,20,32,55,36,42, +36,34,38,34,20,38,34,1,12,20,8,4,11,12,4,1,8,2,10,10, +0,49,1,1,11,3,25,50,70,42,28,40,44,46,48,32,23,47,17,13, +9,89,5,4,47,34,6,6,2,4,9,2,8,35,59,29,35,33,49,25, +34,32,20,8,2,7,17,21,31,3,58,32,20,6,26,2,5,19,5,3, +56,30,20,10,22,2,9,17,29,17,60,28,18,8,14,9,21,27,8,70, +46,30,16,32,8,1,9,13,124,55,45,31,39,39,31,27,21,21,17,11, +0,27,27,37,41,36,39,41,27,17,15,19,15,15,13,11,17,35,9,9, +26,11,27,7,9,11,5,7,9,25,9,9,19,17,14,51,17,26,17,1, +11,9,1,2,3,5,1,19,19,37,98,92,96,82,66,74,72,64,64,58, +60,60,36,26,0,38,36,26,1,20,18,6,14,1,3,13,21,29,31,42, +34,40,20,13,2,1,27,5,21,29,61,45,53,65,6,14,37,2,8,11, +31,25,27,45,25,37,37,67,47,55,75,7,33,49,19,4,12,16,36,24, +36,4,32,28,44,46,54,52,26,102,50,34,22,6,2,39,49,65,14,76, +64,64,48,48,26,22,10,2,19,4,12,16,36,24,36,4,32,28,44,46, +54,52,26,102,50,34,22,6,2,39,49,65,0,0,0,0,90,12,31,90, +12,31,31,3,42,22,2,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,44,0,0,0, +7,57,67,6,2,7,104,14,11,69,33,37,2,15,35,21,45,1,35,29, +25,61,61,63,65,42,1,10,37,1,31,19,25,17,45,31,59,28,19,1, +47,35,9,15,2,14,4,0,26,20,21,1,2,3,4,21,24,0,24,38, +14,34,34,22,11,22,4,5,6,43,45,21,31,11,19,15,12,11,15,3, +4,15,17,3,51,49,21,63,9,23,14,3,15,32,2,3,17,34,17,35, +2,57,46,58,50,48,58,46,20,50,48,5,16,24,8,2,17,10,0,1, +6,3,17,4,3,41,17,15,31,21,51,78,86,74,76,72,62,56,62,48, +32,38,22,0,3,45,38,30,3,34,16,14,4,3,11,13,23,47,15,37, +63,49,73,3,64,44,30,10,10,1,9,17,23,10,90,60,46,34,52,18, +4,5,11,15,68,40,24,10,22,2,9,17,35,29,26,6,2,7,1,21, +29,41,1,78,44,28,14,28,2,3,9,19,124,37,19,3,5,11,2,14, +16,5,14,24,26,27,15,19,6,26,4,0,18,28,36,11,2,26,28,29, +21,31,39,29,11,25,15,19,11,5,17,15,13,3,21,21,35,47,15,69, +25,3,13,14,11,3,28,7,9,5,20,19,17,53,64,68,72,58,40,62, +54,44,40,38,36,28,7,9,23,12,14,1,31,5,7,19,19,21,19,23, +49,41,49,76,74,70,62,42,48,42,22,30,18,16,5,9,19,31,36,40, +7,36,38,18,6,8,2,3,1,11,25,31,39,47,69,19,39,57,55,29, +39,5,5,3,72,16,14,9,34,96,68,108,16,76,66,22,9,27,35,89, +91,101,11,84,56,38,18,24,4,3,9,25,37,23,1,11,12,14,0,2, +14,20,22,12,30,28,2,76,68,48,34,24,12,31,41,53,0,0,0,0, +90,12,31,90,12,31,31,3,42,22,2,1,42,80,58,14,20,8,29,4, +3,7,38,33,19,40,30,55,81,107,19,31,13,29,4,3,37,1,60,4, +13,27,33,51,55,53,85,1,25,41,15,43,41,71,6,17,15,25,50,4, +44,0,0,0,7,57,67,6,2,7,36,17,59,5,2,15,44,40,9,2, +21,22,17,9,1,69,41,47,45,38,7,8,1,13,43,17,25,3,23,17, +43,36,19,12,25,31,7,19,5,6,10,2,20,12,21,0,1,7,4,17, +52,7,2,48,46,64,56,42,51,2,1,7,7,35,9,34,5,5,32,70, +108,84,36,53,55,6,74,80,97,13,12,53,28,7,2,32,66,110,92,50, +59,43,3,14,26,51,36,42,36,32,38,32,20,36,34,1,12,20,6,4, +13,12,2,3,8,2,10,10,1,53,1,3,11,5,25,44,66,38,26,36, +40,40,44,28,27,51,19,17,13,93,7,0,51,30,4,4,0,0,13,1, +4,37,59,31,37,35,45,21,38,34,20,8,4,7,17,19,29,1,60,34, +22,6,28,4,3,17,1,3,58,32,22,10,24,2,7,15,27,17,64,30, +18,8,14,7,21,27,8,72,46,32,16,34,8,1,7,13,124,51,41,27, +35,35,29,23,19,17,13,7,4,27,25,37,41,42,39,43,27,17,13,19, +15,15,13,11,17,37,9,9,26,11,27,7,9,11,5,7,9,27,11,9, +19,17,16,53,17,28,19,1,11,9,0,2,3,3,0,19,19,41,96,90, +94,78,62,68,68,58,60,52,54,54,30,20,3,32,30,18,11,16,12,2, +10,5,7,15,23,31,31,38,30,36,16,17,0,3,31,9,27,33,65,49, +57,67,4,10,41,0,4,13,35,29,31,47,27,39,39,65,49,59,79,9, +37,51,17,6,14,16,38,26,38,4,34,30,46,48,56,54,28,100,46,30, +18,2,1,43,53,67,16,76,66,66,48,50,28,24,12,2,17,6,14,16, +38,26,38,4,34,30,46,48,56,54,28,100,46,30,18,2,1,43,53,67, +0,0,0,0,86,12,31,86,12,31,29,0,42,22,0,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,44,0,0,0,7,59,67,8,0,7,104,14,11,67,31,37, +4,13,31,17,43,0,31,27,21,59,61,61,63,42,1,12,35,1,31,17, +21,17,45,29,57,28,19,0,45,33,7,15,2,14,4,0,28,22,23,1, +2,3,4,21,24,1,22,38,12,34,34,22,15,22,2,9,4,45,43,19, +29,9,19,13,14,9,13,1,6,15,17,3,53,49,19,63,9,23,16,3, +17,34,2,3,19,36,17,37,2,59,42,56,48,46,56,44,18,48,48,9, +14,22,8,2,19,8,1,3,4,5,19,2,5,45,19,17,33,23,51,74, +84,70,72,68,58,52,58,42,28,34,16,3,7,49,34,26,7,30,12,10, +0,7,15,19,27,53,17,41,65,51,73,3,64,44,30,10,10,1,9,17, +23,10,90,60,46,34,54,18,6,5,9,15,70,42,24,10,22,2,7,17, +33,27,28,8,2,7,0,19,27,39,1,78,44,28,14,30,4,3,7,17, +124,37,19,3,5,11,2,14,16,5,14,24,26,27,15,19,4,28,2,1, +16,26,36,15,0,26,28,31,23,31,39,27,9,23,15,17,11,3,19,15, +13,3,23,21,35,45,13,69,25,3,13,16,11,3,30,7,11,5,22,21, +17,55,62,68,70,56,38,60,52,42,38,36,34,26,9,11,25,8,12,3, +35,7,9,21,21,23,19,23,49,41,49,70,68,66,58,36,44,38,16,26, +14,12,9,13,23,33,32,36,9,32,34,14,2,2,1,7,5,15,31,35, +43,51,71,23,43,59,53,27,37,3,3,1,76,18,16,9,36,98,72,110, +18,72,62,16,15,33,41,95,95,103,11,84,56,38,18,24,4,3,9,25, +35,21,0,11,14,16,0,4,16,22,24,12,30,28,2,74,64,44,30,20, +8,35,45,55,0,0,0,0,86,12,31,86,12,31,29,0,42,22,0,5, +40,78,60,14,24,4,29,6,3,7,40,35,23,36,26,61,85,109,15,29, +13,29,6,3,37,0,60,2,11,25,31,53,59,55,85,1,25,39,15,43, +41,71,6,17,15,25,52,4,44,0,0,0,7,59,67,8,0,7,34,17, +57,1,4,13,46,42,9,4,17,24,15,7,2,71,41,47,45,38,9,10, +2,13,41,15,21,3,23,17,43,36,19,12,23,31,7,19,5,6,10,4, +20,12,21,1,1,7,4,17,52,7,2,50,46,64,56,42,53,2,0,7, +7,35,9,36,5,5,34,72,110,86,40,53,57,6,74,80,99,13,14,55, +30,7,2,34,66,110,92,52,61,39,5,8,20,49,34,42,34,30,36,32, +18,36,32,3,10,18,6,4,13,10,0,5,6,0,8,8,1,55,3,5, +11,9,27,40,62,34,22,32,36,32,38,26,31,57,23,21,17,95,11,1, +55,28,2,2,1,1,17,5,0,41,59,33,39,39,43,19,40,34,20,8, +6,5,15,17,25,0,62,34,24,8,30,6,0,15,2,1,58,32,22,12, +26,4,7,15,25,17,66,32,18,8,16,7,21,25,10,72,48,32,16,36, +10,0,7,11,124,49,39,25,31,33,25,21,15,15,11,3,8,25,23,35, +39,48,39,45,27,15,13,19,15,15,15,9,17,39,9,9,28,11,27,7, +9,11,7,7,9,29,13,9,19,17,18,55,17,28,21,1,11,9,0,2, +5,3,2,19,19,43,94,88,92,74,58,64,62,52,54,46,46,48,22,14, +7,24,22,10,21,10,8,1,6,11,11,19,25,33,31,32,26,32,12,21, +3,7,35,13,31,37,69,55,61,69,2,8,47,3,0,17,39,31,33,49, +29,41,39,63,51,61,81,11,39,53,17,6,14,18,40,26,40,4,36,32, +48,48,58,54,30,100,42,26,14,1,5,47,57,71,16,78,66,68,50,50, +28,24,12,4,17,6,14,18,40,26,40,4,36,32,48,48,58,54,30,100, +42,26,14,1,5,47,57,71,0,0,0,0,84,12,31,84,12,31,25,2, +42,22,0,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,44,0,0,0,5,59,67,8, +1,7,104,14,11,65,29,37,4,9,29,13,39,2,29,23,17,57,59,59, +63,44,1,14,33,1,29,15,17,17,45,29,53,30,17,0,43,33,7,15, +4,16,6,2,28,22,23,3,2,3,4,21,24,1,20,38,12,34,34,20, +19,22,2,11,2,47,41,17,27,7,17,11,16,7,13,0,8,15,17,1, +55,47,17,63,7,23,16,3,19,36,2,3,23,38,19,39,2,59,40,54, +48,44,54,42,16,48,48,11,12,22,8,2,19,8,1,5,4,7,21,2, +7,49,21,19,35,25,51,70,82,66,68,66,54,46,54,38,24,30,12,9, +11,55,30,24,11,24,8,6,3,13,19,25,31,57,19,43,69,51,73,3, +64,46,30,10,10,1,9,17,21,12,92,60,46,34,56,20,8,5,7,13, +72,44,24,12,24,4,7,15,31,27,32,8,2,5,2,17,27,37,0,80, +46,28,14,32,6,1,5,15,124,37,19,1,5,11,2,14,16,3,14,26, +28,27,15,19,2,28,0,3,14,26,36,17,1,24,28,33,25,33,37,27, +7,23,13,17,9,1,19,15,13,3,25,21,35,45,11,69,25,1,13,16, +11,3,32,7,11,5,24,21,19,55,60,68,70,56,36,58,50,40,38,34, +32,24,11,13,27,6,8,7,39,9,11,23,23,23,19,21,49,43,47,66, +64,62,52,32,40,34,12,22,10,8,13,17,25,35,28,32,11,28,30,10, +1,1,5,11,9,19,35,39,47,55,73,27,47,63,51,23,35,3,1,0, +80,20,18,9,38,102,74,114,18,70,58,12,21,37,47,99,99,105,11,84, +56,38,18,24,4,3,9,23,33,19,2,9,16,18,2,6,18,24,26,14, +32,30,2,70,62,42,28,16,4,39,49,57,0,0,0,0,84,12,31,84, +12,31,25,2,42,22,0,9,36,76,62,14,26,0,27,10,5,7,42,37, +25,34,22,67,91,109,11,27,13,27,10,5,37,2,60,2,11,23,27,55, +61,55,85,1,23,37,17,43,41,71,6,15,15,23,52,4,44,0,0,0, +5,59,67,8,1,7,34,15,53,4,6,11,50,46,7,6,13,26,13,5, +8,71,43,47,47,38,9,12,8,11,41,15,17,3,23,17,41,36,19,14, +21,29,5,17,5,8,12,6,22,12,23,1,0,7,4,17,54,7,2,50, +48,64,56,42,53,4,0,9,7,33,9,38,3,3,38,76,112,90,44,55, +59,8,76,80,101,13,14,55,32,7,2,38,66,110,92,56,63,37,7,4, +14,47,34,42,34,30,36,32,18,36,32,5,8,18,6,4,13,10,0,7, +6,0,8,6,3,57,5,5,11,11,27,36,58,32,20,30,32,26,34,24, +35,61,25,25,21,97,13,3,57,26,0,0,5,5,21,9,1,43,59,35, +41,43,39,15,42,36,20,8,8,3,13,17,21,4,64,36,24,10,34,8, +2,13,8,0,60,34,24,12,28,6,5,13,23,15,68,34,18,8,18,5, +19,23,12,72,50,32,16,38,12,2,5,9,124,47,35,21,29,31,23,17, +11,11,7,0,14,23,21,33,37,54,37,47,25,13,11,19,15,15,15,9, +19,41,9,9,30,11,27,7,9,9,7,9,9,31,15,11,19,17,20,55, +19,30,21,3,11,9,0,0,5,3,2,19,19,47,92,86,90,72,52,58, +56,46,50,40,40,42,16,10,11,16,16,2,31,4,4,3,2,15,15,21, +27,35,31,28,20,26,8,25,7,9,39,17,35,41,73,59,63,73,0,6, +51,5,1,19,43,33,35,51,31,43,39,61,55,63,85,15,41,55,17,8, +16,20,42,28,40,6,38,34,50,50,60,56,30,98,38,22,10,5,9,53, +61,73,18,78,68,68,52,52,30,26,12,6,17,8,16,20,42,28,40,6, +38,34,50,50,60,56,30,98,38,22,10,5,9,53,61,73,0,0,0,0, +82,12,31,82,12,31,21,6,44,22,1,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, +44,0,0,0,5,59,67,10,3,7,104,14,11,63,27,37,6,7,25,9, +37,4,25,21,13,55,57,57,61,46,1,16,31,1,29,15,13,17,43,27, +51,30,17,2,39,31,5,15,4,16,6,4,30,24,25,3,2,3,4,21, +24,3,20,38,10,34,34,20,23,22,0,15,0,49,39,15,25,5,15,11, +18,7,11,2,10,15,17,1,57,47,15,63,7,23,18,3,21,38,2,3, +25,40,19,41,2,61,36,52,46,42,52,40,16,46,46,13,10,22,8,2, +21,6,3,7,2,9,23,0,7,53,23,19,37,27,51,68,78,64,64,62, +50,42,50,32,18,26,6,13,17,59,26,20,13,20,4,0,9,17,25,29, +35,63,21,47,71,53,73,3,66,46,30,10,10,1,9,17,21,12,92,60, +46,34,58,20,8,3,7,11,74,44,26,12,26,4,5,15,29,25,34,10, +4,5,4,15,25,35,0,80,46,28,14,34,6,0,3,13,124,35,17,1, +5,11,2,14,16,3,14,26,28,27,15,19,2,30,1,5,12,24,36,19, +3,24,28,33,27,33,35,25,5,21,13,15,9,0,19,15,13,1,25,21, +35,43,9,69,25,1,13,18,11,3,34,7,11,5,26,23,19,57,58,66, +68,54,34,56,48,38,36,32,30,22,13,15,29,2,6,9,43,13,13,25, +23,25,19,21,49,43,45,62,60,58,48,26,36,30,6,18,6,4,19,21, +29,37,24,30,15,24,26,6,5,5,9,15,13,23,41,43,51,59,75,31, +51,65,49,21,33,1,0,2,82,22,20,9,40,104,78,116,20,66,56,6, +27,43,53,105,103,107,11,84,56,38,18,24,4,3,9,23,31,17,4,7, +18,18,2,8,18,24,26,14,32,30,2,68,58,38,24,12,0,43,53,59, +0,0,0,0,82,12,31,82,12,31,21,6,44,22,1,13,34,74,62,14, +30,1,27,12,5,9,44,39,27,32,18,75,95,111,7,23,13,27,12,5, +35,4,62,2,9,21,25,57,63,55,87,1,23,35,17,45,41,71,6,15, +15,21,54,4,44,0,0,0,5,59,67,10,3,7,32,15,51,8,8,9, +52,48,5,8,9,28,11,3,12,73,43,47,47,40,9,14,12,11,39,13, +13,3,23,17,41,38,19,14,19,29,3,17,5,8,12,8,22,12,23,1, +0,7,4,17,54,7,2,52,48,66,56,44,55,4,2,9,7,33,9,40, +3,3,40,78,114,92,48,55,61,8,76,80,103,13,16,57,32,7,2,40, +66,110,92,58,65,33,9,1,8,43,34,42,32,28,34,30,16,36,30,7, +6,18,6,4,15,8,1,9,4,0,8,4,3,59,5,7,11,13,29,32, +54,28,16,26,28,20,28,22,39,65,29,29,25,101,15,5,61,24,1,1, +7,7,25,13,5,47,59,37,43,45,37,13,46,36,20,8,10,1,11,15, +17,6,66,38,26,10,36,10,6,11,12,0,60,34,24,14,30,6,5,11, +21,15,72,36,18,8,20,5,19,21,14,74,52,34,16,40,12,4,5,9, +124,43,33,19,25,29,19,15,9,9,3,4,18,23,19,33,35,60,37,49, +25,11,9,19,15,15,15,7,19,43,9,9,30,11,27,7,9,9,9,9, +9,33,17,11,19,17,22,57,19,32,23,3,11,9,2,0,7,1,4,19, +19,49,90,84,88,68,48,54,52,40,44,34,34,36,10,4,15,8,8,5, +41,1,0,7,1,21,19,23,29,37,31,24,16,22,4,29,11,13,43,21, +39,45,77,63,67,75,1,4,55,9,5,23,47,37,39,53,33,45,39,59, +57,67,87,17,43,57,17,8,16,20,44,30,42,6,40,36,52,50,62,56, +32,98,34,18,6,9,13,57,65,75,18,80,68,70,52,54,30,26,14,6, +17,8,16,20,44,30,42,6,40,36,52,50,62,56,32,98,34,18,6,9, +13,57,65,75,0,0,0,0,80,12,31,80,12,31,17,8,44,22,1,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,44,0,0,0,3,59,67,10,5,7,104,14, +11,61,25,37,6,5,21,5,33,6,21,19,9,53,55,55,59,48,1,18, +29,1,27,13,9,17,43,27,49,30,17,2,37,31,3,15,4,16,6,6, +30,24,25,3,2,3,4,21,24,3,18,38,8,34,34,20,27,22,0,19, +1,51,37,13,23,3,13,9,20,5,11,4,12,15,17,1,59,45,13,63, +7,23,20,3,23,40,2,3,27,42,21,43,2,63,34,50,46,40,50,38, +14,44,46,15,8,22,8,2,21,4,5,9,0,11,25,1,9,57,25,21, +39,29,51,64,76,60,60,58,46,38,46,28,14,22,2,19,21,65,22,16, +17,16,0,3,13,21,29,35,39,67,23,51,73,55,73,3,66,46,30,10, +10,1,9,17,19,12,92,60,46,34,60,22,10,3,5,9,76,46,26,12, +28,6,5,13,27,23,36,12,4,5,6,13,23,33,2,80,46,28,14,36, +8,2,1,11,124,35,17,0,5,11,2,14,16,3,14,26,30,27,15,19, +0,30,3,7,10,22,36,21,5,24,28,35,29,35,33,23,3,21,11,15, +7,2,19,15,13,1,27,21,35,43,7,69,25,1,13,20,11,3,36,7, +11,5,28,25,19,59,56,66,68,52,32,54,46,36,34,30,28,20,15,17, +31,0,4,13,47,15,15,27,25,25,19,21,49,45,43,58,56,54,44,20, +32,26,2,14,2,0,23,25,31,39,20,26,17,20,22,2,9,9,13,19, +17,27,45,47,55,63,77,35,55,69,47,19,31,0,2,4,86,24,22,9, +42,108,80,120,22,64,52,2,33,49,59,111,107,109,11,84,56,38,18,24, +4,3,9,21,29,15,6,5,20,20,4,10,20,26,28,14,34,30,2,66, +56,34,20,8,3,47,57,61,0,0,0,0,80,12,31,80,12,31,17,8, +44,22,1,17,30,72,64,14,34,5,27,16,5,9,46,41,29,30,14,81, +99,113,3,21,13,27,16,5,35,6,62,2,7,19,23,59,65,55,87,1, +23,33,17,45,41,71,6,15,15,19,54,4,44,0,0,0,3,59,67,10, +5,7,32,13,49,12,10,7,56,52,3,10,5,30,9,1,16,75,43,47, +47,40,9,16,16,11,37,11,9,3,23,17,41,38,19,16,17,29,1,17, +5,8,14,10,24,12,23,1,0,7,4,17,54,7,2,52,48,66,56,44, +55,6,4,11,7,33,9,42,3,1,42,80,116,96,52,57,63,10,76,80, +105,13,16,57,34,7,2,42,66,110,92,60,67,31,11,7,2,41,34,42, +32,26,34,30,16,36,30,9,4,18,6,4,15,8,3,11,4,0,8,2, +5,61,7,9,11,15,29,28,50,24,14,22,24,14,24,20,43,69,31,33, +29,103,17,7,65,22,3,3,9,11,29,17,9,49,59,39,45,49,33,9, +48,38,20,8,12,0,9,13,13,8,68,40,28,12,38,12,8,9,16,2, +62,36,26,14,32,8,3,9,19,15,74,38,18,8,22,3,19,19,16,74, +54,34,16,42,14,6,3,7,124,41,29,15,21,27,17,11,5,5,0,8, +22,21,17,31,33,66,37,51,25,9,7,19,15,15,15,7,19,45,9,9, +32,11,27,7,9,9,9,9,9,35,19,11,19,17,24,59,19,34,25,3, +11,9,2,0,7,1,6,19,19,53,88,82,86,64,44,48,46,34,40,28, +28,30,4,1,19,0,2,13,51,7,3,11,5,25,23,25,31,39,31,20, +12,18,0,33,15,15,47,25,43,49,81,67,71,77,3,2,59,11,9,25, +51,39,41,55,35,47,39,57,59,69,91,19,45,59,17,10,18,22,46,32, +44,6,42,38,54,52,64,58,34,96,30,14,2,13,17,61,69,77,20,80, +70,72,54,56,32,28,14,8,17,10,18,22,46,32,44,6,42,38,54,52, +64,58,34,96,30,14,2,13,17,61,69,77,0,0,0,0,76,10,33,76, +10,33,15,10,44,22,3,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,44,0,0,0, +3,61,67,10,7,9,104,12,11,59,25,37,6,3,19,3,31,8,19,17, +7,51,55,53,59,48,1,18,29,1,27,13,7,17,43,27,47,30,17,2, +35,31,3,15,4,16,6,6,30,24,27,5,2,5,4,21,22,5,16,38, +6,32,34,18,31,20,1,23,3,53,37,13,23,3,13,9,22,5,11,4, +14,17,17,1,63,45,13,63,7,25,20,3,25,40,2,3,31,42,23,45, +2,65,30,48,44,38,48,36,12,42,44,19,6,20,6,2,23,2,7,11, +1,13,27,3,11,61,29,23,43,33,51,60,72,56,56,54,40,32,40,22, +8,16,3,25,27,71,18,12,21,10,5,9,19,27,35,41,45,73,25,55, +77,57,75,3,66,46,30,10,10,3,9,17,19,12,92,60,46,34,62,22, +10,3,5,9,76,46,26,12,28,6,5,13,25,23,38,12,4,5,6,13, +23,31,2,80,46,28,14,36,8,2,1,11,124,35,17,0,5,11,2,14, +16,3,14,26,30,27,15,21,1,30,5,9,8,20,34,25,9,22,26,37, +33,37,33,23,1,21,11,15,7,2,21,15,13,1,29,21,35,43,7,71, +25,1,13,20,13,3,36,9,13,5,28,27,21,61,54,64,66,50,28,52, +44,34,32,28,26,18,17,21,35,3,0,17,51,19,19,29,27,27,19,21, +49,47,43,52,50,50,38,14,26,20,3,8,3,5,29,31,35,41,16,22, +21,16,16,3,15,15,19,23,23,33,51,51,61,67,81,39,59,73,45,17, +29,0,2,4,88,24,22,9,42,110,82,122,22,60,48,3,41,55,65,117, +113,113,11,84,54,36,18,24,4,5,9,21,29,15,6,5,22,20,4,10, +20,26,28,14,34,30,0,62,52,30,16,4,7,53,61,63,0,0,0,0, +76,10,33,76,10,33,15,10,44,22,3,21,26,70,64,14,36,9,27,18, +7,11,48,43,33,26,10,89,105,115,0,19,13,27,18,7,35,6,62,0, +7,19,21,63,69,57,89,3,23,33,19,47,41,71,4,15,15,19,54,2, +44,0,0,0,3,61,67,10,7,9,30,13,47,16,12,7,58,54,3,12, +3,30,7,1,20,77,45,49,49,40,11,16,20,11,37,11,7,3,23,17, +41,38,21,16,17,29,1,17,5,8,14,12,24,12,25,3,0,7,2,17, +54,7,2,52,48,66,56,44,57,6,4,13,7,33,11,42,3,1,44,82, +116,98,54,59,67,10,76,80,107,15,16,59,34,9,2,44,66,108,92,62, +69,29,15,13,5,39,32,42,30,24,32,28,14,34,28,11,2,16,4,2, +17,6,5,13,2,1,6,0,7,65,9,11,11,19,31,22,44,20,10,18, +18,6,18,16,47,75,35,39,33,107,21,11,69,18,5,5,13,15,33,21, +13,53,59,41,47,53,31,7,50,38,20,8,12,0,9,13,11,10,68,40, +28,12,40,14,10,9,20,2,62,36,26,14,32,8,3,9,17,15,76,40, +18,6,22,3,19,19,16,74,54,34,16,44,14,6,3,7,124,39,27,13, +19,25,15,9,3,3,2,10,26,21,17,31,33,72,37,55,25,9,7,19, +15,15,17,7,21,47,11,9,32,13,27,9,9,9,11,11,11,37,21,13, +21,17,26,61,21,34,27,5,11,11,2,1,9,1,6,19,19,57,84,80, +82,60,38,42,40,28,34,22,20,24,3,7,23,7,5,21,63,13,9,15, +11,31,27,29,35,41,31,14,6,12,3,39,19,19,53,29,49,53,87,73, +75,81,7,1,65,15,13,29,55,43,45,57,37,49,41,55,63,73,95,23, +49,63,17,10,18,22,48,32,44,6,44,38,56,52,64,58,34,94,26,10, +3,19,21,67,73,81,20,80,70,72,54,56,32,28,14,8,17,10,18,22, +48,32,44,6,44,38,56,52,64,58,34,94,26,10,3,19,21,67,73,81, +0,0,0,0,74,10,33,74,10,33,11,14,46,24,3,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,44,0,0,0,1,61,67,12,7,9,104,12,11,55,23,37, +8,0,15,0,27,12,15,13,3,47,53,51,57,50,0,20,27,0,25,11, +3,15,41,25,43,32,15,4,31,29,1,13,6,18,8,8,32,26,27,5, +4,5,4,19,22,5,16,38,6,32,34,18,33,20,1,25,5,53,35,11, +21,1,11,7,24,3,9,6,18,17,17,0,65,43,11,63,5,25,22,1, +25,42,2,3,33,44,23,47,2,65,28,48,44,38,48,36,12,42,44,21, +6,20,6,2,23,2,7,11,1,13,29,3,11,63,31,23,45,35,51,58, +70,54,54,52,36,28,36,18,4,12,7,29,31,75,16,10,23,6,9,13, +23,31,39,45,49,77,25,57,79,57,75,1,68,48,32,12,10,3,7,15, +17,14,94,62,48,34,64,24,12,1,3,7,78,48,28,14,30,8,3,11, +21,21,42,14,6,3,8,11,21,27,4,82,48,30,16,38,10,4,0,9, +124,33,15,2,5,9,2,16,18,1,16,28,32,25,15,21,1,32,5,9, +6,20,34,27,11,22,26,37,35,37,31,21,0,19,9,13,5,4,21,13, +11,0,29,19,33,41,5,71,25,0,13,22,13,3,38,9,13,3,30,27, +21,61,54,64,66,50,26,52,44,34,32,28,26,18,17,23,37,5,1,19, +53,21,21,29,27,27,17,19,47,47,41,48,46,46,34,10,22,16,7,4, +7,9,33,35,37,41,14,20,23,14,12,7,19,19,23,27,27,37,55,53, +65,69,83,41,61,75,41,13,25,2,4,6,92,26,24,9,44,114,86,124, +24,58,46,7,47,59,69,121,117,115,9,86,54,36,18,26,4,5,9,19, +27,13,8,3,26,22,6,12,22,28,30,16,36,32,0,60,50,28,14,2, +9,57,63,63,0,0,0,0,74,10,33,74,10,33,11,14,46,24,3,23, +24,70,66,16,40,11,25,22,7,11,52,43,35,24,8,95,109,115,4,15, +11,25,22,7,33,8,64,0,5,17,17,65,71,57,89,3,21,31,19,47, +39,69,4,13,13,17,56,2,44,0,0,0,1,61,67,12,7,9,30,11, +43,22,16,5,62,58,1,16,0,32,3,0,26,77,45,49,49,42,11,18, +26,9,35,9,3,3,21,17,39,40,21,18,15,27,0,15,3,10,16,14, +26,14,25,3,2,5,2,15,56,5,2,54,50,68,58,46,57,8,6,13, +7,31,11,44,1,0,48,86,118,102,58,59,69,12,78,82,107,15,18,59, +36,9,4,48,66,108,94,66,71,25,17,17,11,35,32,42,30,24,32,28, +14,34,28,11,2,16,4,2,17,6,5,13,2,1,6,0,7,67,9,11, +11,21,31,18,40,18,8,16,14,0,14,14,49,79,37,43,35,109,23,13, +71,16,5,5,15,17,35,23,15,55,59,41,47,55,27,3,54,40,20,8, +14,2,7,11,7,14,70,42,30,14,44,16,14,7,26,4,64,38,28,16, +34,10,1,7,13,13,80,42,20,6,24,1,17,17,18,76,56,36,18,46, +16,8,1,5,124,35,23,9,15,21,11,5,0,0,6,14,32,19,15,29, +31,80,35,57,23,7,5,17,15,13,17,5,21,47,11,9,34,13,27,9, +9,7,11,11,11,37,21,13,21,15,30,61,21,36,27,5,11,11,4,1, +9,0,8,17,17,59,82,78,80,58,34,38,36,22,30,18,14,20,9,11, +27,13,11,27,73,17,13,17,15,35,29,31,37,41,31,10,2,8,7,43, +21,21,57,31,53,55,91,77,77,83,9,3,69,17,15,31,57,45,47,59, +37,49,41,53,65,75,97,25,51,65,15,12,20,24,52,34,46,8,48,40, +58,54,66,60,36,94,24,8,7,23,23,71,75,83,22,82,72,74,56,58, +34,30,16,10,15,12,20,24,52,34,46,8,48,40,58,54,66,60,36,94, +24,8,7,23,23,71,75,83,0,0,0,0,72,10,33,72,10,33,7,16, +46,24,3,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,44,0,0,0,0,61,67,12, +9,9,104,12,11,53,21,37,8,2,11,4,25,14,11,11,0,45,51,49, +55,52,0,22,25,0,25,9,0,15,41,25,41,32,15,4,29,29,0,13, +6,18,8,10,32,26,29,5,4,5,4,19,22,5,14,38,4,32,34,18, +37,20,1,29,7,55,33,9,19,0,9,5,26,1,9,8,20,17,17,0, +67,43,9,63,5,25,24,1,27,44,2,3,35,46,25,49,2,67,24,46, +42,36,46,34,10,40,44,23,4,20,6,2,23,0,9,13,3,15,31,5, +13,67,33,25,47,37,51,54,68,50,50,48,32,24,32,12,0,8,13,35, +35,81,12,6,27,2,13,17,27,35,43,51,53,81,27,61,81,59,75,1, +68,48,32,12,10,3,7,15,15,14,94,62,48,34,66,24,14,1,1,5, +80,50,28,14,32,8,3,9,19,19,44,16,6,3,10,9,19,25,4,82, +48,30,16,40,12,6,2,7,124,33,15,2,5,9,2,16,18,1,16,28, +34,25,15,21,3,32,7,11,4,18,34,29,13,22,26,39,37,39,29,19, +2,19,9,13,3,6,21,13,11,0,31,19,33,41,3,71,25,0,13,24, +13,3,40,9,13,3,32,29,21,63,52,64,66,48,24,50,42,32,30,26, +24,16,19,25,39,9,3,23,57,23,23,31,29,27,17,19,47,49,39,44, +42,42,30,4,18,12,13,0,11,13,37,39,39,43,10,16,25,10,8,11, +23,23,27,31,31,41,59,57,69,73,85,45,65,79,39,11,23,4,6,8, +96,28,26,9,46,116,88,124,26,56,42,13,53,65,75,125,121,117,9,86, +54,36,18,26,4,5,9,17,25,11,10,1,28,24,8,14,24,30,32,16, +38,32,0,58,46,24,10,1,13,61,67,65,0,0,0,0,72,10,33,72, +10,33,7,16,46,24,3,27,20,68,68,16,44,15,25,24,7,11,54,45, +37,22,4,101,113,117,8,13,11,25,24,7,33,10,64,0,3,15,15,67, +73,57,89,3,21,29,19,47,39,69,4,13,13,15,56,2,44,0,0,0, +0,61,67,12,9,9,30,9,41,26,18,3,66,62,0,18,4,34,1,2, +30,79,45,49,49,42,11,20,30,9,33,7,0,3,21,17,39,40,21,18, +13,27,2,15,3,10,16,16,28,14,25,3,2,5,2,15,56,5,2,54, +50,68,58,46,59,10,8,15,7,31,11,46,1,0,50,88,120,106,62,61, +71,12,78,82,109,15,18,61,38,9,4,50,66,108,94,68,73,23,19,23, +17,33,32,42,30,22,30,28,14,34,26,13,0,16,4,2,17,4,7,15, +2,1,6,1,9,69,11,13,11,23,33,14,36,14,4,12,10,5,10,12, +53,83,41,47,39,111,25,15,75,14,7,7,17,21,39,27,19,59,59,43, +49,59,25,1,56,42,20,8,16,4,5,9,3,16,72,44,32,16,46,18, +16,5,30,6,64,38,28,16,36,12,0,5,11,13,82,44,20,6,26,0, +17,15,20,76,58,36,18,48,18,10,0,3,124,33,19,5,11,19,9,1, +4,2,10,18,36,17,13,27,29,86,35,59,23,5,3,17,15,13,17,5, +21,49,11,9,36,13,27,9,9,7,11,11,11,39,23,13,21,15,32,63, +21,38,29,5,11,11,4,1,9,0,10,17,17,63,80,76,78,54,30,32, +30,16,26,12,8,14,15,17,31,21,19,35,83,23,17,21,19,39,33,33, +39,43,31,6,1,4,11,47,25,25,61,35,57,59,95,81,81,85,11,5, +73,21,19,35,61,47,49,61,39,51,41,51,67,77,101,27,53,67,15,12, +22,26,54,36,48,8,50,42,60,54,68,62,38,92,20,4,11,27,27,75, +79,85,24,82,72,76,58,60,34,32,16,12,15,12,22,26,54,36,48,8, +50,42,60,54,68,62,38,92,20,4,11,27,27,75,79,85,0,0,0,0, +70,10,33,70,10,33,3,20,48,24,5,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, +44,0,0,0,0,61,67,14,11,9,104,12,11,51,19,37,10,4,7,8, +21,16,7,9,4,43,49,47,53,54,0,24,23,0,23,9,4,15,39,23, +39,32,15,6,25,27,2,13,6,18,8,12,34,28,29,5,4,5,4,19, +22,7,14,38,2,32,34,18,41,20,3,33,9,57,31,7,17,2,7,5, +28,1,7,10,22,17,17,0,69,41,7,63,5,25,26,1,29,46,2,3, +37,48,25,51,2,69,22,44,42,34,44,32,10,38,42,25,2,20,6,2, +25,1,11,15,5,17,33,7,13,71,35,25,49,39,51,52,64,48,46,44, +28,20,28,8,5,4,17,39,41,85,8,2,29,1,17,23,33,39,49,55, +57,87,29,65,83,61,75,1,70,48,32,12,10,3,7,15,15,14,94,62, +48,34,68,26,14,0,1,3,82,50,30,14,34,10,1,9,17,17,46,18, +8,3,12,7,17,23,6,82,48,30,16,42,12,8,4,5,124,31,13,4, +5,9,2,16,18,1,16,28,34,25,15,21,3,34,9,13,2,16,34,31, +15,22,26,39,39,39,27,17,4,17,7,11,3,8,21,13,11,2,31,19, +33,39,1,71,25,0,13,26,13,3,42,9,13,3,34,31,21,65,50,62, +64,46,22,48,40,30,28,24,22,14,21,27,41,11,5,25,61,27,25,33, +29,29,17,19,47,49,37,40,38,38,26,1,14,8,17,3,15,17,43,43, +43,45,6,14,29,6,4,15,27,27,31,35,35,45,65,61,73,77,87,49, +69,81,37,9,21,6,8,10,98,30,28,9,48,120,92,124,28,52,40,17, +59,71,81,125,125,119,9,86,54,36,18,26,4,5,9,17,23,9,12,0, +30,24,8,16,24,30,32,16,38,32,0,56,44,20,6,5,17,65,71,67, +0,0,0,0,70,10,33,70,10,33,3,20,48,24,5,31,18,66,68,16, +48,17,25,28,7,13,56,47,39,20,0,109,117,119,12,9,11,25,28,7, +31,12,66,0,1,13,13,69,75,57,91,3,21,27,19,49,39,69,4,13, +13,13,58,2,44,0,0,0,0,61,67,14,11,9,28,9,39,30,20,1, +68,64,2,20,8,36,0,4,34,81,45,49,49,44,11,22,34,9,31,5, +4,3,21,17,39,42,21,20,11,27,4,15,3,10,18,18,28,14,25,3, +2,5,2,15,56,5,2,56,50,70,58,48,59,10,10,15,7,31,11,48, +1,2,52,90,122,108,66,61,73,14,78,82,111,15,20,61,38,9,4,52, +66,108,94,70,75,19,21,29,23,29,32,42,28,20,30,26,12,34,26,15, +1,16,4,2,19,4,9,17,0,1,6,3,9,71,11,15,11,25,33,10, +32,10,2,8,6,11,4,10,57,87,43,51,43,115,27,17,79,12,9,9, +19,23,43,31,23,61,59,45,51,61,21,2,60,42,20,8,18,6,3,7, +0,18,74,46,34,16,48,20,20,3,34,6,66,40,30,18,38,12,0,3, +9,13,86,46,20,6,28,0,17,13,22,78,60,38,18,50,18,12,0,3, +124,29,17,3,7,17,5,0,6,6,14,22,40,17,11,27,27,92,35,61, +23,3,1,17,15,13,17,3,21,51,11,9,36,13,27,9,9,7,13,11, +11,41,25,13,21,15,34,65,21,40,31,5,11,11,6,1,11,2,12,17, +17,65,78,74,76,50,26,28,26,10,20,6,2,8,21,23,35,29,25,43, +93,29,21,25,23,45,37,35,41,45,31,2,5,0,15,51,29,27,65,39, +61,63,99,85,85,87,13,7,77,23,23,37,65,51,53,63,41,53,41,49, +69,81,103,29,55,69,15,14,22,26,56,38,50,8,52,44,62,56,70,62, +40,92,16,0,15,31,31,79,83,87,24,84,74,78,58,62,36,32,18,12, +15,14,22,26,56,38,50,8,52,44,62,56,70,62,40,92,16,0,15,31, +31,79,83,87,0,0,0,0,66,10,33,66,10,33,1,22,48,24,5,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,44,0,0,0,2,63,67,14,13,9,104,12, +11,49,17,37,10,8,5,12,19,18,5,5,8,41,49,45,53,54,0,26, +21,0,23,7,8,15,39,23,37,32,13,6,23,27,2,13,8,18,8,12, +34,28,31,7,4,5,4,19,22,7,12,38,2,32,34,16,45,20,3,37, +11,59,29,5,15,4,7,3,30,0,7,12,24,17,17,2,71,41,5,63, +5,25,26,1,31,48,2,3,41,50,27,53,2,71,18,42,40,32,42,30, +8,36,42,29,0,18,6,2,25,3,11,17,5,19,35,9,15,75,37,27, +51,41,51,48,62,44,42,40,24,14,24,2,9,0,23,45,45,91,4,0, +33,7,21,27,37,45,53,61,61,91,31,67,87,63,75,1,70,50,32,12, +10,3,7,15,13,16,96,62,48,34,70,26,16,0,0,3,84,52,30,14, +34,10,1,7,15,17,48,18,8,3,14,5,17,21,6,84,48,30,16,44, +14,8,6,3,124,31,13,4,5,9,2,16,18,0,16,28,36,25,15,21, +5,34,11,15,0,14,34,35,17,20,26,41,41,41,27,17,6,17,7,11, +1,10,23,13,11,2,33,19,33,39,0,71,25,2,13,26,13,3,44,9, +15,3,36,31,23,67,48,62,64,44,20,46,38,28,26,22,20,12,23,29, +43,15,9,29,65,29,27,35,31,29,17,19,47,51,37,34,32,34,20,7, +10,4,23,7,19,21,47,47,45,47,2,10,31,2,0,19,31,33,35,39, +39,49,69,65,77,81,89,53,73,85,35,7,19,6,10,12,102,32,30,9, +50,122,94,124,28,50,36,23,65,77,87,125,125,121,9,86,54,36,18,26, +4,5,9,15,21,7,14,0,32,26,10,18,26,32,34,18,40,34,0,52, +40,16,2,9,21,69,75,69,0,0,0,0,66,10,33,66,10,33,1,22, +48,24,5,35,14,64,70,16,50,21,25,30,9,13,58,49,43,16,3,115, +123,121,16,7,11,25,30,9,31,14,66,1,1,11,9,71,79,59,91,3, +19,25,21,49,39,69,4,13,13,13,58,2,44,0,0,0,2,63,67,14, +13,9,28,7,37,34,22,0,72,68,2,22,12,38,2,6,40,81,47,49, +51,44,13,24,40,7,31,5,8,3,21,17,39,42,21,20,9,27,4,13, +3,10,18,20,30,14,27,5,2,5,2,15,56,5,2,56,50,70,58,48, +61,12,10,17,7,29,11,50,0,2,56,94,124,112,70,63,75,14,80,82, +113,15,20,63,40,9,4,54,66,108,94,74,77,17,23,35,29,27,30,42, +28,20,28,26,12,34,24,17,3,14,4,2,19,2,9,19,0,3,4,5, +11,73,13,17,11,29,35,6,28,6,1,6,2,19,0,8,61,93,47,55, +47,117,31,19,81,10,11,11,23,27,47,35,25,65,59,47,53,65,19,4, +62,44,20,8,20,8,1,7,4,22,76,46,34,18,52,22,22,1,40,8, +66,40,30,18,40,14,2,3,7,13,88,48,20,6,30,2,17,11,24,78, +62,38,18,52,20,14,2,1,124,27,13,0,5,15,3,4,10,8,16,26, +46,15,9,25,25,98,33,63,21,1,1,17,15,13,19,3,23,53,11,9, +38,13,27,9,9,5,13,13,11,43,27,15,21,15,36,67,23,40,31,7, +11,11,6,3,11,2,12,17,17,69,76,72,74,48,20,22,20,4,16,0, +5,2,29,27,39,37,33,51,103,35,25,29,27,49,41,39,43,47,31,3, +11,5,19,55,33,31,69,43,65,67,103,91,87,91,15,9,83,27,25,41, +69,53,55,65,43,55,41,47,73,83,107,33,57,71,15,14,24,28,58,38, +50,10,54,46,64,56,72,64,40,90,12,3,19,35,35,85,87,91,26,84, +74,78,60,62,36,34,18,14,15,14,24,28,58,38,50,10,54,46,64,56, +72,64,40,90,12,3,19,35,35,85,87,91,0,0,0,0,64,10,33,64, +10,33,2,26,48,24,7,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,44,0,0,0, +2,63,67,16,15,9,104,12,11,47,15,37,12,10,1,16,15,20,1,3, +12,39,47,43,51,56,0,28,19,0,21,5,12,15,39,21,33,34,13,8, +21,25,4,13,8,20,10,14,36,30,31,7,4,5,4,19,22,9,10,38, +0,32,34,16,49,20,5,39,13,61,27,3,13,6,5,1,32,2,5,14, +26,17,17,2,73,39,3,63,3,25,28,1,33,50,2,3,43,52,27,55, +2,71,16,40,40,30,40,28,6,36,42,31,1,18,6,2,27,3,13,19, +7,21,37,9,17,79,39,29,53,43,51,44,60,40,38,38,20,10,20,1, +13,3,27,49,49,95,0,3,37,11,25,31,41,49,57,67,65,97,33,71, +89,63,75,1,70,50,32,12,10,3,7,15,13,16,96,62,48,34,72,28, +18,0,2,1,86,54,30,16,36,12,0,7,13,15,52,20,8,1,16,3, +15,19,8,84,50,30,16,46,16,10,8,1,124,31,13,6,5,9,2,16, +18,0,16,30,36,25,15,21,7,36,13,17,1,14,34,37,19,20,26,43, +43,41,25,15,8,15,5,9,1,12,23,13,11,2,35,19,33,37,2,71, +25,2,13,28,13,3,46,9,15,3,38,33,23,67,46,62,62,44,18,44, +36,26,26,20,18,10,25,31,45,17,11,31,69,31,29,37,33,31,17,17, +47,51,35,30,28,30,16,11,6,0,27,11,23,25,51,51,49,49,1,6, +33,1,3,23,35,37,39,43,43,53,75,69,81,85,91,57,77,87,33,3, +17,8,12,14,106,34,32,9,52,124,98,124,30,46,32,27,71,81,93,125, +125,123,9,86,54,36,18,26,4,5,9,15,19,5,16,2,34,28,10,20, +28,34,36,18,40,34,0,50,38,14,0,13,25,73,79,71,0,0,0,0, +64,10,33,64,10,33,2,26,48,24,7,39,12,62,72,16,54,25,23,34, +9,13,60,51,45,14,7,121,125,121,20,5,11,23,34,9,31,16,66,1, +0,9,7,73,81,59,91,3,19,23,21,49,39,69,4,11,13,11,60,2, +44,0,0,0,2,63,67,16,15,9,26,7,33,40,24,2,74,70,4,24, +16,40,4,8,44,83,47,49,51,44,13,26,44,7,29,3,12,3,21,17, +37,42,21,22,7,25,6,13,3,12,20,22,30,14,27,5,4,5,2,15, +58,5,2,58,52,70,58,48,61,12,12,17,7,29,11,52,0,4,58,96, +124,114,74,63,77,16,80,82,115,15,22,63,42,9,4,58,66,108,94,76, +79,13,25,39,35,25,30,42,26,18,28,26,10,34,24,19,5,14,4,2, +19,2,11,21,1,3,4,7,11,75,15,17,11,31,35,2,24,4,3,2, +1,25,5,6,65,97,49,59,51,119,33,21,85,8,13,13,25,29,51,39, +29,67,59,49,55,69,15,8,64,44,20,8,22,10,0,5,8,24,78,48, +36,20,54,24,26,0,44,10,68,42,32,20,42,16,2,1,5,11,90,50, +20,6,32,2,15,9,26,78,64,38,18,54,22,16,2,0,124,25,11,2, +1,13,0,6,14,12,20,30,50,13,7,23,23,104,33,65,21,0,0,17, +15,13,19,1,23,55,11,9,40,13,27,9,9,5,15,13,11,45,29,15, +21,15,38,67,23,42,33,7,11,11,6,3,13,2,14,17,17,71,74,70, +72,44,16,18,14,1,10,5,11,3,35,33,43,45,39,59,113,41,29,31, +31,55,45,41,45,49,31,7,15,9,23,59,37,33,73,47,69,71,107,95, +91,93,17,11,87,29,29,43,73,55,57,67,45,57,41,45,75,85,109,35, +59,73,15,16,24,30,60,40,52,10,56,48,66,58,74,64,42,90,8,7, +23,39,39,89,91,93,26,86,76,80,62,64,38,34,18,16,15,16,24,30, +60,40,52,10,56,48,66,58,74,64,42,90,8,7,23,39,39,89,91,93, +0,0,0,0,62,10,35,62,10,35,6,28,50,24,7,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,44,0,0,0,4,63,67,16,15,11,104,12,11,45,15,37, +12,12,2,20,13,22,2,1,16,37,45,41,49,58,0,30,19,2,21,5, +16,15,37,21,31,34,13,8,17,25,6,11,8,20,10,16,36,30,33,7, +4,5,4,19,22,9,10,38,1,32,34,16,53,20,5,43,15,63,27,1, +13,6,3,1,34,2,5,14,30,17,17,2,75,39,1,63,3,25,30,0, +35,50,2,3,45,54,29,57,2,73,12,38,38,30,38,28,6,34,40,33, +3,18,6,2,27,5,15,21,9,21,39,11,17,83,41,29,55,45,51,42, +56,38,34,34,16,6,16,7,19,7,33,55,55,101,3,7,39,15,31,37, +47,53,63,71,71,101,35,75,91,65,75,0,72,50,34,12,10,3,7,15, +11,16,96,64,48,34,74,28,18,2,2,0,88,54,32,16,38,12,0,5, +11,13,54,22,10,1,16,3,13,15,8,84,50,30,18,46,16,12,8,0, +124,29,11,6,5,9,2,16,18,0,18,30,38,25,15,23,7,36,15,19, +3,12,34,39,21,20,26,43,45,43,23,13,10,15,5,9,0,12,23,11, +9,4,35,19,33,37,4,71,25,2,13,30,13,3,48,11,15,3,38,35, +23,69,44,60,62,42,16,44,36,24,24,20,16,8,27,33,47,21,13,35, +73,35,33,39,33,31,17,17,45,53,33,26,24,26,12,17,2,3,33,15, +29,29,57,55,51,49,3,4,37,5,9,27,39,41,43,47,49,57,79,73, +85,87,95,61,81,91,31,1,15,10,14,16,108,36,34,9,54,124,100,124, +32,44,30,33,77,87,97,125,125,125,7,86,54,36,18,26,4,5,9,13, +17,5,18,4,36,28,12,22,28,34,36,18,42,34,0,48,34,10,3,15, +27,79,81,73,0,0,0,0,62,10,35,62,10,35,6,28,50,24,7,41, +8,60,72,18,58,27,23,36,9,15,62,53,47,12,9,125,125,123,24,1, +11,23,36,9,29,18,68,1,2,7,5,77,83,59,93,3,19,23,21,51, +37,69,2,11,13,9,60,2,44,0,0,0,4,63,67,16,15,11,26,5, +31,44,26,4,78,74,6,26,20,42,6,8,48,85,47,49,51,46,13,28, +48,7,27,1,16,3,21,17,37,44,23,22,7,25,8,13,1,12,20,24, +32,14,27,5,4,5,2,15,58,5,2,58,52,72,60,50,63,14,14,19, +7,29,11,54,0,4,60,98,124,118,76,65,79,16,80,82,115,17,22,65, +42,11,6,60,66,108,96,78,81,11,27,45,41,21,30,42,26,16,26,24, +10,32,22,19,5,14,2,2,21,0,13,23,1,3,4,7,13,79,15,19, +11,33,37,3,20,0,7,1,5,31,9,2,69,101,53,63,55,123,35,25, +89,4,15,15,27,33,55,43,33,71,59,51,57,71,13,10,68,46,20,8, +24,10,0,3,10,26,80,50,38,20,56,26,28,2,48,10,68,42,32,20, +44,16,4,0,3,11,94,52,20,6,32,4,15,9,26,80,64,40,18,56, +22,16,4,0,124,21,7,6,2,9,2,10,16,14,24,34,54,13,5,23, +23,110,33,67,21,0,2,17,15,13,19,1,23,57,11,9,40,13,27,9, +9,5,15,13,11,47,31,15,21,15,40,69,23,44,35,7,11,11,8,3, +13,4,16,17,17,75,72,68,70,40,12,12,10,7,6,11,17,9,41,39, +47,51,47,67,123,45,35,35,35,59,49,43,47,51,31,11,19,13,27,63, +39,37,77,51,75,75,111,99,95,95,19,15,91,33,33,47,77,59,61,69, +47,59,43,43,77,89,113,37,63,75,13,16,26,30,62,42,54,10,58,50, +68,58,76,66,44,88,4,11,27,43,43,93,95,95,28,86,76,82,62,66, +38,36,20,16,13,16,26,30,62,42,54,10,58,50,68,58,76,66,44,88, +4,11,27,43,43,93,95,95,0,0,0,0,60,10,35,60,10,35,10,32, +50,24,9,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,44,0,0,0,4,63,67,18, +17,11,104,12,11,43,13,37,14,16,4,24,9,24,4,2,20,35,43,39, +49,60,0,32,17,2,19,3,20,15,37,19,29,34,11,10,15,23,6,11, +10,20,10,18,38,32,33,9,4,5,4,19,22,11,8,38,1,32,34,14, +57,20,7,47,17,65,25,0,11,8,1,0,36,4,3,16,32,17,17,4, +77,37,0,63,3,25,30,0,37,52,2,3,49,56,29,59,2,75,10,36, +38,28,36,26,4,32,40,35,5,18,6,2,29,7,15,23,9,23,41,13, +19,87,43,31,57,47,51,38,54,34,30,30,12,0,12,11,23,11,37,59, +59,105,7,9,43,21,35,41,51,59,67,77,75,107,37,77,95,67,75,0, +72,52,34,12,10,3,7,15,11,18,98,64,48,34,76,30,20,2,4,2, +90,56,32,16,40,14,2,5,9,13,56,22,10,1,18,1,13,13,10,86, +50,30,18,48,18,14,10,2,124,29,11,8,5,9,2,16,18,2,18,30, +38,25,15,23,9,38,17,21,5,10,34,41,23,18,26,45,47,43,21,13, +12,13,3,7,0,14,23,11,9,4,37,19,33,35,6,71,25,4,13,30, +13,3,50,11,15,3,40,35,25,71,42,60,60,40,14,42,34,22,22,18, +14,6,29,35,49,23,17,37,77,37,35,41,35,33,17,17,45,53,31,22, +20,22,6,23,1,7,37,19,33,33,61,59,55,51,7,0,39,9,13,31, +43,45,47,51,53,61,85,77,89,91,97,65,85,93,29,0,13,10,16,18, +112,38,36,9,56,124,104,124,32,40,26,37,83,93,103,125,125,125,7,86, +54,36,18,26,4,5,9,13,15,3,20,6,38,30,12,24,30,36,38,20, +42,36,0,44,32,6,7,19,31,83,85,75,0,0,0,0,60,10,35,60, +10,35,10,32,50,24,9,45,6,58,74,18,60,31,23,40,11,15,64,55, +49,10,13,125,125,125,28,0,11,23,40,11,29,20,68,1,2,5,1,79, +85,59,93,3,17,21,23,51,37,69,2,11,13,7,62,2,44,0,0,0, +4,63,67,18,17,11,24,5,29,48,28,6,80,76,8,28,24,44,8,10, +54,85,49,49,53,46,13,30,54,5,27,1,20,3,21,17,37,44,23,24, +5,25,10,11,1,12,22,26,32,14,29,5,4,5,2,15,58,5,2,60, +52,72,60,50,63,14,14,19,7,27,11,56,2,6,64,102,124,120,80,65, +81,18,82,82,117,17,24,65,44,11,6,62,66,108,96,82,83,7,29,51, +47,19,30,42,24,16,26,24,8,32,22,21,7,14,2,2,21,0,13,25, +3,3,4,9,13,81,17,21,11,35,37,7,16,3,9,3,9,37,15,0, +73,105,55,67,59,125,37,27,91,2,17,17,31,35,59,47,35,73,59,53, +59,75,9,14,70,46,20,8,26,12,2,3,14,30,82,52,38,22,60,28, +32,4,54,12,70,44,34,22,46,18,4,2,1,11,96,54,20,6,34,4, +15,7,28,80,66,40,18,58,24,18,4,2,124,19,5,8,4,7,6,12, +20,18,28,38,60,11,3,21,21,116,31,69,19,2,4,17,15,13,19,0, +25,59,11,9,42,13,27,9,9,3,17,15,11,49,33,17,21,15,42,71, +25,46,35,9,11,11,8,5,15,4,16,17,17,77,70,66,68,38,6,8, +4,13,0,17,23,15,47,43,51,59,53,75,125,51,39,39,39,65,53,45, +49,53,31,15,25,19,31,67,43,39,81,55,79,79,115,103,97,99,21,17, +95,35,35,49,81,61,63,71,49,61,43,41,81,91,115,41,65,77,13,18, +26,32,64,44,54,12,60,52,70,60,78,66,44,88,0,15,31,47,47,99, +99,97,28,88,78,82,64,68,40,36,20,18,13,18,26,32,64,44,54,12, +60,52,70,60,78,66,44,88,0,15,31,47,47,99,99,97,0,0,0,0, +56,8,35,56,8,35,12,34,50,24,9,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, +44,0,0,0,6,65,67,18,19,11,104,12,11,41,11,37,14,18,8,28, +7,26,8,4,22,33,43,37,47,60,0,34,15,2,19,3,22,15,37,19, +27,34,11,10,13,23,8,11,10,20,10,18,38,32,35,9,4,5,4,19, +22,11,6,38,3,32,34,14,61,20,7,51,19,67,23,2,9,10,1,0, +38,4,3,18,34,17,17,4,81,37,2,63,3,27,32,0,39,54,2,3, +51,58,31,61,2,77,6,34,36,26,34,24,2,30,38,39,7,16,6,2, +29,9,17,25,11,25,43,15,21,91,47,33,59,49,51,34,50,30,26,26, +8,3,8,17,29,15,43,65,65,111,11,13,47,25,39,47,57,63,73,83, +79,111,39,81,97,69,77,0,72,52,34,12,10,3,7,15,9,18,98,64, +48,34,78,30,20,2,4,2,92,56,32,16,40,14,2,3,7,11,58,24, +10,1,20,0,11,11,10,86,50,30,18,50,18,14,12,2,124,29,11,8, +5,9,2,16,18,2,18,30,40,25,15,23,11,38,19,23,7,8,34,45, +27,18,26,47,49,45,21,11,14,13,3,7,2,16,25,11,9,4,39,19, +33,35,6,73,25,4,13,32,13,3,50,11,17,3,42,37,25,73,40,58, +60,38,10,40,32,20,20,16,12,4,31,37,51,27,19,41,81,41,37,43, +37,33,17,17,45,55,31,16,14,18,2,29,7,13,43,23,37,37,67,63, +57,53,11,3,43,13,17,37,49,51,53,55,57,67,89,81,95,95,99,69, +89,97,27,2,11,12,18,18,114,40,36,9,56,124,106,124,34,38,22,43, +89,99,109,125,125,125,7,86,54,36,18,26,4,5,9,11,15,1,22,6, +40,30,14,24,30,36,38,20,44,36,1,42,28,2,11,23,35,87,89,77, +0,0,0,0,56,8,35,56,8,35,12,34,50,24,9,49,2,56,74,18, +64,35,23,42,11,17,66,57,53,6,17,125,125,125,32,2,11,23,42,11, +29,20,68,3,4,3,0,81,89,61,95,3,17,19,23,53,37,69,2,11, +13,7,62,2,44,0,0,0,6,65,67,18,19,11,24,3,27,52,30,6, +84,80,8,30,28,44,10,12,58,87,49,51,53,46,15,30,58,5,25,0, +22,3,21,17,37,44,23,24,3,25,10,11,1,12,22,28,34,14,29,7, +4,5,0,15,58,5,2,60,52,72,60,50,65,16,16,21,7,27,11,58, +2,6,66,104,124,124,84,67,83,18,82,82,119,17,24,67,44,11,6,64, +66,108,96,84,85,5,31,57,55,17,28,42,24,14,24,22,8,32,20,23, +9,12,2,0,23,1,15,27,3,5,2,11,15,83,19,23,11,39,39,11, +12,7,13,7,15,45,19,1,77,111,59,73,63,125,41,29,95,0,19,19, +33,39,63,51,39,77,59,55,61,79,7,16,72,48,20,8,26,14,4,1, +18,32,82,52,40,22,62,30,34,6,58,12,70,44,34,22,46,18,6,2, +0,11,98,56,20,6,36,6,15,5,30,80,68,40,18,60,24,20,6,2, +124,17,1,12,8,5,8,16,22,20,30,42,64,11,1,21,19,122,31,71, +19,4,4,17,15,13,21,0,25,61,11,9,42,13,27,11,9,3,17,15, +13,51,35,17,23,15,44,73,25,46,37,9,11,13,8,5,15,4,18,17, +17,81,68,64,66,34,2,2,1,19,3,23,31,21,55,49,55,67,61,83, +125,57,43,43,45,69,57,49,53,55,31,21,29,23,35,73,47,43,87,59, +83,83,119,109,101,101,25,19,101,39,39,53,85,65,67,73,51,63,43,39, +83,95,119,43,67,79,13,18,28,32,66,44,56,12,62,52,72,60,78,68, +46,86,3,19,35,51,51,103,103,101,30,88,78,84,64,68,40,38,20,18, +13,18,28,32,66,44,56,12,62,52,72,60,78,68,46,86,3,19,35,51, +51,103,103,101,0,0,0,0,54,8,35,54,8,35,16,36,52,24,9,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,44,0,0,0,8,65,67,18,21,11,104,12, +11,39,9,37,14,20,12,32,3,30,12,6,26,31,41,35,45,62,2,36, +13,2,17,1,26,15,35,19,23,36,11,10,9,23,10,11,10,22,12,20, +38,32,35,9,6,5,4,17,22,11,6,38,5,32,34,14,65,20,7,53, +21,67,21,4,7,12,0,2,40,6,3,20,36,17,17,4,83,35,4,63, +1,27,34,0,41,56,2,3,53,60,33,63,2,77,4,32,36,24,32,22, +2,30,38,41,9,16,6,2,29,9,19,27,13,27,45,15,21,93,49,33, +61,51,51,32,48,28,24,24,4,7,4,21,33,19,47,71,69,117,13,17, +49,29,43,51,61,67,77,87,83,115,39,85,99,69,77,0,74,52,34,14, +10,3,5,15,7,18,98,64,50,34,80,32,22,4,6,4,94,58,34,18, +42,16,2,1,5,9,62,26,12,0,22,2,9,9,12,86,52,32,18,52, +20,16,14,4,124,27,9,10,5,9,2,18,20,2,18,32,42,25,15,23, +11,38,21,23,9,8,34,47,29,18,26,47,51,47,19,9,16,13,1,7, +4,18,25,11,9,6,39,19,33,35,8,73,25,4,13,34,13,3,52,11, +17,3,44,39,25,73,38,58,60,38,8,38,30,18,20,14,10,4,31,39, +53,29,21,45,85,43,39,43,37,33,15,15,45,57,29,12,10,14,1,33, +11,17,47,27,41,41,71,67,59,55,15,5,45,17,21,41,53,55,57,59, +61,71,93,83,99,99,101,73,93,101,25,6,7,14,20,20,118,42,38,9, +58,124,108,124,36,36,20,47,95,103,115,125,125,125,7,86,54,36,18,28, +4,5,9,9,13,0,24,8,44,32,16,26,32,38,40,20,46,36,1,40, +26,0,13,27,39,91,93,77,0,0,0,0,54,8,35,54,8,35,16,36, +52,24,9,53,1,56,76,18,68,37,21,46,11,17,68,57,55,4,21,125, +125,125,36,6,9,21,46,11,27,22,70,3,6,1,2,83,91,61,95,3, +17,17,23,53,37,69,2,9,11,5,62,2,44,0,0,0,8,65,67,18, +21,11,24,1,23,58,32,8,88,84,10,32,32,46,14,14,62,89,49,51, +53,48,15,32,62,5,23,2,26,3,19,17,35,46,23,26,1,23,12,11, +1,14,24,30,36,14,29,7,6,3,0,15,60,5,2,60,54,74,60,52, +65,18,18,23,7,27,11,60,2,8,68,106,124,124,88,69,85,20,82,84, +121,17,24,67,46,11,6,68,66,108,96,86,87,3,33,61,61,13,28,42, +24,12,24,22,8,32,20,25,11,12,2,0,23,1,17,27,3,5,2,13, +17,85,19,23,11,41,39,15,8,9,15,11,19,51,23,3,81,115,61,77, +65,125,43,31,99,1,21,21,35,43,65,55,43,79,59,55,63,81,3,20, +76,50,20,8,28,16,6,0,22,34,84,54,42,24,64,32,36,8,62,14, +72,46,36,22,48,20,8,4,4,9,102,58,22,6,38,8,13,3,32,82, +70,42,20,62,26,22,8,4,124,13,2,16,12,3,10,20,26,24,34,46, +68,9,0,19,17,124,31,73,19,6,6,15,15,13,21,0,25,63,11,9, +44,13,27,11,9,3,17,15,13,51,37,17,23,13,48,73,25,48,39,9, +11,13,10,5,15,6,20,15,15,85,66,62,64,30,1,3,5,25,7,27, +37,25,61,55,59,75,67,89,125,63,47,45,49,73,59,51,55,57,31,25, +33,27,39,77,51,45,91,63,87,87,123,113,105,103,27,21,105,41,43,55, +89,67,69,75,53,63,43,37,85,97,123,45,69,81,13,20,30,34,70,46, +58,12,64,54,74,62,80,70,48,84,5,23,39,55,55,107,107,103,32,88, +80,86,66,70,42,40,22,20,13,20,30,34,70,46,58,12,64,54,74,62, +80,70,48,84,5,23,39,55,55,107,107,103,0,0,0,0,52,8,35,52, +8,35,20,40,52,24,11,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,44,0,0,0, +8,65,67,20,23,11,104,12,11,37,7,37,16,24,14,36,1,32,14,10, +30,29,39,33,45,64,2,38,11,2,17,0,30,15,35,17,21,36,9,12, +7,21,10,11,12,22,12,22,40,34,37,11,6,5,4,17,22,13,4,38, +5,32,34,12,69,20,9,57,23,69,19,6,5,14,2,4,42,8,1,22, +38,17,17,6,85,35,6,63,1,27,34,0,43,58,2,3,57,62,33,65, +2,79,0,30,34,22,30,20,0,28,38,43,11,16,6,2,31,11,19,29, +13,29,47,17,23,97,51,35,63,53,51,28,46,24,20,20,0,13,0,27, +37,23,53,75,73,121,17,19,53,35,47,55,65,73,81,93,87,121,41,87, +103,71,77,0,74,54,34,14,10,3,5,15,7,20,100,64,50,34,82,32, +24,4,8,6,96,60,34,18,44,16,4,1,3,9,64,26,12,0,24,4, +9,7,12,88,52,32,18,54,22,18,16,6,124,27,9,10,5,9,2,18, +20,4,18,32,42,25,15,23,13,40,23,25,11,6,34,49,31,16,26,49, +53,47,17,9,18,11,1,5,4,20,25,11,9,6,41,19,33,33,10,73, +25,6,13,34,13,3,54,11,17,3,46,39,27,75,36,58,58,36,6,36, +28,16,18,12,8,2,33,41,55,33,25,47,89,45,41,45,39,35,15,15, +45,57,27,8,6,10,7,39,15,21,53,31,45,45,75,71,63,57,19,9, +47,21,25,45,57,59,61,63,65,75,99,87,103,103,103,77,97,103,23,8, +5,14,22,22,122,44,40,9,60,124,112,124,36,32,16,53,101,109,121,125, +125,125,7,86,54,36,18,28,4,5,9,9,11,2,26,10,46,34,16,28, +34,40,42,22,46,38,1,36,22,3,17,31,43,95,97,79,0,0,0,0, +52,8,35,52,8,35,20,40,52,24,11,57,3,54,78,18,70,41,21,48, +13,17,70,59,57,2,25,125,125,125,40,8,9,21,48,13,27,24,70,3, +6,0,6,85,93,61,95,3,15,15,25,53,37,69,2,9,11,3,64,2, +44,0,0,0,8,65,67,20,23,11,22,1,21,62,34,10,90,86,12,34, +36,48,16,16,68,89,51,51,55,48,15,34,68,3,23,2,30,3,19,17, +35,46,23,26,0,23,14,9,1,14,24,32,36,14,31,7,6,3,0,15, +60,5,2,62,54,74,60,52,67,18,18,23,7,25,11,62,4,8,72,110, +124,124,92,69,87,20,84,84,123,17,26,69,48,11,6,70,66,108,96,90, +89,0,35,67,67,11,28,42,22,12,22,22,6,32,18,27,13,12,2,0, +23,3,17,29,5,5,2,15,17,87,21,25,11,43,41,19,4,13,19,13, +23,57,29,5,85,119,65,81,69,125,45,33,101,3,23,23,39,45,69,59, +45,83,59,57,65,85,1,22,78,50,20,8,30,18,8,0,26,38,86,56, +42,26,68,34,40,10,68,16,72,46,36,24,50,22,8,6,6,9,104,60, +22,6,40,8,13,1,34,82,72,42,20,64,28,24,8,6,124,11,4,18, +14,1,14,22,30,26,38,50,74,7,2,17,15,124,29,75,17,8,8,15, +15,13,21,2,27,65,11,9,46,13,27,11,9,1,19,17,13,53,39,19, +23,13,50,75,27,50,39,11,11,13,10,7,17,6,20,15,15,87,64,60, +62,28,7,7,11,31,13,33,43,31,67,59,63,83,75,97,125,69,51,49, +53,79,63,53,57,59,31,29,39,33,43,81,55,49,95,67,91,91,125,117, +107,107,29,23,109,45,45,59,93,69,71,77,55,65,43,35,89,99,125,49, +71,83,13,20,30,36,72,48,58,14,66,56,76,62,82,70,48,84,9,27, +43,59,59,113,111,105,32,90,80,86,68,72,42,40,22,22,13,20,30,36, +72,48,58,14,66,56,76,62,82,70,48,84,9,27,43,59,59,113,111,105, +0,0,0,0,50,8,37,50,8,37,24,42,54,24,11,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,44,0,0,0,10,65,67,20,23,13,104,12,11,35,7,37, +16,26,18,40,2,34,18,12,34,27,37,31,43,66,2,40,11,4,15,0, +34,15,33,17,19,36,9,12,3,21,12,9,12,22,12,24,40,34,37,11, +6,5,4,17,22,13,4,38,7,32,34,12,73,20,9,61,25,71,19,8, +5,14,4,4,44,8,1,22,42,17,17,6,87,33,8,63,1,27,36,2, +45,58,2,3,59,64,35,67,2,81,1,28,34,22,28,20,0,26,36,45, +13,16,6,2,31,13,21,31,15,29,49,19,23,101,53,35,65,55,51,26, +42,22,16,16,3,17,3,31,43,27,57,81,79,125,21,23,55,39,53,61, +71,77,87,97,93,125,43,91,105,73,77,2,76,54,36,14,10,3,5,15, +5,20,100,66,50,34,84,34,24,6,8,8,98,60,36,18,46,18,4,0, +1,7,66,28,14,0,24,4,7,3,14,88,52,32,20,54,22,20,16,8, +124,25,7,12,5,9,2,18,20,4,20,32,44,25,15,25,13,40,25,27, +13,4,34,51,33,16,26,49,55,49,15,7,20,11,0,5,6,20,25,9, +7,8,41,19,33,33,12,73,25,6,13,36,13,3,56,13,17,3,46,41, +27,77,34,56,58,34,4,36,28,14,16,12,6,0,35,43,57,35,27,51, +93,49,45,47,39,35,15,15,43,59,25,4,2,6,11,45,19,25,57,35, +51,49,81,75,65,57,21,11,51,25,31,49,61,63,65,67,71,79,103,91, +107,105,107,81,101,107,21,10,3,16,24,24,124,46,42,9,62,124,114,124, +38,30,14,57,107,115,125,125,125,125,5,86,54,36,18,28,4,5,9,7, +9,2,28,12,48,34,18,30,34,40,42,22,48,38,1,34,20,7,21,33, +45,101,99,81,0,0,0,0,50,8,37,50,8,37,24,42,54,24,11,59, +7,52,78,20,74,43,21,52,13,19,72,61,59,0,27,125,125,125,44,12, +9,21,52,13,25,26,72,3,8,2,8,89,95,61,97,3,15,15,25,55, +35,69,0,9,11,1,64,2,44,0,0,0,10,65,67,20,23,13,22,0, +19,66,36,12,94,90,14,36,40,50,18,16,72,91,51,51,55,50,15,36, +72,3,21,4,34,3,19,17,35,48,25,28,0,23,16,9,0,14,26,34, +38,14,31,7,6,3,0,15,60,5,2,62,54,76,62,54,67,20,20,25, +7,25,11,64,4,10,74,112,124,124,94,71,89,22,84,84,123,19,26,69, +48,13,8,72,66,108,98,92,91,2,37,73,73,7,28,42,22,10,22,20, +6,30,18,27,13,12,0,0,25,3,19,31,5,5,2,15,19,91,21,27, +11,45,41,25,0,17,21,17,27,63,33,9,89,123,67,85,73,125,47,37, +105,7,25,25,41,49,73,63,49,85,59,59,67,87,2,26,82,52,20,8, +32,18,8,2,28,40,88,58,44,26,70,36,42,12,72,16,74,48,38,24, +52,22,10,8,8,9,108,62,22,6,40,10,13,1,34,84,72,44,20,66, +28,24,10,6,124,7,8,22,18,2,16,26,32,30,42,54,78,7,4,17, +15,124,29,77,17,8,10,15,15,13,21,2,27,67,11,9,46,13,27,11, +9,1,19,17,13,55,41,19,23,13,52,77,27,52,41,11,11,13,12,7, +17,8,22,15,15,91,62,58,60,24,11,13,15,37,17,39,49,37,73,65, +67,89,81,105,125,73,57,53,57,83,67,55,59,61,31,33,43,37,47,85, +57,51,99,71,97,95,125,121,111,109,31,27,113,47,49,61,97,73,75,79, +57,67,45,33,91,103,125,51,75,85,11,22,32,36,74,50,60,14,68,58, +78,64,84,72,50,82,13,31,47,63,63,117,115,107,34,90,82,88,68,74, +44,42,24,22,11,22,32,36,74,50,60,14,68,58,78,64,84,72,50,82, +13,31,47,63,63,117,115,107,0,0,0,0,46,8,37,46,8,37,26,46, +54,24,13,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,44,0,0,0,10,67,67,22, +25,13,104,12,11,33,5,37,18,28,22,44,4,36,22,14,38,25,37,29, +41,66,2,42,9,4,15,2,38,15,33,15,17,36,9,14,1,19,14,9, +12,22,12,24,42,36,39,11,6,5,4,17,22,15,2,38,9,32,34,12, +77,20,11,65,27,73,17,10,3,16,4,6,46,10,0,24,44,17,17,6, +89,33,10,63,1,27,38,2,47,60,2,3,61,66,35,69,2,83,5,26, +32,20,26,18,1,24,36,49,15,14,6,2,33,15,23,33,17,31,51,21, +25,105,55,37,67,57,51,22,40,18,12,12,7,21,7,37,47,31,63,85, +83,125,25,27,59,43,57,65,75,81,91,103,97,125,45,95,107,75,77,2, +76,54,36,14,10,3,5,15,5,20,100,66,50,34,86,34,26,6,10,8, +100,62,36,18,46,18,6,0,0,5,68,30,14,0,26,6,5,1,14,88, +52,32,20,56,24,20,18,10,124,25,7,12,5,9,2,18,20,4,20,32, +44,25,15,25,15,42,27,29,15,2,34,55,35,16,26,51,57,49,15,5, +22,9,0,3,6,22,27,9,7,8,43,19,33,31,14,73,25,6,13,38, +13,3,58,13,19,3,48,43,27,79,32,56,56,32,2,34,26,12,14,10, +4,1,37,45,59,39,29,53,97,51,47,49,41,37,15,15,43,59,25,1, +3,2,15,51,23,29,63,39,55,53,85,79,69,59,25,15,53,29,35,53, +65,69,69,71,75,83,109,95,111,109,109,85,105,109,19,12,1,18,26,26, +124,48,44,9,64,124,118,124,40,26,10,63,113,121,125,125,125,125,5,86, +54,36,18,28,4,5,9,7,7,4,30,12,50,36,18,32,36,42,44,22, +48,38,1,32,16,11,25,37,49,105,103,83,0,0,0,0,46,8,37,46, +8,37,26,46,54,24,13,63,9,50,80,20,78,47,21,54,13,19,74,63, +63,3,31,125,125,125,48,14,9,21,54,13,25,28,72,5,10,4,10,91, +99,63,97,3,15,13,25,55,35,69,0,9,11,1,66,2,44,0,0,0, +10,67,67,22,25,13,20,0,17,70,38,14,96,92,14,38,44,52,20,18, +76,93,51,51,55,50,17,38,76,3,19,6,38,3,19,17,35,48,25,28, +2,23,16,9,0,14,26,36,38,14,31,9,6,3,0,15,60,5,2,64, +54,76,62,54,69,20,22,25,7,25,11,66,4,10,76,114,124,124,98,71, +91,22,84,84,125,19,28,71,50,13,8,74,66,108,98,94,93,6,39,79, +79,5,26,42,20,8,20,20,4,30,16,29,15,10,0,0,25,5,21,33, +7,7,0,17,19,93,23,29,11,49,43,29,3,21,25,21,31,71,39,11, +93,125,71,89,77,125,51,39,109,9,27,27,43,51,77,67,53,89,59,61, +69,91,4,28,84,52,20,8,34,20,10,4,32,42,90,58,46,28,72,38, +46,14,76,18,74,48,38,26,54,24,10,8,10,9,110,64,22,6,42,10, +13,0,36,84,74,44,20,68,30,26,10,8,124,5,10,24,22,4,20,28, +36,32,44,58,82,5,6,15,13,124,29,79,17,10,10,15,15,13,23,4, +27,69,11,9,48,13,27,11,9,1,21,17,13,57,43,19,23,13,54,79, +27,52,43,11,11,13,12,7,19,8,24,15,15,93,60,56,58,20,15,17, +21,43,23,45,57,43,81,71,71,97,89,113,125,79,61,57,61,89,71,59, +61,63,31,39,47,41,51,89,61,55,103,75,101,99,125,125,115,111,33,29, +119,51,53,65,101,75,77,81,59,69,45,31,93,105,125,53,77,87,11,22, +32,38,76,50,62,14,70,60,80,64,86,72,52,82,17,35,51,67,67,121, +119,111,34,92,82,90,70,74,44,42,24,24,11,22,32,38,76,50,62,14, +70,60,80,64,86,72,52,82,17,35,51,67,67,121,119,111,0,0,0,0, +44,8,37,44,8,37,30,48,54,24,13,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, +44,0,0,0,12,67,67,22,27,13,104,12,11,31,3,37,18,32,24,48, +8,38,24,18,42,23,35,27,41,68,2,44,7,4,13,4,42,15,33,15, +13,38,7,14,0,19,14,9,14,24,14,26,42,36,39,13,6,5,4,17, +22,15,0,38,9,32,34,10,81,20,11,67,29,75,15,12,1,18,6,8, +48,12,0,26,46,17,17,8,91,31,12,63,0,27,38,2,49,62,2,3, +65,68,37,71,2,83,7,24,32,18,24,16,3,24,36,51,17,14,6,2, +33,15,23,35,17,33,53,21,27,109,57,39,69,59,51,18,38,14,8,10, +11,27,11,41,51,35,67,91,87,125,29,29,63,49,61,69,79,87,95,109, +101,125,47,97,111,75,77,2,76,56,36,14,10,3,5,15,3,22,102,66, +50,34,88,36,28,6,12,10,102,64,36,20,48,20,6,2,2,5,72,30, +14,2,28,8,5,0,16,90,54,32,20,58,26,22,20,12,124,25,7,14, +5,9,2,18,20,6,20,34,46,25,15,25,17,42,29,31,17,2,34,57, +37,14,26,53,59,51,13,5,24,9,2,3,8,24,27,9,7,8,45,19, +33,31,16,73,25,8,13,38,13,3,60,13,19,3,50,43,29,79,30,56, +56,32,0,32,24,10,14,8,2,3,39,47,61,41,33,57,101,53,49,51, +43,37,15,13,43,61,23,5,7,1,21,55,27,33,67,43,59,57,89,83, +71,61,29,19,55,33,39,57,69,73,73,75,79,87,113,99,115,113,111,89, +109,113,17,16,0,18,28,28,124,50,46,9,66,124,120,124,40,24,6,67, +119,125,125,125,125,125,5,86,54,36,18,28,4,5,9,5,5,6,32,14, +52,38,20,34,38,44,46,24,50,40,1,28,14,13,27,41,53,109,107,85, +0,0,0,0,44,8,37,44,8,37,30,48,54,24,13,67,13,48,82,20, +80,51,19,58,15,19,76,65,65,5,35,125,125,125,52,16,9,19,58,15, +25,30,72,5,10,6,14,93,101,63,97,3,13,11,27,55,35,69,0,7, +11,0,66,2,44,0,0,0,12,67,67,22,27,13,20,2,13,76,40,16, +100,96,16,40,48,54,22,20,82,93,53,51,57,50,17,40,82,1,19,6, +42,3,19,17,33,48,25,30,4,21,18,7,0,16,28,38,40,14,33,9, +8,3,0,15,62,5,2,64,56,76,62,54,69,22,22,27,7,23,11,68, +6,12,80,118,124,124,102,73,93,24,86,84,125,19,28,71,52,13,8,78, +66,108,98,98,95,8,41,83,85,3,26,42,20,8,20,20,4,30,16,31, +17,10,0,0,25,5,21,35,7,7,0,19,21,95,25,29,11,51,43,33, +7,23,27,23,35,77,43,13,97,125,73,93,81,125,53,41,111,11,29,29, +47,55,81,71,55,91,59,63,71,95,8,32,86,54,20,8,36,22,12,4, +36,46,92,60,46,30,76,40,48,16,82,20,76,50,40,26,56,26,12,10, +12,7,112,66,22,6,44,12,11,2,38,84,76,44,20,70,32,28,12,10, +124,3,14,28,24,6,22,32,40,36,48,62,88,3,8,13,11,124,27,81, +15,12,12,15,15,13,23,4,29,71,11,9,50,13,27,11,9,0,21,19, +13,59,45,21,23,13,56,79,29,54,43,13,11,13,12,9,19,8,24,15, +15,97,58,54,56,18,21,23,27,49,27,51,63,49,87,75,75,105,95,121, +125,85,65,59,65,93,75,61,63,65,31,43,53,47,55,93,65,57,107,79, +105,103,125,125,117,115,35,31,123,53,55,67,105,77,79,83,61,71,45,29, +97,107,125,57,79,89,11,24,34,40,78,52,62,16,72,62,82,66,88,74, +52,80,21,39,55,71,71,125,123,113,36,92,84,90,72,76,46,44,24,26, +11,24,34,40,78,52,62,16,72,62,82,66,88,74,52,80,21,39,55,71, +71,125,123,113,0,0,0,0,42,8,37,42,8,37,34,52,56,24,15,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,44,0,0,0,12,67,67,24,29,13,104,12, +11,29,1,37,20,34,28,52,10,40,28,20,46,21,33,25,39,70,2,46, +5,4,13,4,46,15,31,13,11,38,7,16,4,17,16,9,14,24,14,28, +44,38,41,13,6,5,4,17,22,17,0,38,11,32,34,10,85,20,13,71, +31,77,13,14,0,20,8,8,50,12,2,28,48,17,17,8,93,31,14,63, +0,27,40,2,51,64,2,3,67,70,37,73,2,85,11,22,30,16,22,14, +3,22,34,53,19,14,6,2,35,17,25,37,19,35,55,23,27,113,59,39, +71,61,51,16,34,12,4,6,15,31,15,47,57,39,73,95,93,125,33,33, +65,53,65,75,85,91,101,113,105,125,49,101,113,77,77,2,78,56,36,14, +10,3,5,15,3,22,102,66,50,34,90,36,28,8,12,12,104,64,38,20, +50,20,8,2,4,3,74,32,16,2,30,10,3,2,16,90,54,32,20,60, +26,24,22,14,124,23,5,14,5,9,2,18,20,6,20,34,46,25,15,25, +17,44,31,33,19,0,34,59,39,14,26,53,61,51,11,3,26,7,2,1, +8,26,27,9,7,10,45,19,33,29,18,73,25,8,13,40,13,3,62,13, +19,3,52,45,29,81,28,54,54,30,1,30,22,8,12,6,0,5,41,49, +63,45,35,59,105,57,51,53,43,39,15,13,43,61,21,9,11,5,25,61, +31,37,73,47,63,61,95,87,75,63,33,21,59,37,43,61,73,77,77,79, +83,91,119,103,119,117,113,93,113,115,15,18,2,20,30,30,124,52,48,9, +68,124,124,124,42,20,4,73,125,125,125,125,125,125,5,86,54,36,18,28, +4,5,9,5,3,8,34,16,54,38,20,36,38,44,46,24,50,40,1,26, +10,17,31,45,57,113,111,87,0,0,0,0,42,8,37,42,8,37,34,52, +56,24,15,71,15,46,82,20,84,53,19,60,15,21,78,67,67,7,39,125, +125,125,56,20,9,19,60,15,23,32,74,5,12,8,16,95,103,63,99,3, +13,9,27,57,35,69,0,7,11,2,68,2,44,0,0,0,12,67,67,24, +29,13,18,2,11,80,42,18,102,98,18,42,52,56,24,22,86,95,53,51, +57,52,17,42,86,1,17,8,46,3,19,17,33,50,25,30,6,21,20,7, +0,16,28,40,40,14,33,9,8,3,0,15,62,5,2,66,56,78,62,56, +71,22,24,27,7,23,11,70,6,12,82,120,124,124,106,73,95,24,86,84, +125,19,30,73,52,13,8,80,66,108,98,100,97,12,43,89,91,0,26,42, +18,6,18,18,2,30,14,33,19,10,0,0,27,7,23,37,9,7,0,21, +21,97,25,31,11,53,45,37,11,27,31,27,39,83,49,15,101,125,77,97, +85,125,55,43,115,13,31,31,49,57,85,75,59,95,59,65,73,97,10,34, +90,54,20,8,38,24,14,6,40,48,94,62,48,30,78,42,52,18,86,20, +76,50,40,28,58,26,12,12,14,7,116,68,22,6,46,12,11,4,40,86, +78,46,20,72,32,30,12,10,124,0,16,30,28,8,26,34,42,38,52,66, +92,3,10,13,9,124,27,83,15,14,14,15,15,13,23,6,29,73,11,9, +50,13,27,11,9,0,23,19,13,61,47,21,23,13,58,81,29,56,45,13, +11,13,14,9,21,10,26,15,15,99,56,52,54,14,25,27,31,55,33,57, +69,55,93,81,79,113,103,125,125,91,69,63,69,99,79,63,65,67,31,47, +57,51,59,97,69,61,111,83,109,107,125,125,121,117,37,33,125,57,59,71, +109,81,83,85,63,73,45,27,99,111,125,59,81,91,11,24,34,40,80,54, +64,16,74,64,84,66,90,74,54,80,25,43,59,75,75,125,125,115,36,94, +84,92,72,78,46,44,26,26,11,24,34,40,80,54,64,16,74,64,84,66, +90,74,54,80,25,43,59,75,75,125,125,115,0,0,0,0,40,8,37,40, +8,37,38,54,56,24,15,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,44,0,0,0, +14,67,67,24,31,13,104,12,11,27,0,37,20,36,32,56,14,42,32,22, +50,19,31,23,37,72,2,48,3,4,11,6,50,15,31,13,9,38,7,16, +6,17,18,9,14,24,14,30,44,38,41,13,6,5,4,17,22,17,1,38, +13,32,34,10,89,20,13,75,33,79,11,16,2,22,10,10,52,14,2,30, +50,17,17,8,95,29,16,63,0,27,42,2,53,66,2,3,69,72,39,75, +2,87,13,20,30,14,20,12,5,20,34,55,21,14,6,2,35,19,27,39, +21,37,57,25,29,117,61,41,73,63,51,12,32,8,0,2,19,35,19,51, +61,43,77,101,97,125,37,37,69,57,69,79,89,95,105,119,109,125,51,105, +115,79,77,2,78,56,36,14,10,3,5,15,1,22,102,66,50,34,92,38, +30,8,14,14,106,66,38,20,52,22,8,4,6,1,76,34,16,2,32,12, +1,4,18,90,54,32,20,62,28,26,24,16,124,23,5,16,5,9,2,18, +20,6,20,34,48,25,15,25,19,44,33,35,21,1,34,61,41,14,26,55, +63,53,9,1,28,7,4,1,10,28,27,9,7,10,47,19,33,29,20,73, +25,8,13,42,13,3,64,13,19,3,54,47,29,83,26,54,54,28,3,28, +20,6,10,4,1,7,43,51,65,47,37,63,109,59,53,55,45,39,15,13, +43,63,19,13,15,9,29,67,35,41,77,51,67,65,99,91,77,65,37,25, +61,41,47,65,77,81,81,83,87,95,123,107,123,121,115,97,117,119,13,20, +4,22,32,32,124,54,50,9,70,124,124,124,44,18,0,77,125,125,125,125, +125,125,5,86,54,36,18,28,4,5,9,3,1,10,36,18,56,40,22,38, +40,46,48,24,52,40,1,24,8,21,35,49,61,117,115,89,0,0,0,0, +40,8,37,40,8,37,38,54,56,24,15,75,19,44,84,20,88,57,19,64, +15,21,80,69,69,9,43,125,125,125,60,22,9,19,64,15,23,34,74,5, +14,10,18,97,105,63,99,3,13,7,27,57,35,69,0,7,11,4,68,2, +44,0,0,0,14,67,67,24,31,13,18,4,9,84,44,20,106,102,20,44, +56,58,26,24,90,97,53,51,57,52,17,44,90,1,15,10,50,3,19,17, +33,50,25,32,8,21,22,7,0,16,30,42,42,14,33,9,8,3,0,15, +62,5,2,66,56,78,62,56,71,24,26,29,7,23,11,72,6,14,84,122, +124,124,110,75,97,26,86,84,125,19,30,73,54,13,8,82,66,108,98,102, +99,14,45,95,97,2,26,42,18,4,18,18,2,30,14,35,21,10,0,0, +27,7,25,39,9,7,0,23,23,99,27,33,11,55,45,41,15,31,33,31, +43,89,53,17,105,125,79,101,89,125,57,45,119,15,33,33,51,61,89,79, +63,97,59,67,75,101,14,38,92,56,20,8,40,26,16,8,44,50,96,64, +50,32,80,44,54,20,90,22,78,52,42,28,60,28,14,14,16,7,118,70, +22,6,48,14,11,6,42,86,80,46,20,74,34,32,14,12,124,2,20,34, +32,10,28,38,46,42,56,70,96,1,12,11,7,124,27,85,15,16,16,15, +15,13,23,6,29,75,11,9,52,13,27,11,9,0,23,19,13,63,49,21, +23,13,60,83,29,58,47,13,11,13,14,9,21,10,28,15,15,103,54,50, +52,10,29,33,37,61,37,63,75,61,99,87,83,121,109,125,125,97,73,67, +73,103,83,65,67,69,31,51,61,55,63,101,73,63,115,87,113,111,125,125, +125,119,39,35,125,59,63,73,113,83,85,87,65,75,45,25,101,113,125,61, +83,93,11,26,36,42,82,56,66,16,76,66,86,68,92,76,56,78,29,47, +63,79,79,125,125,117,38,94,86,94,74,80,48,46,26,28,11,26,36,42, +82,56,66,16,76,66,86,68,92,76,56,78,29,47,63,79,79,125,125,117, +0,0,0,0,36,6,39,36,6,39,40,56,56,24,17,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,44,0,0,0,14,69,67,24,33,15,104,10,11,25,0,37, +20,38,34,58,16,44,34,24,52,17,31,21,37,72,2,48,3,4,11,6, +52,15,31,13,7,38,7,16,8,17,18,9,14,24,14,30,44,38,43,15, +6,7,4,17,20,19,3,38,15,30,34,8,93,18,15,79,35,81,11,16, +2,22,10,10,54,14,2,30,52,19,17,8,99,29,16,63,0,29,42,2, +55,66,2,3,73,72,41,77,2,89,17,18,28,12,18,10,7,18,32,59, +23,12,4,2,37,21,29,41,23,39,59,27,31,121,65,43,77,67,51,8, +28,4,3,1,25,41,25,57,67,49,83,107,103,125,41,41,73,63,75,85, +95,101,111,125,115,125,53,109,119,81,79,2,78,56,36,14,10,5,5,15, +1,22,102,66,50,34,94,38,30,8,14,14,106,66,38,20,52,22,8,4, +8,1,78,34,16,2,32,12,1,6,18,90,54,32,20,62,28,26,24,16, +124,23,5,16,5,9,2,18,20,6,20,34,48,25,15,27,21,44,35,37, +23,3,32,65,45,12,24,57,67,55,9,1,30,7,4,1,10,28,29,9, +7,10,49,19,33,29,20,75,25,8,13,42,15,3,64,15,21,3,54,49, +31,85,24,52,52,26,7,26,18,4,8,2,3,9,45,55,69,51,41,67, +113,63,57,57,47,41,15,13,43,65,19,19,21,13,35,73,41,47,83,57, +73,71,105,97,81,67,41,29,65,45,53,71,83,87,87,87,93,101,125,111, +125,125,119,101,121,123,11,22,6,22,32,32,124,54,50,9,70,124,124,124, +44,14,3,83,125,125,125,125,125,125,5,86,52,34,18,28,4,7,9,3, +1,10,36,18,58,40,22,38,40,46,48,24,52,40,3,20,4,25,39,53, +65,123,119,91,0,0,0,0,36,6,39,36,6,39,40,56,56,24,17,79, +23,42,84,20,90,61,19,66,17,23,82,71,73,13,47,125,125,125,64,24, +9,19,66,17,23,34,74,7,14,10,20,101,109,65,101,5,13,7,29,59, +35,69,1,7,11,4,68,0,44,0,0,0,14,69,67,24,33,15,16,4, +7,88,46,20,108,104,20,46,58,58,28,24,94,99,55,53,59,52,19,44, +94,1,15,10,52,3,19,17,33,50,27,32,8,21,22,7,0,16,30,44, +42,14,35,11,8,3,1,15,62,5,2,66,56,78,62,56,73,24,26,31, +7,23,13,72,6,14,86,124,124,124,112,77,101,26,86,84,125,21,30,75, +54,15,8,84,66,106,98,104,101,16,49,101,105,4,24,42,16,2,16,16, +0,28,12,37,23,8,1,1,29,9,27,41,11,9,1,25,25,103,29,35, +11,59,47,47,21,35,37,35,49,97,59,21,109,125,83,107,93,125,61,49, +123,19,35,35,55,65,93,83,67,101,59,69,77,105,16,40,94,56,20,8, +40,26,16,8,46,52,96,64,50,32,82,46,56,20,94,22,78,52,42,28, +60,28,14,14,18,7,120,72,22,4,48,14,11,6,42,86,80,46,20,76, +34,32,14,12,124,4,22,36,34,12,30,40,48,44,58,72,100,1,12,11, +7,124,27,89,15,16,16,15,15,13,25,6,31,77,13,9,52,15,27,13, +9,0,25,21,15,65,51,23,25,13,62,85,31,58,49,15,11,15,14,11, +23,10,28,15,15,107,50,48,48,6,35,39,43,67,43,69,83,67,107,93, +87,125,117,125,125,103,79,71,79,109,87,69,71,71,31,57,67,61,67,107, +77,67,121,91,119,115,125,125,125,123,43,39,125,63,67,77,117,87,89,89, +67,77,47,23,105,117,125,65,87,97,11,26,36,42,84,56,66,16,78,66, +88,68,92,76,56,76,33,51,69,85,83,125,125,121,38,94,86,94,74,80, +48,46,26,28,11,26,36,42,84,56,66,16,78,66,88,68,92,76,56,76, +33,51,69,85,83,125,125,121,0,0,0,0,34,6,39,34,6,39,44,60, +58,26,17,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,44,0,0,0,16,69,67,26, +33,15,104,10,11,21,2,37,22,42,38,62,20,48,38,28,56,13,29,19, +35,74,4,50,1,6,9,8,56,13,29,11,3,40,5,18,12,15,20,7, +16,26,16,32,46,40,43,15,8,7,4,15,20,19,3,38,15,30,34,8, +95,18,15,81,37,81,9,18,4,24,12,12,56,16,4,32,56,19,17,10, +101,27,18,63,2,29,44,4,55,68,2,3,75,74,41,79,2,89,19,18, +28,12,18,10,7,18,32,61,23,12,4,2,37,21,29,41,23,39,61,27, +31,123,67,43,79,69,51,6,26,2,5,3,29,45,29,61,71,53,87,111, +107,125,43,43,75,67,79,89,99,105,115,125,119,125,53,111,121,81,79,4, +80,58,38,16,10,5,3,13,0,24,104,68,52,34,96,40,32,10,16,16, +108,68,40,22,54,24,10,6,12,0,82,36,18,4,34,14,0,10,20,92, +56,34,22,64,30,28,26,18,124,21,3,18,5,7,2,20,22,8,22,36, +50,23,15,27,21,46,35,37,25,3,32,67,47,12,24,57,69,55,7,0, +32,5,6,0,12,30,29,7,5,12,49,17,31,27,22,75,25,10,13,44, +15,3,66,15,21,1,56,49,31,85,24,52,52,26,9,26,18,4,8,2, +3,9,45,57,71,53,43,69,115,65,59,57,47,41,13,11,41,65,17,23, +25,17,39,77,45,51,87,61,77,75,109,101,83,67,43,31,67,47,57,75, +87,91,91,91,97,105,125,113,125,125,121,103,123,125,7,26,10,24,34,34, +124,56,52,9,72,124,124,124,46,12,5,87,125,125,125,125,125,125,3,88, +52,34,18,30,4,7,9,1,0,12,38,20,62,42,24,40,42,48,50,26, +54,42,3,18,2,27,41,55,67,125,121,91,0,0,0,0,34,6,39,34, +6,39,44,60,58,26,17,81,25,42,86,22,94,63,17,70,17,23,86,71, +75,15,49,125,125,125,68,28,7,17,70,17,21,36,76,7,16,12,24,103, +111,65,101,5,11,5,29,59,33,67,1,5,9,6,70,0,44,0,0,0, +16,69,67,26,33,15,16,6,3,94,50,22,112,108,22,50,62,60,32,26, +100,99,55,53,59,54,19,46,100,0,13,12,56,3,17,17,31,52,27,34, +10,19,24,5,2,18,32,46,44,16,35,11,10,1,1,13,64,3,2,68, +58,80,64,58,73,26,28,31,7,21,13,74,8,16,90,124,124,124,116,77, +103,28,88,86,125,21,32,75,56,15,10,88,66,106,100,108,103,20,51,105, +111,8,24,42,16,2,16,16,0,28,12,37,23,8,1,1,29,9,27,41, +11,9,1,25,25,105,29,35,11,61,47,51,25,37,39,37,53,103,63,23, +111,125,85,111,95,125,63,51,125,21,35,35,57,67,95,85,69,103,59,69, +77,107,20,44,98,58,20,8,42,28,18,10,50,56,98,66,52,34,86,48, +60,22,100,24,80,54,44,30,62,30,16,16,22,5,124,74,24,4,50,16, +9,8,44,88,82,48,22,78,36,34,16,14,124,8,26,40,38,16,34,44, +52,48,62,76,106,0,14,9,5,124,25,91,13,18,18,13,15,11,25,8, +31,77,13,9,54,15,27,13,9,2,25,21,15,65,51,23,25,11,66,85, +31,60,49,15,11,15,16,11,23,12,30,13,13,109,48,46,46,4,39,43, +47,73,47,73,89,71,113,97,91,125,123,125,125,107,83,73,83,113,89,71, +73,71,31,61,71,65,71,111,79,69,125,93,123,117,125,125,125,125,45,41, +125,65,69,79,119,89,91,91,67,77,47,21,107,119,125,67,89,99,9,28, +38,44,88,58,68,18,82,68,90,70,94,78,58,76,35,53,73,89,85,125, +125,123,40,96,88,96,76,82,50,48,28,30,9,28,38,44,88,58,68,18, +82,68,90,70,94,78,58,76,35,53,73,89,85,125,125,123,0,0,0,0, +32,6,39,32,6,39,48,62,58,26,17,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, +44,0,0,0,18,69,67,26,35,15,104,10,11,19,4,37,22,44,42,66, +22,50,42,30,60,11,27,17,33,76,4,52,0,6,9,10,60,13,29,11, +1,40,5,18,14,15,22,7,16,26,16,34,46,40,45,15,8,7,4,15, +20,19,5,38,17,30,34,8,99,18,15,85,39,83,7,20,6,26,14,14, +58,18,4,34,58,19,17,10,103,27,20,63,2,29,46,4,57,70,2,3, +77,76,43,81,2,91,23,16,26,10,16,8,9,16,32,63,25,12,4,2, +37,23,31,43,25,41,63,29,33,125,69,45,81,71,51,2,24,1,9,7, +33,49,33,67,75,57,93,117,111,125,47,47,79,71,83,93,103,109,119,125, +123,125,55,115,123,83,79,4,80,58,38,16,10,5,3,13,2,24,104,68, +52,34,98,40,34,10,18,18,110,70,40,22,56,24,10,8,14,2,84,38, +18,4,36,16,2,12,20,92,56,34,22,66,32,30,28,20,124,21,3,18, +5,7,2,20,22,8,22,36,52,23,15,27,23,46,37,39,27,5,32,69, +49,12,24,59,71,57,5,2,34,5,6,0,14,32,29,7,5,12,51,17, +31,27,24,75,25,10,13,46,15,3,68,15,21,1,58,51,31,87,22,52, +52,24,11,24,16,2,6,0,5,11,47,59,73,57,45,73,119,67,61,59, +49,41,13,11,41,67,15,27,29,21,43,83,49,55,93,65,81,79,113,105, +85,69,47,35,69,51,61,79,91,95,95,95,101,109,125,117,125,125,123,107, +125,125,5,28,12,26,36,36,124,58,54,9,74,124,124,124,48,10,9,93, +125,125,125,125,125,125,3,88,52,34,18,30,4,7,9,0,2,14,40,22, +64,44,26,42,44,50,52,26,56,42,3,16,1,31,45,59,71,125,125,93, +0,0,0,0,32,6,39,32,6,39,48,62,58,26,17,85,29,40,88,22, +98,67,17,72,17,23,88,73,77,17,53,125,125,125,72,30,7,17,72,17, +21,38,76,7,18,14,26,105,113,65,101,5,11,3,29,59,33,67,1,5, +9,8,70,0,44,0,0,0,18,69,67,26,35,15,16,8,1,98,52,24, +116,112,24,52,66,62,34,28,104,101,55,53,59,54,19,48,104,0,11,14, +60,3,17,17,31,52,27,34,12,19,26,5,2,18,32,48,46,16,35,11, +10,1,1,13,64,3,2,68,58,80,64,58,75,28,30,33,7,21,13,76, +8,16,92,124,124,124,120,79,105,28,88,86,125,21,32,77,58,15,10,90, +66,106,100,110,105,22,53,111,117,10,24,42,16,0,14,16,0,28,10,39, +25,8,1,1,29,11,29,43,11,9,1,27,27,107,31,37,11,63,49,55, +29,41,43,41,57,109,67,25,115,125,89,115,99,125,65,53,125,23,37,37, +59,71,99,89,73,107,59,71,79,111,22,46,100,60,20,8,44,30,20,12, +54,58,100,68,54,36,88,50,62,24,104,26,80,54,44,30,64,32,18,18, +24,5,124,76,24,4,52,18,9,10,46,88,84,48,22,80,38,36,18,16, +124,10,30,44,42,18,36,48,56,50,66,80,110,2,16,7,3,124,25,93, +13,20,20,13,15,11,25,8,31,79,13,9,56,15,27,13,9,2,25,21, +15,67,53,23,25,11,68,87,31,62,51,15,11,15,16,11,23,12,32,13, +13,113,46,44,44,0,43,49,53,79,51,79,95,77,119,103,95,125,125,125, +125,113,87,77,87,117,93,73,75,73,31,65,75,69,75,115,83,73,125,97, +125,121,125,125,125,125,47,43,125,69,73,83,123,91,93,93,69,79,47,19, +109,121,125,69,91,101,9,28,40,46,90,60,70,18,84,70,92,70,96,80, +60,74,39,57,77,93,89,125,125,125,42,96,88,98,78,84,50,50,28,32, +9,28,40,46,90,60,70,18,84,70,92,70,96,80,60,74,39,57,77,93, +89,125,125,125,0,0,0,0,30,6,39,30,6,39,52,66,60,26,19,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,44,0,0,0,18,69,67,28,37,15,104,10, +11,17,6,37,24,46,46,70,26,52,46,32,64,9,25,15,31,78,4,54, +2,6,7,10,64,13,27,9,0,40,5,20,18,13,24,7,16,26,16,36, +48,42,45,15,8,7,4,15,20,21,5,38,19,30,34,8,103,18,17,89, +41,85,5,22,8,28,16,14,60,18,6,36,60,19,17,10,105,25,22,63, +2,29,48,4,59,72,2,3,79,78,43,83,2,93,25,14,26,8,14,6, +9,14,30,65,27,12,4,2,39,25,33,45,27,43,65,31,33,125,71,45, +83,73,51,0,20,3,13,11,37,53,37,71,81,61,97,121,117,125,51,51, +81,75,87,99,109,113,125,125,125,125,57,119,125,85,79,4,82,58,38,16, +10,5,3,13,2,24,104,68,52,34,100,42,34,12,18,20,112,70,42,22, +58,26,12,8,16,4,86,40,20,4,38,18,4,14,22,92,56,34,22,68, +32,32,30,22,124,19,1,20,5,7,2,20,22,8,22,36,52,23,15,27, +23,48,39,41,29,7,32,71,51,12,24,59,73,57,3,4,36,3,8,2, +14,34,29,7,5,14,51,17,31,25,26,75,25,10,13,48,15,3,70,15, +21,1,60,53,31,89,20,50,50,22,13,22,14,0,4,1,7,13,49,61, +75,59,47,75,123,71,63,61,49,43,13,11,41,67,13,31,33,25,47,89, +53,59,97,69,85,83,119,109,89,71,51,37,73,55,65,83,95,99,99,99, +105,113,125,121,125,125,125,111,125,125,3,30,14,28,38,38,124,60,56,9, +76,124,124,124,50,6,11,97,125,125,125,125,125,125,3,88,52,34,18,30, +4,7,9,0,4,16,42,24,66,44,26,44,44,50,52,26,56,42,3,14, +3,35,49,63,75,125,125,95,0,0,0,0,30,6,39,30,6,39,52,66, +60,26,19,89,31,38,88,22,102,69,17,76,17,25,90,75,79,19,57,125, +125,125,76,34,7,17,76,17,19,40,78,7,20,16,28,107,115,65,103,5, +11,1,29,61,33,67,1,5,9,10,72,0,44,0,0,0,18,69,67,28, +37,15,14,8,0,102,54,26,118,114,26,54,70,64,36,30,108,103,55,53, +59,56,19,50,108,0,9,16,64,3,17,17,31,54,27,36,14,19,28,5, +2,18,34,50,46,16,35,11,10,1,1,13,64,3,2,70,58,82,64,60, +75,28,32,33,7,21,13,78,8,18,94,124,124,124,124,79,107,30,88,86, +125,21,34,77,58,15,10,92,66,106,100,112,107,26,55,117,123,14,24,42, +14,1,14,14,1,28,10,41,27,8,1,1,31,11,31,45,13,9,1,29, +27,109,31,39,11,65,49,59,33,45,45,45,61,115,73,27,119,125,91,119, +103,125,67,55,125,25,39,39,61,73,103,93,77,109,59,73,81,113,26,50, +104,60,20,8,46,32,22,14,58,60,102,70,56,36,90,52,66,26,108,26, +82,56,46,32,66,32,18,20,26,5,124,78,24,4,54,18,9,12,48,90, +86,50,22,82,38,38,18,16,124,14,32,46,46,20,40,50,58,54,70,84, +114,2,18,7,1,124,25,95,13,22,22,13,15,11,25,10,31,81,13,9, +56,15,27,13,9,2,27,21,15,69,55,23,25,11,70,89,31,64,53,15, +11,15,18,11,25,14,34,13,13,115,44,42,42,3,47,53,57,85,57,85, +101,83,125,109,99,125,125,125,125,119,91,81,91,123,97,75,77,75,31,69, +79,73,79,119,87,75,125,101,125,125,125,125,125,125,49,45,125,71,77,85, +125,95,97,95,71,81,47,17,111,125,125,71,93,103,9,30,40,46,92,62, +72,18,86,72,94,72,98,80,62,74,43,61,81,97,93,125,125,125,42,98, +90,100,78,86,52,50,30,32,9,30,40,46,92,62,72,18,86,72,94,72, +98,80,62,74,43,61,81,97,93,125,125,125,0,0,0,0} +}; + +#endif + + +#endif /* __H264CABACCONTEXT_H__ */ diff --git a/lib/vc8000nanoe/source/h264/H264CodeFrame.c b/lib/vc8000nanoe/source/h264/H264CodeFrame.c new file mode 100644 index 000000000..2875608ee --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264CodeFrame.c @@ -0,0 +1,894 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encode picture + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "enccommon.h" +#include "ewl.h" +#include "H264CodeFrame.h" + +#ifdef INTERNAL_TEST +#include "H264TestId.h" +#endif + +/*------------------------------------------------------------------------------ + 2. External compiler flags +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Module defines +------------------------------------------------------------------------------*/ + +/* H.264 intra mode selection favors */ +static const u32 h264Intra16Favor[52] = { + 24, 24, 24, 26, 27, 30, 32, 35, 39, 43, 48, 53, 58, 64, 71, 78, + 85, 93, 102, 111, 121, 131, 142, 154, 167, 180, 195, 211, 229, + 248, 271, 296, 326, 361, 404, 457, 523, 607, 714, 852, 1034, + 1272, 1588, 2008, 2568, 3318, 4323, 5672, 7486, 9928, 13216, + 17648 +}; + +static const u32 h264PrevModeFavor[52] = { + 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, + 49, 51, 55, 58, 61, 65, 69, 73, 78, 82, 87, 93, 98, 104, 110, + 117, 124, 132, 140 +}; + +/* H.264 motion estimation parameters */ +static const u32 h264InterFavor[52] = { + 4, 4, 5, 6, 6, 7, 8, 9, 10, 12, 13, 15, 17, 19, + 21, 24, 26, 30, 34, 38, 42, 48, 53, 60, 68, 76, 85, 96, + 107, 121, 136, 152, 171, 192, 215, 242, 272, 305, 342, 384, 431, 484, + 544, 610, 685, 769, 863, 969, 1088, 1221, 1370, 1538 +}; + +/* Favor value for web cam use case, 1.3x larger +static const u32 h264InterFavorWebCam[52] = { + 52, 52, 53, 54, 55, 57, 58, 62, 66, 68, + 71, 78, 80, 87, 89, 93, 101, 109, 117, 124, + 143, 156, 175, 197, 221, 245, 273, 305, 344, 386, + 435, 488, 546, 611, 678, 743, 806, 871, 941, 1001, + 1066, 1127, 1189, 1261, 1326, 1398, 1471, 1534, 1599, 1657, + 1716, 1781 +};*/ + +/* Penalty factor in 1/256 units for skip mode */ +static const u32 h264SkipSadPenalty[52] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 240, 224, 208, 192, 176, 160, 144, 128, 112, + 96, 80, 64, 60, 56, 52, 48, 44, 40, 36, + 32, 28, 24, 20, 18, 16, 16, 15, 15, 14, + 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, + 9, 8 +}; + +/* sqrt(2^((qp-12)/3))*8 */ +static const u32 h264DiffMvPenalty[52] = + { 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, + 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, + 20, 23, 26, 29, 32, 36, 40, 45, 51, 57, + 64, 72, 81, 91, 102, 114, 128, 144, 161, 181, + 203, 228, 256, 287, 323, 362, 406, 456, 512, 575, + 645, 724 +}; + +/* 31*sqrt(2^((qp-12)/3))/4 */ +static const u32 h264DiffMvPenalty4p[52] = + { 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, + 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, + 20, 22, 25, 28, 31, 35, 39, 44, 49, 55, + 62, 70, 78, 88, 98, 110, 124, 139, 156, 175, + 197, 221, 248, 278, 312, 351, 394, 442, 496, 557, + 625, 701 +}; + +static const i32 h264DmvPenalty[128] = /* 4*sqrt(i*4*6) */ + { 0, 19, 27, 33, 39, 43, 48, 51, 55, 58, + 61, 64, 67, 70, 73, 75, 78, 80, 83, 85, + 87, 89, 91, 93, 96, 97, 99, 101, 103, 105, + 107, 109, 110, 112, 114, 115, 117, 119, 120, 122, + 123, 125, 126, 128, 129, 131, 132, 134, 135, 137, + 138, 139, 141, 142, 144, 145, 146, 147, 149, 150, + 151, 153, 154, 155, 156, 157, 159, 160, 161, 162, + 163, 165, 166, 167, 168, 169, 170, 171, 173, 174, + 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 192, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 219, 220 + }; + + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ +static void H264SetNewFrame(h264Instance_s * inst); +static void SetSegmentMap(h264Instance_s *inst); +static i32 ExpGolombSigned(i32 val); +static void EncSwap32(u32 * buf, u32 sizeBytes); +static i32 float2fixpoint8(float data); + +/*------------------------------------------------------------------------------ + + float2fixpoint8 + +------------------------------------------------------------------------------*/ +static i32 float2fixpoint8(float data) +{ + i32 i = 0; + i32 result = 0; + float pow2=2.0; + /*0.16 format*/ + float base = 0.5; + for(i= 0; i<8 ;i++) + { + result <<= 1; + if(data >= base) + { + result |= 1; + data -= base; + + } + + pow2 *= 2; + base = 1.0/pow2; + + } + return result; + +} + +/*------------------------------------------------------------------------------ + + H264CodeFrame + +------------------------------------------------------------------------------*/ +h264EncodeFrame_e H264CodeFrame(h264Instance_s * inst) +{ + asicData_s *asic = &inst->asic; + h264EncodeFrame_e ret; + i32 status = ASIC_STATUS_ERROR, go_on; + H264EncSliceReady slice; + + /* Reset callback struct */ + slice.slicesReadyPrev = 0; + slice.slicesReady = 0; + slice.sliceSizes = (u32 *) inst->asic.sizeTbl.virtualAddress; + slice.sliceSizes += inst->naluOffset; + slice.pOutBuf = inst->pOutBuf; + slice.pAppData = inst->pAppData; + + H264SetNewFrame(inst); + +#ifdef INTERNAL_TEST + /* Configure the ASIC penalties according to the test vector */ + H264ConfigureTestPenalties(inst); +#endif + + EncAsicFrameStart(inst->asic.ewl, &inst->asic.regs); + + do { + /* Encode one frame */ + i32 ewl_ret; + + /* Wait for IRQ for every slice or for complete frame */ + if ((inst->slice.sliceSize > 0) && inst->sliceReadyCbFunc) + ewl_ret = EWLWaitHwRdy(asic->ewl, &slice.slicesReady); + else + ewl_ret = EWLWaitHwRdy(asic->ewl, NULL); + + if(ewl_ret != EWL_OK) + { + status = ASIC_STATUS_ERROR; + + if(ewl_ret == EWL_ERROR) + { + /* IRQ error => Stop and release HW */ + ret = H264ENCODE_SYSTEM_ERROR; + } + else /*if(ewl_ret == EWL_HW_WAIT_TIMEOUT) */ + { + /* IRQ Timeout => Stop and release HW */ + ret = H264ENCODE_TIMEOUT; + } + + EncAsicStop(asic->ewl); + /* Release HW so that it can be used by other codecs */ + EWLReleaseHw(asic->ewl); + + } + else + { + /* Check ASIC status bits and possibly release HW */ + status = EncAsicCheckStatus_V2(asic); + + switch (status) + { + case ASIC_STATUS_ERROR: + ret = H264ENCODE_HW_ERROR; + break; + case ASIC_STATUS_HW_TIMEOUT: + ret = H264ENCODE_TIMEOUT; + break; + case ASIC_STATUS_SLICE_READY: + ret = H264ENCODE_OK; + break; + case ASIC_STATUS_BUFF_FULL: + ret = H264ENCODE_OK; + inst->stream.overflow = ENCHW_YES; + break; + case ASIC_STATUS_HW_RESET: + ret = H264ENCODE_HW_RESET; + break; + case ASIC_STATUS_FUSE: + ret = H264ENCODE_FUSE_ERROR; + break; + case ASIC_STATUS_FRAME_READY: + { + /* Stream header remainder ie. last not full 64-bit address + * is counted in HW data. */ + const u32 hw_offset = inst->stream.byteCnt & (0x07U); + + inst->stream.byteCnt += + asic->regs.outputStrmSize - hw_offset; + inst->stream.stream += + asic->regs.outputStrmSize - hw_offset; + + ret = H264ENCODE_OK; + break; + } + case ASIC_STATUS_LINE_BUFFER_DONE: + ret = H264ENCODE_OK; + /* SW handshaking: the callback function should wait until enough mb rows has been + * feed into the input buffer and then update the input write pointer to make + * the encoder continue to run. */ + if (!inst->inputLineBuf.inputLineBufHwModeEn) + { + if (inst->inputLineBuf.cbFunc) + inst->inputLineBuf.cbFunc(inst->pAppData); + } + break; + case ASIC_STATUS_RFC_BUFF_OVERFLOW: + /* when current frame is finished, the software force the slice type to I slice + * in next frame, and set a bigger QP */ + inst->rfcBufOverflow = ENCHW_YES; + ret = H264ENCODE_OK; + break; + default: + /* should never get here */ + ASSERT(0); + ret = H264ENCODE_HW_ERROR; + } + + /* double check ASIC_STATUS_RFC_BUFF_OVERFLOW */ + if (asic->irqStatus & ASIC_STATUS_RFC_BUFF_OVERFLOW) + inst->rfcBufOverflow = ENCHW_YES; + + go_on = (status == ASIC_STATUS_SLICE_READY) || + (status == ASIC_STATUS_LINE_BUFFER_DONE) || + (status == ASIC_STATUS_RFC_BUFF_OVERFLOW); + + /* Issue callback to application telling how many slices are available. */ + if (go_on && (slice.slicesReadyPrev < slice.slicesReady)) + { + if (inst->sliceReadyCbFunc) + inst->sliceReadyCbFunc(&slice); + slice.slicesReadyPrev = slice.slicesReady; + } + } + } while (go_on); + + /* Don't update map for next frame unless it is modified. */ + inst->asic.regs.segmentMapUpdate = 0; + + return ret; +} + +/*------------------------------------------------------------------------------ + + Set encoding parameters at the beginning of a new frame. + +------------------------------------------------------------------------------*/ +void H264SetNewFrame(h264Instance_s * inst) +{ + asicData_s *asic = &inst->asic; + regValues_s *regs = &inst->asic.regs; + i32 qpHdr, qpMin, qpMax; + i32 qp[4]; + i32 s,lamdaIdx, i, aroiDeltaQ = 0, tmp, qpAddr; + i32 qpDeltaGain; + float strength = 1.6f; + float qpDeltaGainFloat; + + regs->outputStrmSize -= inst->stream.byteCnt; + regs->outputStrmSize /= 8; /* 64-bit addresses */ + regs->outputStrmSize &= (~0x07); /* 8 multiple size */ + + /* 64-bit aligned stream base address */ + regs->outputStrmBase += (inst->stream.byteCnt & (~0x07)); + + /* bit offset in the last 64-bit word */ + regs->firstFreeBit = (inst->stream.byteCnt & 0x07) * 8; + + /* header remainder is byte aligned, max 7 bytes = 56 bits */ + if(regs->firstFreeBit != 0) + { + /* 64-bit aligned stream pointer */ + u8 *pTmp = (u8 *) ((ptr_t) (inst->stream.stream) & (ptr_t) (~0x07)); + u32 val; + + /* Clear remaining bits */ + for (val = 6; val >= regs->firstFreeBit/8; val--) + pTmp[val] = 0; + + val = pTmp[0] << 24; + val |= pTmp[1] << 16; + val |= pTmp[2] << 8; + val |= pTmp[3]; + + regs->strmStartMSB = val; /* 32 bits to MSB */ + + if(regs->firstFreeBit > 32) + { + val = pTmp[4] << 24; + val |= pTmp[5] << 16; + val |= pTmp[6] << 8; + + regs->strmStartLSB = val; + } + else + regs->strmStartLSB = 0; + } + else + { + regs->strmStartMSB = regs->strmStartLSB = 0; + } + + /* MVC frames with same timestamp and field pairs have equal frameNum. */ + if ((inst->numViews > 1) || inst->interlaced) + regs->frameNum = inst->slice.frameNum/2; + else + regs->frameNum = inst->slice.frameNum; + + regs->idrPicId = inst->slice.idrPicId; + + /* Store the final register values in the register structure */ + regs->sliceSizeMbRows = inst->slice.sliceSize / inst->mbPerRow; + regs->chromaQpIndexOffset = inst->picParameterSet.chromaQpIndexOffset; + + /* Enable slice ready interrupts if defined by config and slices in use */ + regs->sliceReadyInterrupt = + ENCH1_SLICE_READY_INTERRUPT & (inst->slice.sliceSize > 0); + + regs->picInitQp = (u32) (inst->picParameterSet.picInitQpMinus26 + 26); + + + regs->qp = qpHdr = inst->rateControl.qpHdr >> QP_FRACTIONAL_BITS; + + regs->qpfrac = (inst->rateControl.qpHdr - (asic->regs.qp << QP_FRACTIONAL_BITS))<<(16 - QP_FRACTIONAL_BITS); + + regs->qpMin = qpMin = inst->rateControl.qpMin >> QP_FRACTIONAL_BITS; + regs->qpMax = qpMax = inst->rateControl.qpMax >> QP_FRACTIONAL_BITS; + regs->cpTarget = NULL; + + regs->filterDisable = inst->slice.disableDeblocking; + if(inst->slice.disableDeblocking != 1) + { + regs->sliceAlphaOffset = inst->slice.filterOffsetA / 2; + regs->sliceBetaOffset = inst->slice.filterOffsetB / 2; + } + else + { + regs->sliceAlphaOffset = 0; + regs->sliceBetaOffset = 0; + } + regs->transform8x8Mode = inst->picParameterSet.transform8x8Mode; + + /* CABAC mode 2 uses ppsId=0 (CAVLC) for intra frames and + * ppsId=1 (CABAC) for inter frames */ + if (inst->picParameterSet.enableCabac == 2) + { + regs->ppsId = (inst->slice.sliceType == ISLICE) ? 0 : 1; + regs->enableCabac = regs->ppsId; + } + else + { + regs->ppsId = 0; + regs->enableCabac = inst->picParameterSet.enableCabac; + } + + if(inst->picParameterSet.enableCabac) + regs->cabacInitIdc = inst->slice.cabacInitIdc; + + regs->constrainedIntraPrediction = + (inst->picParameterSet.constIntraPred == ENCHW_YES) ? 1 : 0; + + /* Select frame type based on viewMode and frame number */ + if ((inst->slice.sliceType == ISLICE) && (inst->slice.nalUnitType == IDR)) + regs->frameCodingType = ASIC_INTRA; + else if ((inst->numViews > 1) && (inst->numRefBuffsLum == 1) && + (inst->slice.frameNum % 2) && (inst->slice.frameNum > 1)) + regs->frameCodingType = ASIC_MVC_REF_MOD; + else if ((inst->numViews > 1) && (inst->slice.frameNum % 2)) + regs->frameCodingType = ASIC_MVC; + else + regs->frameCodingType = ASIC_INTER; + + qpDeltaGainFloat = (float)inst->rateControl.rcMSESum / inst->rateControl.mbPerPic; + //printf("qpDeltaGainFloat=%f\n",qpDeltaGainFloat); + if(qpDeltaGainFloat<14) + qpDeltaGainFloat = 14; + qpDeltaGainFloat = qpDeltaGainFloat*qpDeltaGainFloat*strength/256; + //printf("qpDeltaGainFloat=%f\n",qpDeltaGainFloat); + qpDeltaGainFloat = strength; + qpDeltaGain = (((i32)qpDeltaGainFloat)<<8)+ float2fixpoint8(qpDeltaGainFloat - (float)((i32)qpDeltaGainFloat) ); + + if(regs->frameCodingType == ASIC_INTRA) + { + regs->qpDeltaMBGain = qpDeltaGain ; + regs->offsetMBComplexity = 17; + } + else + { + regs->qpDeltaMBGain = qpDeltaGain ; + regs->offsetMBComplexity = 15; + } + //printf("regs->offsetMBComplexity = 0x%x,regs->qpDeltaMBGain=0x%x\n",regs->offsetMBComplexity,regs->qpDeltaMBGain); + + regs->intraSliceMap1 = inst->intraSliceMap[0]; + regs->intraSliceMap2 = inst->intraSliceMap[1]; + regs->intraSliceMap3 = inst->intraSliceMap[2]; + + if ((inst->slice.sliceType == ISLICE) && (inst->slice.nalUnitType == NONIDR)) { + /* Non-IDR I-frame forced using intra slice map. */ + regs->intraSliceMap1 = regs->intraSliceMap2 = + regs->intraSliceMap3 = 0xFFFFFFFF; + } + + /* Disable frame reconstruction for view=1 frames that are not used + * as reference. */ + if ( (inst->numViews > 1) && + (inst->numRefBuffsLum == 1) && (inst->slice.frameNum % 2) ) + regs->recWriteDisable = 1; + + if (inst->slice.quarterPixelMv == 0) + inst->asic.regs.disableQuarterPixelMv = 1; + else if (inst->slice.quarterPixelMv == 1) + { + /* Adaptive setting. When resolution larger than 1080p = 8160 macroblocks + * there is not enough time to do 1/4 pixel ME */ + if(inst->mbPerFrame > 8160) + inst->asic.regs.disableQuarterPixelMv = 1; + else + inst->asic.regs.disableQuarterPixelMv = 0; + } + else + inst->asic.regs.disableQuarterPixelMv = 0; + + inst->asic.regs.splitMvMode = 1; + + /* Limits for AROI QP */ + if (inst->preProcess.adaptiveRoi) { + aroiDeltaQ = inst->preProcess.adaptiveRoi; + + /* When qp close to max limit deltaQ. Note that deltaQ is negative. */ + aroiDeltaQ = MAX(aroiDeltaQ, 2*(qpHdr-51)); + /* When qp close to min limit deltaQ. */ + aroiDeltaQ = MAX(aroiDeltaQ, MIN(0, 10-qpHdr)); + } + + /* Segment map is used when AROI is enabled. + Update segment map when either AROI is updated or ROIs are updated. */ + if (inst->preProcess.roiMapEnable) + { + regValues_s *regs = &inst->asic.regs; + regs->segmentEnable = 1; + } + else if (inst->preProcess.adaptiveRoi && + (inst->preProcess.roiUpdate || regs->roiUpdate)) + SetSegmentMap(inst); + + regs->roiUpdate = 0; /* Clear for next frame */ + + if(inst->rateControl.mbRc != 0) + { + if (inst->preProcess.roiMapEnable) + { + regs->madQpDelta[0] = CLIP3(inst->preProcess.qpOffset[0], -qpHdr, 51-qpHdr); + regs->madQpDelta[0] = CLIP3(regs->madQpDelta[0], -8, 7); + regs->madQpDelta[1] = CLIP3(inst->preProcess.qpOffset[1], -30, 30); + regs->madQpDelta[2] = CLIP3(inst->preProcess.qpOffset[2], -30, 30); /* AROI ID 3 */ + } + else if (inst->preProcess.adaptiveRoi && regs->segmentEnable) { + regs->madQpDelta[0] = CLIP3(inst->preProcess.qpOffset[0], -qpHdr, 51-qpHdr); + regs->madQpDelta[0] = CLIP3(regs->madQpDelta[0], -8, 7); + regs->madQpDelta[1] = CLIP3(inst->preProcess.qpOffset[1], -30, 30); + regs->madQpDelta[2] = CLIP3(inst->preProcess.qpOffset[2], -30, 30); /* AROI ID 3 */ + } + else + { + //not support MADQP adjustment + regs->madQpDelta[0] = 0; + regs->madQpDelta[1] = 0; + regs->madQpDelta[2] = 0; + } + inst->preProcess.qpOffset[0] = regs->madQpDelta[0]; + inst->preProcess.qpOffset[1] = regs->madQpDelta[1]; + inst->preProcess.qpOffset[2] = regs->madQpDelta[2]; + } + else if (inst->preProcess.roiMapEnable) + { + regs->madQpDelta[0] = CLIP3(inst->preProcess.qpOffset[0], -qpHdr, 51-qpHdr); + regs->madQpDelta[0] = CLIP3(regs->madQpDelta[0], -8, 7); + regs->madQpDelta[1] = CLIP3(inst->preProcess.qpOffset[1], -qpHdr, 51-qpHdr); + regs->madQpDelta[2] = CLIP3(inst->preProcess.qpOffset[2], -qpHdr, 51-qpHdr); /* AROI ID 3 */ + inst->preProcess.qpOffset[0] = regs->madQpDelta[0]; + inst->preProcess.qpOffset[1] = regs->madQpDelta[1]; + inst->preProcess.qpOffset[2] = regs->madQpDelta[2]; + } + else if (inst->preProcess.adaptiveRoi && regs->segmentEnable) { + regs->madQpDelta[0] = CLIP3(-regs->roi1DeltaQp, -qpHdr, 51-qpHdr); + regs->madQpDelta[0] = CLIP3(regs->madQpDelta[0], -8, 7); + regs->madQpDelta[1] = CLIP3(-regs->roi2DeltaQp, -qpHdr, 51-qpHdr); + regs->madQpDelta[2] = CLIP3(aroiDeltaQ, -qpHdr, 51-qpHdr); /* AROI ID 3 */ + } else { + /* MAD thresholding and segment map uses the same MB QP delta values. */ + regs->madQpDelta[0] = CLIP3(inst->rateControl.mbQpAdjustment[0], + qpMin - qpHdr, qpMax - qpHdr); + regs->madQpDelta[1] = CLIP3(inst->rateControl.mbQpAdjustment[1], + qpMin - qpHdr, qpMax - qpHdr); + regs->madQpDelta[2] = CLIP3(inst->rateControl.mbQpAdjustment[2], + qpMin - qpHdr, qpMax - qpHdr); + } + + /* QP values for each segment 0-3 */ + qp[0] = qpHdr; + qp[1] = qpHdr + regs->madQpDelta[0]; + qp[2] = qpHdr + regs->madQpDelta[1]; + qp[3] = qpHdr + regs->madQpDelta[2]; + + /* Set penalty values for every segment based on segment QP */ + for (s = 0; s < 4; s++) { + regs->pen[s][ASIC_PENALTY_I16FAVOR] = h264Intra16Favor[qp[s]]; + regs->pen[s][ASIC_PENALTY_I4_PREV_MODE_FAVOR] = h264PrevModeFavor[qp[s]]; + regs->pen[s][ASIC_PENALTY_INTER_FAVOR] = h264InterFavor[qp[s]]; + regs->pen[s][ASIC_PENALTY_SKIP] = h264SkipSadPenalty[qp[s]]; + { + i32 tmp = h264DiffMvPenalty4p[qp[s]]/10; + tmp = (tmp + 4) / 8; + if( tmp == 0 ) tmp++; + regs->pen[s][ASIC_PENALTY_DMV_4P] = tmp; + + tmp = (4*h264DiffMvPenalty[qp[s]])/5; + tmp = (tmp + 4) / 8; + if( tmp == 0 ) tmp++; + regs->pen[s][ASIC_PENALTY_DMV_1P] = tmp; + } + regs->pen[s][ASIC_PENALTY_DMV_QP] = h264DiffMvPenalty[qp[s]]; + regs->pen[s][ASIC_PENALTY_SPLIT16x8] = 0; + regs->pen[s][ASIC_PENALTY_SPLIT8x8] = 0; + regs->pen[s][ASIC_PENALTY_SPLIT8x4] = 0; + regs->pen[s][ASIC_PENALTY_SPLIT4x4] = 0; + regs->pen[s][ASIC_PENALTY_SPLIT_ZERO] = 0; +#if 0 + /* VP8 penalties not used. */ + for (i = ASIC_PENALTY_I16MODE0; i <= ASIC_PENALTY_I4MODE9; i++) + regs->pen[s][i] = 0; + for (i = ASIC_PENALTY_DZ_RATE0; i <= ASIC_PENALTY_DZ_SKIP1; i++) + regs->pen[s][i] = 0; +#endif + regs->pen[s][ASIC_PENALTY_GOLDEN] = h264DiffMvPenalty[qp[s]]/2; + if (regs->pen[s][ASIC_PENALTY_GOLDEN] > 255) + regs->pen[s][ASIC_PENALTY_GOLDEN] = 255; + // regs->pen[s][ASIC_PENALTY_DMV_COST_CONST] = 0; + //regs->pen[s][ASIC_PENALTY_COST_INTER] = 0; + } + + regs->mbRcEnable = 0; + regs->mbQpDeltaRange = 10; + regs->offsetSliceQp = 0; + if( qpHdr > 36) + { + regs->offsetSliceQp = 36 - qpHdr; + } + if(qpHdr < 15) + { + regs->offsetSliceQp = 15 - qpHdr; + } + if(inst->rateControl.mbRc != 0) + { + /* Set penalty values for every segment based on segment QP */ + regs->mbRcEnable = inst->rateControl.mbRc; + for (s = -15, lamdaIdx = 17 - regs->offsetSliceQp; s <= +15; s++, lamdaIdx++) { + qpAddr = (lamdaIdx & 0x1f); + regs->pen[qpAddr][ASIC_PENALTY_I16FAVOR] = h264Intra16Favor[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]; + regs->pen[qpAddr][ASIC_PENALTY_I4_PREV_MODE_FAVOR] = h264PrevModeFavor[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]; + regs->pen[qpAddr][ASIC_PENALTY_INTER_FAVOR] = h264InterFavor[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]; + regs->pen[qpAddr][ASIC_PENALTY_SKIP] = h264SkipSadPenalty[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]; + #if 0 + { + i32 tmp = h264DiffMvPenalty4p[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]/10; + tmp = (tmp + 4) / 8; + if( tmp == 0 ) tmp++; + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_DMV_4P] = tmp; + + tmp = (4*h264DiffMvPenalty[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)])/5; + tmp = (tmp + 4) / 8; + if( tmp == 0 ) tmp++; + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_DMV_1P] = tmp; + } + #endif + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_DMV_QP] = h264DiffMvPenalty[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]; + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_SPLIT16x8] = 0; + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_SPLIT8x8] = 0; + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_SPLIT8x4] = 0; + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_SPLIT4x4] = 0; + //regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_SPLIT_ZERO] = 0; +#if 0 + /* VP8 penalties not used. */ + for (i = ASIC_PENALTY_I16MODE0; i <= ASIC_PENALTY_I4MODE9; i++) + regs->pen[(lamdaIdx & 0x1f)][i] = 0; + for (i = ASIC_PENALTY_DZ_RATE0; i <= ASIC_PENALTY_DZ_SKIP1; i++) + regs->pen[(lamdaIdx & 0x1f)][i] = 0; +#endif + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_GOLDEN] = h264DiffMvPenalty[CLIP3(CLIP3(qpHdr - s + regs->offsetSliceQp,0,51),qpMin, qpMax)]/2; + if (regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_GOLDEN] > 255) + regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_GOLDEN] = 255; + + //regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_DMV_COST_CONST] = 0; + //regs->pen[(lamdaIdx & 0x1f)][ASIC_PENALTY_COST_INTER] = 0; + } + } + + /* DMV penalty tables */ + for (i = 0; i < ASIC_PENALTY_TABLE_SIZE; i++) { + regs->dmvPenalty[i] = (h264DmvPenalty[i] + 1) / 2; + regs->dmvQpelPenalty[i] = MIN(255,ExpGolombSigned(i)); + } + regs->zeroMvFavorDiv2 = 10; + + /* HW base address for NAL unit sizes is affected by start offset + * and SW created NALUs. */ + regs->sizeTblBase = asic->sizeTbl.busAddress + + inst->naluOffset*4 + inst->numNalus*4; + + /* HW Base must be 64-bit aligned */ + ASSERT(regs->sizeTblBase%8 == 0); + + if (regs->segmentMapUpdate) { + /* Swap segment map endianess to match ASIC reading. */ + EncSwap32((u32*)inst->asic.segmentMap.virtualAddress, + (inst->mbPerFrame+15)/16*8); +#ifdef TRACE_SEGMENTS + EncTraceSegments((u32*)inst->asic.segmentMap.virtualAddress, + (inst->mbPerFrame+15)/16*8, regs->segmentEnable, + regs->segmentMapUpdate, 0, regs->madQpDelta); +#endif + } + + /* When segment map is enabled, MAD thresholding can't be used. */ + if (!regs->segmentEnable) { + /* MAD threshold range [0, 63*256] register 6-bits range [0,63] */ + regs->madThreshold[0] = inst->mad.threshold[0] / 256; + regs->madThreshold[1] = inst->mad.threshold[1] / 256; + regs->madThreshold[2] = inst->mad.threshold[2] / 256; + } + else + regs->madThreshold[0] = regs->madThreshold[1] = regs->madThreshold[2] = 0; + + /* MVC */ + regs->mvcAnchorPicFlag = inst->mvc.anchorPicFlag; + regs->mvcPriorityId = inst->mvc.priorityId; + regs->mvcViewId = inst->mvc.viewId; + regs->mvcTemporalId = inst->mvc.temporalId; + regs->mvcInterViewFlag = inst->mvc.interViewFlag; + + /* Interlaced */ + if (inst->interlaced) { + regs->fieldPicFlag = 1; + regs->bottomFieldFlag = (inst->slice.frameNum%2) == inst->slice.fieldOrder; + regs->fieldParity = 0; + /* I-frame bottom field will reference top field */ + if (inst->slice.frameNum == 1) regs->fieldParity = 2-inst->slice.fieldOrder; + } + + /* current marked as long term */ + regs->markCurrentLongTerm = inst->picBuffer.cur_pic->grf == true; + + /* Pskip coding mode: 0=force coeff to zero (PSKIP), 1=don't force coeff to + * zero (INTER) */ + if (qpHdr < 45) { + regs->pskipMode = 1; + } else { + regs->pskipMode = 1; + } + + /* Boost */ + if (inst->rateControl.mbQpAutoBoost) { + if (inst->slice.frameNum%15 == 0) { + tmp = qpHdr - 8; + regs->pskipMode = 1; + } else { + tmp = qpHdr; + } + regs->boostVar1 = 1000; + regs->boostVar2 = 10; + regs->boostQp = MIN(qpMax, MAX(qpMin, tmp)); + } else { + regs->boostVar1 = 0; + regs->boostVar2 = 0; + regs->boostQp = 52; + } + + /* Intra vs Inter variance limits */ + regs->varLimitDiv32 = 256/32; /* 0..511 */ + regs->varInterFavorDiv16 = 16/16; /* 0..255 */ + regs->varMultiplier = 24; /* 0..31 */ + regs->varAdd = 1; /* 0..15 */ + + /* configure the input buffer control related register.*/ + regs->lineBufferEn = inst->inputLineBuf.inputLineBufEn; + regs->lineBufferHwHandShake = inst->inputLineBuf.inputLineBufHwModeEn; + if ((regs->lineBufferHwHandShake == 0) && inst->inputLineBuf.inputLineBufDepth) + regs->lineBufferIrqEnable = 1; + else + regs->lineBufferIrqEnable = 0; + regs->lineBufferLoopBackEn = inst->inputLineBuf.inputLineBufLoopBackEn; + regs->lineBufferDepth = inst->inputLineBuf.inputLineBufDepth; + regs->mbWrPtr = inst->inputLineBuf.wrCnt; + regs->mbRrPtr = 0; /* MB write pointer. */ + +#if defined(ASIC_WAVE_TRACE_TRIGGER) + { + u32 index; + + if(asic->regs.internalImageLumBaseW == + asic->internalImageLuma[0].busAddress) + index = 0; + else + index = 1; + + EWLmemset(asic->internalImageLuma[index].virtualAddress, 0, + asic->internalImageLuma[index].size); + } +#endif + +} + +/*------------------------------------------------------------------------------ + + SetSegmentMap + +------------------------------------------------------------------------------*/ +void SetSegmentMap(h264Instance_s *inst) +{ + regValues_s *regs = &inst->asic.regs; + u32 *map = inst->asic.segmentMap.virtualAddress; + u32 mask, mb, x, y; + + if (inst->preProcess.roiMbCount[2] == 0) { + /* AROI update with empty map means we can disable segments. */ + regs->segmentEnable = 0; + } else { + regs->segmentEnable = 1; + regs->segmentMapUpdate = 1; + + /* Set AROI (ID=3), ROI1 (ID=1) and ROI2 (ID=2) into segment map. */ + for (y = 0, mb = 0, mask = 0; y < inst->mbPerCol; y++) { + for (x = 0; x < inst->mbPerRow; x++, mb++) { + u32 id = 0; + /* AROI is checked first, then ROI1 and last ROR2 */ + if (inst->preProcess.roiSegmentMap[2][mb]) + id = 3; + if ((x >= regs->roi1Left) && (x <= regs->roi1Right) && + (y >= regs->roi1Top) && (y <= regs->roi1Bottom)) + id = 1; + if ((x >= regs->roi2Left) && (x <= regs->roi2Right) && + (y >= regs->roi2Top) && (y <= regs->roi2Bottom)) + id = 2; + + mask |= id << (28-4*(mb%8)); + if ((mb%8) == 7) { + *map++ = mask; + mask = 0; + } + } + } + *map++ = mask; + } + inst->preProcess.roiCoded = 1; /* AROI is coded into stream */ + +} + +/*------------------------------------------------------------------------------ + + ExpGolombSigned + +------------------------------------------------------------------------------*/ +i32 ExpGolombSigned(i32 val) +{ + i32 tmp = 0; + + if (val > 0) { + val = 2*val; + } else { + val = -2*val + 1; + } + + while (val >> ++tmp); + + /* + H264NalBits(stream, val, tmp*2-1); + */ + + return tmp*2-1; +} + +/*------------------------------------------------------------------------------ + EncSwap32 +------------------------------------------------------------------------------*/ +void EncSwap32(u32 * buf, u32 sizeBytes) +{ + u32 i = 0; + u32 words = sizeBytes / 4; + + ASSERT((sizeBytes % 8) == 0); + + while (i < words) + { +#if(ENCH1_OUTPUT_SWAP_32 == 1) /* need this for 64-bit HW */ + u32 val = buf[i]; + u32 val2 = buf[i+1]; + + buf[i] = val2; + buf[i+1] = val; +#endif + + i+=2; + } + +} + diff --git a/lib/vc8000nanoe/source/h264/H264CodeFrame.h b/lib/vc8000nanoe/source/h264/H264CodeFrame.h new file mode 100644 index 000000000..c6be2395f --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264CodeFrame.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encode picture + * + ******************************************************************************** + */ + +#ifndef __H264_CODE_FRAME_H__ +#define __H264_CODE_FRAME_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "H264Instance.h" +#include "H264Slice.h" +#include "H264RateControl.h" +#include "encasiccontroller.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +typedef enum +{ + H264ENCODE_OK = 0, + H264ENCODE_TIMEOUT = 1, + H264ENCODE_DATA_ERROR = 2, + H264ENCODE_HW_ERROR = 3, + H264ENCODE_SYSTEM_ERROR = 4, + H264ENCODE_HW_RESET = 5, + H264ENCODE_FUSE_ERROR = 6, +} h264EncodeFrame_e; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +h264EncodeFrame_e H264CodeFrame(h264Instance_s * inst); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264Denoise.c b/lib/vc8000nanoe/source/h264/H264Denoise.c new file mode 100644 index 000000000..aaff0227b --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Denoise.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "H264Denoise.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#ifdef TRACE_DENOISE_INTERNAL +#define APIDNF_DBG_LEVEL 20 +#define APIDNF_DBG_PARAM 10 +#define APIDNF_DBG_UPDATE 30 + +#define DBG(l, ...) if (l <= APIDNF_DBG_LEVEL) printf(__VA_ARGS__) +#else +#define DBG(l, ...) +#endif + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Function name : H264EncDnfInit + Description : Init denoise parameters. + Return type : H264EncRet + Argument : inst - encoder instance +------------------------------------------------------------------------------*/ +H264EncRet H264EncDnfInit(h264Instance_s *inst) +{ + inst->dnfEnable = 0; + inst->dnfNoiseLevelLow = 5 << FIX_POINT_BIT_WIDTH; + inst->dnfNoiseLevelY = 10 << FIX_POINT_BIT_WIDTH; + inst->dnfNoiseYCRatio = (1<dnfTableLoaded = 0; + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncDnfSetParameters + Description : Set DNF parameters according to coding parameters. + Return type : H264EncRet + Argument : inst - encoder instance +------------------------------------------------------------------------------*/ +H264EncRet H264EncDnfSetParameters(h264Instance_s *inst, const H264EncCodingCtrl *pCodeParams) +{ + inst->dnfEnable = pCodeParams->noiseReductionEnable; + inst->dnfNoiseLevelLow = pCodeParams->noiseLow; + inst->dnfNoiseLevelY = pCodeParams->noiseLevel; + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncDnfGetParameters + Description : Get DNF parameters. + Return type : H264EncRet + Argument : inst - encoder instance +------------------------------------------------------------------------------*/ +H264EncRet H264EncDnfGetParameters(h264Instance_s *inst, H264EncCodingCtrl *pCodeParams) +{ + pCodeParams->noiseReductionEnable = inst->dnfEnable; + pCodeParams->noiseLow = inst->dnfNoiseLevelLow; + pCodeParams->noiseLevel = inst->dnfNoiseLevelY; + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncDnfPrepare + Description : run before HW run, set register's value according to coding settings + Return type : H264EncRet + Argument : inst - encoder instance +------------------------------------------------------------------------------*/ +H264EncRet H264EncDnfPrepare(h264Instance_s *inst) +{ +#define SETPSIx2(x) (64+x/2) +#define SETPSIx1(x) (x) +#define MAP8x8(a, x) a[(x)/16*2+((x)/4)%2][(x)%4+4*(((x)/8)%2)] + + const int g_psi4e[4][4] = + { + {128, 114, 90, 41}, + {114, 102, 81, 36}, + { 90, 81, 64, 29}, + { 41, 36, 29, 13} + }; + const int g_psi8e[8][8] = + { + {128, 125, 118, 107, 86, 58, 41, 28}, + {125, 122, 115, 105, 84, 56, 40, 27}, + {118, 115, 109, 99, 80, 53, 38, 26}, + {107, 105, 99, 90, 72, 48, 34, 23}, + { 86, 84, 80, 72, 58, 39, 27, 19}, + { 58, 56, 53, 48, 39, 26, 18, 12}, + { 41, 40, 38, 34, 27, 18, 13, 9}, + { 28, 27, 26, 23, 19, 12, 9, 6} + }; + /* 4096/level, 12bits */ + const unsigned int g_table_sigReci[200] = + { + 803, 788, 773, 759, 745, 731, 719, 706, 694, 683, + 671, 661, 650, 640, 630, 621, 611, 602, 594, 585, + 577, 569, 561, 554, 546, 539, 532, 525, 518, 512, + 506, 500, 493, 488, 482, 476, 471, 465, 460, 455, + 450, 445, 440, 436, 431, 427, 422, 418, 414, 410, + 406, 402, 398, 394, 390, 386, 383, 379, 376, 372, + 369, 366, 362, 359, 356, 353, 350, 347, 344, 341, + 339, 336, 333, 330, 328, 325, 323, 320, 318, 315, + 313, 310, 308, 306, 303, 301, 299, 297, 295, 293, + 290, 288, 286, 284, 282, 281, 279, 277, 275, 273, + 271, 269, 268, 266, 264, 263, 261, 259, 258, 256, + 254, 253, 251, 250, 248, 247, 245, 244, 242, 241, + 240, 238, 237, 235, 234, 233, 231, 230, 229, 228, + 226, 225, 224, 223, 221, 220, 219, 218, 217, 216, + 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, + 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, + 194, 193, 192, 191, 191, 190, 189, 188, 187, 186, + 185, 185, 184, 183, 182, 181, 180, 180, 179, 178, + 177, 177, 176, 175, 174, 174, 173, 172, 171, 171, + 170, 169, 169, 168, 167, 167, 166, 165, 164, 164 + }; + + asicData_s *asic = &inst->asic; + i32 qp = inst->rateControl.qpHdr>>QP_FRACTIONAL_BITS; + + /* fill dnf table */ + if (inst->dnfTableLoaded==0) + { + #ifdef DNF_PARAM_REGS + /* load table from registers */ + int i; + /* intra 4x4 */ + for(i=0; i<16; i++) asic->regs.dnfParamS1[i] = SETPSIx2(g_psi4e[i/4][i%4]); + /* inter 4x4 */ + for(i=0; i<16; i++) asic->regs.dnfParamS2[i] = SETPSIx1(g_psi4e[i/4][i%4]); + /* intra 8x8 */ + for(i=0; i<64; i++) asic->regs.dnfParamS4[i] = SETPSIx2(MAP8x8(g_psi8e,i)); + /* inter 8x8 */ + for(i=0; i<64; i++) asic->regs.dnfParamS4[i] = SETPSIx1(MAP8x8(g_psi8e,i)); + #else + /* load table from DDR */ + int i; + u8 *base; + /* intra 4x4 */ + base = (u8*)inst->asic.dnfTable.virtualAddress; + for(i=0; i<16; i++) base[i] = SETPSIx2(g_psi4e[i/4][i%4]); + /* inter 4x4 */ + base += 16; + for(i=0; i<16; i++) base[i] = SETPSIx1(g_psi4e[i/4][i%4]); + /* intra 8x8 */ + base += 16; + for(i=0; i<64; i++) base[i] = SETPSIx2(MAP8x8(g_psi8e,i)); + /* inter 8x8 */ + base += 64; + for(i=0; i<64; i++) base[i] = SETPSIx1(MAP8x8(g_psi8e,i)); + #endif + + inst->dnfTableLoaded = 1; + } + + if (inst->dnfEnable==0) + return H264ENC_OK; + + if ((inst->dnfNoiseLevelY <= inst->dnfNoiseLevelLow) ||(inst->dnfNoiseLevelY <= MAX(80 * qp, inst->dnfNoiseLevelLow))) + { + asic->regs.dnfStrength = FILTER_STRENGTH_H; + asic->regs.dnfNoiseLevelInvertY = BITMASK(DNF_LEVELIVT_BITS); + asic->regs.dnfNoiseLevelInvertC = BITMASK(DNF_LEVELIVT_BITS); + } + else + { + inst->dnfNoiseLevelC = (inst->dnfNoiseLevelY * inst->dnfNoiseYCRatio) >> FIX_POINT_BIT_WIDTH; + + asic->regs.dnfStrength = CLIP3((FILTER_STRENGTH_H - ((FILTER_STRENGTH_PARAM * (MAX(inst->dnfNoiseLevelY - inst->dnfNoiseLevelLow, 0))) >> FIX_POINT_BIT_WIDTH)), + FILTER_STRENGTH_L, FILTER_STRENGTH_H); + asic->regs.dnfNoiseLevelInvertY = g_table_sigReci[CLIP3((((inst->dnfNoiseLevelY*1311)>>17) - 51), 0, 199)]; + asic->regs.dnfNoiseLevelInvertC = g_table_sigReci[CLIP3((((inst->dnfNoiseLevelC*1311)>>17) - 51), 0, 199)]; + } + + ASSERT(asic->regs.dnfStrength <= BITMASK(DNF_STENGTH_BITS)); + ASSERT(asic->regs.dnfNoiseLevelInvertY <= BITMASK(DNF_LEVELIVT_BITS)); + ASSERT(asic->regs.dnfNoiseLevelInvertC <= BITMASK(DNF_LEVELIVT_BITS)); + + asic->regs.dnfEnable = (inst->dnfEnable!=0); + asic->regs.dnfNoiseLevelMax = inst->dnfNoiseLevelMax; + ASSERT(asic->regs.dnfNoiseLevelMax < BITMASK(DNF_LEVELMAX_BITS)); + + DBG(APIDNF_DBG_PARAM, "DNF Parameters :\n"); + DBG(APIDNF_DBG_PARAM, " Noise level is %.2f\n", (float)inst->dnfNoiseLevelY/1024.0); + DBG(APIDNF_DBG_PARAM, " Noise Low is %.2f\n", (float)inst->dnfNoiseLevelLow/1024.0); + DBG(APIDNF_DBG_PARAM, " Noise Max is %.2f\n", (float)inst->dnfNoiseLevelMax/1024.0); + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncDnfUpdate + Description : run after HW finish one frame, update collected parameters + Return type : H264EncRet + Argument : inst - encoder instance +------------------------------------------------------------------------------*/ +H264EncRet H264EncDnfUpdate(h264Instance_s *inst) +{ + const int SMOOTHFACTOR[5] = {1024, 512, 341, 256, 205}; + const int KK=160; + + asicData_s *asic = &inst->asic; + unsigned int j = 0; + int qp = inst->asic.regs.qp; + int frameCodingType = inst->asic.regs.frameCodingType; + unsigned int frameCnt = inst->dnfFrameNum++; + int noiseSum = 0; + int noiseMbNum; + int noiseLevel; + int noiseNext; + int noiseMax; + + /** + * check pre-conditions + * 1. disable or without noise estimation. + * 2. no stream generated, estimation fail. + */ + if (inst->dnfEnable != 1 || inst->stream.byteCnt == 0) + return H264ENC_OK; + + /* calculate the noise level */ + noiseMbNum = asic->regs.dnfNoiseMbNum; + noiseLevel = (noiseMbNum!=0u)?(int)(asic->regs.dnfNoiseLevelPred/noiseMbNum):-1; + + inst->dnfQpPrev = qp; + + /* estimate noise level */ + if (noiseLevel == -1) + { + noiseLevel = inst->dnfNoiseLevelY; + } + noiseLevel = (noiseLevel * KK) >> 7; + inst->dnfNoiseLevels[(frameCnt)%SIGMA_SMOOTH_NUM] = noiseLevel; + for (j = 0; j < (MIN(SIGMA_SMOOTH_NUM - 1, frameCnt) + 1); j++) + { + noiseSum += inst->dnfNoiseLevels[j]; + DBG(APIDNF_DBG_UPDATE, " %.2f", (float)inst->dnfNoiseLevels[j]/1024.0); + } + DBG(APIDNF_DBG_UPDATE, "\n"); + noiseNext = (noiseSum * SMOOTHFACTOR[MIN(SIGMA_SMOOTH_NUM-1, frameCnt)]) >> 10; + inst->dnfNoiseLevelY = CLIP3(noiseNext, 0, (SIGMA_MAX << FIX_POINT_BIT_WIDTH)); + DBG(APIDNF_DBG_UPDATE, "DNF Update :\n"); + DBG(APIDNF_DBG_UPDATE, " Pedict Noise level is %.2f\n", (float)noiseLevel/1024.0); + DBG(APIDNF_DBG_UPDATE, " Smooth Noise Level is %.2f by smoothing %d frames\n", (float)noiseNext/1024.0, frameCnt); + DBG(APIDNF_DBG_UPDATE, " Final Noise Level as %.2f\n", (float)inst->dnfNoiseLevelY/1024.0); + + /* estimate noise max */ + noiseMax = (frameCodingType != (int)ASIC_INTRA) ? (int)(asic->regs.dnfNoiseMaxPred/inst->mbPerFrame) : inst->dnfNoiseMaxPrev; + if (noiseMax > BITMASK(DNF_LEVELMAX_BITS)) + { + noiseMax = BITMASK(DNF_LEVELMAX_BITS); + } + inst->dnfNoiseLevelMax = inst->dnfNoiseMaxPred = noiseMax; + DBG(APIDNF_DBG_UPDATE, " Predict Noise Max is %.2f\n", (float)noiseMax/1024.0); + + return H264ENC_OK; +} + + diff --git a/lib/vc8000nanoe/source/h264/H264Denoise.h b/lib/vc8000nanoe/source/h264/H264Denoise.h new file mode 100644 index 000000000..20ee459bc --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Denoise.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Encoder initialization and setup + * + ******************************************************************************** + */ + +#ifndef __H264_DENOISE_H__ +#define __H264_DENOISE_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "h264encapi.h" +#include "H264Instance.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ +#define DNF_STENGTH_BITS 11 +#define DNF_LEVELIVT_BITS 12 +#define DNF_LEVELMAX_BITS 16 + +#define BITMASK(n) ((1<<(n))-1) + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +H264EncRet H264EncDnfInit(h264Instance_s *inst); +H264EncRet H264EncDnfSetParameters(h264Instance_s *inst, const H264EncCodingCtrl *pCodeParams); +H264EncRet H264EncDnfGetParameters(h264Instance_s *inst, H264EncCodingCtrl *pCodeParams); +H264EncRet H264EncDnfPrepare(h264Instance_s *inst); +H264EncRet H264EncDnfUpdate(h264Instance_s *inst); + +#endif + diff --git a/lib/vc8000nanoe/source/h264/H264EncApi.c b/lib/vc8000nanoe/source/h264/H264EncApi.c new file mode 100644 index 000000000..fbf554d65 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264EncApi.c @@ -0,0 +1,3075 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : H264 Encoder API + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + Version Information +------------------------------------------------------------------------------*/ + +#define H264ENC_MAJOR_VERSION 5 +#define H264ENC_MINOR_VERSION 0 + +#define H264ENC_BUILD_MAJOR 5 +#define H264ENC_BUILD_MINOR 0 +#define H264ENC_BUILD_REVISION 0 +#define H264ENC_SW_BUILD ((H264ENC_BUILD_MAJOR * 1000000) + \ +(H264ENC_BUILD_MINOR * 1000) + H264ENC_BUILD_REVISION) + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include +#include "h264encapi.h" +#include "enccommon.h" +#include "H264Instance.h" +#include "H264Init.h" +#include "H264PutBits.h" +#include "H264CodeFrame.h" +#include "H264Sei.h" +#include "H264RateControl.h" +#include "H264Cabac.h" +#include "H264Denoise.h" +#include "encasiccontroller.h" + +#ifdef INTERNAL_TEST +#include "H264TestId.h" +#endif + +#ifdef VIDEOSTAB_ENABLED +#include "vidstabcommon.h" +#endif + + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +#define EVALUATION_LIMIT 300 max number of frames to encode + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Parameter limits */ +#define H264ENCSTRMSTART_MIN_BUF 64 +#define H264ENCSTRMENCODE_MIN_BUF 4096 +#define H264ENC_MAX_PP_INPUT_WIDTH 8176 +#define H264ENC_MAX_PP_INPUT_HEIGHT 8176 +#define H264ENC_MAX_BITRATE (50000*1200) /* Level 4.1 limit */ +#define H264ENC_MAX_USER_DATA_SIZE 2048 + +#define H264ENC_IDR_ID_MODULO 16 + +#define H264_BUS_ADDRESS_VALID(bus_address) (((bus_address) != 0) && \ + ((bus_address & 0x07) == 0)) + +/* HW ID check. H264EncInit() will fail if HW doesn't match. */ +#define HW_ID_MASK 0xFFFF0000 +#define HW_ID 0x48310000 +#define HW_ID_NE 0x6e650000 + + +/* Tracing macro */ +#ifdef H264ENC_TRACE +#define APITRACE(str) H264EncTrace(str) +#define APITRACEPARAM(str, val) \ + { char tmpstr[255]; sprintf(tmpstr, " %s: %d", str, (int)val); H264EncTrace(tmpstr); } +#else +#ifndef APITRACE +#define APITRACE(str) +#endif +#ifndef APITRACEPARAM +#define APITRACEPARAM(str, val) +#endif +#endif + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static void H264AddNaluSize(H264EncOut * pEncOut, u32 naluSizeBytes); + +static i32 VSCheckSize(u32 inputWidth, u32 inputHeight, u32 stabilizedWidth, + u32 stabilizedHeight); + +static void H264PrefixNal(h264Instance_s *pEncInst, bool svcExtFlag); +static void H264SvcSeiNal(h264Instance_s *pEncInst); + +/* Supply prefix for svct muti-slice. */ +static void H264SupplyPrefixForSvctMutiSlice(H264EncInst inst, const H264EncIn *pEncIn, H264EncOut *pEncOut, + u32 prefix_nalu_length, u8 *prefix_nalu_addr); + + +/*------------------------------------------------------------------------------ + + Function name : H264EncGetApiVersion + Description : Return the API version info + + Return type : H264EncApiVersion + Argument : void +------------------------------------------------------------------------------*/ +H264EncApiVersion H264EncGetApiVersion(void) +{ + H264EncApiVersion ver; + + ver.major = H264ENC_MAJOR_VERSION; + ver.minor = H264ENC_MINOR_VERSION; + + APITRACE("H264EncGetApiVersion# OK"); + return ver; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncGetBuild + Description : Return the SW and HW build information + + Return type : H264EncBuild + Argument : void +------------------------------------------------------------------------------*/ +H264EncBuild H264EncGetBuild(void) +{ + H264EncBuild ver; + + ver.swBuild = H264ENC_SW_BUILD; + ver.hwBuild = EWLReadAsicID(); + + APITRACE("H264EncGetBuild# OK"); + + return (ver); +} + +/*------------------------------------------------------------------------------ + Function name : H264EncInit + Description : Initialize an encoder instance and returns it to application + + Return type : H264EncRet + Argument : pEncCfg - initialization parameters + instAddr - where to save the created instance +------------------------------------------------------------------------------*/ +H264EncRet H264EncInit(const H264EncConfig * pEncCfg, H264EncInst * instAddr) +{ + H264EncRet ret; + h264Instance_s *pEncInst = NULL; + + APITRACE("H264EncInit#"); + APITRACEPARAM("streamType", pEncCfg->streamType); + APITRACEPARAM("viewMode", pEncCfg->viewMode); + APITRACEPARAM("level", pEncCfg->level); + APITRACEPARAM("refFrameAmount", pEncCfg->refFrameAmount); + APITRACEPARAM("refFrameCompress", pEncCfg->refFrameCompress); + APITRACEPARAM("width", pEncCfg->width); + APITRACEPARAM("height", pEncCfg->height); + APITRACEPARAM("frameRateNum", pEncCfg->frameRateNum); + APITRACEPARAM("frameRateDenom", pEncCfg->frameRateDenom); + APITRACEPARAM("scaledWidth", pEncCfg->scaledWidth); + APITRACEPARAM("scaledHeight", pEncCfg->scaledHeight); + APITRACEPARAM("scvtLevel", pEncCfg->svctLevel); + + /* check that right shift on negative numbers is performed signed */ + /*lint -save -e* following check causes multiple lint messages */ +#if (((-1) >> 1) != (-1)) +#error Right bit-shifting (>>) does not preserve the sign +#endif + /*lint -restore */ + + /* Check for illegal inputs */ + if(pEncCfg == NULL || instAddr == NULL) + { + APITRACE("H264EncInit: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for correct HW */ + if ((EWLReadAsicID() & HW_ID_MASK) != HW_ID && (EWLReadAsicID() & HW_ID_MASK) != HW_ID_NE) + { + APITRACE("H264EncInit: ERROR Invalid HW ID"); + return H264ENC_ERROR; + } + + /* Check that configuration is valid */ + if(H264CheckCfg(pEncCfg) == ENCHW_NOK) + { + APITRACE("H264EncInit: ERROR Invalid configuration"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Initialize encoder instance and allocate memories */ + ret = H264Init(pEncCfg, &pEncInst); + + if(ret != H264ENC_OK) + { + APITRACE("H264EncInit: ERROR Initialization failed"); + return ret; + } + + /* Status == INIT Initialization succesful */ + pEncInst->encStatus = H264ENCSTAT_INIT; + + pEncInst->inst = pEncInst; /* used as checksum */ + + *instAddr = (H264EncInst) pEncInst; + + APITRACE("H264EncInit: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncRelease + Description : Releases encoder instance and all associated resource + + Return type : H264EncRet + Argument : inst - the instance to be released +------------------------------------------------------------------------------*/ +H264EncRet H264EncRelease(H264EncInst inst) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + APITRACE("H264EncRelease#"); + + /* Check for illegal inputs */ + if(pEncInst == NULL) + { + APITRACE("H264EncRelease: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncRelease: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + +#ifdef TRACE_STREAM + EncCloseStreamTrace(); +#endif + + H264Shutdown(pEncInst); + + APITRACE("H264EncRelease: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncSetCodingCtrl + Description : Sets encoding parameters + + Return type : H264EncRet + Argument : inst - the instance in use + pCodeParams - user provided parameters +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetCodingCtrl(H264EncInst inst, + const H264EncCodingCtrl * pCodeParams) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + regValues_s *regs = &pEncInst->asic.regs; + + APITRACE("H264EncSetCodingCtrl#"); + APITRACEPARAM("sliceSize", pCodeParams->sliceSize); + APITRACEPARAM("seiMessages", pCodeParams->seiMessages); + APITRACEPARAM("idrHeader", pCodeParams->idrHeader); + APITRACEPARAM("videoFullRange", pCodeParams->videoFullRange); + APITRACEPARAM("constrainedIntraPrediction", pCodeParams->constrainedIntraPrediction); + APITRACEPARAM("disableDeblockingFilter", pCodeParams->disableDeblockingFilter); + APITRACEPARAM("sampleAspectRatioWidth", pCodeParams->sampleAspectRatioWidth); + APITRACEPARAM("sampleAspectRatioHeight", pCodeParams->sampleAspectRatioHeight); + APITRACEPARAM("enableCabac", pCodeParams->enableCabac); + APITRACEPARAM("cabacInitIdc", pCodeParams->cabacInitIdc); + APITRACEPARAM("transform8x8Mode", pCodeParams->transform8x8Mode); + APITRACEPARAM("quarterPixelMv", pCodeParams->quarterPixelMv); + APITRACEPARAM("cirStart", pCodeParams->cirStart); + APITRACEPARAM("cirInterval", pCodeParams->cirInterval); + APITRACEPARAM("intraSliceMap1", pCodeParams->intraSliceMap1); + APITRACEPARAM("intraSliceMap2", pCodeParams->intraSliceMap2); + APITRACEPARAM("intraSliceMap3", pCodeParams->intraSliceMap3); + APITRACEPARAM("intraArea.enable", pCodeParams->intraArea.enable); + APITRACEPARAM("intraArea.top", pCodeParams->intraArea.top); + APITRACEPARAM("intraArea.bottom", pCodeParams->intraArea.bottom); + APITRACEPARAM("intraArea.left", pCodeParams->intraArea.left); + APITRACEPARAM("intraArea.right", pCodeParams->intraArea.right); + APITRACEPARAM("roi1Area.enable", pCodeParams->roi1Area.enable); + APITRACEPARAM("roi1Area.top", pCodeParams->roi1Area.top); + APITRACEPARAM("roi1Area.bottom", pCodeParams->roi1Area.bottom); + APITRACEPARAM("roi1Area.left", pCodeParams->roi1Area.left); + APITRACEPARAM("roi1Area.right", pCodeParams->roi1Area.right); + APITRACEPARAM("roi2Area.enable", pCodeParams->roi2Area.enable); + APITRACEPARAM("roi2Area.top", pCodeParams->roi2Area.top); + APITRACEPARAM("roi2Area.bottom", pCodeParams->roi2Area.bottom); + APITRACEPARAM("roi2Area.left", pCodeParams->roi2Area.left); + APITRACEPARAM("roi2Area.right", pCodeParams->roi2Area.right); + APITRACEPARAM("roi1DeltaQp", pCodeParams->roi1DeltaQp); + APITRACEPARAM("roi2DeltaQp", pCodeParams->roi2DeltaQp); + APITRACEPARAM("adaptiveRoi", pCodeParams->adaptiveRoi); + APITRACEPARAM("adaptiveRoiColor", pCodeParams->adaptiveRoiColor); + APITRACEPARAM("fieldOrder", pCodeParams->fieldOrder); + APITRACEPARAM("gdrDuration", pCodeParams->gdrDuration); + APITRACEPARAM("roiMapEnable", pCodeParams->roiMapEnable); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pCodeParams == NULL)) + { + APITRACE("H264EncSetCodingCtrl: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* Check for invalid values */ + if(pCodeParams->sliceSize > pEncInst->mbPerCol) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid sliceSize"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pCodeParams->cirStart > pEncInst->mbPerFrame || + pCodeParams->cirInterval > pEncInst->mbPerFrame) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid CIR value"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pCodeParams->intraArea.enable) { + if(!(pCodeParams->intraArea.top <= pCodeParams->intraArea.bottom && + pCodeParams->intraArea.bottom < pEncInst->mbPerCol && + pCodeParams->intraArea.left <= pCodeParams->intraArea.right && + pCodeParams->intraArea.right < pEncInst->mbPerRow) || (pCodeParams->gdrDuration > 0)) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid intraArea"); + return H264ENC_INVALID_ARGUMENT; + } + } + + if(pCodeParams->roi1Area.enable) { + if(!(pCodeParams->roi1Area.top <= pCodeParams->roi1Area.bottom && + pCodeParams->roi1Area.bottom < pEncInst->mbPerCol && + pCodeParams->roi1Area.left <= pCodeParams->roi1Area.right && + pCodeParams->roi1Area.right < pEncInst->mbPerRow) || (pCodeParams->gdrDuration > 0)) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid roi1Area"); + return H264ENC_INVALID_ARGUMENT; + } + } + + if(pCodeParams->roi2Area.enable) { + if(!(pCodeParams->roi2Area.top <= pCodeParams->roi2Area.bottom && + pCodeParams->roi2Area.bottom < pEncInst->mbPerCol && + pCodeParams->roi2Area.left <= pCodeParams->roi2Area.right && + pCodeParams->roi2Area.right < pEncInst->mbPerRow)) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid roi2Area"); + return H264ENC_INVALID_ARGUMENT; + } + } + + if(pCodeParams->roi1DeltaQp < -15 || + pCodeParams->roi1DeltaQp > 0 || + pCodeParams->roi2DeltaQp < -15 || + pCodeParams->roi2DeltaQp > 0 || + pCodeParams->adaptiveRoi < -51 || + pCodeParams->adaptiveRoi > 0) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid ROI delta QP"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pCodeParams->qpOffset[0] < -8 || + pCodeParams->qpOffset[0] > 7 || + pCodeParams->qpOffset[1] < -127 || + pCodeParams->qpOffset[1] > 127 || + pCodeParams->qpOffset[2] < -127 || + pCodeParams->qpOffset[2] > 127) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid ROI delta QP for ROI MAP"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Check status, only slice size, CIR & ROI allowed to change after start */ + if(pEncInst->encStatus != H264ENCSTAT_INIT) + { + goto set_slice_size; + } + + if(pCodeParams->constrainedIntraPrediction > 1 || + pCodeParams->disableDeblockingFilter > 2 || + pCodeParams->enableCabac > 2 || + pCodeParams->transform8x8Mode > 2 || + pCodeParams->quarterPixelMv > 2 || + pCodeParams->seiMessages > 1 || + pCodeParams->idrHeader > 1 || + pCodeParams->videoFullRange > 1) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid enable/disable"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pCodeParams->sampleAspectRatioWidth > 65535 || + pCodeParams->sampleAspectRatioHeight > 65535) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid sampleAspectRatio"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pCodeParams->cabacInitIdc > 2) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid cabacInitIdc"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Configure the values */ + if(pCodeParams->constrainedIntraPrediction == 0) + pEncInst->picParameterSet.constIntraPred = ENCHW_NO; + else + pEncInst->picParameterSet.constIntraPred = ENCHW_YES; + + /* filter control header always present */ + pEncInst->picParameterSet.deblockingFilterControlPresent = ENCHW_YES; + pEncInst->slice.disableDeblocking = pCodeParams->disableDeblockingFilter; + + pEncInst->picParameterSet.enableCabac = pCodeParams->enableCabac; + pEncInst->slice.cabacInitIdc = pCodeParams->cabacInitIdc; + + /* cavlc -> long-term ref pics disabled */ + /* exception: when svct is enable, it use only 1 reference. */ + if ( pEncInst->svc.level == 0 && pCodeParams->enableCabac == 0 && + pEncInst->seqParameterSet.numRefFrames > 1 && !pEncInst->interlaced) + { + pEncInst->seqParameterSet.numRefFrames = 1; + pEncInst->picBuffer.size = 1; + } + + if(((pCodeParams->gdrDuration > 0) && + (pEncInst->seqParameterSet.numRefFrames > 1) && + (!pEncInst->interlaced))) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid gdr parameters"); + return H264ENC_INVALID_ARGUMENT; + } + + /* SVCT check */ + if (pEncInst->svc.level) + { + /* check HW support */ + if (pEncInst->hwCfg.svctSupport==0) + return ENCHW_NOK; + + if (pCodeParams->gdrDuration) + { + APITRACE("H264EncSetCodingCtrl: ERROR Cannot enable GDR for SVCT"); + return H264ENC_INVALID_ARGUMENT; + } + if (pEncInst->interlaced) + { + /* TODO: this limitation may be removed later */ + APITRACE("H264EncSetCodingCtrl: ERROR Support interlace when enable SVCT"); + return H264ENC_INVALID_ARGUMENT; + } + if (pEncInst->numViews>1) + { + /* TODO: this limitation may be removed later */ + APITRACE("H264EncSetCodingCtrl: ERROR Support MVC when enable SVCT"); + return H264ENC_INVALID_ARGUMENT; + } + } + + + /* 8x8 mode: 2=enable, 1=adaptive (720p or bigger frame) */ + if ((pCodeParams->transform8x8Mode == 2) || + ((pCodeParams->transform8x8Mode == 1) && + (pEncInst->mbPerFrame >= 3600))) + { + pEncInst->picParameterSet.transform8x8Mode = ENCHW_YES; + } + + /* check HW support */ + if ((pCodeParams->noiseReductionEnable)&&(pEncInst->hwCfg.dnfSupport==0)) + return ENCHW_NOK; + + H264EncDnfSetParameters(pEncInst, pCodeParams); + + H264SpsSetVuiAspectRatio(&pEncInst->seqParameterSet, + pCodeParams->sampleAspectRatioWidth, + pCodeParams->sampleAspectRatioHeight); + + H264SpsSetVuiVideoInfo(&pEncInst->seqParameterSet, + pCodeParams->videoFullRange); + + /* SEI messages are written in the beginning of each frame */ + if(pCodeParams->seiMessages) + pEncInst->rateControl.sei.enabled = ENCHW_YES; + else + pEncInst->rateControl.sei.enabled = ENCHW_NO; + + set_slice_size: + /* Slice size is set in macroblock rows => convert to macroblocks */ + pEncInst->slice.sliceSize = pCodeParams->sliceSize * pEncInst->mbPerRow; + pEncInst->slice.fieldOrder = pCodeParams->fieldOrder ? 1 : 0; + + pEncInst->slice.quarterPixelMv = pCodeParams->quarterPixelMv; + + /* SPS/PPSheader written to each IDR or in the beginning of sequence */ + if(pCodeParams->idrHeader) + pEncInst->idrHdr = ENCHW_YES; + else + pEncInst->idrHdr = ENCHW_NO; + + /* Set CIR, intra forcing and ROI parameters */ + regs->cirStart = pCodeParams->cirStart; + regs->cirInterval = pCodeParams->cirInterval; + pEncInst->intraSliceMap[0] = pCodeParams->intraSliceMap1; + pEncInst->intraSliceMap[1] = pCodeParams->intraSliceMap2; + pEncInst->intraSliceMap[2] = pCodeParams->intraSliceMap3; + if (pCodeParams->intraArea.enable) { + regs->intraAreaTop = pCodeParams->intraArea.top; + regs->intraAreaLeft = pCodeParams->intraArea.left; + regs->intraAreaBottom = pCodeParams->intraArea.bottom; + regs->intraAreaRight = pCodeParams->intraArea.right; + } else { + regs->intraAreaTop = regs->intraAreaLeft = regs->intraAreaBottom = + regs->intraAreaRight = 255; + } + if (pCodeParams->roi1Area.enable) { + regs->roi1Top = pCodeParams->roi1Area.top; + regs->roi1Left = pCodeParams->roi1Area.left; + regs->roi1Bottom = pCodeParams->roi1Area.bottom; + regs->roi1Right = pCodeParams->roi1Area.right; + } else { + regs->roi1Top = regs->roi1Left = regs->roi1Bottom = + regs->roi1Right = 255; + } + if (pCodeParams->roi2Area.enable) { + regs->roi2Top = pCodeParams->roi2Area.top; + regs->roi2Left = pCodeParams->roi2Area.left; + regs->roi2Bottom = pCodeParams->roi2Area.bottom; + regs->roi2Right = pCodeParams->roi2Area.right; + } else { + regs->roi2Top = regs->roi2Left = regs->roi2Bottom = + regs->roi2Right = 255; + } + regs->roi1DeltaQp = -pCodeParams->roi1DeltaQp; + regs->roi2DeltaQp = -pCodeParams->roi2DeltaQp; + regs->roiUpdate = 1; /* ROI has changed from previous frame. */ + + pEncInst->preProcess.roiMapEnable = pCodeParams->roiMapEnable; + pEncInst->preProcess.adaptiveRoi = pCodeParams->adaptiveRoi; + pEncInst->preProcess.adaptiveRoiColor = + CLIP3(pCodeParams->adaptiveRoiColor, -10, 10); + if (pCodeParams->roiMapEnable) + { + if ((pEncInst->preProcess.adaptiveRoi)||(pCodeParams->roi1Area.enable) + ||(pCodeParams->roi2Area.enable)) + { + APITRACE("H264EncSetCodingCtrl: ERROR Invalid ROI feature"); + return H264ENC_INVALID_ARGUMENT; + } + /* set the roi1,roi2 region registers as invalid. */ + regs->roi1Top = regs->roi1Left = regs->roi1Bottom = regs->roi1Right = 255; + regs->roi2Top = regs->roi2Left = regs->roi2Bottom = regs->roi2Right = 255; + pEncInst->preProcess.qpOffset[0] = pCodeParams->qpOffset[0]; + pEncInst->preProcess.qpOffset[1] = pCodeParams->qpOffset[1]; + pEncInst->preProcess.qpOffset[2] = pCodeParams->qpOffset[2]; + } + + pEncInst->rateControl.sei.insertRecoveryPointMessage = ENCHW_NO; + pEncInst->rateControl.sei.recoveryFrameCnt = pCodeParams->gdrDuration; + if (pEncInst->encStatus < H264ENCSTAT_START_FRAME) + { + pEncInst->gdrFirstIntraFrame = (1 + pEncInst->interlaced); + } + pEncInst->gdrEnabled = (pCodeParams->gdrDuration > 0); + pEncInst->gdrDuration = pCodeParams->gdrDuration; + if (pEncInst->gdrEnabled == 1) + { + pEncInst->gdrStart = 0; + pEncInst->gdrCount = 0; +#ifndef SEARCH_AREA_SMALL + pEncInst->gdrAverageMBRows = (pEncInst->mbPerCol-2) / pEncInst->gdrDuration; + pEncInst->gdrMBLeft = pEncInst->mbPerCol - 2 - pEncInst->gdrAverageMBRows * pEncInst->gdrDuration; +#else + pEncInst->gdrAverageMBRows = (pEncInst->mbPerCol - 1) / pEncInst->gdrDuration; + pEncInst->gdrMBLeft = pEncInst->mbPerCol - 1 - pEncInst->gdrAverageMBRows * pEncInst->gdrDuration; +#endif + if(pEncInst->gdrAverageMBRows == 0) + { + pEncInst->rateControl.sei.recoveryFrameCnt = pEncInst->gdrMBLeft; + pEncInst->gdrDuration = pEncInst->gdrMBLeft; + } + } + + /* Input Line buffer check */ + if (pCodeParams->inputLineBufEn) + { + /* check HW support */ + if (pEncInst->hwCfg.instantSupport==0) + return ENCHW_NOK; + + /* check zero depth */ + if ((pCodeParams->inputLineBufDepth == 0) && + (pCodeParams->inputLineBufLoopBackEn || pCodeParams->inputLineBufHwModeEn)) + { + APITRACE("H264EncSetCodingCtrl: Invalid input buffer depth"); + return ENCHW_NOK; + } + + /* check depth*mb_width align to 4 */ + if ((pEncInst->mbPerRow * pCodeParams->inputLineBufDepth) & 3) + { + APITRACE("H264EncSetCodingCtrl: Invalid input buffer depth (depth*mb_width align to 4)"); + APITRACEPARAM("mbPerRow", pEncInst->mbPerRow); + return ENCHW_NOK; + } + } + pEncInst->inputLineBuf.inputLineBufEn = pCodeParams->inputLineBufEn; + pEncInst->inputLineBuf.inputLineBufLoopBackEn = pCodeParams->inputLineBufLoopBackEn; + pEncInst->inputLineBuf.inputLineBufDepth = pCodeParams->inputLineBufDepth; + pEncInst->inputLineBuf.inputLineBufHwModeEn = pCodeParams->inputLineBufHwModeEn; + + pEncInst->svc.next_base_priority_id = pCodeParams->nBaseLayerPID; + + APITRACE("H264EncSetCodingCtrl: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncGetCodingCtrl + Description : Returns current encoding parameters + + Return type : H264EncRet + Argument : inst - the instance in use + pCodeParams - palce where parameters are returned +------------------------------------------------------------------------------*/ +H264EncRet H264EncGetCodingCtrl(H264EncInst inst, + H264EncCodingCtrl * pCodeParams) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + regValues_s *regs = &pEncInst->asic.regs; + + APITRACE("H264EncGetCodingCtrl#"); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pCodeParams == NULL)) + { + APITRACE("H264EncGetCodingCtrl: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncGetCodingCtrl: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* Get values */ + pCodeParams->constrainedIntraPrediction = + (pEncInst->picParameterSet.constIntraPred == ENCHW_NO) ? 0 : 1; + + /* Slice size from macroblocks to macroblock rows */ + pCodeParams->sliceSize = pEncInst->slice.sliceSize / pEncInst->mbPerRow; + pCodeParams->fieldOrder = pEncInst->slice.fieldOrder; + + pCodeParams->seiMessages = + (pEncInst->rateControl.sei.enabled == ENCHW_YES) ? 1 : 0; + pCodeParams->idrHeader = + (pEncInst->idrHdr == ENCHW_YES) ? 1 : 0; + pCodeParams->videoFullRange = + (pEncInst->seqParameterSet.vui.videoFullRange == ENCHW_YES) ? 1 : 0; + pCodeParams->sampleAspectRatioWidth = + pEncInst->seqParameterSet.vui.sarWidth; + pCodeParams->sampleAspectRatioHeight = + pEncInst->seqParameterSet.vui.sarHeight; + pCodeParams->disableDeblockingFilter = pEncInst->slice.disableDeblocking; + pCodeParams->enableCabac = pEncInst->picParameterSet.enableCabac; + pCodeParams->cabacInitIdc = pEncInst->slice.cabacInitIdc; + pCodeParams->transform8x8Mode = pEncInst->picParameterSet.transform8x8Mode; + pCodeParams->quarterPixelMv = pEncInst->slice.quarterPixelMv; + + pCodeParams->cirStart = regs->cirStart; + pCodeParams->cirInterval = regs->cirInterval; + pCodeParams->intraSliceMap1 = pEncInst->intraSliceMap[0]; + pCodeParams->intraSliceMap2 = pEncInst->intraSliceMap[1]; + pCodeParams->intraSliceMap3 = pEncInst->intraSliceMap[2]; + pCodeParams->intraArea.enable = regs->intraAreaTop < pEncInst->mbPerCol ? 1 : 0; + pCodeParams->intraArea.top = regs->intraAreaTop; + pCodeParams->intraArea.left = regs->intraAreaLeft; + pCodeParams->intraArea.bottom = regs->intraAreaBottom; + pCodeParams->intraArea.right = regs->intraAreaRight; + pCodeParams->roi1Area.enable = regs->roi1Top < pEncInst->mbPerCol ? 1 : 0; + pCodeParams->roi1Area.top = regs->roi1Top; + pCodeParams->roi1Area.left = regs->roi1Left; + pCodeParams->roi1Area.bottom = regs->roi1Bottom; + pCodeParams->roi1Area.right = regs->roi1Right; + pCodeParams->roi2Area.enable = regs->roi2Top < pEncInst->mbPerCol ? 1 : 0; + pCodeParams->roi2Area.top = regs->roi2Top; + pCodeParams->roi2Area.left = regs->roi2Left; + pCodeParams->roi2Area.bottom = regs->roi2Bottom; + pCodeParams->roi2Area.right = regs->roi2Right; + pCodeParams->roi1DeltaQp = -regs->roi1DeltaQp; + pCodeParams->roi2DeltaQp = -regs->roi2DeltaQp; + pCodeParams->adaptiveRoi = pEncInst->preProcess.adaptiveRoi; + pCodeParams->adaptiveRoiColor = pEncInst->preProcess.adaptiveRoiColor; + pCodeParams->roiMapEnable = pEncInst->preProcess.roiMapEnable; + pCodeParams->qpOffset[0] = pEncInst->preProcess.qpOffset[0]; + pCodeParams->qpOffset[1] = pEncInst->preProcess.qpOffset[1]; + pCodeParams->qpOffset[2] = pEncInst->preProcess.qpOffset[2]; + pCodeParams->gdrDuration = pEncInst->gdrEnabled ? pEncInst->gdrDuration : 0; + + H264EncDnfGetParameters(pEncInst, pCodeParams); + + pCodeParams->inputLineBufEn = pEncInst->inputLineBuf.inputLineBufEn; + pCodeParams->inputLineBufLoopBackEn = pEncInst->inputLineBuf.inputLineBufLoopBackEn; + pCodeParams->inputLineBufDepth = pEncInst->inputLineBuf.inputLineBufDepth; + pCodeParams->inputLineBufHwModeEn = pEncInst->inputLineBuf.inputLineBufHwModeEn; + + pCodeParams->nBaseLayerPID = pEncInst->svc.base_priority_id; + + APITRACE("H264EncGetCodingCtrl: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncSetRateCtrl + Description : Sets rate control parameters + + Return type : H264EncRet + Argument : inst - the instance in use + pRateCtrl - user provided parameters +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetRateCtrl(H264EncInst inst, + const H264EncRateCtrl * pRateCtrl) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + h264RateControl_s *rc; + i32 prevBitrate; + + u32 i, tmp; + + APITRACE("H264EncSetRateCtrl#"); + APITRACEPARAM("pictureRc", pRateCtrl->pictureRc); + APITRACEPARAM("mbRc", pRateCtrl->mbRc); + APITRACEPARAM("pictureSkip", pRateCtrl->pictureSkip); + APITRACEPARAM("qpHdr", pRateCtrl->qpHdr); + APITRACEPARAM("qpMin", pRateCtrl->qpMin); + APITRACEPARAM("qpMax", pRateCtrl->qpMax); + APITRACEPARAM("bitPerSecond", pRateCtrl->bitPerSecond); + APITRACEPARAM("gopLen", pRateCtrl->gopLen); + APITRACEPARAM("hrd", pRateCtrl->hrd); + APITRACEPARAM("hrdCpbSize", pRateCtrl->hrdCpbSize); + APITRACEPARAM("intraQpDelta", pRateCtrl->intraQpDelta); + APITRACEPARAM("fixedIntraQp", pRateCtrl->fixedIntraQp); + APITRACEPARAM("mbQpAdjustment", pRateCtrl->mbQpAdjustment); + APITRACEPARAM("longTermPicRate", pRateCtrl->longTermPicRate); + APITRACEPARAM("mbQpAutoBoost", pRateCtrl->mbQpAutoBoost); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pRateCtrl == NULL)) + { + APITRACE("H264EncSetRateCtrl: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncSetRateCtrl: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + rc = &pEncInst->rateControl; + + /* after stream was started with HRD ON, + * it is not allowed to change RC params */ + if(pEncInst->encStatus == H264ENCSTAT_START_FRAME && rc->hrd == ENCHW_YES) + { + APITRACE + ("H264EncSetRateCtrl: ERROR Stream started with HRD ON. Not allowed to change any parameters"); + return H264ENC_INVALID_STATUS; + } + + /* Check for invalid input values */ + if(pRateCtrl->pictureRc > 1 || + pRateCtrl->mbRc > 1 || pRateCtrl->pictureSkip > 1 || pRateCtrl->hrd > 1) + { + APITRACE("H264EncSetRateCtrl: ERROR Invalid enable/disable value"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pRateCtrl->qpHdr > 51 || + pRateCtrl->qpMin > 51 || + pRateCtrl->qpMax > 51 || + pRateCtrl->qpMax < pRateCtrl->qpMin) + { + APITRACE("H264EncSetRateCtrl: ERROR Invalid QP"); + return H264ENC_INVALID_ARGUMENT; + } + + if((pRateCtrl->qpHdr != -1) && + (pRateCtrl->qpHdr < (i32)pRateCtrl->qpMin || + pRateCtrl->qpHdr > (i32)pRateCtrl->qpMax)) + { + APITRACE("H264EncSetRateCtrl: ERROR QP out of range"); + return H264ENC_INVALID_ARGUMENT; + } + if((u32)(pRateCtrl->intraQpDelta + 51) > 102) + { + APITRACE("H264EncSetRateCtrl: ERROR intraQpDelta out of range"); + return H264ENC_INVALID_ARGUMENT; + } + if(pRateCtrl->fixedIntraQp > 51) + { + APITRACE("H264EncSetRateCtrl: ERROR fixedIntraQp out of range"); + return H264ENC_INVALID_ARGUMENT; + } + if(pRateCtrl->gopLen < 1 || pRateCtrl->gopLen > 300) + { + APITRACE("H264EncSetRateCtrl: ERROR Invalid GOP length"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Bitrate affects only when rate control is enabled */ + if((pRateCtrl->pictureRc || + pRateCtrl->pictureSkip || pRateCtrl->hrd) && + (pRateCtrl->bitPerSecond < 10000 || + pRateCtrl->bitPerSecond > H264ENC_MAX_BITRATE)) + { + APITRACE("H264EncSetRateCtrl: ERROR Invalid bitPerSecond"); + return H264ENC_INVALID_ARGUMENT; + } + + { + u32 cpbSize = pRateCtrl->hrdCpbSize; + u32 bps = pRateCtrl->bitPerSecond; + u32 level = pEncInst->seqParameterSet.levelIdx; + + /* Limit maximum bitrate based on resolution and frame rate */ + /* Saturates really high settings */ + /* bits per unpacked frame */ + tmp = 3 * 8 * pEncInst->mbPerFrame * 256 / 2; + /* bits per second */ + tmp = H264Calculate(tmp, rc->outRateNum, rc->outRateDenom); + if (bps > (tmp / 2)) + bps = tmp / 2; + + if(cpbSize == 0) + cpbSize = H264MaxCPBS[level]; + else if(cpbSize == (u32) (-1)) + cpbSize = bps; + + /* Limit minimum CPB size based on average bits per frame */ + tmp = H264Calculate(bps, rc->outRateDenom, rc->outRateNum); + cpbSize = MAX(cpbSize, tmp); + + /* cpbSize must be rounded so it is exactly the size written in stream */ + i = 0; + tmp = cpbSize; + while (4095 < (tmp >> (4 + i++))); + + cpbSize = (tmp >> (4 + i)) << (4 + i); + + /* if HRD is ON we have to obay all its limits */ + if(pRateCtrl->hrd != 0) + { + if(cpbSize > H264MaxCPBS[level]) + { + APITRACE + ("H264EncSetRateCtrl: ERROR. HRD is ON. hrdCpbSize higher than maximum allowed for stream level"); + return H264ENC_INVALID_ARGUMENT; + } + + if(bps > H264MaxBR[level]) + { + APITRACE + ("H264EncSetRateCtrl: ERROR. HRD is ON. bitPerSecond higher than maximum allowed for stream level"); + return H264ENC_INVALID_ARGUMENT; + } + } + + rc->virtualBuffer.bufferSize = cpbSize; + + /* Set the parameters to rate control */ + if(pRateCtrl->pictureRc != 0) + rc->picRc = ENCHW_YES; + else + rc->picRc = ENCHW_NO; + + rc->mbRc = pRateCtrl->mbRc; + + if(pRateCtrl->pictureSkip != 0) + rc->picSkip = ENCHW_YES; + else + rc->picSkip = ENCHW_NO; + + if(pRateCtrl->hrd != 0) + { + rc->hrd = ENCHW_YES; + rc->picRc = ENCHW_YES; + if(rc->mbRc == 0) + rc->mbRc = 1; + } + else + rc->hrd = ENCHW_NO; + + rc->qpHdr = pRateCtrl->qpHdr << QP_FRACTIONAL_BITS; + rc->qpMin = pRateCtrl->qpMin << QP_FRACTIONAL_BITS; + rc->qpMax = pRateCtrl->qpMax << QP_FRACTIONAL_BITS; + prevBitrate = rc->virtualBuffer.bitRate; + rc->virtualBuffer.bitRate = bps; + rc->gopLen = pRateCtrl->gopLen; + } + rc->intraQpDelta = pRateCtrl->intraQpDelta << QP_FRACTIONAL_BITS; + rc->fixedIntraQp = pRateCtrl->fixedIntraQp << QP_FRACTIONAL_BITS; + rc->mbQpAdjustment[0] = pRateCtrl->mbQpAdjustment*2; + rc->mbQpAdjustment[1] = pRateCtrl->mbQpAdjustment*3; + rc->mbQpAdjustment[2] = pRateCtrl->mbQpAdjustment*4; + rc->longTermPicRate = pRateCtrl->longTermPicRate; + rc->mbQpAutoBoost = pRateCtrl->mbQpAutoBoost; + + if(rc->mbRc != 0) + { + rc->mbQpAutoBoost = 0; + rc->mbQpAdjustment[0] = 0; + rc->mbQpAdjustment[1] = 0; + rc->mbQpAdjustment[2] = 0; + } + + /* New parameters checked already so ignore return value. + * Reset RC bit counters when changing bitrate. */ + (void) H264InitRc(rc, (pEncInst->encStatus == H264ENCSTAT_INIT) || + (rc->virtualBuffer.bitRate != prevBitrate)); + + APITRACE("H264EncSetRateCtrl: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncGetRateCtrl + Description : Return current rate control parameters + + Return type : H264EncRet + Argument : inst - the instance in use + pRateCtrl - place where parameters are returned +------------------------------------------------------------------------------*/ +H264EncRet H264EncGetRateCtrl(H264EncInst inst, H264EncRateCtrl * pRateCtrl) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + h264RateControl_s *rc; + + APITRACE("H264EncGetRateCtrl#"); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pRateCtrl == NULL)) + { + APITRACE("H264EncGetRateCtrl: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncGetRateCtrl: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* Get the values */ + rc = &pEncInst->rateControl; + + pRateCtrl->pictureRc = rc->picRc == ENCHW_NO ? 0 : 1; + pRateCtrl->mbRc = rc->mbRc; + pRateCtrl->pictureSkip = rc->picSkip == ENCHW_NO ? 0 : 1; + pRateCtrl->qpHdr = rc->qpHdr >> QP_FRACTIONAL_BITS; + pRateCtrl->qpMin = rc->qpMin >> QP_FRACTIONAL_BITS; + pRateCtrl->qpMax = rc->qpMax >> QP_FRACTIONAL_BITS; + pRateCtrl->bitPerSecond = rc->virtualBuffer.bitRate; + pRateCtrl->hrd = rc->hrd == ENCHW_NO ? 0 : 1; + pRateCtrl->gopLen = rc->gopLen; + + pRateCtrl->hrdCpbSize = (u32) rc->virtualBuffer.bufferSize; + pRateCtrl->intraQpDelta = rc->intraQpDelta >> QP_FRACTIONAL_BITS; + pRateCtrl->fixedIntraQp = rc->fixedIntraQp >> QP_FRACTIONAL_BITS; + pRateCtrl->mbQpAdjustment = rc->mbQpAdjustment[0]/2; + pRateCtrl->longTermPicRate = rc->longTermPicRate; + pRateCtrl->mbQpAutoBoost = rc->mbQpAutoBoost; + + APITRACE("H264EncGetRateCtrl: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : VSCheckSize + Description : + Return type : i32 + Argument : u32 inputWidth + Argument : u32 inputHeight + Argument : u32 stabilizedWidth + Argument : u32 stabilizedHeight +------------------------------------------------------------------------------*/ +i32 VSCheckSize(u32 inputWidth, u32 inputHeight, u32 stabilizedWidth, + u32 stabilizedHeight) +{ + /* Input picture minimum dimensions */ + if((inputWidth < 104) || (inputHeight < 104)) + return 1; + + /* Stabilized picture minimum values */ + if((stabilizedWidth < 96) || (stabilizedHeight < 96)) + return 1; + + /* Stabilized dimensions multiple of 4 */ + if(((stabilizedWidth & 3) != 0) || ((stabilizedHeight & 3) != 0)) + return 1; + + /* Edge >= 4 pixels, not checked because stabilization can be + * used without cropping for scene detection + if((inputWidth < (stabilizedWidth + 8)) || + (inputHeight < (stabilizedHeight + 8))) + return 1; */ + + return 0; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncSetPreProcessing + Description : Sets the preprocessing parameters + Return type : H264EncRet + Argument : inst - encoder instance in use + Argument : pPreProcCfg - user provided parameters +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetPreProcessing(H264EncInst inst, + const H264EncPreProcessingCfg * pPreProcCfg) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + preProcess_s pp_tmp; + + APITRACE("H264EncSetPreProcessing#"); + APITRACEPARAM("origWidth", pPreProcCfg->origWidth); + APITRACEPARAM("origHeight", pPreProcCfg->origHeight); + APITRACEPARAM("xOffset", pPreProcCfg->xOffset); + APITRACEPARAM("yOffset", pPreProcCfg->yOffset); + APITRACEPARAM("inputType", pPreProcCfg->inputType); + APITRACEPARAM("rotation", pPreProcCfg->rotation); + APITRACEPARAM("videoStabilization", pPreProcCfg->videoStabilization); + APITRACEPARAM("colorConversion.type", pPreProcCfg->colorConversion.type); + APITRACEPARAM("colorConversion.coeffA", pPreProcCfg->colorConversion.coeffA); + APITRACEPARAM("colorConversion.coeffB", pPreProcCfg->colorConversion.coeffB); + APITRACEPARAM("colorConversion.coeffC", pPreProcCfg->colorConversion.coeffC); + APITRACEPARAM("colorConversion.coeffE", pPreProcCfg->colorConversion.coeffE); + APITRACEPARAM("colorConversion.coeffF", pPreProcCfg->colorConversion.coeffF); + APITRACEPARAM("scaledOutput", pPreProcCfg->scaledOutput); + APITRACEPARAM("interlacedFrame", pPreProcCfg->interlacedFrame); + + /* Check for illegal inputs */ + if((inst == NULL) || (pPreProcCfg == NULL)) + { + APITRACE("H264EncSetPreProcessing: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncSetPreProcessing: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* check HW limitations */ + { + EWLHwConfig_t cfg = EWLReadAsicConfig(); + + /* is video stabilization supported? */ + if(cfg.vsEnabled == EWL_HW_CONFIG_NOT_SUPPORTED && + pPreProcCfg->videoStabilization != 0) + { + APITRACE("H264EncSetPreProcessing: ERROR Stabilization not supported"); + return H264ENC_INVALID_ARGUMENT; + } + if(cfg.rgbEnabled == EWL_HW_CONFIG_NOT_SUPPORTED && + pPreProcCfg->inputType >= H264ENC_RGB565 && + pPreProcCfg->inputType <= H264ENC_BGR101010) + { + APITRACE("H264EncSetPreProcessing: ERROR RGB input not supported"); + return H264ENC_INVALID_ARGUMENT; + } + if(cfg.scalingEnabled == EWL_HW_CONFIG_NOT_SUPPORTED && + pPreProcCfg->scaledOutput != 0) + { + APITRACE("H264EncSetPreProcessing: WARNING Scaling not supported, disabling output"); + } + } + + if(pPreProcCfg->origWidth > H264ENC_MAX_PP_INPUT_WIDTH || + pPreProcCfg->origHeight > H264ENC_MAX_PP_INPUT_HEIGHT) + { + APITRACE("H264EncSetPreProcessing: ERROR Too big input image"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pPreProcCfg->inputType > H264ENC_P010) + { + APITRACE("H264EncSetPreProcessing: ERROR Invalid YUV type"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pPreProcCfg->rotation > H264ENC_ROTATE_180R) + { + APITRACE("H264EncSetPreProcessing: ERROR Invalid rotation"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pEncInst->interlaced && pPreProcCfg->rotation) + { + APITRACE("H264EncSetPreProcessing: ERROR Rotation and interlace"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Input Line buffer is not supported for stabilization*/ + if(pEncInst->inputLineBuf.inputLineBufEn && pPreProcCfg->videoStabilization) + { + APITRACE("H264EncSetPreProcessing: Input Line buffer is not supportted for stabilization feature"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Input Line buffer is not supported rotation */ + if(pEncInst->inputLineBuf.inputLineBufEn && pPreProcCfg->rotation) + { + APITRACE("H264EncSetPreProcessing: ERROR Rotation and Line Buffer Mode"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Encoded frame resolution as set in Init() */ + pp_tmp = pEncInst->preProcess; + + if(pPreProcCfg->videoStabilization == 0) { + pp_tmp.horOffsetSrc = pPreProcCfg->xOffset; + pp_tmp.verOffsetSrc = pPreProcCfg->yOffset; + } else { + pp_tmp.horOffsetSrc = pp_tmp.verOffsetSrc = 0; + } + + pp_tmp.lumWidthSrc = pPreProcCfg->origWidth; + pp_tmp.lumHeightSrc = pPreProcCfg->origHeight; + pp_tmp.rotation = pPreProcCfg->rotation; + pp_tmp.inputFormat = pPreProcCfg->inputType; + pp_tmp.videoStab = (pPreProcCfg->videoStabilization != 0) ? 1 : 0; + pp_tmp.interlacedFrame = (pPreProcCfg->interlacedFrame != 0) ? 1 : 0; + + pp_tmp.scaledOutput = (pPreProcCfg->scaledOutput) ? 1 : 0; + if (pEncInst->preProcess.scaledWidth*pEncInst->preProcess.scaledHeight == 0) + pp_tmp.scaledOutput = 0; + + /* Check for invalid values */ + if(EncPreProcessCheck(&pp_tmp) != ENCHW_OK) + { + APITRACE("H264EncSetPreProcessing: ERROR Invalid cropping values"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Set cropping parameters if required */ + if( pEncInst->preProcess.lumWidth%16 || pEncInst->preProcess.lumHeight%16 ) + { + u32 fillRight = (pEncInst->preProcess.lumWidth+15)/16*16 - + pEncInst->preProcess.lumWidth; + u32 fillBottom = (pEncInst->preProcess.lumHeight+15)/16*16 - + pEncInst->preProcess.lumHeight; + + pEncInst->seqParameterSet.frameCropping = ENCHW_YES; + pEncInst->seqParameterSet.frameCropLeftOffset = 0; + pEncInst->seqParameterSet.frameCropRightOffset = 0; + pEncInst->seqParameterSet.frameCropTopOffset = 0; + pEncInst->seqParameterSet.frameCropBottomOffset = 0; + + if (pPreProcCfg->rotation == 0) { /* No rotation */ + pEncInst->seqParameterSet.frameCropRightOffset = fillRight/2; + pEncInst->seqParameterSet.frameCropBottomOffset = fillBottom/2; + } else if (pPreProcCfg->rotation == 1) { /* Rotate right */ + pEncInst->seqParameterSet.frameCropLeftOffset = fillRight/2; + pEncInst->seqParameterSet.frameCropBottomOffset = fillBottom/2; + } else if (pPreProcCfg->rotation == 2) { /* Rotate left */ + pEncInst->seqParameterSet.frameCropRightOffset = fillRight/2; + pEncInst->seqParameterSet.frameCropTopOffset = fillBottom/2; + } else if (pPreProcCfg->rotation == 3) { /* Rotate left */ + pEncInst->seqParameterSet.frameCropTopOffset = fillBottom/2; + pEncInst->seqParameterSet.frameCropLeftOffset = fillRight/2; + } + } + + if(pp_tmp.videoStab != 0) + { + u32 width = pp_tmp.lumWidth; + u32 height = pp_tmp.lumHeight; + u32 heightSrc = pp_tmp.lumHeightSrc; + + if(pp_tmp.rotation == 1 || pp_tmp.rotation == 2) + { + u32 tmp; + + tmp = width; + width = height; + height = tmp; + } + + if(VSCheckSize(pp_tmp.lumWidthSrc, heightSrc, width, height) + != 0) + { + APITRACE + ("H264EncSetPreProcessing: ERROR Invalid size for stabilization"); + return H264ENC_INVALID_ARGUMENT; + } + +#ifdef VIDEOSTAB_ENABLED + VSAlgInit(&pEncInst->vsSwData, pp_tmp.lumWidthSrc, heightSrc, + width, height); + + VSAlgGetResult(&pEncInst->vsSwData, &pp_tmp.horOffsetSrc, + &pp_tmp.verOffsetSrc); +#endif + } + + pp_tmp.colorConversionType = pPreProcCfg->colorConversion.type; + pp_tmp.colorConversionCoeffA = pPreProcCfg->colorConversion.coeffA; + pp_tmp.colorConversionCoeffB = pPreProcCfg->colorConversion.coeffB; + pp_tmp.colorConversionCoeffC = pPreProcCfg->colorConversion.coeffC; + pp_tmp.colorConversionCoeffE = pPreProcCfg->colorConversion.coeffE; + pp_tmp.colorConversionCoeffF = pPreProcCfg->colorConversion.coeffF; + EncSetColorConversion(&pp_tmp, &pEncInst->asic); + + pEncInst->preProcess = pp_tmp; + + APITRACE("H264EncSetPreProcessing: OK"); + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncGetPreProcessing + Description : Returns current preprocessing parameters + Return type : H264EncRet + Argument : inst - encoder instance + Argument : pPreProcCfg - place where the parameters are returned +------------------------------------------------------------------------------*/ +H264EncRet H264EncGetPreProcessing(H264EncInst inst, + H264EncPreProcessingCfg * pPreProcCfg) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + preProcess_s *pPP; + + APITRACE("H264EncGetPreProcessing#"); + + /* Check for illegal inputs */ + if((inst == NULL) || (pPreProcCfg == NULL)) + { + APITRACE("H264EncGetPreProcessing: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncGetPreProcessing: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + pPP = &pEncInst->preProcess; + + pPreProcCfg->origHeight = pPP->lumHeightSrc; + pPreProcCfg->origWidth = pPP->lumWidthSrc; + pPreProcCfg->xOffset = pPP->horOffsetSrc; + pPreProcCfg->yOffset = pPP->verOffsetSrc; + + pPreProcCfg->rotation = (H264EncPictureRotation) pPP->rotation; + pPreProcCfg->inputType = (H264EncPictureType) pPP->inputFormat; + + pPreProcCfg->interlacedFrame = pPP->interlacedFrame; + pPreProcCfg->videoStabilization = pPP->videoStab; + pPreProcCfg->scaledOutput = pPP->scaledOutput; + + pPreProcCfg->colorConversion.type = + (H264EncColorConversionType) pPP->colorConversionType; + pPreProcCfg->colorConversion.coeffA = pPP->colorConversionCoeffA; + pPreProcCfg->colorConversion.coeffB = pPP->colorConversionCoeffB; + pPreProcCfg->colorConversion.coeffC = pPP->colorConversionCoeffC; + pPreProcCfg->colorConversion.coeffE = pPP->colorConversionCoeffE; + pPreProcCfg->colorConversion.coeffF = pPP->colorConversionCoeffF; + + APITRACE("H264EncGetPreProcessing: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncSetRoiMap + Description : Returns current roimap status + Return type : H264EncRet + Argument : inst - encoder instance + Argument : map - place where the roi index map for each mb in raster scan way. +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetRoiMap(H264EncInst inst, u8 *roimap) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + regValues_s *regs = &pEncInst->asic.regs; + u32 *map = pEncInst->asic.segmentMap.virtualAddress; + u32 mask, mb, x, y; + int idx = 0; + + APITRACE("H264EncSetRoiMap#"); + + /* Check for illegal inputs */ + if (inst == NULL) + { + APITRACE("H264EncSetRoiMap: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + regs->segmentEnable = 1; + regs->segmentMapUpdate = 1; + /* Set AROI (ID=3), ROI1 (ID=1) and ROI2 (ID=2) into segment map. */ + for (y = 0, mb = 0, mask = 0; y < pEncInst->mbPerCol; y++) + { + for (x = 0; x < pEncInst->mbPerRow; x++, mb++) + { + u32 id = (u32)roimap[idx++]; + mask |= id << (28 - 4 * (mb % 8)); + if ((mb % 8) == 7) { + *map++ = mask; + mask = 0; + } + } + } + *map++ = mask; + pEncInst->preProcess.roiCoded = 1; /* AROI is coded into stream */ + + APITRACE("H264EncSetRoiMap: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncSetSeiUserData + Description : Sets user data SEI messages + Return type : H264EncRet + Argument : inst - the instance in use + pUserData - pointer to userData, this is used by the + encoder so it must not be released before + disabling user data + userDataSize - size of userData, minimum size 16, + maximum size H264ENC_MAX_USER_DATA_SIZE + not valid size disables userData sei messages +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetSeiUserData(H264EncInst inst, const u8 * pUserData, + u32 userDataSize) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + APITRACE("H264EncSetSeiUserData#"); + APITRACEPARAM("userDataSize", userDataSize); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (userDataSize != 0 && pUserData == NULL)) + { + APITRACE("H264EncSetSeiUserData: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncSetSeiUserData: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* Disable user data */ + if((userDataSize < 16) || (userDataSize > H264ENC_MAX_USER_DATA_SIZE)) + { + pEncInst->rateControl.sei.userDataEnabled = ENCHW_NO; + pEncInst->rateControl.sei.pUserData = NULL; + pEncInst->rateControl.sei.userDataSize = 0; + } + else + { + pEncInst->rateControl.sei.userDataEnabled = ENCHW_YES; + pEncInst->rateControl.sei.pUserData = pUserData; + pEncInst->rateControl.sei.userDataSize = userDataSize; + } + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncStrmStart + Description : Starts a new stream + Return type : H264EncRet + Argument : inst - encoder instance + Argument : pEncIn - user provided input parameters + pEncOut - place where output info is returned +------------------------------------------------------------------------------*/ +H264EncRet H264EncStrmStart(H264EncInst inst, const H264EncIn * pEncIn, + H264EncOut * pEncOut) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + h264RateControl_s *rc; + u32 tmp; + + APITRACE("H264EncStrmStart#"); + APITRACEPARAM("busLuma", pEncIn->busLuma); + APITRACEPARAM("busChromaU", pEncIn->busChromaU); + APITRACEPARAM("busChromaV", pEncIn->busChromaV); + APITRACEPARAM("pOutBuf", pEncIn->pOutBuf); + APITRACEPARAM("busOutBuf", pEncIn->busOutBuf); + APITRACEPARAM("outBufSize", pEncIn->outBufSize); + APITRACEPARAM("codingType", pEncIn->codingType); + APITRACEPARAM("timeIncrement", pEncIn->timeIncrement); + APITRACEPARAM("busLumaStab", pEncIn->busLumaStab); + APITRACEPARAM("ipf", pEncIn->ipf); + APITRACEPARAM("ltrf", pEncIn->ltrf); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pEncIn == NULL) || (pEncOut == NULL)) + { + APITRACE("H264EncStrmStart: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncStrmStart: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + pEncOut->streamSize = 0; + + rc = &pEncInst->rateControl; + + /* Check status */ + if((pEncInst->encStatus != H264ENCSTAT_INIT) && + (pEncInst->encStatus != H264ENCSTAT_START_FRAME)) + { + APITRACE("H264EncStrmStart: ERROR Invalid status"); + return H264ENC_INVALID_STATUS; + } + + /* Check for invalid input values */ + if((pEncIn->pOutBuf == NULL) || + (pEncIn->outBufSize < H264ENCSTRMSTART_MIN_BUF)) + { + APITRACE("H264EncStrmStart: ERROR Invalid input. Stream buffer"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Set stream buffer, the size has been checked */ + (void) H264SetBuffer(&pEncInst->stream, (u8 *) pEncIn->pOutBuf, + (u32) pEncIn->outBufSize); + + /* Set pointer to the beginning of NAL unit size buffer */ + pEncOut->pNaluSizeBuf = (u32 *) pEncInst->asic.sizeTbl.virtualAddress; + pEncOut->numNalus = 0; + +#ifdef TRACE_STREAM + /* Open stream tracing */ + EncOpenStreamTrace("stream.trc"); + + traceStream.frameNum = pEncInst->frameCnt; + traceStream.id = 0; /* Stream generated by SW */ + traceStream.bitCnt = 0; /* New frame */ +#endif + + /* Set the profile to be used */ + pEncInst->seqParameterSet.profileIdc = 66; /* base profile */ + + /* Interlaced => main profile */ + if (pEncInst->interlaced >= 1) + pEncInst->seqParameterSet.profileIdc = 77; + + /* CABAC => main profile */ + if (pEncInst->picParameterSet.enableCabac >= 1) + pEncInst->seqParameterSet.profileIdc = 77; + + /* 8x8 transform enabled => high profile */ + if (pEncInst->picParameterSet.transform8x8Mode == ENCHW_YES) + pEncInst->seqParameterSet.profileIdc = 100; + + if (pEncIn->sendAUD) + { + tmp = pEncInst->stream.byteCnt; + H264AccessUnitDelimiter(&pEncInst->stream, pEncInst->seqParameterSet.byteStream, 2); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt - tmp); + } + + /* update VUI */ + if(rc->sei.enabled == ENCHW_YES) + { + H264SpsSetVuiPictStructPresentFlag(&pEncInst->seqParameterSet, 1); + } + + if(rc->hrd == ENCHW_YES) + { + H264SpsSetVuiHrd(&pEncInst->seqParameterSet, 1); + + H264SpsSetVuiHrdBitRate(&pEncInst->seqParameterSet, + rc->virtualBuffer.bitRate); + + H264SpsSetVuiHrdCpbSize(&pEncInst->seqParameterSet, + rc->virtualBuffer.bufferSize); + } + + /* Initialize cabac context tables for HW */ + if (pEncInst->picParameterSet.enableCabac >= 1) + { + if (H264CabacInit(pEncInst->asic.cabacCtx.virtualAddress, + pEncInst->slice.cabacInitIdc) != 0) + { + APITRACE("H264EncStrmStart: ERROR in CABAC Context Init"); + return H264ENC_MEMORY_ERROR; + } + } + + /* Use the first frame QP in the PPS */ + pEncInst->picParameterSet.picInitQpMinus26 = (i32) (rc->qpHdr >> QP_FRACTIONAL_BITS) - 26; + pEncInst->picParameterSet.picParameterSetId = 0; + + if((pEncInst->picParameterSet.enableCabac == 0) || + (pEncInst->picParameterSet.enableCabac == 2)) + pEncInst->picParameterSet.entropyCodingMode = ENCHW_NO; + else + pEncInst->picParameterSet.entropyCodingMode = ENCHW_YES; + + /* Init SEI */ + H264InitSei(&rc->sei, pEncInst->seqParameterSet.byteStream, + rc->hrd, rc->outRateNum, rc->outRateDenom); + + if (pEncInst->svc.level) + { + tmp = pEncInst->stream.byteCnt; + H264SvcSeiNal(pEncInst); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + } + tmp = pEncInst->stream.byteCnt; + + H264SeqParameterSet(&pEncInst->stream, &pEncInst->seqParameterSet, ENCHW_YES); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + + /* Subset SPS for MVC */ + if (pEncInst->numViews > 1) + { + H264SubsetSeqParameterSet(&pEncInst->stream, &pEncInst->seqParameterSet); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + } + + H264PicParameterSet(&pEncInst->stream, &pEncInst->picParameterSet); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + + /* In CABAC mode 2 we need two PPS: one with CAVLC (ppsId=0 for intra) and + * one with CABAC (ppsId=1 for inter) */ + if (pEncInst->picParameterSet.enableCabac == 2) + { + pEncInst->picParameterSet.picParameterSetId = 1; + pEncInst->picParameterSet.entropyCodingMode = ENCHW_YES; + H264PicParameterSet(&pEncInst->stream, &pEncInst->picParameterSet); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + } + + if(pEncInst->stream.overflow == ENCHW_YES) + { + pEncOut->streamSize = 0; + pEncOut->numNalus = 0; + APITRACE("H264EncStrmStart: ERROR Output buffer too small"); + return H264ENC_OUTPUT_BUFFER_OVERFLOW; + } + + /* Bytes generated */ + pEncOut->streamSize = pEncInst->stream.byteCnt; + + /* Status == START_STREAM Stream started */ + pEncInst->encStatus = H264ENCSTAT_START_STREAM; + + pEncInst->slice.frameNum = 0; + pEncInst->rateControl.fillerIdx = (u32) (-1); + + if(rc->hrd == ENCHW_YES) + { + /* Update HRD Parameters to RC if needed */ + u32 bitrate = H264SpsGetVuiHrdBitRate(&pEncInst->seqParameterSet); + u32 cpbsize = H264SpsGetVuiHrdCpbSize(&pEncInst->seqParameterSet); + + if ((rc->virtualBuffer.bitRate != (i32)bitrate) || + (rc->virtualBuffer.bufferSize != (i32)cpbsize)) + { + rc->virtualBuffer.bitRate = bitrate; + rc->virtualBuffer.bufferSize = cpbsize; + (void) H264InitRc(rc, 1); + } + } + +#ifdef VIDEOSTAB_ENABLED + /* new stream so reset the stabilization */ + VSAlgReset(&pEncInst->vsSwData); +#endif + + APITRACE("H264EncStrmStart: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncStrmEncode + Description : Encodes a new picture + Return type : H264EncRet + Argument : inst - encoder instance + Argument : pEncIn - user provided input parameters + pEncOut - place where output info is returned +------------------------------------------------------------------------------*/ +H264EncRet H264EncStrmEncode(H264EncInst inst, const H264EncIn * pEncIn, + H264EncOut * pEncOut, + H264EncSliceReadyCallBackFunc sliceReadyCbFunc, + EncInputMBLineBufCallBackFunc lineBufCbFunc, + void * pAppData) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + slice_s *pSlice; + regValues_s *regs; + h264EncodeFrame_e ret; + H264EncPictureCodingType ct; + picBuffer *picBuffer; + sliceType_e rcSliceType; + u32 tmp = 0; + u32 setSpsPps = 0; + i32 top_pos,bottom_pos; + i32 prefix_nalu_length = 0; + u8 *prefix_nalu_addr = NULL; + APITRACE("H264EncStrmEncode#"); + APITRACEPARAMX("busLuma", pEncIn->busLuma); + APITRACEPARAMX("busChromaU", pEncIn->busChromaU); + APITRACEPARAMX("busChromaV", pEncIn->busChromaV); + APITRACEPARAMX("pOutBuf", pEncIn->pOutBuf); + APITRACEPARAMX("busOutBuf", pEncIn->busOutBuf); + APITRACEPARAM("outBufSize", pEncIn->outBufSize); + APITRACEPARAM("codingType", pEncIn->codingType); + APITRACEPARAM("timeIncrement", pEncIn->timeIncrement); + APITRACEPARAMX("busLumaStab", pEncIn->busLumaStab); + APITRACEPARAM("ipf", pEncIn->ipf); + APITRACEPARAM("ltrf", pEncIn->ltrf); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pEncIn == NULL) || (pEncOut == NULL)) + { + APITRACE("H264EncStrmEncode: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncStrmEncode: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* some shortcuts */ + pSlice = &pEncInst->slice; + regs = &pEncInst->asic.regs; + + /* Clear the output structure */ + pEncOut->codingType = H264ENC_NOTCODED_FRAME; + pEncOut->streamSize = 0; + pEncOut->ipf = pEncOut->ltrf = 0; + + /* Output buffer for down-scaled picture, 0/NULL when disabled. */ + pEncOut->busScaledLuma = regs->scaledLumBase; + pEncOut->scaledPicture = (u8*)pEncInst->asic.scaledImage.virtualAddress; + + /* Set pointer to the beginning of NAL unit size buffer */ + pEncOut->pNaluSizeBuf = (u32 *) pEncInst->asic.sizeTbl.virtualAddress; + pEncOut->numNalus = pEncInst->naluOffset = 0; + pEncInst->numNalus = 0; + + /* Clear the NAL unit size table */ + if(pEncOut->pNaluSizeBuf != NULL) + pEncOut->pNaluSizeBuf[0] = 0; + +#ifdef EVALUATION_LIMIT + /* Check for evaluation limit */ + if(pEncInst->frameCnt >= EVALUATION_LIMIT) + { + APITRACE("H264EncStrmEncode: OK Evaluation limit exceeded"); + return H264ENC_OK; + } +#endif + + /* Check status, INIT and ERROR not allowed */ + if((pEncInst->encStatus != H264ENCSTAT_START_STREAM) && + (pEncInst->encStatus != H264ENCSTAT_START_FRAME)) + { + APITRACE("H264EncStrmEncode: ERROR Invalid status"); + return H264ENC_INVALID_STATUS; + } + + /* Check for invalid input values */ + if((!H264_BUS_ADDRESS_VALID(pEncIn->busOutBuf)) || + (pEncIn->pOutBuf == NULL) || + (pEncIn->outBufSize < H264ENCSTRMENCODE_MIN_BUF) || + (pEncIn->codingType > H264ENC_NONIDR_INTRA_FRAME)) + { + APITRACE("H264EncStrmEncode: ERROR Invalid input. Output buffer"); + return H264ENC_INVALID_ARGUMENT; + } + + switch (pEncInst->preProcess.inputFormat) + { + case H264ENC_YUV420_PLANAR: + case H264ENC_P010: + if(!H264_BUS_ADDRESS_VALID(pEncIn->busChromaV)) + { + APITRACE("H264EncStrmEncode: ERROR Invalid input busChromaV"); + return H264ENC_INVALID_ARGUMENT; + } + /* fall through */ + case H264ENC_YUV420_SEMIPLANAR: + case H264ENC_YUV420_SEMIPLANAR_VU: + case H264ENC_SP_101010: + if(!H264_BUS_ADDRESS_VALID(pEncIn->busChromaU)) + { + APITRACE("H264EncStrmEncode: ERROR Invalid input busChromaU"); + return H264ENC_INVALID_ARGUMENT; + } + /* fall through */ + case H264ENC_YUV422_INTERLEAVED_YUYV: + case H264ENC_YUV422_INTERLEAVED_UYVY: + case H264ENC_RGB565: + case H264ENC_BGR565: + case H264ENC_RGB555: + case H264ENC_BGR555: + case H264ENC_RGB444: + case H264ENC_BGR444: + case H264ENC_RGB888: + case H264ENC_BGR888: + case H264ENC_RGB101010: + case H264ENC_BGR101010: + if(!H264_BUS_ADDRESS_VALID(pEncIn->busLuma)) + { + APITRACE("H264EncStrmEncode: ERROR Invalid input busLuma"); + return H264ENC_INVALID_ARGUMENT; + } + break; + default: + APITRACE("H264EncStrmEncode: ERROR Invalid input format"); + return H264ENC_INVALID_ARGUMENT; + } + + if(pEncInst->preProcess.videoStab) + { + if(!H264_BUS_ADDRESS_VALID(pEncIn->busLumaStab)) + { + APITRACE("H264EncStrmEncode: ERROR Invalid input busLumaStab"); + return H264ENC_INVALID_ARGUMENT; + } + } + + /* Set stream buffer, the size has been checked */ + if(H264SetBuffer(&pEncInst->stream, (u8 *) pEncIn->pOutBuf, + (i32) pEncIn->outBufSize) == ENCHW_NOK) + { + APITRACE("H264EncStrmEncode: ERROR Invalid output buffer"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Try to reserve the HW resource */ + if(EWLReserveHw(pEncInst->asic.ewl) == EWL_ERROR) + { + APITRACE("H264EncStrmEncode: ERROR HW unavailable"); + return H264ENC_HW_RESERVED; + } + /* update in/out buffers */ + regs->inputLumBase = pEncIn->busLuma; + regs->inputCbBase = pEncIn->busChromaU; + regs->inputCrBase = pEncIn->busChromaV; + + regs->outputStrmBase = pEncIn->busOutBuf; + regs->outputStrmSize = pEncIn->outBufSize; + + pEncInst->inputLineBuf.wrCnt = pEncIn->lineBufWrCnt; + pEncInst->inputLineBuf.cbFunc = lineBufCbFunc; + pEncInst->sliceReadyCbFunc = sliceReadyCbFunc; + pEncInst->pOutBuf = pEncIn->pOutBuf; + pEncInst->pAppData = pAppData; + pEncInst->rfcBufOverflow = ENCHW_NO; + + /* setup stabilization */ + if(pEncInst->preProcess.videoStab) + { + regs->vsNextLumaBase = pEncIn->busLumaStab; + } + + ct = pEncIn->codingType; + if((pEncInst->gdrEnabled == 1) && (pEncInst->encStatus == H264ENCSTAT_START_FRAME) && (pEncInst->gdrFirstIntraFrame == 0)) + { + regs->intraAreaTop = regs->intraAreaLeft = regs->intraAreaBottom = + regs->intraAreaRight = 255; + regs->roi1Top = regs->roi1Left = regs->roi1Bottom = + regs->roi1Right = 255; + regs->roi1DeltaQp = 0; + if(pEncIn->codingType == H264ENC_INTRA_FRAME) + { + pEncInst->gdrStart++ ; + ct = H264ENC_PREDICTED_FRAME; + } + else if(pEncIn->codingType == H264ENC_NONIDR_INTRA_FRAME) + { + ct = H264ENC_PREDICTED_FRAME; + } + if(pEncInst->gdrStart) + { + if(pEncInst->gdrCount == 0) + pEncInst->rateControl.sei.insertRecoveryPointMessage = ENCHW_YES; + else + pEncInst->rateControl.sei.insertRecoveryPointMessage = ENCHW_NO; + top_pos = (pEncInst->gdrCount / (1 + pEncInst->interlaced)) * pEncInst->gdrAverageMBRows; + bottom_pos = 0; + if(pEncInst->gdrMBLeft) + { + if((pEncInst->gdrCount / (1 + (i32)pEncInst->interlaced)) < pEncInst->gdrMBLeft) + { + top_pos += (pEncInst->gdrCount / (1 + (i32)pEncInst->interlaced)); + bottom_pos += 1; + } + else + { + top_pos += pEncInst->gdrMBLeft; + } + } + bottom_pos += top_pos + pEncInst->gdrAverageMBRows; +#ifndef SEARCH_AREA_SMALL + bottom_pos += 1; +#endif + if(bottom_pos > ((i32)pEncInst->mbPerCol - 1)) + { + bottom_pos=pEncInst->mbPerCol - 1; + } + + regs->intraAreaTop = top_pos; + regs->intraAreaLeft = 0; + regs->intraAreaBottom = bottom_pos; + regs->intraAreaRight = pEncInst->mbPerRow - 1; + + //to make video quality in intra area is close to inter area. + regs->roi1Top = top_pos; + regs->roi1Left = 0; + regs->roi1Bottom = bottom_pos; + regs->roi1Right = pEncInst->mbPerRow - 1; + + regs->roi1DeltaQp = 3; + } + + regs->roiUpdate = 1; /* ROI has changed from previous frame. */ + + } + + if (pEncInst->svc.level==0) + { + /* Status may affect the frame coding type */ + if(pEncInst->encStatus == H264ENCSTAT_START_STREAM) + { + ct = H264ENC_INTRA_FRAME; + } +#ifdef VIDEOSTAB_ENABLED + if(pEncInst->vsSwData.sceneChange) + { + pEncInst->encStatus = H264ENCSTAT_START_STREAM; + pEncInst->vsSwData.sceneChange = 0; + ct = H264ENC_INTRA_FRAME; + } +#endif + pSlice->prevFrameNum = pSlice->frameNum; + + /* MVC view frames are always predicted from base view. */ + if ((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 1)) + ct = H264ENC_PREDICTED_FRAME; + + /* Interlaced picture second field can't be IDR. */ + if (pEncInst->interlaced && ((pSlice->frameNum % 2) == 1) && + (ct == H264ENC_INTRA_FRAME)) + ct = H264ENC_NONIDR_INTRA_FRAME; + + /* Frame coding type defines the NAL unit type */ + switch (ct) + { + case H264ENC_INTRA_FRAME: + /* IDR-slice */ + pSlice->nalUnitType = IDR; + pSlice->sliceType = rcSliceType = ISLICE; + pSlice->frameNum = 0; + pEncInst->preProcess.intra = 1; + H264MadInit(&pEncInst->mad, pEncInst->mbPerFrame); + break; + case H264ENC_NONIDR_INTRA_FRAME: + /* non-IDR P-slice */ + pSlice->nalUnitType = NONIDR; + pSlice->sliceType = rcSliceType = ISLICE; + if (pEncInst->interlaced) rcSliceType = PSLICE; /* No new GOP */ + pEncInst->preProcess.intra = 0; + break; + case H264ENC_PREDICTED_FRAME: + default: + /* non-IDR P-slice */ + pSlice->nalUnitType = NONIDR; + pSlice->sliceType = rcSliceType = PSLICE; + pEncInst->preProcess.intra = 0; + break; + } + + /* Interlaced with intra-only, top and bottom fields. */ + if (pEncInst->interlaced && ((pSlice->prevFrameNum % 2) == 1)) + pSlice->frameNum = pSlice->prevFrameNum; + + } + else + { + /* Status may affect the frame coding type */ + if(pEncInst->encStatus == H264ENCSTAT_START_STREAM) + { + ct = H264ENC_INTRA_FRAME; + } +#ifdef VIDEOSTAB_ENABLED + if(pEncInst->vsSwData.sceneChange) + { + pEncInst->encStatus = H264ENCSTAT_START_STREAM; + pEncInst->vsSwData.sceneChange = 0; + ct = H264ENC_INTRA_FRAME; + } +#endif + pSlice->prevFrameNum = pSlice->frameNum; + + /* MVC view frames are always predicted from base view. */ + if ((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 1)) + ct = H264ENC_PREDICTED_FRAME; + + /* Interlaced picture second field can't be IDR. */ + if (pEncInst->interlaced && ((pSlice->frameNum % 2) == 1) && + (ct == H264ENC_INTRA_FRAME)) + ct = H264ENC_NONIDR_INTRA_FRAME; + + /* Frame coding type defines the NAL unit type */ + switch (ct) + { + case H264ENC_INTRA_FRAME: + /* IDR-slice */ + pSlice->nalUnitType = IDR; + pSlice->sliceType = rcSliceType = ISLICE; + pSlice->frameNum = 0; + pEncInst->preProcess.intra = 1; + H264MadInit(&pEncInst->mad, pEncInst->mbPerFrame); + break; + case H264ENC_NONIDR_INTRA_FRAME: + /* non-IDR P-slice */ + pSlice->nalUnitType = NONIDR; + pSlice->sliceType = rcSliceType = ISLICE; + if (pEncInst->interlaced) rcSliceType = PSLICE; /* No new GOP */ + pEncInst->preProcess.intra = 0; + break; + case H264ENC_PREDICTED_FRAME: + default: + /* non-IDR P-slice */ + pSlice->nalUnitType = NONIDR; + pSlice->sliceType = rcSliceType = PSLICE; + pEncInst->preProcess.intra = 0; + break; + } + + /* Interlaced with intra-only, top and bottom fields. */ + if (pEncInst->interlaced && ((pSlice->prevFrameNum % 2) == 1)) + pSlice->frameNum = pSlice->prevFrameNum; + + } + + /* Rate control, ISLICE begins a new GOP */ + H264BeforePicRc(&pEncInst->rateControl, pEncIn->timeIncrement, rcSliceType); + + /* set registers for denoise */ + H264EncDnfPrepare(pEncInst); + + /* time stamp updated */ + H264UpdateSeiTS(&pEncInst->rateControl.sei, pEncIn->timeIncrement); + + /* Rate control may choose to skip the frame */ + if(pEncInst->rateControl.frameCoded == ENCHW_NO) + { + APITRACE("H264EncStrmEncode: OK, frame skipped"); + pSlice->frameNum = pSlice->prevFrameNum; /* restore frame_num */ + +#if 0 + /* Write previous reconstructed frame when frame is skipped */ + EncAsicRecycleInternalImage(&pEncInst->asic.regs); + EncDumpRecon(&pEncInst->asic); + EncAsicRecycleInternalImage(&pEncInst->asic.regs); +#endif + + EWLReleaseHw(pEncInst->asic.ewl); + + return H264ENC_FRAME_READY; + } + +#ifdef TRACE_STREAM + traceStream.frameNum = pEncInst->frameCnt; + traceStream.id = 0; /* Stream generated by SW */ + traceStream.bitCnt = 0; /* New frame */ +#endif + + /* Initialize picture buffer and ref pic list according to frame type */ + picBuffer = &pEncInst->picBuffer; + picBuffer->cur_pic->show = 1; + if (pEncInst->numViews > 1) + picBuffer->cur_pic->poc = pEncInst->frameCnt/2; + else + picBuffer->cur_pic->poc = pEncInst->frameCnt; + picBuffer->cur_pic->i_frame = (ct == H264ENC_INTRA_FRAME); + picBuffer->cur_pic->frameNum = pSlice->frameNum; + H264InitializePictureBuffer(picBuffer); + + /* Set picture buffer according to frame coding type */ + if (ct != H264ENC_INTRA_FRAME) { + picBuffer->cur_pic->p_frame = 1; + picBuffer->cur_pic->arf = 0; + picBuffer->cur_pic->ipf = (pEncIn->ipf&H264ENC_REFRESH) ? 1 : 0; + if (pEncIn->ipf&H264ENC_REFERENCE) + { + if (picBuffer->refPicList[0].ipf) + picBuffer->refPicList[0].search = true; + else if (picBuffer->refPicList[1].ipf) + picBuffer->refPicList[1].search = true; + } + if (pEncIn->ltrf&H264ENC_REFERENCE) + { + if (picBuffer->refPicList[0].grf) + picBuffer->refPicList[0].search = true; + else if (picBuffer->refPicList[1].grf) + picBuffer->refPicList[1].search = true; + } + } + + /* LTR marking, not used for interlaced coding. */ + if (!pEncInst->interlaced) { + picBuffer->cur_pic->grf = (pEncIn->ltrf&H264ENC_REFRESH) ? 1 : 0; + + if (pEncInst->rateControl.longTermPicRate && + pEncInst->seqParameterSet.numRefFrames >= 2) + { + if ((pEncInst->frameCnt%pEncInst->rateControl.longTermPicRate) == 0) + picBuffer->cur_pic->grf = 1; + } + if (picBuffer->cur_pic->i_frame) + picBuffer->cur_pic->grf = 1; + } + +#ifdef INTERNAL_TEST + /* Configure the encoder instance according to the test vector */ + H264ConfigureTestBeforeFrame(pEncInst); +#endif + + /* cannot mark picture both long-term and short-term ref -> if long-term + * to be refreshed, short-term won't refresh */ + if (picBuffer->cur_pic->grf && + pEncInst->seqParameterSet.numRefFrames >= 2) + picBuffer->cur_pic->ipf = false; + + /* check if GDR and idrHdr enabled, when to set SPS/PPS headers */ + if(pEncInst->idrHdr && pEncInst->gdrEnabled == 1) + { + if(pEncInst->gdrCount == 0 && pEncInst->gdrStart == 1) + setSpsPps = 1; + else + setSpsPps = 0; + } + + if(pEncInst->idrHdr) + { + if( (!pEncInst->gdrEnabled && ct == H264ENC_INTRA_FRAME && pEncInst->frameCnt) || + (pEncInst->gdrEnabled && setSpsPps) ) + { + /* Determine the start offset for NALU size table. + * HW needs a 64-bit aligned address so we leave the first 32-bits unused + * if SW creates one leading NAL unit. Also the HW bus address needs to be + * offset in H264CodeFrame. */ + { + i32 numLeadingNalus = 2; + sei_s *sei = &pEncInst->rateControl.sei; + + if(sei->enabled == ENCHW_YES || sei->userDataEnabled == ENCHW_YES || + sei->insertRecoveryPointMessage == ENCHW_YES) + numLeadingNalus++; + + if((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 0)) + numLeadingNalus++; + + if(pEncInst->picParameterSet.enableCabac == 2) + numLeadingNalus++; + + if( pEncInst->svc.level || pEncInst->svc.enableSvctPrefix ) ////prefix + numLeadingNalus++; + + if(pEncInst->frameCnt && pEncIn->sendAUD) ////aud + numLeadingNalus++; + + if(numLeadingNalus % 2) + { + pEncOut->pNaluSizeBuf++; + pEncInst->naluOffset++; + } + + } + + if(pEncInst->frameCnt && pEncIn->sendAUD) + { + tmp = pEncInst->stream.byteCnt; + H264AccessUnitDelimiter(&pEncInst->stream, pEncInst->seqParameterSet.byteStream, 2); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt - tmp); + tmp = pEncInst->stream.byteCnt; + pEncInst->numNalus++; + } + + tmp = pEncInst->stream.byteCnt; + H264SeqParameterSet(&pEncInst->stream, &pEncInst->seqParameterSet, ENCHW_YES); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + pEncInst->numNalus++; + + /* Subset SPS for MVC */ + if (pEncInst->numViews > 1) + { + H264SubsetSeqParameterSet(&pEncInst->stream, &pEncInst->seqParameterSet); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + pEncInst->numNalus++; + } + + H264PicParameterSet(&pEncInst->stream, &pEncInst->picParameterSet); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + pEncInst->numNalus++; + + /* In CABAC mode 2 we need two PPS: one with CAVLC (ppsId=0 for intra) and + * one with CABAC (ppsId=1 for inter) */ + if (pEncInst->picParameterSet.enableCabac == 2) + { + pEncInst->picParameterSet.picParameterSetId = 1; + pEncInst->picParameterSet.entropyCodingMode = ENCHW_YES; + H264PicParameterSet(&pEncInst->stream, &pEncInst->picParameterSet); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + tmp = pEncInst->stream.byteCnt; + pEncInst->numNalus++; + } + pEncOut->streamSize = pEncInst->stream.byteCnt; + } + else if(ct == H264ENC_INTRA_FRAME && !pEncInst->frameCnt )//the first I frame + { + i32 numLeadingNalus = 0; + sei_s *sei = &pEncInst->rateControl.sei; + + if(sei->enabled == ENCHW_YES || sei->userDataEnabled == ENCHW_YES || + sei->insertRecoveryPointMessage == ENCHW_YES) + numLeadingNalus++; + + if((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 0)) + numLeadingNalus++; + + if( pEncInst->svc.level || pEncInst->svc.enableSvctPrefix ) //prefix + numLeadingNalus++; + + //aud is added in H264EncStrmStrat + /*if(pEncInst->frameCnt && pEncInst->svc.level && pEncIn->sendAUD) + numLeadingNalus++; */ + + if(numLeadingNalus % 2) + { + pEncOut->pNaluSizeBuf++; + pEncInst->naluOffset++; + } + } + else if(ct != H264ENC_INTRA_FRAME ) + { + i32 numLeadingNalus = 0; + sei_s *sei = &pEncInst->rateControl.sei; + + if(sei->enabled == ENCHW_YES || sei->userDataEnabled == ENCHW_YES || + sei->insertRecoveryPointMessage == ENCHW_YES) + numLeadingNalus++; + + if((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 0)) + numLeadingNalus++; + + if( pEncInst->svc.level || pEncInst->svc.enableSvctPrefix ) //prefix + numLeadingNalus++; + + if(pEncInst->frameCnt && pEncIn->sendAUD) //aud + numLeadingNalus++; + + if(numLeadingNalus % 2) + { + pEncOut->pNaluSizeBuf++; + pEncInst->naluOffset++; + } + } + } + /* Determine the start offset for NALU size table. + * HW needs a 64-bit aligned address so we leave the first 32-bits unused + * if SW creates one leading NAL unit. Also the HW bus address needs to be + * offset in H264CodeFrame. */ + if(pEncInst->idrHdr == ENCHW_NO) + { + i32 numLeadingNalus = 0; + sei_s *sei = &pEncInst->rateControl.sei; + + if(sei->enabled == ENCHW_YES || sei->userDataEnabled == ENCHW_YES || sei->insertRecoveryPointMessage == ENCHW_YES) + numLeadingNalus++; + + if ((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 0)) + numLeadingNalus++; + + if( pEncInst->svc.level || pEncInst->svc.enableSvctPrefix ) ////prefix + numLeadingNalus++; + + if(pEncInst->frameCnt && pEncIn->sendAUD) ////aud + numLeadingNalus++; + + //pEncInst->numNalus = numLeadingNalus; //Not pre add. + if(numLeadingNalus % 2) + { + pEncOut->pNaluSizeBuf++; + pEncInst->naluOffset++; + } + } + + /* update any cropping/rotation/filling */ + pEncInst->preProcess.bottomField = (pSlice->frameNum%2) == pSlice->fieldOrder; + EncPreProcess(&pEncInst->asic, &pEncInst->preProcess); + + if (!((pEncInst->idrHdr && !pEncInst->gdrEnabled && ct == H264ENC_INTRA_FRAME && pEncInst->frameCnt) || + (pEncInst->idrHdr && pEncInst->gdrEnabled && setSpsPps) )) + { + if(pEncInst->frameCnt && pEncIn->sendAUD) + { + tmp = pEncInst->stream.byteCnt; + H264AccessUnitDelimiter(&pEncInst->stream, pEncInst->seqParameterSet.byteStream, 2); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt - tmp); + tmp = pEncInst->stream.byteCnt; + pEncInst->numNalus++; + } + } + + /* SEI message */ + { + sei_s *sei = &pEncInst->rateControl.sei; + + if(sei->enabled == ENCHW_YES || sei->userDataEnabled == ENCHW_YES || sei->insertRecoveryPointMessage == ENCHW_YES) + { + + H264NalUnitHdr(&pEncInst->stream, 0, SEI, sei->byteStream); + + if(sei->enabled == ENCHW_YES) + { + if(pSlice->nalUnitType == IDR) + { + H264BufferingSei(&pEncInst->stream, sei); + } + + H264PicTimingSei(&pEncInst->stream, sei); + } + + if(sei->userDataEnabled == ENCHW_YES) + { + H264UserDataUnregSei(&pEncInst->stream, sei); + } + + if (sei->insertRecoveryPointMessage == ENCHW_YES) + { + H264RecoveryPointSei(&pEncInst->stream, sei); + } + + H264RbspTrailingBits(&pEncInst->stream); + + sei->nalUnitSize = pEncInst->stream.byteCnt; + + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-tmp); + //if(pEncInst->idrHdr == ENCHW_YES) + pEncInst->numNalus++; + } + } + + /* For MVC stream insert prefix NALU before base view pictures */ + if ((pEncInst->numViews > 1) && ((pSlice->frameNum % 2) == 0)) + { + i32 byteCnt = pEncInst->stream.byteCnt; + H264PrefixNal(pEncInst, false); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-byteCnt); + //if(pEncInst->idrHdr == ENCHW_YES) + pEncInst->numNalus++; + } + else + { + pEncInst->mvc.anchorPicFlag = (pSlice->frameNum == 1); + pEncInst->mvc.viewId = 1; + pEncInst->mvc.interViewFlag = 0; + } + + if (pEncInst->svc.level) + { + i32 byteCnt = pEncInst->stream.byteCnt; + + if (ct==H264ENC_INTRA_FRAME) + { + picBuffer->cur_pic->ipf = true; + picBuffer->cur_pic->grf = false; + picBuffer->cur_pic->arf = false; + picBuffer->cur_pic->orderCmd = 0; + pEncInst->svc.gopIndex = -1; + /* Get the reference frame buffers from picture buffer */ + H264PictureBufferSetRef(picBuffer, &pEncInst->asic, + pEncInst->interlaced ? 2 : pEncInst->numViews); + } + else + { + int index;; + gopinfo_s *ctrl; + index = (pEncInst->svc.gopIndex+1)&(pEncInst->svc.gopLength-1); + pEncInst->svc.gopIndex = index; + ctrl = &pEncInst->svc.gop[index]; + if ((ctrl->isRef)) + { + picBuffer->cur_pic->ipf = true; + picBuffer->cur_pic->grf = false; + picBuffer->cur_pic->arf = false; + } + else + { + picBuffer->cur_pic->ipf = false; + picBuffer->cur_pic->grf = false; + picBuffer->cur_pic->arf = false; + } + if (ct==H264ENC_INTRA_FRAME) + { + picBuffer->cur_pic->orderCmd = 0; + } + else + { + picBuffer->cur_pic->orderCmd = ctrl->orderCmd; + } + /* Get the reference frame buffers from picture buffer */ + H264PictureBufferSetRefForSvct(picBuffer, &pEncInst->asic, + pSlice->frameNumBits); + } + + /* for SVCT, insert prefix NALU before each slice */ + //pEncOut->pNaluSizeBuf++; + //pEncInst->naluOffset++; + + H264PrefixNal(pEncInst, true); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-byteCnt); + pEncInst->numNalus++; + prefix_nalu_length = pEncInst->stream.byteCnt-byteCnt;//save prefix length. + prefix_nalu_addr = pEncInst->stream.stream - (pEncInst->stream.byteCnt-byteCnt);//save prefix addr. + //if(pEncInst->idrHdr == ENCHW_YES) + //pEncInst->numNalus++; + } + else + { + picBuffer->cur_pic->orderCmd = 0; + pEncInst->svc.gopIndex = -1; + /* Get the reference frame buffers from picture buffer */ + H264PictureBufferSetRef(picBuffer, &pEncInst->asic, + pEncInst->interlaced ? 2 : pEncInst->numViews); + + if( pEncInst->svc.enableSvctPrefix ) + { + if (ct==H264ENC_INTRA_FRAME) + { + pEncInst->svc.gopIndex = -1; + } + else + { + pEncInst->svc.gopIndex = -2; + } + APITRACE("svc.enableSVC"); + + i32 byteCnt = pEncInst->stream.byteCnt; + /* for SVCT, insert prefix NALU before each slice */ + //pEncOut->pNaluSizeBuf++; + //pEncInst->naluOffset++; + pEncInst->numNalus++; + H264PrefixNal(pEncInst, true); + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt-byteCnt); + prefix_nalu_length = pEncInst->stream.byteCnt-byteCnt;//save prefix length. + prefix_nalu_addr = pEncInst->stream.stream - (pEncInst->stream.byteCnt-byteCnt);//save prefix addr. + //if(pEncInst->idrHdr == ENCHW_YES) + //pEncInst->numNalus++; + } + } + + /* Code one frame */ + ret = H264CodeFrame(pEncInst); + +#ifdef TRACE_RECON + EncDumpRecon(&pEncInst->asic); +#endif + + if(ret != H264ENCODE_OK) + { + /* Error has occured and the frame is invalid */ + H264EncRet to_user; + + switch (ret) + { + case H264ENCODE_TIMEOUT: + APITRACE("H264EncStrmEncode: ERROR HW/IRQ timeout"); + to_user = H264ENC_HW_TIMEOUT; + break; + case H264ENCODE_HW_RESET: + APITRACE("H264EncStrmEncode: ERROR HW reset detected"); + to_user = H264ENC_HW_RESET; + break; + case H264ENCODE_HW_ERROR: + APITRACE("H264EncStrmEncode: ERROR HW bus access error"); + to_user = H264ENC_HW_BUS_ERROR; + break; + case H264ENCODE_FUSE_ERROR: + APITRACE("H264EncStrmEncode: ERROR Fuse error"); + to_user = H264ENC_FUSE_ERROR; + break; + case H264ENCODE_SYSTEM_ERROR: + default: + /* System error has occured, encoding can't continue */ + pEncInst->encStatus = H264ENCSTAT_ERROR; + APITRACE("H264EncStrmEncode: ERROR Fatal system error"); + to_user = H264ENC_SYSTEM_ERROR; + } + + return to_user; + } + +#ifdef VIDEOSTAB_ENABLED + /* Finalize video stabilization */ + if(pEncInst->preProcess.videoStab) + { + u32 no_motion; + + VSReadStabData(pEncInst->asic.regs.regMirror, &pEncInst->vsHwData); + + no_motion = VSAlgStabilize(&pEncInst->vsSwData, &pEncInst->vsHwData); + if(no_motion) + { + VSAlgReset(&pEncInst->vsSwData); + } + + /* update offset after stabilization */ + VSAlgGetResult(&pEncInst->vsSwData, &pEncInst->preProcess.horOffsetSrc, + &pEncInst->preProcess.verOffsetSrc); + } +#endif + + H264EncDnfUpdate(pEncInst); + + /* Update NALU table with the amount of slices created by the HW */ + { + i32 numSlices; + + if (pEncInst->slice.sliceSize) + numSlices = (pEncInst->mbPerFrame + pEncInst->slice.sliceSize - 1) / + pEncInst->slice.sliceSize; + else + numSlices = 1; + + pEncOut->numNalus += numSlices; + pEncOut->pNaluSizeBuf[pEncOut->numNalus] = 0; + } + + if (pEncInst->svc.level || pEncInst->svc.enableSvctPrefix) + { + pEncOut->streamSize = pEncInst->stream.byteCnt; + H264SupplyPrefixForSvctMutiSlice(inst, pEncIn, pEncOut, prefix_nalu_length, prefix_nalu_addr); + } + + /* Filler data if needed */ + if(0) + { + u32 s = H264FillerRc(&pEncInst->rateControl, pEncInst->frameCnt); + + if(s != 0) + { + s = H264FillerNALU(&pEncInst->stream, + (i32) s, pEncInst->seqParameterSet.byteStream); + } + pEncInst->fillerNalSize = s; + H264AddNaluSize(pEncOut, s); + } + + pEncOut->motionVectors = (i8*)pEncInst->asic.mvOutput.virtualAddress; + + /* After stream buffer overflow discard the coded frame */ + if(pEncInst->stream.overflow == ENCHW_YES) + { + if ((pEncInst->numRefBuffsLum == 1) || (pEncInst->numViews == 2)) + { + /* Only one reference frame buffer in use, so we can't use it + * as reference => we must encode next frame as intra */ + pEncInst->encStatus = H264ENCSTAT_START_STREAM; + } + pEncOut->numNalus = 0; + pEncOut->pNaluSizeBuf[0] = 0; + APITRACE("H264EncStrmEncode: ERROR Output buffer too small"); + return H264ENC_OUTPUT_BUFFER_OVERFLOW; + } + + /* Rate control action after vop */ + { + i32 stat; + + pEncInst->rateControl.rcMSESum = regs->rcMSESum; + + stat = H264AfterPicRc(&pEncInst->rateControl, regs->rlcCount, + pEncInst->stream.byteCnt, regs->qpSum); + /*H264MadThreshold(&pEncInst->mad, regs->madCount);*/ + + /* After HRD overflow discard the coded frame and go back old time, + * just like not coded frame. But if only one reference frame + * buffer is in use we can't discard the frame unless the next frame + * is coded as intra. */ + if((stat == H264RC_OVERFLOW) && + (pEncInst->numRefBuffsLum > 1) && + (pEncInst->numViews == 1)) + { + pSlice->frameNum = pSlice->prevFrameNum; /* revert frame_num */ + pEncOut->numNalus = 0; + pEncOut->pNaluSizeBuf[0] = 0; + APITRACE("H264EncStrmEncode: OK, Frame discarded (HRD overflow)"); + return H264ENC_FRAME_READY; + } + } + + /* Use the reconstructed frame as the reference for the next frame */ + EncAsicRecycleInternalImage(&pEncInst->asic, pEncInst->interlaced ? 2 : pEncInst->numViews, + (pSlice->frameNum % 2), (pSlice->frameNum <= 1), + pEncInst->numRefBuffsLum, pEncInst->numRefBuffsChr); + + /* Store the stream size and frame coding type in output structure */ + pEncOut->streamSize = pEncInst->stream.byteCnt; + if(pSlice->nalUnitType == IDR) { + pEncOut->codingType = H264ENC_INTRA_FRAME; + pSlice->idrPicId += 1; + if(pSlice->idrPicId == H264ENC_IDR_ID_MODULO) + pSlice->idrPicId = 0; + pEncOut->ipf = pEncOut->ltrf = 0; + } else if (pSlice->sliceType == PSLICE) { + pEncOut->codingType = H264ENC_PREDICTED_FRAME; + if (picBuffer->refPicList[0].ipf) + { + pEncOut->ipf = picBuffer->refPicList[0].search ? H264ENC_REFERENCE : 0; + pEncOut->ltrf = picBuffer->refPicList[1].search ? H264ENC_REFERENCE : 0; + } + else + { + pEncOut->ipf = picBuffer->refPicList[1].search ? H264ENC_REFERENCE : 0; + pEncOut->ltrf = picBuffer->refPicList[0].search ? H264ENC_REFERENCE : 0; + } + } else { + pEncOut->codingType = H264ENC_NONIDR_INTRA_FRAME; + } + + /* Mark which reference frame was refreshed */ + pEncOut->ipf |= picBuffer->cur_pic->ipf ? H264ENC_REFRESH : 0; + pEncOut->ltrf |= picBuffer->cur_pic->grf ? H264ENC_REFRESH : 0; + + pEncOut->mse_mul256 = regs->mse_mul256; + + if (pEncInst->svc.level) + { + H264UpdatePictureBufferForSvct(picBuffer, pSlice->frameNumBits, pEncInst->svc.gop[pEncInst->svc.gopIndex].markCmd); + } + else + { + H264UpdatePictureBuffer(picBuffer); + } + + /* Frame was encoded so increment frame number */ + pEncInst->frameCnt++; + /* When frame not used for reference, POC shouldn't increment. */ + if (!regs->recWriteDisable || pEncInst->numViews > 1) pSlice->frameNum++; + pSlice->frameNum %= (1U << pSlice->frameNumBits); + + pEncInst->encStatus = H264ENCSTAT_START_FRAME; + + /* Force to Intra Frame because last compressed ref is overflow */ + if (pEncInst->rfcBufOverflow == ENCHW_YES) + pEncInst->encStatus = H264ENCSTAT_START_STREAM; + + if(pEncInst->gdrEnabled == 1) + { + if(pEncInst->gdrFirstIntraFrame != 0) + { + pEncInst->gdrFirstIntraFrame--; + } + if(pEncInst->gdrStart) + pEncInst->gdrCount++; + + if(pEncInst->gdrCount == (pEncInst->gdrDuration * (1 + (i32)pEncInst->interlaced))) + { + pEncInst->gdrStart--; + pEncInst->gdrCount = 0; + } + } + APITRACE("H264EncStrmEncode: OK"); + return H264ENC_FRAME_READY; +} + +/*------------------------------------------------------------------------------ + + Function name : H264EncStrmEnd + Description : Ends a stream + Return type : H264EncRet + Argument : inst - encoder instance + Argument : pEncIn - user provided input parameters + pEncOut - place where output info is returned +------------------------------------------------------------------------------*/ +H264EncRet H264EncStrmEnd(H264EncInst inst, const H264EncIn * pEncIn, + H264EncOut * pEncOut) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + APITRACE("H264EncStrmEnd#"); + APITRACEPARAM("busLuma", pEncIn->busLuma); + APITRACEPARAM("busChromaU", pEncIn->busChromaU); + APITRACEPARAM("busChromaV", pEncIn->busChromaV); + APITRACEPARAM("pOutBuf", pEncIn->pOutBuf); + APITRACEPARAM("busOutBuf", pEncIn->busOutBuf); + APITRACEPARAM("outBufSize", pEncIn->outBufSize); + APITRACEPARAM("codingType", pEncIn->codingType); + APITRACEPARAM("timeIncrement", pEncIn->timeIncrement); + APITRACEPARAM("busLumaStab", pEncIn->busLumaStab); + APITRACEPARAM("ipf", pEncIn->ipf); + APITRACEPARAM("ltrf", pEncIn->ltrf); + + /* Check for illegal inputs */ + if((pEncInst == NULL) || (pEncIn == NULL) || (pEncOut == NULL)) + { + APITRACE("H264EncStrmEnd: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if(pEncInst->inst != pEncInst) + { + APITRACE("H264EncStrmEnd: ERROR Invalid instance"); + return H264ENC_INSTANCE_ERROR; + } + + /* Check status, this also makes sure that the instance is valid */ + if((pEncInst->encStatus != H264ENCSTAT_START_FRAME) && + (pEncInst->encStatus != H264ENCSTAT_START_STREAM)) + { + APITRACE("H264EncStrmEnd: ERROR Invalid status"); + return H264ENC_INVALID_STATUS; + } + + pEncOut->streamSize = 0; + + /* Set pointer to the beginning of NAL unit size buffer */ + pEncOut->pNaluSizeBuf = (u32 *) pEncInst->asic.sizeTbl.virtualAddress; + pEncOut->numNalus = 0; + + /* Clear the NAL unit size table */ + if(pEncOut->pNaluSizeBuf != NULL) + pEncOut->pNaluSizeBuf[0] = 0; + + /* Check for invalid input values */ + if(pEncIn->pOutBuf == NULL || + (pEncIn->outBufSize < H264ENCSTRMSTART_MIN_BUF)) + { + APITRACE("H264EncStrmEnd: ERROR Invalid input. Stream buffer"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Set stream buffer and check the size */ + if(H264SetBuffer(&pEncInst->stream, (u8 *) pEncIn->pOutBuf, + (u32) pEncIn->outBufSize) != ENCHW_OK) + { + APITRACE("H264EncStrmEnd: ERROR Output buffer too small"); + return H264ENC_INVALID_ARGUMENT; + } + + /* Write end-of-stream code */ + H264EndOfSequence(&pEncInst->stream, &pEncInst->seqParameterSet); + + /* Bytes generated */ + pEncOut->streamSize = pEncInst->stream.byteCnt; + H264AddNaluSize(pEncOut, pEncInst->stream.byteCnt); + + /* Status == INIT Stream ended, next stream can be started */ + pEncInst->encStatus = H264ENCSTAT_INIT; + + APITRACE("H264EncStrmEnd: OK"); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + + Function name : H264AddNaluSize + Description : Adds the size of a NAL unit into NAL size output buffer. + + Return type : void + Argument : pEncOut - encoder output structure + Argument : naluSizeBytes - size of the NALU in bytes +------------------------------------------------------------------------------*/ +void H264AddNaluSize(H264EncOut * pEncOut, u32 naluSizeBytes) +{ + if(pEncOut->pNaluSizeBuf != NULL) + { + pEncOut->pNaluSizeBuf[pEncOut->numNalus++] = naluSizeBytes; + pEncOut->pNaluSizeBuf[pEncOut->numNalus] = 0; + } +} + +/*------------------------------------------------------------------------------ + + H264PrefixSvcNal + +------------------------------------------------------------------------------*/ +void H264PrefixNal(h264Instance_s *pEncInst, bool svcExtFlag) +{ + i32 nalRefIdc = 1; + + if (svcExtFlag) + { + svc_s *svc = &pEncInst->svc; + u32 layer = (svc->gopIndex==-1)?(0):(svc->gop[svc->gopIndex].layer); + if ( svc->level > 0 && layer == svc->level ) + { + nalRefIdc = 0; + } + } + + H264NalUnitHdr(&pEncInst->stream, nalRefIdc, PREFIX, + pEncInst->seqParameterSet.byteStream); + + H264PutBits(&pEncInst->stream, svcExtFlag, 1); + COMMENT("svc_extension_flag"); + + if (svcExtFlag) + { + H264NalUnitHdrSvcExtension(&pEncInst->stream, &pEncInst->svc); + } + else + { + pEncInst->mvc.anchorPicFlag = (pEncInst->slice.nalUnitType == IDR); + pEncInst->mvc.priorityId = 0; + pEncInst->mvc.viewId = 0; + pEncInst->mvc.temporalId = 0; + pEncInst->mvc.interViewFlag = 1; + + H264NalUnitHdrMvcExtension(&pEncInst->stream, &pEncInst->mvc); + } +} + +/*------------------------------------------------------------------------------ + + H264PrefixSvcNal + +------------------------------------------------------------------------------*/ +void H264SvcSeiNal(h264Instance_s *pEncInst) +{ + h264RateControl_s *rc = &pEncInst->rateControl; + H264NalUnitHdr(&pEncInst->stream, 0, SEI, + pEncInst->seqParameterSet.byteStream); + + H264ScalabilityInfoSei(&pEncInst->stream, pEncInst->svc.level, rc->outRateNum*256/rc->outRateDenom); + H264RbspTrailingBits(&pEncInst->stream); +} +/*------------------------------------------------------------------------------ + Function name : H264EncGetBitsPerPixel + Description : Returns the amount of bits per pixel for given format. + Return type : u32 +------------------------------------------------------------------------------*/ +u32 H264EncGetBitsPerPixel(H264EncPictureType type) +{ + switch (type) + { + case H264ENC_YUV420_PLANAR: + case H264ENC_YUV420_SEMIPLANAR: + case H264ENC_YUV420_SEMIPLANAR_VU: + return 12; + case H264ENC_YUV422_INTERLEAVED_YUYV: + case H264ENC_YUV422_INTERLEAVED_UYVY: + case H264ENC_RGB565: + case H264ENC_BGR565: + case H264ENC_RGB555: + case H264ENC_BGR555: + case H264ENC_RGB444: + case H264ENC_BGR444: + return 16; + case H264ENC_RGB888: + case H264ENC_BGR888: + case H264ENC_RGB101010: + case H264ENC_BGR101010: + return 32; + case H264ENC_P010: + case H264ENC_SP_101010: + return 24; + default: + return 0; + } +} + +/*------------------------------------------------------------------------------ + Function name : H264EncSetTestId + Description : Sets the encoder configuration according to a test vector + Return type : H264EncRet + Argument : inst - encoder instance + Argument : testId - test vector ID +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetTestId(H264EncInst inst, u32 testId) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + (void) pEncInst; + (void) testId; + + APITRACE("H264EncSetTestId#"); + +#ifdef INTERNAL_TEST + pEncInst->testId = testId; + + APITRACE("H264EncSetTestId# OK"); + return H264ENC_OK; +#else + /* Software compiled without testing support, return error always */ + APITRACE("H264EncSetTestId# ERROR, testing disabled at compile time"); + return H264ENC_ERROR; +#endif +} + +/*------------------------------------------------------------------------------ + Function name : H264EncGetMbInfo + Description : Set the motionVectors field of H264EncOut structure to + point macroblock mbNum + Return type : H264EncRet + Argument : inst - encoder instance + Argument : mbNum - macroblock number +------------------------------------------------------------------------------*/ +H264EncRet H264EncGetMbInfo(H264EncInst inst, H264EncOut * pEncOut, u32 mbNum) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + APITRACE("H264EncSetTestId#"); + + /* Check for illegal inputs */ + if (!pEncInst || !pEncOut) { + APITRACE("H264EncSetTestId: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + if (mbNum >= pEncInst->mbPerFrame) { + APITRACE("H264EncSetTestId: ERROR Invalid argument"); + return H264ENC_INVALID_ARGUMENT; + } + + pEncOut->motionVectors = (i8 *)EncAsicGetMvOutput(&pEncInst->asic, mbNum); + + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncGetInputBufferConsumed + Description : Get how many MB lines has been encoded by encoder. + Return type : int + Argument : inst - encoder instance +------------------------------------------------------------------------------*/ +u32 H264EncGetEncodedMbLines(H264EncInst inst) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + int lines; + + APITRACE("H264EncGetEncodedMbLines#"); + + /* Check for illegal inputs */ + if (!pEncInst) { + APITRACE("H264EncGetEncodedMbLines: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + if (!pEncInst->inputLineBuf.inputLineBufEn) { + APITRACE("H264EncGetEncodedMbLines: ERROR Invalid mode for input control"); + return H264ENC_INVALID_ARGUMENT; + } + lines = EncAsicGetRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncMbRdPtr); + return lines; +} + +/*------------------------------------------------------------------------------ + Function name : H264EncSetInputMbLines + Description : Set the input buffer lines available of current picture. + Return type : H264EncRet + Argument : inst - encoder instance + Argument : mbNum - macroblock number +------------------------------------------------------------------------------*/ +H264EncRet H264EncSetInputMbLines(H264EncInst inst, u32 lines) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + APITRACE("H264EncSetInputMBLines#"); + + /* Check for illegal inputs */ + if (!pEncInst) { + APITRACE("H264EncSetInputMbLines: ERROR Null argument"); + return H264ENC_NULL_ARGUMENT; + } + + if (!pEncInst->inputLineBuf.inputLineBufEn) { + APITRACE("H264EncSetInputMbLines: ERROR Invalid mode for input control"); + return H264ENC_INVALID_ARGUMENT; + } + EncAsicWriteRegisterValue(pEncInst->asic.ewl, pEncInst->asic.regs.regMirror, HEncMbWrPtr, lines); + return H264ENC_OK; +} + +/*------------------------------------------------------------------------------ + Function name : H264SupplyPrefixForSvctMutiSlice + Description : Supply prefix for svct muti-slice. + Return type : void + Argument : inst - encoder instance + Argument : *pEncIn - user provided input parameters + Argument : *pEncOut - place where output info is returned + Argument : prefix_length - the length of prefix nalu + Argument : prefix_nalu_addr - prefix nalu addr +------------------------------------------------------------------------------*/ +void H264SupplyPrefixForSvctMutiSlice(H264EncInst inst, const H264EncIn *pEncIn, H264EncOut *pEncOut, + u32 prefix_length, u8 *prefix_nalu_addr) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + if (!pEncInst) { + APITRACE("H264SupplyPrefixForSvctMutiSlice: ERROR Null argument"); + return; + } + if(!pEncInst->slice.sliceSize) + { + APITRACE("H264SupplyPrefixForSvctMutiSlice: Prifix is not added for singal slice."); + return; + } + ASSERT((prefix_length != 0) && (prefix_nalu_addr != NULL) && (pEncOut->streamSize != 0)); + + u32 num_prefix_to_supply = (pEncInst->mbPerFrame + pEncInst->slice.sliceSize - 1) / pEncInst->slice.sliceSize - 1;//how many prefixs lack. + if(pEncOut->streamSize + prefix_length * num_prefix_to_supply > pEncIn->outBufSize) + { + APITRACE("H264SupplyPrefixForSvctMutiSlice: The output buffer overflows."); + pEncInst->stream.overflow = ENCHW_YES; + return; + } + + u32 i = 0, j = 0, copy_times = 0, data_left = 0; + u32 num_nalus = pEncOut->numNalus; + u8 *data_addr_tail = (u8 *)pEncIn->pOutBuf + pEncOut->streamSize; + u8 *copy_src = data_addr_tail; + u8 *copy_dst = data_addr_tail + prefix_length * num_prefix_to_supply;//spare n prefix_length + u8 *prefix_data = prefix_nalu_addr; + + /* 1.insert prefix data and move slice data. */ + for(j = 0; j < num_prefix_to_supply; j++) + { + copy_times = pEncOut->pNaluSizeBuf[num_nalus - 1 - j] / prefix_length; + data_left = pEncOut->pNaluSizeBuf[num_nalus - 1 - j] % prefix_length; + copy_src -= prefix_length; + copy_dst -= prefix_length; + ASSERT(copy_dst >= (u8 *)pEncIn->pOutBuf); + + for(i = 0; i < copy_times; i++) + { + memcpy(copy_dst, copy_src, prefix_length); + if(i == copy_times-1) + { + copy_src -= data_left; + copy_dst -= data_left; + } + else + { + copy_src -= prefix_length; + copy_dst -= prefix_length; + } + } + if(data_left) + memcpy(copy_dst, copy_src, data_left); + copy_dst -= prefix_length; + memcpy(copy_dst, prefix_data, prefix_length); + } + + /* 2.update H264EncOut pEncInst state. */ + for(j = 0; j < num_prefix_to_supply; j++) + { + ASSERT(&pEncOut->pNaluSizeBuf[num_nalus - 1 + num_prefix_to_supply -j*2]); + pEncOut->pNaluSizeBuf[num_nalus-1+num_prefix_to_supply-j*2 ] = pEncOut->pNaluSizeBuf[num_nalus-1-j]; + pEncOut->pNaluSizeBuf[num_nalus - 1 + num_prefix_to_supply - j*2 - 1] = prefix_length; + pEncOut->streamSize += prefix_length; + pEncOut->numNalus++; + } + pEncOut->pNaluSizeBuf[pEncOut->numNalus] = 0; + + pEncInst->stream.stream += prefix_length * num_prefix_to_supply; + pEncInst->stream.byteCnt += prefix_length * num_prefix_to_supply; +} + +/*------------------------------------------------------------------------------ + Function name : H264AccessUnitDelimiter + Description : Add AUD + Return type : void + Argument : u32 byte_stream + Argument : u32 primary_pic_type - primary_pic_type +------------------------------------------------------------------------------*/ +void H264AccessUnitDelimiter(stream_s *b, u32 byte_stream, u32 primary_pic_type) +{ + H264NalUnitHdr(b, 0, AUD_NUT, byte_stream); + H264PutBits(b, primary_pic_type, 3); + COMMENT("primary_pic_type"); + H264RbspTrailingBits(b); +} diff --git a/lib/vc8000nanoe/source/h264/H264Init.c b/lib/vc8000nanoe/source/h264/H264Init.c new file mode 100644 index 000000000..c0f102785 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Init.c @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Encoder initialization and setup + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "string.h" +#include "H264Init.h" +#include "H264Denoise.h" +#include "enccommon.h" +#include "ewl.h" + + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ +#define H264ENC_MIN_ENC_WIDTH 132 /* 144 - 12 pixels overfill */ +#define H264ENC_MAX_ENC_WIDTH 4080 +#define H264ENC_MIN_ENC_HEIGHT 96 +#define H264ENC_MAX_ENC_HEIGHT 4080 +#define H264ENC_MAX_REF_FRAMES 3 + +#define H264ENC_MAX_MBS_PER_PIC 65025 /* 4080x4080 */ + +/* Level 51 MB limit is increased to enable max resolution */ +#define H264ENC_MAX_LEVEL 51 + +#define H264ENC_DEFAULT_QP 26 + +/* Tracing macro */ +#ifdef H264ENC_TRACE +#define APITRACE(str) H264EncTrace(str) +#else +#ifndef APITRACE +#define APITRACE(str) +#endif +#endif + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ +static bool_e SetParameter(h264Instance_s *inst, + const H264EncConfig *pEncCfg); +static bool_e CheckParameter(const h264Instance_s *inst); + +static i32 SetPictureBuffer(h264Instance_s *inst); + +/*------------------------------------------------------------------------------ + + H264CheckCfg + + Function checks that the configuration is valid. + + Input pEncCfg Pointer to configuration structure. + + Return ENCHW_OK The configuration is valid. + ENCHW_NOK Some of the parameters in configuration are not valid. + +------------------------------------------------------------------------------*/ +bool_e H264CheckCfg(const H264EncConfig *pEncCfg) +{ + u32 height = pEncCfg->height; + + ASSERT(pEncCfg); + + /* Interlaced coding sets height limitations per field */ + if (pEncCfg->viewMode == H264ENC_INTERLACED_FIELD) + height /= 2; + + if ((pEncCfg->streamType != H264ENC_BYTE_STREAM) && + (pEncCfg->streamType != H264ENC_NAL_UNIT_STREAM)) + { + APITRACE("H264CheckCfg: Invalid stream type"); + return ENCHW_NOK; + } + + /* Encoded image width limits, multiple of 4 */ + if (pEncCfg->width < H264ENC_MIN_ENC_WIDTH || + pEncCfg->width > H264ENC_MAX_ENC_WIDTH || (pEncCfg->width & 0x3) != 0) + { + APITRACE("H264CheckCfg: Invalid width"); + return ENCHW_NOK; + } + + /* Encoded image height limits, multiple of 2 */ + if (height < H264ENC_MIN_ENC_HEIGHT || + height > H264ENC_MAX_ENC_HEIGHT || (height & 0x1) != 0) + { + APITRACE("H264CheckCfg: Invalid height"); + return ENCHW_NOK; + } + + /* Scaled image width limits, multiple of 4 (YUYV) and smaller than input */ + if ((pEncCfg->scaledWidth > pEncCfg->width) || + (pEncCfg->scaledWidth & 0x3) != 0) + { + APITRACE("H264CheckCfg: Invalid scaledWidth"); + return ENCHW_NOK; + } + + if ((pEncCfg->scaledHeight > height) || + (pEncCfg->scaledHeight & 0x1) != 0) + { + APITRACE("H264CheckCfg: Invalid scaledHeight"); + return ENCHW_NOK; + } + + if ((pEncCfg->scaledWidth == pEncCfg->width) && + (pEncCfg->scaledHeight == height)) + { + APITRACE("H264CheckCfg: Invalid scaler output, no downscaling"); + return ENCHW_NOK; + } + + /* total macroblocks per picture limit */ + if (((height + 15) / 16) *((pEncCfg->width + 15) / 16) > + H264ENC_MAX_MBS_PER_PIC) + { + APITRACE("H264CheckCfg: Invalid max resolution"); + return ENCHW_NOK; + } + + /* Check frame rate */ + if (pEncCfg->frameRateNum < 1 || pEncCfg->frameRateNum > ((1 << 20) - 1)) + { + APITRACE("H264CheckCfg: Invalid frameRateNum"); + return ENCHW_NOK; + } + + if (pEncCfg->frameRateDenom < 1) + { + APITRACE("H264CheckCfg: Invalid frameRateDenom"); + return ENCHW_NOK; + } + + /* special allowal of 1000/1001, 0.99 fps by customer request */ + if (pEncCfg->frameRateDenom > pEncCfg->frameRateNum && + !(pEncCfg->frameRateDenom == 1001 && pEncCfg->frameRateNum == 1000)) + { + APITRACE("H264CheckCfg: Invalid frameRate"); + return ENCHW_NOK; + } + + /* check level */ + if ((pEncCfg->level > H264ENC_MAX_LEVEL) && + (pEncCfg->level != H264ENC_LEVEL_1_b)) + { + APITRACE("H264CheckCfg: Invalid level"); + return ENCHW_NOK; + } + + if (pEncCfg->refFrameAmount < 1 || + pEncCfg->refFrameAmount > H264ENC_MAX_REF_FRAMES || + (pEncCfg->refFrameAmount > 1 && + pEncCfg->viewMode != H264ENC_BASE_VIEW_MULTI_BUFFER)) + { + APITRACE("H264CheckCfg: Invalid refFrameAmount"); + return ENCHW_NOK; + } + + /* check HW limitations */ + { + EWLHwConfig_t cfg = EWLReadAsicConfig(); + /* is H.264 encoding supported */ + if (cfg.h264Enabled == EWL_HW_CONFIG_NOT_SUPPORTED) + { + APITRACE("H264CheckCfg: Invalid format, h264 not supported by HW"); + return ENCHW_NOK; + } + + /* max width supported */ + if (cfg.maxEncodedWidth < pEncCfg->width) + { + APITRACE("H264CheckCfg: Invalid width, not supported by HW"); + return ENCHW_NOK; + } + } + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + H264Init + + Function initializes the Encoder and create new encoder instance. + + Input pEncCfg Encoder configuration. + instAddr Pointer to instance will be stored in this address + + Return H264ENC_OK + H264ENC_MEMORY_ERROR + H264ENC_EWL_ERROR + H264ENC_EWL_MEMORY_ERROR + H264ENC_INVALID_ARGUMENT + +------------------------------------------------------------------------------*/ +H264EncRet H264Init(const H264EncConfig *pEncCfg, h264Instance_s **instAddr) +{ + h264Instance_s *inst = NULL; + const void *ewl = NULL; + H264EncRet ret = H264ENC_OK; + EWLInitParam_t param; + + ASSERT(pEncCfg); + ASSERT(instAddr); + + *instAddr = NULL; + + param.clientType = EWL_CLIENT_TYPE_H264_ENC; + + /* Init EWL */ + if ((ewl = EWLInit(¶m)) == NULL) + return H264ENC_EWL_ERROR; + + /* Encoder instance */ + inst = (h264Instance_s *) EWLcalloc(1, sizeof(h264Instance_s)); + + if (inst == NULL) + { + ret = H264ENC_MEMORY_ERROR; + goto err; + } + + /* read HW configuration */ + inst->hwCfg = EWLReadAsicConfig(); + + /* Default values */ + H264SeqParameterSetInit(&inst->seqParameterSet); + H264PicParameterSetInit(&inst->picParameterSet); + H264SliceInit(&inst->slice); + H264EncDnfInit(inst); + + /* Set parameters depending on user config */ + if (SetParameter(inst, pEncCfg) != ENCHW_OK) + { + ret = H264ENC_INVALID_ARGUMENT; + goto err; + } + + if (SetPictureBuffer(inst) != ENCHW_OK) + { + ret = H264ENC_INVALID_ARGUMENT; + goto err; + } + + /* Check and init the rest of parameters */ + if (CheckParameter(inst) != ENCHW_OK) + { + ret = H264ENC_INVALID_ARGUMENT; + goto err; + } + + if (H264InitRc(&inst->rateControl, 1) != ENCHW_OK) + { + return H264ENC_INVALID_ARGUMENT; + } + + if (EncPreProcessAlloc(&inst->preProcess, + inst->mbPerRow * inst->mbPerCol) != ENCHW_OK) + return ENCHW_NOK; + + /* Initialize ASIC */ + inst->asic.ewl = ewl; + (void) EncAsicControllerInit(&inst->asic); + + /* Allocate internal SW/HW shared memories */ + if (EncAsicMemAlloc_V2(&inst->asic, + (u32) inst->preProcess.lumWidth, + (u32) inst->preProcess.lumHeight, + (u32) inst->preProcess.scaledWidth, + (u32) inst->preProcess.scaledHeight, + ASIC_H264, inst->numRefBuffsLum, + inst->numRefBuffsChr) != ENCHW_OK) + { + + ret = H264ENC_EWL_MEMORY_ERROR; + goto err; + } + + /* Assign allocated HW frame buffers into picture buffer */ + H264PictureBufferSetupH264(&inst->picBuffer, &inst->asic, + inst->numRefBuffsLum, inst->numRefBuffsChr); + + *instAddr = inst; + + /* init VUI */ + { + const h264VirtualBuffer_s *vb = &inst->rateControl.virtualBuffer; + + H264SpsSetVuiTimigInfo(&inst->seqParameterSet, + vb->timeScale, vb->unitsInTic); + } + + /* Disable 4x4 MV mode for high levels to limit MaxMvsPer2Mb */ + if (inst->seqParameterSet.levelIdc >= 31) + inst->asic.regs.h264Inter4x4Disabled = 1; + else + inst->asic.regs.h264Inter4x4Disabled = 0; + + return ret; + +err: + if (inst != NULL) + EWLfree(inst); + if (ewl != NULL) + (void) EWLRelease(ewl); + + return ret; +} + +/*------------------------------------------------------------------------------ + + H264Shutdown + + Function frees the encoder instance. + + Input h264Instance_s * Pointer to the encoder instance to be freed. + After this the pointer is no longer valid. + +------------------------------------------------------------------------------*/ +void H264Shutdown(h264Instance_s *data) +{ + const void *ewl; + + ASSERT(data); + + ewl = data->asic.ewl; + + EncAsicMemFree_V2(&data->asic); + + EncPreProcessFree(&data->preProcess); + + EWLfree(data); + + (void) EWLRelease(ewl); +} + +/*------------------------------------------------------------------------------ + + SetParameter + + Set all parameters in instance to valid values depending on user config. + +------------------------------------------------------------------------------*/ +bool_e SetParameter(h264Instance_s *inst, const H264EncConfig *pEncCfg) +{ + static gopinfo_s SvctGopL1[2] = + { + {.layer = 1, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L1 */ + {.layer = 0, .isRef = 1, .orderCmd = 0, .markCmd = 0} /* L0 */ + }; + static gopinfo_s SvctGopL2[4] = + { + {.layer = 2, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L2 */ + {.layer = 1, .isRef = 1, .orderCmd = 0, .markCmd = 0}, /* L1 */ + {.layer = 2, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L2 */ + {.layer = 0, .isRef = 1, .orderCmd = 2, .markCmd = 0} /* L0 */ + }; + static gopinfo_s SvctGopL3[8] = + { + {.layer = 3, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L3 NUM0 */ + {.layer = 2, .isRef = 1, .orderCmd = 0, .markCmd = 0}, /* L2 NUM1 */ + {.layer = 3, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L3 NUM1 */ + {.layer = 1, .isRef = 1, .orderCmd = 2, .markCmd = 0}, /* L1 NUM2 */ + {.layer = 3, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L3 NUM2 */ + {.layer = 2, .isRef = 1, .orderCmd = 0, .markCmd = 2}, /* L2 NUM3 */ + {.layer = 3, .isRef = 0, .orderCmd = 0, .markCmd = 0}, /* L3 NUM3 */ + {.layer = 0, .isRef = 1, .orderCmd = 4, .markCmd = 0} /* L0 NUM4 */ + }; + static gopinfo_s SvctReorderTest[16] = + { + {.layer = 4, .isRef = 1, .orderCmd = 0, .markCmd = 1}, /* L3 */ + {.layer = 3, .isRef = 1, .orderCmd = 2, .markCmd = 1}, /* L2 */ + {.layer = 4, .isRef = 1, .orderCmd = 3, .markCmd = 1}, /* L3 */ + {.layer = 2, .isRef = 1, .orderCmd = 4, .markCmd = 1}, /* L1 */ + {.layer = 4, .isRef = 1, .orderCmd = 5, .markCmd = 1}, /* L3 */ + {.layer = 3, .isRef = 1, .orderCmd = 6, .markCmd = 1}, /* L2 */ + {.layer = 4, .isRef = 1, .orderCmd = 7, .markCmd = 1}, /* L3 */ + {.layer = 1, .isRef = 1, .orderCmd = 8, .markCmd = 1}, /* L0 */ + {.layer = 4, .isRef = 1, .orderCmd = 9, .markCmd = 1}, /* L3 */ + {.layer = 3, .isRef = 1, .orderCmd = 10, .markCmd = 1}, /* L2 */ + {.layer = 4, .isRef = 1, .orderCmd = 11, .markCmd = 1}, /* L3 */ + {.layer = 2, .isRef = 1, .orderCmd = 12, .markCmd = 1}, /* L1 */ + {.layer = 4, .isRef = 1, .orderCmd = 13, .markCmd = 1}, /* L3 */ + {.layer = 2, .isRef = 1, .orderCmd = 14, .markCmd = 1}, /* L2 */ + {.layer = 4, .isRef = 1, .orderCmd = 15, .markCmd = 1}, /* L3 */ + {.layer = 0, .isRef = 1, .orderCmd = 16, .markCmd = 0} /* L0 */ + }; + static gopinfo_s *svctGop[4] = {&SvctGopL1[0], &SvctGopL2[0], &SvctGopL3[0], &SvctReorderTest[0]}; + + i32 width, height, tmp, bps; + EWLHwConfig_t cfg = EWLReadAsicConfig(); + + ASSERT(inst); + + /* Internal images, next macroblock boundary */ + width = 16 * ((pEncCfg->width + 15) / 16); + height = 16 * ((pEncCfg->height + 15) / 16); + + /* SVCT */ + inst->svc.level = pEncCfg->svctLevel; + inst->svc.enableSvctPrefix = pEncCfg->enableSvctPrefix; + if (pEncCfg->svctLevel) + { + if (inst->hwCfg.svctSupport==0) + return ENCHW_NOK; + + u32 level = pEncCfg->svctLevel; + u32 length = 1 << level; + + inst->seqParameterSet.gapsInFrameNumValueAllowed = ENCHW_YES; + inst->svc.gopIndex = -1; + inst->svc.gopLength = length; + inst->svc.base_priority_id = inst->svc.next_base_priority_id = 0; + memcpy(&inst->svc.gop[0], svctGop[level-1], sizeof(gopinfo_s)*length); + } + + /* stream type */ + if (pEncCfg->streamType == H264ENC_BYTE_STREAM) + { + inst->asic.regs.h264StrmMode = ASIC_H264_BYTE_STREAM; + inst->picParameterSet.byteStream = ENCHW_YES; + inst->seqParameterSet.byteStream = ENCHW_YES; + inst->rateControl.sei.byteStream = ENCHW_YES; + inst->slice.byteStream = ENCHW_YES; + } + else + { + inst->asic.regs.h264StrmMode = ASIC_H264_NAL_UNIT; + inst->picParameterSet.byteStream = ENCHW_NO; + inst->seqParameterSet.byteStream = ENCHW_NO; + inst->rateControl.sei.byteStream = ENCHW_NO; + inst->slice.byteStream = ENCHW_NO; + } + + if (pEncCfg->viewMode == H264ENC_BASE_VIEW_SINGLE_BUFFER) + { + inst->numViews = 1; + inst->numRefBuffsLum = 1; + inst->numRefBuffsChr = 2; + inst->seqParameterSet.numRefFrames = 1; + } + else if (pEncCfg->viewMode == H264ENC_BASE_VIEW_DOUBLE_BUFFER) + { + inst->numViews = 1; + inst->numRefBuffsLum = 2; + inst->numRefBuffsChr = 2; + inst->seqParameterSet.numRefFrames = 1; + } + else if (pEncCfg->viewMode == H264ENC_BASE_VIEW_MULTI_BUFFER) + { + inst->numViews = 1; + inst->numRefBuffsLum = pEncCfg->refFrameAmount + 1; + inst->numRefBuffsChr = pEncCfg->refFrameAmount + 1; + if (pEncCfg->svctLevel == 3) + { + inst->seqParameterSet.numRefFrames = 4; + } + else if (pEncCfg->svctLevel == 4) + { + inst->seqParameterSet.numRefFrames = 16; /*just for HW test */ + } + else + { + inst->seqParameterSet.numRefFrames = pEncCfg->refFrameAmount; + } + } + else if (pEncCfg->viewMode == H264ENC_MVC_STEREO_INTER_VIEW_PRED) + { + inst->numViews = 2; + inst->numRefBuffsLum = 1; + inst->numRefBuffsChr = 2; + inst->seqParameterSet.numRefFrames = 1; + } + else if (pEncCfg->viewMode == H264ENC_MVC_STEREO_INTER_PRED) + { + inst->numViews = 2; + inst->numRefBuffsLum = 2; + inst->numRefBuffsChr = 3; + inst->seqParameterSet.numRefFrames = 1; + } + else /*if(pEncCfg->viewMode == H264ENC_INTERLACED_FIELD)*/ + { + inst->numViews = 1; + inst->numRefBuffsLum = 2; + inst->numRefBuffsChr = 3; + inst->seqParameterSet.frameMbsOnly = ENCHW_NO; + /* 2 ref frames will be buffered so each field will reference previous + field with same parity (except for I-frame bottom referencing top) */ + inst->seqParameterSet.numRefFrames = 2; + inst->interlaced = 1; + /* Map unit 32-pixels high for fields */ + height = 32 * ((pEncCfg->height + 31) / 32); + } + + /* Slice */ + inst->slice.sliceSize = 0; + + /* Macroblock */ + inst->mbPerRow = width / 16; + inst->mbPerCol = height / (16 * (1 + inst->interlaced)); + inst->mbPerFrame = inst->mbPerRow * inst->mbPerCol; + + /* Disable intra and ROI areas by default */ + inst->asic.regs.intraAreaTop = inst->asic.regs.intraAreaBottom = inst->mbPerCol; + inst->asic.regs.intraAreaLeft = inst->asic.regs.intraAreaRight = inst->mbPerRow; + inst->asic.regs.roi1Top = inst->asic.regs.roi1Bottom = inst->mbPerCol; + inst->asic.regs.roi1Left = inst->asic.regs.roi1Right = inst->mbPerRow; + inst->asic.regs.roi2Top = inst->asic.regs.roi2Bottom = inst->mbPerCol; + inst->asic.regs.roi2Left = inst->asic.regs.roi2Right = inst->mbPerRow; + inst->preProcess.roiMapEnable = 0; + inst->preProcess.qpOffset[0] = 0; + inst->preProcess.qpOffset[1] = 0; + inst->preProcess.qpOffset[2] = 0; + + /* Sequence parameter set */ + inst->seqParameterSet.levelIdc = pEncCfg->level; + inst->seqParameterSet.picWidthInMbsMinus1 = width / 16 - 1; + inst->seqParameterSet.picHeightInMapUnitsMinus1 = height / (16 * (1 + inst->interlaced)) - 1; + + /* Set cropping parameters if required */ + if (pEncCfg->width % 16 || pEncCfg->height % 16 || + (inst->interlaced && pEncCfg->height % 32)) + { + inst->seqParameterSet.frameCropping = ENCHW_YES; + inst->seqParameterSet.frameCropRightOffset = (width - pEncCfg->width) / 2 ; + inst->seqParameterSet.frameCropBottomOffset = (height - pEncCfg->height) / 2; + } + + /* Level 1b is indicated with levelIdc == 11 (later) and constraintSet3 */ + if (pEncCfg->level == H264ENC_LEVEL_1_b) + { + inst->seqParameterSet.constraintSet3 = ENCHW_YES; + } + + /* Get the index for the table of level maximum values */ + tmp = H264GetLevelIndex(inst->seqParameterSet.levelIdc); + if (tmp == INVALID_LEVEL) + return ENCHW_NOK; + + inst->seqParameterSet.levelIdx = tmp; + +#if 1 /* enforce maximum frame size in level */ + if (inst->mbPerFrame > H264MaxFS[inst->seqParameterSet.levelIdx]) + { + return ENCHW_NOK; + } +#endif + +#if 0 /* enforce macroblock rate limit in level */ + { + u32 mb_rate = + (pEncCfg->frameRateNum * inst->mbPerFrame) / + pEncCfg->frameRateDenom; + + if (mb_rate > H264MaxMBPS[inst->seqParameterSet.levelIdx]) + { + return ENCHW_NOK; + } + } +#endif + + /* Picture parameter set */ + inst->picParameterSet.picInitQpMinus26 = (i32) H264ENC_DEFAULT_QP - 26; + + /* CABAC enabled by default */ + inst->picParameterSet.enableCabac = 1; + + /* Rate control setup */ + + /* Maximum bitrate for the specified level */ + bps = H264MaxBR[inst->seqParameterSet.levelIdx]; + + { + h264RateControl_s *rc = &inst->rateControl; + + rc->outRateDenom = pEncCfg->frameRateDenom; + rc->outRateNum = pEncCfg->frameRateNum; + rc->mbPerPic = (width / 16) * (height / 16); + rc->mbRows = height / 16; + + { + h264VirtualBuffer_s *vb = &rc->virtualBuffer; + + vb->bitRate = bps; + vb->unitsInTic = pEncCfg->frameRateDenom; + vb->timeScale = pEncCfg->frameRateNum; + vb->bufferSize = H264MaxCPBS[inst->seqParameterSet.levelIdx]; + } + + rc->hrd = ENCHW_YES; + rc->picRc = ENCHW_YES; + rc->mbRc = ENCHW_NO; + rc->picSkip = ENCHW_NO; + + rc->qpHdr = H264ENC_DEFAULT_QP << QP_FRACTIONAL_BITS; + rc->qpMin = 10 << QP_FRACTIONAL_BITS; + rc->qpMax = 51 << QP_FRACTIONAL_BITS; + + rc->frameCoded = ENCHW_YES; + rc->sliceTypeCur = ISLICE; + rc->sliceTypePrev = PSLICE; + rc->gopLen = 150; + + /* Default initial value for intra QP delta */ + rc->intraQpDelta = -3 << QP_FRACTIONAL_BITS; + rc->fixedIntraQp = 0 << QP_FRACTIONAL_BITS; + /* default long-term pic rate */ + rc->longTermPicRate = 15; + rc->mbQpAutoBoost = 0; + } + + /* no SEI by default */ + inst->rateControl.sei.enabled = ENCHW_NO; + + /* Pre processing */ + inst->preProcess.lumWidth = pEncCfg->width; + inst->preProcess.lumWidthSrc = + H264GetAllowedWidth(pEncCfg->width, H264ENC_YUV420_PLANAR); + + inst->preProcess.lumHeight = pEncCfg->height; + if (inst->interlaced) inst->preProcess.lumHeight = pEncCfg->height / 2; + inst->preProcess.lumHeightSrc = pEncCfg->height; + + inst->preProcess.horOffsetSrc = 0; + inst->preProcess.verOffsetSrc = 0; + + inst->preProcess.rotation = ROTATE_0; + inst->preProcess.inputFormat = H264ENC_YUV420_PLANAR; + inst->preProcess.videoStab = 0; + inst->preProcess.scaledWidth = pEncCfg->scaledWidth; + inst->preProcess.scaledHeight = pEncCfg->scaledHeight; + + /* Is HW scaling supported */ + if (cfg.scalingEnabled == EWL_HW_CONFIG_NOT_SUPPORTED) + inst->preProcess.scaledWidth = inst->preProcess.scaledHeight = 0; + + inst->preProcess.scaledOutput = + (inst->preProcess.scaledWidth * inst->preProcess.scaledHeight ? 1 : 0); + inst->preProcess.adaptiveRoi = 0; + inst->preProcess.adaptiveRoiColor = 0; + inst->preProcess.adaptiveRoiMotion = -5; + + inst->preProcess.colorConversionType = 0; + EncSetColorConversion(&inst->preProcess, &inst->asic); + + /* Level 1b is indicated with levelIdc == 11 (constraintSet3) */ + if (pEncCfg->level == H264ENC_LEVEL_1_b) + { + inst->seqParameterSet.levelIdc = 11; + } + + /* reference frame compression */ + if ((pEncCfg->refFrameCompress)&&(inst->hwCfg.rfcSupport==0)) + return ENCHW_NOK; + + inst->asic.regs.refLumCompress = (pEncCfg->refFrameCompress&1) ? 1 : 0; + inst->asic.regs.refChrCompress = (pEncCfg->refFrameCompress&2) ? 1 : 0; + inst->asic.regs.rfcLumDiscreteMode = 1; + + if ((pEncCfg->viewMode == H264ENC_BASE_VIEW_DOUBLE_BUFFER) || + (pEncCfg->viewMode == H264ENC_BASE_VIEW_MULTI_BUFFER)) + inst->asic.regs.rfcLumDiscreteMode = 0; + inst->asic.regs.rfcLumBufLimit = inst->mbPerCol*inst->mbPerRow*256*pEncCfg->rfcLumBufLimit/100; + inst->asic.regs.rfcChrBufLimit = inst->mbPerCol*inst->mbPerRow*128*pEncCfg->rfcChrBufLimit/100; + inst->asic.regs.rfcLumBufLimit /= 8; + inst->asic.regs.rfcChrBufLimit /= 8; + inst->asic.regs.rfcOverflowIRQEn = ENCH1_RFC_OVERFLOW_INTERRUPT&1; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + CheckParameter + +------------------------------------------------------------------------------*/ +bool_e CheckParameter(const h264Instance_s *inst) +{ + /* Check crop */ + if (EncPreProcessCheck(&inst->preProcess) != ENCHW_OK) + { + return ENCHW_NOK; + } + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + SetPictureBuffer + +------------------------------------------------------------------------------*/ +i32 SetPictureBuffer(h264Instance_s *inst) +{ + picBuffer *picBuffer = &inst->picBuffer; + i32 width, height; + + width = inst->mbPerRow * 16; + height = inst->mbPerCol * 16; + if (H264PictureBufferAlloc(picBuffer, width, height) != ENCHW_OK) + return ENCHW_NOK; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + Round the width to the next multiple of 8 or 16 depending on YUV type. + +------------------------------------------------------------------------------*/ +i32 H264GetAllowedWidth(i32 width, H264EncPictureType inputType) +{ + if (inputType == H264ENC_YUV420_PLANAR) + { + /* Width must be multiple of 16 to make + * chrominance row 64-bit aligned */ + return ((width + 15) / 16) * 16; + } + else + { + /* H264ENC_YUV420_SEMIPLANAR */ + /* H264ENC_YUV422_INTERLEAVED_YUYV */ + /* H264ENC_YUV422_INTERLEAVED_UYVY */ + return ((width + 7) / 8) * 8; + } +} diff --git a/lib/vc8000nanoe/source/h264/H264Init.h b/lib/vc8000nanoe/source/h264/H264Init.h new file mode 100644 index 000000000..87fc047eb --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Init.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Encoder initialization and setup + * + ******************************************************************************** + */ + +#ifndef __H264_INIT_H__ +#define __H264_INIT_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "h264encapi.h" +#include "H264Instance.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +bool_e H264CheckCfg(const H264EncConfig * pEncCfg); +i32 H264GetAllowedWidth(i32 width, H264EncPictureType inputType); + +H264EncRet H264Init(const H264EncConfig * pEncCfg, h264Instance_s ** instAddr); + +void H264Shutdown(h264Instance_s *data); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264Instance.h b/lib/vc8000nanoe/source/h264/H264Instance.h new file mode 100644 index 000000000..27873c684 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Instance.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Encoder instance + * + ******************************************************************************** + */ + +#ifndef __H264_INSTANCE_H__ +#define __H264_INSTANCE_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "enccommon.h" +#include "encpreprocess.h" +#include "encasiccontroller.h" + +#include "h264encapi.h" /* Callback type from API is reused */ + +#include "H264NalUnit.h" +#include "H264SequenceParameterSet.h" +#include "H264PictureParameterSet.h" +#include "H264PictureBuffer.h" +#include "H264Slice.h" +#include "H264RateControl.h" +#include "H264Mad.h" + +#ifdef VIDEOSTAB_ENABLED +#include "vidstabcommon.h" +#endif + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ +enum H264EncStatus +{ + H264ENCSTAT_INIT = 0xA1, + H264ENCSTAT_START_STREAM, + H264ENCSTAT_START_FRAME, + H264ENCSTAT_ERROR +}; + +typedef struct +{ + u32 encStatus; + u32 mbPerFrame; + u32 mbPerRow; + u32 mbPerCol; + u32 interlaced; + u32 frameCnt; + u32 fillerNalSize; + u32 testId; + u32 numViews; + u32 numRefBuffsLum; + u32 numRefBuffsChr; + u32 intraSliceMap[3]; + u32 idrHdr; + stream_s stream; + preProcess_s preProcess; + sps_s seqParameterSet; + pps_s picParameterSet; + slice_s slice; + mvc_s mvc; + svc_s svc; /* info of SVCT */ + h264RateControl_s rateControl; + madTable_s mad; + asicData_s asic; + i32 naluOffset; /* Start offset for NAL unit size table */ + i32 numNalus; /* Number of NAL units created */ + H264EncSliceReadyCallBackFunc sliceReadyCbFunc; + u32 *pOutBuf; /* User given stream output buffer */ + void *pAppData; /* User given application specific data */ + const void *inst; + picBuffer picBuffer; + EWLHwConfig_t hwCfg; +#ifdef VIDEOSTAB_ENABLED + HWStabData vsHwData; + SwStbData vsSwData; +#endif + i32 gdrEnabled; + i32 gdrStart; + i32 gdrDuration; + i32 gdrCount; + i32 gdrAverageMBRows; + i32 gdrMBLeft; + i32 gdrFirstIntraFrame; + inputLineBuf_s inputLineBuf; + i32 rfcBufOverflow; + /* denoise filter */ + int dnfEnable; + int dnfNoiseLevelY; + int dnfNoiseYCRatio; + int dnfTableLoaded; + int dnfNoiseLevelLow; + int dnfNoiseLevels[5]; + int dnfNoiseLevelC; + u32 dnfNoiseLevelPred; + int dnfNoiseLevelMax; + int dnfNoiseMaxPred; + int dnfNoiseMaxPrev; + int dnfQpPrev; + u32 dnfFrameNum; +} h264Instance_s; + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264Mad.c b/lib/vc8000nanoe/source/h264/H264Mad.c new file mode 100644 index 000000000..106ae1a58 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Mad.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Rate control + * + ******************************************************************************** + */ + +#include "H264Mad.h" + +/*------------------------------------------------------------------------------ + + Init MAD structure + +------------------------------------------------------------------------------*/ +void H264MadInit(madTable_s *mad, u32 mbPerFrame) +{ + i32 i; + + mad->mbPerFrame = mbPerFrame; + + /* Initial threshold for the first frame. */ + mad->threshold[0] = 256*16; + mad->threshold[1] = 256*8; + mad->threshold[2] = 256*4; + + for (i = 0; i < MAD_TABLE_LEN; i++) + { + mad->th[i] = 0; + mad->count[i] = 0; + } + mad->pos = 0; + mad->len = 0; +} + +/*------------------------------------------------------------------------------ + update_tables() +------------------------------------------------------------------------------*/ +static void update_tables(madTable_s *p, i32 th, i32 count) +{ + const i32 clen = 3; + i32 tmp = p->pos; + + p->th[tmp] = th; + p->count[tmp] = count; + + if (++p->pos >= clen) { + p->pos = 0; + } + if (p->len < clen) { + p->len++; + } +} +/*------------------------------------------------------------------------------ + lin_sx() calculate value of Sx for n points. +------------------------------------------------------------------------------*/ +static i32 lin_sx(i32 *x, i32 n) +{ + i32 sum = 0; + + while (n--) { + sum += x[n]; + if (sum < 0) { + return I32_MAX; + } + } + return sum; +} + +/*------------------------------------------------------------------------------ + lin_sxy() calculate value of Sxy for n points. +------------------------------------------------------------------------------*/ +static i32 lin_sxy(i32 *qp, i32 *r, i32 n) +{ + i32 sum = 0; + + while (n--) { + sum += qp[n] * r[n]; + if (sum < 0) { + return I32_MAX; + } + } + return sum; +} + +/*------------------------------------------------------------------------------ + lin_nsxx() calculate value of n * Sxx for n points. +------------------------------------------------------------------------------*/ +static i32 lin_nsxx(i32 *qp, i32 n) +{ + i32 sum = 0, d = n; + + while (n--) { + sum += d * qp[n] * qp[n]; + if (sum < 0) { + return I32_MAX; + } + } + return sum; +} + +/*------------------------------------------------------------------------------ + update_model() Update model parameter by Linear Regression. +------------------------------------------------------------------------------*/ +static void update_model(madTable_s *p) +{ + i32 *count = p->count, *th = p->th, n = p->len; + i32 sx = lin_sx(p->count, n); + i32 sy = lin_sx(p->th, n); + i32 a1 = 0, a2 = 0; + + /*i32 i; + for (i = 0; i < n; i++) { + printf("model: cnt %i th %i\n", count[i], th[i]); + }*/ + + ASSERT(sx >= 0); + ASSERT(sy >= 0); + + if (n > 1) + { + a1 = lin_sxy(count, th, n); + a1 = a1 < (I32_MAX / n) ? a1 * n : I32_MAX; + + if (sy) { + a1 -= sx < (I32_MAX / sy) ? sx * sy : I32_MAX; + } + + a2 = (lin_nsxx(count, n) - (sx * sx)); + if (a2) { + a1 = DIV(a1 * DSCY, a2); + } else { + a1 = 0; + } + + /* Value of a1 shouldn't be excessive */ + a1 = MAX(a1, 0); + a1 = MIN(a1, 1024*DSCY); + + if (n) + a2 = DIV(sy, n) - DIV(a1 * sx, n*DSCY); + else + a2 = 0; + } + + p->a1 = a1; + p->a2 = a2; + + /*printf("model: a2:%9d a1:%8d\n", p->a2, p->a1);*/ +} + +/*------------------------------------------------------------------------------ + + Update MAD threshold based on previous frame count of macroblocks with MAD + under threshold. Trying to adjust threshold so that madCount == targetCount. + +------------------------------------------------------------------------------*/ +void H264MadThreshold(madTable_s *mad, u32 *madCount) +{ + /* Target to improve quality for 40% of macroblocks */ + i32 targetCount = 40*mad->mbPerFrame/100; + i32 threshold = mad->threshold[0]; + i32 prevthreshold = mad->threshold[0]; + i32 lowLimit, highLimit; + + update_tables(mad, prevthreshold, madCount[0]); + update_model(mad); + + /* Calculate new threshold for next frame using either linear regression + * model or adjustment based on current setting */ + if (mad->a1) + threshold = mad->a1 * targetCount / DSCY + mad->a2; + else if (madCount[0] < (u32)targetCount) + threshold = MAX(prevthreshold * 5/4, prevthreshold + 256); + else + threshold = MIN(prevthreshold * 3/4, prevthreshold - 256); + + /* For small count, ensure that we increase the threshold minimum 1 step */ + if (madCount[0] < (u32)targetCount/2) + threshold = MAX(threshold, prevthreshold + 256); + + /* If previous frame had zero count, ensure that we increase threshold */ + if (!madCount[0]) + threshold = MAX(threshold, prevthreshold + 256*4); + + /* Limit how much the threshold can change between two frames */ + lowLimit = prevthreshold/2; + highLimit = MAX(prevthreshold*2, 256*4); + threshold = MIN(highLimit, MAX(lowLimit, threshold)); + + /* threshold_div256 has 6-bits range [0,63] */ + threshold = ((threshold+128)/256)*256; + mad->threshold[0] = MAX(0, MIN(63*256, threshold)); + + /* Middle threshold: 2/3 of high threshold, smaller but not negative. */ + threshold = ((mad->threshold[0] * 2/3 + 128)/256)*256; + mad->threshold[1] = MAX(0, MIN(mad->threshold[0] - 256, threshold)); + + /* Low threshold: 1/3 of high threshold, smaller but not negative. */ + threshold = ((mad->threshold[0] * 1/3 + 128)/256)*256; + mad->threshold[2] = MAX(0, MIN(mad->threshold[1] - 256, threshold)); + +} + diff --git a/lib/vc8000nanoe/source/h264/H264Mad.h b/lib/vc8000nanoe/source/h264/H264Mad.h new file mode 100644 index 000000000..aa411fc94 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Mad.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : MAD threshold calculation + * + ******************************************************************************** + */ + +#ifndef H264_MAD_H +#define H264_MAD_H + +#include "enccommon.h" + +#define DSCY 32 /* n * 32 */ +#define I32_MAX 2147483647 /* 2 ^ 31 - 1 */ +#define DIV(a, b) (((a) + (SIGN(a) * (b)) / 2) / (b)) +#define MAD_TABLE_LEN 5 + +typedef struct { + i32 a1; /* model parameter, y = a1*x + a2 */ + i32 a2; /* model parameter */ + i32 th[MAD_TABLE_LEN]; /* mad threshold */ + i32 count[MAD_TABLE_LEN]; /* number of macroblocks under threshold */ + i32 pos; /* current position */ + i32 len; /* current lenght */ + i32 threshold[3]; /* current frame thresholds: high/mid/low */ + i32 mbPerFrame; /* number of macroblocks per frame */ +} madTable_s; + +/*------------------------------------------------------------------------------ + Function prototypes +------------------------------------------------------------------------------*/ + +void H264MadInit(madTable_s *mad, u32 mbPerFrame); + +void H264MadThreshold(madTable_s *madTable, u32 *madCount); + +#endif + diff --git a/lib/vc8000nanoe/source/h264/H264NalUnit.c b/lib/vc8000nanoe/source/h264/H264NalUnit.c new file mode 100644 index 000000000..bda98c3a5 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264NalUnit.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : NAL unit handling + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "enccommon.h" +#include "H264NalUnit.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + H264NalUnit + +------------------------------------------------------------------------------*/ +void H264NalUnitHdr(stream_s * stream, i32 nalRefIdc, nalUnitType_e nalUnitType, + true_e byteStream) +{ + if(byteStream == ENCHW_YES) + { + H264PutBits(stream, 0, 8); + COMMENT("BYTE STREAM: leadin_zero_8bits"); + + H264PutBits(stream, 0, 8); + COMMENT("BYTE STREAM: Start_code_prefix"); + + H264PutBits(stream, 0, 8); + COMMENT("BYTE STREAM: Start_code_prefix"); + + H264PutBits(stream, 1, 8); + COMMENT("BYTE STREAM: Start_code_prefix"); + } + + H264PutBits(stream, 0, 1); + COMMENT("forbidden_zero_bit"); + + H264PutBits(stream, nalRefIdc, 2); + COMMENT("nal_ref_idc"); + + H264PutBits(stream, (i32) nalUnitType, 5); + COMMENT("nal_unit_type"); + + stream->zeroBytes = 0; /* we start new counter for zero bytes */ + +} + +/*------------------------------------------------------------------------------ + + H264NalUnitHdrMvcExtension + +------------------------------------------------------------------------------*/ +void H264NalUnitHdrMvcExtension(stream_s * stream, mvc_s * mvc) +{ + + H264PutBits(stream, !mvc->anchorPicFlag, 1); + COMMENT("non_idr_flag"); + H264PutBits(stream, mvc->priorityId, 6); + COMMENT("priority_id"); + H264PutBits(stream, mvc->viewId, 10); + COMMENT("view_id"); + H264PutBits(stream, mvc->temporalId, 3); + COMMENT("temporal_id"); + H264PutBits(stream, mvc->anchorPicFlag, 1); + COMMENT("anchor_pic_flag"); + H264PutBits(stream, mvc->interViewFlag, 1); + COMMENT("inter_view_flag"); + H264PutBits(stream, 1, 1); + COMMENT("reserved_one_bit"); + + stream->zeroBytes = 0; /* we start new counter for zero bytes */ + +} + +/*------------------------------------------------------------------------------ + + H264NalUnitHdrSvcExtension + +------------------------------------------------------------------------------*/ +void H264NalUnitHdrSvcExtension(stream_s * stream, svc_s * svc) +{ + u32 layer = (svc->gopIndex==-1)?(0):(svc->gop[svc->gopIndex].layer); + H264PutBits(stream, (svc->gopIndex == -1), 1); + COMMENT("idr_flag"); + H264PutBits(stream, layer, 6); + COMMENT("priority_id"); + H264PutBits(stream, 1, 1); + COMMENT("no_inter_layer_pred_flag"); + H264PutBits(stream, 0, 3); + COMMENT("dependency_id"); + H264PutBits(stream, 0, 4); + COMMENT("quality_id"); + H264PutBits(stream, layer, 3); + COMMENT("temporal_id"); + H264PutBits(stream, 0, 1); + COMMENT("use_ref_base_pic_flag"); + H264PutBits(stream, 1, 1); + COMMENT("discardable_flag"); + H264PutBits(stream, 1, 1); + COMMENT("output_flag"); + H264PutBits(stream, 3, 2); + COMMENT("reserved_three_2bits"); + + stream->zeroBytes = 0; /* we start new counter for zero bytes */ + + /* prefix_nal_unit_svc() */ + if (layer != svc->level) + { + H264PutBits(stream, 0x20, 8); + COMMENT("prefix_nal_unit_svc()"); + } + +} + +/*------------------------------------------------------------------------------ + + H264NalUnitTrailinBits + +------------------------------------------------------------------------------*/ +void H264NalUnitTrailinBits(stream_s * stream, true_e byteStream) +{ + H264RbspTrailingBits(stream); + + if(byteStream == ENCHW_YES) + { +#if 0 /* system model has removed this */ + H264PutBits(stream, 0, 8); + COMMENT("BYTE STREAM: trailing_zero_8bits"); +#endif + } + + return; +} + +u32 H264FillerNALU(stream_s * sp, i32 cnt, true_e byteStream) +{ + i32 i = cnt; + u32 nal_size; + + nal_size = sp->byteCnt; + + ASSERT(sp != NULL); + + H264NalUnitHdr(sp, 0, FILLERDATA, byteStream); + + for(; i > 0; i--) + { + H264NalBits(sp, 0xFF, 8); + COMMENT("filler ff_byte"); + } + H264RbspTrailingBits(sp); + + nal_size = sp->byteCnt - nal_size; + + return nal_size; +} diff --git a/lib/vc8000nanoe/source/h264/H264NalUnit.h b/lib/vc8000nanoe/source/h264/H264NalUnit.h new file mode 100644 index 000000000..96edcfda2 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264NalUnit.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : NAL unit handling + * + ******************************************************************************** + */ + +#ifndef __H264_NAL_UNIT_H__ +#define __H264_NAL_UNIT_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "H264PutBits.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +typedef struct +{ + u32 anchorPicFlag; + u32 priorityId; + u32 viewId; + u32 temporalId; + u32 interViewFlag; +} mvc_s; + +#define MAX_GOP_SIZE 16 + +typedef struct +{ + int layer; + int isRef; + int orderCmd; + int markCmd; +} gopinfo_s; + +typedef struct +{ + u32 level; + gopinfo_s gop[MAX_GOP_SIZE]; + i32 gopIndex; /* -1: IDR; 0~GOP_SIZE-1: index in gop */ + i32 gopLength; + u32 next_base_priority_id; + u32 base_priority_id; + u32 enableSvctPrefix; +} svc_s; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +void H264NalUnitHdr(stream_s * stream, i32 nalRefIdc, nalUnitType_e + nalUnitType, true_e byteStream); +void H264NalUnitHdrMvcExtension(stream_s * stream, mvc_s * mvc); +void H264NalUnitHdrSvcExtension(stream_s * stream, svc_s * svc); +void H264NalUnitTrailinBits(stream_s * stream, true_e byteStream); +u32 H264FillerNALU(stream_s * sp, i32 cnt, true_e byteStream); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264PictureBuffer.c b/lib/vc8000nanoe/source/h264/H264PictureBuffer.c new file mode 100644 index 000000000..e6920212f --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264PictureBuffer.c @@ -0,0 +1,737 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + Include headers +------------------------------------------------------------------------------*/ + +#include "enccommon.h" +#include "H264PictureBuffer.h" + +/*------------------------------------------------------------------------------ + External compiler flags +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Module defines +------------------------------------------------------------------------------*/ + +/* Enable this to print contents of picture buffer */ +/*#define TRACE_PIC_BUFFER*/ + +/*------------------------------------------------------------------------------ + Local function prototypes +------------------------------------------------------------------------------*/ +static i32 Alloc(refPic *refPic, i32 width, i32 height); +static void RefPicListInitialization(picBuffer *ref); +static void ResetRefPic(refPic *refPic); +#ifdef TRACE_PIC_BUFFER +static void PrintPicBuffer(picBuffer *picBuffer); +#endif + +/*------------------------------------------------------------------------------ + PictureBufferAlloc +------------------------------------------------------------------------------*/ +i32 H264PictureBufferAlloc(picBuffer *picBuffer, i32 width, i32 height) +{ + i32 i; + + /* Be sure that everything is initialized if something goes wrong */ + EWLmemset(picBuffer->refPic, 0, sizeof(picBuffer->refPic)); + EWLmemset(picBuffer->refPicList, 0, sizeof(picBuffer->refPicList)); + + /* Reference frame base (lum,cb) and macroblock stuff */ + for (i = 0; i < BUFFER_SIZE + 1; i++) { + if (Alloc(&picBuffer->refPic[i], width, height) != ENCHW_OK) { + H264PictureBufferFree(picBuffer); + return ENCHW_NOK; + } + /* Back reference pointer (pointer to itself) */ + picBuffer->refPic[i].refPic = &picBuffer->refPic[i]; + } + picBuffer->cur_pic = &picBuffer->refPic[0]; + + return ENCHW_OK; +} + + +/*------------------------------------------------------------------------------ + H264PictureBufferSetupH264 +------------------------------------------------------------------------------*/ +i32 H264PictureBufferSetupH264(picBuffer *picBuffer, asicData_s *asic, u32 numRefBuffsLum, u32 numRefBuffsChr) +{ + u32 i; + + picBuffer->size = MAX(1, numRefBuffsLum - 1); + for (i = 0; i < numRefBuffsLum; i++) + picBuffer->refPic[i].picture.lum = asic->internalImageLuma[i].busAddress; + for (i = 0; i < numRefBuffsChr; i++) + picBuffer->refPic[i].picture.cb = asic->internalImageChroma[i].busAddress; + + /* single luma buffer -> copy buffer pointer */ + if (numRefBuffsLum == 1) + { + /* single buffer mode */ + picBuffer->refPic[1].picture.lum = + picBuffer->refPic[0].picture.lum; + } + return ENCHW_OK; +} +/*------------------------------------------------------------------------------ + PictureBufferFree +------------------------------------------------------------------------------*/ +void H264PictureBufferFree(picBuffer *picBuffer) +{ + EWLmemset(picBuffer->refPic, 0, sizeof(picBuffer->refPic)); +} + +/*------------------------------------------------------------------------------ + Alloc Reserve memory of reference picture. +------------------------------------------------------------------------------*/ +i32 Alloc(refPic *refPic, i32 width, i32 height) +{ + refPic->picture.lumWidth = width; + refPic->picture.lumHeight = height; + refPic->picture.chWidth = width/2; + refPic->picture.chHeight = height/2; + refPic->picture.lum = 0; + refPic->picture.cb = 0; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + InitializePictureBuffer +------------------------------------------------------------------------------*/ +void H264InitializePictureBuffer(picBuffer *picBuffer) +{ + i32 i; + + /* I frame (key frame) resets reference pictures */ + if (picBuffer->cur_pic->i_frame) { + picBuffer->cur_pic->p_frame = false; + picBuffer->cur_pic->ipf = true; + picBuffer->cur_pic->grf = false; /* Only mark LTR when told. */ + picBuffer->cur_pic->arf = false; + for (i = 0; i < BUFFER_SIZE + 1; i++) { + if (&picBuffer->refPic[i] != picBuffer->cur_pic) { + ResetRefPic(&picBuffer->refPic[i]); + } + } + } + + /* Initialize reference picture list, note that API (user) can change + * reference picture list */ + for (i = 0; i < BUFFER_SIZE; i++) { + ResetRefPic(&picBuffer->refPicList[i]); + } + RefPicListInitialization(picBuffer); +} + +/*------------------------------------------------------------------------------ + UpdatePictureBuffer +------------------------------------------------------------------------------*/ +void H264UpdatePictureBuffer(picBuffer *picBuffer) +{ + refPic *cur_pic, *tmp, *refPic, *refPicList; + i32 i, j; + + refPicList = picBuffer->refPicList; /* Reference frame list */ + refPic = picBuffer->refPic; /* Reference frame store */ + cur_pic = picBuffer->cur_pic; /* Reconstructed picture */ + picBuffer->last_pic = picBuffer->cur_pic; + + /* Reset old marks from reference frame store if user wants to change + * current ips/grf/arf frames. */ + + /* Input picture marking */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (&refPic[i] == cur_pic) continue; + if (cur_pic->ipf) refPic[i].ipf = false; + if (cur_pic->grf) { + refPic[i].grf = false; + /*refPic[i].search = false;*/ + if (!cur_pic->i_frame) + refPic[i].ipf = false; + } + if (cur_pic->arf) refPic[i].arf = false; + } + + /* Reference picture marking */ + for (i = 0; i < picBuffer->size; i++) { + for (j = 0; j < picBuffer->size + 1; j++) { + if (refPicList[i].grf) refPic[j].grf = false; + if (refPicList[i].arf) refPic[j].arf = false; + } + } + + /* Reference picture status is changed */ + for (i = 0; i < picBuffer->size; i++) { + if (refPicList[i].grf) refPicList[i].refPic->grf = true; + if (refPicList[i].arf) refPicList[i].refPic->arf = true; + } + + /* Find new picture not used as reference and set it to new cur_pic */ + for (i = 0; i < picBuffer->size + 1; i++) { + tmp = &refPic[i]; + if (!tmp->ipf && !tmp->arf && !tmp->grf) { + picBuffer->cur_pic = &refPic[i]; + break; + } + } +} + +static i32 H264FindMinFrameNum(picBuffer *picBuffer, u32 frameNumBits) +{ + refPic *cur_pic, *refPic; + i32 maxPic=0, lminPic=(1<refPic; /* Reference frame store */ + cur_pic = picBuffer->cur_pic; /* Reconstructed picture */ + + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].ipf) { + if (cur_pic==&refPic[i]) continue; + num = refPic[i].frameNum; + if (num > maxPic) maxPic = num; + if (num < lminPic) lminPic = num; + if ( (num>256) && (num (1<<(frameNumBits-1))) + { + /*need Wrap */ + return rminPic; + } + else + { + /*no Wrap */ + return lminPic; + } +} + + +static i32 H264FindMaxFrameNum(picBuffer *picBuffer, u32 frameNumBits) +{ + refPic *cur_pic, *refPic; + i32 rmaxPic=0, lmaxPic=0; + i32 i, num; + + refPic = picBuffer->refPic; /* Reference frame store */ + cur_pic = picBuffer->cur_pic; /* Reconstructed picture */ + + for (i = 0; i < picBuffer->size + 1; i++) + { + if (refPic[i].ipf) + { + if (cur_pic==&refPic[i]) continue; + num = refPic[i].frameNum; + if (num > rmaxPic) rmaxPic = num; + if ((num<256) && (num >lmaxPic)) lmaxPic = num; + } + } + if ( rmaxPic == (1<<(frameNumBits))) + { + /*need Wrap */ + return lmaxPic; + } + else + { + /*no Wrap */ + return rmaxPic; + } +} + +/*------------------------------------------------------------------------------ + H264UpdatePictureBufferForSvct +------------------------------------------------------------------------------*/ +void H264UpdatePictureBufferForSvct(picBuffer *picBuffer, u32 frameNumBits, i32 mark) +{ + refPic *tmp, *refPic; + i32 picNum; + i32 i; + + refPic = picBuffer->refPic; /* Reference frame store */ + picBuffer->last_pic = picBuffer->cur_pic; + + picBuffer->cur_pic = NULL; + + /* Find new picture not used as reference and set it to new cur_pic */ + for (i = 0; i < picBuffer->size + 1; i++) { + tmp = &refPic[i]; + if (!tmp->ipf && !tmp->arf && !tmp->grf) { + picBuffer->cur_pic = &refPic[i]; + break; + } + } + + /* find the small picNum */ + if (picBuffer->cur_pic==NULL) + { + if (mark!=0) + { + /* mark some reference as non-reference */ + picNum = picBuffer->last_pic->frameNum - (mark-1); + if (picNum < 0) picNum += (1<size + 1; i++) { + tmp = &refPic[i]; + if (picNum==tmp->frameNum) { + picBuffer->cur_pic = tmp; + continue; + } + } + } + ASSERT(picBuffer->cur_pic!=NULL); +} + +/*------------------------------------------------------------------------------ + RefPicListInitialization +------------------------------------------------------------------------------*/ +void RefPicListInitialization(picBuffer *picBuffer) +{ + refPic *cur_pic, *refPic, *refPicList; + i32 i, j = 0; + + refPicList = picBuffer->refPicList; /* Reference frame list */ + refPic = picBuffer->refPic; /* Reference frame store */ + cur_pic = picBuffer->cur_pic; /* Reconstructed picture */ + + /* The first in the list is immediately previous picture. Note that + * cur_pic (the picture under reconstruction) is skipped */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].ipf && (&refPic[i] != cur_pic)) { + refPicList[j++] = refPic[i]; + /* break; */ + } + } + + /* The second in the list is golden frame */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].grf && (&refPic[i] != cur_pic)) { + refPicList[j++] = refPic[i]; + break; + } + } + + /* The third in the list is alternative reference frame */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].arf && (&refPic[i] != cur_pic)) { + refPicList[j] = refPic[i]; + break; + } + } + + /* Reset the ipf/grf/arf flags */ + for (i = 0; i < picBuffer->size; i++) { + /*refPicList[i].ipf = false;*/ + refPicList[i].arf = false; + } +} + +/*------------------------------------------------------------------------------ + ResetRefPic +------------------------------------------------------------------------------*/ +void ResetRefPic(refPic *refPic) +{ + refPic->poc = -1; + refPic->i_frame = false; + refPic->p_frame = false; + refPic->show = false; + refPic->ipf = false; + refPic->arf = false; + refPic->grf = false; + refPic->search = false; +} + +/*------------------------------------------------------------------------------ + PictureBufferSetRef + + Set the ASIC reference and reconstructed frame buffers based + on the user preference and picture buffer. +------------------------------------------------------------------------------*/ +void H264PictureBufferSetRef(picBuffer *picBuffer, asicData_s *asic, u32 numViews) +{ + i32 i, j, refIdx = -1, refIdx2 = -1; + refPic *refPicList = picBuffer->refPicList; + i32 noGrf = 0, noArf = 0; + + /* Amount of buffered frames limits grf/arf availability. */ + if (picBuffer->size < 2) { picBuffer->cur_pic->grf = false; } + picBuffer->cur_pic->arf = false; + + /* ASIC can use one or two reference frame, use the first ones marked + * for reference but don't use the same frame for both. */ + for (i = 0; i < BUFFER_SIZE; i++) { + if ((i < picBuffer->size) && refPicList[i].search && + (refPicList[i].ipf || refPicList[i].grf)) { + if (refIdx == -1) + refIdx = i; + else if ((refIdx2 == -1) && + (refPicList[refIdx].picture.lum != + refPicList[i].picture.lum)) + refIdx2 = i; + else + refPicList[i].search = 0; + } else { + refPicList[i].search = 0; + } + } + + /* If no reference specified, use ipf if available, otherwise ltr */ + if (refIdx == -1) + { + refIdx = 0; + picBuffer->refPicList[refIdx].search = 1; + } + + asic->regs.mvRefIdx[0] = asic->regs.markCurrentLongTerm = 0; + + /* Set the reference buffer for ASIC, no reference for intra frames */ + if (numViews == 1 && picBuffer->cur_pic->p_frame) { + /* Mark the ref pic that is used */ + ASSERT(picBuffer->refPicList[refIdx].search == 1); + + /* Check that enough frame buffers is available. */ + ASSERT(refPicList[refIdx].picture.lum); + + asic->regs.internalImageLumBaseR[0] = refPicList[refIdx].picture.lum; + asic->regs.internalImageChrBaseR[0] = refPicList[refIdx].picture.cb; + asic->regs.internalImageLumBaseR[1] = refPicList[refIdx].picture.lum; + asic->regs.internalImageChrBaseR[1] = refPicList[refIdx].picture.cb; + asic->regs.ref2Enable = 0; + if (refIdx || (refPicList[refIdx].grf && !refPicList[refIdx].i_frame)) + asic->regs.mvRefIdx[0] = 1; /* long-term as primary ref */ + + /* Enable second reference frame usage */ + if (refIdx2 != -1 && !refPicList[refIdx].grf) { + asic->regs.internalImageLumBaseR[1] = refPicList[refIdx2].picture.lum; + asic->regs.internalImageChrBaseR[1] = refPicList[refIdx2].picture.cb; + asic->regs.ref2Enable = 1; + } + } + + if (picBuffer->cur_pic->grf) + { + asic->regs.markCurrentLongTerm = 1; /* current marked as long term */ + } + + /* Set the reconstructed frame buffer for ASIC. Luma can be written + * to same buffer but chroma read and write buffers must be different. */ + asic->regs.recWriteDisable = 0; + if (!picBuffer->cur_pic->picture.lum) { + refPic *cur_pic = picBuffer->cur_pic; + refPic *cand; + i32 recIdx = -1; + + /* No free luma buffer so we must "steal" a luma buffer from + * some other ref pic that is no longer needed. */ + for (i = 0; i < picBuffer->size + 1; i++) { + noGrf = noArf = 0; + cand = &picBuffer->refPic[i]; + if (cand == cur_pic) continue; + /* Also check the list for frame buffer copy flags. */ + for (j = 0; j < picBuffer->size; j++) + if (refPicList[j].refPic == cand) { + noGrf = refPicList[j].grf; + noArf = refPicList[j].arf; + } + /* Buffer is available if cur_pic refreshes the reference. */ + if (((cur_pic->ipf | cand->ipf ) == cur_pic->ipf) && + ((cur_pic->grf | cand->grf | noGrf) == cur_pic->grf) && + ((cur_pic->arf | cand->arf | noArf) == cur_pic->arf)) + recIdx = i; + } + + if (recIdx >= 0) { + /* recIdx is overwritten or unused so steal it */ + cur_pic->picture.lum = picBuffer->refPic[recIdx].picture.lum; + picBuffer->refPic[recIdx].picture.lum = 0; + } else { + /* No available buffer found, must be no refresh */ + ASSERT((cur_pic->ipf | cur_pic->grf | cur_pic->arf) == 0); + asic->regs.recWriteDisable = 1; + } + } + + if (!picBuffer->cur_pic->ipf && !picBuffer->cur_pic->grf) + asic->regs.recWriteDisable = 1; + + /* set orderCmd */ + asic->regs.reorderFlag = 0; + asic->regs.reorderDiff = 0; + + if (numViews == 1) + { + asic->regs.internalImageLumBaseW = picBuffer->cur_pic->picture.lum; + asic->regs.internalImageChrBaseW = picBuffer->cur_pic->picture.cb; + } + + /* For P-frames the chroma buffers must be different. */ + if (picBuffer->cur_pic->p_frame) { + ASSERT(asic->regs.internalImageChrBaseR[0] != asic->regs.internalImageChrBaseW); + } + + /* If current picture shall refresh grf/arf remove marks from ref list */ + for (i = 0; i < picBuffer->size; i++) { + if (picBuffer->cur_pic->grf) + picBuffer->refPicList[i].grf = false; + } + + /* Set compression table */ + if (asic->regs.refLumCompress) + { + asic->regs.internalImageLumTableBaseW = asic->regs.internalImageLumBaseW + asic->internalImageLumSize; + asic->regs.internalImageLumTableBaseR[0] = asic->regs.internalImageLumBaseR[0] + asic->internalImageLumSize; + if (asic->regs.internalImageLumBaseR[1]) + asic->regs.internalImageLumTableBaseR[1] = asic->regs.internalImageLumBaseR[1] + asic->internalImageLumSize; + else + asic->regs.internalImageLumTableBaseR[1] = 0; + } + if (asic->regs.refChrCompress) + { + asic->regs.internalImageChrTableBaseW = asic->regs.internalImageChrBaseW + asic->internalImageChrSize; + asic->regs.internalImageChrTableBaseR[0] = asic->regs.internalImageChrBaseR[0] + asic->internalImageChrSize; + if (asic->regs.internalImageChrBaseR[1]) + asic->regs.internalImageChrTableBaseR[1] = asic->regs.internalImageChrBaseR[1] + asic->internalImageChrSize; + else + asic->regs.internalImageChrTableBaseR[1] = 0; + } + +#ifdef TRACE_PIC_BUFFER + PrintPicBuffer(picBuffer); +#endif +} + +/*------------------------------------------------------------------------------ + H264PictureBufferSetRefForSvct + + Set the ASIC reference and reconstructed frame buffers based + on the user preference and picture buffer. +------------------------------------------------------------------------------*/ +void H264PictureBufferSetRefForSvct(picBuffer *picBuffer, asicData_s *asic, u32 frameNumBits) +{ + i32 i, refIdx = -1; + refPic *refPicList = picBuffer->refPicList; + i32 picNum; + u32 numViews = 1; + + /* Amount of buffered frames limits grf/arf availability. */ + if (picBuffer->size < 2) { picBuffer->cur_pic->grf = false; } + picBuffer->cur_pic->arf = false; + picNum = picBuffer->cur_pic->frameNum; + if (picBuffer->cur_pic->orderCmd!=0) + { + if (picNum >= picBuffer->cur_pic->orderCmd) + picNum = picNum - picBuffer->cur_pic->orderCmd; + else + picNum = picNum + (1U << frameNumBits) - picBuffer->cur_pic->orderCmd; + } + else + { + picNum = H264FindMaxFrameNum(picBuffer, frameNumBits); + } + + /* ASIC can use one or two reference frame, use the first ones marked + * for reference but don't use the same frame for both. */ + for (i = 0; i < BUFFER_SIZE; i++) { + if ((i < picBuffer->size) /* && refPicList[i].search*/ && (refPicList[i].ipf|refPicList[i].grf)) + { + if (refPicList[i].frameNum==picNum) + { + refIdx = i; + refPicList[refIdx].search = 1; + break; + } + } + } + + /* If no reference specified, use last ipf if available, otherwise ltr */ + ASSERT(refIdx!=-1); + + asic->regs.mvRefIdx[0] = asic->regs.markCurrentLongTerm = 0; + + /* Set the reference buffer for ASIC, no reference for intra frames */ + if (numViews == 1 && picBuffer->cur_pic->p_frame) { + /* Mark the ref pic that is used */ + ASSERT(picBuffer->refPicList[refIdx].search == 1); + + /* Check that enough frame buffers is available. */ + ASSERT(refPicList[refIdx].picture.lum); + asic->regs.internalImageLumBaseR[0] = refPicList[refIdx].picture.lum; + asic->regs.internalImageChrBaseR[0] = refPicList[refIdx].picture.cb; + asic->regs.ref2Enable = 0; + /* long-term/second reference will not be used */ + asic->regs.mvRefIdx[0] = 0; + asic->regs.ref2Enable = 0; + asic->regs.markCurrentLongTerm = 0; /* current marked as long term */ + } + + if (!picBuffer->cur_pic->ipf && !picBuffer->cur_pic->grf) + { + asic->regs.recWriteDisable = 1; + } + else + { + asic->regs.recWriteDisable = 0; + } + + /* set orderCmd */ + asic->regs.reorderFlag = (picBuffer->cur_pic->orderCmd!=0); + if (picBuffer->cur_pic->orderCmd) + asic->regs.reorderDiff = picBuffer->cur_pic->orderCmd - 1; + else + asic->regs.reorderDiff = 0; + + if (numViews == 1) + { + asic->regs.internalImageLumBaseW = picBuffer->cur_pic->picture.lum; + asic->regs.internalImageChrBaseW = picBuffer->cur_pic->picture.cb; + } + + /* For P-frames the chroma buffers must be different. */ + if (picBuffer->cur_pic->p_frame) { + ASSERT(asic->regs.internalImageChrBaseR[0] != asic->regs.internalImageChrBaseW); + } + + /* If current picture shall refresh grf/arf remove marks from ref list */ + for (i = 0; i < picBuffer->size; i++) { + if (picBuffer->cur_pic->grf) + picBuffer->refPicList[i].grf = false; + } + + /* Set compression table */ + if (asic->regs.refLumCompress) + { + asic->regs.internalImageLumTableBaseW = asic->regs.internalImageLumBaseW + asic->internalImageLumSize; + asic->regs.internalImageLumTableBaseR[0] = asic->regs.internalImageLumBaseR[0] + asic->internalImageLumSize; + if (asic->regs.internalImageLumBaseR[1]) + asic->regs.internalImageLumTableBaseR[1] = asic->regs.internalImageLumBaseR[1] + asic->internalImageLumSize; + else + asic->regs.internalImageLumTableBaseR[1] = 0; + } + if (asic->regs.refChrCompress) + { + asic->regs.internalImageChrTableBaseW = asic->regs.internalImageChrBaseW + asic->internalImageChrSize; + asic->regs.internalImageChrTableBaseR[0] = asic->regs.internalImageChrBaseR[0] + asic->internalImageChrSize; + if (asic->regs.internalImageChrBaseR[1]) + asic->regs.internalImageChrTableBaseR[1] = asic->regs.internalImageChrBaseR[1] + asic->internalImageChrSize; + else + asic->regs.internalImageChrTableBaseR[1] = 0; + } + +#ifdef TRACE_PIC_BUFFER + PrintPicBuffer(picBuffer); +#endif +} + +#ifdef TRACE_PIC_BUFFER +/*------------------------------------------------------------------------------ + PrintPicBuffer +------------------------------------------------------------------------------*/ +void PrintPicBuffer(picBuffer *picBuffer) +{ + i32 i; + refPic *refPic; + + refPic = picBuffer->cur_pic; + printf("Current picture\n"); + printf("Poc i_frame p_frame show ipf grf arf search:\n"); + printf("%-3i %-7i %-7i %-4i %-3i %-3i %-3i %-6i %p %p %p %p\n", + refPic->poc, + refPic->i_frame, + refPic->p_frame, + refPic->show, + refPic->ipf, + refPic->grf, + refPic->arf, + refPic->search, + refPic, + refPic->refPic, + refPic->picture.lum, refPic->picture.cb); + + refPic = picBuffer->refPic; + printf("Ref refPic[picBuffer->size + 1] \n"); + printf("Poc i_frame p_frame show ipf grf arf search:\n"); + for (i = 0; i < picBuffer->size + 1; i++) { + printf("%-3i %-7i %-7i %-4i %-3i %-3i %-3i %-6i %p %p %p %p\n", + refPic[i].poc, + refPic[i].i_frame, + refPic[i].p_frame, + refPic[i].show, + refPic[i].ipf, + refPic[i].grf, + refPic[i].arf, + refPic[i].search, + &refPic[i], + refPic[i].refPic, + refPic[i].picture.lum, refPic[i].picture.cb); + } + + refPic = picBuffer->refPicList; + printf("Ref refPicList[picBuffer->size] \n"); + printf("Poc i_frame p_frame show ipf grf arf search:\n"); + for (i = 0; i < picBuffer->size; i++) { + printf("%-3i %-7i %-7i %-4i %-3i %-3i %-3i %-6i %p %p %p %p\n", + refPic[i].poc, + refPic[i].i_frame, + refPic[i].p_frame, + refPic[i].show, + refPic[i].ipf, + refPic[i].grf, + refPic[i].arf, + refPic[i].search, + &refPic[i], + refPic[i].refPic, + refPic[i].picture.lum, refPic[i].picture.cb); + } +} +#endif diff --git a/lib/vc8000nanoe/source/h264/H264PictureBuffer.h b/lib/vc8000nanoe/source/h264/H264PictureBuffer.h new file mode 100644 index 000000000..ef8bff220 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264PictureBuffer.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : + * + ******************************************************************************** + */ + +#ifndef H264PICTURE_BUFFER_H +#define H264PICTURE_BUFFER_H + +/*------------------------------------------------------------------------------ + Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "encasiccontroller.h" + +/*------------------------------------------------------------------------------ + External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + Module defines +------------------------------------------------------------------------------*/ +#define BUFFER_SIZE 4 /* to support svct */ + +typedef struct { + i32 lumWidth; /* Width of *lum */ + i32 lumHeight; /* Height of *lum */ + i32 chWidth; /* Width of *cb and *cr */ + i32 chHeight; /* Height of *cb and *cr */ + ptr_t lum; + ptr_t cb; +} picture; + +typedef struct refPic { + picture picture; /* Image data */ + i32 poc; /* Picture order count */ + i32 frameNum; + + bool i_frame; /* I frame (key frame), only intra mb */ + bool p_frame; /* P frame, intra and inter mb */ + bool show; /* Frame is for display (showFrame flag) */ + bool ipf; /* Frame is immediately previous frame */ + bool arf; /* Frame is altref frame */ + bool grf; /* Frame is golden frame */ + bool search; /* Frame is used for motion estimation */ + struct refPic *refPic; /* Back reference pointer to itself */ + i32 orderCmd; +} refPic; + +typedef struct { + i32 size; /* Amount of allocated reference pictures */ + picture input; /* Input picture */ + refPic refPic[BUFFER_SIZE + 1]; /* Reference picture store */ + refPic refPicList[BUFFER_SIZE]; /* Reference picture list */ + refPic *cur_pic; /* Pointer to picture under reconstruction */ + refPic *last_pic; /* Last picture */ +} picBuffer; + +/*------------------------------------------------------------------------------ + Function prototypes +------------------------------------------------------------------------------*/ +i32 H264PictureBufferAlloc(picBuffer *picBuffer, i32 width, i32 height); +void H264PictureBufferFree(picBuffer *picBuffer); +void H264InitializePictureBuffer(picBuffer *picBuffer); +void H264UpdatePictureBuffer(picBuffer *picBuffer); +void H264PictureBufferSetRef(picBuffer *picBuffer, asicData_s *asic, u32 numViews); +i32 H264PictureBufferSetupH264(picBuffer *picBuffer, asicData_s *asic, u32 numRefBuffsLum, u32 numRefBuffsChr); +void H264UpdatePictureBufferForSvct(picBuffer *picBuffer, u32 frameNumBits, i32 gopIndex); +void H264PictureBufferSetRefForSvct(picBuffer *picBuffer, asicData_s *asic, u32 frameNumBits); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264PictureParameterSet.c b/lib/vc8000nanoe/source/h264/H264PictureParameterSet.c new file mode 100644 index 000000000..1b36e13e7 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264PictureParameterSet.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Picture Parameter Set handling + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "H264PictureParameterSet.h" +#include "H264NalUnit.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + H264PicParameterInit + +------------------------------------------------------------------------------*/ +void H264PicParameterSetInit(pps_s * pps) +{ + pps->byteStream = ENCHW_YES; + pps->picParameterSetId = 0; + pps->seqParameterSetId = 0; + pps->entropyCodingMode = ENCHW_NO; + pps->picOrderPresent = ENCHW_NO; + pps->numSliceGroupsMinus1 = 0; + pps->numRefIdxL0ActiveMinus1 = 0; + pps->numRefIdxL1ActiveMinus1 = 0; + pps->weightedPred = ENCHW_NO; + pps->weightedBipredIdc = 0; + pps->picInitQpMinus26 = 0; + pps->picInitQsMinus26 = 0; + pps->chromaQpIndexOffset = 2; + pps->deblockingFilterControlPresent = ENCHW_YES; + pps->constIntraPred = ENCHW_NO; + pps->redundantPicCntPresent = ENCHW_NO; + pps->transform8x8Mode = ENCHW_NO; + + return; +} + +/*------------------------------------------------------------------------------ + + H264PicParameterSet + +------------------------------------------------------------------------------*/ +void H264PicParameterSet(stream_s * stream, pps_s * pps) +{ + /* Nal unit sytax */ + H264NalUnitHdr(stream, 1, PPSET, pps->byteStream); + + H264ExpGolombUnsigned(stream, pps->picParameterSetId); + COMMENT("pic_parameter_set_id"); + + H264ExpGolombUnsigned(stream, pps->seqParameterSetId); + COMMENT("seq_parameter_set_id"); + + H264NalBits(stream, (i32) pps->entropyCodingMode, 1); + COMMENT("entropy_coding_mode_flag"); + + H264NalBits(stream, (i32) pps->picOrderPresent, 1); + COMMENT("pic_order_present_flag"); + + H264ExpGolombUnsigned(stream, pps->numSliceGroupsMinus1); + COMMENT("num_slice_groups_minus1"); + + /* if( num_slice_groups_minus1 > 0 ) etc... not implementet yet */ + + H264ExpGolombUnsigned(stream, pps->numRefIdxL0ActiveMinus1); + COMMENT("num_ref_idx_l0_active_minus1"); + + H264ExpGolombUnsigned(stream, pps->numRefIdxL1ActiveMinus1); + COMMENT("num_ref_idx_l1_active_minus1"); + + H264NalBits(stream, (i32) pps->weightedPred, 1); + COMMENT("weighted_pred_flag"); + + H264NalBits(stream, pps->weightedBipredIdc, 2); + COMMENT("weighted_bipred_idc"); + + H264ExpGolombSigned(stream, pps->picInitQpMinus26); + COMMENT("pic_init_qp_minus26"); + + H264ExpGolombSigned(stream, pps->picInitQsMinus26); + COMMENT("pic_init_qs_minus26"); + + H264ExpGolombSigned(stream, pps->chromaQpIndexOffset); + COMMENT("chroma_qp_index_offset"); + + H264NalBits(stream, (i32) pps->deblockingFilterControlPresent, 1); + COMMENT("deblocking_filter_control_present_flag"); + + H264NalBits(stream, (i32) pps->constIntraPred, 1); + COMMENT("constrained_intra_pred_flag"); + + H264NalBits(stream, (i32) pps->redundantPicCntPresent, 1); + COMMENT("redundant_pic_cnt_present_flag"); + + if (pps->transform8x8Mode == ENCHW_YES) + { + H264NalBits(stream, pps->transform8x8Mode, 1); + COMMENT("transform_8x8_mode_flag"); + + H264NalBits(stream, 0, 1); + COMMENT("pic_scaling_matrix_present_flag"); + + H264ExpGolombSigned(stream, pps->chromaQpIndexOffset); + COMMENT("second_chroma_qp_index_offset"); + } + + + H264NalUnitTrailinBits(stream, pps->byteStream); + + return; +} diff --git a/lib/vc8000nanoe/source/h264/H264PictureParameterSet.h b/lib/vc8000nanoe/source/h264/H264PictureParameterSet.h new file mode 100644 index 000000000..fccd77ba0 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264PictureParameterSet.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : + * + ******************************************************************************** + */ + +#ifndef __H264_PICTURE_PARAMETER_SET_H__ +#define __H264_PICTURE_PARAMETER_SET_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "enccommon.h" +#include "H264PutBits.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ +typedef struct +{ + true_e byteStream; + i32 picParameterSetId; + i32 seqParameterSetId; + true_e entropyCodingMode; + true_e picOrderPresent; + i32 numSliceGroupsMinus1; + i32 numRefIdxL0ActiveMinus1; + i32 numRefIdxL1ActiveMinus1; + true_e weightedPred; + i32 weightedBipredIdc; + i32 picInitQpMinus26; + i32 picInitQsMinus26; + i32 chromaQpIndexOffset; + true_e deblockingFilterControlPresent; + true_e constIntraPred; + true_e redundantPicCntPresent; + true_e transform8x8Mode; + u32 enableCabac; /* 0=cavlc, 1=cabac, 2=cavlc(intra)+cabac(inter) */ +} pps_s; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +void H264PicParameterSetInit(pps_s * pps); +void H264PicParameterSet(stream_s * stream, pps_s * pps); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264PutBits.c b/lib/vc8000nanoe/source/h264/H264PutBits.c new file mode 100644 index 000000000..fc832da8e --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264PutBits.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Bit stream handling + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "H264PutBits.h" +#include "enccommon.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ +static bool_e H264BufferStatus(stream_s * stream); + +/*------------------------------------------------------------------------------ + + H264PutBits + + Write bits to stream. For example (value=2, number=4) write 0010 to the + stream. Number of bits must be < 25, otherwise overflow occur. Four + bytes is maximum number of bytes to put stream and there should be at + least 5 byte free space available because of byte buffer. + + Used only for NAL unit headers! + + Input stream Pointer to the stream stucture + value Bit pattern + number Number of bits + +------------------------------------------------------------------------------*/ +void H264PutBits(stream_s * buffer, i32 value, i32 number) +{ + i32 bits; + u32 byteBuffer = buffer->byteBuffer; + u8 *stream = buffer->stream; + + if(H264BufferStatus(buffer) != ENCHW_OK) + { + return; + } + + TRACE_BIT_STREAM(value, number); + + /* Debug: value is too big */ + ASSERT(value < (1 << number)); + ASSERT(number < 25); + + bits = number + buffer->bufferedBits; + value <<= (32 - bits); + byteBuffer = byteBuffer | value; + + while(bits > 7) + { + *stream = (u8) (byteBuffer >> 24); + + bits -= 8; + byteBuffer <<= 8; + stream++; + buffer->byteCnt++; + } + + buffer->byteBuffer = byteBuffer; + buffer->bufferedBits = (u8) bits; + buffer->stream = stream; + + return; +} + +/*------------------------------------------------------------------------------ + + H264PutNalBits + + Write bits to stream. For example (value=2, number=4) write 0010 to the + stream. Number of bits must be < 25, otherwise overflow occur. Four + bytes is maximum number of bytes to put stream and there should be at + least 5 byte free space available because of byte buffer. + + Used only for NAL unit RBSP data! + + Input stream Pointer to the stream stucture + value Bit pattern + number Number of bits + +------------------------------------------------------------------------------*/ +void H264PutNalBits(stream_s * buffer, i32 value, i32 number) +{ + i32 bits; + u8 *stream = buffer->stream; + u32 byteBuffer = buffer->byteBuffer; + + ASSERT(value < (1<bufferedBits; + byteBuffer = byteBuffer | ((u32) value << (32 - bits)); + + while(bits > 7) + { + i32 zeroBytes = buffer->zeroBytes; + i32 byteCnt = buffer->byteCnt; + + if(H264BufferStatus(buffer) != ENCHW_OK) + return; + + *stream = (u8) (byteBuffer >> 24); + byteCnt++; + + if((zeroBytes == 2) && (*stream < 4)) + { + *stream++ = 3; + *stream = (u8) (byteBuffer >> 24); + byteCnt++; + zeroBytes = 0; + buffer->emulCnt++; + } + + if(*stream == 0) + zeroBytes++; + else + zeroBytes = 0; + + bits -= 8; + byteBuffer <<= 8; + stream++; + buffer->zeroBytes = zeroBytes; + buffer->byteCnt = byteCnt; + buffer->stream = stream; + } + + buffer->bufferedBits = (u8) bits; + buffer->byteBuffer = byteBuffer; +} + +/*------------------------------------------------------------------------------ + + EncSetBuffer + + Set stream buffer. + + Input buffer Pointer to the stream_s structure. + stream Pointer to stream buffer. + size Size of stream buffer. + +------------------------------------------------------------------------------*/ +bool_e H264SetBuffer(stream_s * buffer, u8 * stream, u32 size) +{ + buffer->stream = stream; + buffer->size = size; + buffer->byteCnt = 0; + buffer->overflow = ENCHW_NO; + buffer->zeroBytes = 0; + buffer->byteBuffer = 0; + buffer->bufferedBits = 0; + + if(H264BufferStatus(buffer) != ENCHW_OK) + { + return ENCHW_NOK; + } + buffer->stream[0] = 0; + buffer->stream[1] = 0; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + BufferStatus + + Check fullness of stream buffer. + + Input stream Pointer to the stream stucture. + + Return ENCHW_OK Buffer status is ENCHW_OK. + ENCHW_NOK Buffer overflow. + +------------------------------------------------------------------------------*/ +bool_e H264BufferStatus(stream_s * stream) +{ + if(stream->byteCnt + 5 > stream->size) + { + stream->overflow = ENCHW_YES; + return ENCHW_NOK; + } + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + H264ExpGolombUnsigned + +------------------------------------------------------------------------------*/ +void H264ExpGolombUnsigned(stream_s * stream, u32 val) +{ + u32 numBits = 0; + + val++; + while(val >> ++numBits); + + if(numBits > 12) + { + u32 tmp; + tmp = numBits-1; + + if(tmp > 24) + { + tmp -= 24; + H264NalBits(stream, 0, 24); + } + + H264NalBits(stream, 0, tmp); + COMMENT("++"); + + if(numBits > 24) + { + numBits -= 24; + H264NalBits(stream, val >> numBits, 24); + val = val >> numBits; + } + + H264NalBits(stream, val, numBits); + } + else + { + H264NalBits(stream, val , 2*numBits - 1); + } + +} + +/*------------------------------------------------------------------------------ + + H264ExpGolombSigned + +------------------------------------------------------------------------------*/ +void H264ExpGolombSigned(stream_s * stream, i32 val) +{ + u32 tmp; + + if (val > 0) + tmp = (u32) (2 * val - 1); + else + tmp = (u32) (-2 * val); + + H264ExpGolombUnsigned(stream, tmp); +} + +/*------------------------------------------------------------------------------ + + H264RbspTrailingBits + + Function add rbsp_stop_one_bit and p_alignment_zero_bit until next byte + aligned if needed. Note that stream->stream[1] is bits in byte bufer. + + Input stream Pointer to the stream structure. + +------------------------------------------------------------------------------*/ +void H264RbspTrailingBits(stream_s * stream) +{ + H264PutNalBits(stream, 1, 1); + COMMENT("rbsp_stop_one_bit"); + if(stream->bufferedBits > 0) + { + H264PutNalBits(stream, 0, 8 - stream->bufferedBits); + COMMENT("bsp_alignment_zero_bit(s)"); + } + + return; +} diff --git a/lib/vc8000nanoe/source/h264/H264PutBits.h b/lib/vc8000nanoe/source/h264/H264PutBits.h new file mode 100644 index 000000000..ae94d5e16 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264PutBits.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Bit stream handling + * + ******************************************************************************** + */ + +#ifndef __H264_PUT_BITS_H__ +#define __H264_PUT_BITS_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "enccommon.h" +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#if 1 +#define H264NalBits(stream, val, num) H264PutNalBits(stream, val, num) +#else +#define H264NalBits(stream, val, num) \ + if (stream->bufferedBits + num < 8) { \ + i32 bits = stream->bufferedBits + (num); \ + stream->bufferedBits += (num); \ + stream->byteBuffer = stream->byteBuffer | ((u32)(val) << (32-bits)); \ + } else { \ + H264PutNalBits(stream, val, num); \ + } +#endif + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +bool_e H264SetBuffer(stream_s * buffer, u8 * stream, u32 size); +void H264PutBits(stream_s *, i32, i32); +void H264PutNalBits(stream_s *, i32, i32); +void H264ExpGolombUnsigned(stream_s * stream, u32 val); +void H264ExpGolombSigned(stream_s * stream, i32 val); +void H264RbspTrailingBits(stream_s * stream); +void H264Comment(char *comment); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264RateControl.c b/lib/vc8000nanoe/source/h264/H264RateControl.c new file mode 100644 index 000000000..56440bb67 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264RateControl.c @@ -0,0 +1,1369 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Rate control + * + ******************************************************************************** + */ +/* + * Using only one leaky bucket (Multible buckets is supported by std). + * Constant bit rate (CBR) operation, ie. leaky bucket drain rate equals + * average rate of the stream, is enabled if RC_CBR_HRD = 1. Frame skiping and + * filler data are minimum requirements for the CBR conformance. + * + * Constant HRD parameters: + * low_delay_hrd_flag = 0, assumes constant delay mode. + * cpb_cnt_minus1 = 0, only one leaky bucket used. + * (cbr_flag[0] = RC_CBR_HRD, CBR mode.) + */ +#include "H264RateControl.h" +#include "H264Slice.h" + +/*------------------------------------------------------------------------------ + Module defines +------------------------------------------------------------------------------*/ + +/* Define this if strict bitrate control is needed, each window has a strict + * bit budget. Otherwise a moving window is used for smoother quality.*/ +//#define RC_WINDOW_STRICT + +#ifdef TRACE_RC +#include +FILE *fpRcTrc = NULL; +/* Select debug output: fpRcTrc or stdout */ +#define DBGOUTPUT fpRcTrc +/* Select debug level: 0 = minimum, 2 = maximum */ +#define DBG_LEVEL 2 +#define DBG(l, str) if (l <= DBG_LEVEL) fprintf str +#else +#define DBG(l, str) +#endif + +#define INITIAL_BUFFER_FULLNESS 60 /* Decoder Buffer in procents */ +#define MIN_PIC_SIZE 50 /* Procents from picPerPic */ + +#define DIV(a, b) ((b) ? ((a) + (SIGN(a) * (b)) / 2) / (b) : (a)) +#define DSCY 32 /* n * 32 */ +#define DSCBITPERMB 128 /* bitPerMb scaler */ +#define I32_MAX 2147483647 /* 2 ^ 31 - 1 */ +#define I64_MAX 9223372036854775807LL /* 2 ^ 63 - 1 */ +//#define QP_DELTA 2.0 /* Limit QP change between consecutive frames.*/ +#define QP_DELTA 0x200 /* Limit QP change between consecutive frames.*/ + +//#define QP_DELTA_LIMIT 6.0 /* Threshold when above limit is abandoned. */ +#define QP_DELTA_LIMIT 0x600 /* Threshold when above limit is abandoned. */ + + + +#define QP_FIXPOINT_0_POINT_1 0x1a + + +#define INTRA_QP_DELTA (0) +#define WORD_CNT_MAX 65535 + +/*------------------------------------------------------------------------------ + Local structures +------------------------------------------------------------------------------*/ +#if 0 +/* q_step values scaled up by 4 and evenly rounded */ +static const i32 q_step[53] = { 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, + 13, 14, 16, 18, 20, 23, 25, 28, 32, 36, 40, 45, 51, 57, 64, 72, 80, 90, + 101, 114, 128, 144, 160, 180, 203, 228, 256, 288, 320, 360, 405, 456, + 513, 577, 640, 720, 810, 896 + }; +#else +#if 0 +static const i32 q_step[53] = { 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, + 13, 14, 16, 18, 20, 22, 25, 28, 31, 35, 39, 44, 50, 56, 63, 71, 79, 88, + 100, 112, 126, 141, 157, 177, 200, 224, 252, 283, 314, 354, 401, 448, + 503, 566, 629, 707, 802, 896 + }; +#else +#if 0 +static const float q_step[511] ={ + 2.475138122,2.503897841,2.532991733,2.562423679,2.592197608,2.622317493,2.652787355,2.683611259,2.71479332 ,2.746337699, +2.778248606,2.8105303 ,2.843187089,2.876223331,2.909643437,2.943451865,2.977653128,3.012251791,3.047252471,3.082659839, +3.118478621,3.154713597,3.191369603,3.228451532,3.265964332,3.303913009,3.342302629,3.381138315,3.42042525 ,3.460168677, +3.5003739 ,3.541046286,3.582191262,3.623814319,3.665921013,3.708516964,3.751607855,3.795199439,3.839297532,3.883908021, +3.929036858,3.974690067,4.020873741,4.067594043,4.11485721 ,4.162669547,4.211037438,4.259967336,4.309465772,4.359539352, +4.410194759,4.461438754,4.513278175,4.565719942,4.618771052,4.672438587,4.726729708,4.781651661,4.837211777,4.893417471, +4.950276243,5.007795682,5.065983465,5.124847358,5.184395216,5.244634986,5.30557471 ,5.367222518,5.42958664 ,5.492675398, +5.556497212,5.621060599,5.686374177,5.752446663,5.819286873,5.88690373 ,5.955306256,6.024503581,6.094504941,6.165319678, +6.236957241,6.309427194,6.382739206,6.456903064,6.531928663,6.607826018,6.684605258,6.76227663 ,6.8408505 ,6.920337354, +7.0007478 ,7.082092572,7.164382523,7.247628638,7.331842027,7.417033928,7.50321571 ,7.590398877,7.678595064,7.767816041, +7.858073716,7.949380134,8.041747482,8.135188087,8.229714419,8.325339095,8.422074875,8.519934672,8.618931544,8.719078704, +8.820389519,8.922877508,9.026556351,9.131439883,9.237542104,9.344877173,9.453459416,9.563303323,9.674423555,9.786834942, +9.900552486,10.01559136,10.13196693,10.24969472,10.36879043,10.48926997,10.61114942,10.73444504,10.85917328,10.9853508 , +11.11299442,11.2421212 ,11.37274835,11.50489333,11.63857375,11.77380746,11.91061251,12.04900716,12.18900988,12.33063936, +12.47391448,12.61885439,12.76547841,12.91380613,13.06385733,13.21565204,13.36921052,13.52455326,13.681701 ,13.84067471, +14.0014956 ,14.16418514,14.32876505,14.49525728,14.66368405,14.83406786,15.00643142,15.18079775,15.35719013,15.53563208, +15.71614743,15.89876027,16.08349496,16.27037617,16.45942884,16.65067819,16.84414975,17.03986934,17.23786309,17.43815741, +17.64077904,17.84575502,18.0531127 ,18.26287977,18.47508421,18.68975435,18.90691883,19.12660665,19.34884711,19.57366988, +19.80110497,20.03118273,20.26393386,20.49938943,20.73758086,20.97853995,21.22229884,21.46889007,21.71834656,21.97070159, +22.22598885,22.4842424 ,22.74549671,23.00978665,23.27714749,23.54761492,23.82122502,24.09801433,24.37801976,24.66127871, +24.94782897,25.23770878,25.53095683,25.82761225,26.12771465,26.43130407,26.73842103,27.04910652,27.363402 ,27.68134941, +28.0029912 ,28.32837029,28.65753009,28.99051455,29.32736811,29.66813571,30.01286284,30.36159551,30.71438026,31.07126416, +31.43229486,31.79752054,32.16698993,32.54075235,32.91885768,33.30135638,33.6882995 ,34.07973869,34.47572618,34.87631482, +35.28155808,35.69151003,36.1062254 ,36.52575953,36.95016842,37.37950869,37.81383766,38.25321329,38.69769422,39.14733977, +39.60220994,40.06236546,40.52786772,40.99877886,41.47516173,41.95707989,42.44459768,42.93778015,43.43669312,43.94140318, +44.45197769,44.96848479,45.49099342,46.0195733 ,46.55429498,47.09522984,47.64245005,48.19602865,48.75603953,49.32255742, +49.89565793,50.47541755,51.06191365,51.65522451,52.25542931,52.86260815,53.47684207,54.09821304,54.726804 ,55.36269883, +56.0059824 ,56.65674057,57.31506019,57.98102911,58.65473621,59.33627142,60.02572568,60.72319102,61.42876051,62.14252833, +62.86458973,63.59504107,64.33397986,65.0815047 ,65.83771535,66.60271276,67.376599 ,68.15947737,68.95145235,69.75262963, +70.56311615,71.38302007,72.21245081,73.05151907,73.90033683,74.75901738,75.62767532,76.50642658,77.39538844,78.29467953, +79.20441989,80.12473092,81.05573545,81.99755772,82.95032345,83.91415978,84.88919535,85.87556029,86.87338624,87.88280636, +88.90395538,89.93696959,90.98198684,92.0391466 ,93.10858997,94.19045967,95.2849001 ,96.3920573 ,97.51207906,98.64511484, +99.79131586,100.9508351,102.1238273,103.310449 ,104.5108586,105.7252163,106.9536841,108.1964261,109.453608 ,110.7253977, +112.0119648,113.3134811,114.6301204,115.9620582,117.3094724,118.6725428,120.0514514,121.446382 ,122.857521 ,124.2850567, +125.7291795,127.1900821,128.6679597,130.1630094,131.6754307,133.2054255,134.753198 ,136.3189547,137.9029047,139.5052593, +141.1262323,142.7660401,144.4249016,146.1030381,147.8006737,149.5180348,151.2553506,153.0128532,154.7907769,156.5893591, +158.4088398,160.2494618,162.1114709,163.9951154,165.9006469,167.8283196,169.7783907,171.7511206,173.7467725,175.7656127, +177.8079108,179.8739392,181.9639737,184.0782932,186.2171799,188.3809193,190.5698002,192.7841146,195.0241581,197.2902297, +199.5826317,201.9016702,204.2476546,206.620898 ,209.0217172,211.4504326,213.9073683,216.3928522,218.907216 ,221.4507953, +224.0239296,226.6269623,229.2602408,231.9241164,234.6189449,237.3450857,240.1029027,242.8927641,245.7150421,248.5701133, +251.4583589,254.3801643,257.3359194,260.3260188,263.3508614,266.410851 ,269.506396 ,272.6379095,275.8058094,279.0105185, +282.2524646,285.5320803,288.8498032,292.2060763,295.6013473,299.0360695,302.5107013,306.0257063,309.5815538,313.1787181, +316.8176796,320.4989237,324.2229418,327.9902309,331.8012938,335.6566391,339.5567814,343.5022412,347.4935449,351.5312254, +355.6158215,359.7478783,363.9279473,368.1565864,372.4343599,376.7618387,381.1396004,385.5682292,390.0483162,394.5804594, +399.1652635,403.8033404,408.4953092,413.2417961,418.0434344,422.9008652,427.8147365,432.7857043,437.814432 ,442.9015906, +448.0478592,453.2539246,458.5204815,463.8482329,469.2378897,474.6901714,480.2058055,485.7855282,491.4300841,497.1402266, +502.9167178,508.7603286,514.6718389,520.6520376,526.7017228,532.8217021,539.012792 ,545.275819 ,551.6116188,558.0210371, +564.5049292,571.0641605,577.6996065,584.4121525,591.2026947,598.0721391,605.0214026,612.0514127,619.1631075,626.3574363, +633.6353591,640.9978473,648.4458836,655.9804618,663.6025876,671.3132783,679.1135628,687.0044823,694.9870899,703.0624509, +711.2316431,719.4957567,727.8558947,736.3131728,744.8687198,753.5236774,762.2792008,771.1364584,780.0966325,789.1609187, +798.3305269,807.6066808,816.9906184,826.4835921,836.0868689,845.8017304,855.6294731,865.5714087,875.628864 ,885.8031813, +896.0957185 + +}; +#else +static const i32 q_step[511] ={ + +0x279 ,0x280 ,0x288 ,0x28f ,0x297 ,0x29f ,0x2a7 ,0x2af ,0x2b6 ,0x2bf , +0x2c7 ,0x2cf ,0x2d7 ,0x2e0 ,0x2e8 ,0x2f1 ,0x2fa ,0x303 ,0x30c ,0x315 , +0x31e ,0x327 ,0x330 ,0x33a ,0x344 ,0x34d ,0x357 ,0x361 ,0x36b ,0x375 , +0x380 ,0x38a ,0x395 ,0x39f ,0x3aa ,0x3b5 ,0x3c0 ,0x3cb ,0x3d6 ,0x3e2 , +0x3ed ,0x3f9 ,0x405 ,0x411 ,0x41d ,0x429 ,0x436 ,0x442 ,0x44f ,0x45c , +0x469 ,0x476 ,0x483 ,0x490 ,0x49e ,0x4ac ,0x4ba ,0x4c8 ,0x4d6 ,0x4e4 , +0x4f3 ,0x501 ,0x510 ,0x51f ,0x52f ,0x53e ,0x54e ,0x55e ,0x56d ,0x57e , +0x58e ,0x59e ,0x5af ,0x5c0 ,0x5d1 ,0x5e3 ,0x5f4 ,0x606 ,0x618 ,0x62a , +0x63c ,0x64f ,0x661 ,0x674 ,0x688 ,0x69b ,0x6af ,0x6c3 ,0x6d7 ,0x6eb , +0x700 ,0x715 ,0x72a ,0x73f ,0x754 ,0x76a ,0x780 ,0x797 ,0x7ad ,0x7c4 , +0x7db ,0x7f3 ,0x80a ,0x822 ,0x83a ,0x853 ,0x86c ,0x885 ,0x89e ,0x8b8 , +0x8d2 ,0x8ec ,0x906 ,0x921 ,0x93c ,0x958 ,0x974 ,0x990 ,0x9ac ,0x9c9 , +0x9e6 ,0xa03 ,0xa21 ,0xa3f ,0xa5e ,0xa7d ,0xa9c ,0xabc ,0xadb ,0xafc , +0xb1c ,0xb3d ,0xb5f ,0xb81 ,0xba3 ,0xbc6 ,0xbe9 ,0xc0c ,0xc30 ,0xc54 , +0xc79 ,0xc9e ,0xcc3 ,0xce9 ,0xd10 ,0xd37 ,0xd5e ,0xd86 ,0xdae ,0xdd7 , +0xe00 ,0xe2a ,0xe54 ,0xe7e ,0xea9 ,0xed5 ,0xf01 ,0xf2e ,0xf5b ,0xf89 , +0xfb7 ,0xfe6 ,0x1015 ,0x1045 ,0x1075 ,0x10a6 ,0x10d8 ,0x110a ,0x113c ,0x1170 , +0x11a4 ,0x11d8 ,0x120d ,0x1243 ,0x1279 ,0x12b0 ,0x12e8 ,0x1320 ,0x1359 ,0x1392 , +0x13cd ,0x1407 ,0x1443 ,0x147f ,0x14bc ,0x14fa ,0x1538 ,0x1578 ,0x15b7 ,0x15f8 , +0x1639 ,0x167b ,0x16be ,0x1702 ,0x1746 ,0x178c ,0x17d2 ,0x1819 ,0x1860 ,0x18a9 , +0x18f2 ,0x193c ,0x1987 ,0x19d3 ,0x1a20 ,0x1a6e ,0x1abd ,0x1b0c ,0x1b5d ,0x1bae , +0x1c00 ,0x1c54 ,0x1ca8 ,0x1cfd ,0x1d53 ,0x1dab ,0x1e03 ,0x1e5c ,0x1eb6 ,0x1f12 , +0x1f6e ,0x1fcc ,0x202a ,0x208a ,0x20eb ,0x214d ,0x21b0 ,0x2214 ,0x2279 ,0x22e0 , +0x2348 ,0x23b1 ,0x241b ,0x2486 ,0x24f3 ,0x2561 ,0x25d0 ,0x2640 ,0x26b2 ,0x2725 , +0x279a ,0x280f ,0x2887 ,0x28ff ,0x2979 ,0x29f5 ,0x2a71 ,0x2af0 ,0x2b6f ,0x2bf0 , +0x2c73 ,0x2cf7 ,0x2d7d ,0x2e05 ,0x2e8d ,0x2f18 ,0x2fa4 ,0x3032 ,0x30c1 ,0x3152 , +0x31e5 ,0x3279 ,0x330f ,0x33a7 ,0x3441 ,0x34dc ,0x357a ,0x3619 ,0x36ba ,0x375c , +0x3801 ,0x38a8 ,0x3950 ,0x39fb ,0x3aa7 ,0x3b56 ,0x3c06 ,0x3cb9 ,0x3d6d ,0x3e24 , +0x3edd ,0x3f98 ,0x4055 ,0x4114 ,0x41d6 ,0x429a ,0x4360 ,0x4428 ,0x44f3 ,0x45c0 , +0x4690 ,0x4762 ,0x4836 ,0x490d ,0x49e6 ,0x4ac2 ,0x4ba0 ,0x4c81 ,0x4d65 ,0x4e4b , +0x4f34 ,0x501f ,0x510e ,0x51ff ,0x52f3 ,0x53ea ,0x54e3 ,0x55e0 ,0x56df ,0x57e1 , +0x58e7 ,0x59ef ,0x5afb ,0x5c0a ,0x5d1b ,0x5e30 ,0x5f48 ,0x6064 ,0x6183 ,0x62a5 , +0x63ca ,0x64f3 ,0x661f ,0x674f ,0x6882 ,0x69b9 ,0x6af4 ,0x6c32 ,0x6d74 ,0x6eb9 , +0x7003 ,0x7150 ,0x72a1 ,0x73f6 ,0x754f ,0x76ac ,0x780d ,0x7972 ,0x7adb ,0x7c48 , +0x7dba ,0x7f30 ,0x80aa ,0x8229 ,0x83ac ,0x8534 ,0x86c0 ,0x8851 ,0x89e7 ,0x8b81 , +0x8d20 ,0x8ec4 ,0x906c ,0x921a ,0x93cc ,0x9584 ,0x9741 ,0x9903 ,0x9aca ,0x9c96 , +0x9e68 ,0xa03f ,0xa21c ,0xa3fe ,0xa5e6 ,0xa7d4 ,0xa9c7 ,0xabc0 ,0xadbf ,0xafc3 , +0xb1ce ,0xb3df ,0xb5f6 ,0xb814 ,0xba37 ,0xbc61 ,0xbe91 ,0xc0c8 ,0xc306 ,0xc54a , +0xc795 ,0xc9e6 ,0xcc3f ,0xce9e ,0xd105 ,0xd373 ,0xd5e8 ,0xd864 ,0xdae8 ,0xdd73 , +0xe006 ,0xe2a0 ,0xe542 ,0xe7ec ,0xea9e ,0xed58 ,0xf01a ,0xf2e4 ,0xf5b7 ,0xf891 , +0xfb75 ,0xfe61 ,0x10155,0x10453,0x10759,0x10a69,0x10d81,0x110a3,0x113ce,0x11702, +0x11a40,0x11d88,0x120d9,0x12434,0x12799,0x12b09,0x12e82,0x13206,0x13594,0x1392d, +0x13cd1,0x1407f,0x14439,0x147fd,0x14bcd,0x14fa8,0x1538e,0x15780,0x15b7e,0x15f87, +0x1639d,0x167bf,0x16bed,0x17028,0x1746f,0x178c3,0x17d23,0x18191,0x1860c,0x18a94, +0x18f2a,0x193cd,0x1987e,0x19d3d,0x1a20b,0x1a6e6,0x1abd0,0x1b0c9,0x1b5d0,0x1bae6, +0x1c00c,0x1c541,0x1ca85,0x1cfd9,0x1d53c,0x1dab0,0x1e034,0x1e5c9,0x1eb6e,0x1f123, +0x1f6ea,0x1fcc2,0x202ab,0x208a6,0x20eb3,0x214d2,0x21b03,0x22146,0x2279c,0x22e05, +0x23481,0x23b10,0x241b3,0x24869,0x24f33,0x25612,0x25d05,0x2640d,0x26b29,0x2725b, +0x279a2,0x280ff,0x28872,0x28ffb,0x2979a,0x29f50,0x2a71d,0x2af01,0x2b6fc,0x2bf0f, +0x2c73b,0x2cf7e,0x2d7db,0x2e050,0x2e8de,0x2f186,0x2fa47,0x30322,0x30c18,0x31529, +0x31e54,0x3279b,0x330fd,0x33a7b,0x34416,0x34dcd,0x357a1,0x36192,0x36ba0,0x375cd, +0x38018 +}; +#endif +#endif +#endif +/*------------------------------------------------------------------------------ + Local function prototypes +------------------------------------------------------------------------------*/ + +static i32 InitialQp(i32 bits, i32 pels); +static void SourceParameter(h264RateControl_s * rc, i32 nonZeroCnt); +static void PicSkip(h264RateControl_s * rc); +static void PicQuantLimit(h264RateControl_s * rc); +static i32 VirtualBuffer(h264VirtualBuffer_s *vb, i32 timeInc, true_e hrd); +static void PicQuant(h264RateControl_s * rc); +static i32 avg_rc_error(linReg_s *p); +static void update_rc_error(linReg_s *p, i32 bits, i32 windowLength); +static i32 gop_avg_qp(h264RateControl_s *rc); +static i32 new_pic_quant(linReg_s *p, i32 bits, true_e useQpDeltaLimit); +static i32 get_avg_bits(linReg_s *p, i32 n); +static void update_tables(linReg_s *p, i32 qp, i32 bits); +static void update_model(linReg_s *p); +static i64 lin_sy(i32 *qp, i32 *r, i32 n); +static i64 lin_sx(i32 *qp, i32 n); +static i64 lin_sxy(i32 *qp, i32 *r, i32 n); +static i64 lin_nsxx(i32 *qp, i32 n); + +/*------------------------------------------------------------------------------ + + H264InitRc() Initialize rate control. + +------------------------------------------------------------------------------*/ +bool_e H264InitRc(h264RateControl_s * rc, u32 newStream) +{ + h264VirtualBuffer_s *vb = &rc->virtualBuffer; + + if ((rc->qpMax > (51 << QP_FRACTIONAL_BITS))) + { + return ENCHW_NOK; + } + + /* QP -1: Initial QP estimation done by RC */ + if (rc->qpHdr == (-1 << QP_FRACTIONAL_BITS)) + { + i32 tmp = H264Calculate(vb->bitRate, rc->outRateDenom, rc->outRateNum); + rc->qpHdr = InitialQp(tmp, rc->mbPerPic*16*16); + PicQuantLimit(rc); + } + + if((rc->qpHdr > rc->qpMax) || (rc->qpHdr < rc->qpMin)) + { + return ENCHW_NOK; + } + + rc->mbQpAdjustment[0] = MIN(7, MAX(-8, rc->mbQpAdjustment[0])); + rc->mbQpAdjustment[1] = MIN(51, MAX(-51, rc->mbQpAdjustment[1])); + rc->mbQpAdjustment[2] = MIN(51, MAX(-51, rc->mbQpAdjustment[2])); + + /* HRD needs frame RC and macroblock RC*/ + if (rc->hrd == ENCHW_YES) { + rc->picRc = ENCHW_YES; + } + + //rc->mbRc = ENCHW_YES; + rc->coeffCntMax = rc->mbPerPic * 24 * 16; + rc->frameCoded = ENCHW_YES; + rc->sliceTypeCur = ISLICE; + rc->sliceTypePrev = PSLICE; + + rc->qpHdrPrev = rc->qpHdr; + rc->fixedQp = rc->qpHdr; + + vb->bitPerPic = H264Calculate(vb->bitRate, rc->outRateDenom, rc->outRateNum); + +#if defined(TRACE_RC) && (DBGOUTPUT == fpRcTrc) + if (!fpRcTrc) fpRcTrc = fopen("rc.trc", "wt"); +#endif + + DBG(0, (DBGOUTPUT, "\nInitRc: picRc\t\t%i hrd\t%i picSkip\t%i\n", + rc->picRc, rc->hrd, rc->picSkip)); + DBG(0, (DBGOUTPUT, " mbRc\t\t\t%i qpHdr\t%i Min,Max\t%i,%i\n", + rc->mbRc, rc->qpHdr, rc->qpMin, rc->qpMax)); + + DBG(0, (DBGOUTPUT, " CPBsize\t%i\n BitRate\t%i\n BitPerPic\t%i\n", + vb->bufferSize, vb->bitRate, vb->bitPerPic)); + + /* If changing QP between frames don't reset GOP RC. + * Changing bitrate resets RC the same way as new stream. */ + if(!newStream) return ENCHW_OK; + + /* new rate control algorithm */ + update_rc_error(&rc->rError, 0x7fffffff, 0); + update_rc_error(&rc->intraError, 0x7fffffff, 0); + + EWLmemset(&rc->linReg, 0, sizeof(linReg_s)); + rc->linReg.qs[0] = q_step[510]; + rc->linReg.qp_prev = rc->qpHdr; + EWLmemset(&rc->intra, 0, sizeof(linReg_s)); + rc->intra.qs[0] = q_step[510]; + rc->intra.qp_prev = rc->qpHdr; + + /* API parameter is named gopLen but the actual usage is rate controlling + * window in frames. RC tries to match the target bitrate inside the + * window. Each window can contain multiple GOPs and the RC adapts to the + * intra rate by calculating intraInterval. */ + rc->windowLen = rc->gopLen; + vb->windowRem = rc->gopLen; + rc->intraIntervalCtr = rc->intraInterval = rc->gopLen; + rc->targetPicSize = 0; + rc->frameBitCnt = 0; + rc->gopQpSum = 0; + rc->gopQpDiv = 0; + + rc->rcMSESum = 12* rc->mbPerPic; + + vb->picTimeInc = 0; + vb->realBitCnt = 0; + vb->virtualBitCnt = 0; + + rc->sei.hrd = rc->hrd; + + if(rc->hrd) + { + vb->bucketFullness = + H264Calculate(vb->bufferSize, INITIAL_BUFFER_FULLNESS, 100); + rc->gDelaySum = H264Calculate(90000, vb->bufferSize, vb->bitRate); + rc->gInitialDelay = H264Calculate(90000, vb->bucketFullness, vb->bitRate); + rc->gInitialDoffs = rc->gDelaySum - rc->gInitialDelay; + vb->bucketFullness = vb->bucketLevel = + vb->bufferSize - vb->bucketFullness; +#ifdef TRACE_RC + rc->gBufferMin = vb->bufferSize; + rc->gBufferMax = 0; +#endif + rc->sei.icrd = (u32)rc->gInitialDelay; + rc->sei.icrdo = (u32)rc->gInitialDoffs; + + DBG(1, (DBGOUTPUT, "\n InitialDelay\t%i\n Offset\t\t%i\n", + rc->gInitialDelay, rc->gInitialDoffs)); + } + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + InitialQp() Returns sequence initial quantization parameter. + +------------------------------------------------------------------------------*/ +static i32 InitialQp(i32 bits, i32 pels) +{ + const i32 qp_tbl[2][36] = + { + /*{27, 32, 36, 40, 44, 51, 58, 65, 72, 84, 96, 108, 119, 138, 156, 174, 192, 223, 253, 285, 314, 349, 384, 419, 453, 503, 553, 603, 653, 719, 784, 864, 0x7FFFFFFF},*/ + {16,19,23, 27, 32, 36, 40, 44, 51, 58, 65, 72, 84, 96, 108, 119, 138, 156, 174, 192, 223, 253, 285, 314, 349, 384, 419, 453, 503, 553, 603, 653, 719, 784, 864, 0x7FFFFFFF}, + /*{26, 38, 59, 96, 173, 305, 545, 0x7FFFFFFF},*/ + {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} + }; + const i32 upscale = 22000;//11000; + i32 i = -1; + + /* prevents overflow, QP would anyway be 17 with this high bitrate + for all resolutions under and including 1920x1088 */ + if (bits > 1000000) + return 17<>= 8; + bits >>= 5; + + /* Use maximum QP if bitrate way too low. */ + if (!bits) + return 51< 0); + ASSERT(bits > 0); + bits /= 350 + (3 * pels) / 4; + bits = H264Calculate(bits, upscale, pels << 6); + + while (qp_tbl[0][++i] < bits); + + DBG(0, (DBGOUTPUT, "BPP\t\t%d\n", bits)); + + return qp_tbl[1][i]<fillerIdx == (u32) (-1)) + { + rc->fillerIdx = sizeof(filler) / sizeof(*filler) - 1; + } + + idx = rc->fillerIdx; + if(frameCnt != 0 && ((frameCnt % 128) == 0)) + { + idx++; + } + idx %= sizeof(filler) / sizeof(*filler); + + if(idx != rc->fillerIdx) + { + rc->fillerIdx = idx; + return filler[idx] + 1; + } + return 0; +} +/*------------------------------------------------------------------------------ + VirtualBuffer() Return difference of target and real buffer fullness. + Virtual buffer and real bit count grow until one second. After one second + output bit rate per second is removed from virtualBitCnt and realBitCnt. Bit + drifting has been taken care. + + If the leaky bucket in VBR mode becomes empty (e.g. underflow), those R * T_e + bits are lost and must be decremented from virtualBitCnt. (NOTE: Drift + calculation will mess virtualBitCnt up, so the loss is added to realBitCnt) +------------------------------------------------------------------------------*/ +static i32 VirtualBuffer(h264VirtualBuffer_s *vb, i32 timeInc, true_e hrd) +{ + i32 target; + + vb->picTimeInc += timeInc; + /* picTimeInc must be in range of [0, timeScale) */ + while (vb->picTimeInc >= vb->timeScale) { + vb->picTimeInc -= vb->timeScale; + vb->realBitCnt -= vb->bitRate; + vb->bucketLevel -= vb->bitRate; + vb->seconds++; + vb->averageBitRate = vb->bitRate + vb->realBitCnt/vb->seconds; + } + /* virtualBitCnt grows until one second, this fixes bit drifting + * when bitPerPic is rounded to integer. */ + vb->virtualBitCnt = H264Calculate(vb->bitRate, vb->picTimeInc, + vb->timeScale); + if (hrd) { +#if RC_CBR_HRD + /* In CBR mode, bucket _must not_ underflow. Insert filler when + * needed. */ + vb->bucketFullness = vb->bucketLevel - vb->virtualBitCnt; +#else + /* Treat bucket underflow as unused channel capacity, the bits are lost + * but no filler data is written. Lost bits are added to realBitCnt. */ + if (vb->bucketLevel >= vb->virtualBitCnt) { + vb->bucketFullness = vb->bucketLevel - vb->virtualBitCnt; + } else { + vb->bucketFullness = 0; + vb->realBitCnt += vb->virtualBitCnt - vb->bucketLevel; + vb->bucketLevel = vb->virtualBitCnt; + } +#endif + } + + /* Saturate realBitCnt, this is to prevent overflows caused by much greater + bitrate setting than is really possible to reach */ + if (vb->realBitCnt > 0x1FFFFFFF) + vb->realBitCnt = 0x1FFFFFFF; + if (vb->realBitCnt < -0x1FFFFFFF) + vb->realBitCnt = -0x1FFFFFFF; + + target = vb->virtualBitCnt - vb->realBitCnt; + + /* Saturate target, prevents rc going totally out of control. + This situation should never happen. */ + if (target > 0x1FFFFFFF) + target = 0x1FFFFFFF; + if (target < -0x1FFFFFFF) + target = -0x1FFFFFFF; + + DBG(1, (DBGOUTPUT, "virtualBitCnt:\t%8i realBitCnt:\t%8i", + vb->virtualBitCnt, vb->realBitCnt)); + DBG(1, (DBGOUTPUT, " diff bits:\t%8i avg bitrate:\t%8i\n", target, + vb->averageBitRate)); + + return target; +} + +/*------------------------------------------------------------------------------ + H264AfterPicRc() Update source model, bit rate target error and linear + regression model for frame QP calculation. If HRD enabled, check leaky bucket + status and return RC_OVERFLOW if coded frame must be skipped. Otherwise + returns number of required filler payload bytes. +------------------------------------------------------------------------------*/ +i32 H264AfterPicRc(h264RateControl_s * rc, u32 nonZeroCnt, u32 byteCnt, + u32 qpSum) +{ + h264VirtualBuffer_s *vb = &rc->virtualBuffer; + i32 bitPerPic = rc->virtualBuffer.bitPerPic; + i32 tmp, stat, bitCnt = (i32)byteCnt * 8; + + (void) bitPerPic; + rc->qpSum = (i32)qpSum; + rc->averageQp = (float)qpSum/rc->mbPerPic; + rc->frameBitCnt = bitCnt; + + rc->nonZeroCnt = nonZeroCnt; + rc->gopBitCnt += bitCnt; + rc->frameCnt++; + + if (rc->targetPicSize) { + tmp = ((bitCnt - rc->targetPicSize) * 100) / + rc->targetPicSize; + } else { + tmp = 0; + } + + DBG(1, (DBGOUTPUT, "\nAFTER PIC RC:\n")); + DBG(0, (DBGOUTPUT, "BitCnt\t\t%8d\n", bitCnt)); + DBG(1, (DBGOUTPUT, "BitErr/avg\t%7d%% ", + ((bitCnt - bitPerPic) * 100) / (bitPerPic+1))); + DBG(1, (DBGOUTPUT, "BitErr/target\t%7i%% qpHdr %2i avgQp %2i\n", + tmp, rc->qpHdr, rc->qpSum / rc->mbPerPic)); + + /* Calculate the source parameter only for INTER frames */ + if (rc->sliceTypeCur != ISLICE && rc->sliceTypeCur != ISLICES) + SourceParameter(rc, rc->nonZeroCnt); + + /* Store the error between target and actual frame size in percentage. + * Saturate the error to avoid inter frames with mostly intra MBs + * to affect too much. */ + if (rc->sliceTypeCur != ISLICE && rc->sliceTypeCur != ISLICES) + { + //if((rc->averageQp > (rc->qpHdrPrev-7))&&(bitCnt*4>rc->targetPicSize)) + {// not still picture + update_rc_error(&rc->rError, + bitCnt - rc->targetPicSize, rc->windowLen); + } + } + else + { + update_rc_error(&rc->intraError, + bitCnt - rc->targetPicSize, rc->windowLen); + } + + /* Update number of bits used for residual, inter or intra */ + if (rc->sliceTypeCur != ISLICE && rc->sliceTypeCur != ISLICES) + { + { + update_tables(&rc->linReg, rc->qpHdrPrev, + H264Calculate(bitCnt, DSCBITPERMB, rc->mbPerPic)); + update_model(&rc->linReg); + } + } + else + { + update_tables(&rc->intra, rc->qpHdrPrev, + H264Calculate(bitCnt, DSCBITPERMB, rc->mbPerPic)); + update_model(&rc->intra); + } + + /* Post-frame skip if HRD buffer overflow */ + if ((rc->hrd == ENCHW_YES) && (bitCnt > (vb->bufferSize - vb->bucketFullness))) { + DBG(1, (DBGOUTPUT, "Be: %7i ", vb->bucketFullness)); + DBG(1, (DBGOUTPUT, "fillerBits %5i ", 0)); + DBG(1, (DBGOUTPUT, "bitCnt %d spaceLeft %d ", + bitCnt, (vb->bufferSize - vb->bucketFullness))); + DBG(1, (DBGOUTPUT, "bufSize %d bucketFullness %d bitPerPic %d\n", + vb->bufferSize, vb->bucketFullness, bitPerPic)); + DBG(0, (DBGOUTPUT, "HRD overflow, frame discard\n")); + rc->frameCoded = ENCHW_NO; + return H264RC_OVERFLOW; + } else { + vb->bucketLevel += bitCnt; + vb->bucketFullness += bitCnt; + vb->realBitCnt += bitCnt; + } + + DBG(1, (DBGOUTPUT, "plot\t%4i\t%4i\t%8i\t%8i\t%8i\t%8i\t%8i\t%8i\t%8i\n", + rc->frameCnt, rc->qpHdr, rc->targetPicSize, bitCnt, + bitPerPic, rc->gopAvgBitCnt, vb->realBitCnt-vb->virtualBitCnt, + vb->bitRate, vb->bucketFullness)); + + /* Stats */ + rc->sumQp += rc->qpHdr; + rc->sumBitrateError += ABS(vb->realBitCnt-vb->virtualBitCnt); + rc->sumFrameError += ABS(bitCnt-rc->targetPicSize); + + DBG(1, (DBGOUTPUT, "Average: QP\t%8d ", rc->sumQp/rc->frameCnt)); + DBG(1, (DBGOUTPUT, "Bitrate err\t%8d ", rc->sumBitrateError/rc->frameCnt)); + DBG(1, (DBGOUTPUT, "Framesize err\t%8d\n", rc->sumFrameError/rc->frameCnt)); + + if (rc->hrd == ENCHW_NO) { + return 0; + } + + tmp = 0; + +#if RC_CBR_HRD + /* Bits needed to prevent bucket underflow */ + tmp = bitPerPic - vb->bucketFullness; + + if (tmp > 0) { + tmp = (tmp + 7) / 8; + vb->bucketFullness += tmp * 8; + vb->realBitCnt += tmp * 8; + } else { + tmp = 0; + } +#endif + + /* Update Buffering Info */ + stat = vb->bufferSize - vb->bucketFullness; + + rc->gInitialDelay = H264Calculate(90000, stat, vb->bitRate); + rc->gInitialDoffs = rc->gDelaySum - rc->gInitialDelay; + + rc->sei.icrd = (u32)rc->gInitialDelay; + rc->sei.icrdo = (u32)rc->gInitialDoffs; + + DBG(1, (DBGOUTPUT, "initialDelay: %5i ", rc->gInitialDelay)); + DBG(1, (DBGOUTPUT, "initialDoffs: %5i\n", rc->gInitialDoffs)); + DBG(1, (DBGOUTPUT, "Be: %7i ", vb->bucketFullness)); + DBG(1, (DBGOUTPUT, "fillerBits %5i\n", tmp * 8)); + +#ifdef TRACE_RC + if (vb->bucketFullness < rc->gBufferMin) { + rc->gBufferMin = vb->bucketFullness; + } + if (vb->bucketFullness > rc->gBufferMax) { + rc->gBufferMax = vb->bucketFullness; + } + DBG(1, (DBGOUTPUT, "\nLeaky Bucket Min: %i (%d%%) Max: %i (%d%%)\n", + rc->gBufferMin, (i32)((i64)rc->gBufferMin* 100/vb->bufferSize), + rc->gBufferMax, (i32)((i64)rc->gBufferMax* 100/vb->bufferSize))); +#endif + return tmp; +} + + + +/*------------------------------------------------------------------------------ + H264BeforePicRc() Update virtual buffer, and calculate picInitQp for current + picture , and coded status. +------------------------------------------------------------------------------*/ +void H264BeforePicRc(h264RateControl_s * rc, u32 timeInc, u32 sliceType) +{ + h264VirtualBuffer_s *vb = &rc->virtualBuffer; + i32 rcWindow, intraBits = 0, tmp = 0; + + rc->frameCoded = ENCHW_YES; + rc->sliceTypeCur = sliceType; + + DBG(1, (DBGOUTPUT, "\nBEFORE PIC RC: pic=%d\n", rc->frameCnt)); + DBG(1, (DBGOUTPUT, "Frame type:\t%8i timeInc:\t%8i\n", + sliceType, timeInc)); + + tmp = VirtualBuffer(&rc->virtualBuffer, (i32) timeInc, rc->hrd); + + + if (vb->windowRem == 0) { + vb->windowRem = rc->windowLen-1; + /* New bitrate window, reset error counters. */ + update_rc_error(&rc->rError, 0x7fffffff, rc->windowLen); + /* Don't reset intra error in case of intra-only, it would cause step. */ + if (rc->sliceTypeCur != rc->sliceTypePrev) + update_rc_error(&rc->intraError, 0x7fffffff, rc->windowLen); + } else { + vb->windowRem--; + } + + /* Calculate target size for this picture. Adjust the target bitPerPic + * with the cumulated error between target and actual bitrates (tmp). + * Also take into account the bits used by intra frame starting the GOP. */ + if (rc->sliceTypeCur != ISLICE && rc->sliceTypeCur != ISLICES && + rc->intraInterval > 1) { + /* GOP bits that are used by intra frame. Amount of bits + * "stolen" by intra from each inter frame in the GOP. */ + intraBits = vb->bitPerPic*rc->intraInterval*get_avg_bits(&rc->gop, 10)/100; + intraBits -= vb->bitPerPic; + intraBits /= (rc->intraInterval-1); + intraBits = MAX(0, intraBits); + } + + /* Compensate the virtual bit buffer for intra frames "stealing" bits + * from inter frames because after intra frame the bit buffer seems + * to overflow but the following inters will level the buffer. */ + tmp += intraBits*(rc->intraInterval-rc->intraIntervalCtr); + +#ifdef RC_WINDOW_STRICT + /* In the end of window don't be too strict with matching the error + * otherwise the end of window tends to twist QP. */ + rcWindow = MAX(MAX(3, rc->windowLen/8), vb->windowRem); +#else + /* Actually we can be fairly easy with this one, let's make it + * a moving window to smoothen the changes. */ + rcWindow = MAX(1, rc->windowLen); +#endif + + rc->targetPicSize = vb->bitPerPic - intraBits + DIV(tmp, rcWindow); + /* Limit the target to a realistic minimum that can be reached. + * Setting target lower than this will confuse RC because it can never + * be reached. Frame with only skipped mbs == 96 bits. */ + rc->targetPicSize = MAX(96+rc->mbRows*16, rc->targetPicSize); + + DBG(1, (DBGOUTPUT, "intraRatio: %3i%%\tintraBits: %7i\tbufferComp: %7i\n", + get_avg_bits(&rc->gop, 10), intraBits, DIV(tmp, rcWindow))); + DBG(1, (DBGOUTPUT, "WndRem: %4i ", vb->windowRem)); + if (rc->sliceTypeCur == ISLICE || rc->sliceTypeCur == ISLICES) { + DBG(1, (DBGOUTPUT, "Rd: %6d ", avg_rc_error(&rc->intraError))); + } else { + DBG(1, (DBGOUTPUT, "Rd: %6d ", avg_rc_error(&rc->rError))); + } + DBG(1, (DBGOUTPUT, "Tr: %7d ", rc->targetPicSize)); + if (rc->sliceTypeCur == ISLICE || rc->sliceTypeCur == ISLICES) { + DBG(1, (DBGOUTPUT, "Td: %7d\n", + CLIP3(rc->targetPicSize - avg_rc_error(&rc->intraError), + 0, 2*rc->targetPicSize))); + } else { + DBG(1, (DBGOUTPUT, "Td: %7d\n", + CLIP3(rc->targetPicSize - avg_rc_error(&rc->rError), + 0, 2*rc->targetPicSize))); + } + + if(rc->picSkip) + PicSkip(rc); + + /* determine initial quantization parameter for current picture */ + PicQuant(rc); + + /* quantization parameter user defined limitations */ + PicQuantLimit(rc); + /* Store the start QP, before ROI adjustment */ + rc->qpHdrPrev = rc->qpHdr; + + if(rc->sliceTypeCur == ISLICE || rc->sliceTypeCur == ISLICES) + { + if(rc->fixedIntraQp) + rc->qpHdr = rc->fixedIntraQp; + else if (rc->sliceTypePrev != ISLICE && rc->sliceTypePrev != ISLICES) + rc->qpHdr += rc->intraQpDelta /*+ MIN(0,MAX(-10,(float)1.0 * ((float)offsetMSE - 16)))*/; + + /* quantization parameter user defined limitations still apply */ + PicQuantLimit(rc); + if (rc->intraIntervalCtr > 1) + rc->intraInterval = rc->intraIntervalCtr; + rc->intraIntervalCtr = 1; + } + else + { + /* trace the QP over GOP, excluding Intra QP */ + rc->gopQpSum += rc->qpHdr; + rc->gopQpDiv++; + rc->intraIntervalCtr++; + + /* Check that interval is repeating */ + if (rc->intraIntervalCtr > rc->intraInterval) + rc->intraInterval = rc->intraIntervalCtr; + } + + /* reset counters */ + rc->qpSum = 0; + rc->qpLastCoded = rc->qpHdr; + rc->qpTarget = rc->qpHdr; + rc->nonZeroCnt = 0; + rc->sliceTypePrev = rc->sliceTypeCur; + + DBG(0, (DBGOUTPUT, "Frame coded\t%8d ", rc->frameCoded)); + DBG(0, (DBGOUTPUT, "Frame qpHdr\t%8d ", rc->qpHdr)); + DBG(0, (DBGOUTPUT, "GopRem:\t%8d ", vb->windowRem)); + DBG(0, (DBGOUTPUT, "Target bits:\t%8d ", rc->targetPicSize)); + DBG(1, (DBGOUTPUT, "\nintraBits:\t%8d ", intraBits)); + DBG(1, (DBGOUTPUT, "bufferComp:\t%8d ", DIV(tmp, rcWindow))); + DBG(1, (DBGOUTPUT, "Rd:\t\t%8d\n", avg_rc_error(&rc->rError))); + + + rc->sei.crd += timeInc; + rc->sei.dod = 0; +} + +/*------------------------------------------------------------------------------ + + SourceParameter() Source parameter of last coded frame. Parameters + has been scaled up by factor 256. + +------------------------------------------------------------------------------*/ +void SourceParameter(h264RateControl_s * rc, i32 nonZeroCnt) +{ + // ASSERT(rc->qpSum <= 51 * rc->mbPerPic); + ASSERT(nonZeroCnt <= rc->coeffCntMax); + ASSERT(nonZeroCnt >= 0 && rc->coeffCntMax >= 0); + + /* AVOID division by zero */ + if(nonZeroCnt == 0) + { + nonZeroCnt = 1; + } + + rc->srcPrm = H264Calculate(rc->frameBitCnt, 256, nonZeroCnt); + + DBG(1, (DBGOUTPUT, "nonZeroCnt %6i, srcPrm %i\n", + nonZeroCnt, rc->srcPrm/256)); + +} + +/*------------------------------------------------------------------------------ + PicSkip() Decrease framerate if not enough bits available. +------------------------------------------------------------------------------*/ +void PicSkip(h264RateControl_s * rc) +{ + h264VirtualBuffer_s *vb = &rc->virtualBuffer; + i32 bitAvailable = vb->virtualBitCnt - vb->realBitCnt; + i32 skipIncLimit = -vb->bitPerPic / 3; + i32 skipDecLimit = vb->bitPerPic / 3; + + /* When frameRc is enabled, skipFrameTarget is not allowed to be > 1 + * This makes sure that not too many frames is skipped and lets + * the frameRc adjust QP instead of skipping many frames */ + if(((rc->picRc == ENCHW_NO) || (vb->skipFrameTarget == 0)) && + (bitAvailable < skipIncLimit)) + { + vb->skipFrameTarget++; + } + + if((bitAvailable > skipDecLimit) && vb->skipFrameTarget > 0) + { + vb->skipFrameTarget--; + } + + if(vb->skippedFrames < vb->skipFrameTarget) + { + vb->skippedFrames++; + rc->frameCoded = ENCHW_NO; + } + else + { + vb->skippedFrames = 0; + } +} + +/*------------------------------------------------------------------------------ + PicQuant() Calculate quantization parameter for next frame. In the beginning + of window use previous GOP average QP and otherwise find new QP + using the target size and previous frames QPs and bit counts. +------------------------------------------------------------------------------*/ +void PicQuant(h264RateControl_s * rc) +{ + i32 normBits, targetBits; + true_e useQpDeltaLimit = ENCHW_YES; + + if(rc->picRc != ENCHW_YES) + { + rc->qpHdr = rc->fixedQp; + DBG(1, (DBGOUTPUT, "R/cx: xxxx QP: xx xx D: xxxx newQP: xx\n")); + return; + } + + /* If HRD is enabled we must make sure this frame fits in buffer */ + if (rc->hrd == ENCHW_YES) + { + i32 bitsAvailable = + (rc->virtualBuffer.bufferSize - rc->virtualBuffer.bucketFullness); + + /* If the previous frame didn't fit the buffer we don't limit QP change */ + if (rc->frameBitCnt > bitsAvailable) { + useQpDeltaLimit = ENCHW_NO; + } + } + + /* determine initial quantization parameter for current picture */ + if (rc->sliceTypeCur == ISLICE || rc->sliceTypeCur == ISLICES) { + /* Default intra QP == average of prev frame and prev GOP average */ + rc->qpHdr = (rc->qpHdrPrev + gop_avg_qp(rc))/2; + //rc->qpHdr = rc->qpHdrPrev;// + gop_avg_qp(rc))/2; + + /* If all frames are intra we calculate new QP + * for intra the same way as for inter */ + if (rc->sliceTypePrev == ISLICE || rc->sliceTypePrev == ISLICES) { + targetBits = rc->targetPicSize - avg_rc_error(&rc->intraError); + targetBits = CLIP3(targetBits, 0, 2*rc->targetPicSize); + normBits = H264Calculate(targetBits, DSCBITPERMB, rc->mbPerPic); + rc->qpHdr = new_pic_quant(&rc->intra, normBits, useQpDeltaLimit); + } else { + DBG(1, (DBGOUTPUT, "R/cx: xxxx QP: xx xx D: xxxx newQP: xx\n")); + } + + } else { + /* Calculate new QP by matching to previous inter frames R-Q curve */ + targetBits = rc->targetPicSize - avg_rc_error(&rc->rError); + //printf("rc->targetPicSize=%d,targetBits=%d\n",rc->targetPicSize,targetBits); + //if(rc->mbRc == 2) + //targetBits = CLIP3(targetBits, -rc->targetPicSize, rc->virtualBuffer.bitPerPic*11/10); + normBits = H264Calculate(targetBits, DSCBITPERMB, rc->mbPerPic); + + rc->qpHdr = new_pic_quant(&rc->linReg, normBits, useQpDeltaLimit); + + } +} + +/*------------------------------------------------------------------------------ + + PicQuantLimit() + +------------------------------------------------------------------------------*/ +void PicQuantLimit(h264RateControl_s * rc) +{ + rc->qpHdr = MIN(rc->qpMax, MAX(rc->qpMin, rc->qpHdr)); +} + +/*------------------------------------------------------------------------------ + + Calculate() I try to avoid overflow and calculate good enough result of a*b/c + +------------------------------------------------------------------------------*/ +i32 H264Calculate(i32 a, i32 b, i32 c) +{ +#if 0 + u32 left = 32; + u32 right = 0; + u32 shift; + i32 sign = 1; + i32 tmp; + + if(a == 0 || b == 0) + { + return 0; + } + else if((a * b / b) == a && c != 0) + { + return (a * b / c); + } + if(a < 0) + { + sign = -1; + a = -a; + } + if(b < 0) + { + sign *= -1; + b = -b; + } + if(c < 0) + { + sign *= -1; + c = -c; + } + + if(c == 0 ) + { + return 0x7FFFFFFF * sign; + } + + if(b > a) + { + tmp = b; + b = a; + a = tmp; + } + + for(--left; (((u32)a << left) >> left) != (u32)a; --left); + left--; /* unsigned values have one more bit on left, + we want signed accuracy. shifting signed values gives + lint warnings */ + + while(((u32)b >> right) > (u32)c) + { + right++; + } + + if(right > left) + { + return 0x7FFFFFFF * sign; + } + else + { + shift = left - right; + return (i32)((((u32)a << shift) / (u32)c * (u32)b) >> shift) * sign; + } +#else + return (i32)((i64)a* b/c); +#endif +} +#if 1 + +/*------------------------------------------------------------------------------ + avg_rc_error() PI(D)-control for rate prediction error. +------------------------------------------------------------------------------*/ +static i32 avg_rc_error(linReg_s *p) +{ + if (ABS(p->bits[2]) < 0xFFFFFFF && ABS(p->bits[1]) < 0xFFFFFFF) + return DIV(p->bits[2] * 4 + p->bits[1] * 2 + p->bits[0] * 0, 100); + + /* Avoid overflow */ + return H264Calculate(p->bits[2], 4, 100) + + H264Calculate(p->bits[1], 2, 100); +} + +/*------------------------------------------------------------------------------ + update_overhead() Update PI(D)-control values +------------------------------------------------------------------------------*/ +static void update_rc_error(linReg_s *p, i32 bits, i32 windowLen) +{ + p->len = 3; + + if (bits == (i32)0x7fffffff) { + /* RESET */ + p->bits[0] = 0; + if (windowLen) /* Store the average error of previous GOP. */ + p->bits[1] = p->bits[1]/windowLen; + else + p->bits[1] = 0; + p->bits[2] = 0; + return; + } + p->bits[0] = bits - p->bits[2]; /* Derivative */ + if ((bits > 0) && (bits + p->bits[1] > p->bits[1])) + p->bits[1] = bits + p->bits[1]; /* Integral */ + if ((bits < 0) && (bits + p->bits[1] < p->bits[1])) + p->bits[1] = bits + p->bits[1]; /* Integral */ + p->bits[2] = bits; /* Proportional */ + DBG(1, (DBGOUTPUT, "P %6d I %7d D %7d\n", p->bits[2], p->bits[1], p->bits[0])); +} +#else +/*------------------------------------------------------------------------------ + avg_rc_error() PI(D)-control for rate prediction error. +------------------------------------------------------------------------------*/ +static i32 avg_rc_error(linReg_s *p) +{ + /* Avoid overflow */ + i32 i; + i32 biterror=0; + + for(i=0;ilen;i++) + { + biterror += p->bits[i]; + } + + return biterror/p->len; + +} + +/*------------------------------------------------------------------------------ + update_overhead() Update PI(D)-control values +------------------------------------------------------------------------------*/ +static void update_rc_error(linReg_s *p, i32 bits, i32 windowLen) +{ + p->len = 4; + + if (bits == (i32)0x7fffffff) + { + /* RESET */ + p->bits[0] = 0; + p->bits[1] = 0; + p->bits[2] = 0; + p->bits[3] = 0; + p->bits[4] = 0; + p->pos=0; + return; + } + p->bits[p->pos++] = bits; + if(p->pos==p->len) + p->pos=0; +} + +#endif +/*------------------------------------------------------------------------------ + gop_avg_qp() Average quantization parameter of P frames since previous I. +------------------------------------------------------------------------------*/ +i32 gop_avg_qp(h264RateControl_s *rc) +{ + i32 tmp = rc->qpHdrPrev; + i32 maxIntraBitRatio = 95; /* Percentage of total GOP bits. */ + + /* Average QP of previous GOP inter frames */ + if (rc->gopQpSum && rc->gopQpDiv) { + tmp = DIV(rc->gopQpSum, rc->gopQpDiv); + } + /* Average bit count per frame for previous GOP (intra + inter) */ + rc->gopAvgBitCnt = DIV(rc->gopBitCnt, (rc->gopQpDiv+1)); + /* Ratio of intra_frame_bits/all_gop_bits % for previous GOP */ + if (rc->gopBitCnt) { + i32 gopIntraBitRatio = H264Calculate(get_avg_bits(&rc->intra,1), + rc->mbPerPic, DSCBITPERMB) * 100; + gopIntraBitRatio = DIV(gopIntraBitRatio, rc->gopBitCnt); + /* Limit GOP intra bit ratio to leave room for inters. */ + gopIntraBitRatio = MIN(maxIntraBitRatio, gopIntraBitRatio); + update_tables(&rc->gop, tmp, gopIntraBitRatio); + } + rc->gopQpSum = 0; + rc->gopQpDiv = 0; + rc->gopBitCnt = 0; + + return tmp; +} + +/*------------------------------------------------------------------------------ + new_pic_quant() Calculate new quantization parameter from the 2nd degree R-Q + equation. Further adjust Qp for "smoother" visual quality. +------------------------------------------------------------------------------*/ +static i32 new_pic_quant(linReg_s *p, i32 bits, true_e useQpDeltaLimit) +{ + i32 tmp = 0, qp_best = p->qp_prev, qp = p->qp_prev, diff; + i64 diff_prev = 0, qp_prev = 0, diff_best = 0x7FFFFFFFFFLL; + + DBG(1, (DBGOUTPUT, "R/cx:%6d ",bits)); + + if (p->a1 == 0 && p->a2 == 0) { + DBG(1, (DBGOUTPUT, " QP: xx xx D: ==== newQP: %2d\n", qp)); + p->qp_prev = qp; + return qp; + } + /* Find the qp that has the best match on fitted curve */ + do { + tmp = DIV(p->a1, q_step[((qp*10)>>QP_FRACTIONAL_BITS)]); + tmp += DIV(p->a2, (i64)q_step[((qp*10)>>QP_FRACTIONAL_BITS)] * q_step[((qp*10)>>QP_FRACTIONAL_BITS)]); + diff = ABS(tmp - (bits << QP_FRACTIONAL_BITS)); + + if (diff < diff_best) { + if (diff_best == 0x7FFFFFFFFFLL) { + diff_prev = diff; + qp_prev = qp; + } else { + diff_prev = diff_best; + qp_prev = qp_best; + } + diff_best = diff; + qp_best = qp; + if ((tmp - (bits << QP_FRACTIONAL_BITS)) <= 0) { + if (qp < QP_FIXPOINT_0_POINT_1) { + break; + } + qp -= QP_FIXPOINT_0_POINT_1; + } else { + if (qp >= 0x3300) { + break; + } + qp += QP_FIXPOINT_0_POINT_1; + } + } else { + break; + } + } + while ((qp >= 0) && (qp <= 0x3300)); + + if(qp > 0x3300) + qp = 0x3300; + + DBG(1,(DBGOUTPUT, " QP: %2d %2d D: %5d", qp, qp_prev, diff_prev - diff_best)); + DBG(1, (DBGOUTPUT, " newQP: %2d\n", qp)); + + /* Limit Qp change for smoother visual quality */ + if (useQpDeltaLimit) + { + tmp = qp - p->qp_prev; + if (tmp > QP_DELTA) + { +#if 1 + //qp = p->qp_prev + QP_DELTA; + /* When QP is totally wrong, allow faster QP increase */ + if (tmp > QP_DELTA_LIMIT) + qp = p->qp_prev + QP_DELTA_LIMIT/2; + else + qp = p->qp_prev +QP_DELTA; +#endif + //if(tmp <= QP_DELTA_LIMIT) + //qp = p->qp_prev +(tmp+1)/2; + } + else if (tmp < -QP_DELTA) + { + if(tmp < -QP_DELTA) + qp = p->qp_prev - QP_DELTA; + } + } + + return qp; +} + +/*------------------------------------------------------------------------------ + get_avg_bits() +------------------------------------------------------------------------------*/ +static i32 get_avg_bits(linReg_s *p, i32 n) +{ + i32 i; + i64 sum = 0; + i32 pos = p->pos; + + if (!p->len) return 0; + + if (n == -1 || n > p->len) + n = p->len; + + i = n; + while (i--) { + if (pos) pos--; + else pos = p->len-1; + sum += p->bits[pos]; + if (sum < 0) { + return I64_MAX / (n-i); + } + } + return DIV(sum, n); +} + +/*------------------------------------------------------------------------------ + update_tables() only statistics of PSLICE, please. +------------------------------------------------------------------------------*/ +static void update_tables(linReg_s *p, i32 qp, i32 bits) +{ + const i32 clen = RC_TABLE_LENGTH; + i32 tmp = p->pos; + + p->qp_prev = qp; + p->qs[tmp] = q_step[((qp*10)>>QP_FRACTIONAL_BITS)]; + p->bits[tmp] = bits; + + if (++p->pos >= clen) { + p->pos = 0; + } + if (p->len < clen) { + p->len++; + } +} + +/*------------------------------------------------------------------------------ + update_model() Update model parameter by Linear Regression. +------------------------------------------------------------------------------*/ +static void update_model(linReg_s *p) +{ + i32 i, n = p->len,*r = p->bits; + i32 *qs = p->qs ; + i64 a1, a2, sx = lin_sx(qs, n), sy = lin_sy(qs, r, n); + + for (i = 0; i < n; i++) { + DBG(2, (DBGOUTPUT, "model: qs %i r %i\n",qs[i], r[i])); + } + + a1 = lin_sxy(qs, r, n); + a1 = a1 < I64_MAX / n ? a1 * n : I64_MAX; + + if (sy == 0) { + a1 = 0; + } else { + a1 -= sx < I64_MAX / sy ? sx * sy : I64_MAX; + } + + a2 = (lin_nsxx(qs, n) - (sx * sx)); + if (a2 == 0) { + if (p->a1 == 0) { + /* If encountered in the beginning */ + a1 = 0; + } else { + a1 = (p->a1 * 2) / 3; + } + } else { + //a1 = H264Calculate(a1, DSCY, a2); + a1 = a1 * DSCY / a2; + } + + /* Value of a1 shouldn't be excessive (small) */ + a1 = MAX(a1, -262144LL*256*256); + a1 = MIN(a1, 262143LL*256*256); + a1 = MAX(a1, -I64_MAX/q_step[510]/RC_TABLE_LENGTH); + a1 = MIN(a1, I64_MAX/q_step[510]/RC_TABLE_LENGTH); + + ASSERT(ABS(a1) * sx >= 0); + ASSERT(sx * DSCY >= 0); + a2 = DIV(sy * DSCY, n) - DIV(a1 * sx, n); + + DBG(2, (DBGOUTPUT, "model: a2:%9lld a1:%8lld\n", a2, a1)); + + if (p->len > 0) { + p->a1 = a1; + p->a2 = a2; + } +} + +/*------------------------------------------------------------------------------ + lin_sy() calculate value of Sy for n points. +------------------------------------------------------------------------------*/ +static i64 lin_sy(i32 *qp, i32 *r, i32 n) +{ + i64 sum = 0; + + while (n--) { + sum += (i64)qp[n] * qp[n] * (r[n] << QP_FRACTIONAL_BITS); + if (sum < 0) { + return I64_MAX / DSCY; + } + } + return DIV(sum, DSCY); +} + +/*------------------------------------------------------------------------------ + lin_sx() calculate value of Sx for n points. +------------------------------------------------------------------------------*/ +static i64 lin_sx(i32 *qp, i32 n) +{ + i64 tmp = 0; + + while (n--) { + ASSERT(qp[n]); + tmp += qp[n]; + } + return tmp; +} + +/*------------------------------------------------------------------------------ + lin_sxy() calculate value of Sxy for n points. +------------------------------------------------------------------------------*/ +static i64 lin_sxy(i32 *qp, i32 *r, i32 n) +{ + i64 tmp, sum = 0; + + while (n--) { + tmp = (i64)qp[n] * (i64)qp[n] * (i64)qp[n]; + if (tmp > (r[n] << (3*QP_FRACTIONAL_BITS))){ + sum += DIV(tmp, DSCY) * (r[n] << (QP_FRACTIONAL_BITS)); + } else { + sum += tmp * DIV((r[n] << (QP_FRACTIONAL_BITS)), DSCY); + } + if (sum < 0) { + return I64_MAX; + } + } + return sum; +} + +/*------------------------------------------------------------------------------ + lin_nsxx() calculate value of n * Sxy for n points. +------------------------------------------------------------------------------*/ +static i64 lin_nsxx(i32 *qp, i32 n) +{ + i64 d = n; + i64 tmp = 0, sum = 0; + + while (n--) { + tmp = qp[n]; + tmp *= tmp; + sum += d * tmp; + } + return sum; +} diff --git a/lib/vc8000nanoe/source/h264/H264RateControl.h b/lib/vc8000nanoe/source/h264/H264RateControl.h new file mode 100644 index 000000000..5afb6d299 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264RateControl.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Rate control structures and function prototypes + * + ******************************************************************************** + */ + +#ifndef H264_RATE_CONTROL_H +#define H264_RATE_CONTROL_H + +#include "enccommon.h" +#include "H264Sei.h" + +enum +{ H264RC_OVERFLOW = -1 }; + +#define RC_CBR_HRD 0 /* 1 = Constant bit rate model. Must use filler + * data to conform */ + +#define CTRL_LEVELS 7 /* DO NOT CHANGE THIS */ +#define CHECK_POINTS_MAX 10 /* DO NOT CHANGE THIS */ +#define RC_TABLE_LENGTH 10 /* DO NOT CHANGE THIS */ + + +#define QP_FRACTIONAL_BITS 8 + +typedef struct { + i64 a1; /* model parameter */ + i64 a2; /* model parameter */ + i32 qp_prev; /* previous QP */ + i32 qs[RC_TABLE_LENGTH + 1]; /* quantization step size */ + i32 bits[RC_TABLE_LENGTH+1];/* Number of bits needed to code residual */ + i32 pos; /* current position */ + i32 len; /* current lenght */ + i32 zero_div; /* a1 divisor is 0 */ + i32 cbr; +} linReg_s; + +typedef struct +{ + i32 wordError[CTRL_LEVELS]; /* Check point error bit */ + i32 qpChange[CTRL_LEVELS]; /* Check point qp difference */ + i32 wordCntTarget[CHECK_POINTS_MAX]; /* Required bit count */ + i32 wordCntPrev[CHECK_POINTS_MAX]; /* Real bit count */ + i32 checkPointDistance; + i32 checkPoints; +} h264QpCtrl_s; + +/* Virtual buffer */ +typedef struct +{ + i32 bufferSize; /* size of the virtual buffer */ + i32 bitRate; /* input bit rate per second */ + i32 bitPerPic; /* average number of bits per picture */ + i32 picTimeInc; /* timeInc since last coded picture */ + i32 timeScale; /* input frame rate numerator */ + i32 unitsInTic; /* input frame rate denominator */ + i32 virtualBitCnt; /* virtual (channel) bit count */ + i32 realBitCnt; /* real bit count */ + i32 bufferOccupancy; /* number of bits in the buffer */ + i32 skipFrameTarget; /* how many frames should be skipped in a row */ + i32 skippedFrames; /* how many frames have been skipped in a row */ + i32 nonZeroTarget; + i32 bucketFullness; /* Leaky Bucket fullness */ + i32 bucketLevel; /* Leaky Bucket fullness + virtualBitCnt */ + /* new rate control */ + i32 windowRem; + i32 seconds; /* Full seconds elapsed */ + i32 averageBitRate; /* This buffer average bitrate for full seconds */ +} h264VirtualBuffer_s; + +typedef struct +{ + true_e picRc; + u32 mbRc; /* Mb header qp can vary, check point rc */ + true_e picSkip; /* Frame Skip enable */ + true_e hrd; /* HRD restrictions followed or not */ + u32 fillerIdx; + i32 mbPerPic; /* Number of macroblock per picture */ + i32 mbRows; /* MB rows in picture */ + i32 coeffCntMax; /* Number of coeff per picture */ + i32 nonZeroCnt; + i32 srcPrm; /* Source parameter */ + i32 qpSum; /* Qp sum counter */ + float averageQp; + u32 sliceTypeCur; + u32 sliceTypePrev; + true_e frameCoded; /* Pic coded information */ + i32 fixedQp; /* Pic header qp when fixed */ + i32 qpHdr; /* Pic header qp of current voded picture */ + i32 qpMin; /* Pic header minimum qp, user set */ + i32 qpMax; /* Pic header maximum qp, user set */ + i32 qpHdrPrev; /* Pic header qp of previous coded picture */ + i32 qpLastCoded; /* Quantization parameter of last coded mb */ + i32 qpTarget; /* Target quantrization parameter */ + u32 estTimeInc; + i32 outRateNum; + i32 outRateDenom; + i32 gDelaySum; + i32 gInitialDelay; + i32 gInitialDoffs; + h264VirtualBuffer_s virtualBuffer; + sei_s sei; + i32 gBufferMin, gBufferMax; + /* new rate control */ + linReg_s linReg; /* Data for R-Q model for inter frames */ + linReg_s rError; /* Rate prediction error for inter frames(bits) */ + linReg_s intra; /* Data for intra frames */ + linReg_s intraError; /* Prediction error for intra frames */ + linReg_s gop; /* Data for GOP */ + i32 targetPicSize; + + i32 frameBitCnt; + i32 sumQp; + i32 sumBitrateError; + i32 sumFrameError; + /* for gop rate control */ + i32 gopQpSum; /* Sum of current GOP inter frame QPs */ + i32 gopQpDiv; + i32 gopBitCnt; /* Current GOP bit count so far */ + i32 gopAvgBitCnt; /* Previous GOP average bit count */ + u32 frameCnt; + i32 gopLen; + i32 windowLen; /* Bitrate window which tries to match target */ + i32 intraInterval; /* Distance between two previous I-frames */ + i32 intraIntervalCtr; + i32 intraQpDelta; + u32 fixedIntraQp; + i32 mbQpAdjustment[3]; /* QP delta for MAD macroblock QP adjustment */ + i32 longTermPicRate; + i32 mbQpAutoBoost; + + u32 rcMSESum; +} h264RateControl_s; + +/*------------------------------------------------------------------------------ + Function prototypes +------------------------------------------------------------------------------*/ +bool_e H264InitRc(h264RateControl_s * rc, u32 newStream); +void H264BeforePicRc(h264RateControl_s * rc, u32 timeInc, u32 sliceType); +i32 H264AfterPicRc(h264RateControl_s * rc, u32 nonZeroCnt, u32 byteCnt, + u32 qpSum); +u32 H264FillerRc(h264RateControl_s * rc, u32 frameCnt); +i32 H264Calculate(i32 a, i32 b, i32 c); +#endif /* H264_RATE_CONTROL_H */ + diff --git a/lib/vc8000nanoe/source/h264/H264Sei.c b/lib/vc8000nanoe/source/h264/H264Sei.c new file mode 100644 index 000000000..c4912d874 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Sei.c @@ -0,0 +1,701 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : H.264 SEI Messages. + * + ******************************************************************************** + */ + +#include "H264Sei.h" +#include "H264PutBits.h" +#include "H264NalUnit.h" +#include "enccommon.h" + +#define SEI_BUFFERING_PERIOD 0 +#define SEI_PIC_TIMING 1 +#define SEI_FILLER_PAYLOAD 3 +#define SEI_USER_DATA_UNREGISTERED 5 +#define SEI_RECOVERY_POINT_PAYLOAD 6 +#define SEI_SCALABILITY_INFO 24 +/*------------------------------------------------------------------------------ + H264InitSei() +------------------------------------------------------------------------------*/ +void H264InitSei(sei_s * sei, true_e byteStream, u32 hrd, u32 timeScale, + u32 nuit) +{ + ASSERT(sei != NULL); + + sei->byteStream = byteStream; + sei->hrd = hrd; + sei->seqId = 0x0; + sei->psp = (u32) ENCHW_YES; + sei->cts = (u32) ENCHW_YES; + /* sei->icrd = 0; */ + sei->icrdLen = 24; + /* sei->icrdo = 0; */ + sei->icrdoLen = 24; + /* sei->crd = 0; */ + sei->crdLen = 24; + /* sei->dod = 0; */ + sei->dodLen = 24; + sei->ps = 0; + sei->cntType = 1; + sei->cdf = 0; + sei->nframes = 0; + sei->toffs = 0; + + { + u32 n = 1; + + while(nuit > (1U << n)) + n++; + sei->toffsLen = n; + } + + sei->ts.timeScale = timeScale; + sei->ts.nuit = nuit; + sei->ts.time = 0; + sei->ts.sec = 0; + sei->ts.min = 0; + sei->ts.hr = 0; + sei->ts.fts = (u32) ENCHW_YES; + sei->ts.secf = (u32) ENCHW_NO; + sei->ts.minf = (u32) ENCHW_NO; + sei->ts.hrf = (u32) ENCHW_NO; + + sei->userDataEnabled = (u32) ENCHW_NO; + sei->userDataSize = 0; + sei->pUserData = NULL; +} + +/*------------------------------------------------------------------------------ + H264UpdateSeiTS() Calculate new time stamp. +------------------------------------------------------------------------------*/ +void H264UpdateSeiTS(sei_s * sei, u32 timeInc) +{ + timeStamp_s *ts = &sei->ts; + + ASSERT(sei != NULL); + timeInc += ts->time; + + while(timeInc >= ts->timeScale) + { + timeInc -= ts->timeScale; + ts->sec++; + if(ts->sec == 60) + { + ts->sec = 0; + ts->min++; + if(ts->min == 60) + { + ts->min = 0; + ts->hr++; + if(ts->hr == 32) + { + ts->hr = 0; + } + } + } + } + + ts->time = timeInc; + + sei->nframes = ts->time / ts->nuit; + sei->toffs = ts->time - sei->nframes * ts->nuit; + + ts->hrf = (ts->hr != 0); + ts->minf = ts->hrf || (ts->min != 0); + ts->secf = ts->minf || (ts->sec != 0); + +#ifdef TRACE_PIC_TIMING + DEBUG_PRINT(("Picture Timing: %02i:%02i:%02i %6i ticks\n", ts->hr, ts->min, + ts->sec, (sei->nframes * ts->nuit + sei->toffs))); +#endif +} + +/*------------------------------------------------------------------------------ + H264FillerSei() Filler payload SEI message. Requested filler payload size + could be huge. Use of temporary stream buffer is not needed, because size is + know. +------------------------------------------------------------------------------*/ +void H264FillerSei(stream_s * sp, sei_s * sei, i32 cnt) +{ + i32 i = cnt; + + ASSERT(sp != NULL && sei != NULL); + + H264NalUnitHdr(sp, 0, SEI, sei->byteStream); + + H264NalBits(sp, SEI_FILLER_PAYLOAD, 8); + COMMENT("last_payload_type_byte"); + + while(cnt >= 255) + { + H264NalBits(sp, 0xFF, 0x8); + COMMENT("ff_byte"); + cnt -= 255; + } + H264NalBits(sp, cnt, 8); + COMMENT("last_payload_size_byte"); + + for(; i > 0; i--) + { + H264NalBits(sp, 0xFF, 8); + COMMENT("filler ff_byte"); + } + H264RbspTrailingBits(sp); +} + +/*------------------------------------------------------------------------------ + H264BufferingSei() Buffering period SEI message. +------------------------------------------------------------------------------*/ +void H264BufferingSei(stream_s * sp, sei_s * sei) +{ + u8 *pPayloadSizePos; + u32 startByteCnt; + + ASSERT(sei != NULL); + + if(sei->hrd == ENCHW_NO) + { + return; + } + + H264NalBits(sp, SEI_BUFFERING_PERIOD, 8); + COMMENT("last_payload_type_byte"); + + pPayloadSizePos = sp->stream; + + H264NalBits(sp, 0xFF, 8); /* this will be updated after we know exact payload size */ + COMMENT("last_payload_size_byte"); + + startByteCnt = sp->byteCnt; + sp->emulCnt = 0; /* count emul_3_byte for this payload */ + + H264ExpGolombUnsigned(sp, sei->seqId); + COMMENT("seq_parameter_set_id"); + + H264NalBits(sp, sei->icrd, sei->icrdLen); + COMMENT("initial_cpb_removal_delay"); + + H264NalBits(sp, sei->icrdo, sei->icrdoLen); + COMMENT("initial_cpb_removal_delay_offset"); + + if(sp->bufferedBits) + { + H264RbspTrailingBits(sp); + } + + { + u32 payload_size; + + payload_size = sp->byteCnt - startByteCnt - sp->emulCnt; + *pPayloadSizePos = payload_size; + } + + /* reset cpb_removal_delay */ + sei->crd = 0; +} + +/*------------------------------------------------------------------------------ + TimeStamp() +------------------------------------------------------------------------------*/ +static void TimeStamp(stream_s * sp, timeStamp_s * ts) +{ + if(ts->fts) + { + H264NalBits(sp, ts->sec, 6); + COMMENT("seconds_value"); + H264NalBits(sp, ts->min, 6); + COMMENT("minutes_value"); + H264NalBits(sp, ts->hr, 5); + COMMENT("hours_value"); + } + else + { + H264NalBits(sp, ts->secf, 1); + COMMENT("seconds_flag"); + if(ts->secf) + { + H264NalBits(sp, ts->sec, 6); + COMMENT("seconds_value"); + H264NalBits(sp, ts->minf, 1); + COMMENT("minutes_flag"); + if(ts->minf) + { + H264NalBits(sp, ts->min, 6); + COMMENT("minutes_value"); + H264NalBits(sp, ts->hrf, 1); + COMMENT("hours_flag"); + if(ts->hrf) + { + H264NalBits(sp, ts->hr, 5); + COMMENT("hours_value"); + } + } + } + } +} + +/*------------------------------------------------------------------------------ + H264PicTimingSei() Picture timing SEI message. +------------------------------------------------------------------------------*/ +void H264PicTimingSei(stream_s * sp, sei_s * sei) +{ + u8 *pPayloadSizePos; + u32 startByteCnt; + + ASSERT(sei != NULL); + + H264NalBits(sp, SEI_PIC_TIMING, 8); + COMMENT("last_payload_type_byte"); + + pPayloadSizePos = sp->stream; + + H264NalBits(sp, 0xFF, 8); /* this will be updated after we know exact payload size */ + COMMENT("last_payload_size_byte"); + + startByteCnt = sp->byteCnt; + sp->emulCnt = 0; /* count emul_3_byte for this payload */ + + if(sei->hrd) + { + H264NalBits(sp, sei->crd, sei->crdLen); + COMMENT("cpb_removal_delay"); + H264NalBits(sp, sei->dod, sei->dodLen); + COMMENT("dpb_output_delay"); + } + + if(sei->psp) + { + H264NalBits(sp, sei->ps, 4); + COMMENT("pic_struct"); + H264NalBits(sp, sei->cts, 1); + COMMENT("clock_timestamp_flag"); + if(sei->cts) + { + H264NalBits(sp, 0, 2); + COMMENT("ct_type"); + H264NalBits(sp, 0, 1); + COMMENT("nuit_field_based_flag"); + H264NalBits(sp, sei->cntType, 5); + COMMENT("counting_type"); + H264NalBits(sp, sei->ts.fts, 1); + COMMENT("full_timestamp_flag"); + H264NalBits(sp, 0, 1); + COMMENT("discontinuity_flag"); + H264NalBits(sp, sei->cdf, 1); + COMMENT("cnt_dropped_flag"); + H264NalBits(sp, sei->nframes, 8); + COMMENT("n_frames"); + TimeStamp(sp, &sei->ts); + if(sei->toffsLen > 0) + { + H264NalBits(sp, sei->toffs, sei->toffsLen); + COMMENT("time_offset"); + } + } + } + + if(sp->bufferedBits) + { + H264RbspTrailingBits(sp); + } + + { + u32 payload_size; + + payload_size = sp->byteCnt - startByteCnt - sp->emulCnt; + *pPayloadSizePos = payload_size; + } +} + +/*------------------------------------------------------------------------------ + H264UserDataUnregSei() User data unregistered SEI message. +------------------------------------------------------------------------------*/ +void H264UserDataUnregSei(stream_s * sp, sei_s * sei) +{ + u32 i, cnt; + const u8 * pUserData; + ASSERT(sei != NULL); + ASSERT(sei->pUserData != NULL); + ASSERT(sei->userDataSize >= 16); + + pUserData = sei->pUserData; + cnt = sei->userDataSize; + if(sei->userDataEnabled == ENCHW_NO) + { + return; + } + + H264NalBits(sp, SEI_USER_DATA_UNREGISTERED, 8); + COMMENT("last_payload_type_byte"); + + while(cnt >= 255) + { + H264NalBits(sp, 0xFF, 0x8); + COMMENT("ff_byte"); + cnt -= 255; + } + + H264NalBits(sp, cnt, 8); + COMMENT("last_payload_size_byte"); + + /* Write uuid */ + for (i = 0; i < 16; i++) + { + H264NalBits(sp, pUserData[i], 8); + COMMENT("uuid_iso_iec_11578_byte"); + } + + /* Write payload */ + for (i = 16; i < sei->userDataSize; i++) + { + H264NalBits(sp, pUserData[i], 8); + COMMENT("user_data_payload_byte"); + } +} +/*------------------------------------------------------------------------------ + HevcRecoveryPointSei() recovery point SEI message. +------------------------------------------------------------------------------*/ +void H264RecoveryPointSei(stream_s * sp, sei_s * sei) +{ + u8 *pPayloadSizePos; + u32 startByteCnt; + + ASSERT(sei != NULL); + + H264NalBits(sp, SEI_RECOVERY_POINT_PAYLOAD, 8); + COMMENT("last_payload_type_byte"); + + pPayloadSizePos = sp->stream; + + H264NalBits(sp, 0xFF, 8); /* this will be updated after we know exact payload size */ + COMMENT("last_payload_size_byte"); + + startByteCnt = sp->byteCnt; + sp->emulCnt = 0; /* count emul_3_byte for this payload */ + + H264ExpGolombUnsigned(sp, sei->recoveryFrameCnt-1); + COMMENT("recovery_frame_cnt"); + + H264NalBits(sp, 1, 1); + COMMENT("exact_match_flag"); + + H264NalBits(sp, 0, 1); + COMMENT("broken_link_flag"); + + H264NalBits(sp, 0, 2); + COMMENT("changing_slice_group_idc"); + + if(sp->bufferedBits) + { + H264RbspTrailingBits(sp); + } + + { + u32 payload_size; + + payload_size = sp->byteCnt - startByteCnt - sp->emulCnt; + *pPayloadSizePos = payload_size; + } + +} + + +/*------------------------------------------------------------------------------ + H264ScalabilityInfoSei() Scalability information SEI message. +------------------------------------------------------------------------------*/ +void H264ScalabilityInfoSei(stream_s * sp, i32 svctLevel, i32 frameRate) +{ + u8 *pPayloadSizePos; + u32 startByteCnt; + i32 i; + const bool priority_id_setting_flag=true; + const bool sub_pic_layer_flag=false; + const bool iroi_division_info_present_flag=false; + const bool bitrate_info_present_flag=false; + const bool frm_rate_info_present_flag=true; + const bool frm_size_info_present_flag=false; + const bool layer_dependency_info_present_flag=true; + bool sub_region_layer_flag; + bool profile_level_info_present_flag; + bool parameter_sets_info_present_flag; + + H264NalBits(sp, SEI_SCALABILITY_INFO, 8); + COMMENT("last_payload_type_byte"); + + pPayloadSizePos = sp->stream; + + H264NalBits(sp, 0xFF, 8); /* this will be updated after we know exact payload size */ + COMMENT("last_payload_size_byte"); + + startByteCnt = sp->byteCnt; + sp->emulCnt = 0; /* count emul_3_byte for this payload */ + + H264NalBits(sp, 0, 1); + COMMENT("temporal_id_nesting_flag"); + H264NalBits(sp, 0, 1); + COMMENT("priority_layer_info_present_flag"); + H264NalBits(sp, priority_id_setting_flag , 1); + COMMENT("priority_id_setting_flag"); + H264ExpGolombUnsigned(sp, svctLevel); + COMMENT("num_layers_minus1"); + + for(i=0; i>(svctLevel-i); + H264NalBits(sp, frame_rate, 16); /* constant frame rate */ + COMMENT("avg_frm_rate[i]"); + } + if( frm_size_info_present_flag || iroi_division_info_present_flag ) + { + /* frm_width_in_mbs_minus1[ i ] 5 ue(v) */ + /* frm_height_in_mbs_minus1[ i ] 5 ue(v) */ + } +#if 0 + if( sub_region_layer_flag[ i ] ) { + base_region_layer_id[ i ] 5 ue(v) + dynamic_rect_flag[ i ] 5 u(1) + if( !dynamic_rect_flag[ i ] ) { + horizontal_offset[ i ] 5 u(16) + vertical_offset[ i ] 5 u(16) + region_width[ i ] 5 u(16) + region_height[ i ] 5 u(16) + } + } + if( sub_pic_layer_flag ) + { + roi_id[ i ] 5 ue(v) + } + if ( iroi_division_info_present_flag) + { + iroi_grid_flag[ i ] 5 u(1) + if ( iroi_grid_flag[ i ] ) { + grid_width_in_mbs_minus1[ i ] 5 ue(v) + grid_height_in_mbs_minus1[ i ] 5 ue(v) + } else { + num_rois_minus1[ i ] 5 ue(v) + for (j = 0; j <= num_rois_minus1[ i ]; j++ ) { + first_mb_in_roi[ i ][ j ] 5 ue(v) + roi_width_in_mbs_minus1[ i ][ j ] 5 ue(v) + roi_height_in_mbs_minus1[ i ][ j ] 5 ue(v) + } + } + } +#endif + if( layer_dependency_info_present_flag) + { + u32 num_directly_dependent_layers; + u32 j; + num_directly_dependent_layers = (i==0)?0:1; + H264ExpGolombUnsigned(sp, num_directly_dependent_layers); + COMMENT("num_directly_dependent_layers[i]"); + for( j = 0; j < num_directly_dependent_layers; j++ ) + { + H264ExpGolombUnsigned(sp, 0); + COMMENT("directly_dependent_layer_id_delta_minus1[i]"); + } + } + else + { + H264ExpGolombUnsigned(sp, 0); + COMMENT("layer_dependency_info_src_layer_id_delta[i]"); + } + if( parameter_sets_info_present_flag) + { + u32 j; + u32 num_seq_parameter_set_minus1 = 0; + u32 num_subset_seq_parameter_set_minus1 = 0; + u32 num_pic_parameter_set_minus1 = 0; + H264ExpGolombUnsigned(sp, num_seq_parameter_set_minus1); + COMMENT("num_seq_parameter_set_minus1[i]"); + for( j = 0; j <= num_seq_parameter_set_minus1; j++ ) + { + H264ExpGolombUnsigned(sp, 0); + COMMENT("seq_parameter_set_id_delta[i]"); + } + H264ExpGolombUnsigned(sp, num_subset_seq_parameter_set_minus1); + COMMENT("num_subset_seq_parameter_set_minus1[i]"); + for( j = 0; j <= num_subset_seq_parameter_set_minus1; j++ ) + { + H264ExpGolombUnsigned(sp, 0); + COMMENT("subset_seq_parameter_set_id_delta[i]"); + } + H264ExpGolombUnsigned(sp, num_pic_parameter_set_minus1); + COMMENT("num_pic_parameter_set_minus1[i]"); + for( j = 0; j <= num_pic_parameter_set_minus1; j++ ) + { + H264ExpGolombUnsigned(sp, 0); + COMMENT("pic_parameter_set_id_delta[i]"); + } + } + else + { + H264ExpGolombUnsigned(sp, 0); + COMMENT("parameter_sets_info_src_layer_id_delta[i]"); + } +#if 0 + if( bitstream_restriction_info_present_flag[ i ] ) { + motion_vectors_over_pic_boundaries_flag[ i ] 5 u(1) + max_bytes_per_pic_denom[ i ] 5 ue(v) + max_bits_per_mb_denom[ i ] 5 ue(v) + log2_max_mv_length_horizontal[ i ] 5 ue(v) + log2_max_mv_length_vertical[ i ] 5 ue(v) + num_reorder_frames[ i ] 5 ue(v) + max_dec_frame_buffering[ i ] 5 ue(v) + } + if( layer_conversion_flag[ i ] ) { + conversion_type_idc[ i ] 5 ue(v) + for( j=0; j < 2; j++ ) { + rewriting_info_flag[ i ][ j ] 5 u(1) + if( rewriting_info_flag[ i ][ j ] ) { + rewriting_profile_level_idc[ i ][ j ] 5 u(24) + rewriting_avg_bitrate[ i ][ j ] 5 u(16) + rewriting_max_bitrate[ i ][ j ] 5 u(16) + } + } + } +#endif + } + +#if 0 + if( priority_layer_info_present_flag ) { + pr_num_dId_minus1 5 ue(v) + for( i = 0; i <= pr_num_dId_minus1; i++ ) { + pr_dependency_id[ i ] 5 u(3) + pr_num_minus1[ i ] 5 ue(v) + for( j = 0; j <= pr_num_minus1[ i ]; j++ ) { + pr_id[ i ][ j ] 5 ue(v) + pr_profile_level_idc[ i ][ j ] 5 u(24) + pr_avg_bitrate[ i ][ j ] 5 u(16) + pr_max_bitrate[ i ][ j ] 5 u(16) + } + } + } +#endif + + if( priority_id_setting_flag ) { + int PriorityIdSettingUriIdx = 0; + char priority_id_setting_uri[20] = "http://svc.com"; + do { + H264NalBits(sp, priority_id_setting_uri[ PriorityIdSettingUriIdx ], 8); + COMMENT("priority_id_setting_uri[i]"); + } while( priority_id_setting_uri[ PriorityIdSettingUriIdx++ ] != 0 ); + } + + if(sp->bufferedBits) + { + H264RbspTrailingBits(sp); + } + + { + u32 payload_size; + + payload_size = sp->byteCnt - startByteCnt - sp->emulCnt; + *pPayloadSizePos = payload_size; + } +} + diff --git a/lib/vc8000nanoe/source/h264/H264Sei.h b/lib/vc8000nanoe/source/h264/H264Sei.h new file mode 100644 index 000000000..b91c4bc03 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Sei.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : H.264 SEI Messages. + * + ******************************************************************************** + */ + +#ifndef H264_SEI_H +#define H264_SEI_H + +#include "basetype.h" +#include "H264PutBits.h" + +typedef struct +{ + u32 fts; /* Full time stamp */ + u32 timeScale; + u32 nuit; /* number of units in tick */ + u32 time; /* Modulo time */ + u32 secf; + u32 sec; /* Seconds */ + u32 minf; + u32 min; /* Minutes */ + u32 hrf; + u32 hr; /* Hours */ +} timeStamp_s; + +typedef struct +{ + timeStamp_s ts; + u32 nalUnitSize; + u32 enabled; + true_e byteStream; + u32 hrd; /* HRD conformance */ + u32 seqId; + u32 icrd; /* initial cpb removal delay */ + u32 icrdLen; + u32 icrdo; /* initial cpb removal delay offset */ + u32 icrdoLen; + u32 crd; /* CPB removal delay */ + u32 crdLen; + u32 dod; /* DPB removal delay */ + u32 dodLen; + u32 psp; + u32 ps; + u32 cts; + u32 cntType; + u32 cdf; + u32 nframes; + u32 toffs; + u32 toffsLen; + u32 userDataEnabled; + const u8 * pUserData; + u32 userDataSize; + u32 insertRecoveryPointMessage; + u32 recoveryFrameCnt; +} sei_s; + +void H264InitSei(sei_s * sei, true_e byteStream, u32 hrd, u32 timeScale, + u32 nuit); +void H264UpdateSeiTS(sei_s * sei, u32 timeInc); +void H264FillerSei(stream_s * sp, sei_s * sei, i32 cnt); +void H264BufferingSei(stream_s * stream, sei_s * sei); +void H264PicTimingSei(stream_s * stream, sei_s * sei); +void H264UserDataUnregSei(stream_s * sp, sei_s * sei); +void H264RecoveryPointSei(stream_s * sp, sei_s * sei); +void H264ScalabilityInfoSei(stream_s * sp, i32 svctLevel, i32 frameRate); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264SequenceParameterSet.c b/lib/vc8000nanoe/source/h264/H264SequenceParameterSet.c new file mode 100644 index 000000000..e3524c60a --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264SequenceParameterSet.c @@ -0,0 +1,873 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : H264 Sequence Parameter Set + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "H264SequenceParameterSet.h" +#include "H264NalUnit.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#define MAX_LEVEL_INDEX (sizeof(H264LevelIdc)/sizeof(*H264LevelIdc)) + +/* max MV length is 512 horizontal and 128 vertical in quarter pixel resolution */ +#define LOG2_MAX_MV_LENGTH_HOR 9 +#define LOG2_MAX_MV_LENGTH_VER 7 +#define EXTENDED_SAR 255 + +/* Level 1b indicated by value 99 */ +const u32 H264LevelIdc[16] = + { 10, 99, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51 }; + +const u32 H264MaxCPBS[16] = + { 210000, 420000, 600000, 1200000, 2400000, 2400000, 4800000, 4800000, 12000000, + 16800000, 24000000, 30000000, 75000000, 75000000, 162000000, 288000000 +}; + +/* Level 51 MaxFS in standard is 36864, increased to enable max resolution */ +const u32 H264MaxFS[16] = { 99, 99, 396, 396, 396, 396, 792, 1620, 1620, + 3600, 5120, 8192, 8192, 8704, 22080, 65025 +}; + +/* sqrt(8*maxFrameSize) is maximum width and height of specific level */ +const u32 H264SqrtMaxFS8[16] = + { 28, 28, 56, 56, 56, 56, 79, 113, 113, 169, 202, 256, 256, 263, 420, 543 }; + +const u32 H264MaxMBPS[16] = + { 1485, 1485, 3000, 6000, 11880, 11880, 19800, 20250, 40500, + 108000, 216000, 245760, 245760, 522240, 589824, 983040 +}; + +const u32 H264MaxBR[16] = + { 76800, 153600, 230400, 460800, 921600, 2400000, 4800000, 4800000, 12000000, + 16800000, 24000000, 24000000, 60000000, 60000000, 162000000, 288000000 +}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static void SeqParameterSetMvcExtension(stream_s * stream, sps_s * sps); +static void WriteVui(stream_s * strm, vui_t * vui, i32 numRefFrames); +static i32 GetAspectRatioIdc(i32 sarWidth, i32 sarHeight); +static void UpdateVuiPresence(sps_s * sps); + +/*------------------------------------------------------------------------------ + + H264SpsInit + +------------------------------------------------------------------------------*/ +void H264SeqParameterSetInit(sps_s * sps) +{ + sps->byteStream = ENCHW_YES; + sps->profileIdc = 66; /* 66 = baseline, 77 = main, 100 = high, 118 = MVC */ + sps->constraintSet0 = ENCHW_YES; + sps->constraintSet1 = ENCHW_YES; + sps->constraintSet2 = ENCHW_YES; + sps->constraintSet3 = ENCHW_NO; + + sps->levelIdc = 30; + sps->seqParameterSetId = 0; + sps->log2MaxFrameNumMinus4 = (16 - 4); + sps->picOrderCntType = 2; + + sps->numRefFrames = 1; + sps->gapsInFrameNumValueAllowed = ENCHW_NO; + sps->picWidthInMbsMinus1 = 176 / 16 - 1; + sps->picHeightInMapUnitsMinus1 = 144 / 16 - 1; + sps->frameMbsOnly = ENCHW_YES; + sps->direct8x8Inference = ENCHW_YES; + sps->frameCropping = ENCHW_NO; + sps->vuiParametersPresent = ENCHW_YES; + sps->vui.bitStreamRestrictionFlag = 1; + + sps->vui.videoFullRange = 0; + sps->vui.sarWidth = 0; + sps->vui.sarHeight = 0; + + sps->frameCropLeftOffset = 0; + sps->frameCropRightOffset = 0; + sps->frameCropTopOffset = 0; + sps->frameCropBottomOffset = 0; + + return; +} + +/*------------------------------------------------------------------------------ + + H264SeqParameterSet + +------------------------------------------------------------------------------*/ +void H264SeqParameterSet(stream_s * stream, sps_s * sps, true_e nalHeader) +{ + /* Nal unit syntax */ + if (nalHeader == ENCHW_YES) + H264NalUnitHdr(stream, 1, SPSET, sps->byteStream); + + H264NalBits(stream, sps->profileIdc, 8); + COMMENT("profile_idc"); + + /* constraint_set0 streams obey all baseline profile constraints. */ + if (sps->profileIdc > 66) + sps->constraintSet0 = ENCHW_NO; + /* constraint_set1 streams obey all main profile constraints. */ + if (sps->profileIdc > 77) + sps->constraintSet1 = ENCHW_NO; + /* constraint_set2 streams obey all extended profile constraints. */ + if (sps->profileIdc > 88) + sps->constraintSet2 = ENCHW_NO; + + H264NalBits(stream, (i32) sps->constraintSet0, 1); + COMMENT("constraint_set0_flag"); + + H264NalBits(stream, (i32) sps->constraintSet1, 1); + COMMENT("constraint_set1_flag"); + + H264NalBits(stream, (i32) sps->constraintSet2, 1); + COMMENT("constraint_set2_flag"); + + H264NalBits(stream, (i32) sps->constraintSet3, 1); + COMMENT("constraint_set3_flag"); + + H264NalBits(stream, 0, 4); + COMMENT("reserved_zero_4bits"); + + H264NalBits(stream, sps->levelIdc, 8); + COMMENT("level_idc"); + + H264ExpGolombUnsigned(stream, sps->seqParameterSetId); + COMMENT("seq_parameter_set_id"); + + if (sps->profileIdc >= 100) + { + H264ExpGolombUnsigned(stream, 1); + COMMENT("chroma_format_idc"); + + H264ExpGolombUnsigned(stream, 0); + COMMENT("bit_depth_luma_minus8"); + + H264ExpGolombUnsigned(stream, 0); + COMMENT("bit_depth_chroma_minus8"); + + H264NalBits(stream, 0, 1); + COMMENT("qpprime_y_zero_transform_bypass_flag"); + + H264NalBits(stream, 0, 1); + COMMENT("seq_scaling_matrix_present_flag"); + } + + H264ExpGolombUnsigned(stream, sps->log2MaxFrameNumMinus4); + COMMENT("log2_max_frame_num_minus4"); + + H264ExpGolombUnsigned(stream, sps->picOrderCntType); + COMMENT("pic_order_cnt_type"); + + H264ExpGolombUnsigned(stream, sps->numRefFrames); + COMMENT("num_ref_frames"); + + H264NalBits(stream, (i32) sps->gapsInFrameNumValueAllowed, 1); + COMMENT("gaps_in_frame_num_value_allowed_flag"); + + H264ExpGolombUnsigned(stream, sps->picWidthInMbsMinus1); + COMMENT("pic_width_in_mbs_minus1"); + + H264ExpGolombUnsigned(stream, sps->picHeightInMapUnitsMinus1); + COMMENT("pic_height_in_map_units_minus1"); + + H264NalBits(stream, (i32) sps->frameMbsOnly, 1); + COMMENT("frame_mbs_only_flag"); + + if (!sps->frameMbsOnly) + { + H264NalBits(stream, 0, 1); + COMMENT("mb_adaptive_frame_field_flag"); + } + + H264NalBits(stream, (i32) sps->direct8x8Inference, 1); + COMMENT("direct_8x8_inference_flag"); + + H264NalBits(stream, (i32) sps->frameCropping, 1); + COMMENT("frame_cropping_flag"); + + /* Frame cropping parameters */ + if (sps->frameCropping) + { + H264ExpGolombUnsigned(stream, sps->frameCropLeftOffset); + COMMENT("frame_crop_left_offset"); + H264ExpGolombUnsigned(stream, sps->frameCropRightOffset); + COMMENT("frame_crop_right_offset"); + H264ExpGolombUnsigned(stream, sps->frameCropTopOffset); + COMMENT("frame_crop_top_offset"); + H264ExpGolombUnsigned(stream, sps->frameCropBottomOffset); + COMMENT("frame_crop_bottom_offset"); + } + + UpdateVuiPresence(sps); + +#if 0 + /* Currently JMVC can't decode this */ + sps->vuiParametersPresent = ENCHW_NO; +#endif + + H264NalBits(stream, (i32) sps->vuiParametersPresent, 1); + COMMENT("vui_parameters_present_flag"); + + if(sps->vuiParametersPresent == ENCHW_YES) + WriteVui(stream, &sps->vui, sps->numRefFrames); + + if (nalHeader == ENCHW_YES) + H264NalUnitTrailinBits(stream, sps->byteStream); +} + +void UpdateVuiPresence(sps_s * sps) +{ + + if(sps->vui.nalHrdParametersPresentFlag == 0 && + sps->vui.timeScale == 0 && + sps->vui.pictStructPresentFlag == 0 && + sps->vui.sarWidth == 0 && sps->vui.videoFullRange == 0 && + sps->vui.bitStreamRestrictionFlag == 0) + { + sps->vuiParametersPresent = ENCHW_NO; + } +} + +/*------------------------------------------------------------------------------ + + H264SubsetSeqParameterSet + +------------------------------------------------------------------------------*/ +void H264SubsetSeqParameterSet(stream_s * stream, sps_s * sps) +{ + /* Nal unit syntax */ + H264NalUnitHdr(stream, 1, SSPSET, sps->byteStream); + + sps->profileIdc = 128; /* Stereo High profile */ + + H264SeqParameterSet(stream, sps, ENCHW_NO); + + H264NalBits(stream, 1, 1); + COMMENT("bit_equal_to_one"); + + SeqParameterSetMvcExtension(stream, sps); + + H264NalBits(stream, 0, 1); + COMMENT("mvc_vui_parameters_present_flag"); + + H264NalBits(stream, 0, 1); + COMMENT("additional_extension2_flag"); + + H264NalUnitTrailinBits(stream, sps->byteStream); +} + +/*------------------------------------------------------------------------------ + + H264SubsetSeqParameterSet + +------------------------------------------------------------------------------*/ +static void SeqParameterSetMvcExtension(stream_s * stream, sps_s * sps) +{ + H264ExpGolombUnsigned(stream, 1); + COMMENT("num_views_minus_1"); + + H264ExpGolombUnsigned(stream, 0); + COMMENT("view_id[0]"); + H264ExpGolombUnsigned(stream, 1); + COMMENT("view_id[1]"); + + H264ExpGolombUnsigned(stream, 1); + COMMENT("num_anchor_refs_l0[1]"); + H264ExpGolombUnsigned(stream, 0); + COMMENT("anchor_ref_l0[1]"); + H264ExpGolombUnsigned(stream, 0); + COMMENT("num_anchor_refs_l1[1]"); + + H264ExpGolombUnsigned(stream, 1); + COMMENT("num_non_anchor_refs_l0[1]"); + H264ExpGolombUnsigned(stream, 0); + COMMENT("non_anchor_ref_l0[1]"); + H264ExpGolombUnsigned(stream, 0); + COMMENT("num_non_anchor_refs_l1[1]"); + + H264ExpGolombUnsigned(stream, 0); + COMMENT("num_level_values_signalled_minus1"); + H264NalBits(stream, sps->levelIdc, 8); + COMMENT("level_idc"); + + H264ExpGolombUnsigned(stream, 0); + COMMENT("num_applicable_ops_minus1"); + H264NalBits(stream, 0, 3); + COMMENT("applicable_op_temporal_id"); + H264ExpGolombUnsigned(stream, 0); + COMMENT("applicable_op_num_target_view_minus1"); + H264ExpGolombUnsigned(stream, 1); + COMMENT("applicable_op_target_view_id"); + H264ExpGolombUnsigned(stream, 1); + COMMENT("applicable_op_num_views_minus1"); + + +} + +/*------------------------------------------------------------------------------ + + Function: WriteVui + + Functional description: + Write VUI params into the stream + + Inputs: + vui_t *vui pointer to VUI params structure + u32 numRefFrames number of reference frames, used as + max_dec_frame_buffering + + Outputs: + stream_s * pointer to stream data + +------------------------------------------------------------------------------*/ +static void WriteVui(stream_s * strm, vui_t * vui, i32 numRefFrames) +{ + +/* Variables */ + + i32 sarIdc; + +/* Code */ + + ASSERT(strm); + ASSERT(vui); + + sarIdc = GetAspectRatioIdc(vui->sarWidth, vui->sarHeight); + + if(sarIdc == 0) /* unspecified sample aspect ratio -> not present */ + { + H264NalBits(strm, 0, 1); + COMMENT("aspect_ratio_info_present_flag"); + } + else + { + H264NalBits(strm, 1, 1); + COMMENT("aspect_ratio_info_present_flag"); + H264NalBits(strm, sarIdc, 8); + COMMENT("aspect_ratio_idc"); + if(sarIdc == EXTENDED_SAR) + { + H264NalBits(strm, vui->sarWidth, 16); + COMMENT("sar_width"); + H264NalBits(strm, vui->sarHeight, 16); + COMMENT("sar_height"); + } + } + + H264NalBits(strm, 0, 1); + COMMENT("overscan_info_present_flag"); + + if(vui->videoFullRange != 0) + { + H264NalBits(strm, 1, 1); + COMMENT("video_signal_type_present_flag"); + H264NalBits(strm, 5, 3); + COMMENT("unspecified video_format"); + H264NalBits(strm, 1, 1); + COMMENT("video_full_range_flag"); + H264NalBits(strm, 0, 1); + COMMENT("colour_description_present_flag"); + } + else + { + H264NalBits(strm, 0, 1); + COMMENT("video_signal_type_present_flag"); + } + + H264NalBits(strm, 0, 1); + COMMENT("chroma_loc_info_present_flag"); + + if(vui->timeScale != 0) + { + H264NalBits(strm, 1, 1); + COMMENT("timing_info_present_flag"); + H264NalBits(strm, vui->numUnitsInTick >> 16, 16); + COMMENT("num_units_in_tick msb"); + H264NalBits(strm, vui->numUnitsInTick & 0xFFFF, 16); + COMMENT("num_units_in_tick lsb"); + H264NalBits(strm, vui->timeScale >> 16, 16); + COMMENT("time_scale msb"); + H264NalBits(strm, vui->timeScale & 0xFFFF, 16); + COMMENT("time_scale lsb"); + H264NalBits(strm, 1, 1); + COMMENT("fixed_frame_rate_flag"); + } + else + { + H264NalBits(strm, 0, 1); + COMMENT("timing_info_present_flag"); + } + + H264NalBits(strm, (i32) vui->nalHrdParametersPresentFlag, 1); + COMMENT("nal_hrd_parameters_present_flag"); + + if(vui->nalHrdParametersPresentFlag == ENCHW_YES) + { + H264ExpGolombUnsigned(strm, 0); + COMMENT("cpb_cnt_minus1"); + + { + u32 bit_rate_scale = 1; + u32 cpb_size_scale = 1; + u32 tmp, i = 0; + + tmp = vui->cpbSize; + while (4095 < (tmp >> (4 + i++))); + cpb_size_scale = i; + + i = 0; + tmp = vui->bitRate; + while (4095 < (tmp >> (6 + i++))); + bit_rate_scale = i; + + H264NalBits(strm, bit_rate_scale, 4); + COMMENT("bit_rate_scale"); + + H264NalBits(strm, cpb_size_scale, 4); + COMMENT("cpb_size_scale"); + + tmp = vui->bitRate >> (6 + bit_rate_scale); + H264ExpGolombUnsigned(strm, tmp - 1); + vui->bitRate = tmp << (6 + bit_rate_scale); + COMMENT("bit_rate_value_minus1"); + + tmp = vui->cpbSize >> (4 + cpb_size_scale); + H264ExpGolombUnsigned(strm, tmp - 1); + vui->cpbSize = tmp << (4 + cpb_size_scale); + COMMENT("cpb_size_value_minus1"); + } + + H264NalBits(strm, 0, 1); + COMMENT("cbr_flag"); + + H264NalBits(strm, vui->initialCpbRemovalDelayLength - 1, 5); + COMMENT("initial_cpb_removal_delay_length_minus1"); + H264NalBits(strm, vui->cpbRemovalDelayLength - 1, 5); + COMMENT("cpb_removal_delay_length_minus1"); + H264NalBits(strm, vui->dpbOutputDelayLength - 1, 5); + COMMENT("dpb_output_delay_length_minus1"); + H264NalBits(strm, vui->timeOffsetLength, 5); + COMMENT("time_offset_length"); + } + + H264NalBits(strm, 0, 1); + COMMENT("vcl_hrd_parameters_present_flag"); + + if(vui->nalHrdParametersPresentFlag == ENCHW_YES) + { + H264NalBits(strm, 0, 1); + COMMENT("low_delay_hrd_flag"); + } + + H264NalBits(strm, (i32) vui->pictStructPresentFlag, 1); + COMMENT("pic_struct_present_flag"); + + H264NalBits(strm, (i32) vui->bitStreamRestrictionFlag, 1); + COMMENT("bit_stream_restriction_flag"); + + if(vui->bitStreamRestrictionFlag == ENCHW_YES) + { + H264NalBits(strm, 1, 1); + COMMENT("motion_vectors_over_pic_boundaries"); + + H264ExpGolombUnsigned(strm, 0); + COMMENT("max_bytes_per_pic_denom"); + + H264ExpGolombUnsigned(strm, 0); + COMMENT("max_bits_per_mb_denom"); + + H264ExpGolombUnsigned(strm, LOG2_MAX_MV_LENGTH_HOR); + COMMENT("log2_mv_length_horizontal"); + + H264ExpGolombUnsigned(strm, LOG2_MAX_MV_LENGTH_VER); + COMMENT("log2_mv_length_vertical"); + + H264ExpGolombUnsigned(strm, 0); + COMMENT("num_reorder_frames"); + + H264ExpGolombUnsigned(strm, numRefFrames); + COMMENT("max_dec_frame_buffering"); + } + +} + +/*------------------------------------------------------------------------------ + + Function: GetAspectRatioIdc + + Functional description: + + Inputs: + u32 sarWidth sample aspect ratio width + u32 sarHeight sample aspect ratio height + + Outputs: + + Returns: + u32 acpectRatioIdc + +------------------------------------------------------------------------------*/ +static i32 GetAspectRatioIdc(i32 sarWidth, i32 sarHeight) +{ + + i32 aspectRatioIdc; + + if(sarWidth == 0 || sarHeight == 0) /* unspecified */ + aspectRatioIdc = 0; + else if(sarWidth == sarHeight) /* square, 1:1 */ + aspectRatioIdc = 1; + else if(sarHeight == 11) + { + if(sarWidth == 12) /* 12:11 */ + aspectRatioIdc = 2; + else if(sarWidth == 10) /* 10:11 */ + aspectRatioIdc = 3; + else if(sarWidth == 16) /* 16:11 */ + aspectRatioIdc = 4; + else if(sarWidth == 24) /* 24:11 */ + aspectRatioIdc = 6; + else if(sarWidth == 20) /* 20:11 */ + aspectRatioIdc = 7; + else if(sarWidth == 32) /* 32:11 */ + aspectRatioIdc = 8; + else if(sarWidth == 18) /* 18:11 */ + aspectRatioIdc = 10; + else if(sarWidth == 15) /* 15:11 */ + aspectRatioIdc = 11; + else /* Extended_SAR */ + aspectRatioIdc = EXTENDED_SAR; + } + else if(sarHeight == 33) + { + if(sarWidth == 40) /* 40:33 */ + aspectRatioIdc = 5; + else if(sarWidth == 80) /* 80:33 */ + aspectRatioIdc = 9; + else if(sarWidth == 64) /* 64:33 */ + aspectRatioIdc = 12; + else /* Extended_SAR */ + aspectRatioIdc = EXTENDED_SAR; + } + else if(sarWidth == 160 && sarHeight == 99) /* 160:99 */ + aspectRatioIdc = 13; + else /* Extended_SAR */ + aspectRatioIdc = EXTENDED_SAR; + + return (aspectRatioIdc); + +} + +/*------------------------------------------------------------------------------ + + Function: H264CheckLevel + + Functional description: + Check whether levelIdc can accommodate the stream based on bit and + frame rates set by the application + + Inputs: + seqParamSet_t * pointer to SPS data structure + u32 bitRate bit rate in bits per second + u32 frameRateNum numerator of the frame rate + u32 frameRateDenom denominator of the frame rate + + Outputs: + seqParamSet_t * pointer to SPS data structure + + Returns: + ENCHW_OK for success + ENCHW_NOK for invalid params + +------------------------------------------------------------------------------*/ +bool_e H264CheckLevel(sps_s * sps, i32 bitRate, i32 frameRateNum, + i32 frameRateDenom) +{ + +/* Variables */ + + i32 tmp, i; + +/* Code */ + + ASSERT(sps); + + if(bitRate <= 0 || frameRateNum <= 0 || frameRateDenom <= 0) + return (ENCHW_NOK); + + i = sps->levelIdx; + + tmp = (sps->picWidthInMbsMinus1 + 1) * (sps->picHeightInMapUnitsMinus1 + 1); + + if((u32) tmp > H264MaxFS[i] || + (u32) sps->picWidthInMbsMinus1 >= H264SqrtMaxFS8[i] || + (u32) sps->picHeightInMapUnitsMinus1 >= H264SqrtMaxFS8[i]) + return (ENCHW_NOK); + + tmp = frameRateNum * tmp / frameRateDenom; + + if(H264MaxMBPS[sps->levelIdx] < (u32) tmp) + return (ENCHW_NOK); + + return (ENCHW_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: H264GetLevelIndex + + Functional description: + function determines index to level tables + level argument. If invalid level -> return INVALID_LEVEL + + Inputs: + u32 levelIdc + + Outputs: + + Returns: + u32 index + INVALID_LEVEL + +------------------------------------------------------------------------------*/ + +u32 H264GetLevelIndex(u32 levelIdc) +{ + + u32 i; + + i = 0; + while(H264LevelIdc[i] != levelIdc) + { + i++; + if(i >= MAX_LEVEL_INDEX) + return INVALID_LEVEL; + } + + return (i); + +} + +/*------------------------------------------------------------------------------ + + Function: H264SpsSetVui + + Functional description: + Set VUI parameters in the SPS structure + + Inputs: + u32 timeScale + u32 numUnitsInTick + bool zeroReorderFrames + + Outputs: + seqParamSet_t * pointer to SPS structure + +------------------------------------------------------------------------------*/ +void H264SpsSetVuiTimigInfo(sps_s * sps, u32 timeScale, u32 numUnitsInTick) +{ + if(timeScale) + sps->vuiParametersPresent = ENCHW_YES; + + sps->vui.timeScale = 2 * timeScale; /* used as timing_info_present_flag */ + sps->vui.numUnitsInTick = numUnitsInTick; +} + +void H264SpsSetVuiVideoInfo(sps_s * sps, u32 videoFullRange) +{ + if(videoFullRange) + sps->vuiParametersPresent = ENCHW_YES; + + sps->vui.videoFullRange = videoFullRange; /* used as video_signal_type_present_flag */ +} + +void H264SpsSetVuiAspectRatio(sps_s * sps, u32 sampleAspectRatioWidth, + u32 sampleAspectRatioHeight) +{ + ASSERT(sampleAspectRatioWidth < (1 << 16)); + ASSERT(sampleAspectRatioHeight < (1 << 16)); + + if(sampleAspectRatioWidth) + sps->vuiParametersPresent = ENCHW_YES; + + sps->vui.sarWidth = sampleAspectRatioWidth; /* used as aspect_ratio_info_present_flag */ + sps->vui.sarHeight = sampleAspectRatioHeight; +} + +/*------------------------------------------------------------------------------ + + Function: H264SpsSetVuiHrd + + Functional description: + Set VUI HRD parameters in the SPS structure + + Inputs: + seqParamSet_t * pointer to SPS structure + + Outputs: + seqParamSet_t * pointer to SPS structure + +------------------------------------------------------------------------------*/ + +void H264SpsSetVuiHrd(sps_s * sps, u32 present) +{ + ASSERT(sps); + + sps->vui.nalHrdParametersPresentFlag = present; + + if(present) + sps->vuiParametersPresent = ENCHW_YES; + else + { + return; + } + + ASSERT(sps->vui.timeScale && sps->vui.numUnitsInTick); /* set these first */ + + sps->vui.initialCpbRemovalDelayLength = 24; + sps->vui.cpbRemovalDelayLength = 24; + sps->vui.dpbOutputDelayLength = 24; + + { + u32 n = 1; + + while(sps->vui.numUnitsInTick > (1U << n)) + { + n++; + } + sps->vui.timeOffsetLength = n; + + } +} + +/*------------------------------------------------------------------------------ + + Function: H264SpsSetVuiHrdBitRate + + Functional description: + Set VUI HRD bit rate in the SPS structure + + Inputs: + seqParamSet_t * pointer to SPS structure + u32 bitRate + + Outputs: + seqParamSet_t * pointer to SPS structure + +------------------------------------------------------------------------------*/ + +void H264SpsSetVuiHrdBitRate(sps_s * sps, u32 bitRate) +{ + ASSERT(sps); + + sps->vui.bitRate = bitRate; +} + +void H264SpsSetVuiHrdCpbSize(sps_s * sps, u32 cpbSize) +{ + ASSERT(sps); + + sps->vui.cpbSize = cpbSize; +} + +u32 H264SpsGetVuiHrdBitRate(sps_s * sps) +{ + ASSERT(sps); + + return sps->vui.bitRate; +} + +u32 H264SpsGetVuiHrdCpbSize(sps_s * sps) +{ + ASSERT(sps); + + return sps->vui.cpbSize; +} + +/*------------------------------------------------------------------------------ + Function name : H264EndOfSequence + Description : + Return type : void + Argument : stream_s *stream + Argument : sps_s *sps +------------------------------------------------------------------------------*/ +void H264EndOfSequence(stream_s * stream, sps_s * sps) +{ + H264NalUnitHdr(stream, 0, ENDOFSEQUENCE, sps->byteStream); +} + +/*------------------------------------------------------------------------------ + Function name : H264EndOfStream + Description : + Return type : void + Argument : stream_s *stream + Argument : sps_s *sps +------------------------------------------------------------------------------*/ +void H264EndOfStream(stream_s * stream, sps_s * sps) +{ + H264NalUnitHdr(stream, 0, ENDOFSTREAM, sps->byteStream); +} + +/*------------------------------------------------------------------------------ + Function name : H264SpsSetVuiPictStructPresentFlag + Description : Signal presence of pic_struct in picture timing SEI + Return type : void + Argument : sps_s * sps + Argument : u32 flag +------------------------------------------------------------------------------*/ +void H264SpsSetVuiPictStructPresentFlag(sps_s * sps, u32 flag) +{ + sps->vui.pictStructPresentFlag = flag; +} diff --git a/lib/vc8000nanoe/source/h264/H264SequenceParameterSet.h b/lib/vc8000nanoe/source/h264/H264SequenceParameterSet.h new file mode 100644 index 000000000..fc8f94d4f --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264SequenceParameterSet.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : H264 Sequence Parameter Set + * + ******************************************************************************** + */ + +#ifndef __H264_SEQUENCE_PARAMETER_SET_h__ +#define __H264_SEQUENCE_PARAMETER_SET_h__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "enccommon.h" +#include "H264PutBits.h" +#include "H264Slice.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +typedef struct +{ + u32 timeScale; + u32 numUnitsInTick; + u32 bitStreamRestrictionFlag; + u32 videoFullRange; + u32 sarWidth; + u32 sarHeight; + u32 nalHrdParametersPresentFlag; + u32 vclHrdParametersPresentFlag; + u32 pictStructPresentFlag; + u32 initialCpbRemovalDelayLength; + u32 cpbRemovalDelayLength; + u32 dpbOutputDelayLength; + u32 timeOffsetLength; + u32 bitRate; + u32 cpbSize; +} vui_t; + +typedef struct +{ + true_e byteStream; + u32 profileIdc; + true_e constraintSet0; + true_e constraintSet1; + true_e constraintSet2; + true_e constraintSet3; + u32 levelIdc; + u32 levelIdx; + u32 seqParameterSetId; + i32 log2MaxFrameNumMinus4; + u32 picOrderCntType; + u32 numRefFrames; + true_e gapsInFrameNumValueAllowed; + i32 picWidthInMbsMinus1; + i32 picHeightInMapUnitsMinus1; + true_e frameMbsOnly; + true_e direct8x8Inference; + true_e frameCropping; + true_e vuiParametersPresent; + vui_t vui; + u32 frameCropLeftOffset; + u32 frameCropRightOffset; + u32 frameCropTopOffset; + u32 frameCropBottomOffset; +} sps_s; + +extern const u32 H264LevelIdc[]; +extern const u32 H264MaxCPBS[]; +extern const u32 H264MaxFS[]; +extern const u32 H264SqrtMaxFS8[]; +extern const u32 H264MaxMBPS[]; +extern const u32 H264MaxBR[]; + +#define INVALID_LEVEL 0xFFFF + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +void H264SeqParameterSetInit(sps_s * sps); +void H264SeqParameterSet(stream_s * stream, sps_s * sps, true_e nalHeader); +void H264SubsetSeqParameterSet(stream_s * stream, sps_s * sps); + +void H264EndOfSequence(stream_s * stream, sps_s * sps); +void H264EndOfStream(stream_s * stream, sps_s * sps); + +u32 H264GetLevelIndex(u32 levelIdc); + +bool_e H264CheckLevel(sps_s * sps, i32 bitRate, i32 frameRateNum, + i32 frameRateDenom); + +void H264SpsSetVuiTimigInfo(sps_s * sps, u32 timeScale, u32 numUnitsInTick); +void H264SpsSetVuiVideoInfo(sps_s * sps, u32 videoFullRange); +void H264SpsSetVuiAspectRatio(sps_s * sps, u32 sampleAspectRatioWidth, + u32 sampleAspectRatioHeight); +void H264SpsSetVuiPictStructPresentFlag(sps_s * sps, u32 flag); +void H264SpsSetVuiHrd(sps_s * sps, u32 present); +void H264SpsSetVuiHrdBitRate(sps_s * sps, u32 bitRate); +void H264SpsSetVuiHrdCpbSize(sps_s * sps, u32 cpbSize); +u32 H264SpsGetVuiHrdBitRate(sps_s * sps); +u32 H264SpsGetVuiHrdCpbSize(sps_s * sps); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264Slice.c b/lib/vc8000nanoe/source/h264/H264Slice.c new file mode 100644 index 000000000..a402ee56f --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Slice.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "H264Slice.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + H264SliceInit + +------------------------------------------------------------------------------*/ +void H264SliceInit(slice_s * slice) +{ + slice->byteStream = ENCHW_YES; + slice->nalUnitType = IDR; + slice->sliceType = ISLICE; + slice->picParameterSetId = 0; + slice->frameNum = 0; + slice->frameNumBits = 16; + slice->idrPicId = 0; + slice->nalRefIdc = 1; + slice->disableDeblocking = 0; + slice->filterOffsetA = -4; + slice->filterOffsetB = 6; + slice->sliceSize = 0; + slice->cabacInitIdc = 0; + slice->quarterPixelMv = 1; + + return; +} diff --git a/lib/vc8000nanoe/source/h264/H264Slice.h b/lib/vc8000nanoe/source/h264/H264Slice.h new file mode 100644 index 000000000..ca01657ec --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264Slice.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : + * + ******************************************************************************** + */ + +#ifndef __H264_SLICE_H__ +#define __H264_SLICE_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "enccommon.h" +#include "H264PutBits.h" +#include "H264NalUnit.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ +typedef enum +{ + PSLICE = 0, + ISLICE = 2, + PSLICES = 5, + ISLICES = 7 +} sliceType_e; + +typedef struct +{ + true_e byteStream; + u32 sliceSize; + sliceType_e sliceType; + nalUnitType_e nalUnitType; + u32 picParameterSetId; + u32 prevFrameNum; + u32 frameNum; + u32 frameNumBits; + u32 idrPicId; + u32 nalRefIdc; + u32 disableDeblocking; + i32 filterOffsetA; + i32 filterOffsetB; + u32 cabacInitIdc; + u32 quarterPixelMv; + u32 fieldOrder; /* 1=top first, 0=bottom first */ +} slice_s; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +void H264SliceInit(slice_s * slice); + +#endif diff --git a/lib/vc8000nanoe/source/h264/H264TestId.c b/lib/vc8000nanoe/source/h264/H264TestId.c new file mode 100644 index 000000000..1969e64e8 --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264TestId.c @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : Encoder setup according to a test vector + * + ******************************************************************************** + */ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "H264TestId.h" + +#include +#include + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ +static void H264FrameQuantizationTest(h264Instance_s *inst); +static void H264SliceTest(h264Instance_s *inst); +static void H264StreamBufferLimitTest(h264Instance_s *inst); +static void H264MbQuantizationTest(h264Instance_s *inst); +static void H264FilterTest(h264Instance_s *inst); +static void H264UserDataTest(h264Instance_s *inst); +static void H264Intra16FavorTest(h264Instance_s *inst); +static void H264InterFavorTest(h264Instance_s *inst); +static void H264RgbInputMaskTest(h264Instance_s *inst); +static void H264MadTest(h264Instance_s *inst); +static void H264MvTest(h264Instance_s *inst); +static void H264DMVPenaltyTest(h264Instance_s *inst); +static void H264MaxOverfillMv(h264Instance_s *inst); +static void H264RoiTest(h264Instance_s *inst); +static void H264IntraAreaTest(h264Instance_s *inst); +static void H264CirTest(h264Instance_s *inst); +static void H264IntraSliceMapTest(h264Instance_s *inst); +static void H264SegmentTest(h264Instance_s *inst); +static void H264RefFrameTest(h264Instance_s *inst); +static void H264TemporalLayerTest(h264Instance_s *inst); +static void H264SegmentMapTest(h264Instance_s *inst); +static void H264PenaltyTest(h264Instance_s *inst); +static void H264DownscalingTest(h264Instance_s *inst); +static void H264TransOverflowTest(h264Instance_s *inst); +static void H264RfcBufOverflowTest(h264Instance_s *inst); +static void H264ToggleMvOut(h264Instance_s *inst); + +/*------------------------------------------------------------------------------ + + TestID defines a test configuration for the encoder. If the encoder control + software is compiled with INTERNAL_TEST flag the test ID will force the + encoder operation according to the test vector. + + TestID Description + 0 No action, normal encoder operation + 1 Frame quantization test, adjust qp for every frame, qp = 0..51 + 2 Slice test, adjust slice amount for each frame + 4 Stream buffer limit test, limit=500 (4kB) for first frame + 6 Quantization test, min and max QP values. + 7 Filter test, set disableDeblocking and filterOffsets A and B + 8 Segment test, set segment map and segment qps + 9 Reference frame test, all combinations of reference and refresh. + 10 Segment map test + 11 Temporal layer test, reference and refresh as with 3 layers + 12 User data test + 15 Intra16Favor test, set to maximum value + 16 Cropping test, set cropping values for every frame + 19 RGB input mask test, set all values + 20 MAD test, test all MAD QP change values + 21 InterFavor test, set to maximum value + 22 MV test, set cropping offsets so that max MVs are tested + 23 DMV penalty test, set to minimum/maximum values + 24 Max overfill MV + 26 ROI test + 27 Intra area test + 28 CIR test + 29 Intra slice map test + 31 Non-zero penalty test, don't use zero penalties + 34 Downscaling test + +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + + H264ConfigureTestBeforeFrame + + Function configures the encoder instance before starting frame encoding + +------------------------------------------------------------------------------*/ +void H264ConfigureTestBeforeFrame(h264Instance_s * inst) +{ + ASSERT(inst); + + switch(inst->testId) + { + case 1: H264FrameQuantizationTest(inst); break; + case 2: H264SliceTest(inst); break; + case 4: H264StreamBufferLimitTest(inst); break; + case 6: H264MbQuantizationTest(inst); break; + case 7: H264FilterTest(inst); break; + case 8: H264SegmentTest(inst); break; + case 9: H264RefFrameTest(inst); break; + case 10: H264SegmentMapTest(inst); break; + case 11: H264TemporalLayerTest(inst); break; + case 12: H264UserDataTest(inst); break; + case 16: + /* do not change vertical offset here in input line buffer mode, because test bench don't know this change */ + if ((!inst->inputLineBuf.inputLineBufEn) || + (!inst->inputLineBuf.inputLineBufLoopBackEn)) + H264CroppingTest(inst); + break; + case 19: H264RgbInputMaskTest(inst); break; + case 20: H264MadTest(inst); break; + case 22: H264MvTest(inst); break; + case 24: H264MaxOverfillMv(inst); break; + case 26: H264RoiTest(inst); break; + case 27: H264IntraAreaTest(inst); break; + case 28: H264CirTest(inst); break; + case 29: H264IntraSliceMapTest(inst); break; + case TID_DOWNSCALING: + H264DownscalingTest(inst); + break; + case TID_RFC_OVERFLOW: + H264RfcBufOverflowTest(inst); + break; + case TID_MVOUT_TOGGLE: + H264ToggleMvOut(inst); + break; + default: break; + } +} + +/*------------------------------------------------------------------------------ + + H264ConfigureTestPenalties + + Function configures the encoder instance before starting frame encoding + +------------------------------------------------------------------------------*/ +void H264ConfigureTestPenalties(h264Instance_s * inst) +{ + ASSERT(inst); + + switch(inst->testId) + { + case 15: H264Intra16FavorTest(inst); break; + case 21: H264InterFavorTest(inst); break; + case 23: H264DMVPenaltyTest(inst); break; + case TID_NONZERO_PANEALTY: + H264PenaltyTest(inst); + break; + case TID_TRANS_OVERFLOW: + H264TransOverflowTest(inst); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------------ + H264QuantizationTest +------------------------------------------------------------------------------*/ +void H264FrameQuantizationTest(h264Instance_s *inst) +{ + i32 vopNum = inst->frameCnt; + + /* Inter frame qp start zero */ + inst->rateControl.qpHdr = MIN(inst->rateControl.qpMax, + MAX(inst->rateControl.qpMin, ((vopNum-1)%52)<< QP_FRACTIONAL_BITS)); + + printf("H264FrameQuantTest# qpHdr %d\n", inst->rateControl.qpHdr >> QP_FRACTIONAL_BITS); +} + +/*------------------------------------------------------------------------------ + H264SliceTest +------------------------------------------------------------------------------*/ +void H264SliceTest(h264Instance_s *inst) +{ + i32 vopNum = inst->frameCnt; + + inst->slice.sliceSize = (inst->mbPerRow*vopNum)%inst->mbPerFrame; + + printf("H264SliceTest# sliceSize %d\n", inst->slice.sliceSize); +} + +/*------------------------------------------------------------------------------ + H264StreamBufferLimitTest +------------------------------------------------------------------------------*/ +void H264StreamBufferLimitTest(h264Instance_s *inst) +{ + static u32 firstFrame = 1; + + if (!firstFrame) + return; + + firstFrame = 0; + inst->asic.regs.outputStrmSize = 4000; + + printf("H264StreamBufferLimitTest# streamBufferLimit %d bytes\n", + inst->asic.regs.outputStrmSize); +} + +/*------------------------------------------------------------------------------ + H264QuantizationTest + NOTE: ASIC resolution for wordCntTarget and wordError is value/4 +------------------------------------------------------------------------------*/ +void H264MbQuantizationTest(h264Instance_s *inst) +{ + i32 vopNum = inst->frameCnt; + h264RateControl_s *rc = &inst->rateControl; + + rc->qpMin = (MIN(51, vopNum/4))<< QP_FRACTIONAL_BITS; + rc->qpMax = (MAX(0, 51 - vopNum/4))<< QP_FRACTIONAL_BITS; + rc->qpMax =( MAX(rc->qpMax, rc->qpMin)); + + rc->qpLastCoded = rc->qpTarget = rc->qpHdr = + MIN(rc->qpMax, MAX(rc->qpMin, 26 << QP_FRACTIONAL_BITS)); + + printf("H264MbQuantTest# min %d max %d QP %d\n", + rc->qpMin >> QP_FRACTIONAL_BITS, rc->qpMax >> QP_FRACTIONAL_BITS, rc->qpHdr >> QP_FRACTIONAL_BITS); +} + +/*------------------------------------------------------------------------------ + H264FilterTest +------------------------------------------------------------------------------*/ +void H264FilterTest(h264Instance_s *inst) +{ + i32 vopNum = inst->frameCnt; + slice_s *slice = &inst->slice; + + slice->disableDeblocking = (vopNum/2)%3; + if (vopNum == 0) { + slice->filterOffsetA = -12; + slice->filterOffsetB = 12; + } else if (vopNum < 77) { + if (vopNum%6 == 0) { + slice->filterOffsetA += 2; + slice->filterOffsetB -= 2; + } + } else if (vopNum == 78) { + slice->filterOffsetA = -12; + slice->filterOffsetB = -12; + } else if (vopNum < 155) { + if (vopNum%6 == 0) { + slice->filterOffsetA += 2; + slice->filterOffsetB += 2; + } + } + + printf("H264FilterTest# disableDeblock = %d, filterOffA = %i filterOffB = %i\n", + slice->disableDeblocking, slice->filterOffsetA, + slice->filterOffsetB); + +} + +/*------------------------------------------------------------------------------ + H264SegmentTest +------------------------------------------------------------------------------*/ +void H264SegmentTest(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + u32 *map = inst->asic.segmentMap.virtualAddress; + u32 mbPerFrame = (inst->mbPerFrame+7)/8*8; /* Rounded upwards to 8 */ + u32 i, j; + u32 mask; + i32 qpSgm[4]; + + inst->asic.regs.segmentEnable = 1; + inst->asic.regs.segmentMapUpdate = 1; + if (frame < 2) { + for (i = 0; i < mbPerFrame/8/4; i++) { + map[i*4+0] = 0x00000000; + map[i*4+1] = 0x11111111; + map[i*4+2] = 0x22222222; + map[i*4+3] = 0x33333333; + } + } else { + for (i = 0; i < mbPerFrame/8; i++) { + mask = 0; + for (j = 0; j < 8; j++) + mask |= ((j + (frame-2)/2 + j*frame/3)%4) << (28-j*4); + map[i] = mask; + } + } + + for (i = 0; i < 4; i++) { + qpSgm[i] = (32 + i + frame/2 + frame*i)%52; + qpSgm[i] = MAX(inst->rateControl.qpMin, + MIN(inst->rateControl.qpMax, qpSgm[i])); + } + inst->rateControl.qpHdr = qpSgm[0]; + inst->rateControl.mbQpAdjustment[0] = MAX(-8, MIN(7, qpSgm[1] - qpSgm[0])); + inst->rateControl.mbQpAdjustment[1] = qpSgm[2] - qpSgm[0]; + inst->rateControl.mbQpAdjustment[2] = qpSgm[3] - qpSgm[0]; + + printf("H264SegmentTest# enable=%d update=%d map=0x%08x%08x%08x%08x\n", + inst->asic.regs.segmentEnable, inst->asic.regs.segmentMapUpdate, + map[0], map[1], map[2], map[3]); + printf("H264SegmentTest# qp=%d,%d,%d,%d\n", + qpSgm[0], qpSgm[1], qpSgm[2], qpSgm[3]); +} + +/*------------------------------------------------------------------------------ + H264RefFrameTest +------------------------------------------------------------------------------*/ +void H264RefFrameTest(h264Instance_s *inst) +{ + i32 pic = inst->frameCnt; + picBuffer *picBuffer = &inst->picBuffer; + + /* Only adjust for p-frames */ + if (picBuffer->cur_pic->p_frame) { + picBuffer->cur_pic->ipf = pic & 0x1 ? 1 : 0; + if (inst->seqParameterSet.numRefFrames > 1) + picBuffer->cur_pic->grf = pic & 0x2 ? 1 : 0; + picBuffer->refPicList[0].search = pic & 0x8 ? 1 : 0; + if (inst->seqParameterSet.numRefFrames > 1) + picBuffer->refPicList[1].search = pic & 0x10 ? 1 : 0; + } + + printf("H264RefFrameTest#\n"); +} + +/*------------------------------------------------------------------------------ + H264TemporalLayerTest +------------------------------------------------------------------------------*/ +void H264TemporalLayerTest(h264Instance_s *inst) +{ + i32 pic = inst->frameCnt; + picBuffer *picBuffer = &inst->picBuffer; + + /* Four temporal layers, base layer (LTR) every 8th frame. */ + if (inst->seqParameterSet.numRefFrames > 1) + picBuffer->cur_pic->grf = pic & 0x7 ? 0 : 1; + if (picBuffer->cur_pic->p_frame) { + /* Odd frames don't update ipf */ + picBuffer->cur_pic->ipf = pic & 0x1 ? 0 : 1; + /* Frames 1,2,3 & 4,5,6 reference prev */ + picBuffer->refPicList[0].search = pic & 0x3 ? 1 : 0; + /* Every fourth frame (layers 0&1) reference LTR */ + if (inst->seqParameterSet.numRefFrames > 1) + picBuffer->refPicList[1].search = pic & 0x3 ? 0 : 1; + } + + printf("H264TemporalLayer#\n"); +} + +/*------------------------------------------------------------------------------ + H264SegmentMapTest +------------------------------------------------------------------------------*/ +void H264SegmentMapTest(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + u32 *map = inst->asic.segmentMap.virtualAddress; + u32 mbPerFrame = (inst->mbPerFrame+7)/8*8; /* Rounded upwards to 8 */ + u32 i, j; + u32 mask; + i32 qpSgm[4]; + + inst->asic.regs.segmentEnable = 1; + inst->asic.regs.segmentMapUpdate = 1; + if (frame < 2) { + for (i = 0; i < mbPerFrame/8; i++) + map[i] = 0x01020120; + } else { + for (i = 0; i < mbPerFrame/8; i++) { + mask = 0; + for (j = 0; j < 8; j++) + mask |= ((j + frame)%4) << (28-j*4); + map[i] = mask; + } + } + + if (frame < 2) { + qpSgm[0] = inst->rateControl.qpMax; + qpSgm[1] = qpSgm[2] = qpSgm[3] = inst->rateControl.qpMin; + } else { + for (i = 0; i < 4; i++) { + qpSgm[i] = (32 + i*frame)%52; + qpSgm[i] = MAX(inst->rateControl.qpMin, + MIN(inst->rateControl.qpMax, qpSgm[i])); + } + } + inst->rateControl.qpHdr = qpSgm[0]; + inst->rateControl.mbQpAdjustment[0] = MAX(-8, MIN(7, qpSgm[1] - qpSgm[0])); + inst->rateControl.mbQpAdjustment[1] = qpSgm[2] - qpSgm[0]; + inst->rateControl.mbQpAdjustment[2] = qpSgm[3] - qpSgm[0]; + + printf("H264SegmentMapTest# enable=%d update=%d map=0x%08x%08x%08x%08x\n", + inst->asic.regs.segmentEnable, inst->asic.regs.segmentMapUpdate, + map[0], map[1], map[2], map[3]); + printf("H264SegmentMapTest# qp=%d,%d,%d,%d\n", + qpSgm[0], qpSgm[1], qpSgm[2], qpSgm[3]); +} + + +/*------------------------------------------------------------------------------ + H264UserDataTest +------------------------------------------------------------------------------*/ +void H264UserDataTest(h264Instance_s *inst) +{ + static u8 *userDataBuf = NULL; + i32 userDataLength = 16 + ((inst->frameCnt*11) % 2000); + i32 i; + + /* Allocate a buffer for user data, encoder reads data from this buffer + * and writes it to the stream. TODO: This is never freed. */ + if (!userDataBuf) + userDataBuf = (u8*)malloc(2048); + + if (!userDataBuf) + return; + + for(i = 0; i < userDataLength; i++) + { + /* Fill user data buffer with ASCII symbols from 48 to 125 */ + userDataBuf[i] = 48 + i % 78; + } + + /* Enable user data insertion */ + inst->rateControl.sei.userDataEnabled = ENCHW_YES; + inst->rateControl.sei.pUserData = userDataBuf; + inst->rateControl.sei.userDataSize = userDataLength; + + printf("H264UserDataTest# userDataSize %d\n", userDataLength); +} + +/*------------------------------------------------------------------------------ + H264Intra16FavorTest +------------------------------------------------------------------------------*/ +void H264Intra16FavorTest(h264Instance_s *inst) +{ + i32 s; + + /* Force intra16 favor to maximum value */ + for (s = 0; s < 4; s++) + inst->asic.regs.pen[s][ASIC_PENALTY_I16FAVOR] = 0xFFFF; + + printf("H264Intra16FavorTest# intra16Favor %d\n", + inst->asic.regs.pen[0][ASIC_PENALTY_I16FAVOR]); +} + +/*------------------------------------------------------------------------------ + H264InterFavorTest +------------------------------------------------------------------------------*/ +void H264InterFavorTest(h264Instance_s *inst) +{ + i32 s; + + /* Force combinations of inter favor and skip penalty values */ + + for (s = 0; s < 4; s++) { + if ((inst->frameCnt % 3) == 0) { + inst->asic.regs.pen[s][ASIC_PENALTY_INTER_FAVOR] = 0x7FFF; + } else if ((inst->frameCnt % 3) == 1) { + inst->asic.regs.pen[s][ASIC_PENALTY_SKIP] = 0; + inst->asic.regs.pen[s][ASIC_PENALTY_INTER_FAVOR] = 0x7FFF; + } else { + inst->asic.regs.pen[s][ASIC_PENALTY_SKIP] = 0; + } + } + + printf("H264InterFavorTest# interFavor %d skipPenalty %d\n", + inst->asic.regs.pen[0][ASIC_PENALTY_INTER_FAVOR], + inst->asic.regs.pen[0][ASIC_PENALTY_SKIP]); +} + +/*------------------------------------------------------------------------------ + H264CroppingTest +------------------------------------------------------------------------------*/ +void H264CroppingTest(h264Instance_s *inst) +{ + inst->preProcess.horOffsetSrc = inst->frameCnt % 16; + if (EncPreProcessCheck(&inst->preProcess) == ENCHW_NOK) + inst->preProcess.horOffsetSrc = 0; + inst->preProcess.verOffsetSrc = inst->frameCnt / 2; + if (EncPreProcessCheck(&inst->preProcess) == ENCHW_NOK) + inst->preProcess.verOffsetSrc = 0; + + printf("H264CroppingTest# horOffsetSrc %d verOffsetSrc %d\n", + inst->preProcess.horOffsetSrc, inst->preProcess.verOffsetSrc); +} + +/*------------------------------------------------------------------------------ + H264RgbInputMaskTest +------------------------------------------------------------------------------*/ +void H264RgbInputMaskTest(h264Instance_s *inst) +{ + u32 frameNum = (u32)inst->frameCnt; + static u32 rMsb = 0; + static u32 gMsb = 0; + static u32 bMsb = 0; + static u32 lsMask = 0; /* Lowest possible mask position */ + static u32 msMask = 0; /* Highest possible mask position */ + + /* First frame normal + * 1..29 step rMaskMsb values + * 30..58 step gMaskMsb values + * 59..87 step bMaskMsb values */ + if (frameNum == 0) { + rMsb = inst->asic.regs.rMaskMsb; + gMsb = inst->asic.regs.gMaskMsb; + bMsb = inst->asic.regs.bMaskMsb; + lsMask = MIN(rMsb, gMsb); + lsMask = MIN(bMsb, lsMask); + msMask = MAX(rMsb, gMsb); + msMask = MAX(bMsb, msMask); + if (msMask < 16) + msMask = 15-2; /* 16bit RGB, 13 mask positions: 3..15 */ + else + msMask = 31-2; /* 32bit RGB, 29 mask positions: 3..31 */ + } else if (frameNum <= msMask) { + inst->asic.regs.rMaskMsb = MAX(frameNum+2, lsMask); + inst->asic.regs.gMaskMsb = gMsb; + inst->asic.regs.bMaskMsb = bMsb; + } else if (frameNum <= msMask*2) { + inst->asic.regs.rMaskMsb = rMsb; + inst->asic.regs.gMaskMsb = MAX(frameNum-msMask+2, lsMask); + if (inst->asic.regs.inputImageFormat == 4) /* RGB 565 special case */ + inst->asic.regs.gMaskMsb = MAX(frameNum-msMask+2, lsMask+1); + inst->asic.regs.bMaskMsb = bMsb; + } else if (frameNum <= msMask*3) { + inst->asic.regs.rMaskMsb = rMsb; + inst->asic.regs.gMaskMsb = gMsb; + inst->asic.regs.bMaskMsb = MAX(frameNum-msMask*2+2, lsMask); + } else { + inst->asic.regs.rMaskMsb = rMsb; + inst->asic.regs.gMaskMsb = gMsb; + inst->asic.regs.bMaskMsb = bMsb; + } + + printf("H264RgbInputMaskTest# %d %d %d\n", inst->asic.regs.rMaskMsb, + inst->asic.regs.gMaskMsb, inst->asic.regs.bMaskMsb); +} + +/*------------------------------------------------------------------------------ + H264MadTest +------------------------------------------------------------------------------*/ +void H264MadTest(h264Instance_s *inst) +{ + u32 frameNum = (u32)inst->frameCnt; + + /* All values in range [-8,7] */ + inst->rateControl.mbQpAdjustment[0] = -8 + (frameNum%16); + inst->rateControl.mbQpAdjustment[1] = -127 + (frameNum%254); + inst->rateControl.mbQpAdjustment[2] = 127 - (frameNum%254); + /* Step 256, range [0,63*256] */ + inst->mad.threshold[0] = 256 * ((frameNum+1)%64); + inst->mad.threshold[1] = 256 * ((frameNum/2)%64); + inst->mad.threshold[2] = 256 * ((frameNum/3)%64); + + printf("H264MadTest# Thresholds: %d,%d,%d QpDeltas: %d,%d,%d\n", + inst->asic.regs.madThreshold[0], + inst->asic.regs.madThreshold[1], + inst->asic.regs.madThreshold[2], + inst->rateControl.mbQpAdjustment[0], + inst->rateControl.mbQpAdjustment[1], + inst->rateControl.mbQpAdjustment[2]); +} + +/*------------------------------------------------------------------------------ + H264MvTest +------------------------------------------------------------------------------*/ +void H264MvTest(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + + /* Set cropping offsets according to max MV length, decrement by frame + * x = 32, 160, 32, 159, 32, 158, .. + * y = 48, 80, 48, 79, 48, 78, .. */ + inst->preProcess.horOffsetSrc = 32 + (frame%2)*128 - (frame%2)*(frame/2); + if (EncPreProcessCheck(&inst->preProcess) == ENCHW_NOK) + inst->preProcess.horOffsetSrc = 0; + inst->preProcess.verOffsetSrc = 48 + (frame%2)*32 - (frame%2)*(frame/2); + if (EncPreProcessCheck(&inst->preProcess) == ENCHW_NOK) + inst->preProcess.verOffsetSrc = 0; + + printf("H264MvTest# horOffsetSrc %d verOffsetSrc %d\n", + inst->preProcess.horOffsetSrc, inst->preProcess.verOffsetSrc); +} + +/*------------------------------------------------------------------------------ + H264DMVPenaltyTest +------------------------------------------------------------------------------*/ +void H264DMVPenaltyTest(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + i32 s; + + /* Set DMV penalty values to maximum and minimum */ + for (s = 0; s < 4; s++) { + inst->asic.regs.pen[s][ASIC_PENALTY_DMV_4P] = frame%2 ? 127-frame/2 : frame/2; + inst->asic.regs.pen[s][ASIC_PENALTY_DMV_1P] = frame%2 ? 127-frame/2 : frame/2; + inst->asic.regs.pen[s][ASIC_PENALTY_DMV_QP] = frame%2 ? 127-frame/2 : frame/2; + } + + printf("H264DMVPenaltyTest# penalty4p %d penalty1p %d penaltyQp %d\n", + inst->asic.regs.pen[0][ASIC_PENALTY_DMV_4P], + inst->asic.regs.pen[0][ASIC_PENALTY_DMV_1P], + inst->asic.regs.pen[0][ASIC_PENALTY_DMV_QP]); +} + +/*------------------------------------------------------------------------------ + H264MaxOverfillMv +------------------------------------------------------------------------------*/ +void H264MaxOverfillMv(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + + /* Set cropping offsets according to max MV length. + * In test cases the picture is selected so that this will + * cause maximum horizontal MV to point into overfilled area. */ + inst->preProcess.horOffsetSrc = 32 + (frame%2)*128; + if (EncPreProcessCheck(&inst->preProcess) == ENCHW_NOK) + inst->preProcess.horOffsetSrc = 0; + + inst->preProcess.verOffsetSrc = 176; + if (EncPreProcessCheck(&inst->preProcess) == ENCHW_NOK) + inst->preProcess.verOffsetSrc = 0; + + printf("H264MaxOverfillMv# horOffsetSrc %d verOffsetSrc %d\n", + inst->preProcess.horOffsetSrc, inst->preProcess.verOffsetSrc); +} + +/*------------------------------------------------------------------------------ + H264RoiTest +------------------------------------------------------------------------------*/ +void H264RoiTest(h264Instance_s *inst) +{ + regValues_s *regs = &inst->asic.regs; + u32 frame = (u32)inst->frameCnt; + u32 mbPerRow = inst->mbPerRow; + u32 mbPerCol = inst->mbPerCol; + u32 frames = MIN(mbPerRow, mbPerCol); + u32 loop = frames*3; + + /* Loop after this many encoded frames */ + frame = frame % loop; + + regs->roi1DeltaQp = (frame % 15) + 1; + regs->roi2DeltaQp = 15 - (frame % 15); + regs->roiUpdate = 1; + + /* Set two ROI areas according to frame dimensions. */ + if (frame < frames) + { + /* ROI1 in top-left corner, ROI2 in bottom-right corner */ + regs->roi1Left = regs->roi1Top = 0; + regs->roi1Right = regs->roi1Bottom = frame; + regs->roi2Left = mbPerRow - 1 - frame; + regs->roi2Top = mbPerCol - 1 - frame; + regs->roi2Right = mbPerRow - 1; + regs->roi2Bottom = mbPerCol - 1; + } + else if (frame < frames*2) + { + /* ROI1 gets smaller towards top-right corner, + * ROI2 towards bottom-left corner */ + frame -= frames; + regs->roi1Left = frame; + regs->roi1Top = 0; + regs->roi1Right = mbPerRow - 1; + regs->roi1Bottom = mbPerCol - 1 - frame; + regs->roi2Left = 0; + regs->roi2Top = frame; + regs->roi2Right = mbPerRow - 1 - frame; + regs->roi2Bottom = mbPerCol - 1; + } + else if (frame < frames*3) + { + /* 1x1/2x2 ROIs moving diagonal across frame */ + frame -= frames*2; + regs->roi1Left = frame - frame%2; + regs->roi1Right = frame; + regs->roi1Top = frame - frame%2; + regs->roi1Bottom = frame; + regs->roi2Left = frame - frame%2; + regs->roi2Right = frame; + regs->roi2Top = mbPerCol - 1 - frame; + regs->roi2Bottom = mbPerCol - 1 - frame + frame%2; + } + + printf("H264RoiTest# ROI1:%d x%dy%d-x%dy%d ROI2:%d x%dy%d-x%dy%d\n", + regs->roi1DeltaQp, regs->roi1Left, regs->roi1Top, + regs->roi1Right, regs->roi1Bottom, + regs->roi2DeltaQp, regs->roi2Left, regs->roi2Top, + regs->roi2Right, regs->roi2Bottom); +} + +/*------------------------------------------------------------------------------ + H264IntraAreaTest +------------------------------------------------------------------------------*/ +void H264IntraAreaTest(h264Instance_s *inst) +{ + regValues_s *regs = &inst->asic.regs; + u32 frame = (u32)inst->frameCnt; + u32 mbPerRow = inst->mbPerRow; + u32 mbPerCol = inst->mbPerCol; + u32 frames = MIN(mbPerRow, mbPerCol); + u32 loop = frames*3; + + /* Loop after this many encoded frames */ + frame = frame % loop; + + if (frame < frames) + { + /* Intra area in top-left corner, gets bigger every frame */ + regs->intraAreaLeft = regs->intraAreaTop = 0; + regs->intraAreaRight = regs->intraAreaBottom = frame; + } + else if (frame < frames*2) + { + /* Intra area gets smaller towards top-right corner */ + frame -= frames; + regs->intraAreaLeft = frame; + regs->intraAreaTop = 0; + regs->intraAreaRight = mbPerRow - 1; + regs->intraAreaBottom = mbPerCol - 1 - frame; + } + else if (frame < frames*3) + { + /* 1x1/2x2 Intra area moving diagonal across frame */ + frame -= frames*2; + regs->intraAreaLeft = frame - frame%2; + regs->intraAreaRight = frame; + regs->intraAreaTop = frame - frame%2; + regs->intraAreaBottom = frame; + } + + printf("H264IntraAreaTest# x%dy%d-x%dy%d\n", + regs->intraAreaLeft, regs->intraAreaTop, + regs->intraAreaRight, regs->intraAreaBottom); +} + +/*------------------------------------------------------------------------------ + H264CirTest +------------------------------------------------------------------------------*/ +void H264CirTest(h264Instance_s *inst) +{ + regValues_s *regs = &inst->asic.regs; + u32 frame = (u32)inst->frameCnt; + u32 mbPerRow = inst->mbPerRow; + u32 mbPerFrame = inst->mbPerFrame; + u32 loop = inst->mbPerFrame+6; + + /* Loop after this many encoded frames */ + frame = frame % loop; + + switch (frame) + { + case 0: + case 1: + regs->cirStart = 0; + regs->cirInterval = 1; + break; + case 2: + regs->cirStart = 0; + regs->cirInterval = 2; + break; + case 3: + regs->cirStart = 0; + regs->cirInterval = 3; + break; + case 4: + regs->cirStart = 0; + regs->cirInterval = mbPerRow; + break; + case 5: + regs->cirStart = 0; + regs->cirInterval = mbPerRow+1; + break; + case 6: + regs->cirStart = 0; + regs->cirInterval = mbPerFrame-1; + break; + case 7: + regs->cirStart = mbPerFrame-1; + regs->cirInterval = 1; + break; + default: + regs->cirStart = frame-7; + regs->cirInterval = (mbPerFrame-frame)%(mbPerRow*2); + break; + } + + printf("H264CirTest# start:%d interval:%d\n", + regs->cirStart, regs->cirInterval); +} + +/*------------------------------------------------------------------------------ + H264IntraSliceMapTest +------------------------------------------------------------------------------*/ +void H264IntraSliceMapTest(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + u32 mbPerCol = inst->mbPerCol; + + frame = frame % (mbPerCol*10); + + if (frame <= 1) + { + inst->slice.sliceSize = inst->mbPerRow; + inst->intraSliceMap[0] = 0x55555555; + inst->intraSliceMap[1] = 0x55555555; + inst->intraSliceMap[2] = 0x55555555; + } + else if (frame < mbPerCol+1) + { + inst->slice.sliceSize = inst->mbPerRow * (frame-1); + inst->intraSliceMap[0] = 0xAAAAAAAA; + inst->intraSliceMap[1] = 0xAAAAAAAA; + inst->intraSliceMap[2] = 0xAAAAAAAA; + } + else + { + inst->slice.sliceSize = inst->mbPerRow * (frame%mbPerCol); + inst->intraSliceMap[0] += frame; + inst->intraSliceMap[1] += frame; + inst->intraSliceMap[2] += frame; + } + + printf("H264IntraSliceMapTest# " + "sliceSize: %d map1: 0x%x map2: 0x%x map3: 0x%x \n", + inst->slice.sliceSize, inst->intraSliceMap[0], + inst->intraSliceMap[1], inst->intraSliceMap[2]); +} + +/*------------------------------------------------------------------------------ + H264PenaltyTest +------------------------------------------------------------------------------*/ +void H264PenaltyTest(h264Instance_s *inst) +{ + i32 s; + + inst->asic.regs.inputReadChunk = 1; + + /* Set non-zero values */ + for (s = 0; s < 4; s++) { + inst->asic.regs.pen[s][ASIC_PENALTY_SPLIT16x8] = 1; + inst->asic.regs.pen[s][ASIC_PENALTY_SPLIT8x8] = 2; + inst->asic.regs.pen[s][ASIC_PENALTY_SPLIT8x4] = 3; + inst->asic.regs.pen[s][ASIC_PENALTY_SPLIT4x4] = 4; + inst->asic.regs.pen[s][ASIC_PENALTY_SPLIT_ZERO] = 5; + } + + printf("H264PenaltyTest# splitPenalty %d %d %d %d %d\n", + inst->asic.regs.pen[0][ASIC_PENALTY_SPLIT16x8], + inst->asic.regs.pen[0][ASIC_PENALTY_SPLIT8x8], + inst->asic.regs.pen[0][ASIC_PENALTY_SPLIT8x4], + inst->asic.regs.pen[0][ASIC_PENALTY_SPLIT4x4], + inst->asic.regs.pen[0][ASIC_PENALTY_SPLIT_ZERO]); +} + +/*------------------------------------------------------------------------------ + H264Downscaling +------------------------------------------------------------------------------*/ +void H264DownscalingTest(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + u32 xy = MIN(inst->preProcess.lumWidth, inst->preProcess.lumHeight); + + if (!frame) return; + + if (frame <= xy/2) { + inst->preProcess.scaledWidth = inst->preProcess.lumWidth - (frame/2)*4; + inst->preProcess.scaledHeight = inst->preProcess.lumHeight - frame*2; + } else { + u32 i, x, y; + i = frame - xy/2; + x = i%(inst->preProcess.lumWidth/8); + y = i/(inst->preProcess.lumWidth/8); + inst->preProcess.scaledWidth = inst->preProcess.lumWidth - x*8; + inst->preProcess.scaledHeight = inst->preProcess.lumHeight - y*8; + } + + if (!inst->preProcess.scaledWidth) + inst->preProcess.scaledWidth = inst->preProcess.lumWidth - 4; + + if (!inst->preProcess.scaledHeight) + inst->preProcess.scaledHeight = inst->preProcess.lumHeight - 4; + + printf("H264DownscalingTest# %dx%d => %dx%d\n", + inst->preProcess.lumWidth, inst->preProcess.lumHeight, + inst->preProcess.scaledWidth, inst->preProcess.scaledHeight); +} + +/*------------------------------------------------------------------------------ + H264InputLineBufDepthTest +------------------------------------------------------------------------------*/ +void H264InputLineBufDepthTest(h264Instance_s *inst) +{ + u32 maxDepth = inst->mbPerCol; + /* limitation: ((line buffer height/16) * (frame width/16)) % 4 == 0 */ + i32 tail = inst->mbPerRow & 3; + i32 align = 1; + if (tail == 2) align = 2; + else if (tail&1) align = 4; + + if ((!inst->inputLineBuf.inputLineBufLoopBackEn) && + (!inst->inputLineBuf.inputLineBufHwModeEn)) return; + + if (inst->inputLineBuf.inputLineBufLoopBackEn) + { + const u32 maxLineBufSize = 0x100000; + u32 stride = inst->preProcess.lumWidthSrc * (inst->preProcess.interlacedFrame ? 2 : 1); + u32 mbLineSize = stride*16*H264EncGetBitsPerPixel(inst->preProcess.inputFormat)/8; + maxDepth = MIN(maxDepth, maxLineBufSize/mbLineSize/2); + } + maxDepth = maxDepth / align; + + /* frame 0 use user config */ + if (inst->frameCnt > 0) + { + u32 depth = inst->inputLineBuf.inputLineBufDepth; + u32 nFrm = inst->frameCnt - 1; + inst->inputLineBuf.inputLineBufDepth = (nFrm%maxDepth) + 1; + inst->inputLineBuf.inputLineBufDepth *= align; + + printf("inputLineBufTest# depth changed from %d to %d for next frame \n", + depth, inst->inputLineBuf.inputLineBufDepth); + } +} + +/*------------------------------------------------------------------------------ + H264RfcBufOverflowTest +------------------------------------------------------------------------------*/ +void H264RfcBufOverflowTest(h264Instance_s *inst) +{ + u32 lumLimit[16] = {30, 70, 0, 40, 55, 75, 55, 0, 80, 70, 65, 60, 50, 45, 35, 30}; + u32 chrLimit[16] = {70, 25, 0, 30, 45, 65, 0, 45, 70, 60, 55, 50, 40, 35, 25, 20}; + u32 idx = inst->frameCnt & 0xf; + + if (inst->asic.regs.refLumCompress) + inst->asic.regs.rfcLumBufLimit = inst->mbPerCol*inst->mbPerRow*256*lumLimit[idx]/100; + + if (inst->asic.regs.refChrCompress) + inst->asic.regs.rfcChrBufLimit = inst->mbPerCol*inst->mbPerRow*128*chrLimit[idx]/100; + + inst->asic.regs.rfcLumBufLimit /= 8; + inst->asic.regs.rfcChrBufLimit /= 8; + + printf("H264RfcBufOverflowTest# lumLimit = %d%%; chrLimit = %d%%\n", lumLimit[idx], chrLimit[idx]); +} + +/*------------------------------------------------------------------------------ + H264TransOverflowTest +------------------------------------------------------------------------------*/ +void H264TransOverflowTest(h264Instance_s *inst) +{ + i32 s; + + /* Set large InterFavor register to make more InterMB. + * it makes the overflow happens. */ + + for (s = 0; s < 4; s++) { + inst->asic.regs.pen[s][ASIC_PENALTY_INTER_FAVOR] = 32200; + } + + printf("H264TransOverflowTest# interFavor %d\n", + inst->asic.regs.pen[0][ASIC_PENALTY_INTER_FAVOR]); +} + +/*------------------------------------------------------------------------------ + H264ToggleMvOut +------------------------------------------------------------------------------*/ +void H264ToggleMvOut(h264Instance_s *inst) +{ + u32 frame = (u32)inst->frameCnt; + u32 pattern[4] = {0, 1, 1, 0}; + + /* set swreg HEncMvWrite as 0-1-1-0 patter according to frameCnt%4. + * so when recon output pattern is 1-0-1-0, full combination will be + * tested. */ + inst->asic.regs.mvOutEnable = pattern[frame%4]; + + printf("H264ToggleMvOut# mvWrite=%d\n", inst->asic.regs.mvOutEnable); +} + +#if 0 +/*------------------------------------------------------------------------------ + MbPerInterruptTest +------------------------------------------------------------------------------*/ +void MbPerInterruptTest(trace_s *trace) +{ + if (trace->testId != 3) { + return; + } + + trace->control.mbPerInterrupt = trace->vopNum; +} + +/*------------------------------------------------------------------------------ +H264FilterTest +------------------------------------------------------------------------------*/ +void H264FilterTest(trace_s *trace, slice_s *slice) +{ + i32 vopNum = trace->vopNum; + + if (trace->testId != 7) { + return; + } + + slice->disableDeblocking = (vopNum/2)%3; + if (vopNum == 0) { + slice->filterOffsetA = -12; + slice->filterOffsetB = 12; + } else if (vopNum < 77) { + if (vopNum%6 == 0) { + slice->filterOffsetA += 2; + slice->filterOffsetB -= 2; + } + } else if (vopNum == 78) { + slice->filterOffsetA = -12; + slice->filterOffsetB = -12; + } else if (vopNum < 155) { + if (vopNum%6 == 0) { + slice->filterOffsetA += 2; + slice->filterOffsetB += 2; + } + } +} + +/*------------------------------------------------------------------------------ +H264SliceQuantTest() Change sliceQP from min->max->min. +------------------------------------------------------------------------------*/ +void H264SliceQuantTest(trace_s *trace, slice_s *slice, mb_s *mb, + rateControl_s *rc) +{ + if (trace->testId != 8) { + return; + } + + rc->vopRc = NO; + rc->mbRc = NO; + rc->picSkip = NO; + + if (mb->qpPrev == rc->qpMin) { + mb->qpLum = rc->qpMax; + } else if (mb->qpPrev == rc->qpMax) { + mb->qpLum = rc->qpMin; + } else { + mb->qpLum = rc->qpMax; + } + + mb->qpCh = qpCh[MIN(51, MAX(0, mb->qpLum + mb->chromaQpOffset))]; + rc->qp = rc->qpHdr = mb->qpLum; + slice->sliceQpDelta = mb->qpLum - slice->picInitQpMinus26 - 26; +} + +#endif + diff --git a/lib/vc8000nanoe/source/h264/H264TestId.h b/lib/vc8000nanoe/source/h264/H264TestId.h new file mode 100644 index 000000000..4abb6dcfe --- /dev/null +++ b/lib/vc8000nanoe/source/h264/H264TestId.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Description : Encoder setup according to a test vector + * + ******************************************************************************** + */ + +#ifndef __H264_TESTID_H__ +#define __H264_TESTID_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "basetype.h" +#include "H264Instance.h" +#include "H264Slice.h" +#include "H264RateControl.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + TestID defines a test configuration for the encoder. If the encoder control + software is compiled with INTERNAL_TEST flag the test ID will force the + encoder operation according to the test vector. + + TestID Description + 0 No action, normal encoder operation + 1 Frame quantization test, adjust qp for every frame, qp = 0..51 + 2 Slice test, adjust slice amount for each frame + 4 Stream buffer limit test, limit=500 (4kB) for first frame + 6 Quantization test, min and max QP values. + 7 Filter test, set disableDeblocking and filterOffsets A and B + 8 Segment test, set segment map and segment qps + 9 Reference frame test, all combinations of reference and refresh. + 10 Segment map test + 11 Temporal layer test, reference and refresh as with 3 layers + 12 User data test + 15 Intra16Favor test, set to maximum value + 16 Cropping test, set cropping values for every frame + 19 RGB input mask test, set all values + 20 MAD test, test all MAD QP change values + 21 InterFavor test, set to maximum value + 22 MV test, set cropping offsets so that max MVs are tested + 23 DMV penalty test, set to minimum/maximum values + 24 Max overfill MV + 26 ROI test + 27 Intra area test + 28 CIR test + 29 Intra slice map test + 31 Non-zero penalty test, don't use zero penalties + 34 Downscaling test + +------------------------------------------------------------------------------*/ +enum +{ + TID_NONZERO_PANEALTY=31, /* 31 Non-zero penalty test, don't use zero penalties */ + TID_DOWNSCALING=34, /* 34 Downscaling test */ + TID_INPUT_BUFFER=35, /* 35 */ + TID_RFC_OVERFLOW=36, + TID_TRANS_OVERFLOW=37, + TID_MVOUT_TOGGLE, /* 38 Toggle MV Output */ + TID_COUNT_MAX +}; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void H264ConfigureTestBeforeFrame(h264Instance_s * inst); +void H264ConfigureTestPenalties(h264Instance_s * inst); +void H264InputLineBufDepthTest(h264Instance_s *inst); +void H264CroppingTest(h264Instance_s *inst); + +#endif diff --git a/lib/vc8000nanoe/source/h264/h264encapi_ext.c b/lib/vc8000nanoe/source/h264/h264encapi_ext.c new file mode 100644 index 000000000..d31dc1bce --- /dev/null +++ b/lib/vc8000nanoe/source/h264/h264encapi_ext.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015-2022, Verisilicon Inc. - All Rights Reserved + * Copyright (c) 2011-2014, Google Inc. - All Rights Reserved + * + * + ******************************************************************************** + * + * This software is distributed under the terms of + * BSD-3-Clause. The following provisions apply : + * + ******************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************** + * + * Abstract : H264 Encoder Extended API (just for testing) + * + ******************************************************************************** + */ +#include "h264encapi.h" +#include "h264encapi_ext.h" +#include "H264Instance.h" +#include "H264TestId.h" + +H264EncRet H264EncSetFilter(H264EncInst inst, const H264EncFilter * pEncCfg) +{ + + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + if(pEncInst->picParameterSet.deblockingFilterControlPresent == ENCHW_NO) + return H264ENC_INVALID_STATUS; + + pEncInst->slice.disableDeblocking = pEncCfg->disableDeblocking; + +#if 0 + if(pEncCfg->disableDeblocking != 1) + { + pEncInst->slice.filterOffsetA = pEncCfg->filterOffsetA; + pEncInst->slice.filterOffsetB = pEncCfg->filterOffsetB; + } + else + { + pEncInst->slice.filterOffsetA = 0; + pEncInst->slice.filterOffsetB = 0; + } +#else + pEncInst->slice.filterOffsetA = pEncCfg->filterOffsetA; + pEncInst->slice.filterOffsetB = pEncCfg->filterOffsetB; +#endif + + return H264ENC_OK; +} + +H264EncRet H264EncGetFilter(H264EncInst inst, H264EncFilter * pEncCfg) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + pEncCfg->disableDeblocking = pEncInst->slice.disableDeblocking; + pEncCfg->filterOffsetA = pEncInst->slice.filterOffsetA; + pEncCfg->filterOffsetB = pEncInst->slice.filterOffsetB; + + return H264ENC_OK; +} + +H264EncRet H264EncSetChromaQpIndexOffset(H264EncInst inst, i32 offset) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + ASSERT(inst != NULL); + + if(offset < -12 || offset > 12) + { + return H264ENC_INVALID_ARGUMENT; + } + + /* Check status, only INIT is allowed */ + if(pEncInst->encStatus != H264ENCSTAT_INIT) + { + return H264ENC_INVALID_STATUS; + } + + pEncInst->picParameterSet.chromaQpIndexOffset = offset; + + return H264ENC_OK; +} + +H264EncRet H264EncSetHwBurstSize(H264EncInst inst, u32 burst) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + ASSERT(inst != NULL); + ASSERT(burst < 64); + + pEncInst->asic.regs.asicCfgReg &= ~(63 << 8); + pEncInst->asic.regs.asicCfgReg |= ((burst & (63)) << 8); + + return H264ENC_OK; +} + +H264EncRet H264EncSetHwBurstType(H264EncInst inst, u32 bursttype) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + ASSERT(inst != NULL); + + pEncInst->asic.regs.asicCfgReg &= ~(1 << 6); + pEncInst->asic.regs.asicCfgReg |= ((bursttype & (1)) << 6); + + return H264ENC_OK; +} + +H264EncRet H264EncTestInputLineBuf(H264EncInst inst) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + ASSERT(inst != NULL); + + H264InputLineBufDepthTest(pEncInst); + + return H264ENC_OK; +} + +H264EncRet H264EncTestCropping(H264EncInst inst) +{ + h264Instance_s *pEncInst = (h264Instance_s *) inst; + + ASSERT(inst != NULL); + + H264CroppingTest(pEncInst); + + return H264ENC_OK; +} + diff --git a/lib/vc8000nanoe/st_readme.txt b/lib/vc8000nanoe/st_readme.txt new file mode 100644 index 000000000..133608b4e --- /dev/null +++ b/lib/vc8000nanoe/st_readme.txt @@ -0,0 +1,60 @@ + + @verbatim + ****************************************************************************** + * + * Copyright (C) 2015-2022, Verisilicon Inc. - All Rights Reserved + * + * Copyright (C) 2011-2014, Google Inc. - All Rights Reserved + * + * @file st_readme.txt + * @author GPM Application Team + * @brief This file lists the main modification done by STMicroelectronics on + * VERISILICON Video Encoder software package. + ****************************************************************************** + * + * Original licensing conditions by Verisilicon Inc. + * + * "This software is dual licensed, either GPL-2.0 or BSD-3-Clause, at your + * option." + * + ****************************************************************************** + @endverbatim + + +### 22-October-2024 ### +========================= + + Add fuse error handling + in \inc\h264encapi.h + in \source\common\encasiccontroller.c + in \source\h264\H264CodeFrame.c + in \source\h264\H264CodeFrame.h + in \source\h264\H264EncApi.c + + Change include files order to avoid typedef conflicts + in \source\h264\H264EncApi.c + in \source\h264\H264Init.c + + +### 25-June-2024 ### +========================= + + Fix output overflow bug + lower output buffer size in \source\common\encasiccontroller.c + + +### 08-December-2023 ### +========================= + + Correct input RGB32 endianness + Set ENCH1_INPUT_SWAP_32_RGB32 to 1 in \source\common\enccfg.h + + +### 29-September-2023 ### +========================= + + Deliver VERISILICON VC8000NanoE SW package + Version: 9.22.3.7 + Release Date: Nov. 07.2022 + + Delivery of software header (.h) and source (.c) files. + License set to BSD 3-Clause license. + + + +