diff --git a/packages/mediacenter/kodi-binary-addons/inputstream.adaptive/package.mk b/packages/mediacenter/kodi-binary-addons/inputstream.adaptive/package.mk index 119dadb31b..df9ce0bcb2 100644 --- a/packages/mediacenter/kodi-binary-addons/inputstream.adaptive/package.mk +++ b/packages/mediacenter/kodi-binary-addons/inputstream.adaptive/package.mk @@ -17,8 +17,8 @@ ################################################################################ PKG_NAME="inputstream.adaptive" -PKG_VERSION="b28d3f0" -PKG_SHA256="83103097ee933b8794bc50bcfa601715ff5e819e81778bcbc50403f6fb5f8182" +PKG_VERSION="29ba406" +PKG_SHA256="f9bc404dd06e205c15418b28b650648737b666254870ae91e3789103a9347e21" PKG_LICENSE="GPL" PKG_SITE="http://www.kodi.tv" PKG_URL="https://github.com/peak3d/inputstream.adaptive/archive/$PKG_VERSION.tar.gz" diff --git a/packages/mediacenter/kodi-binary-addons/inputstream.rtmp/package.mk b/packages/mediacenter/kodi-binary-addons/inputstream.rtmp/package.mk index 6cfdef87f0..6ce40b33ec 100644 --- a/packages/mediacenter/kodi-binary-addons/inputstream.rtmp/package.mk +++ b/packages/mediacenter/kodi-binary-addons/inputstream.rtmp/package.mk @@ -17,8 +17,8 @@ ################################################################################ PKG_NAME="inputstream.rtmp" -PKG_VERSION="b3ffc49" -PKG_SHA256="99e2c4b168a1026a2c0683894700e85210990f7c4ed9d3068c15101116dc6273" +PKG_VERSION="eba92bd" +PKG_SHA256="3fa2601f26523350252fa09e08bd66cfa94f4810e37b8cdeff8d2657d33d6bf7" PKG_LICENSE="GPL" PKG_SITE="http://www.kodi.tv" PKG_URL="https://github.com/notspiff/inputstream.rtmp/archive/$PKG_VERSION.tar.gz" diff --git a/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk b/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk index 5f497408b4..15d7e462ab 100644 --- a/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk +++ b/packages/mediacenter/kodi-binary-addons/peripheral.joystick/package.mk @@ -17,8 +17,8 @@ ################################################################################ PKG_NAME="peripheral.joystick" -PKG_VERSION="02da6ed" -PKG_SHA256="3c0a8443cc0a0b177ba94d1a2288d57ea20860bee7450411674539d8e8583687" +PKG_VERSION="12e7d52" +PKG_SHA256="2d66199dee46afddfaede1ffbe2aa5691f5441b5dcf54cb0e3d3059a95c34c61" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi-binary-addons/pvr.mythtv/package.mk b/packages/mediacenter/kodi-binary-addons/pvr.mythtv/package.mk index 99d06d29b4..c47077fdcf 100644 --- a/packages/mediacenter/kodi-binary-addons/pvr.mythtv/package.mk +++ b/packages/mediacenter/kodi-binary-addons/pvr.mythtv/package.mk @@ -17,8 +17,8 @@ ################################################################################ PKG_NAME="pvr.mythtv" -PKG_VERSION="3200b09" -PKG_SHA256="8e9443c386cbc4183e74f100aa7dd968310b8b8739d7a4640d8f69c31d3c20e8" +PKG_VERSION="59ff911" +PKG_SHA256="18a530c022e991b03c981563d6f3e2c56093ca9d2aadf760ba895165852b2d0c" PKG_REV="2" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi-platform/package.mk b/packages/mediacenter/kodi-platform/package.mk index b2b2b2a79a..dbea051339 100644 --- a/packages/mediacenter/kodi-platform/package.mk +++ b/packages/mediacenter/kodi-platform/package.mk @@ -17,8 +17,8 @@ ################################################################################ PKG_NAME="kodi-platform" -PKG_VERSION="36fb493" -PKG_SHA256="c53f37888d752e233f5adabc6ecfb8a1ea02728e010007200bbf671f6b9462de" +PKG_VERSION="e8574b8" +PKG_SHA256="132d5398b3bb72c6b5394ffa473c52e556419d6df8c52eb0830555dae87eb75a" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://www.kodi.tv" diff --git a/packages/mediacenter/kodi/package.mk b/packages/mediacenter/kodi/package.mk index e2cf42dad7..591c7914fc 100644 --- a/packages/mediacenter/kodi/package.mk +++ b/packages/mediacenter/kodi/package.mk @@ -17,8 +17,8 @@ ################################################################################ PKG_NAME="kodi" -PKG_VERSION="f5871d9" -PKG_SHA256="1762381765e5fcecdf4923ed4d02bacba079136b21782f8b3fb17170e423f0f1" +PKG_VERSION="89a53e4" +PKG_SHA256="26b7a02af4853f89d48276ec0dbd39d3c3599734b4184179339d45640a2081c3" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://www.kodi.tv" @@ -203,7 +203,7 @@ KODI_LIBDVD="$KODI_DVDCSS \ -DLIBDVDREAD_URL=$SOURCES/libdvdread/libdvdread-$(get_pkg_version libdvdread).tar.gz" # Build Kodi using parallel LTO -[ "$LTO_SUPPORT" = "yes" -a "$DEBUG" != "yes" ] && PKG_KODI_USE_LTO="-DUSE_LTO=$CONCURRENCY_MAKE_LEVEL" +[ "$LTO_SUPPORT" = "yes" ] && ! build_with_debug && PKG_KODI_USE_LTO="-DUSE_LTO=$CONCURRENCY_MAKE_LEVEL" PKG_CMAKE_OPTS_TARGET="-DNATIVEPREFIX=$TOOLCHAIN \ -DWITH_TEXTUREPACKER=$TOOLCHAIN/bin/TexturePacker \ diff --git a/packages/mediacenter/kodi/patches/kodi-999.99-PR13552.patch b/packages/mediacenter/kodi/patches/kodi-999.99-PR13552.patch deleted file mode 100644 index d3d8032ec2..0000000000 --- a/packages/mediacenter/kodi/patches/kodi-999.99-PR13552.patch +++ /dev/null @@ -1,349 +0,0 @@ -From ec9e4d1fe085d585b6107fb0bb27645506b540f3 Mon Sep 17 00:00:00 2001 -From: Alex Deryskyba -Date: Thu, 15 Feb 2018 21:48:16 +0200 -Subject: [PATCH] amlcodec: cleanup and simplify 3D handling code - ---- - .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 178 ++++----------------- - xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 7 +- - xbmc/utils/AMLUtils.cpp | 20 --- - xbmc/utils/AMLUtils.h | 1 - - 4 files changed, 30 insertions(+), 176 deletions(-) - -diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp -index d83fbda65bd4..d8a14fed1a25 100644 ---- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp -@@ -55,8 +55,7 @@ - - // amcodec include - extern "C" { --#include --#include -+#include - } // extern "C" - - CEvent g_aml_sync_event; -@@ -346,44 +345,6 @@ typedef struct vframe_states - int buf_avail_num; - } vframe_states_t; - --static int aml_ioctl_get(CODEC_HANDLE h, int subcmd, unsigned long paramter) --{ -- struct am_ioctl_parm parm; -- memset(&parm, 0, sizeof(parm)); -- parm.cmd = subcmd; -- parm.data_32 = *(unsigned int *)paramter; -- if (ioctl(h, AMSTREAM_IOC_GET, (unsigned long)&parm) < 0) -- { -- CLog::Log(LOGERROR, "aml_ioctl_get failed: subcmd=%x, errno=%d", subcmd, errno); -- return -1; -- } -- *(unsigned int *)paramter = parm.data_32; -- return 0; --} -- -- --#ifndef AMSTREAM_IOC_MAGIC --#define AMSTREAM_IOC_MAGIC 'S' --#endif -- --#ifndef AMSTREAM_IOC_VF_STATUS --#define AMSTREAM_IOC_VF_STATUS _IOR(AMSTREAM_IOC_MAGIC, 0x60, unsigned long) --#endif -- --#ifndef AMSTREAM_IOC_GET_3D_TYPE --#define AMSTREAM_IOC_GET_3D_TYPE _IOW((AMSTREAM_IOC_MAGIC), 0x3d, unsigned int) --#endif -- -- --enum --{ -- VPP_3D_MODE_NULL = 0, -- VPP_3D_MODE_LR, -- VPP_3D_MODE_TB, -- VPP_3D_MODE_LA, -- VPP_3D_MODE_FA --}; -- - /*************************************************************************/ - /*************************************************************************/ - void dumpfile_open(am_private_t *para) -@@ -2264,53 +2225,21 @@ void CAMLCodec::SetVideoSaturation(const int saturation) - SysfsUtils::SetInt("/sys/class/video/saturation", saturation); - } - --bool CAMLCodec::SetVideo3dMode(const int mode3d) --{ -- bool result = true; -- if (SysfsUtils::Has("/sys/class/ppmgr/ppmgr_3d_mode")) -- { -- CLog::Log(LOGDEBUG, "CAMLCodec::SetVideo3dMode:mode3d(0x%x)", mode3d); -- SysfsUtils::SetInt("/sys/class/ppmgr/ppmgr_3d_mode", mode3d); -- } -- else -- { -- CLog::Log(LOGINFO, "CAMLCodec::SetVideo3dMode: ppmgr_3d support not found in kernel."); -- result = false; -- } -- return result; --} -- --std::string CAMLCodec::GetStereoMode() -+std::string CAMLCodec::GetVideoStereoMode() - { - std::string stereoMode; - -- //Get Decoder Stereo mode -- int decoder_sm(VPP_3D_MODE_NULL); -- aml_ioctl_get(am_private->vcodec.handle, AMSTREAM_IOC_GET_3D_TYPE, (unsigned long)&decoder_sm); -- -- switch (decoder_sm) -+ switch (m_processInfo.GetVideoSettings().m_StereoMode) - { -- case VPP_3D_MODE_LR: -+ case RENDER_STEREO_MODE_SPLIT_VERTICAL: - stereoMode = "left_right"; - break; -- case VPP_3D_MODE_TB: -+ case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: - stereoMode = "top_bottom"; - break; -- case VPP_3D_MODE_LA: -- case VPP_3D_MODE_FA: - default: -- switch(m_processInfo.GetVideoSettings().m_StereoMode) -- { -- case RENDER_STEREO_MODE_SPLIT_VERTICAL: -- stereoMode = "left_right"; -- break; -- case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: -- stereoMode = "top_bottom"; -- break; -- default: -- stereoMode = m_hints.stereo_mode; -- break; -- } -+ stereoMode = m_hints.stereo_mode; -+ break; - } - - if (m_processInfo.GetVideoSettings().m_StereoInvert) -@@ -2320,6 +2249,7 @@ std::string CAMLCodec::GetStereoMode() - else if (stereoMode == "left_right") - stereoMode = "right_left"; - } -+ - return stereoMode; - } - -@@ -2359,20 +2289,20 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) - update = true; - } - -- // video stereo mode/view. -- RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode(); -- if (m_stereo_mode != stereo_mode) -+ // GUI stereo mode/view. -+ RENDER_STEREO_MODE guiStereoMode = g_graphicsContext.GetStereoMode(); -+ if (m_guiStereoMode != guiStereoMode) - { -- m_stereo_mode = stereo_mode; -+ m_guiStereoMode = guiStereoMode; - update = true; - } -- RENDER_STEREO_VIEW stereo_view = g_graphicsContext.GetStereoView(); -- if (m_stereo_view != stereo_view) -+ RENDER_STEREO_VIEW guiStereoView = g_graphicsContext.GetStereoView(); -+ if (m_guiStereoView != guiStereoView) - { - // left/right/top/bottom eye, - // this might change every other frame. - // we do not care but just track it. -- m_stereo_view = stereo_view; -+ m_guiStereoView = guiStereoView; - } - - // dest_rect -@@ -2424,9 +2354,9 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) - { - float xscale = display.Width() / gui.Width(); - float yscale = display.Height() / gui.Height(); -- if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) -+ if (m_guiStereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - xscale /= 2.0; -- else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) -+ else if (m_guiStereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) - yscale /= 2.0; - dst_rect.x1 *= xscale; - dst_rect.x2 *= xscale; -@@ -2434,75 +2364,21 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) - dst_rect.y2 *= yscale; - } - -- if (m_stereo_mode == RENDER_STEREO_MODE_MONO) -+ if (m_guiStereoMode == RENDER_STEREO_MODE_MONO) - { -- std::string mode = GetStereoMode(); -- if (mode == "left_right") -- { -- if (!SetVideo3dMode(MODE_3D_TO_2D_L)) -- { -- // fall back to software scaling if no hw support -- // was found -- dst_rect.x2 *= 2.0; -- } -- } -- else if (mode == "right_left") -- { -- if (!SetVideo3dMode(MODE_3D_TO_2D_R)) -- { -- // fall back to software scaling if no hw support -- // was found -- dst_rect.x2 *= 2.0; -- } -- } -- else if (mode == "top_bottom") -- { -- if (!SetVideo3dMode(MODE_3D_TO_2D_T)) -- { -- // fall back to software scaling if no hw support -- // was found -- dst_rect.y2 *= 2.0; -- } -- } -- else if (mode == "bottom_top") -- { -- if (!SetVideo3dMode(MODE_3D_TO_2D_B)) -- { -- // fall back to software scaling if no hw support -- // was found -- dst_rect.y2 *= 2.0; -- } -- } -- else -- SetVideo3dMode(MODE_3D_DISABLE); -+ std::string videoStereoMode = GetVideoStereoMode(); -+ if (videoStereoMode == "left_right" || videoStereoMode == "righ_left") -+ dst_rect.x2 *= 2.0; -+ else if (videoStereoMode == "top_bottom" || videoStereoMode == "bottom_top") -+ dst_rect.y2 *= 2.0; - } -- else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) -+ else if (m_guiStereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - { - dst_rect.x2 *= 2.0; -- SetVideo3dMode(MODE_3D_DISABLE); - } -- else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) -+ else if (m_guiStereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) - { - dst_rect.y2 *= 2.0; -- SetVideo3dMode(MODE_3D_DISABLE); -- } -- else if (m_stereo_mode == RENDER_STEREO_MODE_INTERLACED) -- { -- std::string mode = GetStereoMode(); -- if (mode == "left_right") -- SetVideo3dMode(MODE_3D_LR); -- else if (mode == "right_left") -- SetVideo3dMode(MODE_3D_LR_SWITCH); -- else if (mode == "row_interleaved_lr") -- SetVideo3dMode(MODE_3D_LR); -- else if (mode == "row_interleaved_rl") -- SetVideo3dMode(MODE_3D_LR_SWITCH); -- else -- SetVideo3dMode(MODE_3D_DISABLE); -- } -- else -- { -- SetVideo3dMode(MODE_3D_DISABLE); - } - - #if 1 -@@ -2522,8 +2398,8 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) - CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:gui(%s)", s_gui.c_str()); - CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_dst_rect(%s)", s_m_dst_rect.c_str()); - CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", s_dst_rect.c_str()); -- CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_mode(%d)", m_stereo_mode); -- CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_view(%d)", m_stereo_view); -+ CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_guiStereoMode(%d)", m_guiStereoMode); -+ CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_guiStereoView(%d)", m_guiStereoView); - #endif - - // goofy 0/1 based difference in aml axis coordinates. -diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h -index 378c237c3b38..fdb1b63fffe1 100644 ---- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h -@@ -71,8 +71,7 @@ class CAMLCodec - void SetVideoContrast(const int contrast); - void SetVideoBrightness(const int brightness); - void SetVideoSaturation(const int saturation); -- bool SetVideo3dMode(const int mode3d); -- std::string GetStereoMode(); -+ std::string GetVideoStereoMode(); - bool OpenAmlVideo(const CDVDStreamInfo &hints); - void CloseAmlVideo(); - std::string GetVfmMap(const std::string &name); -@@ -96,8 +95,8 @@ class CAMLCodec - CRect m_display_rect; - - int m_view_mode = -1; -- RENDER_STEREO_MODE m_stereo_mode = RENDER_STEREO_MODE_OFF; -- RENDER_STEREO_VIEW m_stereo_view = RENDER_STEREO_VIEW_OFF; -+ RENDER_STEREO_MODE m_guiStereoMode = RENDER_STEREO_MODE_OFF; -+ RENDER_STEREO_VIEW m_guiStereoView = RENDER_STEREO_VIEW_OFF; - float m_zoom = -1.0f; - int m_contrast = -1; - int m_brightness = -1; -diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp -index 5666236e93a5..9ba833838ff4 100644 ---- a/xbmc/utils/AMLUtils.cpp -+++ b/xbmc/utils/AMLUtils.cpp -@@ -54,22 +54,6 @@ bool aml_present() - return has_aml == 1; - } - --bool aml_hw3d_present() --{ -- static int has_hw3d = -1; -- if (has_hw3d == -1) -- { -- if (SysfsUtils::Has("/sys/class/ppmgr/ppmgr_3d_mode") || -- SysfsUtils::Has("/sys/class/amhdmitx/amhdmitx0/config")) -- has_hw3d = 1; -- else -- has_hw3d = 0; -- if (has_hw3d) -- CLog::Log(LOGNOTICE, "AML 3D support detected"); -- } -- return has_hw3d == 1; --} -- - bool aml_wired_present() - { - static int has_wired = -1; -@@ -138,10 +122,6 @@ bool aml_permissions() - { - CLog::Log(LOGERROR, "AML: no rw on /sys/class/audiodsp/digital_raw"); - } -- if (!SysfsUtils::HasRW("/sys/class/ppmgr/ppmgr_3d_mode")) -- { -- CLog::Log(LOGERROR, "AML: no rw on /sys/class/ppmgr/ppmgr_3d_mode"); -- } - if (!SysfsUtils::HasRW("/sys/class/amhdmitx/amhdmitx0/config")) - { - CLog::Log(LOGERROR, "AML: no rw on /sys/class/amhdmitx/amhdmitx0/config"); -diff --git a/xbmc/utils/AMLUtils.h b/xbmc/utils/AMLUtils.h -index a012d1b0aedc..1fc7dab3e3b3 100644 ---- a/xbmc/utils/AMLUtils.h -+++ b/xbmc/utils/AMLUtils.h -@@ -54,7 +54,6 @@ enum AML_SUPPORT_H264_4K2K - - bool aml_present(); - bool aml_permissions(); --bool aml_hw3d_present(); - bool aml_wired_present(); - bool aml_support_hevc(); - bool aml_support_hevc_4k2k(); diff --git a/packages/mediacenter/kodi/scripts/kodi-config b/packages/mediacenter/kodi/scripts/kodi-config index b5a55ac48e..343de20e8b 100755 --- a/packages/mediacenter/kodi/scripts/kodi-config +++ b/packages/mediacenter/kodi/scripts/kodi-config @@ -55,4 +55,6 @@ echo "KODI_ARGS=\"$KODI_ARGS\"" > /run/libreelec/kodi.conf if [ "$(uname -m)" = "x86_64" -o "$(uname -m)" = "aarch64" ]; then echo "MALLOC_MMAP_THRESHOLD_=524288" >> /run/libreelec/kodi.conf +else #arm + echo "MALLOC_MMAP_THRESHOLD_=8192" >> /run/libreelec/kodi.conf fi diff --git a/packages/multimedia/ffmpeg/patches/ffmpeg-99.1003-pfcd_hevc_optimisations.patch b/packages/multimedia/ffmpeg/patches/ffmpeg-99.1003-pfcd_hevc_optimisations.patch index 325c99a41e..629ea1b225 100644 --- a/packages/multimedia/ffmpeg/patches/ffmpeg-99.1003-pfcd_hevc_optimisations.patch +++ b/packages/multimedia/ffmpeg/patches/ffmpeg-99.1003-pfcd_hevc_optimisations.patch @@ -577,33 +577,13 @@ index 1eeac5449e..022ab7ab3d 100644 NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o diff --git a/libavcodec/arm/cabac.h b/libavcodec/arm/cabac.h -index fdbf86b45e..a60bc899bd 100644 +index fdbf86b45e..2ff0973f31 100644 --- a/libavcodec/arm/cabac.h +++ b/libavcodec/arm/cabac.h -@@ -26,83 +26,173 @@ +@@ -26,83 +26,198 @@ #include "libavutil/internal.h" #include "libavcodec/cabac.h" -+ -+#if UNCHECKED_BITSTREAM_READER -+#define LOAD_16BITS_BEHI\ -+ "ldrh %[tmp] , [%[ptr]] , #2 \n\t"\ -+ "rev %[tmp] , %[tmp] \n\t" -+#elif CONFIG_THUMB -+#define LOAD_16BITS_BEHI\ -+ "ldr %[tmp] , [%[c], %[end]] \n\t"\ -+ "cmp %[tmp] , %[ptr] \n\t"\ -+ "it cs \n\t"\ -+ "ldrhcs %[tmp] , [%[ptr]] , #2 \n\t"\ -+ "rev %[tmp] , %[tmp] \n\t" -+#else -+#define LOAD_16BITS_BEHI\ -+ "ldr %[tmp] , [%[c], %[end]] \n\t"\ -+ "cmp %[tmp] , %[ptr] \n\t"\ -+ "ldrcsh %[tmp] , [%[ptr]] , #2 \n\t"\ -+ "rev %[tmp] , %[tmp] \n\t" -+#endif -+ + #define get_cabac_inline get_cabac_inline_arm static av_always_inline int get_cabac_inline_arm(CABACContext *c, @@ -612,33 +592,6 @@ index fdbf86b45e..a60bc899bd 100644 { - int bit; - void *reg_b, *reg_c, *tmp; -- -- __asm__ volatile( -- "ldrb %[bit] , [%[state]] \n\t" -- "add %[r_b] , %[tables] , %[lps_off] \n\t" -- "mov %[tmp] , %[range] \n\t" -- "and %[range] , %[range] , #0xC0 \n\t" -- "add %[r_b] , %[r_b] , %[bit] \n\t" -- "ldrb %[range] , [%[r_b], %[range], lsl #1] \n\t" -- "add %[r_b] , %[tables] , %[norm_off] \n\t" -- "sub %[r_c] , %[tmp] , %[range] \n\t" -- "lsl %[tmp] , %[r_c] , #17 \n\t" -- "cmp %[tmp] , %[low] \n\t" -- "it gt \n\t" -- "movgt %[range] , %[r_c] \n\t" -- "itt cc \n\t" -- "mvncc %[bit] , %[bit] \n\t" -- "subcc %[low] , %[low] , %[tmp] \n\t" -- "add %[r_c] , %[tables] , %[mlps_off] \n\t" -- "ldrb %[tmp] , [%[r_b], %[range]] \n\t" -- "ldrb %[r_b] , [%[r_c], %[bit]] \n\t" -- "lsl %[low] , %[low] , %[tmp] \n\t" -- "lsl %[range] , %[range] , %[tmp] \n\t" -- "uxth %[r_c] , %[low] \n\t" -- "strb %[r_b] , [%[state]] \n\t" -- "tst %[r_c] , %[r_c] \n\t" -- "bne 2f \n\t" -- "ldr %[r_c] , [%[c], %[byte]] \n\t" + const uint8_t *mlps_tables = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128; + int bit, ptr, low, tmp1, tmp2; + __asm__ volatile ( @@ -664,49 +617,17 @@ index fdbf86b45e..a60bc899bd 100644 + "bne 1f \n\t" + "ldr %[ptr], [%[c], %[ptr_off]] \n\t" + "lsl %[tmp2], %[tmp1], %[tmp2] \n\t" - #if UNCHECKED_BITSTREAM_READER -- "ldrh %[tmp] , [%[r_c]] \n\t" -- "add %[r_c] , %[r_c] , #2 \n\t" -- "str %[r_c] , [%[c], %[byte]] \n\t" ++#if UNCHECKED_BITSTREAM_READER + "strb %[mlps_tables], [%[state]] \n\t" + "rbit %[state], %[low] \n\t" + "ldrh %[tmp1], [%[ptr]], #2 \n\t" - #else -- "ldr %[r_b] , [%[c], %[end]] \n\t" -- "ldrh %[tmp] , [%[r_c]] \n\t" -- "cmp %[r_c] , %[r_b] \n\t" -- "itt lt \n\t" -- "addlt %[r_c] , %[r_c] , #2 \n\t" -- "strlt %[r_c] , [%[c], %[byte]] \n\t" ++#else + "ldr %[tmp1], [%[c], %[end_off]] \n\t" + "strb %[mlps_tables], [%[state]] \n\t" + "rbit %[state], %[low] \n\t" + "cmp %[tmp1], %[ptr] \n\t" + "ldrcsh %[tmp1], [%[ptr]], #2 \n\t" - #endif -- "sub %[r_c] , %[low] , #1 \n\t" -- "add %[r_b] , %[tables] , %[norm_off] \n\t" -- "eor %[r_c] , %[low] , %[r_c] \n\t" -- "rev %[tmp] , %[tmp] \n\t" -- "lsr %[r_c] , %[r_c] , #15 \n\t" -- "lsr %[tmp] , %[tmp] , #15 \n\t" -- "ldrb %[r_c] , [%[r_b], %[r_c]] \n\t" -- "movw %[r_b] , #0xFFFF \n\t" -- "sub %[tmp] , %[tmp] , %[r_b] \n\t" -- "rsb %[r_c] , %[r_c] , #7 \n\t" -- "lsl %[tmp] , %[tmp] , %[r_c] \n\t" -- "add %[low] , %[low] , %[tmp] \n\t" -- "2: \n\t" -- : [bit]"=&r"(bit), -- [low]"+&r"(c->low), -- [range]"+&r"(c->range), -- [r_b]"=&r"(reg_b), -- [r_c]"=&r"(reg_c), -- [tmp]"=&r"(tmp) -- : [c]"r"(c), -- [state]"r"(state), -- [tables]"r"(ff_h264_cabac_tables), -- [byte]"M"(offsetof(CABACContext, bytestream)), ++#endif + "clz %[state], %[state] \n\t" + "movw %[mlps_tables], #0xffff \n\t" + "sub %[state], %[state], #16 \n\t" @@ -744,90 +665,194 @@ index fdbf86b45e..a60bc899bd 100644 + ); + return bit; +} -+ + +- __asm__ volatile( +- "ldrb %[bit] , [%[state]] \n\t" +- "add %[r_b] , %[tables] , %[lps_off] \n\t" +- "mov %[tmp] , %[range] \n\t" +- "and %[range] , %[range] , #0xC0 \n\t" +- "add %[r_b] , %[r_b] , %[bit] \n\t" +- "ldrb %[range] , [%[r_b], %[range], lsl #1] \n\t" +- "add %[r_b] , %[tables] , %[norm_off] \n\t" +- "sub %[r_c] , %[tmp] , %[range] \n\t" +- "lsl %[tmp] , %[r_c] , #17 \n\t" +- "cmp %[tmp] , %[low] \n\t" +- "it gt \n\t" +- "movgt %[range] , %[r_c] \n\t" +- "itt cc \n\t" +- "mvncc %[bit] , %[bit] \n\t" +- "subcc %[low] , %[low] , %[tmp] \n\t" +- "add %[r_c] , %[tables] , %[mlps_off] \n\t" +- "ldrb %[tmp] , [%[r_b], %[range]] \n\t" +- "ldrb %[r_b] , [%[r_c], %[bit]] \n\t" +- "lsl %[low] , %[low] , %[tmp] \n\t" +- "lsl %[range] , %[range] , %[tmp] \n\t" +- "uxth %[r_c] , %[low] \n\t" +- "strb %[r_b] , [%[state]] \n\t" +- "tst %[r_c] , %[r_c] \n\t" +- "bne 2f \n\t" +- "ldr %[r_c] , [%[c], %[byte]] \n\t" +#define get_cabac_bypass get_cabac_bypass_arm +static inline int get_cabac_bypass_arm(CABACContext * const c) +{ -+ int rv = 0; -+ unsigned int tmp; -+ __asm ( -+ "lsl %[low] , #1 \n\t" -+ "cmp %[low] , %[range] , lsl #17 \n\t" -+ "adc %[rv] , %[rv] , #0 \n\t" -+ "it cs \n\t" -+ "subcs %[low] , %[low] , %[range], lsl #17 \n\t" -+ "lsls %[tmp] , %[low] , #16 \n\t" -+ "bne 1f \n\t" -+ LOAD_16BITS_BEHI -+ "add %[low] , %[low] , %[tmp], lsr #15 \n\t" -+ "movw %[tmp] , #0xFFFF \n\t" -+ "sub %[low] , %[low] , %[tmp] \n\t" -+ "1: \n\t" -+ : // Outputs -+ [rv]"+r"(rv), -+ [low]"+r"(c->low), -+ [tmp]"=r"(tmp), -+ [ptr]"+r"(c->bytestream) -+ : // Inputs ++ uint32_t low = c->low, range, ptr, tmp; ++ int rv; ++ __asm volatile ( ++ "ldr %[range] , [%[c], %[range_off]] \n\t" ++ "mov %[rv] , #0 \n\t" ++ "ldr %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "lsl %[low] , #1 \n\t" +#if !UNCHECKED_BITSTREAM_READER -+ [c]"r"(c), - [end]"M"(offsetof(CABACContext, bytestream_end)), ++ "ldr %[tmp] , [%[c], %[end_off]] \n\t" ++#endif ++ "cmp %[low] , %[range], lsl #17 \n\t" ++ "it cs \n\t" ++ "subcs %[low] , %[range], lsl #17 \n\t" ++ "it cs \n\t" ++ "movcs %[rv] , #1 \n\t" + #if UNCHECKED_BITSTREAM_READER +- "ldrh %[tmp] , [%[r_c]] \n\t" +- "add %[r_c] , %[r_c] , #2 \n\t" +- "str %[r_c] , [%[c], %[byte]] \n\t" ++ "ldrh %[tmp] , [%[ptr]], #2 \n\t" ++#else ++ "cmp %[tmp] , %[ptr] \n\t" ++#if CONFIG_THUMB ++ "it cs \n\t" ++ "ldrhcs %[tmp] , [%[ptr]], #2 \n\t" + #else +- "ldr %[r_b] , [%[c], %[end]] \n\t" +- "ldrh %[tmp] , [%[r_c]] \n\t" +- "cmp %[r_c] , %[r_b] \n\t" +- "itt lt \n\t" +- "addlt %[r_c] , %[r_c] , #2 \n\t" +- "strlt %[r_c] , [%[c], %[byte]] \n\t" ++ "ldrcsh %[tmp] , [%[ptr]], #2 \n\t" ++#endif + #endif +- "sub %[r_c] , %[low] , #1 \n\t" +- "add %[r_b] , %[tables] , %[norm_off] \n\t" +- "eor %[r_c] , %[low] , %[r_c] \n\t" +- "rev %[tmp] , %[tmp] \n\t" +- "lsr %[r_c] , %[r_c] , #15 \n\t" +- "lsr %[tmp] , %[tmp] , #15 \n\t" +- "ldrb %[r_c] , [%[r_b], %[r_c]] \n\t" +- "movw %[r_b] , #0xFFFF \n\t" +- "sub %[tmp] , %[tmp] , %[r_b] \n\t" +- "rsb %[r_c] , %[r_c] , #7 \n\t" +- "lsl %[tmp] , %[tmp] , %[r_c] \n\t" +- "add %[low] , %[low] , %[tmp] \n\t" +- "2: \n\t" +- : [bit]"=&r"(bit), +- [low]"+&r"(c->low), +- [range]"+&r"(c->range), +- [r_b]"=&r"(reg_b), +- [r_c]"=&r"(reg_c), +- [tmp]"=&r"(tmp) +- : [c]"r"(c), +- [state]"r"(state), +- [tables]"r"(ff_h264_cabac_tables), +- [byte]"M"(offsetof(CABACContext, bytestream)), +- [end]"M"(offsetof(CABACContext, bytestream_end)), - [norm_off]"I"(H264_NORM_SHIFT_OFFSET), - [lps_off]"I"(H264_LPS_RANGE_OFFSET), - [mlps_off]"I"(H264_MLPS_STATE_OFFSET + 128) - : "memory", "cc" - ); -+#endif -+ [range]"r"(c->range) -+ : "cc" -+ ); -+ return rv; -+} ++ "lsls %[range] , %[low], #16 \n\t" ++ "bne 1f \n\t" - return bit & 1; ++ "str %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "rev %[tmp] , %[tmp] \n\t" ++ "add %[low] , %[tmp], lsr #15 \n\t" ++ "movw %[tmp] , 0xFFFF \n\t" ++ "sub %[low] , %[tmp] \n\t" ++ "1: \n\t" ++ "str %[low] , [%[c], %[low_off]] \n\t" ++ : // Outputs ++ [rv]"=&r"(rv), ++ [low]"+r"(low), ++ [range]"=&r"(range), ++ [ptr]"=&r"(ptr), ++ [tmp]"=&r"(tmp) ++ : // Inputs ++ [c]"r"(c), ++ [low_off]"J"(offsetof(CABACContext, low)), ++ [range_off]"J"(offsetof(CABACContext, range)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)), ++ [end_off]"J"(offsetof(CABACContext, bytestream_end)) ++ : // Clobbers ++ "memory", "cc" ++ ); ++ return rv; + } ++ + +#define get_cabac_bypass_sign get_cabac_bypass_sign_arm +static inline int get_cabac_bypass_sign_arm(CABACContext * const c, int rv) +{ -+ unsigned int tmp; -+ __asm ( -+ "lsl %[low] , #1 \n\t" -+ "cmp %[low] , %[range] , lsl #17 \n\t" -+ "ite cc \n\t" -+ "rsbcc %[rv] , %[rv] , #0 \n\t" -+ "subcs %[low] , %[low] , %[range], lsl #17 \n\t" -+ "lsls %[tmp] , %[low] , #16 \n\t" -+ "bne 1f \n\t" -+ LOAD_16BITS_BEHI -+ "add %[low] , %[low] , %[tmp], lsr #15 \n\t" -+ "movw %[tmp] , #0xFFFF \n\t" -+ "sub %[low] , %[low] , %[tmp] \n\t" -+ "1: \n\t" -+ : // Outputs -+ [rv]"+r"(rv), -+ [low]"+r"(c->low), -+ [tmp]"=r"(tmp), -+ [ptr]"+r"(c->bytestream) -+ : // Inputs ++ uint32_t low = c->low, range, ptr, tmp; ++ __asm volatile ( ++ "ldr %[range] , [%[c], %[range_off]] \n\t" ++ "ldr %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "lsl %[low] , #1 \n\t" +#if !UNCHECKED_BITSTREAM_READER -+ [c]"r"(c), -+ [end]"M"(offsetof(CABACContext, bytestream_end)), ++ "ldr %[tmp] , [%[c], %[end_off]] \n\t" +#endif -+ [range]"r"(c->range) -+ : "cc" ++ "cmp %[low] , %[range], lsl #17 \n\t" ++ "it cs \n\t" ++ "subcs %[low] , %[range], lsl #17 \n\t" ++ "it cc \n\t" ++ "rsbcc %[rv] , %[rv], #0 \n\t" ++#if UNCHECKED_BITSTREAM_READER ++ "ldrh %[tmp] , [%[ptr]], #2 \n\t" ++#else ++ "cmp %[tmp] , %[ptr] \n\t" ++#if CONFIG_THUMB ++ "it cs \n\t" ++ "ldrhcs %[tmp] , [%[ptr]], #2 \n\t" ++#else ++ "ldrcsh %[tmp] , [%[ptr]], #2 \n\t" ++#endif ++#endif ++ "lsls %[range] , %[low], #16 \n\t" ++ "bne 1f \n\t" ++ ++ "str %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "rev %[tmp] , %[tmp] \n\t" ++ "add %[low] , %[tmp], lsr #15 \n\t" ++ "movw %[tmp] , 0xFFFF \n\t" ++ "sub %[low] , %[tmp] \n\t" ++ "1: \n\t" ++ "str %[low] , [%[c], %[low_off]] \n\t" ++ : // Outputs ++ [rv]"+r"(rv), ++ [low]"+r"(low), ++ [range]"=&r"(range), ++ [ptr]"=&r"(ptr), ++ [tmp]"=&r"(tmp) ++ : // Inputs ++ [c]"r"(c), ++ [low_off]"J"(offsetof(CABACContext, low)), ++ [range_off]"J"(offsetof(CABACContext, range)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)), ++ [end_off]"J"(offsetof(CABACContext, bytestream_end)) ++ : // Clobbers ++ "memory", "cc" + ); + return rv; - } ++} + #endif /* HAVE_ARMV6T2_INLINE */ #endif /* AVCODEC_ARM_CABAC_H */ diff --git a/libavcodec/arm/rpi_hevc_cabac.h b/libavcodec/arm/rpi_hevc_cabac.h new file mode 100644 -index 0000000000..10b2c6f850 +index 0000000000..9c317c713b --- /dev/null +++ b/libavcodec/arm/rpi_hevc_cabac.h -@@ -0,0 +1,477 @@ +@@ -0,0 +1,526 @@ +/* + * This file is part of FFmpeg. + * @@ -1103,15 +1128,64 @@ index 0000000000..10b2c6f850 +// --------------------------------------------------------------------------- +// +// CABAC_BY22 functions -+// -+// By and large these are (at best) no faster than their C equivalents - the -+// only one worth having is _peek where we do a slightly better job than the -+// compiler -+// -+// The others have been stashed here for reference in case larger scale asm -+// is attempted in which case they might be a useful base + + ++#define get_cabac_by22_start get_cabac_by22_start_arm ++static const uint32_t cabac_by22_inv_range[256] __attribute__((section(".text"))); ++static inline void get_cabac_by22_start_arm(CABACContext * const c) ++{ ++ const uint8_t *ptr = c->bytestream; ++ register uint32_t low __asm__("r1"), range __asm__("r2"); ++ uint32_t inv, m, range8, bits; ++ av_assert0(offsetof (CABACContext, low) == 0); ++ av_assert0(offsetof (CABACContext, range) == 4); ++ av_assert0(offsetof (CABACContext, by22.range) == offsetof (CABACContext, by22.bits) + 2); ++ __asm__ ( ++ "ldmia %[c], {%[low], %[range]} \n\t" ++#if !USE_BY22_DIV ++ "adrl %[inv], cabac_by22_inv_range \n\t" ++#endif ++ "ldr %[m], [%[ptr]], #-("AV_STRINGIFY(CABAC_BITS)"/8) \n\t" ++#if !USE_BY22_DIV ++ "uxtb %[range8], %[range] \n\t" ++#endif ++ "rbit %[bits], %[low] \n\t" ++ "lsl %[low], %[low], #22 - "AV_STRINGIFY(CABAC_BITS)" \n\t" ++ "clz %[bits], %[bits] \n\t" ++ "str %[ptr], [%[c], %[ptr_off]] \n\t" ++ "rev %[m], %[m] \n\t" ++ "rsb %[ptr], %[bits], #9 + "AV_STRINGIFY(CABAC_BITS)" \n\t" ++ "eor %[m], %[m], #0x80000000 \n\t" ++#if !USE_BY22_DIV ++ "ldr %[inv], [%[inv], %[range8], lsl #2] \n\t" ++ "pkhbt %[range], %[bits], %[range], lsl #16 \n\t" ++ "str %[range], [%[c], %[bits_off]] \n\t" ++#else ++ "strh %[bits], [%[c], %[bits_off]] \n\t" ++#endif ++ "eor %[range], %[low], %[m], lsr %[ptr] \n\t" ++ : // Outputs ++ [ptr]"+r"(ptr), ++ [low]"=&r"(low), ++ [range]"=&r"(range), ++ [inv]"=&r"(inv), ++ [m]"=&r"(m), ++ [range8]"=&r"(range8), ++ [bits]"=&r"(bits) ++ : // Inputs ++ [c]"r"(c), ++ [bits_off]"J"(offsetof (CABACContext, by22.bits)), ++ [ptr_off]"J"(offsetof (CABACContext, bytestream)), ++ [cbir]"X"(cabac_by22_inv_range) ++ : // Clobbers ++ "memory" ++ ); ++ c->low = range; ++#if !USE_BY22_DIV ++ c->range = inv; ++#endif ++} ++ +#define get_cabac_by22_peek get_cabac_by22_peek_arm +static inline uint32_t get_cabac_by22_peek_arm(const CABACContext *const c) +{ @@ -1307,10 +1381,10 @@ index 0000000000..10b2c6f850 +#endif /* AVCODEC_ARM_HEVC_CABAC_H */ diff --git a/libavcodec/arm/rpi_hevc_idct_fn_neon.S b/libavcodec/arm/rpi_hevc_idct_fn_neon.S new file mode 100644 -index 0000000000..91a7bd4f4f +index 0000000000..c8d68f7294 --- /dev/null +++ b/libavcodec/arm/rpi_hevc_idct_fn_neon.S -@@ -0,0 +1,224 @@ +@@ -0,0 +1,181 @@ +@ Included multiple times from hevc_idct_neon.S +@ Macros defined there + @@ -1434,101 +1508,58 @@ index 0000000000..91a7bd4f4f + bx lr +endfunc + -+ -+ +function JOIN(ff_hevc_rpi_transform_8x8_neon_, BIT_DEPTH), export=1 -+ push {r4-r8} -+ vpush {d8-d15} -+ mov r5, #16 ++ add r2, r0, #16 ++ adrl r3, tr4f ++ vpush {d8-d15} ++ vld1.16 {d0, d1}, [r3] ++ mov r3, #32 + -+ adrl r3, tr4f -+ vld1.16 {d0, d1}, [r3] ++ tr8_vert d16, d17, d18, d19, d24, d25, d26, d27, q8, q9, \ ++ "sub r0, r0, #128-8", \ ++ "sub r2, r2, #128-8", \ ++ "cmp r1, #4" ++ ble 2f + -+ // left half -+ vld1.16 {d24}, [r0], r5 -+ vld1.16 {d25}, [r0], r5 -+ vld1.16 {d26}, [r0], r5 -+ vld1.16 {d27}, [r0], r5 -+ vld1.16 {d28}, [r0], r5 -+ vld1.16 {d29}, [r0], r5 -+ vld1.16 {d30}, [r0], r5 -+ vld1.16 {d31}, [r0], r5 -+ sub r0, #128 -+ tr8_begin d25, d27, d29, d31 -+ tr4 d24, d26, d28, d30 -+ tr8_end #7 -+ vst1.16 {d2}, [r0], r5 -+ vst1.16 {d3}, [r0], r5 -+ vst1.16 {d4}, [r0], r5 -+ vst1.16 {d5}, [r0], r5 -+ vst1.16 {d6}, [r0], r5 -+ vst1.16 {d7}, [r0], r5 -+ vst1.16 {d8}, [r0], r5 -+ vst1.16 {d9}, [r0], r5 -+ sub r0, #128 -+ //skip right half if col_limit in r1 is less than 4 -+ cmp r1, #4 -+ blt 1f -+ //right half -+ add r0, #8 -+ vld1.16 {d24}, [r0], r5 -+ vld1.16 {d25}, [r0], r5 -+ vld1.16 {d26}, [r0], r5 -+ vld1.16 {d27}, [r0], r5 -+ vld1.16 {d28}, [r0], r5 -+ vld1.16 {d29}, [r0], r5 -+ vld1.16 {d30}, [r0], r5 -+ vld1.16 {d31}, [r0], r5 -+ sub r0, #128 -+ tr8_begin d25, d27, d29, d31 -+ tr4 d24, d26, d28, d30 -+ tr8_end #7 -+ vst1.16 {d2}, [r0], r5 -+ vst1.16 {d3}, [r0], r5 -+ vst1.16 {d4}, [r0], r5 -+ vst1.16 {d5}, [r0], r5 -+ vst1.16 {d6}, [r0], r5 -+ vst1.16 {d7}, [r0], r5 -+ vst1.16 {d8}, [r0], r5 -+ vst1.16 {d9}, [r0], r5 -+ sub r0, #136 ++ tr8_vert d20, d21, d22, d23, d28, d29, d30, d31, q10, q11, \ ++ "sub r0, r0, #128+8", \ ++ "sub r2, r2, #128+8+16-32", \ ++ "mov r3, #64" ++ ++ vzip.16 d16, d17 ++ vzip.16 d18, d19 ++ ++ vzip.16 d20, d21 ++ vzip.16 d22, d23 ++ vzip.16 d28, d29 ++ vzip.16 d30, d31 ++ vzip.32 q10, q11 ++ vzip.32 q14, q15 +1: -+ // top half -+ vldm r0, {q12-q15} // coeffs -+ transpose_16b_4x4 d24, d26, d28, d30 -+ transpose_16b_4x4 d25, d27, d29, d31 -+ tr8_begin d26, d30, d27, d31 -+ tr4 d24, d28, d25, d29 -+ tr8_end #(TRN_SHIFT) -+ transpose_16b_4x4 d2, d3, d4, d5 -+ transpose_16b_4x4 d6, d7, d8, d9 -+ vswp d7, d5 -+ vswp d7, d8 -+ vswp d3, d6 -+ vswp d6, d4 -+ vstm r0!, {q1-q4} ++ vzip.16 d24, d25 ++ vzip.16 d26, d27 ++ vzip.32 q8, q9 ++ vzip.32 q12, q13 ++ ++ tr8_horiz d16, d17, d18, d19, d20, d21, d22, d23, q8, q9, TRN_SHIFT ++ tr8_horiz d24, d25, d26, d27, d28, d29, d30, d31, q12, q13, TRN_SHIFT ++ ++ vpop {d8-d15} ++ bx lr ++ ++2: vmov.i64 q10, #0 ++ sub r0, r0, #8 ++ vmov.i64 q11, #0 ++ sub r2, r2, #8+16-32 ++ vmov.i64 q14, #0 ++ mov r3, #64 ++ vmov.i64 q15, #0 ++ ++ vzip.16 d16, d17 ++ vzip.16 d18, d19 ++ ++ b 1b + -+ // bottom half -+ vldm r0, {q12-q15} // coeffs -+ transpose_16b_4x4 d24, d26, d28, d30 -+ transpose_16b_4x4 d25, d27, d29, d31 -+ tr8_begin d26, d30, d27, d31 -+ tr4 d24, d28, d25, d29 -+ tr8_end #(TRN_SHIFT) -+ transpose_16b_4x4 d2, d3, d4, d5 -+ transpose_16b_4x4 d6, d7, d8, d9 -+ vswp d7, d5 -+ vswp d7, d8 -+ vswp d3, d6 -+ vswp d6, d4 -+ //vstm r0, {q1-q4} -+ vst1.16 {q1-q2}, [r0] -+ add r0, #32 -+ vst1.16 {q3-q4}, [r0] -+ sub r0, #32 -+ vpop {d8-d15} -+ pop {r4-r8} -+ bx lr +endfunc + +#undef DC_SHIFT @@ -1537,10 +1568,10 @@ index 0000000000..91a7bd4f4f + diff --git a/libavcodec/arm/rpi_hevc_misc_neon.S b/libavcodec/arm/rpi_hevc_misc_neon.S new file mode 100644 -index 0000000000..373576b4cb +index 0000000000..1bdf2ab09f --- /dev/null +++ b/libavcodec/arm/rpi_hevc_misc_neon.S -@@ -0,0 +1,62 @@ +@@ -0,0 +1,26 @@ +#include "libavutil/arm/asm.S" +#include "neon.S" + @@ -1549,60 +1580,24 @@ index 0000000000..373576b4cb +@ unsigned int log_n_m2) [r1] + +function rpi_zap_coeff_vals_neon, export=1 -+ vmov.i64 q8, #0 -+ adr r12, zc_tab -+ vmov.i64 q9, #0 -+ tst r0, #63 -+ vmov.i64 q10, #0 -+ add r0, #63 -+ vmov.i64 q11, #0 -+ and r0, #~63 -+ ldr pc, [r12, r1, lsl #2] ++ mov ip, #1 ++ vmov.i64 q0, #0 ++ teq r1, #0 ++ vmov.i64 q1, #0 ++ beq 2f + -+zc_tab: -+ .word zc_lc2 -+ .word zc_lc3 -+ .word zc_lc4 -+ .word zc_lc5 -+ -+@ 4*4*2: "32 bytes" 64 or 0 depending on dst address -+zc_lc2: -+ it eq -+ vstmeq r0, {q8-q11} -+ bx lr -+ -+@ 16*16*2 = 512 = 64 * 8 -+zc_lc4: -+ vstm r0!, {q8-q11} -+ vstm r0!, {q8-q11} -+ vstm r0!, {q8-q11} -+ vstm r0!, {q8-q11} -+ vstm r0!, {q8-q11} -+ vstm r0!, {q8-q11} -+@ 8*8*2 = 128 -+zc_lc3: -+ vstm r0!, {q8-q11} -+ vstm r0, {q8-q11} -+ bx lr -+ -+@ 32*32*2 = 2048 = 128 * 16 -+zc_lc5: -+ vmov.i64 q12, #0 -+ vmov.i64 q13, #0 -+ vmov.i64 q14, #0 -+ vmov.i64 q15, #0 -+ mov r2, #4 -+1: -+ vstm r0!, {q8-q15} -+ subs r2, #1 -+ vstm r0!, {q8-q15} -+ vstm r0!, {q8-q15} -+ vstm r0!, {q8-q15} -+ bne 1b -+ bx lr -+ -+endfunc ++ lsl ip, r1 @ 2, 4 or 8 ++ add r2, r0, #32 ++ lsl ip, r1 @ 4, 16 or 64 = number of 32-byte blocks to zero ++ mov r3, #64 ++1: vst1.8 {q0,q1}, [r0:256], r3 ++ subs ip, #2 ++ vst1.8 {q0,q1}, [r2:256], r3 ++ bne 1b ++ bx lr + ++2: vst1.8 {q0,q1}, [r0:256] ++ bx lr diff --git a/libavcodec/arm/rpi_hevcdsp_arm.h b/libavcodec/arm/rpi_hevcdsp_arm.h new file mode 100644 index 0000000000..62b9326532 @@ -3428,10 +3423,10 @@ index 0000000000..d691cda836 + diff --git a/libavcodec/arm/rpi_hevcdsp_idct_neon.S b/libavcodec/arm/rpi_hevcdsp_idct_neon.S new file mode 100644 -index 0000000000..cd79460984 +index 0000000000..2ebbf15d2b --- /dev/null +++ b/libavcodec/arm/rpi_hevcdsp_idct_neon.S -@@ -0,0 +1,379 @@ +@@ -0,0 +1,423 @@ +/* + * Copyright (c) 2014 Seppo Tomperi + * @@ -3746,50 +3741,94 @@ index 0000000000..cd79460984 + vqrshrn.s32 \r3, q3, \shift +.endm + -+.macro tr8_begin in0, in1, in2, in3 -+ vmull.s16 q7, \in0, d1[1] // 89 * src1 -+ vmull.s16 q8, \in0, d1[0] // 75 * src1 -+ vmull.s16 q9, \in0, d1[3] // 50 * src1 -+ vmull.s16 q10, \in0, d1[2] // 18 * src1 ++.macro tr8_process d0, d1, d2, d3, d4, d5, d6, d7, \ ++ tmp0, /* Q reg which doesn't alias with d4, d6 or d7 */ \ ++ tmp1, /* Q reg which doesn't alias with d7 or d0 */ \ ++ shift, I1, I2, I3 + -+ vmlal.s16 q7, \in1, d1[0] // 75 * src3 -+ vmlsl.s16 q8, \in1, d1[2] //-18 * src3 -+ vmlsl.s16 q9, \in1, d1[1] //-89 * src3 -+ vmlsl.s16 q10, \in1, d1[3] //-50 * src3 ++ vmull.s16 q4, \d1, d1[1] // 89 * src1 ++ \I1 ++ vmull.s16 q5, \d1, d1[0] // 75 * src1 ++ \I2 ++ vmull.s16 q6, \d1, d1[3] // 50 * src1 ++ \I3 ++ vmull.s16 q7, \d1, d1[2] // 18 * src1 ++ vmlal.s16 q4, \d3, d1[0] // 75 * src3 ++ vmlsl.s16 q5, \d3, d1[2] //-18 * src3 ++ vmlsl.s16 q6, \d3, d1[1] //-89 * src3 ++ vmlsl.s16 q7, \d3, d1[3] //-50 * src3 + -+ vmlal.s16 q7, \in2, d1[3] // 50 * src5 -+ vmlsl.s16 q8, \in2, d1[1] //-89 * src5 -+ vmlal.s16 q9, \in2, d1[2] // 18 * src5 -+ vmlal.s16 q10, \in2, d1[0] // 75 * src5 ++ // tr4 ++ vmull.s16 q1, \d2, d0[0] // 83 * src(1*2) ++ vmull.s16 q2, \d2, d0[1] // 36 * src(1*2) + -+ vmlal.s16 q7, \in3, d1[2] // 18 * src7 -+ vmlsl.s16 q8, \in3, d1[3] //-50 * src7 -+ vmlal.s16 q9, \in3, d1[0] // 75 * src7 -+ vmlsl.s16 q10, \in3, d1[1] //-89 * src7 ++ vmlal.s16 q4, \d5, d1[3] // 50 * src5 ++ vmlsl.s16 q5, \d5, d1[1] //-89 * src5 ++ vmlal.s16 q6, \d5, d1[2] // 18 * src5 ++ vmlal.s16 q7, \d5, d1[0] // 75 * src5 ++ ++ vshll.s16 q3, \d0, #6 // 64 * src(0*2) ++ vshll.s16 \tmp0, \d4, #6 // 64 * src(2*2) ++ vmlal.s16 q1, \d6, d0[1] // 83 * src(1*2) + 36 * src(3*2) o0 ++ vmlsl.s16 q2, \d6, d0[0] // 36 * src(1*2) - 83 * src(3*2) o1 ++ vadd.i32 \tmp1, q3, \tmp0 // 64 * (src(0*2) + src(2*2)) e0 ++ vsub.i32 \tmp0, q3, \tmp0 // 64 * (src(0*2) - src(2*2)) e1 ++ ++ vmlal.s16 q4, \d7, d1[2] // 18 * src7 ++ vmlsl.s16 q5, \d7, d1[3] //-50 * src7 ++ vmlal.s16 q6, \d7, d1[0] // 75 * src7 ++ vmlsl.s16 q7, \d7, d1[1] //-89 * src7 ++ ++ vsub.i32 q3, \tmp1, q1 // e0 - o0 ++ vadd.i32 \tmp1, \tmp1, q1 // e0 + o0 ++ vadd.i32 q1, \tmp0, q2 // e1 + o1 ++ vsub.i32 q2, \tmp0, q2 // e1 - o1 ++ ++ vadd.i32 \tmp0, \tmp1, q4 // e_8[0] + o_8[0], dst[0] ++ vsub.i32 q4, \tmp1, q4 // e_8[0] - o_8[0], dst[7] ++ vsub.i32 \tmp1, q3, q7 // e_8[3] - o_8[3], dst[4] ++ vadd.i32 q7, q3, q7 // e_8[3] + o_8[3], dst[3] ++ vadd.i32 q3, q1, q5 // e_8[1] + o_8[1], dst[1] ++ vsub.i32 q5, q1, q5 // e_8[1] - o_8[1], dst[6] ++ vsub.i32 q1, q2, q6 // e_8[2] - o_8[2], dst[5] ++ vadd.i32 q6, q2, q6 // e_8[2] + o_8[2], dst[2] ++ vqrshrn.s32 \d0, \tmp0, #\shift ++ vqrshrn.s32 \d4, \tmp1, #\shift ++ vqrshrn.s32 \d1, q3, #\shift ++ vqrshrn.s32 \d5, q1, #\shift ++ vqrshrn.s32 \d2, q6, #\shift ++ vqrshrn.s32 \d6, q5, #\shift ++ vqrshrn.s32 \d3, q7, #\shift ++ vqrshrn.s32 \d7, q4, #\shift +.endm + -+.macro tr8_end shift -+ vadd.s32 q1, q4, q7 // e_8[0] + o_8[0], dst[0] -+ vsub.s32 q4, q4, q7 // e_8[0] - o_8[0], dst[7] ++.macro tr8_vert d0, d1, d2, d3, d4, d5, d6, d7, q01, q23, I1, I2, I3 ++ vld1.16 {\d0}, [r0 :64], r3 ++ vld1.16 {\d1}, [r2 :64], r3 ++ vld1.16 {\d2}, [r0 :64], r3 ++ vld1.16 {\d3}, [r2 :64], r3 ++ vld1.16 {\d4}, [r0 :64], r3 ++ vld1.16 {\d5}, [r2 :64], r3 ++ vld1.16 {\d6}, [r0 :64], r3 ++ vld1.16 {\d7}, [r2 :64], r3 + -+ vadd.s32 q2, q5, q8 // e_8[1] + o_8[1], dst[1] -+ vsub.s32 q5, q5, q8 // e_8[1] - o_8[1], dst[6] -+ -+ vadd.s32 q11, q6, q9 // e_8[2] + o_8[2], dst[2] -+ vsub.s32 q6, q6, q9 // e_8[2] - o_8[2], dst[5] -+ -+ vadd.s32 q12, q3, q10 // e_8[3] + o_8[3], dst[3] -+ vsub.s32 q3, q3, q10 // e_8[3] - o_8[3], dst[4] -+ vqrshrn.s32 d2, q1, \shift -+ vqrshrn.s32 d3, q2, \shift -+ vqrshrn.s32 d4, q11, \shift -+ vqrshrn.s32 d5, q12, \shift -+ vqrshrn.s32 d6, q3, \shift -+ vqrshrn.s32 d7, q6, \shift -+ vqrshrn.s32 d9, q4, \shift -+ vqrshrn.s32 d8, q5, \shift ++ tr8_process \ ++ \d0, \d1, \d2, \d3, \d4, \d5, \d6, \d7, \ ++ \q01, \q23, 7, "\I1", "\I2", "\I3" +.endm + ++.macro tr8_horiz d0, d1, d2, d3, d4, d5, d6, d7, q01, q23, shift ++ tr8_process \ ++ \d0, \d1, \d2, \d3, \d4, \d5, \d6, \d7, \ ++ \q01, \q23, \shift ++ ++ vzip.16 \d0, \d4 ++ vzip.16 \d1, \d5 ++ vzip.16 \d2, \d6 ++ vzip.16 \d3, \d7 ++ vst4.16 {\d0-\d3}, [r0 :128], r3 ++ vst4.16 {\d4-\d7}, [r2 :128], r3 ++.endm + +.align 4 +tr4f: @@ -7339,10 +7378,10 @@ index d181b74570..c52c450956 100644 if ((ret = av_image_copy_to_buffer(pkt->data, pkt->size, diff --git a/libavcodec/rpi_hevc_cabac.c b/libavcodec/rpi_hevc_cabac.c new file mode 100644 -index 0000000000..e02c26fea6 +index 0000000000..6566063cd8 --- /dev/null +++ b/libavcodec/rpi_hevc_cabac.c -@@ -0,0 +1,2332 @@ +@@ -0,0 +1,2387 @@ +/* + * HEVC CABAC decoding + * @@ -7987,6 +8026,7 @@ index 0000000000..e02c26fea6 +// Must be called before _by22_peek is used as it sets the CABAC environment +// into the correct state. _by22_finish must be called to return to 'normal' +// (i.e. non-bypass) cabac decoding ++#ifndef get_cabac_by22_start +static inline void get_cabac_by22_start(CABACContext * const c) +{ + const unsigned int bits = __builtin_ctz(c->low); @@ -8004,6 +8044,7 @@ index 0000000000..e02c26fea6 +#endif + c->low = x; +} ++#endif + +// Bypass block finish +// Must be called at the end of the bypass block to return to normal operation @@ -8940,6 +8981,11 @@ index 0000000000..e02c26fea6 + const xy_off_t * const scan_xy_off = off_xys[scan_idx][log2_trafo_size - 2]; + + int use_vpu; ++#if RPI_COMPRESS_COEFFS ++ int num_nonzero = 0; ++ int use_compress = 0; ++ int *coeffs32; ++#endif + int use_dc = 0; + int16_t *coeffs; + uint8_t significant_coeff_group_flag[9] = {0}; // Allow 1 final byte that is always zero @@ -9160,7 +9206,7 @@ index 0000000000..e02c26fea6 + + { + const unsigned int ccount = 1 << (log2_trafo_size * 2); -+ const int special = trans_skip_or_bypass || lc->tu.cross_pf; // These need special processinmg ++ const int special = lc->cu.cu_transquant_bypass_flag || trans_skip_or_bypass || lc->tu.cross_pf; // These need special processing + use_vpu = 0; + use_dc = (num_coeff == 1) && !special && + !(lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2); @@ -9173,7 +9219,14 @@ index 0000000000..e02c26fea6 + else + { + use_vpu = !special && log2_trafo_size >= 4; ++#if RPI_COMPRESS_COEFFS ++ use_compress = use_vpu && lc->jb0->coeffs.s[log2_trafo_size - 2].packed; ++#endif + coeffs = rpi_alloc_coeff_buf(lc->jb0, !use_vpu ? 0 : log2_trafo_size - 2, ccount); ++#if RPI_COMPRESS_COEFFS ++ coeffs32 = (int*)coeffs; ++ if (!use_compress) ++#endif +#if HAVE_NEON + rpi_zap_coeff_vals_neon(coeffs, log2_trafo_size - 2); +#else @@ -9291,6 +9344,25 @@ index 0000000000..e02c26fea6 + nb_significant_coeff_flag++; + } + } ++#if RPI_COMPRESS_COEFFS ++ if (use_compress && (nb_significant_coeff_flag + num_nonzero + 1 >= (1<<(2*log2_trafo_size-1)))) { // Overflow when half-full! ++ int16_t temp[32*32]; ++ const unsigned int ccount = 1 << (log2_trafo_size * 2); ++ lc->jb0->coeffs.s[log2_trafo_size - 2].packed = 0; ++ lc->jb0->coeffs.s[log2_trafo_size - 2].packed_n = lc->jb0->coeffs.s[log2_trafo_size - 2].n - ccount; // Don't want to unpack the last buffer ++ memcpy(temp, coeffs, sizeof(int)*num_nonzero); ++ coeffs32 = (int *)temp; ++ memset(coeffs, 0, ccount * sizeof(int16_t)); ++ num_nonzero--; ++ while (num_nonzero >= 0) { ++ const unsigned int res = coeffs32[num_nonzero]; ++ const unsigned int offset = res & 0xffff; ++ coeffs[ offset ] = res >> 16; ++ num_nonzero--; ++ } ++ use_compress = 0; ++ } ++#endif + + if (nb_significant_coeff_flag != 0) { + const unsigned int gt1_idx_delta = (c_idx_nz << 2) | @@ -9361,12 +9433,17 @@ index 0000000000..e02c26fea6 + const xy_off_t * const xy_off = scan_xy_off + significant_coeff_flag_idx[0]; + const int k = (int32_t)(coeff_sign_flag << 31) >> 31; + const unsigned int scale_m = blk_scale[xy_off->scale]; -+ -+ blk_coeffs[xy_off->coeff] = trans_scale_sat( ++ const int res = trans_scale_sat( + (trans_coeff_level ^ k) - k, // Apply sign + scale, + i == 0 && xy_off->coeff == 0 ? dc_scale : scale_m, + shift); ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) ++ coeffs32[num_nonzero++] = (res<<16) + (&blk_coeffs[xy_off->coeff] - coeffs); ++ else ++#endif ++ blk_coeffs[xy_off->coeff] = res; + } + } + else @@ -9443,8 +9520,14 @@ index 0000000000..e02c26fea6 + if (i == 0 && significant_coeff_flag_idx[m] == 0) + { + const int k = (int32_t)(coeff_sign_flags << m) >> 31; -+ blk_coeffs[0] = trans_scale_sat( ++ const int res = trans_scale_sat( + (levels[m] ^ k) - k, scale, dc_scale, shift); ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) ++ coeffs32[num_nonzero++] = (res<<16) + (blk_coeffs - coeffs); ++ else ++#endif ++ blk_coeffs[0] = res; + --m; + } + @@ -9457,12 +9540,17 @@ index 0000000000..e02c26fea6 + const xy_off_t * const xy_off = scan_xy_off + + significant_coeff_flag_idx[m]; + const int k = (int32_t)(coeff_sign_flags << m) >> 31; -+ -+ blk_coeffs[xy_off->coeff] = trans_scale_sat( ++ const int res = trans_scale_sat( + (levels[m] ^ k) - k, + scale, + blk_scale[xy_off->scale], + shift); ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) { ++ coeffs32[num_nonzero++] = (res<<16) + (&blk_coeffs[xy_off->coeff] - coeffs); ++ } else ++#endif ++ blk_coeffs[xy_off->coeff] = res; + } while (--m >= 0); + } + } @@ -9533,8 +9621,14 @@ index 0000000000..e02c26fea6 + } + } + -+ if (!use_dc) ++ if (!use_dc) { ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) { ++ coeffs32[num_nonzero] = 0; ++ } ++#endif + rpi_add_residual(s, lc->jb0, log2_trafo_size, c_idx, x0, y0, coeffs); ++ } +} + +#if !USE_BY22 @@ -11827,10 +11921,10 @@ index 0000000000..4b4d032a16 +#endif /* AVCODEC_RPI_HEVC_PARSE_H */ diff --git a/libavcodec/rpi_hevc_ps.c b/libavcodec/rpi_hevc_ps.c new file mode 100644 -index 0000000000..93fc26de88 +index 0000000000..f8abc30eef --- /dev/null +++ b/libavcodec/rpi_hevc_ps.c -@@ -0,0 +1,1765 @@ +@@ -0,0 +1,1789 @@ +/* + * HEVC Parameter Set decoding + * @@ -11904,14 +11998,14 @@ index 0000000000..93fc26de88 + { 2, 1 }, +}; + -+static void remove_pps(HEVCRpiParamSets *s, int id) ++static void remove_pps(HEVCRpiParamSets * const s, const int id) +{ + if (s->pps_list[id] && s->pps == (const HEVCRpiPPS*)s->pps_list[id]->data) + s->pps = NULL; + av_buffer_unref(&s->pps_list[id]); +} + -+static void remove_sps(HEVCRpiParamSets *s, int id) ++static void remove_sps(HEVCRpiParamSets * const s, const int id) +{ + int i; + if (s->sps_list[id]) { @@ -11928,7 +12022,7 @@ index 0000000000..93fc26de88 + av_buffer_unref(&s->sps_list[id]); +} + -+static void remove_vps(HEVCRpiParamSets *s, int id) ++static void remove_vps(HEVCRpiParamSets * const s, const int id) +{ + int i; + if (s->vps_list[id]) { @@ -11942,8 +12036,8 @@ index 0000000000..93fc26de88 + av_buffer_unref(&s->vps_list[id]); +} + -+int ff_hevc_rpi_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, -+ ShortTermRPS *rps, const HEVCRpiSPS *sps, int is_slice_header) ++int ff_hevc_rpi_decode_short_term_rps(GetBitContext * const gb, AVCodecContext * const avctx, ++ ShortTermRPS * const rps, const HEVCRpiSPS * const sps, const int is_slice_header) +{ + uint8_t rps_predict = 0; + int delta_poc; @@ -12088,8 +12182,8 @@ index 0000000000..93fc26de88 +} + + -+static int decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx, -+ PTLCommon *ptl) ++static int decode_profile_tier_level(GetBitContext * const gb, AVCodecContext * const avctx, ++ PTLCommon * const ptl) +{ + int i; + @@ -12128,8 +12222,8 @@ index 0000000000..93fc26de88 + return 0; +} + -+static int parse_ptl(GetBitContext *gb, AVCodecContext *avctx, -+ PTL *ptl, int max_num_sub_layers) ++static int parse_ptl(GetBitContext * const gb, AVCodecContext * const avctx, ++ PTL * const ptl, const int max_num_sub_layers) +{ + int i; + if (decode_profile_tier_level(gb, avctx, &ptl->general_ptl) < 0 || @@ -12168,8 +12262,8 @@ index 0000000000..93fc26de88 + return 0; +} + -+static void decode_sublayer_hrd(GetBitContext *gb, unsigned int nb_cpb, -+ int subpic_params_present) ++static void decode_sublayer_hrd(GetBitContext * const gb, const unsigned int nb_cpb, ++ const int subpic_params_present) +{ + int i; + @@ -12185,8 +12279,8 @@ index 0000000000..93fc26de88 + } +} + -+static int decode_hrd(GetBitContext *gb, int common_inf_present, -+ int max_sublayers) ++static int decode_hrd(GetBitContext * const gb, const int common_inf_present, ++ const int max_sublayers) +{ + int nal_params_present = 0, vcl_params_present = 0; + int subpic_params_present = 0; @@ -12247,8 +12341,8 @@ index 0000000000..93fc26de88 + return 0; +} + -+int ff_hevc_rpi_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, -+ HEVCRpiParamSets *ps) ++int ff_hevc_rpi_decode_nal_vps(GetBitContext * const gb, AVCodecContext * const avctx, ++ HEVCRpiParamSets * const ps) +{ + int i,j; + int vps_id = 0; @@ -12381,10 +12475,10 @@ index 0000000000..93fc26de88 + return AVERROR_INVALIDDATA; +} + -+static void decode_vui(GetBitContext *gb, AVCodecContext *avctx, -+ int apply_defdispwin, HEVCRpiSPS *sps) ++static void decode_vui(GetBitContext * const gb, AVCodecContext * const avctx, ++ const int apply_defdispwin, HEVCRpiSPS * const sps) +{ -+ VUI backup_vui, *vui = &sps->vui; ++ VUI backup_vui, * const vui = &sps->vui; + GetBitContext backup; + int sar_present, alt = 0; + @@ -12546,7 +12640,7 @@ index 0000000000..93fc26de88 + } +} + -+static void set_default_scaling_list_data(ScalingList *sl) ++static void set_default_scaling_list_data(ScalingList * const sl) +{ + int matrixId; + @@ -12576,7 +12670,8 @@ index 0000000000..93fc26de88 + memcpy(sl->sl[3][5], default_scaling_list_inter, 64); +} + -+static int scaling_list_data(GetBitContext *gb, AVCodecContext *avctx, ScalingList *sl, HEVCRpiSPS *sps) ++static int scaling_list_data(GetBitContext * const gb, AVCodecContext * const avctx, ScalingList * const sl, ++ const HEVCRpiSPS * const sps) +{ + uint8_t scaling_list_pred_mode_flag; + int32_t scaling_list_dc_coef[2][6]; @@ -12675,8 +12770,8 @@ index 0000000000..93fc26de88 + return 0; +} + -+int ff_hevc_rpi_parse_sps(HEVCRpiSPS *sps, GetBitContext *gb, unsigned int *sps_id, -+ int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx) ++static int ff_hevc_rpi_parse_sps(HEVCRpiSPS * const sps, GetBitContext * const gb, unsigned int * const sps_id, ++ const int apply_defdispwin, AVBufferRef * const * const vps_list, AVCodecContext * const avctx) +{ + HEVCWindow *ow; + int ret = 0; @@ -13104,8 +13199,8 @@ index 0000000000..93fc26de88 + av_freep(&pps); +} + -+static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, -+ HEVCRpiPPS *pps, HEVCRpiSPS *sps) { ++static int pps_range_extensions(GetBitContext * const gb, AVCodecContext * const avctx, ++ HEVCRpiPPS * const pps, const HEVCRpiSPS * const sps) { + int i; + + if (pps->transform_skip_enabled_flag) { @@ -13134,14 +13229,27 @@ index 0000000000..93fc26de88 + } + } + } -+ pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); -+ pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); ++ ++ { ++ const unsigned int max_offset = sps->bit_depth > 10 ? sps->bit_depth - 10 : 0; ++ ++ pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); ++ if (pps->log2_sao_offset_scale_luma > max_offset) { ++ av_log(avctx, AV_LOG_ERROR, "log2_sao_offset_scale_luma invalid"); ++ return AVERROR_INVALIDDATA; ++ } ++ pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); ++ if (pps->log2_sao_offset_scale_chroma > max_offset) { ++ av_log(avctx, AV_LOG_ERROR, "log2_sao_offset_scale_chroma invalid"); ++ return AVERROR_INVALIDDATA; ++ } ++ } + + return(0); +} + -+static inline int setup_pps(AVCodecContext *avctx, GetBitContext *gb, -+ HEVCRpiPPS *pps, HEVCRpiSPS *sps) ++static inline int setup_pps(AVCodecContext * const avctx, ++ HEVCRpiPPS * const pps, const HEVCRpiSPS * const sps) +{ + int log2_diff; + int pic_area_in_ctbs; @@ -13319,10 +13427,10 @@ index 0000000000..93fc26de88 + return 0; +} + -+int ff_hevc_rpi_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, -+ HEVCRpiParamSets *ps) ++int ff_hevc_rpi_decode_nal_pps(GetBitContext * const gb, AVCodecContext * const avctx, ++ HEVCRpiParamSets * const ps) +{ -+ HEVCRpiSPS *sps = NULL; ++ const HEVCRpiSPS *sps = NULL; + int i, ret = 0; + unsigned int pps_id = 0; + ptrdiff_t nal_size; @@ -13393,7 +13501,17 @@ index 0000000000..93fc26de88 + pps->cabac_init_present_flag = get_bits1(gb); + + pps->num_ref_idx_l0_default_active = get_ue_golomb_long(gb) + 1; ++ if (pps->num_ref_idx_l0_default_active < 1 || pps->num_ref_idx_l0_default_active > 15) { ++ av_log(avctx, AV_LOG_ERROR, "pps->num_ref_idx_l0_default_active invalid\n"); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } + pps->num_ref_idx_l1_default_active = get_ue_golomb_long(gb) + 1; ++ if (pps->num_ref_idx_l1_default_active < 1 || pps->num_ref_idx_l1_default_active > 15) { ++ av_log(avctx, AV_LOG_ERROR, "pps->num_ref_idx_l1_default_active invalid\n"); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } + + pps->pic_init_qp_minus26 = get_se_golomb(gb); + if (pps->pic_init_qp_minus26 > 25 || pps->pic_init_qp_minus26 < -(26 + sps->qp_bd_offset)) { @@ -13553,7 +13671,7 @@ index 0000000000..93fc26de88 + } + } + -+ ret = setup_pps(avctx, gb, pps, sps); ++ ret = setup_pps(avctx, pps, sps); + if (ret < 0) + goto err; + @@ -13598,10 +13716,10 @@ index 0000000000..93fc26de88 +} diff --git a/libavcodec/rpi_hevc_ps.h b/libavcodec/rpi_hevc_ps.h new file mode 100644 -index 0000000000..96c3739c4f +index 0000000000..3f192b70a4 --- /dev/null +++ b/libavcodec/rpi_hevc_ps.h -@@ -0,0 +1,447 @@ +@@ -0,0 +1,435 @@ +/* + * HEVC parameter set parsing + * @@ -14018,18 +14136,6 @@ index 0000000000..96c3739c4f + const HEVCRpiPPS *pps; +} HEVCRpiParamSets; + -+/** -+ * Parse the SPS from the bitstream into the provided HEVCRpiSPS struct. -+ * -+ * @param sps_id the SPS id will be written here -+ * @param apply_defdispwin if set 1, the default display window from the VUI -+ * will be applied to the video dimensions -+ * @param vps_list if non-NULL, this function will validate that the SPS refers -+ * to an existing VPS -+ */ -+int ff_hevc_rpi_parse_sps(HEVCRpiSPS *sps, GetBitContext *gb, unsigned int *sps_id, -+ int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx); -+ +int ff_hevc_rpi_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, + HEVCRpiParamSets *ps); +int ff_hevc_rpi_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, @@ -14049,130 +14155,6 @@ index 0000000000..96c3739c4f +int ff_hevc_rpi_compute_poc(const HEVCRpiSPS *sps, int pocTid0, int poc_lsb, int nal_unit_type); + +#endif /* AVCODEC_RPI_HEVC_PS_H */ -diff --git a/libavcodec/rpi_hevc_ps_enc.c b/libavcodec/rpi_hevc_ps_enc.c -new file mode 100644 -index 0000000000..7fa6af1cdf ---- /dev/null -+++ b/libavcodec/rpi_hevc_ps_enc.c -@@ -0,0 +1,118 @@ -+/* -+ * HEVC Parameter Set encoding -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "golomb.h" -+#include "rpi_hevc_ps.h" -+#include "put_bits.h" -+ -+static void write_ptl_layer(PutBitContext *pb, PTLCommon *ptl) -+{ -+ int i; -+ -+ put_bits(pb, 2, ptl->profile_space); -+ put_bits(pb, 1, ptl->tier_flag); -+ put_bits(pb, 5, ptl->profile_idc); -+ for (i = 0; i < 32; i++) -+ put_bits(pb, 1, ptl->profile_compatibility_flag[i]); -+ put_bits(pb, 1, ptl->progressive_source_flag); -+ put_bits(pb, 1, ptl->interlaced_source_flag); -+ put_bits(pb, 1, ptl->non_packed_constraint_flag); -+ put_bits(pb, 1, ptl->frame_only_constraint_flag); -+ put_bits32(pb, 0); // reserved -+ put_bits(pb, 12, 0); // reserved -+} -+ -+static void write_ptl(PutBitContext *pb, PTL *ptl, int max_num_sub_layers) -+{ -+ int i; -+ -+ write_ptl_layer(pb, &ptl->general_ptl); -+ put_bits(pb, 8, ptl->general_ptl.level_idc); -+ -+ for (i = 0; i < max_num_sub_layers - 1; i++) { -+ put_bits(pb, 1, ptl->sub_layer_profile_present_flag[i]); -+ put_bits(pb, 1, ptl->sub_layer_level_present_flag[i]); -+ } -+ -+ if (max_num_sub_layers > 1) -+ for (i = max_num_sub_layers - 1; i < 8; i++) -+ put_bits(pb, 2, 0); // reserved -+ -+ for (i = 0; i < max_num_sub_layers - 1; i++) { -+ if (ptl->sub_layer_profile_present_flag[i]) -+ write_ptl_layer(pb, &ptl->sub_layer_ptl[i]); -+ if (ptl->sub_layer_level_present_flag[i]) -+ put_bits(pb, 8, ptl->sub_layer_ptl[i].level_idc); -+ } -+} -+ -+int ff_hevc_rpi_encode_nal_vps(HEVCRpiVPS *vps, unsigned int id, -+ uint8_t *buf, int buf_size) -+{ -+ PutBitContext pb; -+ int i; -+ -+ init_put_bits(&pb, buf, buf_size); -+ put_bits(&pb, 4, id); -+ put_bits(&pb, 2, 3); // reserved -+ put_bits(&pb, 6, vps->vps_max_layers - 1); -+ put_bits(&pb, 3, vps->vps_max_sub_layers - 1); -+ put_bits(&pb, 1, vps->vps_temporal_id_nesting_flag); -+ put_bits(&pb, 16, 0xffff); // reserved -+ -+ write_ptl(&pb, &vps->ptl, vps->vps_max_sub_layers); -+ -+ put_bits(&pb, 1, vps->vps_sub_layer_ordering_info_present_flag); -+ for (i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_layers - 1; -+ i < vps->vps_max_sub_layers; i++) { -+ set_ue_golomb(&pb, vps->vps_max_dec_pic_buffering[i] - 1); -+ set_ue_golomb(&pb, vps->vps_num_reorder_pics[i]); -+ set_ue_golomb(&pb, vps->vps_max_latency_increase[i] + 1); -+ } -+ -+ put_bits(&pb, 6, vps->vps_max_layer_id); -+ set_ue_golomb(&pb, vps->vps_num_layer_sets - 1); -+ -+ if (vps->vps_num_layer_sets > 1) { -+ avpriv_report_missing_feature(NULL, "Writing layer_id_included_flag"); -+ return AVERROR_PATCHWELCOME; -+ } -+ -+ put_bits(&pb, 1, vps->vps_timing_info_present_flag); -+ if (vps->vps_timing_info_present_flag) { -+ put_bits32(&pb, vps->vps_num_units_in_tick); -+ put_bits32(&pb, vps->vps_time_scale); -+ put_bits(&pb, 1, vps->vps_poc_proportional_to_timing_flag); -+ if (vps->vps_poc_proportional_to_timing_flag) -+ set_ue_golomb(&pb, vps->vps_num_ticks_poc_diff_one - 1); -+ -+ if (vps->vps_num_hrd_parameters) { -+ avpriv_report_missing_feature(NULL, "Writing HRD parameters"); -+ return AVERROR_PATCHWELCOME; -+ } -+ } -+ -+ put_bits(&pb, 1, 0); // extension flag -+ -+ put_bits(&pb, 1, 1); // stop bit -+ avpriv_align_put_bits(&pb); -+ -+ return put_bits_count(&pb) / 8; -+} diff --git a/libavcodec/rpi_hevc_refs.c b/libavcodec/rpi_hevc_refs.c new file mode 100644 index 0000000000..d7745711ab @@ -19316,10 +19298,10 @@ index 0000000000..b9e7c07fe3 + diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s new file mode 100644 -index 0000000000..a08a1d6bef +index 0000000000..e14c0e099e --- /dev/null +++ b/libavcodec/rpi_hevc_transform.s -@@ -0,0 +1,927 @@ +@@ -0,0 +1,1090 @@ +# ****************************************************************************** +# Argon Design Ltd. +# (c) Copyright 2015 Argon Design Ltd. All rights reserved. @@ -19328,8 +19310,14 @@ index 0000000000..a08a1d6bef +# Author : Peter de Rivaz +# ****************************************************************************** + ++# USE_STACK = 1 means temporary data stored on the stack (requires build with larger stack) ++# USE_STACK = 0 means temporary data stored in fixed per-VPU data buffers (requires modifications to vasm to handle instruction encoding for PC relative instructions) ++.set USE_STACK, 0 ++ ++# Lines that fail to assemble start with #: ++# The script insert_magic_opcodes.sh inserts the machine code directly for these. +# HEVC VPU Transform -+# fe ++# +# Transform matrix can be thought of as +# output row vector = input row vector * transMatrix2 +# @@ -19411,15 +19399,35 @@ index 0000000000..a08a1d6bef +hevc_trans_16x16: + cmp r5,1 + beq memclear16 -+ cmp r5,2 -+ beq hevc_deblock_16x16 -+ cmp r5,3 -+ beq hevc_uv_deblock_16x16 -+ cmp r5,4 -+ beq hevc_uv_deblock_16x16_with_clear ++ #cmp r5,2 ++ #beq hevc_deblock_16x16 ++ #cmp r5,3 ++ #beq hevc_uv_deblock_16x16 ++ #cmp r5,4 ++ #beq hevc_uv_deblock_16x16_with_clear + cmp r5,5 + beq hevc_run_command_list + ++.if USE_STACK==0 ++ b do_transform ++ ++ .balign 32 ++packed_buffer: ++ .space 16*2 ++intermediate_results: ++ .space 32*32*2 ++unpacked_buffer: ++ .space 32*32*2 ++ ++packed_buffer2: ++ .space 16*2 ++intermediate_results2: ++ .space 32*32*2 ++unpacked_buffer2: ++ .space 32*32*2 ++.endif ++ ++do_transform: + push r6-r15, lr # TODO cut down number of used registers + mov r14,r3 # coeffs32 + mov r15,r4 # num32 @@ -19435,18 +19443,54 @@ index 0000000000..a08a1d6bef + mov r3,16*2 # Stride of coefficients in bytes (TODO remove) + mov r7,16*16*2 # Total block size + mov r8,64*16 # Value used to swap from current to next VRF location -+ vldh HX(0++,0)+r0,(r1 += r3) REP 16 + mov r4,64 # Constant used for rounding first pass + mov r5,TRANS_RND2 # Constant used for rounding second pass + ++ sub sp,sp,64+16*16*2 # Move on stack pointer in case interrupt occurs and uses stack ++ ++ add r11,sp,64 # Space for 32 bytes before, and rounding ++ lsr r11,5 ++ lsl r11,5 # Make sure r11 is rounded to multiple of 2**5==32 ++ ++ lsr r10, r2, 16 # Number of compressed blocks stored in top short ++ extu r2,16 + # At start of block r0,r1 point to the current block (that has already been loaded) ++ # r0 VRF location of current block ++ # r1 address of current block ++ # r2 number of 16*16 transforms to do ++ # r3 Stride of coefficients (==32) ++ # r4 TRANS_RND1 (64) ++ # r5 TRANS_RND2 ++ # r6 temporary used inside col_trans16 ++ # r7 16*16*2 total bytes in block ++ # r8 64*16 VRF switch locations ++ # r9 temporary in unpack_coeff for index ++ # r10 number of 16x16 transforms using compression ++ # r11 unpacked data buffer (16*16 shorts) (preceded by 16 shorts of packed data buffer) ++ # r12 temporary counter in unpack_coeff ++ # r13 ++ # r14 Save information for 32 bit transform (coeffs location) ++ # r15 Save information for 32 bit transform (number of transforms) ++ cmp r2,0 ++ beq done16x16s +block_loop: -+ eor r0,r8 -+ add r1,r7 ++ # With compressed coefficients, we don't use prefetch as we don't want to issue unnecessary memory requests ++ cmp r10,0 ++ mov r6, r1 ++ beq not_compressed ++ sub r10, 1 ++ bl unpack16x16 ++not_compressed: ++ #mov r6,r1 # DEBUG without compress ++ vldh HX(0++,0)+r0,(r6 += r3) REP 16 ++ #eor r0,r8 ++ #add r1,r7 + # Prefetch the next block -+ vldh HX(0++,0)+r0,(r1 += r3) REP 16 -+ eor r0,r8 -+ sub r1,r7 ++ #bl unpack16x16 ++ #vldh HX(0++,0)+r0,(r6 += r3) REP 16 ++ #vmov HX(0++,0)+r0,0 REP 16 # DEBUG ++ #eor r0,r8 ++ #sub r1,r7 + + # Transform the current block + bl col_trans_16 @@ -19468,11 +19512,49 @@ index 0000000000..a08a1d6bef + add r1,r7 + + addcmpbgt r2,-1,0,block_loop ++done16x16s: + ++ add sp,sp,64+16*16*2 # Move on stack pointer in case interrupt occurs and uses stack + # Now go and do any 32x32 transforms + b hevc_trans_32x32 + + pop r6-r15, pc ++# This returns a value in r6 that says where to load the data from. ++# We load data 16 shorts at a time from memory (uncached), and store to stack space to allow us to process it. ++unpack16x16: ++# Clear out destination ++ vmov HX(0,0)+r0,0 ++ mov r6, r11 ++ vsth HX(0,0)+r0,(r6 += r3) REP 16 ++ mov r5, r1 # Moving pointer to input coefficients ++unpack_outer_loop: ++ # Loop until we find the end ++ vldh HX(0,0)+r0,(r5) # TODO would prefetch help here while unpacking previous? ++ sub r6,r11,32 ++ #add r6,pc,packed_data-$ # Packed data ++ vsth HX(0,0)+r0,(r6) # Store into packed data ++ mov r12,0 ++unpack_loop: ++ ld r4,(r6) ++ add r6,r6,4 ++ lsr r9,r4,16 # r9 is destination value ++ cmp r4,0 # {value,index} ++ extu r4,8 ++ beq done_unpack ++ sth r9,(r11, r4) ++ addcmpblt r12,1,8,unpack_loop ++# # Read next 16 ++ add r5,32 ++ b unpack_outer_loop ++done_unpack: ++# # Set new load location ++ mov r6, r11 ++ #add r6,pc,unpacked_data-$ ++# # Restore constants ++ mov r4,64 ++ mov r5,TRANS_RND2 ++# pop r6-r15, pc ++ b lr + +# r1,r2,r3 r7,r8 should be preserved +# HX(0++,0)+r0 is the block to be transformed @@ -19501,14 +19583,50 @@ index 0000000000..a08a1d6bef + sub r0,16 # put r0 back to its original value + b lr + ++# r1/r10 input pointer ++# r0,r4,r5,r6 free ++# r8/r9 output storage ++# ++# Store packed coefficients at r9-32 ++# Store unpacked at r9+32*32 (because transform works on even/odd rows on input, but writes all rows) ++unpack32x32: ++# Clear out destination ++ vmov HX(0,0),0 ++ add r0, r9, 32*32*2 # Unpacked buffer ++ mov r4, 32 ++ vsth HX(0,0),(r0 += r4) REP 64 ++unpack_outer_loop32: ++ # Loop until we find the end ++ vldh HX(0,0),(r1) # TODO would prefetch help here while unpacking previous? ++ sub r6,r9,32 ++ #add r6,pc,packed_data-$ # Packed data ++ vsth HX(0,0),(r6) # Store into packed data ++ mov r8,0 ++unpack_loop32: ++ ld r4,(r6) ++ add r6,r6,4 ++ lsr r5,r4,16 # r5 is destination value ++ cmp r4,0 # {value,index} ++ extu r4,10 ++ beq done_unpack ++ sth r5,(r0, r4) ++ addcmpblt r8,1,8,unpack_loop32 ++# # Read next 16 ++ add r1,32 ++ b unpack_outer_loop32 ++done_unpack32: ++ b lr +# hevc_trans_32x32(short *transMatrix2, short *coeffs, int num) +# transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) Even followed by odd +# coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) -+# num: number of 16x16 transforms to be done ++# num: number of 16x16 transforms to be done in low 16, number of packed in high 16 +# ++# Note that the 32x32 transforms are stored in reverse order, this means that the unpacked ones appear first! +hevc_trans_32x32: + mov r1,r14 # coeffs + mov r2,r15 # num ++ lsr r15,r15,16 # Number that are packed ++ extu r2,16 # Total number + + # Fetch odd transform matrix + #mov r3, 16*2 # Stride of transMatrix2 in bytes (and of coefficients) @@ -19518,22 +19636,46 @@ index 0000000000..a08a1d6bef + + mov r3, 32*2*2 # Stride used to fetch alternate rows of our input coefficient buffer + mov r7, 16*16*2 # Total block size -+ sub sp,sp,32*32*2+32 # Allocate some space on the stack for us to store 32*32 shorts as temporary results (needs to be aligned) -+ # set r8 to 32byte aligned stack pointer -+ add r8,sp,31 ++ ++.if USE_STACK ++ # Stack base allocation ++ sub sp,sp,32*32*4+64 # Allocate some space on the stack for us to store 32*32 shorts as temporary results (needs to be aligned) and another 32*32 for unpacking ++ # set r8 to 32byte aligned stack pointer with 32 bytes of space before it ++ add r8,sp,63 + lsr r8,5 + lsl r8,5 ++.else ++#:version r8 ++ .half 0x00e8 #AUTOINSERTED ++ btst r8,16 ++#:add r8,pc,intermediate_results-$ ++ .half 0xbfe8 ++ .half intermediate_results-($-2) ++ beq on_vpu1 ++ add r8,r8,32*32*2*2+16*2 # Move to secondary storage ++on_vpu1: ++.endif + mov r9,r8 # Backup of the temporary storage + mov r10,r1 # Backup of the coefficient buffer -+block_loop32: + -+ # COLUMN TRANSFORM -+ mov r4, 64 # Constant used for rounding first pass -+ mov r5, 9 # left shift used for rounding first pass ++ cmp r2,0 ++ beq done32x32s ++block_loop32: + + # Transform the first 16 columns + mov r1,r10 # Input Coefficient buffer + mov r8,r9 # Output temporary storage ++ # Unpacked are first, so need to only do unpacking when r2(=num left) <= r15 (=num packed) ++ cmp r2,r15 ++ bgt not_compressed_32 ++ bl unpack32x32 ++ add r1,r9,32*32*2 # Uncompressed into temporary storage ++ mov r8,r9 # Transform into here ++not_compressed_32: ++ # COLUMN TRANSFORM ++ mov r4, 64 # Constant used for rounding first pass ++ mov r5, 9 # left shift used for rounding first pass ++ + bl trans32 + # Transform the second 16 columns + add r8,32*16*2 @@ -19554,8 +19696,11 @@ index 0000000000..a08a1d6bef + + add r10, 32*32*2 # move onto next block of coefficients + addcmpbgt r2,-1,0,block_loop32 ++done32x32s: + -+ add sp,sp,32*32*2+32 # Restore stack ++.if USE_STACK ++ add sp,sp,32*32*4+64# Restore stack ++.endif + + pop r6-r15, pc + @@ -20249,41 +20394,8299 @@ index 0000000000..a08a1d6bef + pop r6-r7, pc diff --git a/libavcodec/rpi_hevc_transform10.h b/libavcodec/rpi_hevc_transform10.h new file mode 100644 -index 0000000000..ee4e357f38 +index 0000000000..d5c2661186 --- /dev/null +++ b/libavcodec/rpi_hevc_transform10.h -@@ -0,0 +1,3110 @@ +@@ -0,0 +1,11602 @@ +static const unsigned char rpi_hevc_transform10 [] = { +21, +106, +0, +144, -+47, -+1, -+37, -+106, -+0, -+144, -+66, -+1, -+53, -+106, -+0, -+144, -+192, -+4, -+69, -+106, -+0, -+144, -+192, -+4, ++197, ++17, +85, +106, +0, +144, -+240, -+5, ++143, ++22, ++0, ++158, ++42, ++16, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, +169, +3, +62, @@ -20342,16 +28745,6 @@ index 0000000000..ee4e357f38 +4, +0, +0, -+12, -+248, -+0, -+128, -+0, -+0, -+192, -+8, -+4, -+0, +4, +232, +64, @@ -20364,10 +28757,44 @@ index 0000000000..ee4e357f38 +2, +0, +0, ++57, ++239, ++192, ++253, ++255, ++255, ++43, ++239, ++64, ++0, ++0, ++0, ++91, ++122, ++91, ++124, ++74, ++195, ++80, ++23, ++2, ++111, ++2, ++106, ++50, ++24, ++10, ++106, ++22, ++64, ++4, ++24, ++26, ++102, +128, -+69, -+113, -+66, ++144, ++51, ++0, +12, +248, +0, @@ -20376,15 +28803,11 @@ index 0000000000..ee4e357f38 +0, +192, +8, -+4, ++24, +0, +128, -+69, -+113, -+70, -+128, +144, -+40, ++94, +0, +4, +255, @@ -20418,7 +28841,7 @@ index 0000000000..ee4e357f38 +0, +128, +144, -+23, ++77, +0, +4, +255, @@ -20456,12 +28879,120 @@ index 0000000000..ee4e357f38 +66, +242, +140, -+211, ++209, +192, -+34, -+31, ++57, ++239, ++64, ++2, ++0, ++0, ++0, ++158, ++127, ++0, +41, +3, ++0, ++254, ++0, ++128, ++0, ++4, ++0, ++0, ++0, ++0, ++182, ++64, ++140, ++248, ++32, ++0, ++0, ++0, ++0, ++48, ++24, ++0, ++21, ++64, ++8, ++248, ++0, ++128, ++0, ++0, ++192, ++3, ++20, ++0, ++102, ++237, ++224, ++255, ++255, ++255, ++136, ++248, ++32, ++0, ++0, ++0, ++0, ++240, ++24, ++0, ++12, ++96, ++100, ++8, ++70, ++192, ++68, ++55, ++73, ++195, ++80, ++39, ++4, ++106, ++132, ++110, ++9, ++24, ++105, ++160, ++4, ++95, ++28, ++139, ++246, ++200, ++69, ++232, ++32, ++0, ++0, ++0, ++99, ++31, ++182, ++64, ++4, ++232, ++64, ++0, ++0, ++0, ++5, ++232, ++0, ++2, ++0, ++0, ++90, ++0, +70, +192, +80, @@ -20526,10 +29057,100 @@ index 0000000000..ee4e357f38 +103, +90, +0, ++0, ++246, ++0, ++128, ++0, ++4, ++32, ++237, ++0, ++8, ++0, ++0, ++4, ++232, ++32, ++0, ++0, ++0, ++142, ++248, ++32, ++0, ++0, ++0, ++192, ++67, ++0, ++0, ++8, ++240, ++0, ++128, ++129, ++3, ++38, ++237, ++224, ++255, ++255, ++255, ++136, ++240, ++32, ++0, ++134, ++3, ++8, ++96, ++100, ++8, ++70, ++192, ++68, ++55, ++69, ++195, ++80, ++39, ++4, ++106, ++164, ++110, ++127, ++144, ++185, ++255, ++101, ++160, ++4, ++7, ++24, ++139, ++245, ++200, ++65, ++232, ++32, ++0, ++0, ++0, ++102, ++31, ++90, ++0, +225, +64, +242, +64, ++79, ++195, ++80, ++127, ++2, ++111, +3, +232, +128, @@ -20542,24 +29163,50 @@ index 0000000000..ee4e357f38 +2, +0, +0, -+57, -+239, -+224, -+247, -+255, -+255, -+72, -+192, -+95, -+207, -+88, -+122, -+88, -+124, ++232, ++0, ++8, ++109, ++232, ++191, ++0, ++222, ++4, ++24, ++8, ++237, ++32, ++16, ++0, ++0, +137, +64, +26, +64, ++2, ++106, ++46, ++24, ++161, ++64, ++152, ++64, ++242, ++74, ++7, ++30, ++255, ++159, ++187, ++255, ++33, ++237, ++0, ++8, ++0, ++0, ++152, ++64, +4, +232, +64, @@ -20568,13 +29215,9 @@ index 0000000000..ee4e357f38 +0, +149, +96, -+161, -+64, -+152, -+64, +128, +144, -+35, ++32, +0, +72, +232, @@ -20590,7 +29233,7 @@ index 0000000000..ee4e357f38 +0, +128, +144, -+27, ++24, +0, +4, +232, @@ -20606,7 +29249,7 @@ index 0000000000..ee4e357f38 +64, +128, +144, -+19, ++16, +0, +72, +232, @@ -20622,7 +29265,7 @@ index 0000000000..ee4e357f38 +0, +128, +144, -+11, ++8, +0, +74, +232, @@ -20632,14 +29275,8 @@ index 0000000000..ee4e357f38 +0, +242, +140, -+221, ++213, +192, -+57, -+239, -+32, -+8, -+0, -+0, +41, +3, +239, @@ -20668,7 +29305,7 @@ index 0000000000..ee4e357f38 +96, +255, +159, -+154, ++101, +255, +0, +232, @@ -20678,7 +29315,7 @@ index 0000000000..ee4e357f38 +0, +255, +159, -+165, ++112, +255, +4, +255, @@ -23352,8 +31989,8 @@ index 0000000000..ee4e357f38 +98, +255, +159, -+244, -+249, ++94, ++233, +23, +102, +7, @@ -23365,41 +32002,8299 @@ index 0000000000..ee4e357f38 +}; diff --git a/libavcodec/rpi_hevc_transform8.h b/libavcodec/rpi_hevc_transform8.h new file mode 100644 -index 0000000000..56d5206827 +index 0000000000..2ba8583694 --- /dev/null +++ b/libavcodec/rpi_hevc_transform8.h -@@ -0,0 +1,3110 @@ +@@ -0,0 +1,11602 @@ +static const unsigned char rpi_hevc_transform8 [] = { +21, +106, +0, +144, -+47, -+1, -+37, -+106, -+0, -+144, -+66, -+1, -+53, -+106, -+0, -+144, -+192, -+4, -+69, -+106, -+0, -+144, -+192, -+4, ++197, ++17, +85, +106, +0, +144, -+240, -+5, ++143, ++22, ++0, ++158, ++42, ++16, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, ++0, +169, +3, +62, @@ -23458,16 +40353,6 @@ index 0000000000..56d5206827 +4, +0, +0, -+12, -+248, -+0, -+128, -+0, -+0, -+192, -+8, -+4, -+0, +4, +232, +64, @@ -23480,10 +40365,44 @@ index 0000000000..56d5206827 +8, +0, +0, ++57, ++239, ++192, ++253, ++255, ++255, ++43, ++239, ++64, ++0, ++0, ++0, ++91, ++122, ++91, ++124, ++74, ++195, ++80, ++23, ++2, ++111, ++2, ++106, ++50, ++24, ++10, ++106, ++22, ++64, ++4, ++24, ++26, ++102, +128, -+69, -+113, -+66, ++144, ++51, ++0, +12, +248, +0, @@ -23492,15 +40411,11 @@ index 0000000000..56d5206827 +0, +192, +8, -+4, ++24, +0, +128, -+69, -+113, -+70, -+128, +144, -+40, ++94, +0, +4, +255, @@ -23534,7 +40449,7 @@ index 0000000000..56d5206827 +0, +128, +144, -+23, ++77, +0, +4, +255, @@ -23572,12 +40487,120 @@ index 0000000000..56d5206827 +66, +242, +140, -+211, ++209, +192, -+34, -+31, ++57, ++239, ++64, ++2, ++0, ++0, ++0, ++158, ++127, ++0, +41, +3, ++0, ++254, ++0, ++128, ++0, ++4, ++0, ++0, ++0, ++0, ++182, ++64, ++140, ++248, ++32, ++0, ++0, ++0, ++0, ++48, ++24, ++0, ++21, ++64, ++8, ++248, ++0, ++128, ++0, ++0, ++192, ++3, ++20, ++0, ++102, ++237, ++224, ++255, ++255, ++255, ++136, ++248, ++32, ++0, ++0, ++0, ++0, ++240, ++24, ++0, ++12, ++96, ++100, ++8, ++70, ++192, ++68, ++55, ++73, ++195, ++80, ++39, ++4, ++106, ++132, ++110, ++9, ++24, ++105, ++160, ++4, ++95, ++28, ++139, ++246, ++200, ++69, ++232, ++32, ++0, ++0, ++0, ++99, ++31, ++182, ++64, ++4, ++232, ++64, ++0, ++0, ++0, ++5, ++232, ++0, ++8, ++0, ++0, ++90, ++0, +70, +192, +80, @@ -23642,10 +40665,100 @@ index 0000000000..56d5206827 +103, +90, +0, ++0, ++246, ++0, ++128, ++0, ++4, ++32, ++237, ++0, ++8, ++0, ++0, ++4, ++232, ++32, ++0, ++0, ++0, ++142, ++248, ++32, ++0, ++0, ++0, ++192, ++67, ++0, ++0, ++8, ++240, ++0, ++128, ++129, ++3, ++38, ++237, ++224, ++255, ++255, ++255, ++136, ++240, ++32, ++0, ++134, ++3, ++8, ++96, ++100, ++8, ++70, ++192, ++68, ++55, ++69, ++195, ++80, ++39, ++4, ++106, ++164, ++110, ++127, ++144, ++185, ++255, ++101, ++160, ++4, ++7, ++24, ++139, ++245, ++200, ++65, ++232, ++32, ++0, ++0, ++0, ++102, ++31, ++90, ++0, +225, +64, +242, +64, ++79, ++195, ++80, ++127, ++2, ++111, +3, +232, +128, @@ -23658,24 +40771,50 @@ index 0000000000..56d5206827 +2, +0, +0, -+57, -+239, -+224, -+247, -+255, -+255, -+72, -+192, -+95, -+207, -+88, -+122, -+88, -+124, ++232, ++0, ++8, ++109, ++232, ++191, ++0, ++222, ++4, ++24, ++8, ++237, ++32, ++16, ++0, ++0, +137, +64, +26, +64, ++2, ++106, ++46, ++24, ++161, ++64, ++152, ++64, ++242, ++74, ++7, ++30, ++255, ++159, ++187, ++255, ++33, ++237, ++0, ++8, ++0, ++0, ++152, ++64, +4, +232, +64, @@ -23684,13 +40823,9 @@ index 0000000000..56d5206827 +0, +149, +96, -+161, -+64, -+152, -+64, +128, +144, -+35, ++32, +0, +72, +232, @@ -23706,7 +40841,7 @@ index 0000000000..56d5206827 +0, +128, +144, -+27, ++24, +0, +4, +232, @@ -23722,7 +40857,7 @@ index 0000000000..56d5206827 +64, +128, +144, -+19, ++16, +0, +72, +232, @@ -23738,7 +40873,7 @@ index 0000000000..56d5206827 +0, +128, +144, -+11, ++8, +0, +74, +232, @@ -23748,14 +40883,8 @@ index 0000000000..56d5206827 +0, +242, +140, -+221, ++213, +192, -+57, -+239, -+32, -+8, -+0, -+0, +41, +3, +239, @@ -23784,7 +40913,7 @@ index 0000000000..56d5206827 +96, +255, +159, -+154, ++101, +255, +0, +232, @@ -23794,7 +40923,7 @@ index 0000000000..56d5206827 +0, +255, +159, -+165, ++112, +255, +4, +255, @@ -26468,8 +43597,8 @@ index 0000000000..56d5206827 +98, +255, +159, -+244, -+249, ++94, ++233, +23, +102, +7, @@ -26481,10 +43610,10 @@ index 0000000000..56d5206827 +}; diff --git a/libavcodec/rpi_hevcdec.c b/libavcodec/rpi_hevcdec.c new file mode 100644 -index 0000000000..3cee92a11f +index 0000000000..fac0dde400 --- /dev/null +++ b/libavcodec/rpi_hevcdec.c -@@ -0,0 +1,5705 @@ +@@ -0,0 +1,5738 @@ +/* + * HEVC video Decoder + * @@ -26677,6 +43806,19 @@ index 0000000000..3cee92a11f + ipe_chan_info_t chroma; +} ipe_init_info_t; + ++static void *small_memset(void *s, int c, size_t n) ++{ ++ if (n == 1) ++ *(int8_t *) s = c; ++ else if (n == 2) ++ *(int16_t *) s = c * 0x0101; ++ else if (n == 4) ++ *(int32_t *) s = c * 0x01010101; ++ else ++ return memset(s, c, n); ++ return s; ++} ++ +static const ipe_init_info_t ipe_init_infos[9] = { // Alloc for bit depths of 8-16 + { // 8 + .luma = {8, QPU_MC_PRED_N_Y8, inter_pred_setup_y_qpu, inter_pred_sync_qpu, inter_pred_exit_y_qpu}, @@ -27172,6 +44314,10 @@ index 0000000000..3cee92a11f + unsigned int i; + for (i = 0; i != 4; ++i) { + cf->s[i].n = 0; ++#if RPI_COMPRESS_COEFFS ++ cf->s[i].packed = 1; ++ cf->s[i].packed_n = 0; ++#endif + } +} + @@ -29497,7 +46643,7 @@ index 0000000000..3cee92a11f + if (!size_in_pus) + size_in_pus = 1; + for (i = 0; i < size_in_pus; i++) { -+ memset(&s->tab_ipm[(y_pu + i) * min_pu_width + x_pu], ++ small_memset(&s->tab_ipm[(y_pu + i) * min_pu_width + x_pu], + intra_pred_mode, size_in_pus); + + for (j = 0; j < size_in_pus; j++) { @@ -29517,7 +46663,7 @@ index 0000000000..3cee92a11f + int y; + + for (y = 0; y < length; y++) -+ memset(&s->tab_ct_depth[(y_cb + y) * s->ps.sps->min_cb_width + x_cb], ++ small_memset(&s->tab_ct_depth[(y_cb + y) * s->ps.sps->min_cb_width + x_cb], + ct_depth, length); +} + @@ -29607,7 +46753,7 @@ index 0000000000..3cee92a11f + if (size_in_pus == 0) + size_in_pus = 1; + for (j = 0; j < size_in_pus; j++) -+ memset(&s->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, size_in_pus); ++ small_memset(&s->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, size_in_pus); + if (lc->cu.pred_mode == MODE_INTRA) + for (j = 0; j < size_in_pus; j++) + for (k = 0; k < size_in_pus; k++) @@ -29647,14 +46793,14 @@ index 0000000000..3cee92a11f + + x = y_cb * min_cb_width + x_cb; + for (y = 0; y < length; y++) { -+ memset(&s->skip_flag[x], skip_flag, length); ++ small_memset(&s->skip_flag[x], skip_flag, length); + x += min_cb_width; + } + lc->cu.pred_mode = skip_flag ? MODE_SKIP : MODE_INTER; + } else { + x = y_cb * min_cb_width + x_cb; + for (y = 0; y < length; y++) { -+ memset(&s->skip_flag[x], 0, length); ++ small_memset(&s->skip_flag[x], 0, length); + x += min_cb_width; + } + } @@ -29764,7 +46910,7 @@ index 0000000000..3cee92a11f + + x = y_cb * min_cb_width + x_cb; + for (y = 0; y < length; y++) { -+ memset(&s->qp_y_tab[x], lc->qp_y, length); ++ small_memset(&s->qp_y_tab[x], lc->qp_y, length); + x += min_cb_width; + } + @@ -30273,13 +47419,29 @@ index 0000000000..3cee92a11f + { + const unsigned int csize = sizeof(cf->s[3].buf[0]); + const unsigned int offset32 = ((cf->s[3].buf - cf->s[2].buf) - cf->s[3].n) * csize; ++ unsigned int n16 = (cf->s[2].n >> 8); ++ unsigned int n32 = (cf->s[3].n >> 10); ++#if RPI_COMPRESS_COEFFS ++ if (cf->s[2].packed) { ++ n16 = n16 | (n16<<16); ++ } else { ++ const unsigned int npack16 = (cf->s[2].packed_n>>8); ++ n16 = n16 | (npack16<<16); ++ } ++ if (cf->s[3].packed) { ++ n32 = n32 | (n32<<16); ++ } else { ++ const unsigned int npack32 = (cf->s[3].packed_n>>10); ++ n32 = n32 | (npack32<<16); ++ } ++#endif + vpu_qpu_job_add_vpu(vqj, + vpu_get_fn(s->ps.sps->bit_depth), + vpu_get_constants(), + cf->gptr.vc, -+ cf->s[2].n >> 8, ++ n16, + cf->gptr.vc + offset32, -+ cf->s[3].n >> 10, ++ n32, + 0); + + rpi_cache_flush_add_gm_range(rfe, &cf->gptr, RPI_CACHE_FLUSH_MODE_WB_INVALIDATE, 0, cf->s[2].n * csize); @@ -31922,7 +49084,7 @@ index 0000000000..3cee92a11f + } +#endif +#if !RPI_QPU_EMU_Y || !RPI_QPU_EMU_C -+ s->qpu_dummy_frame_qpu = qpu_fn(mc_start); // Use our code as a dummy frame ++ s->qpu_dummy_frame_qpu = qpu_dummy(); +#endif + + bt_lc_init(s, s->HEVClc, 0); @@ -32192,10 +49354,10 @@ index 0000000000..3cee92a11f + diff --git a/libavcodec/rpi_hevcdec.h b/libavcodec/rpi_hevcdec.h new file mode 100644 -index 0000000000..fcbf102fa1 +index 0000000000..59d7be4fe8 --- /dev/null +++ b/libavcodec/rpi_hevcdec.h -@@ -0,0 +1,1060 @@ +@@ -0,0 +1,1066 @@ +/* + * HEVC video decoder + * @@ -32296,6 +49458,8 @@ index 0000000000..fcbf102fa1 +// Print out various usage stats +#define RPI_TSTATS 0 + ++// Define RPI_COMPRESS_COEFFS to 1 to send coefficients in compressed form ++#define RPI_COMPRESS_COEFFS 1 +// Define RPI_DEBLOCK_VPU to perform deblocking on the VPUs +// (currently slower than deblocking on the ARM) +// #define RPI_DEBLOCK_VPU @@ -32749,6 +49913,10 @@ index 0000000000..fcbf102fa1 + +typedef struct HEVCRpiCoeffEnv { + unsigned int n; ++#if RPI_COMPRESS_COEFFS ++ unsigned int packed; // Equal to 1 if coefficients should be being packed ++ unsigned int packed_n; // Value of n when packed was set equal to 0 (i.e. the amount that is sent compressed). Only valid if packed==0 ++#endif + int16_t * buf; +} HEVCRpiCoeffEnv; + @@ -37404,10 +54572,10 @@ index 0000000000..b3168788d2 +#endif diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c new file mode 100644 -index 0000000000..4a8b328236 +index 0000000000..89d6220684 --- /dev/null +++ b/libavcodec/rpi_qpu.c -@@ -0,0 +1,920 @@ +@@ -0,0 +1,954 @@ +#include +#include +#include @@ -37449,7 +54617,7 @@ index 0000000000..4a8b328236 + +// Size in 32bit words +#define QPU_CODE_SIZE 4098 -+#define VPU_CODE_SIZE 2048 ++#define VPU_CODE_SIZE 16384 + +static const short rpi_transMatrix2even[32][16] = { // Even rows first +{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, @@ -37490,7 +54658,7 @@ index 0000000000..4a8b328236 +// Code/constants on GPU +struct GPU +{ -+ unsigned int qpu_code[QPU_CODE_SIZE]; ++// unsigned int qpu_code[QPU_CODE_SIZE]; + unsigned int vpu_code8[VPU_CODE_SIZE]; + unsigned int vpu_code10[VPU_CODE_SIZE]; + short transMatrix2even[16*16*2]; @@ -37540,7 +54708,9 @@ index 0000000000..4a8b328236 + int init_count; + int mb; + int vpu_i_cache_flushed; ++ GPU_MEM_PTR_T qpu_code_gm_ptr; + GPU_MEM_PTR_T code_gm_ptr; ++ GPU_MEM_PTR_T dummy_gm_ptr; + vq_wait_pool_t wait_pool; +#if RPI_TRACE_TIME_VPU_QPU_WAIT + trace_time_wait_t ttw; @@ -37629,6 +54799,20 @@ index 0000000000..4a8b328236 + return 0; +} + ++static int gpu_malloc_vccached_internal(const int mb, const int numbytes, GPU_MEM_PTR_T * const p) { ++ p->numbytes = numbytes; ++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_VC , (char *)"VPU code" ); ++ av_assert0(p->vcsm_handle); ++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); ++ av_assert0(p->vc_handle); ++ p->arm = vcsm_lock(p->vcsm_handle); ++ av_assert0(p->arm); ++ p->vc = mbox_mem_lock(mb, p->vc_handle) & 0x3fffffff; // ??? If I want caching then lose the top 2 bits ++ av_assert0(p->vc); ++// printf("***** %s, %d\n", __func__, numbytes); ++ return 0; ++} ++ +static int gpu_malloc_uncached_internal(const int mb, const int numbytes, GPU_MEM_PTR_T * const p) { + p->numbytes = numbytes; + p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE | 0x80, (char *)"Video Frame" ); @@ -37664,6 +54848,8 @@ index 0000000000..4a8b328236 + vc_gpuserv_deinit(); + + gpu_free_internal(ge->mb, &ge->code_gm_ptr); ++ gpu_free_internal(ge->mb, &ge->qpu_code_gm_ptr); ++ gpu_free_internal(ge->mb, &ge->dummy_gm_ptr); + + vcsm_exit(); + @@ -37691,19 +54877,22 @@ index 0000000000..4a8b328236 + + vcsm_init(); + -+ gpu_malloc_uncached_internal(ge->mb, sizeof(struct GPU), &ge->code_gm_ptr); ++ // Now copy over the QPU code into GPU memory ++ gpu_malloc_uncached_internal(ge->mb, QPU_CODE_SIZE*4, &ge->qpu_code_gm_ptr); ++ ++ { ++ int num_bytes = (char *)mc_end - (char *)ff_hevc_rpi_shader; ++ av_assert0(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy(ge->qpu_code_gm_ptr.arm, ff_hevc_rpi_shader, num_bytes); ++ memset(ge->qpu_code_gm_ptr.arm + num_bytes, 0, QPU_CODE_SIZE*4 - num_bytes); ++ } ++ ++ // And the VPU code ++ gpu_malloc_vccached_internal(ge->mb, sizeof(struct GPU), &ge->code_gm_ptr); + ptr = (volatile struct GPU*)ge->code_gm_ptr.arm; + + // Zero everything so we have zeros between the code bits + memset((void *)ptr, 0, sizeof(*ptr)); -+ -+ // Now copy over the QPU code into GPU memory -+ { -+ int num_bytes = (char *)mc_end - (char *)ff_hevc_rpi_shader; -+ av_assert0(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); -+ memcpy((void*)ptr->qpu_code, ff_hevc_rpi_shader, num_bytes); -+ } -+ // And the VPU code + { + int num_bytes = sizeof(rpi_hevc_transform8); + av_assert0(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); @@ -37717,6 +54906,11 @@ index 0000000000..4a8b328236 + // And the transform coefficients + memcpy((void*)ptr->transMatrix2even, rpi_transMatrix2even, sizeof(rpi_transMatrix2even)); + ++ // Generate a dummy "frame" & fill with 0x80 ++ // * Could reset to 1 <mb, 0x4000, &ge->dummy_gm_ptr); ++ memset(ge->dummy_gm_ptr.arm, 0x80, 0x4000); ++ + *gpu = ge; + return 0; +} @@ -37804,22 +54998,26 @@ index 0000000000..4a8b328236 +} + +unsigned int vpu_get_fn(const unsigned int bit_depth) { ++ uint32_t a = 0; ++ + // Make sure that the gpu is initialized + av_assert0(gpu != NULL); + switch (bit_depth){ + case 8: -+ return gpu->code_gm_ptr.vc + offsetof(struct GPU, vpu_code8); ++ a = gpu->code_gm_ptr.vc + offsetof(struct GPU, vpu_code8); ++ break; + case 10: -+ return gpu->code_gm_ptr.vc + offsetof(struct GPU, vpu_code10); ++ a = gpu->code_gm_ptr.vc + offsetof(struct GPU, vpu_code10); ++ break; + default: + av_assert0(0); + } -+ return 0; ++ return a; +} + +unsigned int vpu_get_constants(void) { + av_assert0(gpu != NULL); -+ return gpu->code_gm_ptr.vc + offsetof(struct GPU,transMatrix2even); ++ return (gpu->code_gm_ptr.vc + offsetof(struct GPU,transMatrix2even)); +} + +int gpu_get_mailbox(void) @@ -38288,9 +55486,13 @@ index 0000000000..4a8b328236 + +uint32_t qpu_fn(const int * const mc_fn) +{ -+ return gpu->code_gm_ptr.vc + ((const char *)mc_fn - (const char *)ff_hevc_rpi_shader) + offsetof(struct GPU, qpu_code); ++ return gpu->qpu_code_gm_ptr.vc + ((const char *)mc_fn - (const char *)ff_hevc_rpi_shader); +} + ++uint32_t qpu_dummy(void) ++{ ++ return gpu->dummy_gm_ptr.vc; ++} + +int rpi_hevc_qpu_init_fn(HEVCRpiQpu * const qf, const unsigned int bit_depth) +{ @@ -38330,10 +55532,10 @@ index 0000000000..4a8b328236 + diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h new file mode 100644 -index 0000000000..1aac6babae +index 0000000000..f75be88ad4 --- /dev/null +++ b/libavcodec/rpi_qpu.h -@@ -0,0 +1,227 @@ +@@ -0,0 +1,228 @@ +#ifndef RPI_QPU_H +#define RPI_QPU_H + @@ -38516,6 +55718,7 @@ index 0000000000..1aac6babae +int rpi_hevc_qpu_init_fn(HEVCRpiQpu * const qf, const unsigned int bit_depth); + +uint32_t qpu_fn(const int * const mc_fn); ++uint32_t qpu_dummy(void); + +#define QPU_N_GRP 4 +#define QPU_N_MAX 12