| /* | 
 |  * Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved | 
 |  * | 
 |  * This source code is subject to the terms of the BSD 2 Clause License and | 
 |  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | 
 |  * was not distributed with this source code in the LICENSE file, you can | 
 |  * obtain it at www.aomedia.org/license/software. If the Alliance for Open | 
 |  * Media Patent License 1.0 was not distributed with this source code in the | 
 |  * PATENTS file, you can obtain it at www.aomedia.org/license/patent. | 
 |  */ | 
 |  | 
 | /* clang-format off */ | 
 |  | 
 | #ifdef HAVE_CONFIG_H | 
 | # include "config.h" | 
 | #endif | 
 |  | 
 | #include "enums.h" | 
 | #include "odintrin.h" | 
 | #include "partition.h" | 
 | #include "zigzag.h" | 
 |  | 
 | OD_EXTERN const index_pair *OD_ZIGZAG4[4] = { | 
 |   OD_ZIGZAG4_DCT_DCT, | 
 |   OD_ZIGZAG4_ADST_DCT, | 
 |   OD_ZIGZAG4_DCT_ADST, | 
 |   OD_ZIGZAG4_ADST_ADST | 
 | }; | 
 |  | 
 | OD_EXTERN const index_pair *OD_ZIGZAG8[4] = { | 
 |   OD_ZIGZAG8_DCT_DCT, | 
 |   OD_ZIGZAG8_ADST_DCT, | 
 |   OD_ZIGZAG8_DCT_ADST, | 
 |   OD_ZIGZAG8_ADST_ADST | 
 | }; | 
 |  | 
 | OD_EXTERN const index_pair *OD_ZIGZAG16[4] = { | 
 |   OD_ZIGZAG16_DCT_DCT, | 
 |   OD_ZIGZAG16_ADST_DCT, | 
 |   OD_ZIGZAG16_DCT_ADST, | 
 |   OD_ZIGZAG16_ADST_ADST | 
 | }; | 
 |  | 
 | OD_EXTERN const index_pair *OD_ZIGZAG32[4] = { | 
 |   OD_ZIGZAG32_DCT_DCT, | 
 |   OD_ZIGZAG32_DCT_DCT, | 
 |   OD_ZIGZAG32_DCT_DCT, | 
 |   OD_ZIGZAG32_DCT_DCT | 
 | }; | 
 |  | 
 | /* The tables below specify how coefficient blocks are translated to | 
 |    and from PVQ partition coding scan order for 4x4, 8x8 and 16x16 */ | 
 |  | 
 | static const int OD_LAYOUT32_OFFSETS[4] = { 0, 128, 256, 768 }; | 
 | const band_layout OD_LAYOUT32 = { | 
 |   OD_ZIGZAG32, | 
 |   32, | 
 |   3, | 
 |   OD_LAYOUT32_OFFSETS | 
 | }; | 
 |  | 
 | static const int OD_LAYOUT16_OFFSETS[4] = { 0, 32, 64, 192 }; | 
 | const band_layout OD_LAYOUT16 = { | 
 |   OD_ZIGZAG16, | 
 |   16, | 
 |   3, | 
 |   OD_LAYOUT16_OFFSETS | 
 | }; | 
 |  | 
 | const int OD_LAYOUT8_OFFSETS[4] = { 0, 8, 16, 48 }; | 
 | const band_layout OD_LAYOUT8 = { | 
 |   OD_ZIGZAG8, | 
 |   8, | 
 |   3, | 
 |   OD_LAYOUT8_OFFSETS | 
 | }; | 
 |  | 
 | static const int OD_LAYOUT4_OFFSETS[2] = { 0, 15 }; | 
 | const band_layout OD_LAYOUT4 = { | 
 |   OD_ZIGZAG4, | 
 |   4, | 
 |   1, | 
 |   OD_LAYOUT4_OFFSETS | 
 | }; | 
 |  | 
 | /* First element is the number of bands, followed by the list all the band | 
 |   boundaries. */ | 
 | static const int OD_BAND_OFFSETS4[] = {1, 1, 16}; | 
 | static const int OD_BAND_OFFSETS8[] = {4, 1, 16, 24, 32, 64}; | 
 | static const int OD_BAND_OFFSETS16[] = {7, 1, 16, 24, 32, 64, 96, 128, 256}; | 
 | static const int OD_BAND_OFFSETS32[] = {10, 1, 16, 24, 32, 64, 96, 128, 256, | 
 |  384, 512, 1024}; | 
 | static const int OD_BAND_OFFSETS64[] = {13, 1, 16, 24, 32, 64, 96, 128, 256, | 
 |  384, 512, 1024, 1536, 2048, 4096}; | 
 |  | 
 | const int *const OD_BAND_OFFSETS[OD_TXSIZES + 1] = { | 
 |   OD_BAND_OFFSETS4, | 
 |   OD_BAND_OFFSETS8, | 
 |   OD_BAND_OFFSETS16, | 
 |   OD_BAND_OFFSETS32, | 
 |   OD_BAND_OFFSETS64 | 
 | }; | 
 |  | 
 | /** Perform a single stage of conversion from a coefficient block in | 
 |  * raster order into coding scan order | 
 |  * | 
 |  * @param [in]     layout  scan order specification | 
 |  * @param [out]    dst     destination vector | 
 |  * @param [in]     src     source coefficient block | 
 |  * @param [int]    int     source vector row stride | 
 |  */ | 
 | static void od_band_from_raster(const band_layout *layout, tran_low_t *dst, | 
 |  const tran_low_t *src, int stride, TX_TYPE tx_type) { | 
 |   int i; | 
 |   int len; | 
 |   len = layout->band_offsets[layout->nb_bands]; | 
 |   for (i = 0; i < len; i++) { | 
 |     dst[i] = src[layout->dst_table[tx_type][i][1]*stride + layout->dst_table[tx_type][i][0]]; | 
 |   } | 
 | } | 
 |  | 
 | /** Perform a single stage of conversion from a vector in coding scan | 
 |     order back into a coefficient block in raster order | 
 |  * | 
 |  * @param [in]     layout  scan order specification | 
 |  * @param [out]    dst     destination coefficient block | 
 |  * @param [in]     src     source vector | 
 |  * @param [int]    stride  destination vector row stride | 
 |  */ | 
 | static void od_raster_from_band(const band_layout *layout, tran_low_t *dst, | 
 |  int stride, TX_TYPE tx_type, const tran_low_t *src) { | 
 |   int i; | 
 |   int len; | 
 |   len = layout->band_offsets[layout->nb_bands]; | 
 |   for (i = 0; i < len; i++) { | 
 |     dst[layout->dst_table[tx_type][i][1]*stride + layout->dst_table[tx_type][i][0]] = src[i]; | 
 |   } | 
 | } | 
 |  | 
 | static const band_layout *const OD_LAYOUTS[] = {&OD_LAYOUT4, &OD_LAYOUT8, | 
 |  &OD_LAYOUT16, &OD_LAYOUT32}; | 
 |  | 
 | /** Converts a coefficient block in raster order into a vector in | 
 |  * coding scan order with the PVQ partitions laid out one after | 
 |  * another.  This works in stages; the 4x4 conversion is applied to | 
 |  * the coefficients nearest DC, then the 8x8 applied to the 8x8 block | 
 |  * nearest DC that was not already coded by 4x4, then 16x16 following | 
 |  * the same pattern. | 
 |  * | 
 |  * @param [out]    dst        destination vector | 
 |  * @param [in]     n          block size (along one side) | 
 |  * @param [in]     ty_type    transfrom type | 
 |  * @param [in]     src        source coefficient block | 
 |  * @param [in]     stride     source vector row stride | 
 |  */ | 
 | void od_raster_to_coding_order(tran_low_t *dst, int n, TX_TYPE ty_type, | 
 |  const tran_low_t *src, int stride) { | 
 |   int bs; | 
 |   /* dst + 1 because DC is not included for 4x4 blocks. */ | 
 |   od_band_from_raster(OD_LAYOUTS[0], dst + 1, src, stride, ty_type); | 
 |   for (bs = 1; bs < OD_TXSIZES; bs++) { | 
 |     int size; | 
 |     int offset; | 
 |     /* Length of block size > 4. */ | 
 |     size = 1 << (OD_LOG_BSIZE0 + bs); | 
 |     /* Offset is the size of the previous block squared. */ | 
 |     offset = 1 << 2*(OD_LOG_BSIZE0 - 1 + bs); | 
 |     if (n >= size) { | 
 |       /* 3 16x16 bands come after 3 8x8 bands, which come after 2 4x4 bands. */ | 
 |       od_band_from_raster(OD_LAYOUTS[bs], dst + offset, src, stride, ty_type); | 
 |     } | 
 |   } | 
 |   dst[0] = src[0]; | 
 | } | 
 |  | 
 | /** Converts a vector in coding scan order witht he PVQ partitions | 
 |  * laid out one after another into a coefficient block in raster | 
 |  * order. This works in stages in the reverse order of raster->scan | 
 |  * order; the 16x16 conversion is applied to the coefficients that | 
 |  * don't appear in an 8x8 block, then the 8x8 applied to the 8x8 block | 
 |  * sans the 4x4 block it contains, then 4x4 is converted sans DC. | 
 |  * | 
 |  * @param [out]    dst        destination coefficient block | 
 |  * @param [in]     stride     destination vector row stride | 
 |  * @param [in]     src        source vector | 
 |  * @param [in]     n          block size (along one side) | 
 |  */ | 
 | void od_coding_order_to_raster(tran_low_t *dst, int stride, TX_TYPE ty_type, | 
 |  const tran_low_t *src, int n) { | 
 |   int bs; | 
 |   /* src + 1 because DC is not included for 4x4 blocks. */ | 
 |   od_raster_from_band(OD_LAYOUTS[0], dst, stride, ty_type, src + 1); | 
 |   for (bs = 1; bs < OD_TXSIZES; bs++) { | 
 |     int size; | 
 |     int offset; | 
 |     /* Length of block size > 4 */ | 
 |     size = 1 << (OD_LOG_BSIZE0 + bs); | 
 |     /* Offset is the size of the previous block squared. */ | 
 |     offset = 1 << 2*(OD_LOG_BSIZE0 - 1 + bs); | 
 |     if (n >= size) { | 
 |       /* 3 16x16 bands come after 3 8x8 bands, which come after 2 4x4 bands. */ | 
 |       od_raster_from_band(OD_LAYOUTS[bs], dst, stride, ty_type, src + offset); | 
 |     } | 
 |   } | 
 |   dst[0] = src[0]; | 
 | } | 
 |  | 
 | /** Perform a single stage of conversion from a coefficient block in | 
 |  * raster order into coding scan order | 
 |  * | 
 |  * @param [in]     layout  scan order specification | 
 |  * @param [out]    dst     destination vector | 
 |  * @param [in]     src     source coefficient block | 
 |  * @param [int]    int     source vector row stride | 
 |  */ | 
 | static void od_band_from_raster_16(const band_layout *layout, int16_t *dst, | 
 |  const int16_t *src, int stride) { | 
 |   int i; | 
 |   int len; | 
 |   len = layout->band_offsets[layout->nb_bands]; | 
 |   for (i = 0; i < len; i++) { | 
 |     dst[i] = src[layout->dst_table[DCT_DCT][i][1]*stride + layout->dst_table[DCT_DCT][i][0]]; | 
 |   } | 
 | } | 
 |  | 
 | /** Converts a coefficient block in raster order into a vector in | 
 |  * coding scan order with the PVQ partitions laid out one after | 
 |  * another.  This works in stages; the 4x4 conversion is applied to | 
 |  * the coefficients nearest DC, then the 8x8 applied to the 8x8 block | 
 |  * nearest DC that was not already coded by 4x4, then 16x16 following | 
 |  * the same pattern. | 
 |  * | 
 |  * @param [out]    dst        destination vector | 
 |  * @param [in]     n          block size (along one side) | 
 |  * @param [in]     src        source coefficient block | 
 |  * @param [in]     stride     source vector row stride | 
 |  */ | 
 | void od_raster_to_coding_order_16(int16_t *dst, int n, const int16_t *src, | 
 |  int stride) { | 
 |   int bs; | 
 |   /* dst + 1 because DC is not included for 4x4 blocks. */ | 
 |   od_band_from_raster_16(OD_LAYOUTS[0], dst + 1, src, stride); | 
 |   for (bs = 1; bs < OD_TXSIZES; bs++) { | 
 |     int size; | 
 |     int offset; | 
 |     /* Length of block size > 4. */ | 
 |     size = 1 << (OD_LOG_BSIZE0 + bs); | 
 |     /* Offset is the size of the previous block squared. */ | 
 |     offset = 1 << 2*(OD_LOG_BSIZE0 - 1 + bs); | 
 |     if (n >= size) { | 
 |       /* 3 16x16 bands come after 3 8x8 bands, which come after 2 4x4 bands. */ | 
 |       od_band_from_raster_16(OD_LAYOUTS[bs], dst + offset, src, stride); | 
 |     } | 
 |   } | 
 |   dst[0] = src[0]; | 
 | } |