diff options
Diffstat (limited to 'media/ffvpx/libavcodec/simple_idct_template.c')
-rw-r--r-- | media/ffvpx/libavcodec/simple_idct_template.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/media/ffvpx/libavcodec/simple_idct_template.c b/media/ffvpx/libavcodec/simple_idct_template.c new file mode 100644 index 0000000000..904263fc71 --- /dev/null +++ b/media/ffvpx/libavcodec/simple_idct_template.c @@ -0,0 +1,371 @@ +/* + * Simple IDCT + * + * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at> + * + * 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 + */ + +/** + * @file + * simpleidct in C. + */ + +/* Based upon some commented-out C code from mpeg2dec (idct_mmx.c + * written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>). */ + +#include "simple_idct.h" + +#include "bit_depth_template.c" + +#undef W1 +#undef W2 +#undef W3 +#undef W4 +#undef W5 +#undef W6 +#undef W7 +#undef ROW_SHIFT +#undef COL_SHIFT +#undef DC_SHIFT +#undef MUL +#undef MAC + +#if BIT_DEPTH == 8 + +#define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 + +#define ROW_SHIFT 11 +#define COL_SHIFT 20 +#define DC_SHIFT 3 + +#define MUL(a, b) MUL16(a, b) +#define MAC(a, b, c) MAC16(a, b, c) + +#elif BIT_DEPTH == 10 || BIT_DEPTH == 12 + +# if BIT_DEPTH == 10 +#define W1 22725 // 90901 +#define W2 21407 // 85627 +#define W3 19265 // 77062 +#define W4 16384 // 65535 +#define W5 12873 // 51491 +#define W6 8867 // 35468 +#define W7 4520 // 18081 + +# ifdef EXTRA_SHIFT +#define ROW_SHIFT 13 +#define COL_SHIFT 18 +#define DC_SHIFT 1 +# elif IN_IDCT_DEPTH == 32 +#define ROW_SHIFT 13 +#define COL_SHIFT 21 +#define DC_SHIFT 2 +# else +#define ROW_SHIFT 12 +#define COL_SHIFT 19 +#define DC_SHIFT 2 +# endif + +# else +#define W1 45451 +#define W2 42813 +#define W3 38531 +#define W4 32767 +#define W5 25746 +#define W6 17734 +#define W7 9041 + +#define ROW_SHIFT 16 +#define COL_SHIFT 17 +#define DC_SHIFT -1 +# endif + +#define MUL(a, b) ((a) * (b)) +#define MAC(a, b, c) ((a) += (b) * (c)) + +#else + +#error "Unsupported bitdepth" + +#endif + +#ifdef EXTRA_SHIFT +static inline void FUNC(idctRowCondDC_extrashift)(int16_t *row, int extra_shift) +#else +static inline void FUNC6(idctRowCondDC)(idctin *row, int extra_shift) +#endif +{ + SUINT a0, a1, a2, a3, b0, b1, b2, b3; + +// TODO: Add DC-only support for int32_t input +#if IN_IDCT_DEPTH == 16 +#if HAVE_FAST_64BIT +#define ROW0_MASK (0xffffLL << 48 * HAVE_BIGENDIAN) + if (((AV_RN64A(row) & ~ROW0_MASK) | AV_RN64A(row+4)) == 0) { + uint64_t temp; + if (DC_SHIFT - extra_shift >= 0) { + temp = (row[0] * (1 << (DC_SHIFT - extra_shift))) & 0xffff; + } else { + temp = ((row[0] + (1<<(extra_shift - DC_SHIFT-1))) >> (extra_shift - DC_SHIFT)) & 0xffff; + } + temp += temp * (1 << 16); + temp += temp * ((uint64_t) 1 << 32); + AV_WN64A(row, temp); + AV_WN64A(row + 4, temp); + return; + } +#else + if (!(AV_RN32A(row+2) | + AV_RN32A(row+4) | + AV_RN32A(row+6) | + row[1])) { + uint32_t temp; + if (DC_SHIFT - extra_shift >= 0) { + temp = (row[0] * (1 << (DC_SHIFT - extra_shift))) & 0xffff; + } else { + temp = ((row[0] + (1<<(extra_shift - DC_SHIFT-1))) >> (extra_shift - DC_SHIFT)) & 0xffff; + } + temp += temp * (1 << 16); + AV_WN32A(row, temp); + AV_WN32A(row+2, temp); + AV_WN32A(row+4, temp); + AV_WN32A(row+6, temp); + return; + } +#endif +#endif + + a0 = (W4 * row[0]) + (1 << (ROW_SHIFT + extra_shift - 1)); + a1 = a0; + a2 = a0; + a3 = a0; + + a0 += W2 * row[2]; + a1 += W6 * row[2]; + a2 -= W6 * row[2]; + a3 -= W2 * row[2]; + + b0 = MUL(W1, row[1]); + MAC(b0, W3, row[3]); + b1 = MUL(W3, row[1]); + MAC(b1, -W7, row[3]); + b2 = MUL(W5, row[1]); + MAC(b2, -W1, row[3]); + b3 = MUL(W7, row[1]); + MAC(b3, -W5, row[3]); + +#if IN_IDCT_DEPTH == 32 + if (AV_RN64A(row + 4) | AV_RN64A(row + 6)) { +#else + if (AV_RN64A(row + 4)) { +#endif + a0 += W4*row[4] + W6*row[6]; + a1 += - W4*row[4] - W2*row[6]; + a2 += - W4*row[4] + W2*row[6]; + a3 += W4*row[4] - W6*row[6]; + + MAC(b0, W5, row[5]); + MAC(b0, W7, row[7]); + + MAC(b1, -W1, row[5]); + MAC(b1, -W5, row[7]); + + MAC(b2, W7, row[5]); + MAC(b2, W3, row[7]); + + MAC(b3, W3, row[5]); + MAC(b3, -W1, row[7]); + } + + row[0] = (int)(a0 + b0) >> (ROW_SHIFT + extra_shift); + row[7] = (int)(a0 - b0) >> (ROW_SHIFT + extra_shift); + row[1] = (int)(a1 + b1) >> (ROW_SHIFT + extra_shift); + row[6] = (int)(a1 - b1) >> (ROW_SHIFT + extra_shift); + row[2] = (int)(a2 + b2) >> (ROW_SHIFT + extra_shift); + row[5] = (int)(a2 - b2) >> (ROW_SHIFT + extra_shift); + row[3] = (int)(a3 + b3) >> (ROW_SHIFT + extra_shift); + row[4] = (int)(a3 - b3) >> (ROW_SHIFT + extra_shift); +} + +#define IDCT_COLS do { \ + a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4)); \ + a1 = a0; \ + a2 = a0; \ + a3 = a0; \ + \ + a0 += W2*col[8*2]; \ + a1 += W6*col[8*2]; \ + a2 += -W6*col[8*2]; \ + a3 += -W2*col[8*2]; \ + \ + b0 = MUL(W1, col[8*1]); \ + b1 = MUL(W3, col[8*1]); \ + b2 = MUL(W5, col[8*1]); \ + b3 = MUL(W7, col[8*1]); \ + \ + MAC(b0, W3, col[8*3]); \ + MAC(b1, -W7, col[8*3]); \ + MAC(b2, -W1, col[8*3]); \ + MAC(b3, -W5, col[8*3]); \ + \ + if (col[8*4]) { \ + a0 += W4*col[8*4]; \ + a1 += -W4*col[8*4]; \ + a2 += -W4*col[8*4]; \ + a3 += W4*col[8*4]; \ + } \ + \ + if (col[8*5]) { \ + MAC(b0, W5, col[8*5]); \ + MAC(b1, -W1, col[8*5]); \ + MAC(b2, W7, col[8*5]); \ + MAC(b3, W3, col[8*5]); \ + } \ + \ + if (col[8*6]) { \ + a0 += W6*col[8*6]; \ + a1 += -W2*col[8*6]; \ + a2 += W2*col[8*6]; \ + a3 += -W6*col[8*6]; \ + } \ + \ + if (col[8*7]) { \ + MAC(b0, W7, col[8*7]); \ + MAC(b1, -W5, col[8*7]); \ + MAC(b2, W3, col[8*7]); \ + MAC(b3, -W1, col[8*7]); \ + } \ + } while (0) + +#ifdef EXTRA_SHIFT +static inline void FUNC(idctSparseCol_extrashift)(int16_t *col) +#else +static inline void FUNC6(idctSparseColPut)(pixel *dest, ptrdiff_t line_size, + idctin *col) +{ + SUINT a0, a1, a2, a3, b0, b1, b2, b3; + + IDCT_COLS; + + dest[0] = av_clip_pixel((int)(a0 + b0) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a1 + b1) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a2 + b2) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a3 + b3) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a3 - b3) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a2 - b2) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a1 - b1) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((int)(a0 - b0) >> COL_SHIFT); +} + +static inline void FUNC6(idctSparseColAdd)(pixel *dest, ptrdiff_t line_size, + idctin *col) +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + + IDCT_COLS; + + dest[0] = av_clip_pixel(dest[0] + ((a0 + b0) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a1 + b1) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a2 + b2) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a3 + b3) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a3 - b3) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a2 - b2) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a1 - b1) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a0 - b0) >> COL_SHIFT)); +} + +static inline void FUNC6(idctSparseCol)(idctin *col) +#endif +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + + IDCT_COLS; + + col[0 ] = ((a0 + b0) >> COL_SHIFT); + col[8 ] = ((a1 + b1) >> COL_SHIFT); + col[16] = ((a2 + b2) >> COL_SHIFT); + col[24] = ((a3 + b3) >> COL_SHIFT); + col[32] = ((a3 - b3) >> COL_SHIFT); + col[40] = ((a2 - b2) >> COL_SHIFT); + col[48] = ((a1 - b1) >> COL_SHIFT); + col[56] = ((a0 - b0) >> COL_SHIFT); +} + +#ifndef EXTRA_SHIFT +void FUNC6(ff_simple_idct_put)(uint8_t *dest_, ptrdiff_t line_size, int16_t *block_) +{ + idctin *block = (idctin *)block_; + pixel *dest = (pixel *)dest_; + int i; + + line_size /= sizeof(pixel); + + for (i = 0; i < 8; i++) + FUNC6(idctRowCondDC)(block + i*8, 0); + + for (i = 0; i < 8; i++) + FUNC6(idctSparseColPut)(dest + i, line_size, block + i); +} + +#if IN_IDCT_DEPTH == 16 +void FUNC6(ff_simple_idct_add)(uint8_t *dest_, ptrdiff_t line_size, int16_t *block) +{ + pixel *dest = (pixel *)dest_; + int i; + + line_size /= sizeof(pixel); + + for (i = 0; i < 8; i++) + FUNC6(idctRowCondDC)(block + i*8, 0); + + for (i = 0; i < 8; i++) + FUNC6(idctSparseColAdd)(dest + i, line_size, block + i); +} + +void FUNC6(ff_simple_idct)(int16_t *block) +{ + int i; + + for (i = 0; i < 8; i++) + FUNC6(idctRowCondDC)(block + i*8, 0); + + for (i = 0; i < 8; i++) + FUNC6(idctSparseCol)(block + i); +} +#endif +#endif |