Update avcodec to 20080825
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27550 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
|
||||
* Copyright (c) 2006 Stefan Gehrer <[email protected]>
|
||||
*
|
||||
* MMX-optimized DSP functions, based on H.264 optimizations by
|
||||
* Michael Niedermayer and Loren Merritt
|
||||
*
|
||||
* 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 "libavutil/common.h"
|
||||
#include "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "dsputil_mmx.h"
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* inverse transform
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void cavs_idct8_1d(int16_t *block, uint64_t bias)
|
||||
{
|
||||
asm volatile(
|
||||
"movq 112(%0), %%mm4 \n\t" /* mm4 = src7 */
|
||||
"movq 16(%0), %%mm5 \n\t" /* mm5 = src1 */
|
||||
"movq 80(%0), %%mm2 \n\t" /* mm2 = src5 */
|
||||
"movq 48(%0), %%mm7 \n\t" /* mm7 = src3 */
|
||||
"movq %%mm4, %%mm0 \n\t"
|
||||
"movq %%mm5, %%mm3 \n\t"
|
||||
"movq %%mm2, %%mm6 \n\t"
|
||||
"movq %%mm7, %%mm1 \n\t"
|
||||
|
||||
"paddw %%mm4, %%mm4 \n\t" /* mm4 = 2*src7 */
|
||||
"paddw %%mm3, %%mm3 \n\t" /* mm3 = 2*src1 */
|
||||
"paddw %%mm6, %%mm6 \n\t" /* mm6 = 2*src5 */
|
||||
"paddw %%mm1, %%mm1 \n\t" /* mm1 = 2*src3 */
|
||||
"paddw %%mm4, %%mm0 \n\t" /* mm0 = 3*src7 */
|
||||
"paddw %%mm3, %%mm5 \n\t" /* mm5 = 3*src1 */
|
||||
"paddw %%mm6, %%mm2 \n\t" /* mm2 = 3*src5 */
|
||||
"paddw %%mm1, %%mm7 \n\t" /* mm7 = 3*src3 */
|
||||
"psubw %%mm4, %%mm5 \n\t" /* mm5 = 3*src1 - 2*src7 = a0 */
|
||||
"paddw %%mm6, %%mm7 \n\t" /* mm7 = 3*src3 + 2*src5 = a1 */
|
||||
"psubw %%mm2, %%mm1 \n\t" /* mm1 = 2*src3 - 3*src5 = a2 */
|
||||
"paddw %%mm0, %%mm3 \n\t" /* mm3 = 2*src1 + 3*src7 = a3 */
|
||||
|
||||
"movq %%mm5, %%mm4 \n\t"
|
||||
"movq %%mm7, %%mm6 \n\t"
|
||||
"movq %%mm3, %%mm0 \n\t"
|
||||
"movq %%mm1, %%mm2 \n\t"
|
||||
SUMSUB_BA( %%mm7, %%mm5 ) /* mm7 = a0 + a1 mm5 = a0 - a1 */
|
||||
"paddw %%mm3, %%mm7 \n\t" /* mm7 = a0 + a1 + a3 */
|
||||
"paddw %%mm1, %%mm5 \n\t" /* mm5 = a0 - a1 + a2 */
|
||||
"paddw %%mm7, %%mm7 \n\t"
|
||||
"paddw %%mm5, %%mm5 \n\t"
|
||||
"paddw %%mm6, %%mm7 \n\t" /* mm7 = b4 */
|
||||
"paddw %%mm4, %%mm5 \n\t" /* mm5 = b5 */
|
||||
|
||||
SUMSUB_BA( %%mm1, %%mm3 ) /* mm1 = a3 + a2 mm3 = a3 - a2 */
|
||||
"psubw %%mm1, %%mm4 \n\t" /* mm4 = a0 - a2 - a3 */
|
||||
"movq %%mm4, %%mm1 \n\t" /* mm1 = a0 - a2 - a3 */
|
||||
"psubw %%mm6, %%mm3 \n\t" /* mm3 = a3 - a2 - a1 */
|
||||
"paddw %%mm1, %%mm1 \n\t"
|
||||
"paddw %%mm3, %%mm3 \n\t"
|
||||
"psubw %%mm2, %%mm1 \n\t" /* mm1 = b7 */
|
||||
"paddw %%mm0, %%mm3 \n\t" /* mm3 = b6 */
|
||||
|
||||
"movq 32(%0), %%mm2 \n\t" /* mm2 = src2 */
|
||||
"movq 96(%0), %%mm6 \n\t" /* mm6 = src6 */
|
||||
"movq %%mm2, %%mm4 \n\t"
|
||||
"movq %%mm6, %%mm0 \n\t"
|
||||
"psllw $2, %%mm4 \n\t" /* mm4 = 4*src2 */
|
||||
"psllw $2, %%mm6 \n\t" /* mm6 = 4*src6 */
|
||||
"paddw %%mm4, %%mm2 \n\t" /* mm2 = 5*src2 */
|
||||
"paddw %%mm6, %%mm0 \n\t" /* mm0 = 5*src6 */
|
||||
"paddw %%mm2, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm0 \n\t"
|
||||
"psubw %%mm0, %%mm4 \n\t" /* mm4 = 4*src2 - 10*src6 = a7 */
|
||||
"paddw %%mm2, %%mm6 \n\t" /* mm6 = 4*src6 + 10*src2 = a6 */
|
||||
|
||||
"movq (%0), %%mm2 \n\t" /* mm2 = src0 */
|
||||
"movq 64(%0), %%mm0 \n\t" /* mm0 = src4 */
|
||||
SUMSUB_BA( %%mm0, %%mm2 ) /* mm0 = src0+src4 mm2 = src0-src4 */
|
||||
"psllw $3, %%mm0 \n\t"
|
||||
"psllw $3, %%mm2 \n\t"
|
||||
"paddw %1, %%mm0 \n\t" /* add rounding bias */
|
||||
"paddw %1, %%mm2 \n\t" /* add rounding bias */
|
||||
|
||||
SUMSUB_BA( %%mm6, %%mm0 ) /* mm6 = a4 + a6 mm0 = a4 - a6 */
|
||||
SUMSUB_BA( %%mm4, %%mm2 ) /* mm4 = a5 + a7 mm2 = a5 - a7 */
|
||||
SUMSUB_BA( %%mm7, %%mm6 ) /* mm7 = dst0 mm6 = dst7 */
|
||||
SUMSUB_BA( %%mm5, %%mm4 ) /* mm5 = dst1 mm4 = dst6 */
|
||||
SUMSUB_BA( %%mm3, %%mm2 ) /* mm3 = dst2 mm2 = dst5 */
|
||||
SUMSUB_BA( %%mm1, %%mm0 ) /* mm1 = dst3 mm0 = dst4 */
|
||||
:: "r"(block), "m"(bias)
|
||||
);
|
||||
}
|
||||
|
||||
static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride)
|
||||
{
|
||||
int i;
|
||||
DECLARE_ALIGNED_8(int16_t, b2[64]);
|
||||
|
||||
for(i=0; i<2; i++){
|
||||
DECLARE_ALIGNED_8(uint64_t, tmp);
|
||||
|
||||
cavs_idct8_1d(block+4*i, ff_pw_4);
|
||||
|
||||
asm volatile(
|
||||
"psraw $3, %%mm7 \n\t"
|
||||
"psraw $3, %%mm6 \n\t"
|
||||
"psraw $3, %%mm5 \n\t"
|
||||
"psraw $3, %%mm4 \n\t"
|
||||
"psraw $3, %%mm3 \n\t"
|
||||
"psraw $3, %%mm2 \n\t"
|
||||
"psraw $3, %%mm1 \n\t"
|
||||
"psraw $3, %%mm0 \n\t"
|
||||
"movq %%mm7, %0 \n\t"
|
||||
TRANSPOSE4( %%mm0, %%mm2, %%mm4, %%mm6, %%mm7 )
|
||||
"movq %%mm0, 8(%1) \n\t"
|
||||
"movq %%mm6, 24(%1) \n\t"
|
||||
"movq %%mm7, 40(%1) \n\t"
|
||||
"movq %%mm4, 56(%1) \n\t"
|
||||
"movq %0, %%mm7 \n\t"
|
||||
TRANSPOSE4( %%mm7, %%mm5, %%mm3, %%mm1, %%mm0 )
|
||||
"movq %%mm7, (%1) \n\t"
|
||||
"movq %%mm1, 16(%1) \n\t"
|
||||
"movq %%mm0, 32(%1) \n\t"
|
||||
"movq %%mm3, 48(%1) \n\t"
|
||||
: "=m"(tmp)
|
||||
: "r"(b2+32*i)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
for(i=0; i<2; i++){
|
||||
cavs_idct8_1d(b2+4*i, ff_pw_64);
|
||||
|
||||
asm volatile(
|
||||
"psraw $7, %%mm7 \n\t"
|
||||
"psraw $7, %%mm6 \n\t"
|
||||
"psraw $7, %%mm5 \n\t"
|
||||
"psraw $7, %%mm4 \n\t"
|
||||
"psraw $7, %%mm3 \n\t"
|
||||
"psraw $7, %%mm2 \n\t"
|
||||
"psraw $7, %%mm1 \n\t"
|
||||
"psraw $7, %%mm0 \n\t"
|
||||
"movq %%mm7, (%0) \n\t"
|
||||
"movq %%mm5, 16(%0) \n\t"
|
||||
"movq %%mm3, 32(%0) \n\t"
|
||||
"movq %%mm1, 48(%0) \n\t"
|
||||
"movq %%mm0, 64(%0) \n\t"
|
||||
"movq %%mm2, 80(%0) \n\t"
|
||||
"movq %%mm4, 96(%0) \n\t"
|
||||
"movq %%mm6, 112(%0) \n\t"
|
||||
:: "r"(b2+4*i)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
add_pixels_clamped_mmx(b2, dst, stride);
|
||||
|
||||
/* clear block */
|
||||
asm volatile(
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"movq %%mm7, (%0) \n\t"
|
||||
"movq %%mm7, 8(%0) \n\t"
|
||||
"movq %%mm7, 16(%0) \n\t"
|
||||
"movq %%mm7, 24(%0) \n\t"
|
||||
"movq %%mm7, 32(%0) \n\t"
|
||||
"movq %%mm7, 40(%0) \n\t"
|
||||
"movq %%mm7, 48(%0) \n\t"
|
||||
"movq %%mm7, 56(%0) \n\t"
|
||||
"movq %%mm7, 64(%0) \n\t"
|
||||
"movq %%mm7, 72(%0) \n\t"
|
||||
"movq %%mm7, 80(%0) \n\t"
|
||||
"movq %%mm7, 88(%0) \n\t"
|
||||
"movq %%mm7, 96(%0) \n\t"
|
||||
"movq %%mm7, 104(%0) \n\t"
|
||||
"movq %%mm7, 112(%0) \n\t"
|
||||
"movq %%mm7, 120(%0) \n\t"
|
||||
:: "r" (block)
|
||||
);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* motion compensation
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* vertical filter [-1 -2 96 42 -7 0] */
|
||||
#define QPEL_CAVSV1(A,B,C,D,E,F,OP) \
|
||||
"movd (%0), "#F" \n\t"\
|
||||
"movq "#C", %%mm6 \n\t"\
|
||||
"pmullw %5, %%mm6 \n\t"\
|
||||
"movq "#D", %%mm7 \n\t"\
|
||||
"pmullw %6, %%mm7 \n\t"\
|
||||
"psllw $3, "#E" \n\t"\
|
||||
"psubw "#E", %%mm6 \n\t"\
|
||||
"psraw $3, "#E" \n\t"\
|
||||
"paddw %%mm7, %%mm6 \n\t"\
|
||||
"paddw "#E", %%mm6 \n\t"\
|
||||
"paddw "#B", "#B" \n\t"\
|
||||
"pxor %%mm7, %%mm7 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"punpcklbw %%mm7, "#F" \n\t"\
|
||||
"psubw "#B", %%mm6 \n\t"\
|
||||
"psraw $1, "#B" \n\t"\
|
||||
"psubw "#A", %%mm6 \n\t"\
|
||||
"paddw %4, %%mm6 \n\t"\
|
||||
"psraw $7, %%mm6 \n\t"\
|
||||
"packuswb %%mm6, %%mm6 \n\t"\
|
||||
OP(%%mm6, (%1), A, d) \
|
||||
"add %3, %1 \n\t"
|
||||
|
||||
/* vertical filter [ 0 -1 5 5 -1 0] */
|
||||
#define QPEL_CAVSV2(A,B,C,D,E,F,OP) \
|
||||
"movd (%0), "#F" \n\t"\
|
||||
"movq "#C", %%mm6 \n\t"\
|
||||
"paddw "#D", %%mm6 \n\t"\
|
||||
"pmullw %5, %%mm6 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"punpcklbw %%mm7, "#F" \n\t"\
|
||||
"psubw "#B", %%mm6 \n\t"\
|
||||
"psubw "#E", %%mm6 \n\t"\
|
||||
"paddw %4, %%mm6 \n\t"\
|
||||
"psraw $3, %%mm6 \n\t"\
|
||||
"packuswb %%mm6, %%mm6 \n\t"\
|
||||
OP(%%mm6, (%1), A, d) \
|
||||
"add %3, %1 \n\t"
|
||||
|
||||
/* vertical filter [ 0 -7 42 96 -2 -1] */
|
||||
#define QPEL_CAVSV3(A,B,C,D,E,F,OP) \
|
||||
"movd (%0), "#F" \n\t"\
|
||||
"movq "#C", %%mm6 \n\t"\
|
||||
"pmullw %6, %%mm6 \n\t"\
|
||||
"movq "#D", %%mm7 \n\t"\
|
||||
"pmullw %5, %%mm7 \n\t"\
|
||||
"psllw $3, "#B" \n\t"\
|
||||
"psubw "#B", %%mm6 \n\t"\
|
||||
"psraw $3, "#B" \n\t"\
|
||||
"paddw %%mm7, %%mm6 \n\t"\
|
||||
"paddw "#B", %%mm6 \n\t"\
|
||||
"paddw "#E", "#E" \n\t"\
|
||||
"pxor %%mm7, %%mm7 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"punpcklbw %%mm7, "#F" \n\t"\
|
||||
"psubw "#E", %%mm6 \n\t"\
|
||||
"psraw $1, "#E" \n\t"\
|
||||
"psubw "#F", %%mm6 \n\t"\
|
||||
"paddw %4, %%mm6 \n\t"\
|
||||
"psraw $7, %%mm6 \n\t"\
|
||||
"packuswb %%mm6, %%mm6 \n\t"\
|
||||
OP(%%mm6, (%1), A, d) \
|
||||
"add %3, %1 \n\t"
|
||||
|
||||
|
||||
#define QPEL_CAVSVNUM(VOP,OP,ADD,MUL1,MUL2)\
|
||||
int w= 2;\
|
||||
src -= 2*srcStride;\
|
||||
\
|
||||
while(w--){\
|
||||
asm volatile(\
|
||||
"pxor %%mm7, %%mm7 \n\t"\
|
||||
"movd (%0), %%mm0 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"movd (%0), %%mm1 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"movd (%0), %%mm2 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"movd (%0), %%mm3 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"movd (%0), %%mm4 \n\t"\
|
||||
"add %2, %0 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm3 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"\
|
||||
VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
|
||||
VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
|
||||
VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
|
||||
VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
|
||||
VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP)\
|
||||
VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP)\
|
||||
VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
|
||||
VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
|
||||
\
|
||||
: "+a"(src), "+c"(dst)\
|
||||
: "S"((x86_reg)srcStride), "D"((x86_reg)dstStride), "m"(ADD), "m"(MUL1), "m"(MUL2)\
|
||||
: "memory"\
|
||||
);\
|
||||
if(h==16){\
|
||||
asm volatile(\
|
||||
VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
|
||||
VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
|
||||
VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP)\
|
||||
VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP)\
|
||||
VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
|
||||
VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
|
||||
VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
|
||||
VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
|
||||
\
|
||||
: "+a"(src), "+c"(dst)\
|
||||
: "S"((x86_reg)srcStride), "D"((x86_reg)dstStride), "m"(ADD), "m"(MUL1), "m"(MUL2)\
|
||||
: "memory"\
|
||||
);\
|
||||
}\
|
||||
src += 4-(h+5)*srcStride;\
|
||||
dst += 4-h*dstStride;\
|
||||
}
|
||||
|
||||
#define QPEL_CAVS(OPNAME, OP, MMX)\
|
||||
static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
int h=8;\
|
||||
asm volatile(\
|
||||
"pxor %%mm7, %%mm7 \n\t"\
|
||||
"movq %5, %%mm6 \n\t"\
|
||||
"1: \n\t"\
|
||||
"movq (%0), %%mm0 \n\t"\
|
||||
"movq 1(%0), %%mm2 \n\t"\
|
||||
"movq %%mm0, %%mm1 \n\t"\
|
||||
"movq %%mm2, %%mm3 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"\
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"\
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"\
|
||||
"paddw %%mm2, %%mm0 \n\t"\
|
||||
"paddw %%mm3, %%mm1 \n\t"\
|
||||
"pmullw %%mm6, %%mm0 \n\t"\
|
||||
"pmullw %%mm6, %%mm1 \n\t"\
|
||||
"movq -1(%0), %%mm2 \n\t"\
|
||||
"movq 2(%0), %%mm4 \n\t"\
|
||||
"movq %%mm2, %%mm3 \n\t"\
|
||||
"movq %%mm4, %%mm5 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"\
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"\
|
||||
"punpckhbw %%mm7, %%mm5 \n\t"\
|
||||
"paddw %%mm4, %%mm2 \n\t"\
|
||||
"paddw %%mm3, %%mm5 \n\t"\
|
||||
"psubw %%mm2, %%mm0 \n\t"\
|
||||
"psubw %%mm5, %%mm1 \n\t"\
|
||||
"movq %6, %%mm5 \n\t"\
|
||||
"paddw %%mm5, %%mm0 \n\t"\
|
||||
"paddw %%mm5, %%mm1 \n\t"\
|
||||
"psraw $3, %%mm0 \n\t"\
|
||||
"psraw $3, %%mm1 \n\t"\
|
||||
"packuswb %%mm1, %%mm0 \n\t"\
|
||||
OP(%%mm0, (%1),%%mm5, q) \
|
||||
"add %3, %0 \n\t"\
|
||||
"add %4, %1 \n\t"\
|
||||
"decl %2 \n\t"\
|
||||
" jnz 1b \n\t"\
|
||||
: "+a"(src), "+c"(dst), "+m"(h)\
|
||||
: "d"((x86_reg)srcStride), "S"((x86_reg)dstStride), "m"(ff_pw_5), "m"(ff_pw_4)\
|
||||
: "memory"\
|
||||
);\
|
||||
}\
|
||||
\
|
||||
static inline void OPNAME ## cavs_qpel8or16_v1_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
|
||||
QPEL_CAVSVNUM(QPEL_CAVSV1,OP,ff_pw_64,ff_pw_96,ff_pw_42) \
|
||||
}\
|
||||
\
|
||||
static inline void OPNAME ## cavs_qpel8or16_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
|
||||
QPEL_CAVSVNUM(QPEL_CAVSV2,OP,ff_pw_4,ff_pw_5,ff_pw_5) \
|
||||
}\
|
||||
\
|
||||
static inline void OPNAME ## cavs_qpel8or16_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
|
||||
QPEL_CAVSVNUM(QPEL_CAVSV3,OP,ff_pw_64,ff_pw_96,ff_pw_42) \
|
||||
}\
|
||||
\
|
||||
static void OPNAME ## cavs_qpel8_v1_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst , src , dstStride, srcStride, 8);\
|
||||
}\
|
||||
static void OPNAME ## cavs_qpel16_v1_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst , src , dstStride, srcStride, 16);\
|
||||
OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\
|
||||
}\
|
||||
\
|
||||
static void OPNAME ## cavs_qpel8_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst , src , dstStride, srcStride, 8);\
|
||||
}\
|
||||
static void OPNAME ## cavs_qpel16_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst , src , dstStride, srcStride, 16);\
|
||||
OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\
|
||||
}\
|
||||
\
|
||||
static void OPNAME ## cavs_qpel8_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst , src , dstStride, srcStride, 8);\
|
||||
}\
|
||||
static void OPNAME ## cavs_qpel16_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst , src , dstStride, srcStride, 16);\
|
||||
OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\
|
||||
}\
|
||||
\
|
||||
static void OPNAME ## cavs_qpel16_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
|
||||
OPNAME ## cavs_qpel8_h_ ## MMX(dst , src , dstStride, srcStride);\
|
||||
OPNAME ## cavs_qpel8_h_ ## MMX(dst+8, src+8, dstStride, srcStride);\
|
||||
src += 8*srcStride;\
|
||||
dst += 8*dstStride;\
|
||||
OPNAME ## cavs_qpel8_h_ ## MMX(dst , src , dstStride, srcStride);\
|
||||
OPNAME ## cavs_qpel8_h_ ## MMX(dst+8, src+8, dstStride, srcStride);\
|
||||
}\
|
||||
|
||||
#define CAVS_MC(OPNAME, SIZE, MMX) \
|
||||
static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
|
||||
OPNAME ## cavs_qpel ## SIZE ## _h_ ## MMX(dst, src, stride, stride);\
|
||||
}\
|
||||
\
|
||||
static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
|
||||
OPNAME ## cavs_qpel ## SIZE ## _v1_ ## MMX(dst, src, stride, stride);\
|
||||
}\
|
||||
\
|
||||
static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
|
||||
OPNAME ## cavs_qpel ## SIZE ## _v2_ ## MMX(dst, src, stride, stride);\
|
||||
}\
|
||||
\
|
||||
static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
|
||||
OPNAME ## cavs_qpel ## SIZE ## _v3_ ## MMX(dst, src, stride, stride);\
|
||||
}\
|
||||
|
||||
#define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b " \n\t"
|
||||
#define AVG_3DNOW_OP(a,b,temp, size) \
|
||||
"mov" #size " " #b ", " #temp " \n\t"\
|
||||
"pavgusb " #temp ", " #a " \n\t"\
|
||||
"mov" #size " " #a ", " #b " \n\t"
|
||||
#define AVG_MMX2_OP(a,b,temp, size) \
|
||||
"mov" #size " " #b ", " #temp " \n\t"\
|
||||
"pavgb " #temp ", " #a " \n\t"\
|
||||
"mov" #size " " #a ", " #b " \n\t"
|
||||
|
||||
QPEL_CAVS(put_, PUT_OP, 3dnow)
|
||||
QPEL_CAVS(avg_, AVG_3DNOW_OP, 3dnow)
|
||||
QPEL_CAVS(put_, PUT_OP, mmx2)
|
||||
QPEL_CAVS(avg_, AVG_MMX2_OP, mmx2)
|
||||
|
||||
CAVS_MC(put_, 8, 3dnow)
|
||||
CAVS_MC(put_, 16,3dnow)
|
||||
CAVS_MC(avg_, 8, 3dnow)
|
||||
CAVS_MC(avg_, 16,3dnow)
|
||||
CAVS_MC(put_, 8, mmx2)
|
||||
CAVS_MC(put_, 16,mmx2)
|
||||
CAVS_MC(avg_, 8, mmx2)
|
||||
CAVS_MC(avg_, 16,mmx2)
|
||||
|
||||
void ff_put_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
|
||||
void ff_avg_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
|
||||
void ff_put_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
|
||||
void ff_avg_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
|
||||
|
||||
void ff_cavsdsp_init_mmx2(DSPContext* c, AVCodecContext *avctx) {
|
||||
#define dspfunc(PFX, IDX, NUM) \
|
||||
c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_mmx2; \
|
||||
c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_mmx2; \
|
||||
c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_mmx2; \
|
||||
c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_mmx2; \
|
||||
c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_mmx2; \
|
||||
|
||||
dspfunc(put_cavs_qpel, 0, 16);
|
||||
dspfunc(put_cavs_qpel, 1, 8);
|
||||
dspfunc(avg_cavs_qpel, 0, 16);
|
||||
dspfunc(avg_cavs_qpel, 1, 8);
|
||||
#undef dspfunc
|
||||
c->cavs_idct8_add = cavs_idct8_add_mmx;
|
||||
}
|
||||
|
||||
void ff_cavsdsp_init_3dnow(DSPContext* c, AVCodecContext *avctx) {
|
||||
#define dspfunc(PFX, IDX, NUM) \
|
||||
c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_mmx2; \
|
||||
c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_3dnow; \
|
||||
c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_3dnow; \
|
||||
c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_3dnow; \
|
||||
c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_3dnow; \
|
||||
|
||||
dspfunc(put_cavs_qpel, 0, 16);
|
||||
dspfunc(put_cavs_qpel, 1, 8);
|
||||
dspfunc(avg_cavs_qpel, 0, 16);
|
||||
dspfunc(avg_cavs_qpel, 1, 8);
|
||||
#undef dspfunc
|
||||
c->cavs_idct8_add = cavs_idct8_add_mmx;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* CPU detection code, extracted from mmx.h
|
||||
* (c)1997-99 by H. Dietz and R. Fisher
|
||||
* Converted to C and improved by Fabrice Bellard.
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
#undef printf
|
||||
|
||||
/* ebx saving is necessary for PIC. gcc seems unable to see it alone */
|
||||
#define cpuid(index,eax,ebx,ecx,edx)\
|
||||
asm volatile\
|
||||
("mov %%"REG_b", %%"REG_S"\n\t"\
|
||||
"cpuid\n\t"\
|
||||
"xchg %%"REG_b", %%"REG_S\
|
||||
: "=a" (eax), "=S" (ebx),\
|
||||
"=c" (ecx), "=d" (edx)\
|
||||
: "0" (index));
|
||||
|
||||
/* Function to test if multimedia instructions are supported... */
|
||||
int mm_support(void)
|
||||
{
|
||||
int rval = 0;
|
||||
int eax, ebx, ecx, edx;
|
||||
int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
|
||||
x86_reg a, c;
|
||||
|
||||
asm volatile (
|
||||
/* See if CPUID instruction is supported ... */
|
||||
/* ... Get copies of EFLAGS into eax and ecx */
|
||||
"pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
"mov %0, %1\n\t"
|
||||
|
||||
/* ... Toggle the ID bit in one copy and store */
|
||||
/* to the EFLAGS reg */
|
||||
"xor $0x200000, %0\n\t"
|
||||
"push %0\n\t"
|
||||
"popf\n\t"
|
||||
|
||||
/* ... Get the (hopefully modified) EFLAGS */
|
||||
"pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
: "=a" (a), "=c" (c)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
|
||||
if (a == c)
|
||||
return 0; /* CPUID not supported */
|
||||
|
||||
cpuid(0, max_std_level, ebx, ecx, edx);
|
||||
|
||||
if(max_std_level >= 1){
|
||||
cpuid(1, eax, ebx, ecx, std_caps);
|
||||
if (std_caps & (1<<23))
|
||||
rval |= FF_MM_MMX;
|
||||
if (std_caps & (1<<25))
|
||||
rval |= FF_MM_MMXEXT
|
||||
#if !defined(__GNUC__) || __GNUC__ > 2
|
||||
| FF_MM_SSE;
|
||||
if (std_caps & (1<<26))
|
||||
rval |= FF_MM_SSE2;
|
||||
if (ecx & 1)
|
||||
rval |= FF_MM_SSE3;
|
||||
if (ecx & 0x00000200 )
|
||||
rval |= FF_MM_SSSE3
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
|
||||
|
||||
if(max_ext_level >= 0x80000001){
|
||||
cpuid(0x80000001, eax, ebx, ecx, ext_caps);
|
||||
if (ext_caps & (1<<31))
|
||||
rval |= FF_MM_3DNOW;
|
||||
if (ext_caps & (1<<30))
|
||||
rval |= FF_MM_3DNOWEXT;
|
||||
if (ext_caps & (1<<23))
|
||||
rval |= FF_MM_MMX;
|
||||
if (ext_caps & (1<<22))
|
||||
rval |= FF_MM_MMXEXT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
av_log(NULL, AV_LOG_DEBUG, "%s%s%s%s%s%s%s%s\n",
|
||||
(rval&FF_MM_MMX) ? "MMX ":"",
|
||||
(rval&FF_MM_MMXEXT) ? "MMX2 ":"",
|
||||
(rval&FF_MM_SSE) ? "SSE ":"",
|
||||
(rval&FF_MM_SSE2) ? "SSE2 ":"",
|
||||
(rval&FF_MM_SSE3) ? "SSE3 ":"",
|
||||
(rval&FF_MM_SSSE3) ? "SSSE3 ":"",
|
||||
(rval&FF_MM_3DNOW) ? "3DNow ":"",
|
||||
(rval&FF_MM_3DNOWEXT) ? "3DNowExt ":"");
|
||||
#endif
|
||||
return rval;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
int main ( void )
|
||||
{
|
||||
int mm_flags;
|
||||
mm_flags = mm_support();
|
||||
printf("mm_support = 0x%08X\n",mm_flags);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Zoltan Hidvegi <hzoli -a- hzoli -d- com>,
|
||||
* Loren Merritt
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* MMX optimized version of (put|avg)_h264_chroma_mc8.
|
||||
* H264_CHROMA_MC8_TMPL must be defined to the desired function name
|
||||
* H264_CHROMA_OP must be defined to empty for put and pavgb/pavgusb for avg
|
||||
* H264_CHROMA_MC8_MV0 must be defined to a (put|avg)_pixels8 function
|
||||
*/
|
||||
static void H264_CHROMA_MC8_TMPL(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y, int rnd)
|
||||
{
|
||||
const uint64_t *rnd_reg;
|
||||
DECLARE_ALIGNED_8(uint64_t, AA);
|
||||
DECLARE_ALIGNED_8(uint64_t, DD);
|
||||
int i;
|
||||
|
||||
if(y==0 && x==0) {
|
||||
/* no filter needed */
|
||||
H264_CHROMA_MC8_MV0(dst, src, stride, h);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(x<8 && y<8 && x>=0 && y>=0);
|
||||
|
||||
if(y==0 || x==0)
|
||||
{
|
||||
/* 1 dimensional filter only */
|
||||
const int dxy = x ? 1 : stride;
|
||||
|
||||
rnd_reg = rnd ? &ff_pw_4 : &ff_pw_3;
|
||||
|
||||
asm volatile(
|
||||
"movd %0, %%mm5\n\t"
|
||||
"movq %1, %%mm4\n\t"
|
||||
"movq %2, %%mm6\n\t" /* mm6 = rnd */
|
||||
"punpcklwd %%mm5, %%mm5\n\t"
|
||||
"punpckldq %%mm5, %%mm5\n\t" /* mm5 = B = x */
|
||||
"pxor %%mm7, %%mm7\n\t"
|
||||
"psubw %%mm5, %%mm4\n\t" /* mm4 = A = 8-x */
|
||||
:: "rm"(x+y), "m"(ff_pw_8), "m"(*rnd_reg));
|
||||
|
||||
for(i=0; i<h; i++) {
|
||||
asm volatile(
|
||||
/* mm0 = src[0..7], mm1 = src[1..8] */
|
||||
"movq %0, %%mm0\n\t"
|
||||
"movq %1, %%mm2\n\t"
|
||||
:: "m"(src[0]), "m"(src[dxy]));
|
||||
|
||||
asm volatile(
|
||||
/* [mm0,mm1] = A * src[0..7] */
|
||||
/* [mm2,mm3] = B * src[1..8] */
|
||||
"movq %%mm0, %%mm1\n\t"
|
||||
"movq %%mm2, %%mm3\n\t"
|
||||
"punpcklbw %%mm7, %%mm0\n\t"
|
||||
"punpckhbw %%mm7, %%mm1\n\t"
|
||||
"punpcklbw %%mm7, %%mm2\n\t"
|
||||
"punpckhbw %%mm7, %%mm3\n\t"
|
||||
"pmullw %%mm4, %%mm0\n\t"
|
||||
"pmullw %%mm4, %%mm1\n\t"
|
||||
"pmullw %%mm5, %%mm2\n\t"
|
||||
"pmullw %%mm5, %%mm3\n\t"
|
||||
|
||||
/* dst[0..7] = (A * src[0..7] + B * src[1..8] + 4) >> 3 */
|
||||
"paddw %%mm6, %%mm0\n\t"
|
||||
"paddw %%mm6, %%mm1\n\t"
|
||||
"paddw %%mm2, %%mm0\n\t"
|
||||
"paddw %%mm3, %%mm1\n\t"
|
||||
"psrlw $3, %%mm0\n\t"
|
||||
"psrlw $3, %%mm1\n\t"
|
||||
"packuswb %%mm1, %%mm0\n\t"
|
||||
H264_CHROMA_OP(%0, %%mm0)
|
||||
"movq %%mm0, %0\n\t"
|
||||
: "=m" (dst[0]));
|
||||
|
||||
src += stride;
|
||||
dst += stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* general case, bilinear */
|
||||
rnd_reg = rnd ? &ff_pw_32.a : &ff_pw_28.a;
|
||||
asm volatile("movd %2, %%mm4\n\t"
|
||||
"movd %3, %%mm6\n\t"
|
||||
"punpcklwd %%mm4, %%mm4\n\t"
|
||||
"punpcklwd %%mm6, %%mm6\n\t"
|
||||
"punpckldq %%mm4, %%mm4\n\t" /* mm4 = x words */
|
||||
"punpckldq %%mm6, %%mm6\n\t" /* mm6 = y words */
|
||||
"movq %%mm4, %%mm5\n\t"
|
||||
"pmullw %%mm6, %%mm4\n\t" /* mm4 = x * y */
|
||||
"psllw $3, %%mm5\n\t"
|
||||
"psllw $3, %%mm6\n\t"
|
||||
"movq %%mm5, %%mm7\n\t"
|
||||
"paddw %%mm6, %%mm7\n\t"
|
||||
"movq %%mm4, %1\n\t" /* DD = x * y */
|
||||
"psubw %%mm4, %%mm5\n\t" /* mm5 = B = 8x - xy */
|
||||
"psubw %%mm4, %%mm6\n\t" /* mm6 = C = 8y - xy */
|
||||
"paddw %4, %%mm4\n\t"
|
||||
"psubw %%mm7, %%mm4\n\t" /* mm4 = A = xy - (8x+8y) + 64 */
|
||||
"pxor %%mm7, %%mm7\n\t"
|
||||
"movq %%mm4, %0\n\t"
|
||||
: "=m" (AA), "=m" (DD) : "rm" (x), "rm" (y), "m" (ff_pw_64));
|
||||
|
||||
asm volatile(
|
||||
/* mm0 = src[0..7], mm1 = src[1..8] */
|
||||
"movq %0, %%mm0\n\t"
|
||||
"movq %1, %%mm1\n\t"
|
||||
: : "m" (src[0]), "m" (src[1]));
|
||||
|
||||
for(i=0; i<h; i++) {
|
||||
src += stride;
|
||||
|
||||
asm volatile(
|
||||
/* mm2 = A * src[0..3] + B * src[1..4] */
|
||||
/* mm3 = A * src[4..7] + B * src[5..8] */
|
||||
"movq %%mm0, %%mm2\n\t"
|
||||
"movq %%mm1, %%mm3\n\t"
|
||||
"punpckhbw %%mm7, %%mm0\n\t"
|
||||
"punpcklbw %%mm7, %%mm1\n\t"
|
||||
"punpcklbw %%mm7, %%mm2\n\t"
|
||||
"punpckhbw %%mm7, %%mm3\n\t"
|
||||
"pmullw %0, %%mm0\n\t"
|
||||
"pmullw %0, %%mm2\n\t"
|
||||
"pmullw %%mm5, %%mm1\n\t"
|
||||
"pmullw %%mm5, %%mm3\n\t"
|
||||
"paddw %%mm1, %%mm2\n\t"
|
||||
"paddw %%mm0, %%mm3\n\t"
|
||||
: : "m" (AA));
|
||||
|
||||
asm volatile(
|
||||
/* [mm2,mm3] += C * src[0..7] */
|
||||
"movq %0, %%mm0\n\t"
|
||||
"movq %%mm0, %%mm1\n\t"
|
||||
"punpcklbw %%mm7, %%mm0\n\t"
|
||||
"punpckhbw %%mm7, %%mm1\n\t"
|
||||
"pmullw %%mm6, %%mm0\n\t"
|
||||
"pmullw %%mm6, %%mm1\n\t"
|
||||
"paddw %%mm0, %%mm2\n\t"
|
||||
"paddw %%mm1, %%mm3\n\t"
|
||||
: : "m" (src[0]));
|
||||
|
||||
asm volatile(
|
||||
/* [mm2,mm3] += D * src[1..8] */
|
||||
"movq %1, %%mm1\n\t"
|
||||
"movq %%mm1, %%mm0\n\t"
|
||||
"movq %%mm1, %%mm4\n\t"
|
||||
"punpcklbw %%mm7, %%mm0\n\t"
|
||||
"punpckhbw %%mm7, %%mm4\n\t"
|
||||
"pmullw %2, %%mm0\n\t"
|
||||
"pmullw %2, %%mm4\n\t"
|
||||
"paddw %%mm0, %%mm2\n\t"
|
||||
"paddw %%mm4, %%mm3\n\t"
|
||||
"movq %0, %%mm0\n\t"
|
||||
: : "m" (src[0]), "m" (src[1]), "m" (DD));
|
||||
|
||||
asm volatile(
|
||||
/* dst[0..7] = ([mm2,mm3] + 32) >> 6 */
|
||||
"paddw %1, %%mm2\n\t"
|
||||
"paddw %1, %%mm3\n\t"
|
||||
"psrlw $6, %%mm2\n\t"
|
||||
"psrlw $6, %%mm3\n\t"
|
||||
"packuswb %%mm3, %%mm2\n\t"
|
||||
H264_CHROMA_OP(%0, %%mm2)
|
||||
"movq %%mm2, %0\n\t"
|
||||
: "=m" (dst[0]) : "m" (*rnd_reg));
|
||||
dst+= stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void H264_CHROMA_MC4_TMPL(uint8_t *dst/*align 4*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y)
|
||||
{
|
||||
asm volatile(
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"movd %5, %%mm2 \n\t"
|
||||
"movd %6, %%mm3 \n\t"
|
||||
"movq "MANGLE(ff_pw_8)", %%mm4\n\t"
|
||||
"movq "MANGLE(ff_pw_8)", %%mm5\n\t"
|
||||
"punpcklwd %%mm2, %%mm2 \n\t"
|
||||
"punpcklwd %%mm3, %%mm3 \n\t"
|
||||
"punpcklwd %%mm2, %%mm2 \n\t"
|
||||
"punpcklwd %%mm3, %%mm3 \n\t"
|
||||
"psubw %%mm2, %%mm4 \n\t"
|
||||
"psubw %%mm3, %%mm5 \n\t"
|
||||
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"movd 1(%1), %%mm6 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm6 \n\t"
|
||||
"pmullw %%mm4, %%mm0 \n\t"
|
||||
"pmullw %%mm2, %%mm6 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
|
||||
"1: \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"movd 1(%1), %%mm1 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"pmullw %%mm4, %%mm0 \n\t"
|
||||
"pmullw %%mm2, %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm1, %%mm0 \n\t"
|
||||
"pmullw %%mm5, %%mm6 \n\t"
|
||||
"pmullw %%mm3, %%mm1 \n\t"
|
||||
"paddw %4, %%mm6 \n\t"
|
||||
"paddw %%mm6, %%mm1 \n\t"
|
||||
"psrlw $6, %%mm1 \n\t"
|
||||
"packuswb %%mm1, %%mm1 \n\t"
|
||||
H264_CHROMA_OP4((%0), %%mm1, %%mm6)
|
||||
"movd %%mm1, (%0) \n\t"
|
||||
"add %3, %0 \n\t"
|
||||
"movd (%1), %%mm6 \n\t"
|
||||
"movd 1(%1), %%mm1 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm6 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"pmullw %%mm4, %%mm6 \n\t"
|
||||
"pmullw %%mm2, %%mm1 \n\t"
|
||||
"paddw %%mm6, %%mm1 \n\t"
|
||||
"movq %%mm1, %%mm6 \n\t"
|
||||
"pmullw %%mm5, %%mm0 \n\t"
|
||||
"pmullw %%mm3, %%mm1 \n\t"
|
||||
"paddw %4, %%mm0 \n\t"
|
||||
"paddw %%mm0, %%mm1 \n\t"
|
||||
"psrlw $6, %%mm1 \n\t"
|
||||
"packuswb %%mm1, %%mm1 \n\t"
|
||||
H264_CHROMA_OP4((%0), %%mm1, %%mm0)
|
||||
"movd %%mm1, (%0) \n\t"
|
||||
"add %3, %0 \n\t"
|
||||
"sub $2, %2 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
: "+r"(dst), "+r"(src), "+r"(h)
|
||||
: "r"((x86_reg)stride), "m"(ff_pw_32), "m"(x), "m"(y)
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef H264_CHROMA_MC2_TMPL
|
||||
static void H264_CHROMA_MC2_TMPL(uint8_t *dst/*align 2*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y)
|
||||
{
|
||||
int tmp = ((1<<16)-1)*x + 8;
|
||||
int CD= tmp*y;
|
||||
int AB= (tmp<<3) - CD;
|
||||
asm volatile(
|
||||
/* mm5 = {A,B,A,B} */
|
||||
/* mm6 = {C,D,C,D} */
|
||||
"movd %0, %%mm5\n\t"
|
||||
"movd %1, %%mm6\n\t"
|
||||
"punpckldq %%mm5, %%mm5\n\t"
|
||||
"punpckldq %%mm6, %%mm6\n\t"
|
||||
"pxor %%mm7, %%mm7\n\t"
|
||||
/* mm0 = src[0,1,1,2] */
|
||||
"movd %2, %%mm2\n\t"
|
||||
"punpcklbw %%mm7, %%mm2\n\t"
|
||||
"pshufw $0x94, %%mm2, %%mm2\n\t"
|
||||
:: "r"(AB), "r"(CD), "m"(src[0]));
|
||||
|
||||
|
||||
asm volatile(
|
||||
"1:\n\t"
|
||||
"add %4, %1\n\t"
|
||||
/* mm1 = A * src[0,1] + B * src[1,2] */
|
||||
"movq %%mm2, %%mm1\n\t"
|
||||
"pmaddwd %%mm5, %%mm1\n\t"
|
||||
/* mm0 = src[0,1,1,2] */
|
||||
"movd (%1), %%mm0\n\t"
|
||||
"punpcklbw %%mm7, %%mm0\n\t"
|
||||
"pshufw $0x94, %%mm0, %%mm0\n\t"
|
||||
/* mm1 += C * src[0,1] + D * src[1,2] */
|
||||
"movq %%mm0, %%mm2\n\t"
|
||||
"pmaddwd %%mm6, %%mm0\n\t"
|
||||
"paddw %3, %%mm1\n\t"
|
||||
"paddw %%mm0, %%mm1\n\t"
|
||||
/* dst[0,1] = pack((mm1 + 32) >> 6) */
|
||||
"psrlw $6, %%mm1\n\t"
|
||||
"packssdw %%mm7, %%mm1\n\t"
|
||||
"packuswb %%mm7, %%mm1\n\t"
|
||||
H264_CHROMA_OP4((%0), %%mm1, %%mm3)
|
||||
"movd %%mm1, %%esi\n\t"
|
||||
"movw %%si, (%0)\n\t"
|
||||
"add %4, %0\n\t"
|
||||
"sub $1, %2\n\t"
|
||||
"jnz 1b\n\t"
|
||||
: "+r" (dst), "+r"(src), "+r"(h)
|
||||
: "m" (ff_pw_32), "r"((x86_reg)stride)
|
||||
: "%esi");
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Loren Merritt
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* SSSE3 optimized version of (put|avg)_h264_chroma_mc8.
|
||||
* H264_CHROMA_MC8_TMPL must be defined to the desired function name
|
||||
* H264_CHROMA_MC8_MV0 must be defined to a (put|avg)_pixels8 function
|
||||
* AVG_OP must be defined to empty for put and the identify for avg
|
||||
*/
|
||||
static void H264_CHROMA_MC8_TMPL(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y, int rnd)
|
||||
{
|
||||
if(y==0 && x==0) {
|
||||
/* no filter needed */
|
||||
H264_CHROMA_MC8_MV0(dst, src, stride, h);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(x<8 && y<8 && x>=0 && y>=0);
|
||||
|
||||
if(y==0 || x==0)
|
||||
{
|
||||
/* 1 dimensional filter only */
|
||||
asm volatile(
|
||||
"movd %0, %%xmm7 \n\t"
|
||||
"movq %1, %%xmm6 \n\t"
|
||||
"pshuflw $0, %%xmm7, %%xmm7 \n\t"
|
||||
"movlhps %%xmm6, %%xmm6 \n\t"
|
||||
"movlhps %%xmm7, %%xmm7 \n\t"
|
||||
:: "r"(255*(x+y)+8), "m"(*(rnd?&ff_pw_4:&ff_pw_3))
|
||||
);
|
||||
|
||||
if(x) {
|
||||
asm volatile(
|
||||
"1: \n\t"
|
||||
"movq (%1), %%xmm0 \n\t"
|
||||
"movq 1(%1), %%xmm1 \n\t"
|
||||
"movq (%1,%3), %%xmm2 \n\t"
|
||||
"movq 1(%1,%3), %%xmm3 \n\t"
|
||||
"punpcklbw %%xmm1, %%xmm0 \n\t"
|
||||
"punpcklbw %%xmm3, %%xmm2 \n\t"
|
||||
"pmaddubsw %%xmm7, %%xmm0 \n\t"
|
||||
"pmaddubsw %%xmm7, %%xmm2 \n\t"
|
||||
AVG_OP("movq (%0), %%xmm4 \n\t")
|
||||
AVG_OP("movhps (%0,%3), %%xmm4 \n\t")
|
||||
"paddw %%xmm6, %%xmm0 \n\t"
|
||||
"paddw %%xmm6, %%xmm2 \n\t"
|
||||
"psrlw $3, %%xmm0 \n\t"
|
||||
"psrlw $3, %%xmm2 \n\t"
|
||||
"packuswb %%xmm2, %%xmm0 \n\t"
|
||||
AVG_OP("pavgb %%xmm4, %%xmm0 \n\t")
|
||||
"movq %%xmm0, (%0) \n\t"
|
||||
"movhps %%xmm0, (%0,%3) \n\t"
|
||||
"sub $2, %2 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%0,%3,2), %0 \n\t"
|
||||
"jg 1b \n\t"
|
||||
:"+r"(dst), "+r"(src), "+r"(h)
|
||||
:"r"((x86_reg)stride)
|
||||
);
|
||||
} else {
|
||||
asm volatile(
|
||||
"1: \n\t"
|
||||
"movq (%1), %%xmm0 \n\t"
|
||||
"movq (%1,%3), %%xmm1 \n\t"
|
||||
"movdqa %%xmm1, %%xmm2 \n\t"
|
||||
"movq (%1,%3,2), %%xmm3 \n\t"
|
||||
"punpcklbw %%xmm1, %%xmm0 \n\t"
|
||||
"punpcklbw %%xmm3, %%xmm2 \n\t"
|
||||
"pmaddubsw %%xmm7, %%xmm0 \n\t"
|
||||
"pmaddubsw %%xmm7, %%xmm2 \n\t"
|
||||
AVG_OP("movq (%0), %%xmm4 \n\t")
|
||||
AVG_OP("movhps (%0,%3), %%xmm4 \n\t")
|
||||
"paddw %%xmm6, %%xmm0 \n\t"
|
||||
"paddw %%xmm6, %%xmm2 \n\t"
|
||||
"psrlw $3, %%xmm0 \n\t"
|
||||
"psrlw $3, %%xmm2 \n\t"
|
||||
"packuswb %%xmm2, %%xmm0 \n\t"
|
||||
AVG_OP("pavgb %%xmm4, %%xmm0 \n\t")
|
||||
"movq %%xmm0, (%0) \n\t"
|
||||
"movhps %%xmm0, (%0,%3) \n\t"
|
||||
"sub $2, %2 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%0,%3,2), %0 \n\t"
|
||||
"jg 1b \n\t"
|
||||
:"+r"(dst), "+r"(src), "+r"(h)
|
||||
:"r"((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* general case, bilinear */
|
||||
asm volatile(
|
||||
"movd %0, %%xmm7 \n\t"
|
||||
"movd %1, %%xmm6 \n\t"
|
||||
"movdqa %2, %%xmm5 \n\t"
|
||||
"pshuflw $0, %%xmm7, %%xmm7 \n\t"
|
||||
"pshuflw $0, %%xmm6, %%xmm6 \n\t"
|
||||
"movlhps %%xmm7, %%xmm7 \n\t"
|
||||
"movlhps %%xmm6, %%xmm6 \n\t"
|
||||
:: "r"((x*255+8)*(8-y)), "r"((x*255+8)*y), "m"(*(rnd?&ff_pw_32:&ff_pw_28))
|
||||
);
|
||||
|
||||
asm volatile(
|
||||
"movq (%1), %%xmm0 \n\t"
|
||||
"movq 1(%1), %%xmm1 \n\t"
|
||||
"punpcklbw %%xmm1, %%xmm0 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%xmm1 \n\t"
|
||||
"movq 1(%1), %%xmm2 \n\t"
|
||||
"movq (%1,%3), %%xmm3 \n\t"
|
||||
"movq 1(%1,%3), %%xmm4 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"punpcklbw %%xmm2, %%xmm1 \n\t"
|
||||
"punpcklbw %%xmm4, %%xmm3 \n\t"
|
||||
"movdqa %%xmm1, %%xmm2 \n\t"
|
||||
"movdqa %%xmm3, %%xmm4 \n\t"
|
||||
"pmaddubsw %%xmm7, %%xmm0 \n\t"
|
||||
"pmaddubsw %%xmm6, %%xmm1 \n\t"
|
||||
"pmaddubsw %%xmm7, %%xmm2 \n\t"
|
||||
"pmaddubsw %%xmm6, %%xmm3 \n\t"
|
||||
"paddw %%xmm5, %%xmm0 \n\t"
|
||||
"paddw %%xmm5, %%xmm2 \n\t"
|
||||
"paddw %%xmm0, %%xmm1 \n\t"
|
||||
"paddw %%xmm2, %%xmm3 \n\t"
|
||||
"movdqa %%xmm4, %%xmm0 \n\t"
|
||||
"psrlw $6, %%xmm1 \n\t"
|
||||
"psrlw $6, %%xmm3 \n\t"
|
||||
AVG_OP("movq (%0), %%xmm2 \n\t")
|
||||
AVG_OP("movhps (%0,%3), %%xmm2 \n\t")
|
||||
"packuswb %%xmm3, %%xmm1 \n\t"
|
||||
AVG_OP("pavgb %%xmm2, %%xmm1 \n\t")
|
||||
"movq %%xmm1, (%0)\n\t"
|
||||
"movhps %%xmm1, (%0,%3)\n\t"
|
||||
"sub $2, %2 \n\t"
|
||||
"lea (%0,%3,2), %0 \n\t"
|
||||
"jg 1b \n\t"
|
||||
:"+r"(dst), "+r"(src), "+r"(h)
|
||||
:"r"((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static void H264_CHROMA_MC4_TMPL(uint8_t *dst/*align 4*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y)
|
||||
{
|
||||
asm volatile(
|
||||
"movd %0, %%mm7 \n\t"
|
||||
"movd %1, %%mm6 \n\t"
|
||||
"movq %2, %%mm5 \n\t"
|
||||
"pshufw $0, %%mm7, %%mm7 \n\t"
|
||||
"pshufw $0, %%mm6, %%mm6 \n\t"
|
||||
:: "r"((x*255+8)*(8-y)), "r"((x*255+8)*y), "m"(ff_pw_32)
|
||||
);
|
||||
|
||||
asm volatile(
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"punpcklbw 1(%1), %%mm0 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
"1: \n\t"
|
||||
"movd (%1), %%mm1 \n\t"
|
||||
"movd (%1,%3), %%mm3 \n\t"
|
||||
"punpcklbw 1(%1), %%mm1 \n\t"
|
||||
"punpcklbw 1(%1,%3), %%mm3 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"movq %%mm1, %%mm2 \n\t"
|
||||
"movq %%mm3, %%mm4 \n\t"
|
||||
"pmaddubsw %%mm7, %%mm0 \n\t"
|
||||
"pmaddubsw %%mm6, %%mm1 \n\t"
|
||||
"pmaddubsw %%mm7, %%mm2 \n\t"
|
||||
"pmaddubsw %%mm6, %%mm3 \n\t"
|
||||
"paddw %%mm5, %%mm0 \n\t"
|
||||
"paddw %%mm5, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm1 \n\t"
|
||||
"paddw %%mm2, %%mm3 \n\t"
|
||||
"movq %%mm4, %%mm0 \n\t"
|
||||
"psrlw $6, %%mm1 \n\t"
|
||||
"psrlw $6, %%mm3 \n\t"
|
||||
"packuswb %%mm1, %%mm1 \n\t"
|
||||
"packuswb %%mm3, %%mm3 \n\t"
|
||||
AVG_OP("pavgb (%0), %%mm1 \n\t")
|
||||
AVG_OP("pavgb (%0,%3), %%mm3 \n\t")
|
||||
"movd %%mm1, (%0)\n\t"
|
||||
"movd %%mm3, (%0,%3)\n\t"
|
||||
"sub $2, %2 \n\t"
|
||||
"lea (%0,%3,2), %0 \n\t"
|
||||
"jg 1b \n\t"
|
||||
:"+r"(dst), "+r"(src), "+r"(h)
|
||||
:"r"((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* MMX optimized DSP utils
|
||||
* Copyright (c) 2007 Aurelien Jacobs <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_DSPUTIL_MMX_H
|
||||
#define FFMPEG_DSPUTIL_MMX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
typedef struct { uint64_t a, b; } xmm_t;
|
||||
|
||||
extern const uint64_t ff_bone;
|
||||
extern const uint64_t ff_wtwo;
|
||||
|
||||
extern const uint64_t ff_pdw_80000000[2];
|
||||
|
||||
extern const uint64_t ff_pw_3;
|
||||
extern const uint64_t ff_pw_4;
|
||||
extern const xmm_t ff_pw_5;
|
||||
extern const uint64_t ff_pw_8;
|
||||
extern const uint64_t ff_pw_15;
|
||||
extern const xmm_t ff_pw_16;
|
||||
extern const uint64_t ff_pw_20;
|
||||
extern const xmm_t ff_pw_28;
|
||||
extern const xmm_t ff_pw_32;
|
||||
extern const uint64_t ff_pw_42;
|
||||
extern const uint64_t ff_pw_64;
|
||||
extern const uint64_t ff_pw_96;
|
||||
extern const uint64_t ff_pw_128;
|
||||
extern const uint64_t ff_pw_255;
|
||||
|
||||
extern const uint64_t ff_pb_1;
|
||||
extern const uint64_t ff_pb_3;
|
||||
extern const uint64_t ff_pb_7;
|
||||
extern const uint64_t ff_pb_3F;
|
||||
extern const uint64_t ff_pb_A1;
|
||||
extern const uint64_t ff_pb_FC;
|
||||
|
||||
extern const double ff_pd_1[2];
|
||||
extern const double ff_pd_2[2];
|
||||
|
||||
#define LOAD4(stride,in,a,b,c,d)\
|
||||
"movq 0*"#stride"+"#in", "#a"\n\t"\
|
||||
"movq 1*"#stride"+"#in", "#b"\n\t"\
|
||||
"movq 2*"#stride"+"#in", "#c"\n\t"\
|
||||
"movq 3*"#stride"+"#in", "#d"\n\t"
|
||||
|
||||
#define STORE4(stride,out,a,b,c,d)\
|
||||
"movq "#a", 0*"#stride"+"#out"\n\t"\
|
||||
"movq "#b", 1*"#stride"+"#out"\n\t"\
|
||||
"movq "#c", 2*"#stride"+"#out"\n\t"\
|
||||
"movq "#d", 3*"#stride"+"#out"\n\t"
|
||||
|
||||
/* in/out: mma=mma+mmb, mmb=mmb-mma */
|
||||
#define SUMSUB_BA( a, b ) \
|
||||
"paddw "#b", "#a" \n\t"\
|
||||
"paddw "#b", "#b" \n\t"\
|
||||
"psubw "#a", "#b" \n\t"
|
||||
|
||||
#define SBUTTERFLY(a,b,t,n,m)\
|
||||
"mov" #m " " #a ", " #t " \n\t" /* abcd */\
|
||||
"punpckl" #n " " #b ", " #a " \n\t" /* aebf */\
|
||||
"punpckh" #n " " #b ", " #t " \n\t" /* cgdh */\
|
||||
|
||||
#define TRANSPOSE4(a,b,c,d,t)\
|
||||
SBUTTERFLY(a,b,t,wd,q) /* a=aebf t=cgdh */\
|
||||
SBUTTERFLY(c,d,b,wd,q) /* c=imjn b=kolp */\
|
||||
SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\
|
||||
SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */
|
||||
|
||||
#ifdef ARCH_X86_64
|
||||
// permutes 01234567 -> 05736421
|
||||
#define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
|
||||
SBUTTERFLY(a,b,%%xmm8,wd,dqa)\
|
||||
SBUTTERFLY(c,d,b,wd,dqa)\
|
||||
SBUTTERFLY(e,f,d,wd,dqa)\
|
||||
SBUTTERFLY(g,h,f,wd,dqa)\
|
||||
SBUTTERFLY(a,c,h,dq,dqa)\
|
||||
SBUTTERFLY(%%xmm8,b,c,dq,dqa)\
|
||||
SBUTTERFLY(e,g,b,dq,dqa)\
|
||||
SBUTTERFLY(d,f,g,dq,dqa)\
|
||||
SBUTTERFLY(a,e,f,qdq,dqa)\
|
||||
SBUTTERFLY(%%xmm8,d,e,qdq,dqa)\
|
||||
SBUTTERFLY(h,b,d,qdq,dqa)\
|
||||
SBUTTERFLY(c,g,b,qdq,dqa)\
|
||||
"movdqa %%xmm8, "#g" \n\t"
|
||||
#else
|
||||
#define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
|
||||
"movdqa "#h", "#t" \n\t"\
|
||||
SBUTTERFLY(a,b,h,wd,dqa)\
|
||||
"movdqa "#h", 16"#t" \n\t"\
|
||||
"movdqa "#t", "#h" \n\t"\
|
||||
SBUTTERFLY(c,d,b,wd,dqa)\
|
||||
SBUTTERFLY(e,f,d,wd,dqa)\
|
||||
SBUTTERFLY(g,h,f,wd,dqa)\
|
||||
SBUTTERFLY(a,c,h,dq,dqa)\
|
||||
"movdqa "#h", "#t" \n\t"\
|
||||
"movdqa 16"#t", "#h" \n\t"\
|
||||
SBUTTERFLY(h,b,c,dq,dqa)\
|
||||
SBUTTERFLY(e,g,b,dq,dqa)\
|
||||
SBUTTERFLY(d,f,g,dq,dqa)\
|
||||
SBUTTERFLY(a,e,f,qdq,dqa)\
|
||||
SBUTTERFLY(h,d,e,qdq,dqa)\
|
||||
"movdqa "#h", 16"#t" \n\t"\
|
||||
"movdqa "#t", "#h" \n\t"\
|
||||
SBUTTERFLY(h,b,d,qdq,dqa)\
|
||||
SBUTTERFLY(c,g,b,qdq,dqa)\
|
||||
"movdqa 16"#t", "#g" \n\t"
|
||||
#endif
|
||||
|
||||
#define MOVQ_WONE(regd) \
|
||||
asm volatile ( \
|
||||
"pcmpeqd %%" #regd ", %%" #regd " \n\t" \
|
||||
"psrlw $15, %%" #regd ::)
|
||||
|
||||
void dsputilenc_init_mmx(DSPContext* c, AVCodecContext *avctx);
|
||||
|
||||
#endif /* FFMPEG_DSPUTIL_MMX_H */
|
||||
@@ -0,0 +1,900 @@
|
||||
/*
|
||||
* DSP utils : average functions are compiled twice for 3dnow/mmx2
|
||||
* Copyright (c) 2000, 2001 Fabrice Bellard.
|
||||
* Copyright (c) 2002-2004 Michael Niedermayer
|
||||
*
|
||||
* MMX optimization by Nick Kurshev <[email protected]>
|
||||
* mostly rewritten by Michael Niedermayer <[email protected]>
|
||||
* and improved by Zdenek Kabelac <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* This header intentionally has no multiple inclusion guards. It is meant to
|
||||
* be included multiple times and generates different code depending on the
|
||||
* value of certain #defines. */
|
||||
|
||||
/* XXX: we use explicit registers to avoid a gcc 2.95.2 register asm
|
||||
clobber bug - now it will work with 2.95.2 and also with -fPIC
|
||||
*/
|
||||
static void DEF(put_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm1 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(put_pixels4_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"movd (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $4, %2 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
"movd %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movd (%1), %%mm1 \n\t"
|
||||
"movd (%2), %%mm2 \n\t"
|
||||
"movd 4(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"movd %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movd %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movd (%1), %%mm1 \n\t"
|
||||
"movd 8(%2), %%mm2 \n\t"
|
||||
"movd 12(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"movd %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movd %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
}
|
||||
|
||||
|
||||
static void DEF(put_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $8, %2 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 8(%2), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" 16(%2), %%mm0 \n\t"
|
||||
PAVGB" 24(%2), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
//the following should be used, though better not with gcc ...
|
||||
/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
|
||||
:"r"(src1Stride), "r"(dstStride)
|
||||
:"memory");*/
|
||||
}
|
||||
|
||||
static void DEF(put_no_rnd_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"pcmpeqb %%mm6, %%mm6 \n\t"
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $8, %2 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%2), %%mm2 \n\t"
|
||||
"movq 8(%2), %%mm3 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm2 \n\t"
|
||||
"pxor %%mm6, %%mm3 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq 16(%2), %%mm2 \n\t"
|
||||
"movq 24(%2), %%mm3 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm2 \n\t"
|
||||
"pxor %%mm6, %%mm3 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
//the following should be used, though better not with gcc ...
|
||||
/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
|
||||
:"r"(src1Stride), "r"(dstStride)
|
||||
:"memory");*/
|
||||
}
|
||||
|
||||
static void DEF(avg_pixels4_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"movd (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $4, %2 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
"movd %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movd (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 4(%2), %%mm1 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
"movd %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
PAVGB" (%3), %%mm1 \n\t"
|
||||
"movd %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movd (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" 8(%2), %%mm0 \n\t"
|
||||
PAVGB" 12(%2), %%mm1 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
"movd %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
PAVGB" (%3), %%mm1 \n\t"
|
||||
"movd %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
}
|
||||
|
||||
|
||||
static void DEF(avg_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $8, %2 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 8(%2), %%mm1 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
PAVGB" (%3), %%mm1 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" 16(%2), %%mm0 \n\t"
|
||||
PAVGB" 24(%2), %%mm1 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
PAVGB" (%3), %%mm1 \n\t"
|
||||
"movq %%mm1, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
//the following should be used, though better not with gcc ...
|
||||
/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
|
||||
:"r"(src1Stride), "r"(dstStride)
|
||||
:"memory");*/
|
||||
}
|
||||
|
||||
static void DEF(put_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq 8(%1), %%mm2 \n\t"
|
||||
"movq 8(%1, %3), %%mm3 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm1 \n\t"
|
||||
PAVGB" 9(%1), %%mm2 \n\t"
|
||||
PAVGB" 9(%1, %3), %%mm3 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"movq %%mm2, 8(%2) \n\t"
|
||||
"movq %%mm3, 8(%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq 8(%1), %%mm2 \n\t"
|
||||
"movq 8(%1, %3), %%mm3 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm1 \n\t"
|
||||
PAVGB" 9(%1), %%mm2 \n\t"
|
||||
PAVGB" 9(%1, %3), %%mm3 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"movq %%mm2, 8(%2) \n\t"
|
||||
"movq %%mm3, 8(%2, %3) \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(put_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 8(%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 8(%2), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" 16(%2), %%mm0 \n\t"
|
||||
PAVGB" 24(%2), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $2, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
//the following should be used, though better not with gcc ...
|
||||
/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
|
||||
:"r"(src1Stride), "r"(dstStride)
|
||||
:"memory");*/
|
||||
}
|
||||
|
||||
static void DEF(avg_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 8(%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
PAVGB" 8(%3), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" 8(%2), %%mm1 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
PAVGB" 8(%3), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGB" 16(%2), %%mm0 \n\t"
|
||||
PAVGB" 24(%2), %%mm1 \n\t"
|
||||
PAVGB" (%3), %%mm0 \n\t"
|
||||
PAVGB" 8(%3), %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $2, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
//the following should be used, though better not with gcc ...
|
||||
/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
|
||||
:"r"(src1Stride), "r"(dstStride)
|
||||
:"memory");*/
|
||||
}
|
||||
|
||||
static void DEF(put_no_rnd_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"pcmpeqb %%mm6, %%mm6 \n\t"
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"movq (%2), %%mm2 \n\t"
|
||||
"movq 8(%2), %%mm3 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm2 \n\t"
|
||||
"pxor %%mm6, %%mm3 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%2), %%mm2 \n\t"
|
||||
"movq 8(%2), %%mm3 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm2 \n\t"
|
||||
"pxor %%mm6, %%mm3 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq 16(%2), %%mm2 \n\t"
|
||||
"movq 24(%2), %%mm3 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm2 \n\t"
|
||||
"pxor %%mm6, %%mm3 \n\t"
|
||||
PAVGB" %%mm2, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm1 \n\t"
|
||||
"pxor %%mm6, %%mm0 \n\t"
|
||||
"pxor %%mm6, %%mm1 \n\t"
|
||||
"movq %%mm0, (%3) \n\t"
|
||||
"movq %%mm1, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $2, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
//the following should be used, though better not with gcc ...
|
||||
/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
|
||||
:"r"(src1Stride), "r"(dstStride)
|
||||
:"memory");*/
|
||||
}
|
||||
|
||||
/* GL: this function does incorrect rounding if overflow */
|
||||
static void DEF(put_no_rnd_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BONE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"movq 1(%1), %%mm1 \n\t"
|
||||
"movq 1(%1, %3), %%mm3 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"psubusb %%mm6, %%mm0 \n\t"
|
||||
"psubusb %%mm6, %%mm2 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm2 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm1 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"movq 1(%1, %3), %%mm3 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"psubusb %%mm6, %%mm0 \n\t"
|
||||
"psubusb %%mm6, %%mm2 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" %%mm3, %%mm2 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(put_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"sub %3, %2 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" %%mm2, %%mm1 \n\t"
|
||||
"movq %%mm0, (%2, %3) \n\t"
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
PAVGB" %%mm1, %%mm2 \n\t"
|
||||
PAVGB" %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D" (block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
/* GL: this function does incorrect rounding if overflow */
|
||||
static void DEF(put_no_rnd_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BONE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"sub %3, %2 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"psubusb %%mm6, %%mm1 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" %%mm2, %%mm1 \n\t"
|
||||
"movq %%mm0, (%2, %3) \n\t"
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"psubusb %%mm6, %%mm1 \n\t"
|
||||
PAVGB" %%mm1, %%mm2 \n\t"
|
||||
PAVGB" %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D" (block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(avg_pixels8)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%2), %%mm0 \n\t"
|
||||
"movq (%2, %3), %%mm1 \n\t"
|
||||
PAVGB" (%1), %%mm0 \n\t"
|
||||
PAVGB" (%1, %3), %%mm1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"movq (%2), %%mm0 \n\t"
|
||||
"movq (%2, %3), %%mm1 \n\t"
|
||||
PAVGB" (%1), %%mm0 \n\t"
|
||||
PAVGB" (%1, %3), %%mm1 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(avg_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm2 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" (%2, %3), %%mm2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm2 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" (%2, %3), %%mm2 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(avg_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"sub %3, %2 \n\t"
|
||||
"1: \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" %%mm2, %%mm1 \n\t"
|
||||
"movq (%2, %3), %%mm3 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm4 \n\t"
|
||||
PAVGB" %%mm3, %%mm0 \n\t"
|
||||
PAVGB" %%mm4, %%mm1 \n\t"
|
||||
"movq %%mm0, (%2, %3) \n\t"
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
PAVGB" %%mm1, %%mm2 \n\t"
|
||||
PAVGB" %%mm0, %%mm1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"movq (%2, %3), %%mm3 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm4 \n\t"
|
||||
PAVGB" %%mm3, %%mm2 \n\t"
|
||||
PAVGB" %%mm4, %%mm1 \n\t"
|
||||
"movq %%mm2, (%2, %3) \n\t"
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
/* Note this is not correctly rounded, but this function is only
|
||||
* used for B-frames so it does not matter. */
|
||||
static void DEF(avg_pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BONE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
PAVGB" 1(%1), %%mm0 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"psubusb %%mm6, %%mm2 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm1 \n\t"
|
||||
PAVGB" 1(%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
PAVGB" %%mm1, %%mm0 \n\t"
|
||||
PAVGB" %%mm2, %%mm1 \n\t"
|
||||
PAVGB" (%2), %%mm0 \n\t"
|
||||
PAVGB" (%2, %3), %%mm1 \n\t"
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
PAVGB" 1(%1, %3), %%mm1 \n\t"
|
||||
PAVGB" 1(%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
PAVGB" %%mm1, %%mm2 \n\t"
|
||||
PAVGB" %%mm0, %%mm1 \n\t"
|
||||
PAVGB" (%2), %%mm2 \n\t"
|
||||
PAVGB" (%2, %3), %%mm1 \n\t"
|
||||
"movq %%mm2, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r" ((x86_reg)line_size)
|
||||
:"%"REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(avg_pixels4)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
do {
|
||||
asm volatile(
|
||||
"movd (%1), %%mm0 \n\t"
|
||||
"movd (%1, %2), %%mm1 \n\t"
|
||||
"movd (%1, %2, 2), %%mm2 \n\t"
|
||||
"movd (%1, %3), %%mm3 \n\t"
|
||||
PAVGB" (%0), %%mm0 \n\t"
|
||||
PAVGB" (%0, %2), %%mm1 \n\t"
|
||||
PAVGB" (%0, %2, 2), %%mm2 \n\t"
|
||||
PAVGB" (%0, %3), %%mm3 \n\t"
|
||||
"movd %%mm0, (%1) \n\t"
|
||||
"movd %%mm1, (%1, %2) \n\t"
|
||||
"movd %%mm2, (%1, %2, 2) \n\t"
|
||||
"movd %%mm3, (%1, %3) \n\t"
|
||||
::"S"(pixels), "D"(block),
|
||||
"r" ((x86_reg)line_size), "r"((x86_reg)3L*line_size)
|
||||
:"memory");
|
||||
block += 4*line_size;
|
||||
pixels += 4*line_size;
|
||||
h -= 4;
|
||||
} while(h > 0);
|
||||
}
|
||||
|
||||
//FIXME the following could be optimized too ...
|
||||
static void DEF(put_no_rnd_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(put_no_rnd_pixels8_x2)(block , pixels , line_size, h);
|
||||
DEF(put_no_rnd_pixels8_x2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
static void DEF(put_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(put_pixels8_y2)(block , pixels , line_size, h);
|
||||
DEF(put_pixels8_y2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
static void DEF(put_no_rnd_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(put_no_rnd_pixels8_y2)(block , pixels , line_size, h);
|
||||
DEF(put_no_rnd_pixels8_y2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
static void DEF(avg_pixels16)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(avg_pixels8)(block , pixels , line_size, h);
|
||||
DEF(avg_pixels8)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
static void DEF(avg_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(avg_pixels8_x2)(block , pixels , line_size, h);
|
||||
DEF(avg_pixels8_x2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
static void DEF(avg_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(avg_pixels8_y2)(block , pixels , line_size, h);
|
||||
DEF(avg_pixels8_y2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
static void DEF(avg_pixels16_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(avg_pixels8_xy2)(block , pixels , line_size, h);
|
||||
DEF(avg_pixels8_xy2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
|
||||
#define QPEL_2TAP_L3(OPNAME) \
|
||||
static void DEF(OPNAME ## 2tap_qpel16_l3)(uint8_t *dst, uint8_t *src, int stride, int h, int off1, int off2){\
|
||||
asm volatile(\
|
||||
"1: \n\t"\
|
||||
"movq (%1,%2), %%mm0 \n\t"\
|
||||
"movq 8(%1,%2), %%mm1 \n\t"\
|
||||
PAVGB" (%1,%3), %%mm0 \n\t"\
|
||||
PAVGB" 8(%1,%3), %%mm1 \n\t"\
|
||||
PAVGB" (%1), %%mm0 \n\t"\
|
||||
PAVGB" 8(%1), %%mm1 \n\t"\
|
||||
STORE_OP( (%1,%4),%%mm0)\
|
||||
STORE_OP(8(%1,%4),%%mm1)\
|
||||
"movq %%mm0, (%1,%4) \n\t"\
|
||||
"movq %%mm1, 8(%1,%4) \n\t"\
|
||||
"add %5, %1 \n\t"\
|
||||
"decl %0 \n\t"\
|
||||
"jnz 1b \n\t"\
|
||||
:"+g"(h), "+r"(src)\
|
||||
:"r"((x86_reg)off1), "r"((x86_reg)off2),\
|
||||
"r"((x86_reg)(dst-src)), "r"((x86_reg)stride)\
|
||||
:"memory"\
|
||||
);\
|
||||
}\
|
||||
static void DEF(OPNAME ## 2tap_qpel8_l3)(uint8_t *dst, uint8_t *src, int stride, int h, int off1, int off2){\
|
||||
asm volatile(\
|
||||
"1: \n\t"\
|
||||
"movq (%1,%2), %%mm0 \n\t"\
|
||||
PAVGB" (%1,%3), %%mm0 \n\t"\
|
||||
PAVGB" (%1), %%mm0 \n\t"\
|
||||
STORE_OP((%1,%4),%%mm0)\
|
||||
"movq %%mm0, (%1,%4) \n\t"\
|
||||
"add %5, %1 \n\t"\
|
||||
"decl %0 \n\t"\
|
||||
"jnz 1b \n\t"\
|
||||
:"+g"(h), "+r"(src)\
|
||||
:"r"((x86_reg)off1), "r"((x86_reg)off2),\
|
||||
"r"((x86_reg)(dst-src)), "r"((x86_reg)stride)\
|
||||
:"memory"\
|
||||
);\
|
||||
}
|
||||
|
||||
#define STORE_OP(a,b) PAVGB" "#a","#b" \n\t"
|
||||
QPEL_2TAP_L3(avg_)
|
||||
#undef STORE_OP
|
||||
#define STORE_OP(a,b)
|
||||
QPEL_2TAP_L3(put_)
|
||||
#undef STORE_OP
|
||||
#undef QPEL_2TAP_L3
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* DSP utils : QNS functions are compiled 3 times for mmx/3dnow/ssse3
|
||||
* Copyright (c) 2004 Michael Niedermayer
|
||||
*
|
||||
* MMX optimization by Michael Niedermayer <[email protected]>
|
||||
* 3DNow! and SSSE3 optimization by Zuxy Meng <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* This header intentionally has no multiple inclusion guards. It is meant to
|
||||
* be included multiple times and generates different code depending on the
|
||||
* value of certain #defines. */
|
||||
|
||||
#define MAX_ABS (512 >> (SCALE_OFFSET>0 ? SCALE_OFFSET : 0))
|
||||
|
||||
static int DEF(try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale)
|
||||
{
|
||||
x86_reg i=0;
|
||||
|
||||
assert(FFABS(scale) < MAX_ABS);
|
||||
scale<<= 16 + SCALE_OFFSET - BASIS_SHIFT + RECON_SHIFT;
|
||||
|
||||
SET_RND(mm6);
|
||||
asm volatile(
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"movd %4, %%mm5 \n\t"
|
||||
"punpcklwd %%mm5, %%mm5 \n\t"
|
||||
"punpcklwd %%mm5, %%mm5 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1, %0), %%mm0 \n\t"
|
||||
"movq 8(%1, %0), %%mm1 \n\t"
|
||||
PMULHRW(%%mm0, %%mm1, %%mm5, %%mm6)
|
||||
"paddw (%2, %0), %%mm0 \n\t"
|
||||
"paddw 8(%2, %0), %%mm1 \n\t"
|
||||
"psraw $6, %%mm0 \n\t"
|
||||
"psraw $6, %%mm1 \n\t"
|
||||
"pmullw (%3, %0), %%mm0 \n\t"
|
||||
"pmullw 8(%3, %0), %%mm1 \n\t"
|
||||
"pmaddwd %%mm0, %%mm0 \n\t"
|
||||
"pmaddwd %%mm1, %%mm1 \n\t"
|
||||
"paddd %%mm1, %%mm0 \n\t"
|
||||
"psrld $4, %%mm0 \n\t"
|
||||
"paddd %%mm0, %%mm7 \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"cmp $128, %0 \n\t" //FIXME optimize & bench
|
||||
" jb 1b \n\t"
|
||||
PHADDD(%%mm7, %%mm6)
|
||||
"psrld $2, %%mm7 \n\t"
|
||||
"movd %%mm7, %0 \n\t"
|
||||
|
||||
: "+r" (i)
|
||||
: "r"(basis), "r"(rem), "r"(weight), "g"(scale)
|
||||
);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void DEF(add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale)
|
||||
{
|
||||
x86_reg i=0;
|
||||
|
||||
if(FFABS(scale) < MAX_ABS){
|
||||
scale<<= 16 + SCALE_OFFSET - BASIS_SHIFT + RECON_SHIFT;
|
||||
SET_RND(mm6);
|
||||
asm volatile(
|
||||
"movd %3, %%mm5 \n\t"
|
||||
"punpcklwd %%mm5, %%mm5 \n\t"
|
||||
"punpcklwd %%mm5, %%mm5 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1, %0), %%mm0 \n\t"
|
||||
"movq 8(%1, %0), %%mm1 \n\t"
|
||||
PMULHRW(%%mm0, %%mm1, %%mm5, %%mm6)
|
||||
"paddw (%2, %0), %%mm0 \n\t"
|
||||
"paddw 8(%2, %0), %%mm1 \n\t"
|
||||
"movq %%mm0, (%2, %0) \n\t"
|
||||
"movq %%mm1, 8(%2, %0) \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"cmp $128, %0 \n\t" // FIXME optimize & bench
|
||||
" jb 1b \n\t"
|
||||
|
||||
: "+r" (i)
|
||||
: "r"(basis), "r"(rem), "g"(scale)
|
||||
);
|
||||
}else{
|
||||
for(i=0; i<8*8; i++){
|
||||
rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,594 @@
|
||||
/*
|
||||
* DSP utils mmx functions are compiled twice for rnd/no_rnd
|
||||
* Copyright (c) 2000, 2001 Fabrice Bellard.
|
||||
* Copyright (c) 2003-2004 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* MMX optimization by Nick Kurshev <[email protected]>
|
||||
* mostly rewritten by Michael Niedermayer <[email protected]>
|
||||
* and improved by Zdenek Kabelac <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* This header intentionally has no multiple inclusion guards. It is meant to
|
||||
* be included multiple times and generates different code depending on the
|
||||
* value of certain #defines. */
|
||||
|
||||
// put_pixels
|
||||
static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm1 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"movq 1(%1, %3), %%mm3 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%2) \n\t"
|
||||
"movq %%mm5, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm1 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"movq 1(%1, %3), %%mm3 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%2) \n\t"
|
||||
"movq %%mm5, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r"((x86_reg)line_size)
|
||||
:REG_a, "memory");
|
||||
}
|
||||
|
||||
static void av_unused DEF(put, pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $8, %2 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm4, %%mm6)
|
||||
"movq %%mm4, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm2 \n\t"
|
||||
"movq 8(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq %%mm5, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 16(%2), %%mm1 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"movq (%1), %%mm2 \n\t"
|
||||
"movq 24(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq %%mm5, (%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
}
|
||||
|
||||
static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm1 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"movq 1(%1, %3), %%mm3 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%2) \n\t"
|
||||
"movq %%mm5, (%2, %3) \n\t"
|
||||
"movq 8(%1), %%mm0 \n\t"
|
||||
"movq 9(%1), %%mm1 \n\t"
|
||||
"movq 8(%1, %3), %%mm2 \n\t"
|
||||
"movq 9(%1, %3), %%mm3 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, 8(%2) \n\t"
|
||||
"movq %%mm5, 8(%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm1 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"movq 1(%1, %3), %%mm3 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%2) \n\t"
|
||||
"movq %%mm5, (%2, %3) \n\t"
|
||||
"movq 8(%1), %%mm0 \n\t"
|
||||
"movq 9(%1), %%mm1 \n\t"
|
||||
"movq 8(%1, %3), %%mm2 \n\t"
|
||||
"movq 9(%1, %3), %%mm3 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, 8(%2) \n\t"
|
||||
"movq %%mm5, 8(%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r"((x86_reg)line_size)
|
||||
:REG_a, "memory");
|
||||
}
|
||||
|
||||
static void av_unused DEF(put, pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
asm volatile(
|
||||
"testl $1, %0 \n\t"
|
||||
" jz 1f \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"movq 8(%1), %%mm2 \n\t"
|
||||
"movq 8(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%3) \n\t"
|
||||
"movq %%mm5, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"decl %0 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%2), %%mm1 \n\t"
|
||||
"movq 8(%1), %%mm2 \n\t"
|
||||
"movq 8(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%3) \n\t"
|
||||
"movq %%mm5, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 16(%2), %%mm1 \n\t"
|
||||
"movq 8(%1), %%mm2 \n\t"
|
||||
"movq 24(%2), %%mm3 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
|
||||
"movq %%mm4, (%3) \n\t"
|
||||
"movq %%mm5, 8(%3) \n\t"
|
||||
"add %5, %3 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"subl $2, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cannot be used
|
||||
:"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#else
|
||||
:"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
|
||||
#endif
|
||||
:"S"((x86_reg)src1Stride), "D"((x86_reg)dstStride)
|
||||
:"memory");
|
||||
}
|
||||
|
||||
static void DEF(put, pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"),%%mm2 \n\t"
|
||||
PAVGBP(%%mm1, %%mm0, %%mm4, %%mm2, %%mm1, %%mm5)
|
||||
"movq %%mm4, (%2) \n\t"
|
||||
"movq %%mm5, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"),%%mm0 \n\t"
|
||||
PAVGBP(%%mm1, %%mm2, %%mm4, %%mm0, %%mm1, %%mm5)
|
||||
"movq %%mm4, (%2) \n\t"
|
||||
"movq %%mm5, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r"((x86_reg)line_size)
|
||||
:REG_a, "memory");
|
||||
}
|
||||
|
||||
static void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_ZERO(mm7);
|
||||
SET_RND(mm6); // =2 for rnd and =1 for no_rnd version
|
||||
asm volatile(
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm4 \n\t"
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm4, %%mm5 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm5 \n\t"
|
||||
"paddusw %%mm0, %%mm4 \n\t"
|
||||
"paddusw %%mm1, %%mm5 \n\t"
|
||||
"xor %%"REG_a", %%"REG_a" \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 1(%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddusw %%mm2, %%mm0 \n\t"
|
||||
"paddusw %%mm3, %%mm1 \n\t"
|
||||
"paddusw %%mm6, %%mm4 \n\t"
|
||||
"paddusw %%mm6, %%mm5 \n\t"
|
||||
"paddusw %%mm0, %%mm4 \n\t"
|
||||
"paddusw %%mm1, %%mm5 \n\t"
|
||||
"psrlw $2, %%mm4 \n\t"
|
||||
"psrlw $2, %%mm5 \n\t"
|
||||
"packuswb %%mm5, %%mm4 \n\t"
|
||||
"movq %%mm4, (%2, %%"REG_a") \n\t"
|
||||
"add %3, %%"REG_a" \n\t"
|
||||
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3
|
||||
"movq 1(%1, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq %%mm2, %%mm3 \n\t"
|
||||
"movq %%mm4, %%mm5 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"punpckhbw %%mm7, %%mm5 \n\t"
|
||||
"paddusw %%mm2, %%mm4 \n\t"
|
||||
"paddusw %%mm3, %%mm5 \n\t"
|
||||
"paddusw %%mm6, %%mm0 \n\t"
|
||||
"paddusw %%mm6, %%mm1 \n\t"
|
||||
"paddusw %%mm4, %%mm0 \n\t"
|
||||
"paddusw %%mm5, %%mm1 \n\t"
|
||||
"psrlw $2, %%mm0 \n\t"
|
||||
"psrlw $2, %%mm1 \n\t"
|
||||
"packuswb %%mm1, %%mm0 \n\t"
|
||||
"movq %%mm0, (%2, %%"REG_a") \n\t"
|
||||
"add %3, %%"REG_a" \n\t"
|
||||
|
||||
"subl $2, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels)
|
||||
:"D"(block), "r"((x86_reg)line_size)
|
||||
:REG_a, "memory");
|
||||
}
|
||||
|
||||
// avg_pixels
|
||||
static void av_unused DEF(avg, pixels4)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movd %0, %%mm0 \n\t"
|
||||
"movd %1, %%mm1 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
"movd %%mm2, %0 \n\t"
|
||||
:"+m"(*block)
|
||||
:"m"(*pixels)
|
||||
:"memory");
|
||||
pixels += line_size;
|
||||
block += line_size;
|
||||
}
|
||||
while (--h);
|
||||
}
|
||||
|
||||
// in case more speed is needed - unroling would certainly help
|
||||
static void DEF(avg, pixels8)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movq %0, %%mm0 \n\t"
|
||||
"movq %1, %%mm1 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
"movq %%mm2, %0 \n\t"
|
||||
:"+m"(*block)
|
||||
:"m"(*pixels)
|
||||
:"memory");
|
||||
pixels += line_size;
|
||||
block += line_size;
|
||||
}
|
||||
while (--h);
|
||||
}
|
||||
|
||||
static void DEF(avg, pixels16)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movq %0, %%mm0 \n\t"
|
||||
"movq %1, %%mm1 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
"movq %%mm2, %0 \n\t"
|
||||
"movq 8%0, %%mm0 \n\t"
|
||||
"movq 8%1, %%mm1 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
"movq %%mm2, 8%0 \n\t"
|
||||
:"+m"(*block)
|
||||
:"m"(*pixels)
|
||||
:"memory");
|
||||
pixels += line_size;
|
||||
block += line_size;
|
||||
}
|
||||
while (--h);
|
||||
}
|
||||
|
||||
static void DEF(avg, pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movq %1, %%mm0 \n\t"
|
||||
"movq 1%1, %%mm1 \n\t"
|
||||
"movq %0, %%mm3 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
|
||||
"movq %%mm0, %0 \n\t"
|
||||
:"+m"(*block)
|
||||
:"m"(*pixels)
|
||||
:"memory");
|
||||
pixels += line_size;
|
||||
block += line_size;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static av_unused void DEF(avg, pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movq %1, %%mm0 \n\t"
|
||||
"movq %2, %%mm1 \n\t"
|
||||
"movq %0, %%mm3 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
|
||||
"movq %%mm0, %0 \n\t"
|
||||
:"+m"(*dst)
|
||||
:"m"(*src1), "m"(*src2)
|
||||
:"memory");
|
||||
dst += dstStride;
|
||||
src1 += src1Stride;
|
||||
src2 += 8;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movq %1, %%mm0 \n\t"
|
||||
"movq 1%1, %%mm1 \n\t"
|
||||
"movq %0, %%mm3 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
|
||||
"movq %%mm0, %0 \n\t"
|
||||
"movq 8%1, %%mm0 \n\t"
|
||||
"movq 9%1, %%mm1 \n\t"
|
||||
"movq 8%0, %%mm3 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
|
||||
"movq %%mm0, 8%0 \n\t"
|
||||
:"+m"(*block)
|
||||
:"m"(*pixels)
|
||||
:"memory");
|
||||
pixels += line_size;
|
||||
block += line_size;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static av_unused void DEF(avg, pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
JUMPALIGN();
|
||||
do {
|
||||
asm volatile(
|
||||
"movq %1, %%mm0 \n\t"
|
||||
"movq %2, %%mm1 \n\t"
|
||||
"movq %0, %%mm3 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
|
||||
"movq %%mm0, %0 \n\t"
|
||||
"movq 8%1, %%mm0 \n\t"
|
||||
"movq 8%2, %%mm1 \n\t"
|
||||
"movq 8%0, %%mm3 \n\t"
|
||||
PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
|
||||
PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
|
||||
"movq %%mm0, 8%0 \n\t"
|
||||
:"+m"(*dst)
|
||||
:"m"(*src1), "m"(*src2)
|
||||
:"memory");
|
||||
dst += dstStride;
|
||||
src1 += src1Stride;
|
||||
src2 += 16;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_BFE(mm6);
|
||||
asm volatile(
|
||||
"lea (%3, %3), %%"REG_a" \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t"
|
||||
PAVGBP(%%mm1, %%mm0, %%mm4, %%mm2, %%mm1, %%mm5)
|
||||
"movq (%2), %%mm3 \n\t"
|
||||
PAVGB(%%mm3, %%mm4, %%mm0, %%mm6)
|
||||
"movq (%2, %3), %%mm3 \n\t"
|
||||
PAVGB(%%mm3, %%mm5, %%mm1, %%mm6)
|
||||
"movq %%mm0, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
PAVGBP(%%mm1, %%mm2, %%mm4, %%mm0, %%mm1, %%mm5)
|
||||
"movq (%2), %%mm3 \n\t"
|
||||
PAVGB(%%mm3, %%mm4, %%mm2, %%mm6)
|
||||
"movq (%2, %3), %%mm3 \n\t"
|
||||
PAVGB(%%mm3, %%mm5, %%mm1, %%mm6)
|
||||
"movq %%mm2, (%2) \n\t"
|
||||
"movq %%mm1, (%2, %3) \n\t"
|
||||
"add %%"REG_a", %1 \n\t"
|
||||
"add %%"REG_a", %2 \n\t"
|
||||
|
||||
"subl $4, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels), "+D"(block)
|
||||
:"r"((x86_reg)line_size)
|
||||
:REG_a, "memory");
|
||||
}
|
||||
|
||||
// this routine is 'slightly' suboptimal but mostly unused
|
||||
static void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
|
||||
{
|
||||
MOVQ_ZERO(mm7);
|
||||
SET_RND(mm6); // =2 for rnd and =1 for no_rnd version
|
||||
asm volatile(
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 1(%1), %%mm4 \n\t"
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm4, %%mm5 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm5 \n\t"
|
||||
"paddusw %%mm0, %%mm4 \n\t"
|
||||
"paddusw %%mm1, %%mm5 \n\t"
|
||||
"xor %%"REG_a", %%"REG_a" \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
ASMALIGN(3)
|
||||
"1: \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 1(%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddusw %%mm2, %%mm0 \n\t"
|
||||
"paddusw %%mm3, %%mm1 \n\t"
|
||||
"paddusw %%mm6, %%mm4 \n\t"
|
||||
"paddusw %%mm6, %%mm5 \n\t"
|
||||
"paddusw %%mm0, %%mm4 \n\t"
|
||||
"paddusw %%mm1, %%mm5 \n\t"
|
||||
"psrlw $2, %%mm4 \n\t"
|
||||
"psrlw $2, %%mm5 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm3 \n\t"
|
||||
"packuswb %%mm5, %%mm4 \n\t"
|
||||
"pcmpeqd %%mm2, %%mm2 \n\t"
|
||||
"paddb %%mm2, %%mm2 \n\t"
|
||||
PAVGB(%%mm3, %%mm4, %%mm5, %%mm2)
|
||||
"movq %%mm5, (%2, %%"REG_a") \n\t"
|
||||
"add %3, %%"REG_a" \n\t"
|
||||
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3
|
||||
"movq 1(%1, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq %%mm2, %%mm3 \n\t"
|
||||
"movq %%mm4, %%mm5 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"punpckhbw %%mm7, %%mm5 \n\t"
|
||||
"paddusw %%mm2, %%mm4 \n\t"
|
||||
"paddusw %%mm3, %%mm5 \n\t"
|
||||
"paddusw %%mm6, %%mm0 \n\t"
|
||||
"paddusw %%mm6, %%mm1 \n\t"
|
||||
"paddusw %%mm4, %%mm0 \n\t"
|
||||
"paddusw %%mm5, %%mm1 \n\t"
|
||||
"psrlw $2, %%mm0 \n\t"
|
||||
"psrlw $2, %%mm1 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm3 \n\t"
|
||||
"packuswb %%mm1, %%mm0 \n\t"
|
||||
"pcmpeqd %%mm2, %%mm2 \n\t"
|
||||
"paddb %%mm2, %%mm2 \n\t"
|
||||
PAVGB(%%mm3, %%mm0, %%mm1, %%mm2)
|
||||
"movq %%mm1, (%2, %%"REG_a") \n\t"
|
||||
"add %3, %%"REG_a" \n\t"
|
||||
|
||||
"subl $2, %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
:"+g"(h), "+S"(pixels)
|
||||
:"D"(block), "r"((x86_reg)line_size)
|
||||
:REG_a, "memory");
|
||||
}
|
||||
|
||||
//FIXME optimize
|
||||
static void DEF(put, pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(put, pixels8_y2)(block , pixels , line_size, h);
|
||||
DEF(put, pixels8_y2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
|
||||
static void DEF(put, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(put, pixels8_xy2)(block , pixels , line_size, h);
|
||||
DEF(put, pixels8_xy2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
|
||||
static void DEF(avg, pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(avg, pixels8_y2)(block , pixels , line_size, h);
|
||||
DEF(avg, pixels8_y2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
|
||||
static void DEF(avg, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
|
||||
DEF(avg, pixels8_xy2)(block , pixels , line_size, h);
|
||||
DEF(avg, pixels8_xy2)(block+8, pixels+8, line_size, h);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
;******************************************************************************
|
||||
;* MMX optimized DSP utils
|
||||
;* Copyright (c) 2008 Loren Merritt
|
||||
;*
|
||||
;* 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
|
||||
;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
;******************************************************************************
|
||||
|
||||
%include "x86inc.asm"
|
||||
|
||||
section .text align=16
|
||||
|
||||
%macro PSWAPD_SSE 2
|
||||
pshufw %1, %2, 0x4e
|
||||
%endmacro
|
||||
%macro PSWAPD_3DN1 2
|
||||
movq %1, %2
|
||||
psrlq %1, 32
|
||||
punpckldq %1, %2
|
||||
%endmacro
|
||||
|
||||
%macro FLOAT_TO_INT16_INTERLEAVE6 1
|
||||
; void ff_float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len)
|
||||
cglobal ff_float_to_int16_interleave6_%1, 2,7,0, dst, src, src1, src2, src3, src4, src5
|
||||
%ifdef ARCH_X86_64
|
||||
%define lend r10d
|
||||
mov lend, r2d
|
||||
%else
|
||||
%define lend dword r2m
|
||||
%endif
|
||||
mov src1q, [srcq+1*gprsize]
|
||||
mov src2q, [srcq+2*gprsize]
|
||||
mov src3q, [srcq+3*gprsize]
|
||||
mov src4q, [srcq+4*gprsize]
|
||||
mov src5q, [srcq+5*gprsize]
|
||||
mov srcq, [srcq]
|
||||
sub src1q, srcq
|
||||
sub src2q, srcq
|
||||
sub src3q, srcq
|
||||
sub src4q, srcq
|
||||
sub src5q, srcq
|
||||
.loop:
|
||||
cvtps2pi mm0, [srcq]
|
||||
cvtps2pi mm1, [srcq+src1q]
|
||||
cvtps2pi mm2, [srcq+src2q]
|
||||
cvtps2pi mm3, [srcq+src3q]
|
||||
cvtps2pi mm4, [srcq+src4q]
|
||||
cvtps2pi mm5, [srcq+src5q]
|
||||
packssdw mm0, mm3
|
||||
packssdw mm1, mm4
|
||||
packssdw mm2, mm5
|
||||
pswapd mm3, mm0
|
||||
punpcklwd mm0, mm1
|
||||
punpckhwd mm1, mm2
|
||||
punpcklwd mm2, mm3
|
||||
pswapd mm3, mm0
|
||||
punpckldq mm0, mm2
|
||||
punpckhdq mm2, mm1
|
||||
punpckldq mm1, mm3
|
||||
movq [dstq ], mm0
|
||||
movq [dstq+16], mm2
|
||||
movq [dstq+ 8], mm1
|
||||
add srcq, 8
|
||||
add dstq, 24
|
||||
sub lend, 2
|
||||
jg .loop
|
||||
emms
|
||||
RET
|
||||
%endmacro ; FLOAT_TO_INT16_INTERLEAVE6
|
||||
|
||||
%define pswapd PSWAPD_SSE
|
||||
FLOAT_TO_INT16_INTERLEAVE6 sse
|
||||
%define cvtps2pi pf2id
|
||||
%define pswapd PSWAPD_3DN1
|
||||
FLOAT_TO_INT16_INTERLEAVE6 3dnow
|
||||
%undef pswapd
|
||||
FLOAT_TO_INT16_INTERLEAVE6 3dn2
|
||||
%undef cvtps2pi
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* MMX optimized forward DCT
|
||||
* The gcc porting is Copyright (c) 2001 Fabrice Bellard.
|
||||
* cleanup/optimizations are Copyright (c) 2002-2004 Michael Niedermayer <[email protected]>
|
||||
* SSE2 optimization is Copyright (c) 2004 Denes Balatoni.
|
||||
*
|
||||
* from fdctam32.c - AP922 MMX(3D-Now) forward-DCT
|
||||
*
|
||||
* Intel Application Note AP-922 - fast, precise implementation of DCT
|
||||
* http://developer.intel.com/vtune/cbts/appnotes.htm
|
||||
*
|
||||
* Also of inspiration:
|
||||
* a page about fdct at http://www.geocities.com/ssavekar/dct.htm
|
||||
* Skal's fdct at http://skal.planet-d.net/coding/dct.html
|
||||
*
|
||||
* 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 "libavutil/common.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "mmx.h"
|
||||
|
||||
#define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align)))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// constants for the forward DCT
|
||||
// -----------------------------
|
||||
//
|
||||
// Be sure to check that your compiler is aligning all constants to QWORD
|
||||
// (8-byte) memory boundaries! Otherwise the unaligned memory access will
|
||||
// severely stall MMX execution.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define BITS_FRW_ACC 3 //; 2 or 3 for accuracy
|
||||
#define SHIFT_FRW_COL BITS_FRW_ACC
|
||||
#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17 - 3)
|
||||
#define RND_FRW_ROW (1 << (SHIFT_FRW_ROW-1))
|
||||
//#define RND_FRW_COL (1 << (SHIFT_FRW_COL-1))
|
||||
|
||||
#define X8(x) x,x,x,x,x,x,x,x
|
||||
|
||||
//concatenated table, for forward DCT transformation
|
||||
static const int16_t fdct_tg_all_16[24] ATTR_ALIGN(16) = {
|
||||
X8(13036), // tg * (2<<16) + 0.5
|
||||
X8(27146), // tg * (2<<16) + 0.5
|
||||
X8(-21746) // tg * (2<<16) + 0.5
|
||||
};
|
||||
|
||||
static const int16_t ocos_4_16[8] ATTR_ALIGN(16) = {
|
||||
X8(23170) //cos * (2<<15) + 0.5
|
||||
};
|
||||
|
||||
static const int16_t fdct_one_corr[8] ATTR_ALIGN(16) = { X8(1) };
|
||||
|
||||
static const int32_t fdct_r_row[2] ATTR_ALIGN(8) = {RND_FRW_ROW, RND_FRW_ROW };
|
||||
|
||||
static struct
|
||||
{
|
||||
const int32_t fdct_r_row_sse2[4] ATTR_ALIGN(16);
|
||||
} fdct_r_row_sse2 ATTR_ALIGN(16)=
|
||||
{{
|
||||
RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW
|
||||
}};
|
||||
//static const long fdct_r_row_sse2[4] ATTR_ALIGN(16) = {RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW};
|
||||
|
||||
static const int16_t tab_frw_01234567[] ATTR_ALIGN(8) = { // forward_dct coeff table
|
||||
16384, 16384, 22725, 19266,
|
||||
16384, 16384, 12873, 4520,
|
||||
21407, 8867, 19266, -4520,
|
||||
-8867, -21407, -22725, -12873,
|
||||
16384, -16384, 12873, -22725,
|
||||
-16384, 16384, 4520, 19266,
|
||||
8867, -21407, 4520, -12873,
|
||||
21407, -8867, 19266, -22725,
|
||||
|
||||
22725, 22725, 31521, 26722,
|
||||
22725, 22725, 17855, 6270,
|
||||
29692, 12299, 26722, -6270,
|
||||
-12299, -29692, -31521, -17855,
|
||||
22725, -22725, 17855, -31521,
|
||||
-22725, 22725, 6270, 26722,
|
||||
12299, -29692, 6270, -17855,
|
||||
29692, -12299, 26722, -31521,
|
||||
|
||||
21407, 21407, 29692, 25172,
|
||||
21407, 21407, 16819, 5906,
|
||||
27969, 11585, 25172, -5906,
|
||||
-11585, -27969, -29692, -16819,
|
||||
21407, -21407, 16819, -29692,
|
||||
-21407, 21407, 5906, 25172,
|
||||
11585, -27969, 5906, -16819,
|
||||
27969, -11585, 25172, -29692,
|
||||
|
||||
19266, 19266, 26722, 22654,
|
||||
19266, 19266, 15137, 5315,
|
||||
25172, 10426, 22654, -5315,
|
||||
-10426, -25172, -26722, -15137,
|
||||
19266, -19266, 15137, -26722,
|
||||
-19266, 19266, 5315, 22654,
|
||||
10426, -25172, 5315, -15137,
|
||||
25172, -10426, 22654, -26722,
|
||||
|
||||
16384, 16384, 22725, 19266,
|
||||
16384, 16384, 12873, 4520,
|
||||
21407, 8867, 19266, -4520,
|
||||
-8867, -21407, -22725, -12873,
|
||||
16384, -16384, 12873, -22725,
|
||||
-16384, 16384, 4520, 19266,
|
||||
8867, -21407, 4520, -12873,
|
||||
21407, -8867, 19266, -22725,
|
||||
|
||||
19266, 19266, 26722, 22654,
|
||||
19266, 19266, 15137, 5315,
|
||||
25172, 10426, 22654, -5315,
|
||||
-10426, -25172, -26722, -15137,
|
||||
19266, -19266, 15137, -26722,
|
||||
-19266, 19266, 5315, 22654,
|
||||
10426, -25172, 5315, -15137,
|
||||
25172, -10426, 22654, -26722,
|
||||
|
||||
21407, 21407, 29692, 25172,
|
||||
21407, 21407, 16819, 5906,
|
||||
27969, 11585, 25172, -5906,
|
||||
-11585, -27969, -29692, -16819,
|
||||
21407, -21407, 16819, -29692,
|
||||
-21407, 21407, 5906, 25172,
|
||||
11585, -27969, 5906, -16819,
|
||||
27969, -11585, 25172, -29692,
|
||||
|
||||
22725, 22725, 31521, 26722,
|
||||
22725, 22725, 17855, 6270,
|
||||
29692, 12299, 26722, -6270,
|
||||
-12299, -29692, -31521, -17855,
|
||||
22725, -22725, 17855, -31521,
|
||||
-22725, 22725, 6270, 26722,
|
||||
12299, -29692, 6270, -17855,
|
||||
29692, -12299, 26722, -31521,
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
const int16_t tab_frw_01234567_sse2[256] ATTR_ALIGN(16);
|
||||
} tab_frw_01234567_sse2 ATTR_ALIGN(16) =
|
||||
{{
|
||||
//static const int16_t tab_frw_01234567_sse2[] ATTR_ALIGN(16) = { // forward_dct coeff table
|
||||
#define TABLE_SSE2 C4, C4, C1, C3, -C6, -C2, -C1, -C5, \
|
||||
C4, C4, C5, C7, C2, C6, C3, -C7, \
|
||||
-C4, C4, C7, C3, C6, -C2, C7, -C5, \
|
||||
C4, -C4, C5, -C1, C2, -C6, C3, -C1,
|
||||
// c1..c7 * cos(pi/4) * 2^15
|
||||
#define C1 22725
|
||||
#define C2 21407
|
||||
#define C3 19266
|
||||
#define C4 16384
|
||||
#define C5 12873
|
||||
#define C6 8867
|
||||
#define C7 4520
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 31521
|
||||
#define C2 29692
|
||||
#define C3 26722
|
||||
#define C4 22725
|
||||
#define C5 17855
|
||||
#define C6 12299
|
||||
#define C7 6270
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 29692
|
||||
#define C2 27969
|
||||
#define C3 25172
|
||||
#define C4 21407
|
||||
#define C5 16819
|
||||
#define C6 11585
|
||||
#define C7 5906
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 26722
|
||||
#define C2 25172
|
||||
#define C3 22654
|
||||
#define C4 19266
|
||||
#define C5 15137
|
||||
#define C6 10426
|
||||
#define C7 5315
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 22725
|
||||
#define C2 21407
|
||||
#define C3 19266
|
||||
#define C4 16384
|
||||
#define C5 12873
|
||||
#define C6 8867
|
||||
#define C7 4520
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 26722
|
||||
#define C2 25172
|
||||
#define C3 22654
|
||||
#define C4 19266
|
||||
#define C5 15137
|
||||
#define C6 10426
|
||||
#define C7 5315
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 29692
|
||||
#define C2 27969
|
||||
#define C3 25172
|
||||
#define C4 21407
|
||||
#define C5 16819
|
||||
#define C6 11585
|
||||
#define C7 5906
|
||||
TABLE_SSE2
|
||||
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
#define C1 31521
|
||||
#define C2 29692
|
||||
#define C3 26722
|
||||
#define C4 22725
|
||||
#define C5 17855
|
||||
#define C6 12299
|
||||
#define C7 6270
|
||||
TABLE_SSE2
|
||||
}};
|
||||
|
||||
#define FDCT_COL(cpu, mm, mov)\
|
||||
static av_always_inline void fdct_col_##cpu(const int16_t *in, int16_t *out, int offset)\
|
||||
{\
|
||||
mov##_m2r(*(in + offset + 1 * 8), mm##0);\
|
||||
mov##_m2r(*(in + offset + 6 * 8), mm##1);\
|
||||
mov##_r2r(mm##0, mm##2);\
|
||||
mov##_m2r(*(in + offset + 2 * 8), mm##3);\
|
||||
paddsw_r2r(mm##1, mm##0);\
|
||||
mov##_m2r(*(in + offset + 5 * 8), mm##4);\
|
||||
psllw_i2r(SHIFT_FRW_COL, mm##0);\
|
||||
mov##_m2r(*(in + offset + 0 * 8), mm##5);\
|
||||
paddsw_r2r(mm##3, mm##4);\
|
||||
paddsw_m2r(*(in + offset + 7 * 8), mm##5);\
|
||||
psllw_i2r(SHIFT_FRW_COL, mm##4);\
|
||||
mov##_r2r(mm##0, mm##6);\
|
||||
psubsw_r2r(mm##1, mm##2);\
|
||||
mov##_m2r(*(fdct_tg_all_16 + 8), mm##1);\
|
||||
psubsw_r2r(mm##4, mm##0);\
|
||||
mov##_m2r(*(in + offset + 3 * 8), mm##7);\
|
||||
pmulhw_r2r(mm##0, mm##1);\
|
||||
paddsw_m2r(*(in + offset + 4 * 8), mm##7);\
|
||||
psllw_i2r(SHIFT_FRW_COL, mm##5);\
|
||||
paddsw_r2r(mm##4, mm##6);\
|
||||
psllw_i2r(SHIFT_FRW_COL, mm##7);\
|
||||
mov##_r2r(mm##5, mm##4);\
|
||||
psubsw_r2r(mm##7, mm##5);\
|
||||
paddsw_r2r(mm##5, mm##1);\
|
||||
paddsw_r2r(mm##7, mm##4);\
|
||||
por_m2r(*fdct_one_corr, mm##1);\
|
||||
psllw_i2r(SHIFT_FRW_COL + 1, mm##2);\
|
||||
pmulhw_m2r(*(fdct_tg_all_16 + 8), mm##5);\
|
||||
mov##_r2r(mm##4, mm##7);\
|
||||
psubsw_m2r(*(in + offset + 5 * 8), mm##3);\
|
||||
psubsw_r2r(mm##6, mm##4);\
|
||||
mov##_r2m(mm##1, *(out + offset + 2 * 8));\
|
||||
paddsw_r2r(mm##6, mm##7);\
|
||||
mov##_m2r(*(in + offset + 3 * 8), mm##1);\
|
||||
psllw_i2r(SHIFT_FRW_COL + 1, mm##3);\
|
||||
psubsw_m2r(*(in + offset + 4 * 8), mm##1);\
|
||||
mov##_r2r(mm##2, mm##6);\
|
||||
mov##_r2m(mm##4, *(out + offset + 4 * 8));\
|
||||
paddsw_r2r(mm##3, mm##2);\
|
||||
pmulhw_m2r(*ocos_4_16, mm##2);\
|
||||
psubsw_r2r(mm##3, mm##6);\
|
||||
pmulhw_m2r(*ocos_4_16, mm##6);\
|
||||
psubsw_r2r(mm##0, mm##5);\
|
||||
por_m2r(*fdct_one_corr, mm##5);\
|
||||
psllw_i2r(SHIFT_FRW_COL, mm##1);\
|
||||
por_m2r(*fdct_one_corr, mm##2);\
|
||||
mov##_r2r(mm##1, mm##4);\
|
||||
mov##_m2r(*(in + offset + 0 * 8), mm##3);\
|
||||
paddsw_r2r(mm##6, mm##1);\
|
||||
psubsw_m2r(*(in + offset + 7 * 8), mm##3);\
|
||||
psubsw_r2r(mm##6, mm##4);\
|
||||
mov##_m2r(*(fdct_tg_all_16 + 0), mm##0);\
|
||||
psllw_i2r(SHIFT_FRW_COL, mm##3);\
|
||||
mov##_m2r(*(fdct_tg_all_16 + 16), mm##6);\
|
||||
pmulhw_r2r(mm##1, mm##0);\
|
||||
mov##_r2m(mm##7, *(out + offset + 0 * 8));\
|
||||
pmulhw_r2r(mm##4, mm##6);\
|
||||
mov##_r2m(mm##5, *(out + offset + 6 * 8));\
|
||||
mov##_r2r(mm##3, mm##7);\
|
||||
mov##_m2r(*(fdct_tg_all_16 + 16), mm##5);\
|
||||
psubsw_r2r(mm##2, mm##7);\
|
||||
paddsw_r2r(mm##2, mm##3);\
|
||||
pmulhw_r2r(mm##7, mm##5);\
|
||||
paddsw_r2r(mm##3, mm##0);\
|
||||
paddsw_r2r(mm##4, mm##6);\
|
||||
pmulhw_m2r(*(fdct_tg_all_16 + 0), mm##3);\
|
||||
por_m2r(*fdct_one_corr, mm##0);\
|
||||
paddsw_r2r(mm##7, mm##5);\
|
||||
psubsw_r2r(mm##6, mm##7);\
|
||||
mov##_r2m(mm##0, *(out + offset + 1 * 8));\
|
||||
paddsw_r2r(mm##4, mm##5);\
|
||||
mov##_r2m(mm##7, *(out + offset + 3 * 8));\
|
||||
psubsw_r2r(mm##1, mm##3);\
|
||||
mov##_r2m(mm##5, *(out + offset + 5 * 8));\
|
||||
mov##_r2m(mm##3, *(out + offset + 7 * 8));\
|
||||
}
|
||||
|
||||
FDCT_COL(mmx, mm, movq)
|
||||
FDCT_COL(sse2, xmm, movdqa)
|
||||
|
||||
static av_always_inline void fdct_row_sse2(const int16_t *in, int16_t *out)
|
||||
{
|
||||
asm volatile(
|
||||
#define FDCT_ROW_SSE2_H1(i,t) \
|
||||
"movq " #i "(%0), %%xmm2 \n\t" \
|
||||
"movq " #i "+8(%0), %%xmm0 \n\t" \
|
||||
"movdqa " #t "+32(%1), %%xmm3 \n\t" \
|
||||
"movdqa " #t "+48(%1), %%xmm7 \n\t" \
|
||||
"movdqa " #t "(%1), %%xmm4 \n\t" \
|
||||
"movdqa " #t "+16(%1), %%xmm5 \n\t"
|
||||
|
||||
#define FDCT_ROW_SSE2_H2(i,t) \
|
||||
"movq " #i "(%0), %%xmm2 \n\t" \
|
||||
"movq " #i "+8(%0), %%xmm0 \n\t" \
|
||||
"movdqa " #t "+32(%1), %%xmm3 \n\t" \
|
||||
"movdqa " #t "+48(%1), %%xmm7 \n\t"
|
||||
|
||||
#define FDCT_ROW_SSE2(i) \
|
||||
"movq %%xmm2, %%xmm1 \n\t" \
|
||||
"pshuflw $27, %%xmm0, %%xmm0 \n\t" \
|
||||
"paddsw %%xmm0, %%xmm1 \n\t" \
|
||||
"psubsw %%xmm0, %%xmm2 \n\t" \
|
||||
"punpckldq %%xmm2, %%xmm1 \n\t" \
|
||||
"pshufd $78, %%xmm1, %%xmm2 \n\t" \
|
||||
"pmaddwd %%xmm2, %%xmm3 \n\t" \
|
||||
"pmaddwd %%xmm1, %%xmm7 \n\t" \
|
||||
"pmaddwd %%xmm5, %%xmm2 \n\t" \
|
||||
"pmaddwd %%xmm4, %%xmm1 \n\t" \
|
||||
"paddd %%xmm7, %%xmm3 \n\t" \
|
||||
"paddd %%xmm2, %%xmm1 \n\t" \
|
||||
"paddd %%xmm6, %%xmm3 \n\t" \
|
||||
"paddd %%xmm6, %%xmm1 \n\t" \
|
||||
"psrad %3, %%xmm3 \n\t" \
|
||||
"psrad %3, %%xmm1 \n\t" \
|
||||
"packssdw %%xmm3, %%xmm1 \n\t" \
|
||||
"movdqa %%xmm1, " #i "(%4) \n\t"
|
||||
|
||||
"movdqa (%2), %%xmm6 \n\t"
|
||||
FDCT_ROW_SSE2_H1(0,0)
|
||||
FDCT_ROW_SSE2(0)
|
||||
FDCT_ROW_SSE2_H2(64,0)
|
||||
FDCT_ROW_SSE2(64)
|
||||
|
||||
FDCT_ROW_SSE2_H1(16,64)
|
||||
FDCT_ROW_SSE2(16)
|
||||
FDCT_ROW_SSE2_H2(112,64)
|
||||
FDCT_ROW_SSE2(112)
|
||||
|
||||
FDCT_ROW_SSE2_H1(32,128)
|
||||
FDCT_ROW_SSE2(32)
|
||||
FDCT_ROW_SSE2_H2(96,128)
|
||||
FDCT_ROW_SSE2(96)
|
||||
|
||||
FDCT_ROW_SSE2_H1(48,192)
|
||||
FDCT_ROW_SSE2(48)
|
||||
FDCT_ROW_SSE2_H2(80,192)
|
||||
FDCT_ROW_SSE2(80)
|
||||
:
|
||||
: "r" (in), "r" (tab_frw_01234567_sse2.tab_frw_01234567_sse2), "r" (fdct_r_row_sse2.fdct_r_row_sse2), "i" (SHIFT_FRW_ROW), "r" (out)
|
||||
);
|
||||
}
|
||||
|
||||
static av_always_inline void fdct_row_mmx2(const int16_t *in, int16_t *out, const int16_t *table)
|
||||
{
|
||||
pshufw_m2r(*(in + 4), mm5, 0x1B);
|
||||
movq_m2r(*(in + 0), mm0);
|
||||
movq_r2r(mm0, mm1);
|
||||
paddsw_r2r(mm5, mm0);
|
||||
psubsw_r2r(mm5, mm1);
|
||||
movq_r2r(mm0, mm2);
|
||||
punpckldq_r2r(mm1, mm0);
|
||||
punpckhdq_r2r(mm1, mm2);
|
||||
movq_m2r(*(table + 0), mm1);
|
||||
movq_m2r(*(table + 4), mm3);
|
||||
movq_m2r(*(table + 8), mm4);
|
||||
movq_m2r(*(table + 12), mm5);
|
||||
movq_m2r(*(table + 16), mm6);
|
||||
movq_m2r(*(table + 20), mm7);
|
||||
pmaddwd_r2r(mm0, mm1);
|
||||
pmaddwd_r2r(mm2, mm3);
|
||||
pmaddwd_r2r(mm0, mm4);
|
||||
pmaddwd_r2r(mm2, mm5);
|
||||
pmaddwd_r2r(mm0, mm6);
|
||||
pmaddwd_r2r(mm2, mm7);
|
||||
pmaddwd_m2r(*(table + 24), mm0);
|
||||
pmaddwd_m2r(*(table + 28), mm2);
|
||||
paddd_r2r(mm1, mm3);
|
||||
paddd_r2r(mm4, mm5);
|
||||
paddd_r2r(mm6, mm7);
|
||||
paddd_r2r(mm0, mm2);
|
||||
movq_m2r(*fdct_r_row, mm0);
|
||||
paddd_r2r(mm0, mm3);
|
||||
paddd_r2r(mm0, mm5);
|
||||
paddd_r2r(mm0, mm7);
|
||||
paddd_r2r(mm0, mm2);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm3);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm5);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm7);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm2);
|
||||
packssdw_r2r(mm5, mm3);
|
||||
packssdw_r2r(mm2, mm7);
|
||||
movq_r2m(mm3, *(out + 0));
|
||||
movq_r2m(mm7, *(out + 4));
|
||||
}
|
||||
|
||||
static av_always_inline void fdct_row_mmx(const int16_t *in, int16_t *out, const int16_t *table)
|
||||
{
|
||||
//FIXME reorder (I do not have an old MMX-only CPU here to benchmark ...)
|
||||
movd_m2r(*(in + 6), mm1);
|
||||
punpcklwd_m2r(*(in + 4), mm1);
|
||||
movq_r2r(mm1, mm2);
|
||||
psrlq_i2r(0x20, mm1);
|
||||
movq_m2r(*(in + 0), mm0);
|
||||
punpcklwd_r2r(mm2, mm1);
|
||||
movq_r2r(mm0, mm5);
|
||||
paddsw_r2r(mm1, mm0);
|
||||
psubsw_r2r(mm1, mm5);
|
||||
movq_r2r(mm0, mm2);
|
||||
punpckldq_r2r(mm5, mm0);
|
||||
punpckhdq_r2r(mm5, mm2);
|
||||
movq_m2r(*(table + 0), mm1);
|
||||
movq_m2r(*(table + 4), mm3);
|
||||
movq_m2r(*(table + 8), mm4);
|
||||
movq_m2r(*(table + 12), mm5);
|
||||
movq_m2r(*(table + 16), mm6);
|
||||
movq_m2r(*(table + 20), mm7);
|
||||
pmaddwd_r2r(mm0, mm1);
|
||||
pmaddwd_r2r(mm2, mm3);
|
||||
pmaddwd_r2r(mm0, mm4);
|
||||
pmaddwd_r2r(mm2, mm5);
|
||||
pmaddwd_r2r(mm0, mm6);
|
||||
pmaddwd_r2r(mm2, mm7);
|
||||
pmaddwd_m2r(*(table + 24), mm0);
|
||||
pmaddwd_m2r(*(table + 28), mm2);
|
||||
paddd_r2r(mm1, mm3);
|
||||
paddd_r2r(mm4, mm5);
|
||||
paddd_r2r(mm6, mm7);
|
||||
paddd_r2r(mm0, mm2);
|
||||
movq_m2r(*fdct_r_row, mm0);
|
||||
paddd_r2r(mm0, mm3);
|
||||
paddd_r2r(mm0, mm5);
|
||||
paddd_r2r(mm0, mm7);
|
||||
paddd_r2r(mm0, mm2);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm3);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm5);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm7);
|
||||
psrad_i2r(SHIFT_FRW_ROW, mm2);
|
||||
packssdw_r2r(mm5, mm3);
|
||||
packssdw_r2r(mm2, mm7);
|
||||
movq_r2m(mm3, *(out + 0));
|
||||
movq_r2m(mm7, *(out + 4));
|
||||
}
|
||||
|
||||
void ff_fdct_mmx(int16_t *block)
|
||||
{
|
||||
int64_t align_tmp[16] ATTR_ALIGN(8);
|
||||
int16_t * block1= (int16_t*)align_tmp;
|
||||
const int16_t *table= tab_frw_01234567;
|
||||
int i;
|
||||
|
||||
fdct_col_mmx(block, block1, 0);
|
||||
fdct_col_mmx(block, block1, 4);
|
||||
|
||||
for(i=8;i>0;i--) {
|
||||
fdct_row_mmx(block1, block, table);
|
||||
block1 += 8;
|
||||
table += 32;
|
||||
block += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void ff_fdct_mmx2(int16_t *block)
|
||||
{
|
||||
int64_t align_tmp[16] ATTR_ALIGN(8);
|
||||
int16_t *block1= (int16_t*)align_tmp;
|
||||
const int16_t *table= tab_frw_01234567;
|
||||
int i;
|
||||
|
||||
fdct_col_mmx(block, block1, 0);
|
||||
fdct_col_mmx(block, block1, 4);
|
||||
|
||||
for(i=8;i>0;i--) {
|
||||
fdct_row_mmx2(block1, block, table);
|
||||
block1 += 8;
|
||||
table += 32;
|
||||
block += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void ff_fdct_sse2(int16_t *block)
|
||||
{
|
||||
int64_t align_tmp[16] ATTR_ALIGN(16);
|
||||
int16_t * const block1= (int16_t*)align_tmp;
|
||||
|
||||
fdct_col_sse2(block, block1, 0);
|
||||
fdct_row_sse2(block1, block);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* FFT/MDCT transform with 3DNow! optimizations
|
||||
* Copyright (c) 2008 Loren Merritt
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define EMULATE_3DNOWEXT
|
||||
#include "fft_3dn2.c"
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* FFT/MDCT transform with Extended 3DNow! optimizations
|
||||
* Copyright (c) 2006-2008 Zuxy MENG Jie, Loren Merritt
|
||||
*
|
||||
* 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 "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
DECLARE_ALIGNED_8(static const int, m1m1[2]) = { 1<<31, 1<<31 };
|
||||
|
||||
#ifdef EMULATE_3DNOWEXT
|
||||
#define PSWAPD(s,d)\
|
||||
"movq "#s","#d"\n"\
|
||||
"psrlq $32,"#d"\n"\
|
||||
"punpckldq "#s","#d"\n"
|
||||
#define ff_fft_calc_3dn2 ff_fft_calc_3dn
|
||||
#define ff_fft_dispatch_3dn2 ff_fft_dispatch_3dn
|
||||
#define ff_fft_dispatch_interleave_3dn2 ff_fft_dispatch_interleave_3dn
|
||||
#define ff_imdct_calc_3dn2 ff_imdct_calc_3dn
|
||||
#define ff_imdct_half_3dn2 ff_imdct_half_3dn
|
||||
#else
|
||||
#define PSWAPD(s,d) "pswapd "#s","#d"\n"
|
||||
#endif
|
||||
|
||||
void ff_fft_dispatch_3dn2(FFTComplex *z, int nbits);
|
||||
void ff_fft_dispatch_interleave_3dn2(FFTComplex *z, int nbits);
|
||||
|
||||
void ff_fft_calc_3dn2(FFTContext *s, FFTComplex *z)
|
||||
{
|
||||
int n = 1<<s->nbits;
|
||||
int i;
|
||||
ff_fft_dispatch_interleave_3dn2(z, s->nbits);
|
||||
asm volatile("femms");
|
||||
if(n <= 8)
|
||||
for(i=0; i<n; i+=2)
|
||||
FFSWAP(FFTSample, z[i].im, z[i+1].re);
|
||||
}
|
||||
|
||||
void ff_imdct_half_3dn2(MDCTContext *s, FFTSample *output, const FFTSample *input)
|
||||
{
|
||||
x86_reg j, k;
|
||||
long n = 1 << s->nbits;
|
||||
long n2 = n >> 1;
|
||||
long n4 = n >> 2;
|
||||
long n8 = n >> 3;
|
||||
const uint16_t *revtab = s->fft.revtab;
|
||||
const FFTSample *tcos = s->tcos;
|
||||
const FFTSample *tsin = s->tsin;
|
||||
const FFTSample *in1, *in2;
|
||||
FFTComplex *z = (FFTComplex *)output;
|
||||
|
||||
/* pre rotation */
|
||||
in1 = input;
|
||||
in2 = input + n2 - 1;
|
||||
#ifdef EMULATE_3DNOWEXT
|
||||
asm volatile("movd %0, %%mm7" ::"r"(1<<31));
|
||||
#endif
|
||||
for(k = 0; k < n4; k++) {
|
||||
// FIXME a single block is faster, but gcc 2.95 and 3.4.x on 32bit can't compile it
|
||||
asm volatile(
|
||||
"movd %0, %%mm0 \n"
|
||||
"movd %2, %%mm1 \n"
|
||||
"punpckldq %1, %%mm0 \n"
|
||||
"punpckldq %3, %%mm1 \n"
|
||||
"movq %%mm0, %%mm2 \n"
|
||||
PSWAPD( %%mm1, %%mm3 )
|
||||
"pfmul %%mm1, %%mm0 \n"
|
||||
"pfmul %%mm3, %%mm2 \n"
|
||||
#ifdef EMULATE_3DNOWEXT
|
||||
"movq %%mm0, %%mm1 \n"
|
||||
"punpckhdq %%mm2, %%mm0 \n"
|
||||
"punpckldq %%mm2, %%mm1 \n"
|
||||
"pxor %%mm7, %%mm0 \n"
|
||||
"pfadd %%mm1, %%mm0 \n"
|
||||
#else
|
||||
"pfpnacc %%mm2, %%mm0 \n"
|
||||
#endif
|
||||
::"m"(in2[-2*k]), "m"(in1[2*k]),
|
||||
"m"(tcos[k]), "m"(tsin[k])
|
||||
);
|
||||
asm volatile(
|
||||
"movq %%mm0, %0 \n\t"
|
||||
:"=m"(z[revtab[k]])
|
||||
);
|
||||
}
|
||||
|
||||
ff_fft_dispatch_3dn2(z, s->fft.nbits);
|
||||
|
||||
#define CMUL(j,mm0,mm1)\
|
||||
"movq (%2,"#j",2), %%mm6 \n"\
|
||||
"movq 8(%2,"#j",2), "#mm0"\n"\
|
||||
"movq %%mm6, "#mm1"\n"\
|
||||
"movq "#mm0",%%mm7 \n"\
|
||||
"pfmul (%3,"#j"), %%mm6 \n"\
|
||||
"pfmul (%4,"#j"), "#mm0"\n"\
|
||||
"pfmul (%4,"#j"), "#mm1"\n"\
|
||||
"pfmul (%3,"#j"), %%mm7 \n"\
|
||||
"pfsub %%mm6, "#mm0"\n"\
|
||||
"pfadd %%mm7, "#mm1"\n"
|
||||
|
||||
/* post rotation */
|
||||
j = -n2;
|
||||
k = n2-8;
|
||||
asm volatile(
|
||||
"1: \n"
|
||||
CMUL(%0, %%mm0, %%mm1)
|
||||
CMUL(%1, %%mm2, %%mm3)
|
||||
"movd %%mm0, (%2,%0,2) \n"
|
||||
"movd %%mm1,12(%2,%1,2) \n"
|
||||
"movd %%mm2, (%2,%1,2) \n"
|
||||
"movd %%mm3,12(%2,%0,2) \n"
|
||||
"psrlq $32, %%mm0 \n"
|
||||
"psrlq $32, %%mm1 \n"
|
||||
"psrlq $32, %%mm2 \n"
|
||||
"psrlq $32, %%mm3 \n"
|
||||
"movd %%mm0, 8(%2,%0,2) \n"
|
||||
"movd %%mm1, 4(%2,%1,2) \n"
|
||||
"movd %%mm2, 8(%2,%1,2) \n"
|
||||
"movd %%mm3, 4(%2,%0,2) \n"
|
||||
"sub $8, %1 \n"
|
||||
"add $8, %0 \n"
|
||||
"jl 1b \n"
|
||||
:"+r"(j), "+r"(k)
|
||||
:"r"(z+n8), "r"(tcos+n8), "r"(tsin+n8)
|
||||
:"memory"
|
||||
);
|
||||
asm volatile("femms");
|
||||
}
|
||||
|
||||
void ff_imdct_calc_3dn2(MDCTContext *s, FFTSample *output, const FFTSample *input)
|
||||
{
|
||||
x86_reg j, k;
|
||||
long n = 1 << s->nbits;
|
||||
long n4 = n >> 2;
|
||||
|
||||
ff_imdct_half_3dn2(s, output+n4, input);
|
||||
|
||||
j = -n;
|
||||
k = n-8;
|
||||
asm volatile(
|
||||
"movq %4, %%mm7 \n"
|
||||
"1: \n"
|
||||
PSWAPD((%2,%1), %%mm0)
|
||||
PSWAPD((%3,%0), %%mm1)
|
||||
"pxor %%mm7, %%mm0 \n"
|
||||
"movq %%mm1, (%3,%1) \n"
|
||||
"movq %%mm0, (%2,%0) \n"
|
||||
"sub $8, %1 \n"
|
||||
"add $8, %0 \n"
|
||||
"jl 1b \n"
|
||||
:"+r"(j), "+r"(k)
|
||||
:"r"(output+n4), "r"(output+n4*3),
|
||||
"m"(*m1m1)
|
||||
);
|
||||
asm volatile("femms");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,467 @@
|
||||
;******************************************************************************
|
||||
;* FFT transform with SSE/3DNow optimizations
|
||||
;* Copyright (c) 2008 Loren Merritt
|
||||
;*
|
||||
;* 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
|
||||
;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
;******************************************************************************
|
||||
|
||||
; These functions are not individually interchangeable with the C versions.
|
||||
; While C takes arrays of FFTComplex, SSE/3DNow leave intermediate results
|
||||
; in blocks as conventient to the vector size.
|
||||
; i.e. {4x real, 4x imaginary, 4x real, ...} (or 2x respectively)
|
||||
|
||||
%include "x86inc.asm"
|
||||
|
||||
SECTION_RODATA
|
||||
|
||||
%define M_SQRT1_2 0.70710678118654752440
|
||||
ps_root2: times 4 dd M_SQRT1_2
|
||||
ps_root2mppm: dd -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2
|
||||
ps_m1p1: dd 1<<31, 0
|
||||
|
||||
%assign i 16
|
||||
%rep 13
|
||||
cextern ff_cos_ %+ i
|
||||
%assign i i<<1
|
||||
%endrep
|
||||
|
||||
%ifdef ARCH_X86_64
|
||||
%define pointer dq
|
||||
%else
|
||||
%define pointer dd
|
||||
%endif
|
||||
|
||||
%macro IF0 1+
|
||||
%endmacro
|
||||
%macro IF1 1+
|
||||
%1
|
||||
%endmacro
|
||||
|
||||
section .text align=16
|
||||
|
||||
%macro T2_3DN 4 ; z0, z1, mem0, mem1
|
||||
mova %1, %3
|
||||
mova %2, %1
|
||||
pfadd %1, %4
|
||||
pfsub %2, %4
|
||||
%endmacro
|
||||
|
||||
%macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
|
||||
mova %5, %3
|
||||
pfsub %3, %4
|
||||
pfadd %5, %4 ; {t6,t5}
|
||||
pxor %3, [ps_m1p1 GLOBAL] ; {t8,t7}
|
||||
mova %6, %1
|
||||
pswapd %3, %3
|
||||
pfadd %1, %5 ; {r0,i0}
|
||||
pfsub %6, %5 ; {r2,i2}
|
||||
mova %4, %2
|
||||
pfadd %2, %3 ; {r1,i1}
|
||||
pfsub %4, %3 ; {r3,i3}
|
||||
SWAP %3, %6
|
||||
%endmacro
|
||||
|
||||
; in: %1={r0,i0,r1,i1} %2={r2,i2,r3,i3}
|
||||
; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
|
||||
%macro T4_SSE 3
|
||||
mova %3, %1
|
||||
shufps %1, %2, 0x64 ; {r0,i0,r3,i2}
|
||||
shufps %3, %2, 0xce ; {r1,i1,r2,i3}
|
||||
mova %2, %1
|
||||
addps %1, %3 ; {t1,t2,t6,t5}
|
||||
subps %2, %3 ; {t3,t4,t8,t7}
|
||||
mova %3, %1
|
||||
shufps %1, %2, 0x44 ; {t1,t2,t3,t4}
|
||||
shufps %3, %2, 0xbe ; {t6,t5,t7,t8}
|
||||
mova %2, %1
|
||||
addps %1, %3 ; {r0,i0,r1,i1}
|
||||
subps %2, %3 ; {r2,i2,r3,i3}
|
||||
mova %3, %1
|
||||
shufps %1, %2, 0x88 ; {r0,r1,r2,r3}
|
||||
shufps %3, %2, 0xdd ; {i0,i1,i2,i3}
|
||||
SWAP %2, %3
|
||||
%endmacro
|
||||
|
||||
%macro T8_SSE 6 ; r0,i0,r1,i1,t0,t1
|
||||
mova %5, %3
|
||||
shufps %3, %4, 0x44 ; {r4,i4,r6,i6}
|
||||
shufps %5, %4, 0xee ; {r5,i5,r7,i7}
|
||||
mova %6, %3
|
||||
subps %3, %5 ; {r5,i5,r7,i7}
|
||||
addps %6, %5 ; {t1,t2,t3,t4}
|
||||
mova %5, %3
|
||||
shufps %5, %5, 0xb1 ; {i5,r5,i7,r7}
|
||||
mulps %3, [ps_root2mppm GLOBAL] ; {-r5,i5,r7,-i7}
|
||||
mulps %5, [ps_root2 GLOBAL]
|
||||
addps %3, %5 ; {t8,t7,ta,t9}
|
||||
mova %5, %6
|
||||
shufps %6, %3, 0x36 ; {t3,t2,t9,t8}
|
||||
shufps %5, %3, 0x9c ; {t1,t4,t7,ta}
|
||||
mova %3, %6
|
||||
addps %6, %5 ; {t1,t2,t9,ta}
|
||||
subps %3, %5 ; {t6,t5,tc,tb}
|
||||
mova %5, %6
|
||||
shufps %6, %3, 0xd8 ; {t1,t9,t5,tb}
|
||||
shufps %5, %3, 0x8d ; {t2,ta,t6,tc}
|
||||
mova %3, %1
|
||||
mova %4, %2
|
||||
addps %1, %6 ; {r0,r1,r2,r3}
|
||||
addps %2, %5 ; {i0,i1,i2,i3}
|
||||
subps %3, %6 ; {r4,r5,r6,r7}
|
||||
subps %4, %5 ; {i4,i5,i6,i7}
|
||||
%endmacro
|
||||
|
||||
; scheduled for cpu-bound sizes
|
||||
%macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
|
||||
IF%1 mova m4, Z(4)
|
||||
IF%1 mova m5, Z(5)
|
||||
mova m0, %2 ; wre
|
||||
mova m2, m4
|
||||
mova m1, %3 ; wim
|
||||
mova m3, m5
|
||||
mulps m2, m0 ; r2*wre
|
||||
IF%1 mova m6, Z(6)
|
||||
mulps m3, m1 ; i2*wim
|
||||
IF%1 mova m7, Z(7)
|
||||
mulps m4, m1 ; r2*wim
|
||||
mulps m5, m0 ; i2*wre
|
||||
addps m2, m3 ; r2*wre + i2*wim
|
||||
mova m3, m1
|
||||
mulps m1, m6 ; r3*wim
|
||||
subps m5, m4 ; i2*wre - r2*wim
|
||||
mova m4, m0
|
||||
mulps m3, m7 ; i3*wim
|
||||
mulps m4, m6 ; r3*wre
|
||||
mulps m0, m7 ; i3*wre
|
||||
subps m4, m3 ; r3*wre - i3*wim
|
||||
mova m3, Z(0)
|
||||
addps m0, m1 ; i3*wre + r3*wim
|
||||
mova m1, m4
|
||||
addps m4, m2 ; t5
|
||||
subps m1, m2 ; t3
|
||||
subps m3, m4 ; r2
|
||||
addps m4, Z(0) ; r0
|
||||
mova m6, Z(2)
|
||||
mova Z(4), m3
|
||||
mova Z(0), m4
|
||||
mova m3, m5
|
||||
subps m5, m0 ; t4
|
||||
mova m4, m6
|
||||
subps m6, m5 ; r3
|
||||
addps m5, m4 ; r1
|
||||
mova Z(6), m6
|
||||
mova Z(2), m5
|
||||
mova m2, Z(3)
|
||||
addps m3, m0 ; t6
|
||||
subps m2, m1 ; i3
|
||||
mova m7, Z(1)
|
||||
addps m1, Z(3) ; i1
|
||||
mova Z(7), m2
|
||||
mova Z(3), m1
|
||||
mova m4, m7
|
||||
subps m7, m3 ; i2
|
||||
addps m3, m4 ; i0
|
||||
mova Z(5), m7
|
||||
mova Z(1), m3
|
||||
%endmacro
|
||||
|
||||
; scheduled to avoid store->load aliasing
|
||||
%macro PASS_BIG 1 ; (!interleave)
|
||||
mova m4, Z(4) ; r2
|
||||
mova m5, Z(5) ; i2
|
||||
mova m2, m4
|
||||
mova m0, [wq] ; wre
|
||||
mova m3, m5
|
||||
mova m1, [wq+o1q] ; wim
|
||||
mulps m2, m0 ; r2*wre
|
||||
mova m6, Z(6) ; r3
|
||||
mulps m3, m1 ; i2*wim
|
||||
mova m7, Z(7) ; i3
|
||||
mulps m4, m1 ; r2*wim
|
||||
mulps m5, m0 ; i2*wre
|
||||
addps m2, m3 ; r2*wre + i2*wim
|
||||
mova m3, m1
|
||||
mulps m1, m6 ; r3*wim
|
||||
subps m5, m4 ; i2*wre - r2*wim
|
||||
mova m4, m0
|
||||
mulps m3, m7 ; i3*wim
|
||||
mulps m4, m6 ; r3*wre
|
||||
mulps m0, m7 ; i3*wre
|
||||
subps m4, m3 ; r3*wre - i3*wim
|
||||
mova m3, Z(0)
|
||||
addps m0, m1 ; i3*wre + r3*wim
|
||||
mova m1, m4
|
||||
addps m4, m2 ; t5
|
||||
subps m1, m2 ; t3
|
||||
subps m3, m4 ; r2
|
||||
addps m4, Z(0) ; r0
|
||||
mova m6, Z(2)
|
||||
mova Z(4), m3
|
||||
mova Z(0), m4
|
||||
mova m3, m5
|
||||
subps m5, m0 ; t4
|
||||
mova m4, m6
|
||||
subps m6, m5 ; r3
|
||||
addps m5, m4 ; r1
|
||||
IF%1 mova Z(6), m6
|
||||
IF%1 mova Z(2), m5
|
||||
mova m2, Z(3)
|
||||
addps m3, m0 ; t6
|
||||
subps m2, m1 ; i3
|
||||
mova m7, Z(1)
|
||||
addps m1, Z(3) ; i1
|
||||
IF%1 mova Z(7), m2
|
||||
IF%1 mova Z(3), m1
|
||||
mova m4, m7
|
||||
subps m7, m3 ; i2
|
||||
addps m3, m4 ; i0
|
||||
IF%1 mova Z(5), m7
|
||||
IF%1 mova Z(1), m3
|
||||
%if %1==0
|
||||
mova m4, m5 ; r1
|
||||
mova m0, m6 ; r3
|
||||
unpcklps m5, m1
|
||||
unpckhps m4, m1
|
||||
unpcklps m6, m2
|
||||
unpckhps m0, m2
|
||||
mova m1, Z(0)
|
||||
mova m2, Z(4)
|
||||
mova Z(2), m5
|
||||
mova Z(3), m4
|
||||
mova Z(6), m6
|
||||
mova Z(7), m0
|
||||
mova m5, m1 ; r0
|
||||
mova m4, m2 ; r2
|
||||
unpcklps m1, m3
|
||||
unpckhps m5, m3
|
||||
unpcklps m2, m7
|
||||
unpckhps m4, m7
|
||||
mova Z(0), m1
|
||||
mova Z(1), m5
|
||||
mova Z(4), m2
|
||||
mova Z(5), m4
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro PUNPCK 3
|
||||
mova %3, %1
|
||||
punpckldq %1, %2
|
||||
punpckhdq %3, %2
|
||||
%endmacro
|
||||
|
||||
INIT_XMM
|
||||
|
||||
%define Z(x) [r0+mmsize*x]
|
||||
|
||||
align 16
|
||||
fft4_sse:
|
||||
mova m0, Z(0)
|
||||
mova m1, Z(1)
|
||||
T4_SSE m0, m1, m2
|
||||
mova Z(0), m0
|
||||
mova Z(1), m1
|
||||
ret
|
||||
|
||||
align 16
|
||||
fft8_sse:
|
||||
mova m0, Z(0)
|
||||
mova m1, Z(1)
|
||||
T4_SSE m0, m1, m2
|
||||
mova m2, Z(2)
|
||||
mova m3, Z(3)
|
||||
T8_SSE m0, m1, m2, m3, m4, m5
|
||||
mova Z(0), m0
|
||||
mova Z(1), m1
|
||||
mova Z(2), m2
|
||||
mova Z(3), m3
|
||||
ret
|
||||
|
||||
align 16
|
||||
fft16_sse:
|
||||
mova m0, Z(0)
|
||||
mova m1, Z(1)
|
||||
T4_SSE m0, m1, m2
|
||||
mova m2, Z(2)
|
||||
mova m3, Z(3)
|
||||
T8_SSE m0, m1, m2, m3, m4, m5
|
||||
mova m4, Z(4)
|
||||
mova m5, Z(5)
|
||||
mova Z(0), m0
|
||||
mova Z(1), m1
|
||||
mova Z(2), m2
|
||||
mova Z(3), m3
|
||||
T4_SSE m4, m5, m6
|
||||
mova m6, Z(6)
|
||||
mova m7, Z(7)
|
||||
T4_SSE m6, m7, m0
|
||||
PASS_SMALL 0, [ff_cos_16 GLOBAL], [ff_cos_16+16 GLOBAL]
|
||||
ret
|
||||
|
||||
|
||||
INIT_MMX
|
||||
|
||||
%macro FFT48_3DN 1
|
||||
align 16
|
||||
fft4%1:
|
||||
T2_3DN m0, m1, Z(0), Z(1)
|
||||
mova m2, Z(2)
|
||||
mova m3, Z(3)
|
||||
T4_3DN m0, m1, m2, m3, m4, m5
|
||||
PUNPCK m0, m1, m4
|
||||
PUNPCK m2, m3, m5
|
||||
mova Z(0), m0
|
||||
mova Z(1), m4
|
||||
mova Z(2), m2
|
||||
mova Z(3), m5
|
||||
ret
|
||||
|
||||
align 16
|
||||
fft8%1:
|
||||
T2_3DN m0, m1, Z(0), Z(1)
|
||||
mova m2, Z(2)
|
||||
mova m3, Z(3)
|
||||
T4_3DN m0, m1, m2, m3, m4, m5
|
||||
mova Z(0), m0
|
||||
mova Z(2), m2
|
||||
T2_3DN m4, m5, Z(4), Z(5)
|
||||
T2_3DN m6, m7, Z(6), Z(7)
|
||||
pswapd m0, m5
|
||||
pswapd m2, m7
|
||||
pxor m0, [ps_m1p1 GLOBAL]
|
||||
pxor m2, [ps_m1p1 GLOBAL]
|
||||
pfsub m5, m0
|
||||
pfadd m7, m2
|
||||
pfmul m5, [ps_root2 GLOBAL]
|
||||
pfmul m7, [ps_root2 GLOBAL]
|
||||
T4_3DN m1, m3, m5, m7, m0, m2
|
||||
mova Z(5), m5
|
||||
mova Z(7), m7
|
||||
mova m0, Z(0)
|
||||
mova m2, Z(2)
|
||||
T4_3DN m0, m2, m4, m6, m5, m7
|
||||
PUNPCK m0, m1, m5
|
||||
PUNPCK m2, m3, m7
|
||||
mova Z(0), m0
|
||||
mova Z(1), m5
|
||||
mova Z(2), m2
|
||||
mova Z(3), m7
|
||||
PUNPCK m4, Z(5), m5
|
||||
PUNPCK m6, Z(7), m7
|
||||
mova Z(4), m4
|
||||
mova Z(5), m5
|
||||
mova Z(6), m6
|
||||
mova Z(7), m7
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
FFT48_3DN _3dn2
|
||||
|
||||
%macro pswapd 2
|
||||
%ifidn %1, %2
|
||||
movd [r0+12], %1
|
||||
punpckhdq %1, [r0+8]
|
||||
%else
|
||||
movq %1, %2
|
||||
psrlq %1, 32
|
||||
punpckldq %1, %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
FFT48_3DN _3dn
|
||||
|
||||
|
||||
%define Z(x) [zq + o1q*(x&6)*((x/6)^1) + o3q*(x/6) + mmsize*(x&1)]
|
||||
|
||||
%macro DECL_PASS 2+ ; name, payload
|
||||
align 16
|
||||
%1:
|
||||
DEFINE_ARGS z, w, n, o1, o3
|
||||
lea o3q, [nq*3]
|
||||
lea o1q, [nq*8]
|
||||
shl o3q, 4
|
||||
.loop:
|
||||
%2
|
||||
add zq, mmsize*2
|
||||
add wq, mmsize
|
||||
sub nd, mmsize/8
|
||||
jg .loop
|
||||
rep ret
|
||||
%endmacro
|
||||
|
||||
INIT_XMM
|
||||
DECL_PASS pass_sse, PASS_BIG 1
|
||||
DECL_PASS pass_interleave_sse, PASS_BIG 0
|
||||
|
||||
INIT_MMX
|
||||
%define mulps pfmul
|
||||
%define addps pfadd
|
||||
%define subps pfsub
|
||||
%define unpcklps punpckldq
|
||||
%define unpckhps punpckhdq
|
||||
DECL_PASS pass_3dn, PASS_SMALL 1, [wq], [wq+o1q]
|
||||
DECL_PASS pass_interleave_3dn, PASS_BIG 0
|
||||
%define pass_3dn2 pass_3dn
|
||||
%define pass_interleave_3dn2 pass_interleave_3dn
|
||||
|
||||
|
||||
%macro DECL_FFT 2-3 ; nbits, cpu, suffix
|
||||
%xdefine list_of_fft fft4%2, fft8%2
|
||||
%if %1==5
|
||||
%xdefine list_of_fft list_of_fft, fft16%2
|
||||
%endif
|
||||
|
||||
%assign n 1<<%1
|
||||
%rep 17-%1
|
||||
%assign n2 n/2
|
||||
%assign n4 n/4
|
||||
%xdefine list_of_fft list_of_fft, fft %+ n %+ %3%2
|
||||
|
||||
align 16
|
||||
fft %+ n %+ %3%2:
|
||||
call fft %+ n2 %+ %2
|
||||
add r0, n*4 - (n&(-2<<%1))
|
||||
call fft %+ n4 %+ %2
|
||||
add r0, n*2 - (n2&(-2<<%1))
|
||||
call fft %+ n4 %+ %2
|
||||
sub r0, n*6 + (n2&(-2<<%1))
|
||||
lea r1, [ff_cos_ %+ n GLOBAL]
|
||||
mov r2d, n4/2
|
||||
jmp pass%3%2
|
||||
|
||||
%assign n n*2
|
||||
%endrep
|
||||
%undef n
|
||||
|
||||
align 8
|
||||
dispatch_tab%3%2: pointer list_of_fft
|
||||
|
||||
; On x86_32, this function does the register saving and restoring for all of fft.
|
||||
; The others pass args in registers and don't spill anything.
|
||||
cglobal ff_fft_dispatch%3%2, 2,5,0, z, nbits
|
||||
lea r2, [dispatch_tab%3%2 GLOBAL]
|
||||
mov r2, [r2 + (nbitsq-2)*gprsize]
|
||||
call r2
|
||||
RET
|
||||
%endmacro ; DECL_FFT
|
||||
|
||||
DECL_FFT 5, _sse
|
||||
DECL_FFT 5, _sse, _interleave
|
||||
DECL_FFT 4, _3dn
|
||||
DECL_FFT 4, _3dn, _interleave
|
||||
DECL_FFT 4, _3dn2
|
||||
DECL_FFT 4, _3dn2, _interleave
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* FFT/MDCT transform with SSE optimizations
|
||||
* Copyright (c) 2008 Loren Merritt
|
||||
*
|
||||
* 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 "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
static const int m1m1m1m1[4] __attribute__((aligned(16))) =
|
||||
{ 1 << 31, 1 << 31, 1 << 31, 1 << 31 };
|
||||
|
||||
void ff_fft_dispatch_sse(FFTComplex *z, int nbits);
|
||||
void ff_fft_dispatch_interleave_sse(FFTComplex *z, int nbits);
|
||||
|
||||
void ff_fft_calc_sse(FFTContext *s, FFTComplex *z)
|
||||
{
|
||||
int n = 1 << s->nbits;
|
||||
|
||||
ff_fft_dispatch_interleave_sse(z, s->nbits);
|
||||
|
||||
if(n <= 16) {
|
||||
x86_reg i = -8*n;
|
||||
asm volatile(
|
||||
"1: \n"
|
||||
"movaps (%0,%1), %%xmm0 \n"
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
"unpcklps 16(%0,%1), %%xmm0 \n"
|
||||
"unpckhps 16(%0,%1), %%xmm1 \n"
|
||||
"movaps %%xmm0, (%0,%1) \n"
|
||||
"movaps %%xmm1, 16(%0,%1) \n"
|
||||
"add $32, %0 \n"
|
||||
"jl 1b \n"
|
||||
:"+r"(i)
|
||||
:"r"(z+n)
|
||||
:"memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void ff_fft_permute_sse(FFTContext *s, FFTComplex *z)
|
||||
{
|
||||
int n = 1 << s->nbits;
|
||||
int i;
|
||||
for(i=0; i<n; i+=2) {
|
||||
asm volatile(
|
||||
"movaps %2, %%xmm0 \n"
|
||||
"movlps %%xmm0, %0 \n"
|
||||
"movhps %%xmm0, %1 \n"
|
||||
:"=m"(s->tmp_buf[s->revtab[i]]),
|
||||
"=m"(s->tmp_buf[s->revtab[i+1]])
|
||||
:"m"(z[i])
|
||||
);
|
||||
}
|
||||
memcpy(z, s->tmp_buf, n*sizeof(FFTComplex));
|
||||
}
|
||||
|
||||
void ff_imdct_half_sse(MDCTContext *s, FFTSample *output, const FFTSample *input)
|
||||
{
|
||||
av_unused x86_reg i, j, k, l;
|
||||
long n = 1 << s->nbits;
|
||||
long n2 = n >> 1;
|
||||
long n4 = n >> 2;
|
||||
long n8 = n >> 3;
|
||||
const uint16_t *revtab = s->fft.revtab + n8;
|
||||
const FFTSample *tcos = s->tcos;
|
||||
const FFTSample *tsin = s->tsin;
|
||||
FFTComplex *z = (FFTComplex *)output;
|
||||
|
||||
/* pre rotation */
|
||||
for(k=n8-2; k>=0; k-=2) {
|
||||
asm volatile(
|
||||
"movaps (%2,%1,2), %%xmm0 \n" // { z[k].re, z[k].im, z[k+1].re, z[k+1].im }
|
||||
"movaps -16(%2,%0,2), %%xmm1 \n" // { z[-k-2].re, z[-k-2].im, z[-k-1].re, z[-k-1].im }
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
"shufps $0x88, %%xmm1, %%xmm0 \n" // { z[k].re, z[k+1].re, z[-k-2].re, z[-k-1].re }
|
||||
"shufps $0x77, %%xmm2, %%xmm1 \n" // { z[-k-1].im, z[-k-2].im, z[k+1].im, z[k].im }
|
||||
"movlps (%3,%1), %%xmm4 \n"
|
||||
"movlps (%4,%1), %%xmm5 \n"
|
||||
"movhps -8(%3,%0), %%xmm4 \n" // { cos[k], cos[k+1], cos[-k-2], cos[-k-1] }
|
||||
"movhps -8(%4,%0), %%xmm5 \n" // { sin[k], sin[k+1], sin[-k-2], sin[-k-1] }
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
"movaps %%xmm1, %%xmm3 \n"
|
||||
"mulps %%xmm5, %%xmm0 \n" // re*sin
|
||||
"mulps %%xmm4, %%xmm1 \n" // im*cos
|
||||
"mulps %%xmm4, %%xmm2 \n" // re*cos
|
||||
"mulps %%xmm5, %%xmm3 \n" // im*sin
|
||||
"subps %%xmm0, %%xmm1 \n" // -> re
|
||||
"addps %%xmm3, %%xmm2 \n" // -> im
|
||||
"movaps %%xmm1, %%xmm0 \n"
|
||||
"unpcklps %%xmm2, %%xmm1 \n" // { z[k], z[k+1] }
|
||||
"unpckhps %%xmm2, %%xmm0 \n" // { z[-k-2], z[-k-1] }
|
||||
::"r"(-4*k), "r"(4*k),
|
||||
"r"(input+n4), "r"(tcos+n8), "r"(tsin+n8)
|
||||
);
|
||||
#ifdef ARCH_X86_64
|
||||
// if we have enough regs, don't let gcc make the luts latency-bound
|
||||
// but if not, latency is faster than spilling
|
||||
asm("movlps %%xmm0, %0 \n"
|
||||
"movhps %%xmm0, %1 \n"
|
||||
"movlps %%xmm1, %2 \n"
|
||||
"movhps %%xmm1, %3 \n"
|
||||
:"=m"(z[revtab[-k-2]]),
|
||||
"=m"(z[revtab[-k-1]]),
|
||||
"=m"(z[revtab[ k ]]),
|
||||
"=m"(z[revtab[ k+1]])
|
||||
);
|
||||
#else
|
||||
asm("movlps %%xmm0, %0" :"=m"(z[revtab[-k-2]]));
|
||||
asm("movhps %%xmm0, %0" :"=m"(z[revtab[-k-1]]));
|
||||
asm("movlps %%xmm1, %0" :"=m"(z[revtab[ k ]]));
|
||||
asm("movhps %%xmm1, %0" :"=m"(z[revtab[ k+1]]));
|
||||
#endif
|
||||
}
|
||||
|
||||
ff_fft_dispatch_sse(z, s->fft.nbits);
|
||||
|
||||
/* post rotation + reinterleave + reorder */
|
||||
|
||||
#define CMUL(j,xmm0,xmm1)\
|
||||
"movaps (%2,"#j",2), %%xmm6 \n"\
|
||||
"movaps 16(%2,"#j",2), "#xmm0"\n"\
|
||||
"movaps %%xmm6, "#xmm1"\n"\
|
||||
"movaps "#xmm0",%%xmm7 \n"\
|
||||
"mulps (%3,"#j"), %%xmm6 \n"\
|
||||
"mulps (%4,"#j"), "#xmm0"\n"\
|
||||
"mulps (%4,"#j"), "#xmm1"\n"\
|
||||
"mulps (%3,"#j"), %%xmm7 \n"\
|
||||
"subps %%xmm6, "#xmm0"\n"\
|
||||
"addps %%xmm7, "#xmm1"\n"
|
||||
|
||||
j = -n2;
|
||||
k = n2-16;
|
||||
asm volatile(
|
||||
"1: \n"
|
||||
CMUL(%0, %%xmm0, %%xmm1)
|
||||
CMUL(%1, %%xmm4, %%xmm5)
|
||||
"shufps $0x1b, %%xmm1, %%xmm1 \n"
|
||||
"shufps $0x1b, %%xmm5, %%xmm5 \n"
|
||||
"movaps %%xmm4, %%xmm6 \n"
|
||||
"unpckhps %%xmm1, %%xmm4 \n"
|
||||
"unpcklps %%xmm1, %%xmm6 \n"
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
"unpcklps %%xmm5, %%xmm0 \n"
|
||||
"unpckhps %%xmm5, %%xmm2 \n"
|
||||
"movaps %%xmm6, (%2,%1,2) \n"
|
||||
"movaps %%xmm4, 16(%2,%1,2) \n"
|
||||
"movaps %%xmm0, (%2,%0,2) \n"
|
||||
"movaps %%xmm2, 16(%2,%0,2) \n"
|
||||
"sub $16, %1 \n"
|
||||
"add $16, %0 \n"
|
||||
"jl 1b \n"
|
||||
:"+&r"(j), "+&r"(k)
|
||||
:"r"(z+n8), "r"(tcos+n8), "r"(tsin+n8)
|
||||
:"memory"
|
||||
);
|
||||
}
|
||||
|
||||
void ff_imdct_calc_sse(MDCTContext *s, FFTSample *output, const FFTSample *input)
|
||||
{
|
||||
x86_reg j, k;
|
||||
long n = 1 << s->nbits;
|
||||
long n4 = n >> 2;
|
||||
|
||||
ff_imdct_half_sse(s, output+n4, input);
|
||||
|
||||
j = -n;
|
||||
k = n-16;
|
||||
asm volatile(
|
||||
"movaps %4, %%xmm7 \n"
|
||||
"1: \n"
|
||||
"movaps (%2,%1), %%xmm0 \n"
|
||||
"movaps (%3,%0), %%xmm1 \n"
|
||||
"shufps $0x1b, %%xmm0, %%xmm0 \n"
|
||||
"shufps $0x1b, %%xmm1, %%xmm1 \n"
|
||||
"xorps %%xmm7, %%xmm0 \n"
|
||||
"movaps %%xmm1, (%3,%1) \n"
|
||||
"movaps %%xmm0, (%2,%0) \n"
|
||||
"sub $16, %1 \n"
|
||||
"add $16, %0 \n"
|
||||
"jl 1b \n"
|
||||
:"+r"(j), "+r"(k)
|
||||
:"r"(output+n4), "r"(output+n4*3),
|
||||
"m"(*m1m1m1m1)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* MMX optimized FLAC DSP utils
|
||||
* Copyright (c) 2007 Loren Merritt
|
||||
*
|
||||
* 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 "libavutil/x86_cpu.h"
|
||||
#include "dsputil_mmx.h"
|
||||
|
||||
static void apply_welch_window_sse2(const int32_t *data, int len, double *w_data)
|
||||
{
|
||||
double c = 2.0 / (len-1.0);
|
||||
int n2 = len>>1;
|
||||
x86_reg i = -n2*sizeof(int32_t);
|
||||
x86_reg j = n2*sizeof(int32_t);
|
||||
asm volatile(
|
||||
"movsd %0, %%xmm7 \n\t"
|
||||
"movapd "MANGLE(ff_pd_1)", %%xmm6 \n\t"
|
||||
"movapd "MANGLE(ff_pd_2)", %%xmm5 \n\t"
|
||||
"movlhps %%xmm7, %%xmm7 \n\t"
|
||||
"subpd %%xmm5, %%xmm7 \n\t"
|
||||
"addsd %%xmm6, %%xmm7 \n\t"
|
||||
::"m"(c)
|
||||
);
|
||||
#define WELCH(MOVPD, offset)\
|
||||
asm volatile(\
|
||||
"1: \n\t"\
|
||||
"movapd %%xmm7, %%xmm1 \n\t"\
|
||||
"mulpd %%xmm1, %%xmm1 \n\t"\
|
||||
"movapd %%xmm6, %%xmm0 \n\t"\
|
||||
"subpd %%xmm1, %%xmm0 \n\t"\
|
||||
"pshufd $0x4e, %%xmm0, %%xmm1 \n\t"\
|
||||
"cvtpi2pd (%3,%0), %%xmm2 \n\t"\
|
||||
"cvtpi2pd "#offset"*4(%3,%1), %%xmm3 \n\t"\
|
||||
"mulpd %%xmm0, %%xmm2 \n\t"\
|
||||
"mulpd %%xmm1, %%xmm3 \n\t"\
|
||||
"movapd %%xmm2, (%2,%0,2) \n\t"\
|
||||
MOVPD" %%xmm3, "#offset"*8(%2,%1,2) \n\t"\
|
||||
"subpd %%xmm5, %%xmm7 \n\t"\
|
||||
"sub $8, %1 \n\t"\
|
||||
"add $8, %0 \n\t"\
|
||||
"jl 1b \n\t"\
|
||||
:"+&r"(i), "+&r"(j)\
|
||||
:"r"(w_data+n2), "r"(data+n2)\
|
||||
);
|
||||
if(len&1)
|
||||
WELCH("movupd", -1)
|
||||
else
|
||||
WELCH("movapd", -2)
|
||||
#undef WELCH
|
||||
}
|
||||
|
||||
void ff_flac_compute_autocorr_sse2(const int32_t *data, int len, int lag,
|
||||
double *autoc)
|
||||
{
|
||||
double tmp[len + lag + 2];
|
||||
double *data1 = tmp + lag;
|
||||
int j;
|
||||
|
||||
if((x86_reg)data1 & 15)
|
||||
data1++;
|
||||
|
||||
apply_welch_window_sse2(data, len, data1);
|
||||
|
||||
for(j=0; j<lag; j++)
|
||||
data1[j-lag]= 0.0;
|
||||
data1[len] = 0.0;
|
||||
|
||||
for(j=0; j<lag; j+=2){
|
||||
x86_reg i = -len*sizeof(double);
|
||||
if(j == lag-2) {
|
||||
asm volatile(
|
||||
"movsd "MANGLE(ff_pd_1)", %%xmm0 \n\t"
|
||||
"movsd "MANGLE(ff_pd_1)", %%xmm1 \n\t"
|
||||
"movsd "MANGLE(ff_pd_1)", %%xmm2 \n\t"
|
||||
"1: \n\t"
|
||||
"movapd (%4,%0), %%xmm3 \n\t"
|
||||
"movupd -8(%5,%0), %%xmm4 \n\t"
|
||||
"movapd (%5,%0), %%xmm5 \n\t"
|
||||
"mulpd %%xmm3, %%xmm4 \n\t"
|
||||
"mulpd %%xmm3, %%xmm5 \n\t"
|
||||
"mulpd -16(%5,%0), %%xmm3 \n\t"
|
||||
"addpd %%xmm4, %%xmm1 \n\t"
|
||||
"addpd %%xmm5, %%xmm0 \n\t"
|
||||
"addpd %%xmm3, %%xmm2 \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"jl 1b \n\t"
|
||||
"movhlps %%xmm0, %%xmm3 \n\t"
|
||||
"movhlps %%xmm1, %%xmm4 \n\t"
|
||||
"movhlps %%xmm2, %%xmm5 \n\t"
|
||||
"addsd %%xmm3, %%xmm0 \n\t"
|
||||
"addsd %%xmm4, %%xmm1 \n\t"
|
||||
"addsd %%xmm5, %%xmm2 \n\t"
|
||||
"movsd %%xmm0, %1 \n\t"
|
||||
"movsd %%xmm1, %2 \n\t"
|
||||
"movsd %%xmm2, %3 \n\t"
|
||||
:"+&r"(i), "=m"(autoc[j]), "=m"(autoc[j+1]), "=m"(autoc[j+2])
|
||||
:"r"(data1+len), "r"(data1+len-j)
|
||||
);
|
||||
} else {
|
||||
asm volatile(
|
||||
"movsd "MANGLE(ff_pd_1)", %%xmm0 \n\t"
|
||||
"movsd "MANGLE(ff_pd_1)", %%xmm1 \n\t"
|
||||
"1: \n\t"
|
||||
"movapd (%3,%0), %%xmm3 \n\t"
|
||||
"movupd -8(%4,%0), %%xmm4 \n\t"
|
||||
"mulpd %%xmm3, %%xmm4 \n\t"
|
||||
"mulpd (%4,%0), %%xmm3 \n\t"
|
||||
"addpd %%xmm4, %%xmm1 \n\t"
|
||||
"addpd %%xmm3, %%xmm0 \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"jl 1b \n\t"
|
||||
"movhlps %%xmm0, %%xmm3 \n\t"
|
||||
"movhlps %%xmm1, %%xmm4 \n\t"
|
||||
"addsd %%xmm3, %%xmm0 \n\t"
|
||||
"addsd %%xmm4, %%xmm1 \n\t"
|
||||
"movsd %%xmm0, %1 \n\t"
|
||||
"movsd %%xmm1, %2 \n\t"
|
||||
:"+&r"(i), "=m"(autoc[j]), "=m"(autoc[j+1])
|
||||
:"r"(data1+len), "r"(data1+len-j)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
|
||||
* Copyright (c) 2003 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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 h264_i386.h
|
||||
* H.264 / AVC / MPEG4 part10 codec.
|
||||
* non-MMX i386-specific optimizations for H.264
|
||||
* @author Michael Niedermayer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_H264_I386_H
|
||||
#define FFMPEG_H264_I386_H
|
||||
|
||||
#include "libavcodec/cabac.h"
|
||||
|
||||
//FIXME use some macros to avoid duplicating get_cabac (cannot be done yet
|
||||
//as that would make optimization work hard)
|
||||
#if defined(ARCH_X86) && defined(HAVE_7REGS) && \
|
||||
defined(HAVE_EBX_AVAILABLE) && \
|
||||
!defined(BROKEN_RELOCATIONS)
|
||||
static int decode_significance_x86(CABACContext *c, int max_coeff,
|
||||
uint8_t *significant_coeff_ctx_base,
|
||||
int *index){
|
||||
void *end= significant_coeff_ctx_base + max_coeff - 1;
|
||||
int minusstart= -(int)significant_coeff_ctx_base;
|
||||
int minusindex= 4-(int)index;
|
||||
int coeff_count;
|
||||
asm volatile(
|
||||
"movl "RANGE "(%3), %%esi \n\t"
|
||||
"movl "LOW "(%3), %%ebx \n\t"
|
||||
|
||||
"2: \n\t"
|
||||
|
||||
BRANCHLESS_GET_CABAC("%%edx", "%3", "(%1)", "%%ebx",
|
||||
"%%bx", "%%esi", "%%eax", "%%al")
|
||||
|
||||
"test $1, %%edx \n\t"
|
||||
" jz 3f \n\t"
|
||||
|
||||
BRANCHLESS_GET_CABAC("%%edx", "%3", "61(%1)", "%%ebx",
|
||||
"%%bx", "%%esi", "%%eax", "%%al")
|
||||
|
||||
"mov %2, %%"REG_a" \n\t"
|
||||
"movl %4, %%ecx \n\t"
|
||||
"add %1, %%"REG_c" \n\t"
|
||||
"movl %%ecx, (%%"REG_a") \n\t"
|
||||
|
||||
"test $1, %%edx \n\t"
|
||||
" jnz 4f \n\t"
|
||||
|
||||
"add $4, %%"REG_a" \n\t"
|
||||
"mov %%"REG_a", %2 \n\t"
|
||||
|
||||
"3: \n\t"
|
||||
"add $1, %1 \n\t"
|
||||
"cmp %5, %1 \n\t"
|
||||
" jb 2b \n\t"
|
||||
"mov %2, %%"REG_a" \n\t"
|
||||
"movl %4, %%ecx \n\t"
|
||||
"add %1, %%"REG_c" \n\t"
|
||||
"movl %%ecx, (%%"REG_a") \n\t"
|
||||
"4: \n\t"
|
||||
"add %6, %%eax \n\t"
|
||||
"shr $2, %%eax \n\t"
|
||||
|
||||
"movl %%esi, "RANGE "(%3) \n\t"
|
||||
"movl %%ebx, "LOW "(%3) \n\t"
|
||||
:"=&a"(coeff_count), "+r"(significant_coeff_ctx_base), "+m"(index)
|
||||
:"r"(c), "m"(minusstart), "m"(end), "m"(minusindex)
|
||||
: "%"REG_c, "%ebx", "%edx", "%esi", "memory"
|
||||
);
|
||||
return coeff_count;
|
||||
}
|
||||
|
||||
static int decode_significance_8x8_x86(CABACContext *c,
|
||||
uint8_t *significant_coeff_ctx_base,
|
||||
int *index, const uint8_t *sig_off){
|
||||
int minusindex= 4-(int)index;
|
||||
int coeff_count;
|
||||
x86_reg last=0;
|
||||
asm volatile(
|
||||
"movl "RANGE "(%3), %%esi \n\t"
|
||||
"movl "LOW "(%3), %%ebx \n\t"
|
||||
|
||||
"mov %1, %%"REG_D" \n\t"
|
||||
"2: \n\t"
|
||||
|
||||
"mov %6, %%"REG_a" \n\t"
|
||||
"movzbl (%%"REG_a", %%"REG_D"), %%edi \n\t"
|
||||
"add %5, %%"REG_D" \n\t"
|
||||
|
||||
BRANCHLESS_GET_CABAC("%%edx", "%3", "(%%"REG_D")", "%%ebx",
|
||||
"%%bx", "%%esi", "%%eax", "%%al")
|
||||
|
||||
"mov %1, %%edi \n\t"
|
||||
"test $1, %%edx \n\t"
|
||||
" jz 3f \n\t"
|
||||
|
||||
"movzbl "MANGLE(last_coeff_flag_offset_8x8)"(%%edi), %%edi\n\t"
|
||||
"add %5, %%"REG_D" \n\t"
|
||||
|
||||
BRANCHLESS_GET_CABAC("%%edx", "%3", "15(%%"REG_D")", "%%ebx",
|
||||
"%%bx", "%%esi", "%%eax", "%%al")
|
||||
|
||||
"mov %2, %%"REG_a" \n\t"
|
||||
"mov %1, %%edi \n\t"
|
||||
"movl %%edi, (%%"REG_a") \n\t"
|
||||
|
||||
"test $1, %%edx \n\t"
|
||||
" jnz 4f \n\t"
|
||||
|
||||
"add $4, %%"REG_a" \n\t"
|
||||
"mov %%"REG_a", %2 \n\t"
|
||||
|
||||
"3: \n\t"
|
||||
"addl $1, %%edi \n\t"
|
||||
"mov %%edi, %1 \n\t"
|
||||
"cmpl $63, %%edi \n\t"
|
||||
" jb 2b \n\t"
|
||||
"mov %2, %%"REG_a" \n\t"
|
||||
"movl %%edi, (%%"REG_a") \n\t"
|
||||
"4: \n\t"
|
||||
"addl %4, %%eax \n\t"
|
||||
"shr $2, %%eax \n\t"
|
||||
|
||||
"movl %%esi, "RANGE "(%3) \n\t"
|
||||
"movl %%ebx, "LOW "(%3) \n\t"
|
||||
:"=&a"(coeff_count),"+m"(last), "+m"(index)
|
||||
:"r"(c), "m"(minusindex), "m"(significant_coeff_ctx_base), "m"(sig_off)
|
||||
: "%"REG_c, "%ebx", "%edx", "%esi", "%"REG_D, "memory"
|
||||
);
|
||||
return coeff_count;
|
||||
}
|
||||
#endif /* defined(ARCH_X86) && defined(HAVE_7REGS) && */
|
||||
/* defined(HAVE_EBX_AVAILABLE) && !defined(BROKEN_RELOCATIONS) */
|
||||
|
||||
#endif /* FFMPEG_H264_I386_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,597 @@
|
||||
/*
|
||||
* idct_mmx.c
|
||||
* Copyright (C) 1999-2001 Aaron Holtzman <[email protected]>
|
||||
*
|
||||
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
|
||||
*
|
||||
* mpeg2dec is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpeg2dec 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with mpeg2dec; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
#include "mmx.h"
|
||||
|
||||
#define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align)))
|
||||
|
||||
#define ROW_SHIFT 11
|
||||
#define COL_SHIFT 6
|
||||
|
||||
#define round(bias) ((int)(((bias)+0.5) * (1<<ROW_SHIFT)))
|
||||
#define rounder(bias) {round (bias), round (bias)}
|
||||
|
||||
#if 0
|
||||
/* C row IDCT - it is just here to document the MMXEXT and MMX versions */
|
||||
static inline void idct_row (int16_t * row, int offset,
|
||||
int16_t * table, int32_t * rounder)
|
||||
{
|
||||
int C1, C2, C3, C4, C5, C6, C7;
|
||||
int a0, a1, a2, a3, b0, b1, b2, b3;
|
||||
|
||||
row += offset;
|
||||
|
||||
C1 = table[1];
|
||||
C2 = table[2];
|
||||
C3 = table[3];
|
||||
C4 = table[4];
|
||||
C5 = table[5];
|
||||
C6 = table[6];
|
||||
C7 = table[7];
|
||||
|
||||
a0 = C4*row[0] + C2*row[2] + C4*row[4] + C6*row[6] + *rounder;
|
||||
a1 = C4*row[0] + C6*row[2] - C4*row[4] - C2*row[6] + *rounder;
|
||||
a2 = C4*row[0] - C6*row[2] - C4*row[4] + C2*row[6] + *rounder;
|
||||
a3 = C4*row[0] - C2*row[2] + C4*row[4] - C6*row[6] + *rounder;
|
||||
|
||||
b0 = C1*row[1] + C3*row[3] + C5*row[5] + C7*row[7];
|
||||
b1 = C3*row[1] - C7*row[3] - C1*row[5] - C5*row[7];
|
||||
b2 = C5*row[1] - C1*row[3] + C7*row[5] + C3*row[7];
|
||||
b3 = C7*row[1] - C5*row[3] + C3*row[5] - C1*row[7];
|
||||
|
||||
row[0] = (a0 + b0) >> ROW_SHIFT;
|
||||
row[1] = (a1 + b1) >> ROW_SHIFT;
|
||||
row[2] = (a2 + b2) >> ROW_SHIFT;
|
||||
row[3] = (a3 + b3) >> ROW_SHIFT;
|
||||
row[4] = (a3 - b3) >> ROW_SHIFT;
|
||||
row[5] = (a2 - b2) >> ROW_SHIFT;
|
||||
row[6] = (a1 - b1) >> ROW_SHIFT;
|
||||
row[7] = (a0 - b0) >> ROW_SHIFT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* MMXEXT row IDCT */
|
||||
|
||||
#define mmxext_table(c1,c2,c3,c4,c5,c6,c7) { c4, c2, -c4, -c2, \
|
||||
c4, c6, c4, c6, \
|
||||
c1, c3, -c1, -c5, \
|
||||
c5, c7, c3, -c7, \
|
||||
c4, -c6, c4, -c6, \
|
||||
-c4, c2, c4, -c2, \
|
||||
c5, -c1, c3, -c1, \
|
||||
c7, c3, c7, -c5 }
|
||||
|
||||
static inline void mmxext_row_head (int16_t * row, int offset, const int16_t * table)
|
||||
{
|
||||
movq_m2r (*(row+offset), mm2); /* mm2 = x6 x4 x2 x0 */
|
||||
|
||||
movq_m2r (*(row+offset+4), mm5); /* mm5 = x7 x5 x3 x1 */
|
||||
movq_r2r (mm2, mm0); /* mm0 = x6 x4 x2 x0 */
|
||||
|
||||
movq_m2r (*table, mm3); /* mm3 = -C2 -C4 C2 C4 */
|
||||
movq_r2r (mm5, mm6); /* mm6 = x7 x5 x3 x1 */
|
||||
|
||||
movq_m2r (*(table+4), mm4); /* mm4 = C6 C4 C6 C4 */
|
||||
pmaddwd_r2r (mm0, mm3); /* mm3 = -C4*x4-C2*x6 C4*x0+C2*x2 */
|
||||
|
||||
pshufw_r2r (mm2, mm2, 0x4e); /* mm2 = x2 x0 x6 x4 */
|
||||
}
|
||||
|
||||
static inline void mmxext_row (const int16_t * table, const int32_t * rounder)
|
||||
{
|
||||
movq_m2r (*(table+8), mm1); /* mm1 = -C5 -C1 C3 C1 */
|
||||
pmaddwd_r2r (mm2, mm4); /* mm4 = C4*x0+C6*x2 C4*x4+C6*x6 */
|
||||
|
||||
pmaddwd_m2r (*(table+16), mm0); /* mm0 = C4*x4-C6*x6 C4*x0-C6*x2 */
|
||||
pshufw_r2r (mm6, mm6, 0x4e); /* mm6 = x3 x1 x7 x5 */
|
||||
|
||||
movq_m2r (*(table+12), mm7); /* mm7 = -C7 C3 C7 C5 */
|
||||
pmaddwd_r2r (mm5, mm1); /* mm1 = -C1*x5-C5*x7 C1*x1+C3*x3 */
|
||||
|
||||
paddd_m2r (*rounder, mm3); /* mm3 += rounder */
|
||||
pmaddwd_r2r (mm6, mm7); /* mm7 = C3*x1-C7*x3 C5*x5+C7*x7 */
|
||||
|
||||
pmaddwd_m2r (*(table+20), mm2); /* mm2 = C4*x0-C2*x2 -C4*x4+C2*x6 */
|
||||
paddd_r2r (mm4, mm3); /* mm3 = a1 a0 + rounder */
|
||||
|
||||
pmaddwd_m2r (*(table+24), mm5); /* mm5 = C3*x5-C1*x7 C5*x1-C1*x3 */
|
||||
movq_r2r (mm3, mm4); /* mm4 = a1 a0 + rounder */
|
||||
|
||||
pmaddwd_m2r (*(table+28), mm6); /* mm6 = C7*x1-C5*x3 C7*x5+C3*x7 */
|
||||
paddd_r2r (mm7, mm1); /* mm1 = b1 b0 */
|
||||
|
||||
paddd_m2r (*rounder, mm0); /* mm0 += rounder */
|
||||
psubd_r2r (mm1, mm3); /* mm3 = a1-b1 a0-b0 + rounder */
|
||||
|
||||
psrad_i2r (ROW_SHIFT, mm3); /* mm3 = y6 y7 */
|
||||
paddd_r2r (mm4, mm1); /* mm1 = a1+b1 a0+b0 + rounder */
|
||||
|
||||
paddd_r2r (mm2, mm0); /* mm0 = a3 a2 + rounder */
|
||||
psrad_i2r (ROW_SHIFT, mm1); /* mm1 = y1 y0 */
|
||||
|
||||
paddd_r2r (mm6, mm5); /* mm5 = b3 b2 */
|
||||
movq_r2r (mm0, mm4); /* mm4 = a3 a2 + rounder */
|
||||
|
||||
paddd_r2r (mm5, mm0); /* mm0 = a3+b3 a2+b2 + rounder */
|
||||
psubd_r2r (mm5, mm4); /* mm4 = a3-b3 a2-b2 + rounder */
|
||||
}
|
||||
|
||||
static inline void mmxext_row_tail (int16_t * row, int store)
|
||||
{
|
||||
psrad_i2r (ROW_SHIFT, mm0); /* mm0 = y3 y2 */
|
||||
|
||||
psrad_i2r (ROW_SHIFT, mm4); /* mm4 = y4 y5 */
|
||||
|
||||
packssdw_r2r (mm0, mm1); /* mm1 = y3 y2 y1 y0 */
|
||||
|
||||
packssdw_r2r (mm3, mm4); /* mm4 = y6 y7 y4 y5 */
|
||||
|
||||
movq_r2m (mm1, *(row+store)); /* save y3 y2 y1 y0 */
|
||||
pshufw_r2r (mm4, mm4, 0xb1); /* mm4 = y7 y6 y5 y4 */
|
||||
|
||||
/* slot */
|
||||
|
||||
movq_r2m (mm4, *(row+store+4)); /* save y7 y6 y5 y4 */
|
||||
}
|
||||
|
||||
static inline void mmxext_row_mid (int16_t * row, int store,
|
||||
int offset, const int16_t * table)
|
||||
{
|
||||
movq_m2r (*(row+offset), mm2); /* mm2 = x6 x4 x2 x0 */
|
||||
psrad_i2r (ROW_SHIFT, mm0); /* mm0 = y3 y2 */
|
||||
|
||||
movq_m2r (*(row+offset+4), mm5); /* mm5 = x7 x5 x3 x1 */
|
||||
psrad_i2r (ROW_SHIFT, mm4); /* mm4 = y4 y5 */
|
||||
|
||||
packssdw_r2r (mm0, mm1); /* mm1 = y3 y2 y1 y0 */
|
||||
movq_r2r (mm5, mm6); /* mm6 = x7 x5 x3 x1 */
|
||||
|
||||
packssdw_r2r (mm3, mm4); /* mm4 = y6 y7 y4 y5 */
|
||||
movq_r2r (mm2, mm0); /* mm0 = x6 x4 x2 x0 */
|
||||
|
||||
movq_r2m (mm1, *(row+store)); /* save y3 y2 y1 y0 */
|
||||
pshufw_r2r (mm4, mm4, 0xb1); /* mm4 = y7 y6 y5 y4 */
|
||||
|
||||
movq_m2r (*table, mm3); /* mm3 = -C2 -C4 C2 C4 */
|
||||
movq_r2m (mm4, *(row+store+4)); /* save y7 y6 y5 y4 */
|
||||
|
||||
pmaddwd_r2r (mm0, mm3); /* mm3 = -C4*x4-C2*x6 C4*x0+C2*x2 */
|
||||
|
||||
movq_m2r (*(table+4), mm4); /* mm4 = C6 C4 C6 C4 */
|
||||
pshufw_r2r (mm2, mm2, 0x4e); /* mm2 = x2 x0 x6 x4 */
|
||||
}
|
||||
|
||||
|
||||
/* MMX row IDCT */
|
||||
|
||||
#define mmx_table(c1,c2,c3,c4,c5,c6,c7) { c4, c2, c4, c6, \
|
||||
c4, c6, -c4, -c2, \
|
||||
c1, c3, c3, -c7, \
|
||||
c5, c7, -c1, -c5, \
|
||||
c4, -c6, c4, -c2, \
|
||||
-c4, c2, c4, -c6, \
|
||||
c5, -c1, c7, -c5, \
|
||||
c7, c3, c3, -c1 }
|
||||
|
||||
static inline void mmx_row_head (int16_t * row, int offset, const int16_t * table)
|
||||
{
|
||||
movq_m2r (*(row+offset), mm2); /* mm2 = x6 x4 x2 x0 */
|
||||
|
||||
movq_m2r (*(row+offset+4), mm5); /* mm5 = x7 x5 x3 x1 */
|
||||
movq_r2r (mm2, mm0); /* mm0 = x6 x4 x2 x0 */
|
||||
|
||||
movq_m2r (*table, mm3); /* mm3 = C6 C4 C2 C4 */
|
||||
movq_r2r (mm5, mm6); /* mm6 = x7 x5 x3 x1 */
|
||||
|
||||
punpckldq_r2r (mm0, mm0); /* mm0 = x2 x0 x2 x0 */
|
||||
|
||||
movq_m2r (*(table+4), mm4); /* mm4 = -C2 -C4 C6 C4 */
|
||||
pmaddwd_r2r (mm0, mm3); /* mm3 = C4*x0+C6*x2 C4*x0+C2*x2 */
|
||||
|
||||
movq_m2r (*(table+8), mm1); /* mm1 = -C7 C3 C3 C1 */
|
||||
punpckhdq_r2r (mm2, mm2); /* mm2 = x6 x4 x6 x4 */
|
||||
}
|
||||
|
||||
static inline void mmx_row (const int16_t * table, const int32_t * rounder)
|
||||
{
|
||||
pmaddwd_r2r (mm2, mm4); /* mm4 = -C4*x4-C2*x6 C4*x4+C6*x6 */
|
||||
punpckldq_r2r (mm5, mm5); /* mm5 = x3 x1 x3 x1 */
|
||||
|
||||
pmaddwd_m2r (*(table+16), mm0); /* mm0 = C4*x0-C2*x2 C4*x0-C6*x2 */
|
||||
punpckhdq_r2r (mm6, mm6); /* mm6 = x7 x5 x7 x5 */
|
||||
|
||||
movq_m2r (*(table+12), mm7); /* mm7 = -C5 -C1 C7 C5 */
|
||||
pmaddwd_r2r (mm5, mm1); /* mm1 = C3*x1-C7*x3 C1*x1+C3*x3 */
|
||||
|
||||
paddd_m2r (*rounder, mm3); /* mm3 += rounder */
|
||||
pmaddwd_r2r (mm6, mm7); /* mm7 = -C1*x5-C5*x7 C5*x5+C7*x7 */
|
||||
|
||||
pmaddwd_m2r (*(table+20), mm2); /* mm2 = C4*x4-C6*x6 -C4*x4+C2*x6 */
|
||||
paddd_r2r (mm4, mm3); /* mm3 = a1 a0 + rounder */
|
||||
|
||||
pmaddwd_m2r (*(table+24), mm5); /* mm5 = C7*x1-C5*x3 C5*x1-C1*x3 */
|
||||
movq_r2r (mm3, mm4); /* mm4 = a1 a0 + rounder */
|
||||
|
||||
pmaddwd_m2r (*(table+28), mm6); /* mm6 = C3*x5-C1*x7 C7*x5+C3*x7 */
|
||||
paddd_r2r (mm7, mm1); /* mm1 = b1 b0 */
|
||||
|
||||
paddd_m2r (*rounder, mm0); /* mm0 += rounder */
|
||||
psubd_r2r (mm1, mm3); /* mm3 = a1-b1 a0-b0 + rounder */
|
||||
|
||||
psrad_i2r (ROW_SHIFT, mm3); /* mm3 = y6 y7 */
|
||||
paddd_r2r (mm4, mm1); /* mm1 = a1+b1 a0+b0 + rounder */
|
||||
|
||||
paddd_r2r (mm2, mm0); /* mm0 = a3 a2 + rounder */
|
||||
psrad_i2r (ROW_SHIFT, mm1); /* mm1 = y1 y0 */
|
||||
|
||||
paddd_r2r (mm6, mm5); /* mm5 = b3 b2 */
|
||||
movq_r2r (mm0, mm7); /* mm7 = a3 a2 + rounder */
|
||||
|
||||
paddd_r2r (mm5, mm0); /* mm0 = a3+b3 a2+b2 + rounder */
|
||||
psubd_r2r (mm5, mm7); /* mm7 = a3-b3 a2-b2 + rounder */
|
||||
}
|
||||
|
||||
static inline void mmx_row_tail (int16_t * row, int store)
|
||||
{
|
||||
psrad_i2r (ROW_SHIFT, mm0); /* mm0 = y3 y2 */
|
||||
|
||||
psrad_i2r (ROW_SHIFT, mm7); /* mm7 = y4 y5 */
|
||||
|
||||
packssdw_r2r (mm0, mm1); /* mm1 = y3 y2 y1 y0 */
|
||||
|
||||
packssdw_r2r (mm3, mm7); /* mm7 = y6 y7 y4 y5 */
|
||||
|
||||
movq_r2m (mm1, *(row+store)); /* save y3 y2 y1 y0 */
|
||||
movq_r2r (mm7, mm4); /* mm4 = y6 y7 y4 y5 */
|
||||
|
||||
pslld_i2r (16, mm7); /* mm7 = y7 0 y5 0 */
|
||||
|
||||
psrld_i2r (16, mm4); /* mm4 = 0 y6 0 y4 */
|
||||
|
||||
por_r2r (mm4, mm7); /* mm7 = y7 y6 y5 y4 */
|
||||
|
||||
/* slot */
|
||||
|
||||
movq_r2m (mm7, *(row+store+4)); /* save y7 y6 y5 y4 */
|
||||
}
|
||||
|
||||
static inline void mmx_row_mid (int16_t * row, int store,
|
||||
int offset, const int16_t * table)
|
||||
{
|
||||
movq_m2r (*(row+offset), mm2); /* mm2 = x6 x4 x2 x0 */
|
||||
psrad_i2r (ROW_SHIFT, mm0); /* mm0 = y3 y2 */
|
||||
|
||||
movq_m2r (*(row+offset+4), mm5); /* mm5 = x7 x5 x3 x1 */
|
||||
psrad_i2r (ROW_SHIFT, mm7); /* mm7 = y4 y5 */
|
||||
|
||||
packssdw_r2r (mm0, mm1); /* mm1 = y3 y2 y1 y0 */
|
||||
movq_r2r (mm5, mm6); /* mm6 = x7 x5 x3 x1 */
|
||||
|
||||
packssdw_r2r (mm3, mm7); /* mm7 = y6 y7 y4 y5 */
|
||||
movq_r2r (mm2, mm0); /* mm0 = x6 x4 x2 x0 */
|
||||
|
||||
movq_r2m (mm1, *(row+store)); /* save y3 y2 y1 y0 */
|
||||
movq_r2r (mm7, mm1); /* mm1 = y6 y7 y4 y5 */
|
||||
|
||||
punpckldq_r2r (mm0, mm0); /* mm0 = x2 x0 x2 x0 */
|
||||
psrld_i2r (16, mm7); /* mm7 = 0 y6 0 y4 */
|
||||
|
||||
movq_m2r (*table, mm3); /* mm3 = C6 C4 C2 C4 */
|
||||
pslld_i2r (16, mm1); /* mm1 = y7 0 y5 0 */
|
||||
|
||||
movq_m2r (*(table+4), mm4); /* mm4 = -C2 -C4 C6 C4 */
|
||||
por_r2r (mm1, mm7); /* mm7 = y7 y6 y5 y4 */
|
||||
|
||||
movq_m2r (*(table+8), mm1); /* mm1 = -C7 C3 C3 C1 */
|
||||
punpckhdq_r2r (mm2, mm2); /* mm2 = x6 x4 x6 x4 */
|
||||
|
||||
movq_r2m (mm7, *(row+store+4)); /* save y7 y6 y5 y4 */
|
||||
pmaddwd_r2r (mm0, mm3); /* mm3 = C4*x0+C6*x2 C4*x0+C2*x2 */
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* C column IDCT - it is just here to document the MMXEXT and MMX versions */
|
||||
static inline void idct_col (int16_t * col, int offset)
|
||||
{
|
||||
/* multiplication - as implemented on mmx */
|
||||
#define F(c,x) (((c) * (x)) >> 16)
|
||||
|
||||
/* saturation - it helps us handle torture test cases */
|
||||
#define S(x) (((x)>32767) ? 32767 : ((x)<-32768) ? -32768 : (x))
|
||||
|
||||
int16_t x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
int16_t y0, y1, y2, y3, y4, y5, y6, y7;
|
||||
int16_t a0, a1, a2, a3, b0, b1, b2, b3;
|
||||
int16_t u04, v04, u26, v26, u17, v17, u35, v35, u12, v12;
|
||||
|
||||
col += offset;
|
||||
|
||||
x0 = col[0*8];
|
||||
x1 = col[1*8];
|
||||
x2 = col[2*8];
|
||||
x3 = col[3*8];
|
||||
x4 = col[4*8];
|
||||
x5 = col[5*8];
|
||||
x6 = col[6*8];
|
||||
x7 = col[7*8];
|
||||
|
||||
u04 = S (x0 + x4);
|
||||
v04 = S (x0 - x4);
|
||||
u26 = S (F (T2, x6) + x2);
|
||||
v26 = S (F (T2, x2) - x6);
|
||||
|
||||
a0 = S (u04 + u26);
|
||||
a1 = S (v04 + v26);
|
||||
a2 = S (v04 - v26);
|
||||
a3 = S (u04 - u26);
|
||||
|
||||
u17 = S (F (T1, x7) + x1);
|
||||
v17 = S (F (T1, x1) - x7);
|
||||
u35 = S (F (T3, x5) + x3);
|
||||
v35 = S (F (T3, x3) - x5);
|
||||
|
||||
b0 = S (u17 + u35);
|
||||
b3 = S (v17 - v35);
|
||||
u12 = S (u17 - u35);
|
||||
v12 = S (v17 + v35);
|
||||
u12 = S (2 * F (C4, u12));
|
||||
v12 = S (2 * F (C4, v12));
|
||||
b1 = S (u12 + v12);
|
||||
b2 = S (u12 - v12);
|
||||
|
||||
y0 = S (a0 + b0) >> COL_SHIFT;
|
||||
y1 = S (a1 + b1) >> COL_SHIFT;
|
||||
y2 = S (a2 + b2) >> COL_SHIFT;
|
||||
y3 = S (a3 + b3) >> COL_SHIFT;
|
||||
|
||||
y4 = S (a3 - b3) >> COL_SHIFT;
|
||||
y5 = S (a2 - b2) >> COL_SHIFT;
|
||||
y6 = S (a1 - b1) >> COL_SHIFT;
|
||||
y7 = S (a0 - b0) >> COL_SHIFT;
|
||||
|
||||
col[0*8] = y0;
|
||||
col[1*8] = y1;
|
||||
col[2*8] = y2;
|
||||
col[3*8] = y3;
|
||||
col[4*8] = y4;
|
||||
col[5*8] = y5;
|
||||
col[6*8] = y6;
|
||||
col[7*8] = y7;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* MMX column IDCT */
|
||||
static inline void idct_col (int16_t * col, int offset)
|
||||
{
|
||||
#define T1 13036
|
||||
#define T2 27146
|
||||
#define T3 43790
|
||||
#define C4 23170
|
||||
|
||||
static const short t1_vector[] ATTR_ALIGN(8) = {T1,T1,T1,T1};
|
||||
static const short t2_vector[] ATTR_ALIGN(8) = {T2,T2,T2,T2};
|
||||
static const short t3_vector[] ATTR_ALIGN(8) = {T3,T3,T3,T3};
|
||||
static const short c4_vector[] ATTR_ALIGN(8) = {C4,C4,C4,C4};
|
||||
|
||||
/* column code adapted from Peter Gubanov */
|
||||
/* http://www.elecard.com/peter/idct.shtml */
|
||||
|
||||
movq_m2r (*t1_vector, mm0); /* mm0 = T1 */
|
||||
|
||||
movq_m2r (*(col+offset+1*8), mm1); /* mm1 = x1 */
|
||||
movq_r2r (mm0, mm2); /* mm2 = T1 */
|
||||
|
||||
movq_m2r (*(col+offset+7*8), mm4); /* mm4 = x7 */
|
||||
pmulhw_r2r (mm1, mm0); /* mm0 = T1*x1 */
|
||||
|
||||
movq_m2r (*t3_vector, mm5); /* mm5 = T3 */
|
||||
pmulhw_r2r (mm4, mm2); /* mm2 = T1*x7 */
|
||||
|
||||
movq_m2r (*(col+offset+5*8), mm6); /* mm6 = x5 */
|
||||
movq_r2r (mm5, mm7); /* mm7 = T3-1 */
|
||||
|
||||
movq_m2r (*(col+offset+3*8), mm3); /* mm3 = x3 */
|
||||
psubsw_r2r (mm4, mm0); /* mm0 = v17 */
|
||||
|
||||
movq_m2r (*t2_vector, mm4); /* mm4 = T2 */
|
||||
pmulhw_r2r (mm3, mm5); /* mm5 = (T3-1)*x3 */
|
||||
|
||||
paddsw_r2r (mm2, mm1); /* mm1 = u17 */
|
||||
pmulhw_r2r (mm6, mm7); /* mm7 = (T3-1)*x5 */
|
||||
|
||||
/* slot */
|
||||
|
||||
movq_r2r (mm4, mm2); /* mm2 = T2 */
|
||||
paddsw_r2r (mm3, mm5); /* mm5 = T3*x3 */
|
||||
|
||||
pmulhw_m2r (*(col+offset+2*8), mm4);/* mm4 = T2*x2 */
|
||||
paddsw_r2r (mm6, mm7); /* mm7 = T3*x5 */
|
||||
|
||||
psubsw_r2r (mm6, mm5); /* mm5 = v35 */
|
||||
paddsw_r2r (mm3, mm7); /* mm7 = u35 */
|
||||
|
||||
movq_m2r (*(col+offset+6*8), mm3); /* mm3 = x6 */
|
||||
movq_r2r (mm0, mm6); /* mm6 = v17 */
|
||||
|
||||
pmulhw_r2r (mm3, mm2); /* mm2 = T2*x6 */
|
||||
psubsw_r2r (mm5, mm0); /* mm0 = b3 */
|
||||
|
||||
psubsw_r2r (mm3, mm4); /* mm4 = v26 */
|
||||
paddsw_r2r (mm6, mm5); /* mm5 = v12 */
|
||||
|
||||
movq_r2m (mm0, *(col+offset+3*8)); /* save b3 in scratch0 */
|
||||
movq_r2r (mm1, mm6); /* mm6 = u17 */
|
||||
|
||||
paddsw_m2r (*(col+offset+2*8), mm2);/* mm2 = u26 */
|
||||
paddsw_r2r (mm7, mm6); /* mm6 = b0 */
|
||||
|
||||
psubsw_r2r (mm7, mm1); /* mm1 = u12 */
|
||||
movq_r2r (mm1, mm7); /* mm7 = u12 */
|
||||
|
||||
movq_m2r (*(col+offset+0*8), mm3); /* mm3 = x0 */
|
||||
paddsw_r2r (mm5, mm1); /* mm1 = u12+v12 */
|
||||
|
||||
movq_m2r (*c4_vector, mm0); /* mm0 = C4/2 */
|
||||
psubsw_r2r (mm5, mm7); /* mm7 = u12-v12 */
|
||||
|
||||
movq_r2m (mm6, *(col+offset+5*8)); /* save b0 in scratch1 */
|
||||
pmulhw_r2r (mm0, mm1); /* mm1 = b1/2 */
|
||||
|
||||
movq_r2r (mm4, mm6); /* mm6 = v26 */
|
||||
pmulhw_r2r (mm0, mm7); /* mm7 = b2/2 */
|
||||
|
||||
movq_m2r (*(col+offset+4*8), mm5); /* mm5 = x4 */
|
||||
movq_r2r (mm3, mm0); /* mm0 = x0 */
|
||||
|
||||
psubsw_r2r (mm5, mm3); /* mm3 = v04 */
|
||||
paddsw_r2r (mm5, mm0); /* mm0 = u04 */
|
||||
|
||||
paddsw_r2r (mm3, mm4); /* mm4 = a1 */
|
||||
movq_r2r (mm0, mm5); /* mm5 = u04 */
|
||||
|
||||
psubsw_r2r (mm6, mm3); /* mm3 = a2 */
|
||||
paddsw_r2r (mm2, mm5); /* mm5 = a0 */
|
||||
|
||||
paddsw_r2r (mm1, mm1); /* mm1 = b1 */
|
||||
psubsw_r2r (mm2, mm0); /* mm0 = a3 */
|
||||
|
||||
paddsw_r2r (mm7, mm7); /* mm7 = b2 */
|
||||
movq_r2r (mm3, mm2); /* mm2 = a2 */
|
||||
|
||||
movq_r2r (mm4, mm6); /* mm6 = a1 */
|
||||
paddsw_r2r (mm7, mm3); /* mm3 = a2+b2 */
|
||||
|
||||
psraw_i2r (COL_SHIFT, mm3); /* mm3 = y2 */
|
||||
paddsw_r2r (mm1, mm4); /* mm4 = a1+b1 */
|
||||
|
||||
psraw_i2r (COL_SHIFT, mm4); /* mm4 = y1 */
|
||||
psubsw_r2r (mm1, mm6); /* mm6 = a1-b1 */
|
||||
|
||||
movq_m2r (*(col+offset+5*8), mm1); /* mm1 = b0 */
|
||||
psubsw_r2r (mm7, mm2); /* mm2 = a2-b2 */
|
||||
|
||||
psraw_i2r (COL_SHIFT, mm6); /* mm6 = y6 */
|
||||
movq_r2r (mm5, mm7); /* mm7 = a0 */
|
||||
|
||||
movq_r2m (mm4, *(col+offset+1*8)); /* save y1 */
|
||||
psraw_i2r (COL_SHIFT, mm2); /* mm2 = y5 */
|
||||
|
||||
movq_r2m (mm3, *(col+offset+2*8)); /* save y2 */
|
||||
paddsw_r2r (mm1, mm5); /* mm5 = a0+b0 */
|
||||
|
||||
movq_m2r (*(col+offset+3*8), mm4); /* mm4 = b3 */
|
||||
psubsw_r2r (mm1, mm7); /* mm7 = a0-b0 */
|
||||
|
||||
psraw_i2r (COL_SHIFT, mm5); /* mm5 = y0 */
|
||||
movq_r2r (mm0, mm3); /* mm3 = a3 */
|
||||
|
||||
movq_r2m (mm2, *(col+offset+5*8)); /* save y5 */
|
||||
psubsw_r2r (mm4, mm3); /* mm3 = a3-b3 */
|
||||
|
||||
psraw_i2r (COL_SHIFT, mm7); /* mm7 = y7 */
|
||||
paddsw_r2r (mm0, mm4); /* mm4 = a3+b3 */
|
||||
|
||||
movq_r2m (mm5, *(col+offset+0*8)); /* save y0 */
|
||||
psraw_i2r (COL_SHIFT, mm3); /* mm3 = y4 */
|
||||
|
||||
movq_r2m (mm6, *(col+offset+6*8)); /* save y6 */
|
||||
psraw_i2r (COL_SHIFT, mm4); /* mm4 = y3 */
|
||||
|
||||
movq_r2m (mm7, *(col+offset+7*8)); /* save y7 */
|
||||
|
||||
movq_r2m (mm3, *(col+offset+4*8)); /* save y4 */
|
||||
|
||||
movq_r2m (mm4, *(col+offset+3*8)); /* save y3 */
|
||||
|
||||
#undef T1
|
||||
#undef T2
|
||||
#undef T3
|
||||
#undef C4
|
||||
}
|
||||
|
||||
static const int32_t rounder0[] ATTR_ALIGN(8) =
|
||||
rounder ((1 << (COL_SHIFT - 1)) - 0.5);
|
||||
static const int32_t rounder4[] ATTR_ALIGN(8) = rounder (0);
|
||||
static const int32_t rounder1[] ATTR_ALIGN(8) =
|
||||
rounder (1.25683487303); /* C1*(C1/C4+C1+C7)/2 */
|
||||
static const int32_t rounder7[] ATTR_ALIGN(8) =
|
||||
rounder (-0.25); /* C1*(C7/C4+C7-C1)/2 */
|
||||
static const int32_t rounder2[] ATTR_ALIGN(8) =
|
||||
rounder (0.60355339059); /* C2 * (C6+C2)/2 */
|
||||
static const int32_t rounder6[] ATTR_ALIGN(8) =
|
||||
rounder (-0.25); /* C2 * (C6-C2)/2 */
|
||||
static const int32_t rounder3[] ATTR_ALIGN(8) =
|
||||
rounder (0.087788325588); /* C3*(-C3/C4+C3+C5)/2 */
|
||||
static const int32_t rounder5[] ATTR_ALIGN(8) =
|
||||
rounder (-0.441341716183); /* C3*(-C5/C4+C5-C3)/2 */
|
||||
|
||||
#undef COL_SHIFT
|
||||
#undef ROW_SHIFT
|
||||
|
||||
#define declare_idct(idct,table,idct_row_head,idct_row,idct_row_tail,idct_row_mid) \
|
||||
void idct (int16_t * block) \
|
||||
{ \
|
||||
static const int16_t table04[] ATTR_ALIGN(16) = \
|
||||
table (22725, 21407, 19266, 16384, 12873, 8867, 4520); \
|
||||
static const int16_t table17[] ATTR_ALIGN(16) = \
|
||||
table (31521, 29692, 26722, 22725, 17855, 12299, 6270); \
|
||||
static const int16_t table26[] ATTR_ALIGN(16) = \
|
||||
table (29692, 27969, 25172, 21407, 16819, 11585, 5906); \
|
||||
static const int16_t table35[] ATTR_ALIGN(16) = \
|
||||
table (26722, 25172, 22654, 19266, 15137, 10426, 5315); \
|
||||
\
|
||||
idct_row_head (block, 0*8, table04); \
|
||||
idct_row (table04, rounder0); \
|
||||
idct_row_mid (block, 0*8, 4*8, table04); \
|
||||
idct_row (table04, rounder4); \
|
||||
idct_row_mid (block, 4*8, 1*8, table17); \
|
||||
idct_row (table17, rounder1); \
|
||||
idct_row_mid (block, 1*8, 7*8, table17); \
|
||||
idct_row (table17, rounder7); \
|
||||
idct_row_mid (block, 7*8, 2*8, table26); \
|
||||
idct_row (table26, rounder2); \
|
||||
idct_row_mid (block, 2*8, 6*8, table26); \
|
||||
idct_row (table26, rounder6); \
|
||||
idct_row_mid (block, 6*8, 3*8, table35); \
|
||||
idct_row (table35, rounder3); \
|
||||
idct_row_mid (block, 3*8, 5*8, table35); \
|
||||
idct_row (table35, rounder5); \
|
||||
idct_row_tail (block, 5*8); \
|
||||
\
|
||||
idct_col (block, 0); \
|
||||
idct_col (block, 4); \
|
||||
}
|
||||
|
||||
void ff_mmx_idct(DCTELEM *block);
|
||||
void ff_mmxext_idct(DCTELEM *block);
|
||||
|
||||
declare_idct (ff_mmxext_idct, mmxext_table,
|
||||
mmxext_row_head, mmxext_row, mmxext_row_tail, mmxext_row_mid)
|
||||
|
||||
declare_idct (ff_mmx_idct, mmx_table,
|
||||
mmx_row_head, mmx_row, mmx_row_tail, mmx_row_mid)
|
||||
|
||||
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* XVID MPEG-4 VIDEO CODEC
|
||||
* - MMX and XMM forward discrete cosine transform -
|
||||
*
|
||||
* Copyright(C) 2001 Peter Ross <[email protected]>
|
||||
*
|
||||
* Originally provided by Intel at AP-922
|
||||
* http://developer.intel.com/vtune/cbts/strmsimd/922down.htm
|
||||
* (See more app notes at http://developer.intel.com/vtune/cbts/strmsimd/appnotes.htm)
|
||||
* but in a limited edition.
|
||||
* New macro implements a column part for precise iDCT
|
||||
* The routine precision now satisfies IEEE standard 1180-1990.
|
||||
*
|
||||
* Copyright(C) 2000-2001 Peter Gubanov <[email protected]>
|
||||
* Rounding trick Copyright(C) 2000 Michel Lespinasse <[email protected]>
|
||||
*
|
||||
* http://www.elecard.com/peter/idct.html
|
||||
* http://www.linuxvideo.org/mpeg2dec/
|
||||
*
|
||||
* These examples contain code fragments for first stage iDCT 8x8
|
||||
* (for rows) and first stage DCT 8x8 (for columns)
|
||||
*
|
||||
* conversion to gcc syntax by Michael Niedermayer
|
||||
*
|
||||
* 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 <inttypes.h>
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
//=============================================================================
|
||||
// Macros and other preprocessor constants
|
||||
//=============================================================================
|
||||
|
||||
#define BITS_INV_ACC 5 // 4 or 5 for IEEE
|
||||
#define SHIFT_INV_ROW (16 - BITS_INV_ACC) //11
|
||||
#define SHIFT_INV_COL (1 + BITS_INV_ACC) //6
|
||||
#define RND_INV_ROW (1024 * (6 - BITS_INV_ACC))
|
||||
#define RND_INV_COL (16 * (BITS_INV_ACC - 3))
|
||||
#define RND_INV_CORR (RND_INV_COL - 1)
|
||||
|
||||
#define BITS_FRW_ACC 3 // 2 or 3 for accuracy
|
||||
#define SHIFT_FRW_COL BITS_FRW_ACC
|
||||
#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17)
|
||||
#define RND_FRW_ROW (262144*(BITS_FRW_ACC - 1))
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Various memory constants (trigonometric values or rounding values)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
DECLARE_ALIGNED(8, static const int16_t, tg_1_16[4*4]) = {
|
||||
13036,13036,13036,13036, // tg * (2<<16) + 0.5
|
||||
27146,27146,27146,27146, // tg * (2<<16) + 0.5
|
||||
-21746,-21746,-21746,-21746, // tg * (2<<16) + 0.5
|
||||
23170,23170,23170,23170}; // cos * (2<<15) + 0.5
|
||||
|
||||
DECLARE_ALIGNED(8, static const int32_t, rounder_0[2*8]) = {
|
||||
65536,65536,
|
||||
3597,3597,
|
||||
2260,2260,
|
||||
1203,1203,
|
||||
0,0,
|
||||
120,120,
|
||||
512,512,
|
||||
512,512};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// The first stage iDCT 8x8 - inverse DCTs of rows
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// The 8-point inverse DCT direct algorithm
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// static const short w[32] = {
|
||||
// FIX(cos_4_16), FIX(cos_2_16), FIX(cos_4_16), FIX(cos_6_16),
|
||||
// FIX(cos_4_16), FIX(cos_6_16), -FIX(cos_4_16), -FIX(cos_2_16),
|
||||
// FIX(cos_4_16), -FIX(cos_6_16), -FIX(cos_4_16), FIX(cos_2_16),
|
||||
// FIX(cos_4_16), -FIX(cos_2_16), FIX(cos_4_16), -FIX(cos_6_16),
|
||||
// FIX(cos_1_16), FIX(cos_3_16), FIX(cos_5_16), FIX(cos_7_16),
|
||||
// FIX(cos_3_16), -FIX(cos_7_16), -FIX(cos_1_16), -FIX(cos_5_16),
|
||||
// FIX(cos_5_16), -FIX(cos_1_16), FIX(cos_7_16), FIX(cos_3_16),
|
||||
// FIX(cos_7_16), -FIX(cos_5_16), FIX(cos_3_16), -FIX(cos_1_16) };
|
||||
//
|
||||
// #define DCT_8_INV_ROW(x, y)
|
||||
// {
|
||||
// int a0, a1, a2, a3, b0, b1, b2, b3;
|
||||
//
|
||||
// a0 =x[0]*w[0]+x[2]*w[1]+x[4]*w[2]+x[6]*w[3];
|
||||
// a1 =x[0]*w[4]+x[2]*w[5]+x[4]*w[6]+x[6]*w[7];
|
||||
// a2 = x[0] * w[ 8] + x[2] * w[ 9] + x[4] * w[10] + x[6] * w[11];
|
||||
// a3 = x[0] * w[12] + x[2] * w[13] + x[4] * w[14] + x[6] * w[15];
|
||||
// b0 = x[1] * w[16] + x[3] * w[17] + x[5] * w[18] + x[7] * w[19];
|
||||
// b1 = x[1] * w[20] + x[3] * w[21] + x[5] * w[22] + x[7] * w[23];
|
||||
// b2 = x[1] * w[24] + x[3] * w[25] + x[5] * w[26] + x[7] * w[27];
|
||||
// b3 = x[1] * w[28] + x[3] * w[29] + x[5] * w[30] + x[7] * w[31];
|
||||
//
|
||||
// y[0] = SHIFT_ROUND ( a0 + b0 );
|
||||
// y[1] = SHIFT_ROUND ( a1 + b1 );
|
||||
// y[2] = SHIFT_ROUND ( a2 + b2 );
|
||||
// y[3] = SHIFT_ROUND ( a3 + b3 );
|
||||
// y[4] = SHIFT_ROUND ( a3 - b3 );
|
||||
// y[5] = SHIFT_ROUND ( a2 - b2 );
|
||||
// y[6] = SHIFT_ROUND ( a1 - b1 );
|
||||
// y[7] = SHIFT_ROUND ( a0 - b0 );
|
||||
// }
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// In this implementation the outputs of the iDCT-1D are multiplied
|
||||
// for rows 0,4 - by cos_4_16,
|
||||
// for rows 1,7 - by cos_1_16,
|
||||
// for rows 2,6 - by cos_2_16,
|
||||
// for rows 3,5 - by cos_3_16
|
||||
// and are shifted to the left for better accuracy
|
||||
//
|
||||
// For the constants used,
|
||||
// FIX(float_const) = (short) (float_const * (1<<15) + 0.5)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tables for mmx processors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Table for rows 0,4 - constants are multiplied by cos_4_16
|
||||
DECLARE_ALIGNED(8, static const int16_t, tab_i_04_mmx[32*4]) = {
|
||||
16384,16384,16384,-16384, // movq-> w06 w04 w02 w00
|
||||
21407,8867,8867,-21407, // w07 w05 w03 w01
|
||||
16384,-16384,16384,16384, // w14 w12 w10 w08
|
||||
-8867,21407,-21407,-8867, // w15 w13 w11 w09
|
||||
22725,12873,19266,-22725, // w22 w20 w18 w16
|
||||
19266,4520,-4520,-12873, // w23 w21 w19 w17
|
||||
12873,4520,4520,19266, // w30 w28 w26 w24
|
||||
-22725,19266,-12873,-22725, // w31 w29 w27 w25
|
||||
// Table for rows 1,7 - constants are multiplied by cos_1_16
|
||||
22725,22725,22725,-22725, // movq-> w06 w04 w02 w00
|
||||
29692,12299,12299,-29692, // w07 w05 w03 w01
|
||||
22725,-22725,22725,22725, // w14 w12 w10 w08
|
||||
-12299,29692,-29692,-12299, // w15 w13 w11 w09
|
||||
31521,17855,26722,-31521, // w22 w20 w18 w16
|
||||
26722,6270,-6270,-17855, // w23 w21 w19 w17
|
||||
17855,6270,6270,26722, // w30 w28 w26 w24
|
||||
-31521,26722,-17855,-31521, // w31 w29 w27 w25
|
||||
// Table for rows 2,6 - constants are multiplied by cos_2_16
|
||||
21407,21407,21407,-21407, // movq-> w06 w04 w02 w00
|
||||
27969,11585,11585,-27969, // w07 w05 w03 w01
|
||||
21407,-21407,21407,21407, // w14 w12 w10 w08
|
||||
-11585,27969,-27969,-11585, // w15 w13 w11 w09
|
||||
29692,16819,25172,-29692, // w22 w20 w18 w16
|
||||
25172,5906,-5906,-16819, // w23 w21 w19 w17
|
||||
16819,5906,5906,25172, // w30 w28 w26 w24
|
||||
-29692,25172,-16819,-29692, // w31 w29 w27 w25
|
||||
// Table for rows 3,5 - constants are multiplied by cos_3_16
|
||||
19266,19266,19266,-19266, // movq-> w06 w04 w02 w00
|
||||
25172,10426,10426,-25172, // w07 w05 w03 w01
|
||||
19266,-19266,19266,19266, // w14 w12 w10 w08
|
||||
-10426,25172,-25172,-10426, // w15 w13 w11 w09
|
||||
26722,15137,22654,-26722, // w22 w20 w18 w16
|
||||
22654,5315,-5315,-15137, // w23 w21 w19 w17
|
||||
15137,5315,5315,22654, // w30 w28 w26 w24
|
||||
-26722,22654,-15137,-26722, // w31 w29 w27 w25
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tables for xmm processors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// %3 for rows 0,4 - constants are multiplied by cos_4_16
|
||||
DECLARE_ALIGNED(8, static const int16_t, tab_i_04_xmm[32*4]) = {
|
||||
16384,21407,16384,8867, // movq-> w05 w04 w01 w00
|
||||
16384,8867,-16384,-21407, // w07 w06 w03 w02
|
||||
16384,-8867,16384,-21407, // w13 w12 w09 w08
|
||||
-16384,21407,16384,-8867, // w15 w14 w11 w10
|
||||
22725,19266,19266,-4520, // w21 w20 w17 w16
|
||||
12873,4520,-22725,-12873, // w23 w22 w19 w18
|
||||
12873,-22725,4520,-12873, // w29 w28 w25 w24
|
||||
4520,19266,19266,-22725, // w31 w30 w27 w26
|
||||
// %3 for rows 1,7 - constants are multiplied by cos_1_16
|
||||
22725,29692,22725,12299, // movq-> w05 w04 w01 w00
|
||||
22725,12299,-22725,-29692, // w07 w06 w03 w02
|
||||
22725,-12299,22725,-29692, // w13 w12 w09 w08
|
||||
-22725,29692,22725,-12299, // w15 w14 w11 w10
|
||||
31521,26722,26722,-6270, // w21 w20 w17 w16
|
||||
17855,6270,-31521,-17855, // w23 w22 w19 w18
|
||||
17855,-31521,6270,-17855, // w29 w28 w25 w24
|
||||
6270,26722,26722,-31521, // w31 w30 w27 w26
|
||||
// %3 for rows 2,6 - constants are multiplied by cos_2_16
|
||||
21407,27969,21407,11585, // movq-> w05 w04 w01 w00
|
||||
21407,11585,-21407,-27969, // w07 w06 w03 w02
|
||||
21407,-11585,21407,-27969, // w13 w12 w09 w08
|
||||
-21407,27969,21407,-11585, // w15 w14 w11 w10
|
||||
29692,25172,25172,-5906, // w21 w20 w17 w16
|
||||
16819,5906,-29692,-16819, // w23 w22 w19 w18
|
||||
16819,-29692,5906,-16819, // w29 w28 w25 w24
|
||||
5906,25172,25172,-29692, // w31 w30 w27 w26
|
||||
// %3 for rows 3,5 - constants are multiplied by cos_3_16
|
||||
19266,25172,19266,10426, // movq-> w05 w04 w01 w00
|
||||
19266,10426,-19266,-25172, // w07 w06 w03 w02
|
||||
19266,-10426,19266,-25172, // w13 w12 w09 w08
|
||||
-19266,25172,19266,-10426, // w15 w14 w11 w10
|
||||
26722,22654,22654,-5315, // w21 w20 w17 w16
|
||||
15137,5315,-26722,-15137, // w23 w22 w19 w18
|
||||
15137,-26722,5315,-15137, // w29 w28 w25 w24
|
||||
5315,22654,22654,-26722, // w31 w30 w27 w26
|
||||
};
|
||||
//=============================================================================
|
||||
// Helper macros for the code
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DCT_8_INV_ROW_MMX( INP, OUT, TABLE, ROUNDER
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DCT_8_INV_ROW_MMX(A1,A2,A3,A4)\
|
||||
"movq " #A1 ",%%mm0 \n\t"/* 0 ; x3 x2 x1 x0*/\
|
||||
"movq 8+" #A1 ",%%mm1 \n\t"/* 1 ; x7 x6 x5 x4*/\
|
||||
"movq %%mm0,%%mm2 \n\t"/* 2 ; x3 x2 x1 x0*/\
|
||||
"movq " #A3 ",%%mm3 \n\t"/* 3 ; w06 w04 w02 w00*/\
|
||||
"punpcklwd %%mm1,%%mm0 \n\t"/* x5 x1 x4 x0*/\
|
||||
"movq %%mm0,%%mm5 \n\t"/* 5 ; x5 x1 x4 x0*/\
|
||||
"punpckldq %%mm0,%%mm0 \n\t"/* x4 x0 x4 x0*/\
|
||||
"movq 8+" #A3 ",%%mm4 \n\t"/* 4 ; w07 w05 w03 w01*/\
|
||||
"punpckhwd %%mm1,%%mm2 \n\t"/* 1 ; x7 x3 x6 x2*/\
|
||||
"pmaddwd %%mm0,%%mm3 \n\t"/* x4*w06+x0*w04 x4*w02+x0*w00*/\
|
||||
"movq %%mm2,%%mm6 \n\t"/* 6 ; x7 x3 x6 x2*/\
|
||||
"movq 32+" #A3 ",%%mm1 \n\t"/* 1 ; w22 w20 w18 w16*/\
|
||||
"punpckldq %%mm2,%%mm2 \n\t"/* x6 x2 x6 x2*/\
|
||||
"pmaddwd %%mm2,%%mm4 \n\t"/* x6*w07+x2*w05 x6*w03+x2*w01*/\
|
||||
"punpckhdq %%mm5,%%mm5 \n\t"/* x5 x1 x5 x1*/\
|
||||
"pmaddwd 16+" #A3 ",%%mm0 \n\t"/* x4*w14+x0*w12 x4*w10+x0*w08*/\
|
||||
"punpckhdq %%mm6,%%mm6 \n\t"/* x7 x3 x7 x3*/\
|
||||
"movq 40+" #A3 ",%%mm7 \n\t"/* 7 ; w23 w21 w19 w17*/\
|
||||
"pmaddwd %%mm5,%%mm1 \n\t"/* x5*w22+x1*w20 x5*w18+x1*w16*/\
|
||||
"paddd " #A4 ",%%mm3 \n\t"/* +%4*/\
|
||||
"pmaddwd %%mm6,%%mm7 \n\t"/* x7*w23+x3*w21 x7*w19+x3*w17*/\
|
||||
"pmaddwd 24+" #A3 ",%%mm2 \n\t"/* x6*w15+x2*w13 x6*w11+x2*w09*/\
|
||||
"paddd %%mm4,%%mm3 \n\t"/* 4 ; a1=sum(even1) a0=sum(even0)*/\
|
||||
"pmaddwd 48+" #A3 ",%%mm5 \n\t"/* x5*w30+x1*w28 x5*w26+x1*w24*/\
|
||||
"movq %%mm3,%%mm4 \n\t"/* 4 ; a1 a0*/\
|
||||
"pmaddwd 56+" #A3 ",%%mm6 \n\t"/* x7*w31+x3*w29 x7*w27+x3*w25*/\
|
||||
"paddd %%mm7,%%mm1 \n\t"/* 7 ; b1=sum(odd1) b0=sum(odd0)*/\
|
||||
"paddd " #A4 ",%%mm0 \n\t"/* +%4*/\
|
||||
"psubd %%mm1,%%mm3 \n\t"/* a1-b1 a0-b0*/\
|
||||
"psrad $11,%%mm3 \n\t"/* y6=a1-b1 y7=a0-b0*/\
|
||||
"paddd %%mm4,%%mm1 \n\t"/* 4 ; a1+b1 a0+b0*/\
|
||||
"paddd %%mm2,%%mm0 \n\t"/* 2 ; a3=sum(even3) a2=sum(even2)*/\
|
||||
"psrad $11,%%mm1 \n\t"/* y1=a1+b1 y0=a0+b0*/\
|
||||
"paddd %%mm6,%%mm5 \n\t"/* 6 ; b3=sum(odd3) b2=sum(odd2)*/\
|
||||
"movq %%mm0,%%mm4 \n\t"/* 4 ; a3 a2*/\
|
||||
"paddd %%mm5,%%mm0 \n\t"/* a3+b3 a2+b2*/\
|
||||
"psubd %%mm5,%%mm4 \n\t"/* 5 ; a3-b3 a2-b2*/\
|
||||
"psrad $11,%%mm0 \n\t"/* y3=a3+b3 y2=a2+b2*/\
|
||||
"psrad $11,%%mm4 \n\t"/* y4=a3-b3 y5=a2-b2*/\
|
||||
"packssdw %%mm0,%%mm1 \n\t"/* 0 ; y3 y2 y1 y0*/\
|
||||
"packssdw %%mm3,%%mm4 \n\t"/* 3 ; y6 y7 y4 y5*/\
|
||||
"movq %%mm4,%%mm7 \n\t"/* 7 ; y6 y7 y4 y5*/\
|
||||
"psrld $16,%%mm4 \n\t"/* 0 y6 0 y4*/\
|
||||
"pslld $16,%%mm7 \n\t"/* y7 0 y5 0*/\
|
||||
"movq %%mm1," #A2 " \n\t"/* 1 ; save y3 y2 y1 y0*/\
|
||||
"por %%mm4,%%mm7 \n\t"/* 4 ; y7 y6 y5 y4*/\
|
||||
"movq %%mm7,8 +" #A2 "\n\t"/* 7 ; save y7 y6 y5 y4*/\
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DCT_8_INV_ROW_XMM( INP, OUT, TABLE, ROUNDER
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DCT_8_INV_ROW_XMM(A1,A2,A3,A4)\
|
||||
"movq " #A1 ",%%mm0 \n\t"/* 0 ; x3 x2 x1 x0*/\
|
||||
"movq 8+" #A1 ",%%mm1 \n\t"/* 1 ; x7 x6 x5 x4*/\
|
||||
"movq %%mm0,%%mm2 \n\t"/* 2 ; x3 x2 x1 x0*/\
|
||||
"movq " #A3 ",%%mm3 \n\t"/* 3 ; w05 w04 w01 w00*/\
|
||||
"pshufw $0x88,%%mm0,%%mm0 \n\t"/* x2 x0 x2 x0*/\
|
||||
"movq 8+" #A3 ",%%mm4 \n\t"/* 4 ; w07 w06 w03 w02*/\
|
||||
"movq %%mm1,%%mm5 \n\t"/* 5 ; x7 x6 x5 x4*/\
|
||||
"pmaddwd %%mm0,%%mm3 \n\t"/* x2*w05+x0*w04 x2*w01+x0*w00*/\
|
||||
"movq 32+" #A3 ",%%mm6 \n\t"/* 6 ; w21 w20 w17 w16*/\
|
||||
"pshufw $0x88,%%mm1,%%mm1 \n\t"/* x6 x4 x6 x4*/\
|
||||
"pmaddwd %%mm1,%%mm4 \n\t"/* x6*w07+x4*w06 x6*w03+x4*w02*/\
|
||||
"movq 40+" #A3 ",%%mm7 \n\t"/* 7 ; w23 w22 w19 w18*/\
|
||||
"pshufw $0xdd,%%mm2,%%mm2 \n\t"/* x3 x1 x3 x1*/\
|
||||
"pmaddwd %%mm2,%%mm6 \n\t"/* x3*w21+x1*w20 x3*w17+x1*w16*/\
|
||||
"pshufw $0xdd,%%mm5,%%mm5 \n\t"/* x7 x5 x7 x5*/\
|
||||
"pmaddwd %%mm5,%%mm7 \n\t"/* x7*w23+x5*w22 x7*w19+x5*w18*/\
|
||||
"paddd " #A4 ",%%mm3 \n\t"/* +%4*/\
|
||||
"pmaddwd 16+" #A3 ",%%mm0 \n\t"/* x2*w13+x0*w12 x2*w09+x0*w08*/\
|
||||
"paddd %%mm4,%%mm3 \n\t"/* 4 ; a1=sum(even1) a0=sum(even0)*/\
|
||||
"pmaddwd 24+" #A3 ",%%mm1 \n\t"/* x6*w15+x4*w14 x6*w11+x4*w10*/\
|
||||
"movq %%mm3,%%mm4 \n\t"/* 4 ; a1 a0*/\
|
||||
"pmaddwd 48+" #A3 ",%%mm2 \n\t"/* x3*w29+x1*w28 x3*w25+x1*w24*/\
|
||||
"paddd %%mm7,%%mm6 \n\t"/* 7 ; b1=sum(odd1) b0=sum(odd0)*/\
|
||||
"pmaddwd 56+" #A3 ",%%mm5 \n\t"/* x7*w31+x5*w30 x7*w27+x5*w26*/\
|
||||
"paddd %%mm6,%%mm3 \n\t"/* a1+b1 a0+b0*/\
|
||||
"paddd " #A4 ",%%mm0 \n\t"/* +%4*/\
|
||||
"psrad $11,%%mm3 \n\t"/* y1=a1+b1 y0=a0+b0*/\
|
||||
"paddd %%mm1,%%mm0 \n\t"/* 1 ; a3=sum(even3) a2=sum(even2)*/\
|
||||
"psubd %%mm6,%%mm4 \n\t"/* 6 ; a1-b1 a0-b0*/\
|
||||
"movq %%mm0,%%mm7 \n\t"/* 7 ; a3 a2*/\
|
||||
"paddd %%mm5,%%mm2 \n\t"/* 5 ; b3=sum(odd3) b2=sum(odd2)*/\
|
||||
"paddd %%mm2,%%mm0 \n\t"/* a3+b3 a2+b2*/\
|
||||
"psrad $11,%%mm4 \n\t"/* y6=a1-b1 y7=a0-b0*/\
|
||||
"psubd %%mm2,%%mm7 \n\t"/* 2 ; a3-b3 a2-b2*/\
|
||||
"psrad $11,%%mm0 \n\t"/* y3=a3+b3 y2=a2+b2*/\
|
||||
"psrad $11,%%mm7 \n\t"/* y4=a3-b3 y5=a2-b2*/\
|
||||
"packssdw %%mm0,%%mm3 \n\t"/* 0 ; y3 y2 y1 y0*/\
|
||||
"packssdw %%mm4,%%mm7 \n\t"/* 4 ; y6 y7 y4 y5*/\
|
||||
"movq %%mm3, " #A2 " \n\t"/* 3 ; save y3 y2 y1 y0*/\
|
||||
"pshufw $0xb1,%%mm7,%%mm7 \n\t"/* y7 y6 y5 y4*/\
|
||||
"movq %%mm7,8 +" #A2 "\n\t"/* 7 ; save y7 y6 y5 y4*/\
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// The first stage DCT 8x8 - forward DCTs of columns
|
||||
//
|
||||
// The %2puts are multiplied
|
||||
// for rows 0,4 - on cos_4_16,
|
||||
// for rows 1,7 - on cos_1_16,
|
||||
// for rows 2,6 - on cos_2_16,
|
||||
// for rows 3,5 - on cos_3_16
|
||||
// and are shifted to the left for rise of accuracy
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// The 8-point scaled forward DCT algorithm (26a8m)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// #define DCT_8_FRW_COL(x, y)
|
||||
//{
|
||||
// short t0, t1, t2, t3, t4, t5, t6, t7;
|
||||
// short tp03, tm03, tp12, tm12, tp65, tm65;
|
||||
// short tp465, tm465, tp765, tm765;
|
||||
//
|
||||
// t0 = LEFT_SHIFT ( x[0] + x[7] );
|
||||
// t1 = LEFT_SHIFT ( x[1] + x[6] );
|
||||
// t2 = LEFT_SHIFT ( x[2] + x[5] );
|
||||
// t3 = LEFT_SHIFT ( x[3] + x[4] );
|
||||
// t4 = LEFT_SHIFT ( x[3] - x[4] );
|
||||
// t5 = LEFT_SHIFT ( x[2] - x[5] );
|
||||
// t6 = LEFT_SHIFT ( x[1] - x[6] );
|
||||
// t7 = LEFT_SHIFT ( x[0] - x[7] );
|
||||
//
|
||||
// tp03 = t0 + t3;
|
||||
// tm03 = t0 - t3;
|
||||
// tp12 = t1 + t2;
|
||||
// tm12 = t1 - t2;
|
||||
//
|
||||
// y[0] = tp03 + tp12;
|
||||
// y[4] = tp03 - tp12;
|
||||
//
|
||||
// y[2] = tm03 + tm12 * tg_2_16;
|
||||
// y[6] = tm03 * tg_2_16 - tm12;
|
||||
//
|
||||
// tp65 =(t6 +t5 )*cos_4_16;
|
||||
// tm65 =(t6 -t5 )*cos_4_16;
|
||||
//
|
||||
// tp765 = t7 + tp65;
|
||||
// tm765 = t7 - tp65;
|
||||
// tp465 = t4 + tm65;
|
||||
// tm465 = t4 - tm65;
|
||||
//
|
||||
// y[1] = tp765 + tp465 * tg_1_16;
|
||||
// y[7] = tp765 * tg_1_16 - tp465;
|
||||
// y[5] = tm765 * tg_3_16 + tm465;
|
||||
// y[3] = tm765 - tm465 * tg_3_16;
|
||||
//}
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DCT_8_INV_COL_4 INP,OUT
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DCT_8_INV_COL(A1,A2)\
|
||||
"movq 2*8(%3),%%mm0\n\t"\
|
||||
"movq 16*3+" #A1 ",%%mm3\n\t"\
|
||||
"movq %%mm0,%%mm1 \n\t"/* tg_3_16*/\
|
||||
"movq 16*5+" #A1 ",%%mm5\n\t"\
|
||||
"pmulhw %%mm3,%%mm0 \n\t"/* x3*(tg_3_16-1)*/\
|
||||
"movq (%3),%%mm4\n\t"\
|
||||
"pmulhw %%mm5,%%mm1 \n\t"/* x5*(tg_3_16-1)*/\
|
||||
"movq 16*7+" #A1 ",%%mm7\n\t"\
|
||||
"movq %%mm4,%%mm2 \n\t"/* tg_1_16*/\
|
||||
"movq 16*1+" #A1 ",%%mm6\n\t"\
|
||||
"pmulhw %%mm7,%%mm4 \n\t"/* x7*tg_1_16*/\
|
||||
"paddsw %%mm3,%%mm0 \n\t"/* x3*tg_3_16*/\
|
||||
"pmulhw %%mm6,%%mm2 \n\t"/* x1*tg_1_16*/\
|
||||
"paddsw %%mm3,%%mm1 \n\t"/* x3+x5*(tg_3_16-1)*/\
|
||||
"psubsw %%mm5,%%mm0 \n\t"/* x3*tg_3_16-x5 = tm35*/\
|
||||
"movq 3*8(%3),%%mm3\n\t"\
|
||||
"paddsw %%mm5,%%mm1 \n\t"/* x3+x5*tg_3_16 = tp35*/\
|
||||
"paddsw %%mm6,%%mm4 \n\t"/* x1+tg_1_16*x7 = tp17*/\
|
||||
"psubsw %%mm7,%%mm2 \n\t"/* x1*tg_1_16-x7 = tm17*/\
|
||||
"movq %%mm4,%%mm5 \n\t"/* tp17*/\
|
||||
"movq %%mm2,%%mm6 \n\t"/* tm17*/\
|
||||
"paddsw %%mm1,%%mm5 \n\t"/* tp17+tp35 = b0*/\
|
||||
"psubsw %%mm0,%%mm6 \n\t"/* tm17-tm35 = b3*/\
|
||||
"psubsw %%mm1,%%mm4 \n\t"/* tp17-tp35 = t1*/\
|
||||
"paddsw %%mm0,%%mm2 \n\t"/* tm17+tm35 = t2*/\
|
||||
"movq 1*8(%3),%%mm7\n\t"\
|
||||
"movq %%mm4,%%mm1 \n\t"/* t1*/\
|
||||
"movq %%mm5,3*16 +" #A2 "\n\t"/* save b0*/\
|
||||
"paddsw %%mm2,%%mm1 \n\t"/* t1+t2*/\
|
||||
"movq %%mm6,5*16 +" #A2 "\n\t"/* save b3*/\
|
||||
"psubsw %%mm2,%%mm4 \n\t"/* t1-t2*/\
|
||||
"movq 2*16+" #A1 ",%%mm5\n\t"\
|
||||
"movq %%mm7,%%mm0 \n\t"/* tg_2_16*/\
|
||||
"movq 6*16+" #A1 ",%%mm6\n\t"\
|
||||
"pmulhw %%mm5,%%mm0 \n\t"/* x2*tg_2_16*/\
|
||||
"pmulhw %%mm6,%%mm7 \n\t"/* x6*tg_2_16*/\
|
||||
"pmulhw %%mm3,%%mm1 \n\t"/* ocos_4_16*(t1+t2) = b1/2*/\
|
||||
"movq 0*16+" #A1 ",%%mm2\n\t"\
|
||||
"pmulhw %%mm3,%%mm4 \n\t"/* ocos_4_16*(t1-t2) = b2/2*/\
|
||||
"psubsw %%mm6,%%mm0 \n\t"/* t2*tg_2_16-x6 = tm26*/\
|
||||
"movq %%mm2,%%mm3 \n\t"/* x0*/\
|
||||
"movq 4*16+" #A1 ",%%mm6\n\t"\
|
||||
"paddsw %%mm5,%%mm7 \n\t"/* x2+x6*tg_2_16 = tp26*/\
|
||||
"paddsw %%mm6,%%mm2 \n\t"/* x0+x4 = tp04*/\
|
||||
"psubsw %%mm6,%%mm3 \n\t"/* x0-x4 = tm04*/\
|
||||
"movq %%mm2,%%mm5 \n\t"/* tp04*/\
|
||||
"movq %%mm3,%%mm6 \n\t"/* tm04*/\
|
||||
"psubsw %%mm7,%%mm2 \n\t"/* tp04-tp26 = a3*/\
|
||||
"paddsw %%mm0,%%mm3 \n\t"/* tm04+tm26 = a1*/\
|
||||
"paddsw %%mm1,%%mm1 \n\t"/* b1*/\
|
||||
"paddsw %%mm4,%%mm4 \n\t"/* b2*/\
|
||||
"paddsw %%mm7,%%mm5 \n\t"/* tp04+tp26 = a0*/\
|
||||
"psubsw %%mm0,%%mm6 \n\t"/* tm04-tm26 = a2*/\
|
||||
"movq %%mm3,%%mm7 \n\t"/* a1*/\
|
||||
"movq %%mm6,%%mm0 \n\t"/* a2*/\
|
||||
"paddsw %%mm1,%%mm3 \n\t"/* a1+b1*/\
|
||||
"paddsw %%mm4,%%mm6 \n\t"/* a2+b2*/\
|
||||
"psraw $6,%%mm3 \n\t"/* dst1*/\
|
||||
"psubsw %%mm1,%%mm7 \n\t"/* a1-b1*/\
|
||||
"psraw $6,%%mm6 \n\t"/* dst2*/\
|
||||
"psubsw %%mm4,%%mm0 \n\t"/* a2-b2*/\
|
||||
"movq 3*16+" #A2 ",%%mm1 \n\t"/* load b0*/\
|
||||
"psraw $6,%%mm7 \n\t"/* dst6*/\
|
||||
"movq %%mm5,%%mm4 \n\t"/* a0*/\
|
||||
"psraw $6,%%mm0 \n\t"/* dst5*/\
|
||||
"movq %%mm3,1*16+" #A2 "\n\t"\
|
||||
"paddsw %%mm1,%%mm5 \n\t"/* a0+b0*/\
|
||||
"movq %%mm6,2*16+" #A2 "\n\t"\
|
||||
"psubsw %%mm1,%%mm4 \n\t"/* a0-b0*/\
|
||||
"movq 5*16+" #A2 ",%%mm3 \n\t"/* load b3*/\
|
||||
"psraw $6,%%mm5 \n\t"/* dst0*/\
|
||||
"movq %%mm2,%%mm6 \n\t"/* a3*/\
|
||||
"psraw $6,%%mm4 \n\t"/* dst7*/\
|
||||
"movq %%mm0,5*16+" #A2 "\n\t"\
|
||||
"paddsw %%mm3,%%mm2 \n\t"/* a3+b3*/\
|
||||
"movq %%mm7,6*16+" #A2 "\n\t"\
|
||||
"psubsw %%mm3,%%mm6 \n\t"/* a3-b3*/\
|
||||
"movq %%mm5,0*16+" #A2 "\n\t"\
|
||||
"psraw $6,%%mm2 \n\t"/* dst3*/\
|
||||
"movq %%mm4,7*16+" #A2 "\n\t"\
|
||||
"psraw $6,%%mm6 \n\t"/* dst4*/\
|
||||
"movq %%mm2,3*16+" #A2 "\n\t"\
|
||||
"movq %%mm6,4*16+" #A2 "\n\t"
|
||||
|
||||
//=============================================================================
|
||||
// Code
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// void idct_mmx(uint16_t block[64]);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void ff_idct_xvid_mmx(short *block){
|
||||
asm volatile(
|
||||
//# Process each row
|
||||
DCT_8_INV_ROW_MMX(0*16(%0), 0*16(%0), 64*0(%2), 8*0(%1))
|
||||
DCT_8_INV_ROW_MMX(1*16(%0), 1*16(%0), 64*1(%2), 8*1(%1))
|
||||
DCT_8_INV_ROW_MMX(2*16(%0), 2*16(%0), 64*2(%2), 8*2(%1))
|
||||
DCT_8_INV_ROW_MMX(3*16(%0), 3*16(%0), 64*3(%2), 8*3(%1))
|
||||
DCT_8_INV_ROW_MMX(4*16(%0), 4*16(%0), 64*0(%2), 8*4(%1))
|
||||
DCT_8_INV_ROW_MMX(5*16(%0), 5*16(%0), 64*3(%2), 8*5(%1))
|
||||
DCT_8_INV_ROW_MMX(6*16(%0), 6*16(%0), 64*2(%2), 8*6(%1))
|
||||
DCT_8_INV_ROW_MMX(7*16(%0), 7*16(%0), 64*1(%2), 8*7(%1))
|
||||
|
||||
//# Process the columns (4 at a time)
|
||||
DCT_8_INV_COL(0(%0), 0(%0))
|
||||
DCT_8_INV_COL(8(%0), 8(%0))
|
||||
:: "r"(block), "r"(rounder_0), "r"(tab_i_04_mmx), "r"(tg_1_16));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// void idct_xmm(uint16_t block[64]);
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void ff_idct_xvid_mmx2(short *block){
|
||||
asm volatile(
|
||||
//# Process each row
|
||||
DCT_8_INV_ROW_XMM(0*16(%0), 0*16(%0), 64*0(%2), 8*0(%1))
|
||||
DCT_8_INV_ROW_XMM(1*16(%0), 1*16(%0), 64*1(%2), 8*1(%1))
|
||||
DCT_8_INV_ROW_XMM(2*16(%0), 2*16(%0), 64*2(%2), 8*2(%1))
|
||||
DCT_8_INV_ROW_XMM(3*16(%0), 3*16(%0), 64*3(%2), 8*3(%1))
|
||||
DCT_8_INV_ROW_XMM(4*16(%0), 4*16(%0), 64*0(%2), 8*4(%1))
|
||||
DCT_8_INV_ROW_XMM(5*16(%0), 5*16(%0), 64*3(%2), 8*5(%1))
|
||||
DCT_8_INV_ROW_XMM(6*16(%0), 6*16(%0), 64*2(%2), 8*6(%1))
|
||||
DCT_8_INV_ROW_XMM(7*16(%0), 7*16(%0), 64*1(%2), 8*7(%1))
|
||||
|
||||
//# Process the columns (4 at a time)
|
||||
DCT_8_INV_COL(0(%0), 0(%0))
|
||||
DCT_8_INV_COL(8(%0), 8(%0))
|
||||
:: "r"(block), "r"(rounder_0), "r"(tab_i_04_xmm), "r"(tg_1_16));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* XVID MPEG-4 VIDEO CODEC
|
||||
* - SSE2 inverse discrete cosine transform -
|
||||
*
|
||||
* Copyright(C) 2003 Pascal Massimino <[email protected]>
|
||||
*
|
||||
* Conversion to gcc syntax with modifications
|
||||
* by Alexander Strange <[email protected]>
|
||||
*
|
||||
* Originally from dct/x86_asm/fdct_sse2_skal.asm in Xvid.
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* Vertical pass is an implementation of the scheme:
|
||||
* Loeffler C., Ligtenberg A., and Moschytz C.S.:
|
||||
* Practical Fast 1D DCT Algorithm with Eleven Multiplications,
|
||||
* Proc. ICASSP 1989, 988-991.
|
||||
*
|
||||
* Horizontal pass is a double 4x4 vector/matrix multiplication,
|
||||
* (see also Intel's Application Note 922:
|
||||
* http://developer.intel.com/vtune/cbts/strmsimd/922down.htm
|
||||
* Copyright (C) 1999 Intel Corporation)
|
||||
*
|
||||
* More details at http://skal.planet-d.net/coding/dct.html
|
||||
*
|
||||
* 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 "libavcodec/dsputil.h"
|
||||
#include "libavcodec/i386/idct_xvid.h"
|
||||
|
||||
/*!
|
||||
* @file idct_sse2_xvid.c
|
||||
* @brief SSE2 idct compatible with xvidmmx
|
||||
*/
|
||||
|
||||
#define X8(x) x,x,x,x,x,x,x,x
|
||||
|
||||
#define ROW_SHIFT 11
|
||||
#define COL_SHIFT 6
|
||||
|
||||
DECLARE_ASM_CONST(16, int16_t, tan1[]) = {X8(13036)}; // tan( pi/16)
|
||||
DECLARE_ASM_CONST(16, int16_t, tan2[]) = {X8(27146)}; // tan(2pi/16) = sqrt(2)-1
|
||||
DECLARE_ASM_CONST(16, int16_t, tan3[]) = {X8(43790)}; // tan(3pi/16)-1
|
||||
DECLARE_ASM_CONST(16, int16_t, sqrt2[])= {X8(23170)}; // 0.5/sqrt(2)
|
||||
DECLARE_ASM_CONST(8, uint8_t, m127[]) = {X8(127)};
|
||||
|
||||
DECLARE_ASM_CONST(16, int16_t, iTab1[]) = {
|
||||
0x4000, 0x539f, 0xc000, 0xac61, 0x4000, 0xdd5d, 0x4000, 0xdd5d,
|
||||
0x4000, 0x22a3, 0x4000, 0x22a3, 0xc000, 0x539f, 0x4000, 0xac61,
|
||||
0x3249, 0x11a8, 0x4b42, 0xee58, 0x11a8, 0x4b42, 0x11a8, 0xcdb7,
|
||||
0x58c5, 0x4b42, 0xa73b, 0xcdb7, 0x3249, 0xa73b, 0x4b42, 0xa73b
|
||||
};
|
||||
|
||||
DECLARE_ASM_CONST(16, int16_t, iTab2[]) = {
|
||||
0x58c5, 0x73fc, 0xa73b, 0x8c04, 0x58c5, 0xcff5, 0x58c5, 0xcff5,
|
||||
0x58c5, 0x300b, 0x58c5, 0x300b, 0xa73b, 0x73fc, 0x58c5, 0x8c04,
|
||||
0x45bf, 0x187e, 0x6862, 0xe782, 0x187e, 0x6862, 0x187e, 0xba41,
|
||||
0x7b21, 0x6862, 0x84df, 0xba41, 0x45bf, 0x84df, 0x6862, 0x84df
|
||||
};
|
||||
|
||||
DECLARE_ASM_CONST(16, int16_t, iTab3[]) = {
|
||||
0x539f, 0x6d41, 0xac61, 0x92bf, 0x539f, 0xd2bf, 0x539f, 0xd2bf,
|
||||
0x539f, 0x2d41, 0x539f, 0x2d41, 0xac61, 0x6d41, 0x539f, 0x92bf,
|
||||
0x41b3, 0x1712, 0x6254, 0xe8ee, 0x1712, 0x6254, 0x1712, 0xbe4d,
|
||||
0x73fc, 0x6254, 0x8c04, 0xbe4d, 0x41b3, 0x8c04, 0x6254, 0x8c04
|
||||
};
|
||||
|
||||
DECLARE_ASM_CONST(16, int16_t, iTab4[]) = {
|
||||
0x4b42, 0x6254, 0xb4be, 0x9dac, 0x4b42, 0xd746, 0x4b42, 0xd746,
|
||||
0x4b42, 0x28ba, 0x4b42, 0x28ba, 0xb4be, 0x6254, 0x4b42, 0x9dac,
|
||||
0x3b21, 0x14c3, 0x587e, 0xeb3d, 0x14c3, 0x587e, 0x14c3, 0xc4df,
|
||||
0x6862, 0x587e, 0x979e, 0xc4df, 0x3b21, 0x979e, 0x587e, 0x979e
|
||||
};
|
||||
|
||||
DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders[]) = {
|
||||
65536, 65536, 65536, 65536,
|
||||
3597, 3597, 3597, 3597,
|
||||
2260, 2260, 2260, 2260,
|
||||
1203, 1203, 1203, 1203,
|
||||
120, 120, 120, 120,
|
||||
512, 512, 512, 512
|
||||
};
|
||||
|
||||
// Temporary storage before the column pass
|
||||
#define ROW1 "%%xmm6"
|
||||
#define ROW3 "%%xmm4"
|
||||
#define ROW5 "%%xmm5"
|
||||
#define ROW7 "%%xmm7"
|
||||
|
||||
#define CLEAR_ODD(r) "pxor "r","r" \n\t"
|
||||
#define PUT_ODD(dst) "pshufhw $0x1B, %%xmm2, "dst" \n\t"
|
||||
|
||||
#ifdef ARCH_X86_64
|
||||
|
||||
# define ROW0 "%%xmm8"
|
||||
# define REG0 ROW0
|
||||
# define ROW2 "%%xmm9"
|
||||
# define REG2 ROW2
|
||||
# define ROW4 "%%xmm10"
|
||||
# define REG4 ROW4
|
||||
# define ROW6 "%%xmm11"
|
||||
# define REG6 ROW6
|
||||
# define CLEAR_EVEN(r) CLEAR_ODD(r)
|
||||
# define PUT_EVEN(dst) PUT_ODD(dst)
|
||||
# define XMMS "%%xmm12"
|
||||
# define MOV_32_ONLY "#"
|
||||
# define SREG2 REG2
|
||||
# define TAN3 "%%xmm13"
|
||||
# define TAN1 "%%xmm14"
|
||||
|
||||
#else
|
||||
|
||||
# define ROW0 "(%0)"
|
||||
# define REG0 "%%xmm4"
|
||||
# define ROW2 "2*16(%0)"
|
||||
# define REG2 "%%xmm4"
|
||||
# define ROW4 "4*16(%0)"
|
||||
# define REG4 "%%xmm6"
|
||||
# define ROW6 "6*16(%0)"
|
||||
# define REG6 "%%xmm6"
|
||||
# define CLEAR_EVEN(r)
|
||||
# define PUT_EVEN(dst) \
|
||||
"pshufhw $0x1B, %%xmm2, %%xmm2 \n\t" \
|
||||
"movdqa %%xmm2, "dst" \n\t"
|
||||
# define XMMS "%%xmm2"
|
||||
# define MOV_32_ONLY "movdqa "
|
||||
# define SREG2 "%%xmm7"
|
||||
# define TAN3 "%%xmm0"
|
||||
# define TAN1 "%%xmm2"
|
||||
|
||||
#endif
|
||||
|
||||
#define ROUND(x) "paddd "MANGLE(x)
|
||||
|
||||
#define JZ(reg, to) \
|
||||
"testl "reg","reg" \n\t" \
|
||||
"jz "to" \n\t"
|
||||
|
||||
#define JNZ(reg, to) \
|
||||
"testl "reg","reg" \n\t" \
|
||||
"jnz "to" \n\t"
|
||||
|
||||
#define TEST_ONE_ROW(src, reg, clear) \
|
||||
clear \
|
||||
"movq "src", %%mm1 \n\t" \
|
||||
"por 8+"src", %%mm1 \n\t" \
|
||||
"paddusb %%mm0, %%mm1 \n\t" \
|
||||
"pmovmskb %%mm1, "reg" \n\t"
|
||||
|
||||
#define TEST_TWO_ROWS(row1, row2, reg1, reg2, clear1, clear2) \
|
||||
clear1 \
|
||||
clear2 \
|
||||
"movq "row1", %%mm1 \n\t" \
|
||||
"por 8+"row1", %%mm1 \n\t" \
|
||||
"movq "row2", %%mm2 \n\t" \
|
||||
"por 8+"row2", %%mm2 \n\t" \
|
||||
"paddusb %%mm0, %%mm1 \n\t" \
|
||||
"paddusb %%mm0, %%mm2 \n\t" \
|
||||
"pmovmskb %%mm1, "reg1" \n\t" \
|
||||
"pmovmskb %%mm2, "reg2" \n\t"
|
||||
|
||||
///IDCT pass on rows.
|
||||
#define iMTX_MULT(src, table, rounder, put) \
|
||||
"movdqa "src", %%xmm3 \n\t" \
|
||||
"movdqa %%xmm3, %%xmm0 \n\t" \
|
||||
"pshufd $0x11, %%xmm3, %%xmm1 \n\t" /* 4602 */ \
|
||||
"punpcklqdq %%xmm0, %%xmm0 \n\t" /* 0246 */ \
|
||||
"pmaddwd "table", %%xmm0 \n\t" \
|
||||
"pmaddwd 16+"table", %%xmm1 \n\t" \
|
||||
"pshufd $0xBB, %%xmm3, %%xmm2 \n\t" /* 5713 */ \
|
||||
"punpckhqdq %%xmm3, %%xmm3 \n\t" /* 1357 */ \
|
||||
"pmaddwd 32+"table", %%xmm2 \n\t" \
|
||||
"pmaddwd 48+"table", %%xmm3 \n\t" \
|
||||
"paddd %%xmm1, %%xmm0 \n\t" \
|
||||
"paddd %%xmm3, %%xmm2 \n\t" \
|
||||
rounder", %%xmm0 \n\t" \
|
||||
"movdqa %%xmm2, %%xmm3 \n\t" \
|
||||
"paddd %%xmm0, %%xmm2 \n\t" \
|
||||
"psubd %%xmm3, %%xmm0 \n\t" \
|
||||
"psrad $11, %%xmm2 \n\t" \
|
||||
"psrad $11, %%xmm0 \n\t" \
|
||||
"packssdw %%xmm0, %%xmm2 \n\t" \
|
||||
put \
|
||||
"1: \n\t"
|
||||
|
||||
#define iLLM_HEAD \
|
||||
"movdqa "MANGLE(tan3)", "TAN3" \n\t" \
|
||||
"movdqa "MANGLE(tan1)", "TAN1" \n\t" \
|
||||
|
||||
///IDCT pass on columns.
|
||||
#define iLLM_PASS(dct) \
|
||||
"movdqa "TAN3", %%xmm1 \n\t" \
|
||||
"movdqa "TAN1", %%xmm3 \n\t" \
|
||||
"pmulhw %%xmm4, "TAN3" \n\t" \
|
||||
"pmulhw %%xmm5, %%xmm1 \n\t" \
|
||||
"paddsw %%xmm4, "TAN3" \n\t" \
|
||||
"paddsw %%xmm5, %%xmm1 \n\t" \
|
||||
"psubsw %%xmm5, "TAN3" \n\t" \
|
||||
"paddsw %%xmm4, %%xmm1 \n\t" \
|
||||
"pmulhw %%xmm7, %%xmm3 \n\t" \
|
||||
"pmulhw %%xmm6, "TAN1" \n\t" \
|
||||
"paddsw %%xmm6, %%xmm3 \n\t" \
|
||||
"psubsw %%xmm7, "TAN1" \n\t" \
|
||||
"movdqa %%xmm3, %%xmm7 \n\t" \
|
||||
"movdqa "TAN1", %%xmm6 \n\t" \
|
||||
"psubsw %%xmm1, %%xmm3 \n\t" \
|
||||
"psubsw "TAN3", "TAN1" \n\t" \
|
||||
"paddsw %%xmm7, %%xmm1 \n\t" \
|
||||
"paddsw %%xmm6, "TAN3" \n\t" \
|
||||
"movdqa %%xmm3, %%xmm6 \n\t" \
|
||||
"psubsw "TAN3", %%xmm3 \n\t" \
|
||||
"paddsw %%xmm6, "TAN3" \n\t" \
|
||||
"movdqa "MANGLE(sqrt2)", %%xmm4 \n\t" \
|
||||
"pmulhw %%xmm4, %%xmm3 \n\t" \
|
||||
"pmulhw %%xmm4, "TAN3" \n\t" \
|
||||
"paddsw "TAN3", "TAN3" \n\t" \
|
||||
"paddsw %%xmm3, %%xmm3 \n\t" \
|
||||
"movdqa "MANGLE(tan2)", %%xmm7 \n\t" \
|
||||
MOV_32_ONLY ROW2", "REG2" \n\t" \
|
||||
MOV_32_ONLY ROW6", "REG6" \n\t" \
|
||||
"movdqa %%xmm7, %%xmm5 \n\t" \
|
||||
"pmulhw "REG6", %%xmm7 \n\t" \
|
||||
"pmulhw "REG2", %%xmm5 \n\t" \
|
||||
"paddsw "REG2", %%xmm7 \n\t" \
|
||||
"psubsw "REG6", %%xmm5 \n\t" \
|
||||
MOV_32_ONLY ROW0", "REG0" \n\t" \
|
||||
MOV_32_ONLY ROW4", "REG4" \n\t" \
|
||||
MOV_32_ONLY" "TAN1", (%0) \n\t" \
|
||||
"movdqa "REG0", "XMMS" \n\t" \
|
||||
"psubsw "REG4", "REG0" \n\t" \
|
||||
"paddsw "XMMS", "REG4" \n\t" \
|
||||
"movdqa "REG4", "XMMS" \n\t" \
|
||||
"psubsw %%xmm7, "REG4" \n\t" \
|
||||
"paddsw "XMMS", %%xmm7 \n\t" \
|
||||
"movdqa "REG0", "XMMS" \n\t" \
|
||||
"psubsw %%xmm5, "REG0" \n\t" \
|
||||
"paddsw "XMMS", %%xmm5 \n\t" \
|
||||
"movdqa %%xmm5, "XMMS" \n\t" \
|
||||
"psubsw "TAN3", %%xmm5 \n\t" \
|
||||
"paddsw "XMMS", "TAN3" \n\t" \
|
||||
"movdqa "REG0", "XMMS" \n\t" \
|
||||
"psubsw %%xmm3, "REG0" \n\t" \
|
||||
"paddsw "XMMS", %%xmm3 \n\t" \
|
||||
MOV_32_ONLY" (%0), "TAN1" \n\t" \
|
||||
"psraw $6, %%xmm5 \n\t" \
|
||||
"psraw $6, "REG0" \n\t" \
|
||||
"psraw $6, "TAN3" \n\t" \
|
||||
"psraw $6, %%xmm3 \n\t" \
|
||||
"movdqa "TAN3", 1*16("dct") \n\t" \
|
||||
"movdqa %%xmm3, 2*16("dct") \n\t" \
|
||||
"movdqa "REG0", 5*16("dct") \n\t" \
|
||||
"movdqa %%xmm5, 6*16("dct") \n\t" \
|
||||
"movdqa %%xmm7, %%xmm0 \n\t" \
|
||||
"movdqa "REG4", %%xmm4 \n\t" \
|
||||
"psubsw %%xmm1, %%xmm7 \n\t" \
|
||||
"psubsw "TAN1", "REG4" \n\t" \
|
||||
"paddsw %%xmm0, %%xmm1 \n\t" \
|
||||
"paddsw %%xmm4, "TAN1" \n\t" \
|
||||
"psraw $6, %%xmm1 \n\t" \
|
||||
"psraw $6, %%xmm7 \n\t" \
|
||||
"psraw $6, "TAN1" \n\t" \
|
||||
"psraw $6, "REG4" \n\t" \
|
||||
"movdqa %%xmm1, ("dct") \n\t" \
|
||||
"movdqa "TAN1", 3*16("dct") \n\t" \
|
||||
"movdqa "REG4", 4*16("dct") \n\t" \
|
||||
"movdqa %%xmm7, 7*16("dct") \n\t"
|
||||
|
||||
///IDCT pass on columns, assuming rows 4-7 are zero.
|
||||
#define iLLM_PASS_SPARSE(dct) \
|
||||
"pmulhw %%xmm4, "TAN3" \n\t" \
|
||||
"paddsw %%xmm4, "TAN3" \n\t" \
|
||||
"movdqa %%xmm6, %%xmm3 \n\t" \
|
||||
"pmulhw %%xmm6, "TAN1" \n\t" \
|
||||
"movdqa %%xmm4, %%xmm1 \n\t" \
|
||||
"psubsw %%xmm1, %%xmm3 \n\t" \
|
||||
"paddsw %%xmm6, %%xmm1 \n\t" \
|
||||
"movdqa "TAN1", %%xmm6 \n\t" \
|
||||
"psubsw "TAN3", "TAN1" \n\t" \
|
||||
"paddsw %%xmm6, "TAN3" \n\t" \
|
||||
"movdqa %%xmm3, %%xmm6 \n\t" \
|
||||
"psubsw "TAN3", %%xmm3 \n\t" \
|
||||
"paddsw %%xmm6, "TAN3" \n\t" \
|
||||
"movdqa "MANGLE(sqrt2)", %%xmm4 \n\t" \
|
||||
"pmulhw %%xmm4, %%xmm3 \n\t" \
|
||||
"pmulhw %%xmm4, "TAN3" \n\t" \
|
||||
"paddsw "TAN3", "TAN3" \n\t" \
|
||||
"paddsw %%xmm3, %%xmm3 \n\t" \
|
||||
"movdqa "MANGLE(tan2)", %%xmm5 \n\t" \
|
||||
MOV_32_ONLY ROW2", "SREG2" \n\t" \
|
||||
"pmulhw "SREG2", %%xmm5 \n\t" \
|
||||
MOV_32_ONLY ROW0", "REG0" \n\t" \
|
||||
"movdqa "REG0", %%xmm6 \n\t" \
|
||||
"psubsw "SREG2", %%xmm6 \n\t" \
|
||||
"paddsw "REG0", "SREG2" \n\t" \
|
||||
MOV_32_ONLY" "TAN1", (%0) \n\t" \
|
||||
"movdqa "REG0", "XMMS" \n\t" \
|
||||
"psubsw %%xmm5, "REG0" \n\t" \
|
||||
"paddsw "XMMS", %%xmm5 \n\t" \
|
||||
"movdqa %%xmm5, "XMMS" \n\t" \
|
||||
"psubsw "TAN3", %%xmm5 \n\t" \
|
||||
"paddsw "XMMS", "TAN3" \n\t" \
|
||||
"movdqa "REG0", "XMMS" \n\t" \
|
||||
"psubsw %%xmm3, "REG0" \n\t" \
|
||||
"paddsw "XMMS", %%xmm3 \n\t" \
|
||||
MOV_32_ONLY" (%0), "TAN1" \n\t" \
|
||||
"psraw $6, %%xmm5 \n\t" \
|
||||
"psraw $6, "REG0" \n\t" \
|
||||
"psraw $6, "TAN3" \n\t" \
|
||||
"psraw $6, %%xmm3 \n\t" \
|
||||
"movdqa "TAN3", 1*16("dct") \n\t" \
|
||||
"movdqa %%xmm3, 2*16("dct") \n\t" \
|
||||
"movdqa "REG0", 5*16("dct") \n\t" \
|
||||
"movdqa %%xmm5, 6*16("dct") \n\t" \
|
||||
"movdqa "SREG2", %%xmm0 \n\t" \
|
||||
"movdqa %%xmm6, %%xmm4 \n\t" \
|
||||
"psubsw %%xmm1, "SREG2" \n\t" \
|
||||
"psubsw "TAN1", %%xmm6 \n\t" \
|
||||
"paddsw %%xmm0, %%xmm1 \n\t" \
|
||||
"paddsw %%xmm4, "TAN1" \n\t" \
|
||||
"psraw $6, %%xmm1 \n\t" \
|
||||
"psraw $6, "SREG2" \n\t" \
|
||||
"psraw $6, "TAN1" \n\t" \
|
||||
"psraw $6, %%xmm6 \n\t" \
|
||||
"movdqa %%xmm1, ("dct") \n\t" \
|
||||
"movdqa "TAN1", 3*16("dct") \n\t" \
|
||||
"movdqa %%xmm6, 4*16("dct") \n\t" \
|
||||
"movdqa "SREG2", 7*16("dct") \n\t"
|
||||
|
||||
inline void ff_idct_xvid_sse2(short *block)
|
||||
{
|
||||
asm volatile(
|
||||
"movq "MANGLE(m127)", %%mm0 \n\t"
|
||||
iMTX_MULT("(%0)", MANGLE(iTab1), ROUND(walkenIdctRounders), PUT_EVEN(ROW0))
|
||||
iMTX_MULT("1*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+1*16), PUT_ODD(ROW1))
|
||||
iMTX_MULT("2*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+2*16), PUT_EVEN(ROW2))
|
||||
|
||||
TEST_TWO_ROWS("3*16(%0)", "4*16(%0)", "%%eax", "%%ecx", CLEAR_ODD(ROW3), CLEAR_EVEN(ROW4))
|
||||
JZ("%%eax", "1f")
|
||||
iMTX_MULT("3*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders+3*16), PUT_ODD(ROW3))
|
||||
|
||||
TEST_TWO_ROWS("5*16(%0)", "6*16(%0)", "%%eax", "%%edx", CLEAR_ODD(ROW5), CLEAR_EVEN(ROW6))
|
||||
TEST_ONE_ROW("7*16(%0)", "%%esi", CLEAR_ODD(ROW7))
|
||||
iLLM_HEAD
|
||||
ASMALIGN(4)
|
||||
JNZ("%%ecx", "2f")
|
||||
JNZ("%%eax", "3f")
|
||||
JNZ("%%edx", "4f")
|
||||
JNZ("%%esi", "5f")
|
||||
iLLM_PASS_SPARSE("%0")
|
||||
"jmp 6f \n\t"
|
||||
"2: \n\t"
|
||||
iMTX_MULT("4*16(%0)", MANGLE(iTab1), "#", PUT_EVEN(ROW4))
|
||||
"3: \n\t"
|
||||
iMTX_MULT("5*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders+4*16), PUT_ODD(ROW5))
|
||||
JZ("%%edx", "1f")
|
||||
"4: \n\t"
|
||||
iMTX_MULT("6*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+5*16), PUT_EVEN(ROW6))
|
||||
JZ("%%esi", "1f")
|
||||
"5: \n\t"
|
||||
iMTX_MULT("7*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+5*16), PUT_ODD(ROW7))
|
||||
#ifndef ARCH_X86_64
|
||||
iLLM_HEAD
|
||||
#endif
|
||||
iLLM_PASS("%0")
|
||||
"6: \n\t"
|
||||
: "+r"(block)
|
||||
:
|
||||
: "%eax", "%ecx", "%edx", "%esi", "memory");
|
||||
}
|
||||
|
||||
void ff_idct_xvid_sse2_put(uint8_t *dest, int line_size, short *block)
|
||||
{
|
||||
ff_idct_xvid_sse2(block);
|
||||
put_pixels_clamped_mmx(block, dest, line_size);
|
||||
}
|
||||
|
||||
void ff_idct_xvid_sse2_add(uint8_t *dest, int line_size, short *block)
|
||||
{
|
||||
ff_idct_xvid_sse2(block);
|
||||
add_pixels_clamped_mmx(block, dest, line_size);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* XVID MPEG-4 VIDEO CODEC
|
||||
*
|
||||
* 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 idct_xvid.h
|
||||
* header for Xvid IDCT functions
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_IDCT_XVID_H
|
||||
#define FFMPEG_IDCT_XVID_H
|
||||
|
||||
void ff_idct_xvid_mmx(short *block);
|
||||
void ff_idct_xvid_mmx2(short *block);
|
||||
void ff_idct_xvid_sse2(short *block);
|
||||
void ff_idct_xvid_sse2_put(uint8_t *dest, int line_size, short *block);
|
||||
void ff_idct_xvid_sse2_add(uint8_t *dest, int line_size, short *block);
|
||||
|
||||
#endif /* FFMPEG_IDCT_XVID_H */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* simple math operations
|
||||
* Copyright (c) 2006 Michael Niedermayer <[email protected]> et al
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_I386_MATHOPS_H
|
||||
#define FFMPEG_I386_MATHOPS_H
|
||||
|
||||
#ifdef FRAC_BITS
|
||||
# define MULL(ra, rb) \
|
||||
({ int rt, dummy; asm (\
|
||||
"imull %3 \n\t"\
|
||||
"shrdl %4, %%edx, %%eax \n\t"\
|
||||
: "=a"(rt), "=d"(dummy)\
|
||||
: "a" (ra), "rm" (rb), "i"(FRAC_BITS));\
|
||||
rt; })
|
||||
#endif
|
||||
|
||||
#define MULH(ra, rb) \
|
||||
({ int rt, dummy;\
|
||||
asm ("imull %3\n\t" : "=d"(rt), "=a"(dummy): "a" (ra), "rm" (rb));\
|
||||
rt; })
|
||||
|
||||
#define MUL64(ra, rb) \
|
||||
({ int64_t rt;\
|
||||
asm ("imull %2\n\t" : "=A"(rt) : "a" (ra), "g" (rb));\
|
||||
rt; })
|
||||
|
||||
#endif /* FFMPEG_I386_MATHOPS_H */
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* mmx.h
|
||||
* Copyright (C) 1997-2001 H. Dietz and R. Fisher
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#ifndef FFMPEG_MMX_H
|
||||
#define FFMPEG_MMX_H
|
||||
|
||||
#warning Everything in this header is deprecated, use plain asm()! New code using this header will be rejected.
|
||||
|
||||
/*
|
||||
* The type of an value that fits in an MMX register (note that long
|
||||
* long constant values MUST be suffixed by LL and unsigned long long
|
||||
* values by ULL, lest they be truncated by the compiler)
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
long long q; /* Quadword (64-bit) value */
|
||||
unsigned long long uq; /* Unsigned Quadword */
|
||||
int d[2]; /* 2 Doubleword (32-bit) values */
|
||||
unsigned int ud[2]; /* 2 Unsigned Doubleword */
|
||||
short w[4]; /* 4 Word (16-bit) values */
|
||||
unsigned short uw[4]; /* 4 Unsigned Word */
|
||||
char b[8]; /* 8 Byte (8-bit) values */
|
||||
unsigned char ub[8]; /* 8 Unsigned Byte */
|
||||
float s[2]; /* Single-precision (32-bit) value */
|
||||
} mmx_t; /* On an 8-byte (64-bit) boundary */
|
||||
|
||||
|
||||
#define mmx_i2r(op,imm,reg) \
|
||||
asm volatile (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "i" (imm) )
|
||||
|
||||
#define mmx_m2r(op,mem,reg) \
|
||||
asm volatile (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "m" (mem))
|
||||
|
||||
#define mmx_r2m(op,reg,mem) \
|
||||
asm volatile (#op " %%" #reg ", %0" \
|
||||
: "=m" (mem) \
|
||||
: /* nothing */ )
|
||||
|
||||
#define mmx_r2r(op,regs,regd) \
|
||||
asm volatile (#op " %" #regs ", %" #regd)
|
||||
|
||||
|
||||
#define emms() asm volatile ("emms")
|
||||
|
||||
#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
|
||||
#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
|
||||
#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
|
||||
|
||||
#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
|
||||
#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
|
||||
#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
|
||||
|
||||
#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
|
||||
#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
|
||||
#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
|
||||
#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
|
||||
|
||||
#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
|
||||
#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
|
||||
|
||||
#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
|
||||
#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
|
||||
#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
|
||||
#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
|
||||
#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
|
||||
#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
|
||||
|
||||
#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
|
||||
#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
|
||||
#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
|
||||
#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
|
||||
|
||||
#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
|
||||
#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
|
||||
#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
|
||||
#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
|
||||
|
||||
#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
|
||||
#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
|
||||
|
||||
#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
|
||||
#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
|
||||
|
||||
#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
|
||||
#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
|
||||
#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
|
||||
#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
|
||||
#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
|
||||
#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
|
||||
|
||||
#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
|
||||
#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
|
||||
#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
|
||||
#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
|
||||
#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
|
||||
#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
|
||||
|
||||
#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
|
||||
#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
|
||||
|
||||
#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
|
||||
#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
|
||||
|
||||
#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
|
||||
#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
|
||||
|
||||
#define por_m2r(var,reg) mmx_m2r (por, var, reg)
|
||||
#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
|
||||
|
||||
#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
|
||||
#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
|
||||
#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
|
||||
#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
|
||||
#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
|
||||
#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
|
||||
#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
|
||||
#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
|
||||
#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
|
||||
|
||||
#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
|
||||
#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
|
||||
#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
|
||||
#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
|
||||
#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
|
||||
#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
|
||||
|
||||
#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
|
||||
#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
|
||||
#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
|
||||
#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
|
||||
#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
|
||||
#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
|
||||
#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
|
||||
#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
|
||||
#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
|
||||
|
||||
#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
|
||||
#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
|
||||
#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
|
||||
#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
|
||||
#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
|
||||
#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
|
||||
|
||||
#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
|
||||
#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
|
||||
#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
|
||||
#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
|
||||
|
||||
#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
|
||||
#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
|
||||
#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
|
||||
#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
|
||||
|
||||
#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
|
||||
#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
|
||||
#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
|
||||
#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
|
||||
#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
|
||||
#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
|
||||
|
||||
#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
|
||||
#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
|
||||
#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
|
||||
#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
|
||||
#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
|
||||
#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
|
||||
|
||||
#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
|
||||
#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
|
||||
|
||||
|
||||
/* 3DNOW extensions */
|
||||
|
||||
#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
|
||||
#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
|
||||
|
||||
|
||||
/* AMD MMX extensions - also available in intel SSE */
|
||||
|
||||
|
||||
#define mmx_m2ri(op,mem,reg,imm) \
|
||||
asm volatile (#op " %1, %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "m" (mem), "i" (imm))
|
||||
#define mmx_r2ri(op,regs,regd,imm) \
|
||||
asm volatile (#op " %0, %%" #regs ", %%" #regd \
|
||||
: /* nothing */ \
|
||||
: "i" (imm) )
|
||||
|
||||
#define mmx_fetch(mem,hint) \
|
||||
asm volatile ("prefetch" #hint " %0" \
|
||||
: /* nothing */ \
|
||||
: "m" (mem))
|
||||
|
||||
|
||||
#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
|
||||
|
||||
#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
|
||||
|
||||
#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
|
||||
#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
|
||||
#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
|
||||
#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
|
||||
|
||||
#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
|
||||
|
||||
#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
|
||||
|
||||
#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
|
||||
#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
|
||||
|
||||
#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
|
||||
#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
|
||||
|
||||
#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
|
||||
#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
|
||||
|
||||
#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
|
||||
#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
|
||||
|
||||
#define pmovmskb(mmreg,reg) \
|
||||
asm volatile ("movmskps %" #mmreg ", %" #reg)
|
||||
|
||||
#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
|
||||
#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
|
||||
|
||||
#define prefetcht0(mem) mmx_fetch (mem, t0)
|
||||
#define prefetcht1(mem) mmx_fetch (mem, t1)
|
||||
#define prefetcht2(mem) mmx_fetch (mem, t2)
|
||||
#define prefetchnta(mem) mmx_fetch (mem, nta)
|
||||
|
||||
#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
|
||||
#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
|
||||
|
||||
#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
|
||||
#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
|
||||
|
||||
#define sfence() asm volatile ("sfence\n\t")
|
||||
|
||||
/* SSE2 */
|
||||
#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm)
|
||||
#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm)
|
||||
#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm)
|
||||
#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm)
|
||||
|
||||
#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm)
|
||||
|
||||
#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg)
|
||||
#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var)
|
||||
#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd)
|
||||
#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg)
|
||||
#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var)
|
||||
#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd)
|
||||
|
||||
#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var)
|
||||
|
||||
#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg)
|
||||
#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg)
|
||||
|
||||
#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd)
|
||||
#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd)
|
||||
|
||||
|
||||
#endif /* FFMPEG_MMX_H */
|
||||
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* MMX optimized motion estimation
|
||||
* Copyright (c) 2001 Fabrice Bellard.
|
||||
* Copyright (c) 2002-2004 Michael Niedermayer
|
||||
*
|
||||
* mostly by Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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 "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
DECLARE_ASM_CONST(8, uint64_t, round_tab[3])={
|
||||
0x0000000000000000ULL,
|
||||
0x0001000100010001ULL,
|
||||
0x0002000200020002ULL,
|
||||
};
|
||||
|
||||
DECLARE_ASM_CONST(8, uint64_t, bone)= 0x0101010101010101LL;
|
||||
|
||||
static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
x86_reg len= -(stride*h);
|
||||
asm volatile(
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm4 \n\t"
|
||||
"add %3, %%"REG_a" \n\t"
|
||||
"psubusb %%mm0, %%mm2 \n\t"
|
||||
"psubusb %%mm4, %%mm0 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm3 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm5 \n\t"
|
||||
"psubusb %%mm1, %%mm3 \n\t"
|
||||
"psubusb %%mm5, %%mm1 \n\t"
|
||||
"por %%mm2, %%mm0 \n\t"
|
||||
"por %%mm1, %%mm3 \n\t"
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm3, %%mm2 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm3 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"paddw %%mm1, %%mm0 \n\t"
|
||||
"paddw %%mm3, %%mm2 \n\t"
|
||||
"paddw %%mm2, %%mm0 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"add %3, %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
: "+a" (len)
|
||||
: "r" (blk1 - len), "r" (blk2 - len), "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void sad8_1_mmx2(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"psadbw (%2), %%mm0 \n\t"
|
||||
"psadbw (%2, %3), %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%2,%3,2), %2 \n\t"
|
||||
"sub $2, %0 \n\t"
|
||||
" jg 1b \n\t"
|
||||
: "+r" (h), "+r" (blk1), "+r" (blk2)
|
||||
: "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)
|
||||
{
|
||||
int ret;
|
||||
asm volatile(
|
||||
"pxor %%xmm6, %%xmm6 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movdqu (%1), %%xmm0 \n\t"
|
||||
"movdqu (%1, %3), %%xmm1 \n\t"
|
||||
"psadbw (%2), %%xmm0 \n\t"
|
||||
"psadbw (%2, %3), %%xmm1 \n\t"
|
||||
"paddw %%xmm0, %%xmm6 \n\t"
|
||||
"paddw %%xmm1, %%xmm6 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%2,%3,2), %2 \n\t"
|
||||
"sub $2, %0 \n\t"
|
||||
" jg 1b \n\t"
|
||||
: "+r" (h), "+r" (blk1), "+r" (blk2)
|
||||
: "r" ((x86_reg)stride)
|
||||
);
|
||||
asm volatile(
|
||||
"movhlps %%xmm6, %%xmm0 \n\t"
|
||||
"paddw %%xmm0, %%xmm6 \n\t"
|
||||
"movd %%xmm6, %0 \n\t"
|
||||
: "=r"(ret)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void sad8_x2a_mmx2(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq (%1, %3), %%mm1 \n\t"
|
||||
"pavgb 1(%1), %%mm0 \n\t"
|
||||
"pavgb 1(%1, %3), %%mm1 \n\t"
|
||||
"psadbw (%2), %%mm0 \n\t"
|
||||
"psadbw (%2, %3), %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%2,%3,2), %2 \n\t"
|
||||
"sub $2, %0 \n\t"
|
||||
" jg 1b \n\t"
|
||||
: "+r" (h), "+r" (blk1), "+r" (blk2)
|
||||
: "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void sad8_y2a_mmx2(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"movq (%1, %3), %%mm2 \n\t"
|
||||
"pavgb %%mm1, %%mm0 \n\t"
|
||||
"pavgb %%mm2, %%mm1 \n\t"
|
||||
"psadbw (%2), %%mm0 \n\t"
|
||||
"psadbw (%2, %3), %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%2,%3,2), %2 \n\t"
|
||||
"sub $2, %0 \n\t"
|
||||
" jg 1b \n\t"
|
||||
: "+r" (h), "+r" (blk1), "+r" (blk2)
|
||||
: "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void sad8_4_mmx2(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
asm volatile(
|
||||
"movq "MANGLE(bone)", %%mm5 \n\t"
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"pavgb 1(%1), %%mm0 \n\t"
|
||||
"add %3, %1 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"movq (%1,%3), %%mm2 \n\t"
|
||||
"pavgb 1(%1), %%mm1 \n\t"
|
||||
"pavgb 1(%1,%3), %%mm2 \n\t"
|
||||
"psubusb %%mm5, %%mm1 \n\t"
|
||||
"pavgb %%mm1, %%mm0 \n\t"
|
||||
"pavgb %%mm2, %%mm1 \n\t"
|
||||
"psadbw (%2), %%mm0 \n\t"
|
||||
"psadbw (%2,%3), %%mm1 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm1, %%mm6 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"lea (%1,%3,2), %1 \n\t"
|
||||
"lea (%2,%3,2), %2 \n\t"
|
||||
"sub $2, %0 \n\t"
|
||||
" jg 1b \n\t"
|
||||
: "+r" (h), "+r" (blk1), "+r" (blk2)
|
||||
: "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
x86_reg len= -(stride*h);
|
||||
asm volatile(
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm1 \n\t"
|
||||
"punpckhbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm0, %%mm1 \n\t"
|
||||
"paddw %%mm2, %%mm3 \n\t"
|
||||
"movq (%3, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq (%3, %%"REG_a"), %%mm2 \n\t"
|
||||
"paddw %%mm5, %%mm1 \n\t"
|
||||
"paddw %%mm5, %%mm3 \n\t"
|
||||
"psrlw $1, %%mm1 \n\t"
|
||||
"psrlw $1, %%mm3 \n\t"
|
||||
"packuswb %%mm3, %%mm1 \n\t"
|
||||
"psubusb %%mm1, %%mm4 \n\t"
|
||||
"psubusb %%mm2, %%mm1 \n\t"
|
||||
"por %%mm4, %%mm1 \n\t"
|
||||
"movq %%mm1, %%mm0 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"paddw %%mm1, %%mm0 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"add %4, %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
: "+a" (len)
|
||||
: "r" (blk1a - len), "r" (blk1b -len), "r" (blk2 - len), "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
x86_reg len= -(stride*h);
|
||||
asm volatile(
|
||||
"movq (%1, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 1(%1, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq %%mm0, %%mm1 \n\t"
|
||||
"movq %%mm2, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpckhbw %%mm7, %%mm1 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"paddw %%mm2, %%mm0 \n\t"
|
||||
"paddw %%mm3, %%mm1 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%2, %%"REG_a"), %%mm2 \n\t"
|
||||
"movq 1(%2, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq %%mm2, %%mm3 \n\t"
|
||||
"movq %%mm4, %%mm5 \n\t"
|
||||
"punpcklbw %%mm7, %%mm2 \n\t"
|
||||
"punpckhbw %%mm7, %%mm3 \n\t"
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"
|
||||
"punpckhbw %%mm7, %%mm5 \n\t"
|
||||
"paddw %%mm4, %%mm2 \n\t"
|
||||
"paddw %%mm5, %%mm3 \n\t"
|
||||
"movq 16+"MANGLE(round_tab)", %%mm5 \n\t"
|
||||
"paddw %%mm2, %%mm0 \n\t"
|
||||
"paddw %%mm3, %%mm1 \n\t"
|
||||
"paddw %%mm5, %%mm0 \n\t"
|
||||
"paddw %%mm5, %%mm1 \n\t"
|
||||
"movq (%3, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq (%3, %%"REG_a"), %%mm5 \n\t"
|
||||
"psrlw $2, %%mm0 \n\t"
|
||||
"psrlw $2, %%mm1 \n\t"
|
||||
"packuswb %%mm1, %%mm0 \n\t"
|
||||
"psubusb %%mm0, %%mm4 \n\t"
|
||||
"psubusb %%mm5, %%mm0 \n\t"
|
||||
"por %%mm4, %%mm0 \n\t"
|
||||
"movq %%mm0, %%mm4 \n\t"
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"
|
||||
"punpckhbw %%mm7, %%mm4 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"paddw %%mm4, %%mm6 \n\t"
|
||||
"movq %%mm2, %%mm0 \n\t"
|
||||
"movq %%mm3, %%mm1 \n\t"
|
||||
"add %4, %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
: "+a" (len)
|
||||
: "r" (blk1 - len), "r" (blk1 -len + stride), "r" (blk2 - len), "r" ((x86_reg)stride)
|
||||
);
|
||||
}
|
||||
|
||||
static inline int sum_mmx(void)
|
||||
{
|
||||
int ret;
|
||||
asm volatile(
|
||||
"movq %%mm6, %%mm0 \n\t"
|
||||
"psrlq $32, %%mm6 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"movq %%mm6, %%mm0 \n\t"
|
||||
"psrlq $16, %%mm6 \n\t"
|
||||
"paddw %%mm0, %%mm6 \n\t"
|
||||
"movd %%mm6, %0 \n\t"
|
||||
: "=r" (ret)
|
||||
);
|
||||
return ret&0xFFFF;
|
||||
}
|
||||
|
||||
static inline int sum_mmx2(void)
|
||||
{
|
||||
int ret;
|
||||
asm volatile(
|
||||
"movd %%mm6, %0 \n\t"
|
||||
: "=r" (ret)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
sad8_2_mmx(blk1, blk1+1, blk2, stride, h);
|
||||
}
|
||||
static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
|
||||
{
|
||||
sad8_2_mmx(blk1, blk1+stride, blk2, stride, h);
|
||||
}
|
||||
|
||||
|
||||
#define PIX_SAD(suf)\
|
||||
static int sad8_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
assert(h==8);\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t":);\
|
||||
\
|
||||
sad8_1_ ## suf(blk1, blk2, stride, 8);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
static int sad8_x2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
assert(h==8);\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
"movq %0, %%mm5 \n\t"\
|
||||
:: "m"(round_tab[1]) \
|
||||
);\
|
||||
\
|
||||
sad8_x2a_ ## suf(blk1, blk2, stride, 8);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
\
|
||||
static int sad8_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
assert(h==8);\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
"movq %0, %%mm5 \n\t"\
|
||||
:: "m"(round_tab[1]) \
|
||||
);\
|
||||
\
|
||||
sad8_y2a_ ## suf(blk1, blk2, stride, 8);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
\
|
||||
static int sad8_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
assert(h==8);\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
::);\
|
||||
\
|
||||
sad8_4_ ## suf(blk1, blk2, stride, 8);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
\
|
||||
static int sad16_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t":);\
|
||||
\
|
||||
sad8_1_ ## suf(blk1 , blk2 , stride, h);\
|
||||
sad8_1_ ## suf(blk1+8, blk2+8, stride, h);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
static int sad16_x2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
"movq %0, %%mm5 \n\t"\
|
||||
:: "m"(round_tab[1]) \
|
||||
);\
|
||||
\
|
||||
sad8_x2a_ ## suf(blk1 , blk2 , stride, h);\
|
||||
sad8_x2a_ ## suf(blk1+8, blk2+8, stride, h);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
static int sad16_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
"movq %0, %%mm5 \n\t"\
|
||||
:: "m"(round_tab[1]) \
|
||||
);\
|
||||
\
|
||||
sad8_y2a_ ## suf(blk1 , blk2 , stride, h);\
|
||||
sad8_y2a_ ## suf(blk1+8, blk2+8, stride, h);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
static int sad16_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
|
||||
{\
|
||||
asm volatile("pxor %%mm7, %%mm7 \n\t"\
|
||||
"pxor %%mm6, %%mm6 \n\t"\
|
||||
::);\
|
||||
\
|
||||
sad8_4_ ## suf(blk1 , blk2 , stride, h);\
|
||||
sad8_4_ ## suf(blk1+8, blk2+8, stride, h);\
|
||||
\
|
||||
return sum_ ## suf();\
|
||||
}\
|
||||
|
||||
PIX_SAD(mmx)
|
||||
PIX_SAD(mmx2)
|
||||
|
||||
void dsputil_init_pix_mmx(DSPContext* c, AVCodecContext *avctx)
|
||||
{
|
||||
if (mm_flags & MM_MMX) {
|
||||
c->pix_abs[0][0] = sad16_mmx;
|
||||
c->pix_abs[0][1] = sad16_x2_mmx;
|
||||
c->pix_abs[0][2] = sad16_y2_mmx;
|
||||
c->pix_abs[0][3] = sad16_xy2_mmx;
|
||||
c->pix_abs[1][0] = sad8_mmx;
|
||||
c->pix_abs[1][1] = sad8_x2_mmx;
|
||||
c->pix_abs[1][2] = sad8_y2_mmx;
|
||||
c->pix_abs[1][3] = sad8_xy2_mmx;
|
||||
|
||||
c->sad[0]= sad16_mmx;
|
||||
c->sad[1]= sad8_mmx;
|
||||
}
|
||||
if (mm_flags & MM_MMXEXT) {
|
||||
c->pix_abs[0][0] = sad16_mmx2;
|
||||
c->pix_abs[1][0] = sad8_mmx2;
|
||||
|
||||
c->sad[0]= sad16_mmx2;
|
||||
c->sad[1]= sad8_mmx2;
|
||||
|
||||
if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
|
||||
c->pix_abs[0][1] = sad16_x2_mmx2;
|
||||
c->pix_abs[0][2] = sad16_y2_mmx2;
|
||||
c->pix_abs[0][3] = sad16_xy2_mmx2;
|
||||
c->pix_abs[1][1] = sad8_x2_mmx2;
|
||||
c->pix_abs[1][2] = sad8_y2_mmx2;
|
||||
c->pix_abs[1][3] = sad8_xy2_mmx2;
|
||||
}
|
||||
}
|
||||
if ((mm_flags & MM_SSE2) && !(mm_flags & MM_3DNOW)) {
|
||||
c->sad[0]= sad16_sse2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* The simplest mpeg encoder (well, it was the simplest!)
|
||||
* Copyright (c) 2000,2001 Fabrice Bellard.
|
||||
*
|
||||
* Optimized for ia32 CPUs by Nick Kurshev <[email protected]>
|
||||
* h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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 "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "libavcodec/mpegvideo.h"
|
||||
#include "dsputil_mmx.h"
|
||||
|
||||
extern uint16_t inv_zigzag_direct16[64];
|
||||
|
||||
|
||||
static void dct_unquantize_h263_intra_mmx(MpegEncContext *s,
|
||||
DCTELEM *block, int n, int qscale)
|
||||
{
|
||||
x86_reg level, qmul, qadd, nCoeffs;
|
||||
|
||||
qmul = qscale << 1;
|
||||
|
||||
assert(s->block_last_index[n]>=0 || s->h263_aic);
|
||||
|
||||
if (!s->h263_aic) {
|
||||
if (n < 4)
|
||||
level = block[0] * s->y_dc_scale;
|
||||
else
|
||||
level = block[0] * s->c_dc_scale;
|
||||
qadd = (qscale - 1) | 1;
|
||||
}else{
|
||||
qadd = 0;
|
||||
level= block[0];
|
||||
}
|
||||
if(s->ac_pred)
|
||||
nCoeffs=63;
|
||||
else
|
||||
nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
|
||||
//printf("%d %d ", qmul, qadd);
|
||||
asm volatile(
|
||||
"movd %1, %%mm6 \n\t" //qmul
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"movd %2, %%mm5 \n\t" //qadd
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"psubw %%mm5, %%mm7 \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %3), %%mm0 \n\t"
|
||||
"movq 8(%0, %3), %%mm1 \n\t"
|
||||
|
||||
"pmullw %%mm6, %%mm0 \n\t"
|
||||
"pmullw %%mm6, %%mm1 \n\t"
|
||||
|
||||
"movq (%0, %3), %%mm2 \n\t"
|
||||
"movq 8(%0, %3), %%mm3 \n\t"
|
||||
|
||||
"pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
|
||||
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
|
||||
"paddw %%mm7, %%mm0 \n\t"
|
||||
"paddw %%mm7, %%mm1 \n\t"
|
||||
|
||||
"pxor %%mm0, %%mm2 \n\t"
|
||||
"pxor %%mm1, %%mm3 \n\t"
|
||||
|
||||
"pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0
|
||||
"pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0
|
||||
|
||||
"pandn %%mm2, %%mm0 \n\t"
|
||||
"pandn %%mm3, %%mm1 \n\t"
|
||||
|
||||
"movq %%mm0, (%0, %3) \n\t"
|
||||
"movq %%mm1, 8(%0, %3) \n\t"
|
||||
|
||||
"add $16, %3 \n\t"
|
||||
"jng 1b \n\t"
|
||||
::"r" (block+nCoeffs), "rm"(qmul), "rm" (qadd), "r" (2*(-nCoeffs))
|
||||
: "memory"
|
||||
);
|
||||
block[0]= level;
|
||||
}
|
||||
|
||||
|
||||
static void dct_unquantize_h263_inter_mmx(MpegEncContext *s,
|
||||
DCTELEM *block, int n, int qscale)
|
||||
{
|
||||
x86_reg qmul, qadd, nCoeffs;
|
||||
|
||||
qmul = qscale << 1;
|
||||
qadd = (qscale - 1) | 1;
|
||||
|
||||
assert(s->block_last_index[n]>=0 || s->h263_aic);
|
||||
|
||||
nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
|
||||
//printf("%d %d ", qmul, qadd);
|
||||
asm volatile(
|
||||
"movd %1, %%mm6 \n\t" //qmul
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"movd %2, %%mm5 \n\t" //qadd
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"packssdw %%mm5, %%mm5 \n\t"
|
||||
"psubw %%mm5, %%mm7 \n\t"
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %3), %%mm0 \n\t"
|
||||
"movq 8(%0, %3), %%mm1 \n\t"
|
||||
|
||||
"pmullw %%mm6, %%mm0 \n\t"
|
||||
"pmullw %%mm6, %%mm1 \n\t"
|
||||
|
||||
"movq (%0, %3), %%mm2 \n\t"
|
||||
"movq 8(%0, %3), %%mm3 \n\t"
|
||||
|
||||
"pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
|
||||
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
|
||||
"paddw %%mm7, %%mm0 \n\t"
|
||||
"paddw %%mm7, %%mm1 \n\t"
|
||||
|
||||
"pxor %%mm0, %%mm2 \n\t"
|
||||
"pxor %%mm1, %%mm3 \n\t"
|
||||
|
||||
"pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0
|
||||
"pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0
|
||||
|
||||
"pandn %%mm2, %%mm0 \n\t"
|
||||
"pandn %%mm3, %%mm1 \n\t"
|
||||
|
||||
"movq %%mm0, (%0, %3) \n\t"
|
||||
"movq %%mm1, 8(%0, %3) \n\t"
|
||||
|
||||
"add $16, %3 \n\t"
|
||||
"jng 1b \n\t"
|
||||
::"r" (block+nCoeffs), "rm"(qmul), "rm" (qadd), "r" (2*(-nCoeffs))
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
NK:
|
||||
Note: looking at PARANOID:
|
||||
"enable all paranoid tests for rounding, overflows, etc..."
|
||||
|
||||
#ifdef PARANOID
|
||||
if (level < -2048 || level > 2047)
|
||||
fprintf(stderr, "unquant error %d %d\n", i, level);
|
||||
#endif
|
||||
We can suppose that result of two multiplications can't be greater than 0xFFFF
|
||||
i.e. is 16-bit, so we use here only PMULLW instruction and can avoid
|
||||
a complex multiplication.
|
||||
=====================================================
|
||||
Full formula for multiplication of 2 integer numbers
|
||||
which are represent as high:low words:
|
||||
input: value1 = high1:low1
|
||||
value2 = high2:low2
|
||||
output: value3 = value1*value2
|
||||
value3=high3:low3 (on overflow: modulus 2^32 wrap-around)
|
||||
this mean that for 0x123456 * 0x123456 correct result is 0x766cb0ce4
|
||||
but this algorithm will compute only 0x66cb0ce4
|
||||
this limited by 16-bit size of operands
|
||||
---------------------------------
|
||||
tlow1 = high1*low2
|
||||
tlow2 = high2*low1
|
||||
tlow1 = tlow1 + tlow2
|
||||
high3:low3 = low1*low2
|
||||
high3 += tlow1
|
||||
*/
|
||||
static void dct_unquantize_mpeg1_intra_mmx(MpegEncContext *s,
|
||||
DCTELEM *block, int n, int qscale)
|
||||
{
|
||||
x86_reg nCoeffs;
|
||||
const uint16_t *quant_matrix;
|
||||
int block0;
|
||||
|
||||
assert(s->block_last_index[n]>=0);
|
||||
|
||||
nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1;
|
||||
|
||||
if (n < 4)
|
||||
block0 = block[0] * s->y_dc_scale;
|
||||
else
|
||||
block0 = block[0] * s->c_dc_scale;
|
||||
/* XXX: only mpeg1 */
|
||||
quant_matrix = s->intra_matrix;
|
||||
asm volatile(
|
||||
"pcmpeqw %%mm7, %%mm7 \n\t"
|
||||
"psrlw $15, %%mm7 \n\t"
|
||||
"movd %2, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"mov %3, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 8(%0, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq 8(%1, %%"REG_a"), %%mm5 \n\t"
|
||||
"pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pxor %%mm2, %%mm2 \n\t"
|
||||
"pxor %%mm3, %%mm3 \n\t"
|
||||
"pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t" // abs(block[i])
|
||||
"psubw %%mm3, %%mm1 \n\t" // abs(block[i])
|
||||
"pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*q
|
||||
"pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*q
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm5, %%mm5 \n\t" // FIXME slow
|
||||
"pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
|
||||
"pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0
|
||||
"psraw $3, %%mm0 \n\t"
|
||||
"psraw $3, %%mm1 \n\t"
|
||||
"psubw %%mm7, %%mm0 \n\t"
|
||||
"psubw %%mm7, %%mm1 \n\t"
|
||||
"por %%mm7, %%mm0 \n\t"
|
||||
"por %%mm7, %%mm1 \n\t"
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t"
|
||||
"psubw %%mm3, %%mm1 \n\t"
|
||||
"pandn %%mm0, %%mm4 \n\t"
|
||||
"pandn %%mm1, %%mm5 \n\t"
|
||||
"movq %%mm4, (%0, %%"REG_a") \n\t"
|
||||
"movq %%mm5, 8(%0, %%"REG_a") \n\t"
|
||||
|
||||
"add $16, %%"REG_a" \n\t"
|
||||
"js 1b \n\t"
|
||||
::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs)
|
||||
: "%"REG_a, "memory"
|
||||
);
|
||||
block[0]= block0;
|
||||
}
|
||||
|
||||
static void dct_unquantize_mpeg1_inter_mmx(MpegEncContext *s,
|
||||
DCTELEM *block, int n, int qscale)
|
||||
{
|
||||
x86_reg nCoeffs;
|
||||
const uint16_t *quant_matrix;
|
||||
|
||||
assert(s->block_last_index[n]>=0);
|
||||
|
||||
nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1;
|
||||
|
||||
quant_matrix = s->inter_matrix;
|
||||
asm volatile(
|
||||
"pcmpeqw %%mm7, %%mm7 \n\t"
|
||||
"psrlw $15, %%mm7 \n\t"
|
||||
"movd %2, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"mov %3, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 8(%0, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq 8(%1, %%"REG_a"), %%mm5 \n\t"
|
||||
"pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pxor %%mm2, %%mm2 \n\t"
|
||||
"pxor %%mm3, %%mm3 \n\t"
|
||||
"pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t" // abs(block[i])
|
||||
"psubw %%mm3, %%mm1 \n\t" // abs(block[i])
|
||||
"paddw %%mm0, %%mm0 \n\t" // abs(block[i])*2
|
||||
"paddw %%mm1, %%mm1 \n\t" // abs(block[i])*2
|
||||
"paddw %%mm7, %%mm0 \n\t" // abs(block[i])*2 + 1
|
||||
"paddw %%mm7, %%mm1 \n\t" // abs(block[i])*2 + 1
|
||||
"pmullw %%mm4, %%mm0 \n\t" // (abs(block[i])*2 + 1)*q
|
||||
"pmullw %%mm5, %%mm1 \n\t" // (abs(block[i])*2 + 1)*q
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm5, %%mm5 \n\t" // FIXME slow
|
||||
"pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
|
||||
"pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0
|
||||
"psraw $4, %%mm0 \n\t"
|
||||
"psraw $4, %%mm1 \n\t"
|
||||
"psubw %%mm7, %%mm0 \n\t"
|
||||
"psubw %%mm7, %%mm1 \n\t"
|
||||
"por %%mm7, %%mm0 \n\t"
|
||||
"por %%mm7, %%mm1 \n\t"
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t"
|
||||
"psubw %%mm3, %%mm1 \n\t"
|
||||
"pandn %%mm0, %%mm4 \n\t"
|
||||
"pandn %%mm1, %%mm5 \n\t"
|
||||
"movq %%mm4, (%0, %%"REG_a") \n\t"
|
||||
"movq %%mm5, 8(%0, %%"REG_a") \n\t"
|
||||
|
||||
"add $16, %%"REG_a" \n\t"
|
||||
"js 1b \n\t"
|
||||
::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs)
|
||||
: "%"REG_a, "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static void dct_unquantize_mpeg2_intra_mmx(MpegEncContext *s,
|
||||
DCTELEM *block, int n, int qscale)
|
||||
{
|
||||
x86_reg nCoeffs;
|
||||
const uint16_t *quant_matrix;
|
||||
int block0;
|
||||
|
||||
assert(s->block_last_index[n]>=0);
|
||||
|
||||
if(s->alternate_scan) nCoeffs= 63; //FIXME
|
||||
else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
|
||||
|
||||
if (n < 4)
|
||||
block0 = block[0] * s->y_dc_scale;
|
||||
else
|
||||
block0 = block[0] * s->c_dc_scale;
|
||||
quant_matrix = s->intra_matrix;
|
||||
asm volatile(
|
||||
"pcmpeqw %%mm7, %%mm7 \n\t"
|
||||
"psrlw $15, %%mm7 \n\t"
|
||||
"movd %2, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"mov %3, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 8(%0, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq 8(%1, %%"REG_a"), %%mm5 \n\t"
|
||||
"pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pxor %%mm2, %%mm2 \n\t"
|
||||
"pxor %%mm3, %%mm3 \n\t"
|
||||
"pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t" // abs(block[i])
|
||||
"psubw %%mm3, %%mm1 \n\t" // abs(block[i])
|
||||
"pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*q
|
||||
"pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*q
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm5, %%mm5 \n\t" // FIXME slow
|
||||
"pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
|
||||
"pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0
|
||||
"psraw $3, %%mm0 \n\t"
|
||||
"psraw $3, %%mm1 \n\t"
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t"
|
||||
"psubw %%mm3, %%mm1 \n\t"
|
||||
"pandn %%mm0, %%mm4 \n\t"
|
||||
"pandn %%mm1, %%mm5 \n\t"
|
||||
"movq %%mm4, (%0, %%"REG_a") \n\t"
|
||||
"movq %%mm5, 8(%0, %%"REG_a") \n\t"
|
||||
|
||||
"add $16, %%"REG_a" \n\t"
|
||||
"jng 1b \n\t"
|
||||
::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs)
|
||||
: "%"REG_a, "memory"
|
||||
);
|
||||
block[0]= block0;
|
||||
//Note, we do not do mismatch control for intra as errors cannot accumulate
|
||||
}
|
||||
|
||||
static void dct_unquantize_mpeg2_inter_mmx(MpegEncContext *s,
|
||||
DCTELEM *block, int n, int qscale)
|
||||
{
|
||||
x86_reg nCoeffs;
|
||||
const uint16_t *quant_matrix;
|
||||
|
||||
assert(s->block_last_index[n]>=0);
|
||||
|
||||
if(s->alternate_scan) nCoeffs= 63; //FIXME
|
||||
else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
|
||||
|
||||
quant_matrix = s->inter_matrix;
|
||||
asm volatile(
|
||||
"pcmpeqw %%mm7, %%mm7 \n\t"
|
||||
"psrlq $48, %%mm7 \n\t"
|
||||
"movd %2, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"packssdw %%mm6, %%mm6 \n\t"
|
||||
"mov %3, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
"movq (%0, %%"REG_a"), %%mm0 \n\t"
|
||||
"movq 8(%0, %%"REG_a"), %%mm1 \n\t"
|
||||
"movq (%1, %%"REG_a"), %%mm4 \n\t"
|
||||
"movq 8(%1, %%"REG_a"), %%mm5 \n\t"
|
||||
"pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
|
||||
"pxor %%mm2, %%mm2 \n\t"
|
||||
"pxor %%mm3, %%mm3 \n\t"
|
||||
"pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t" // abs(block[i])
|
||||
"psubw %%mm3, %%mm1 \n\t" // abs(block[i])
|
||||
"paddw %%mm0, %%mm0 \n\t" // abs(block[i])*2
|
||||
"paddw %%mm1, %%mm1 \n\t" // abs(block[i])*2
|
||||
"pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*2*q
|
||||
"pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*2*q
|
||||
"paddw %%mm4, %%mm0 \n\t" // (abs(block[i])*2 + 1)*q
|
||||
"paddw %%mm5, %%mm1 \n\t" // (abs(block[i])*2 + 1)*q
|
||||
"pxor %%mm4, %%mm4 \n\t"
|
||||
"pxor %%mm5, %%mm5 \n\t" // FIXME slow
|
||||
"pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
|
||||
"pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0
|
||||
"psrlw $4, %%mm0 \n\t"
|
||||
"psrlw $4, %%mm1 \n\t"
|
||||
"pxor %%mm2, %%mm0 \n\t"
|
||||
"pxor %%mm3, %%mm1 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t"
|
||||
"psubw %%mm3, %%mm1 \n\t"
|
||||
"pandn %%mm0, %%mm4 \n\t"
|
||||
"pandn %%mm1, %%mm5 \n\t"
|
||||
"pxor %%mm4, %%mm7 \n\t"
|
||||
"pxor %%mm5, %%mm7 \n\t"
|
||||
"movq %%mm4, (%0, %%"REG_a") \n\t"
|
||||
"movq %%mm5, 8(%0, %%"REG_a") \n\t"
|
||||
|
||||
"add $16, %%"REG_a" \n\t"
|
||||
"jng 1b \n\t"
|
||||
"movd 124(%0, %3), %%mm0 \n\t"
|
||||
"movq %%mm7, %%mm6 \n\t"
|
||||
"psrlq $32, %%mm7 \n\t"
|
||||
"pxor %%mm6, %%mm7 \n\t"
|
||||
"movq %%mm7, %%mm6 \n\t"
|
||||
"psrlq $16, %%mm7 \n\t"
|
||||
"pxor %%mm6, %%mm7 \n\t"
|
||||
"pslld $31, %%mm7 \n\t"
|
||||
"psrlq $15, %%mm7 \n\t"
|
||||
"pxor %%mm7, %%mm0 \n\t"
|
||||
"movd %%mm0, 124(%0, %3) \n\t"
|
||||
|
||||
::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "r" (-2*nCoeffs)
|
||||
: "%"REG_a, "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static void denoise_dct_mmx(MpegEncContext *s, DCTELEM *block){
|
||||
const int intra= s->mb_intra;
|
||||
int *sum= s->dct_error_sum[intra];
|
||||
uint16_t *offset= s->dct_offset[intra];
|
||||
|
||||
s->dct_count[intra]++;
|
||||
|
||||
asm volatile(
|
||||
"pxor %%mm7, %%mm7 \n\t"
|
||||
"1: \n\t"
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
"pxor %%mm1, %%mm1 \n\t"
|
||||
"movq (%0), %%mm2 \n\t"
|
||||
"movq 8(%0), %%mm3 \n\t"
|
||||
"pcmpgtw %%mm2, %%mm0 \n\t"
|
||||
"pcmpgtw %%mm3, %%mm1 \n\t"
|
||||
"pxor %%mm0, %%mm2 \n\t"
|
||||
"pxor %%mm1, %%mm3 \n\t"
|
||||
"psubw %%mm0, %%mm2 \n\t"
|
||||
"psubw %%mm1, %%mm3 \n\t"
|
||||
"movq %%mm2, %%mm4 \n\t"
|
||||
"movq %%mm3, %%mm5 \n\t"
|
||||
"psubusw (%2), %%mm2 \n\t"
|
||||
"psubusw 8(%2), %%mm3 \n\t"
|
||||
"pxor %%mm0, %%mm2 \n\t"
|
||||
"pxor %%mm1, %%mm3 \n\t"
|
||||
"psubw %%mm0, %%mm2 \n\t"
|
||||
"psubw %%mm1, %%mm3 \n\t"
|
||||
"movq %%mm2, (%0) \n\t"
|
||||
"movq %%mm3, 8(%0) \n\t"
|
||||
"movq %%mm4, %%mm2 \n\t"
|
||||
"movq %%mm5, %%mm3 \n\t"
|
||||
"punpcklwd %%mm7, %%mm4 \n\t"
|
||||
"punpckhwd %%mm7, %%mm2 \n\t"
|
||||
"punpcklwd %%mm7, %%mm5 \n\t"
|
||||
"punpckhwd %%mm7, %%mm3 \n\t"
|
||||
"paddd (%1), %%mm4 \n\t"
|
||||
"paddd 8(%1), %%mm2 \n\t"
|
||||
"paddd 16(%1), %%mm5 \n\t"
|
||||
"paddd 24(%1), %%mm3 \n\t"
|
||||
"movq %%mm4, (%1) \n\t"
|
||||
"movq %%mm2, 8(%1) \n\t"
|
||||
"movq %%mm5, 16(%1) \n\t"
|
||||
"movq %%mm3, 24(%1) \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"add $32, %1 \n\t"
|
||||
"add $16, %2 \n\t"
|
||||
"cmp %3, %0 \n\t"
|
||||
" jb 1b \n\t"
|
||||
: "+r" (block), "+r" (sum), "+r" (offset)
|
||||
: "r"(block+64)
|
||||
);
|
||||
}
|
||||
|
||||
static void denoise_dct_sse2(MpegEncContext *s, DCTELEM *block){
|
||||
const int intra= s->mb_intra;
|
||||
int *sum= s->dct_error_sum[intra];
|
||||
uint16_t *offset= s->dct_offset[intra];
|
||||
|
||||
s->dct_count[intra]++;
|
||||
|
||||
asm volatile(
|
||||
"pxor %%xmm7, %%xmm7 \n\t"
|
||||
"1: \n\t"
|
||||
"pxor %%xmm0, %%xmm0 \n\t"
|
||||
"pxor %%xmm1, %%xmm1 \n\t"
|
||||
"movdqa (%0), %%xmm2 \n\t"
|
||||
"movdqa 16(%0), %%xmm3 \n\t"
|
||||
"pcmpgtw %%xmm2, %%xmm0 \n\t"
|
||||
"pcmpgtw %%xmm3, %%xmm1 \n\t"
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pxor %%xmm1, %%xmm3 \n\t"
|
||||
"psubw %%xmm0, %%xmm2 \n\t"
|
||||
"psubw %%xmm1, %%xmm3 \n\t"
|
||||
"movdqa %%xmm2, %%xmm4 \n\t"
|
||||
"movdqa %%xmm3, %%xmm5 \n\t"
|
||||
"psubusw (%2), %%xmm2 \n\t"
|
||||
"psubusw 16(%2), %%xmm3 \n\t"
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pxor %%xmm1, %%xmm3 \n\t"
|
||||
"psubw %%xmm0, %%xmm2 \n\t"
|
||||
"psubw %%xmm1, %%xmm3 \n\t"
|
||||
"movdqa %%xmm2, (%0) \n\t"
|
||||
"movdqa %%xmm3, 16(%0) \n\t"
|
||||
"movdqa %%xmm4, %%xmm6 \n\t"
|
||||
"movdqa %%xmm5, %%xmm0 \n\t"
|
||||
"punpcklwd %%xmm7, %%xmm4 \n\t"
|
||||
"punpckhwd %%xmm7, %%xmm6 \n\t"
|
||||
"punpcklwd %%xmm7, %%xmm5 \n\t"
|
||||
"punpckhwd %%xmm7, %%xmm0 \n\t"
|
||||
"paddd (%1), %%xmm4 \n\t"
|
||||
"paddd 16(%1), %%xmm6 \n\t"
|
||||
"paddd 32(%1), %%xmm5 \n\t"
|
||||
"paddd 48(%1), %%xmm0 \n\t"
|
||||
"movdqa %%xmm4, (%1) \n\t"
|
||||
"movdqa %%xmm6, 16(%1) \n\t"
|
||||
"movdqa %%xmm5, 32(%1) \n\t"
|
||||
"movdqa %%xmm0, 48(%1) \n\t"
|
||||
"add $32, %0 \n\t"
|
||||
"add $64, %1 \n\t"
|
||||
"add $32, %2 \n\t"
|
||||
"cmp %3, %0 \n\t"
|
||||
" jb 1b \n\t"
|
||||
: "+r" (block), "+r" (sum), "+r" (offset)
|
||||
: "r"(block+64)
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSSE3
|
||||
#define HAVE_SSSE3_BAK
|
||||
#endif
|
||||
#undef HAVE_SSSE3
|
||||
|
||||
#undef HAVE_SSE2
|
||||
#undef HAVE_MMX2
|
||||
#define RENAME(a) a ## _MMX
|
||||
#define RENAMEl(a) a ## _mmx
|
||||
#include "mpegvideo_mmx_template.c"
|
||||
|
||||
#define HAVE_MMX2
|
||||
#undef RENAME
|
||||
#undef RENAMEl
|
||||
#define RENAME(a) a ## _MMX2
|
||||
#define RENAMEl(a) a ## _mmx2
|
||||
#include "mpegvideo_mmx_template.c"
|
||||
|
||||
#define HAVE_SSE2
|
||||
#undef RENAME
|
||||
#undef RENAMEl
|
||||
#define RENAME(a) a ## _SSE2
|
||||
#define RENAMEl(a) a ## _sse2
|
||||
#include "mpegvideo_mmx_template.c"
|
||||
|
||||
#ifdef HAVE_SSSE3_BAK
|
||||
#define HAVE_SSSE3
|
||||
#undef RENAME
|
||||
#undef RENAMEl
|
||||
#define RENAME(a) a ## _SSSE3
|
||||
#define RENAMEl(a) a ## _sse2
|
||||
#include "mpegvideo_mmx_template.c"
|
||||
#endif
|
||||
|
||||
void MPV_common_init_mmx(MpegEncContext *s)
|
||||
{
|
||||
if (mm_flags & MM_MMX) {
|
||||
const int dct_algo = s->avctx->dct_algo;
|
||||
|
||||
s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_mmx;
|
||||
s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_mmx;
|
||||
s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_mmx;
|
||||
s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_mmx;
|
||||
if(!(s->flags & CODEC_FLAG_BITEXACT))
|
||||
s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_mmx;
|
||||
s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_mmx;
|
||||
|
||||
if (mm_flags & MM_SSE2) {
|
||||
s->denoise_dct= denoise_dct_sse2;
|
||||
} else {
|
||||
s->denoise_dct= denoise_dct_mmx;
|
||||
}
|
||||
|
||||
if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
|
||||
#ifdef HAVE_SSSE3
|
||||
if(mm_flags & MM_SSSE3){
|
||||
s->dct_quantize= dct_quantize_SSSE3;
|
||||
} else
|
||||
#endif
|
||||
if(mm_flags & MM_SSE2){
|
||||
s->dct_quantize= dct_quantize_SSE2;
|
||||
} else if(mm_flags & MM_MMXEXT){
|
||||
s->dct_quantize= dct_quantize_MMX2;
|
||||
} else {
|
||||
s->dct_quantize= dct_quantize_MMX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* MPEG video MMX templates
|
||||
*
|
||||
* Copyright (c) 2002 Michael Niedermayer <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#undef MMREG_WIDTH
|
||||
#undef MM
|
||||
#undef MOVQ
|
||||
#undef SPREADW
|
||||
#undef PMAXW
|
||||
#undef PMAX
|
||||
#undef SAVE_SIGN
|
||||
#undef RESTORE_SIGN
|
||||
|
||||
#if defined(HAVE_SSE2)
|
||||
#define MMREG_WIDTH "16"
|
||||
#define MM "%%xmm"
|
||||
#define MOVQ "movdqa"
|
||||
#define SPREADW(a) \
|
||||
"pshuflw $0, "a", "a" \n\t"\
|
||||
"punpcklwd "a", "a" \n\t"
|
||||
#define PMAXW(a,b) "pmaxsw "a", "b" \n\t"
|
||||
#define PMAX(a,b) \
|
||||
"movhlps "a", "b" \n\t"\
|
||||
PMAXW(b, a)\
|
||||
"pshuflw $0x0E, "a", "b" \n\t"\
|
||||
PMAXW(b, a)\
|
||||
"pshuflw $0x01, "a", "b" \n\t"\
|
||||
PMAXW(b, a)
|
||||
#else
|
||||
#define MMREG_WIDTH "8"
|
||||
#define MM "%%mm"
|
||||
#define MOVQ "movq"
|
||||
#if defined(HAVE_MMX2)
|
||||
#define SPREADW(a) "pshufw $0, "a", "a" \n\t"
|
||||
#define PMAXW(a,b) "pmaxsw "a", "b" \n\t"
|
||||
#define PMAX(a,b) \
|
||||
"pshufw $0x0E, "a", "b" \n\t"\
|
||||
PMAXW(b, a)\
|
||||
"pshufw $0x01, "a", "b" \n\t"\
|
||||
PMAXW(b, a)
|
||||
#else
|
||||
#define SPREADW(a) \
|
||||
"punpcklwd "a", "a" \n\t"\
|
||||
"punpcklwd "a", "a" \n\t"
|
||||
#define PMAXW(a,b) \
|
||||
"psubusw "a", "b" \n\t"\
|
||||
"paddw "a", "b" \n\t"
|
||||
#define PMAX(a,b) \
|
||||
"movq "a", "b" \n\t"\
|
||||
"psrlq $32, "a" \n\t"\
|
||||
PMAXW(b, a)\
|
||||
"movq "a", "b" \n\t"\
|
||||
"psrlq $16, "a" \n\t"\
|
||||
PMAXW(b, a)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SSSE3
|
||||
#define SAVE_SIGN(a,b) \
|
||||
"movdqa "b", "a" \n\t"\
|
||||
"pabsw "b", "b" \n\t"
|
||||
#define RESTORE_SIGN(a,b) \
|
||||
"psignw "a", "b" \n\t"
|
||||
#else
|
||||
#define SAVE_SIGN(a,b) \
|
||||
"pxor "a", "a" \n\t"\
|
||||
"pcmpgtw "b", "a" \n\t" /* block[i] <= 0 ? 0xFF : 0x00 */\
|
||||
"pxor "a", "b" \n\t"\
|
||||
"psubw "a", "b" \n\t" /* ABS(block[i]) */
|
||||
#define RESTORE_SIGN(a,b) \
|
||||
"pxor "a", "b" \n\t"\
|
||||
"psubw "a", "b" \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
|
||||
#endif
|
||||
|
||||
static int RENAME(dct_quantize)(MpegEncContext *s,
|
||||
DCTELEM *block, int n,
|
||||
int qscale, int *overflow)
|
||||
{
|
||||
x86_reg last_non_zero_p1;
|
||||
int level=0, q; //=0 is because gcc says uninitialized ...
|
||||
const uint16_t *qmat, *bias;
|
||||
DECLARE_ALIGNED_16(int16_t, temp_block[64]);
|
||||
|
||||
assert((7&(int)(&temp_block[0])) == 0); //did gcc align it correctly?
|
||||
|
||||
//s->fdct (block);
|
||||
RENAMEl(ff_fdct) (block); //cannot be anything else ...
|
||||
|
||||
if(s->dct_error_sum)
|
||||
s->denoise_dct(s, block);
|
||||
|
||||
if (s->mb_intra) {
|
||||
int dummy;
|
||||
if (n < 4)
|
||||
q = s->y_dc_scale;
|
||||
else
|
||||
q = s->c_dc_scale;
|
||||
/* note: block[0] is assumed to be positive */
|
||||
if (!s->h263_aic) {
|
||||
#if 1
|
||||
asm volatile (
|
||||
"mul %%ecx \n\t"
|
||||
: "=d" (level), "=a"(dummy)
|
||||
: "a" ((block[0]>>2) + q), "c" (ff_inverse[q<<1])
|
||||
);
|
||||
#else
|
||||
asm volatile (
|
||||
"xorl %%edx, %%edx \n\t"
|
||||
"divw %%cx \n\t"
|
||||
"movzwl %%ax, %%eax \n\t"
|
||||
: "=a" (level)
|
||||
: "a" ((block[0]>>2) + q), "c" (q<<1)
|
||||
: "%edx"
|
||||
);
|
||||
#endif
|
||||
} else
|
||||
/* For AIC we skip quant/dequant of INTRADC */
|
||||
level = (block[0] + 4)>>3;
|
||||
|
||||
block[0]=0; //avoid fake overflow
|
||||
// temp_block[0] = (block[0] + (q >> 1)) / q;
|
||||
last_non_zero_p1 = 1;
|
||||
bias = s->q_intra_matrix16[qscale][1];
|
||||
qmat = s->q_intra_matrix16[qscale][0];
|
||||
} else {
|
||||
last_non_zero_p1 = 0;
|
||||
bias = s->q_inter_matrix16[qscale][1];
|
||||
qmat = s->q_inter_matrix16[qscale][0];
|
||||
}
|
||||
|
||||
if((s->out_format == FMT_H263 || s->out_format == FMT_H261) && s->mpeg_quant==0){
|
||||
|
||||
asm volatile(
|
||||
"movd %%"REG_a", "MM"3 \n\t" // last_non_zero_p1
|
||||
SPREADW(MM"3")
|
||||
"pxor "MM"7, "MM"7 \n\t" // 0
|
||||
"pxor "MM"4, "MM"4 \n\t" // 0
|
||||
MOVQ" (%2), "MM"5 \n\t" // qmat[0]
|
||||
"pxor "MM"6, "MM"6 \n\t"
|
||||
"psubw (%3), "MM"6 \n\t" // -bias[0]
|
||||
"mov $-128, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
MOVQ" (%1, %%"REG_a"), "MM"0 \n\t" // block[i]
|
||||
SAVE_SIGN(MM"1", MM"0") // ABS(block[i])
|
||||
"psubusw "MM"6, "MM"0 \n\t" // ABS(block[i]) + bias[0]
|
||||
"pmulhw "MM"5, "MM"0 \n\t" // (ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16
|
||||
"por "MM"0, "MM"4 \n\t"
|
||||
RESTORE_SIGN(MM"1", MM"0") // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
|
||||
MOVQ" "MM"0, (%5, %%"REG_a") \n\t"
|
||||
"pcmpeqw "MM"7, "MM"0 \n\t" // out==0 ? 0xFF : 0x00
|
||||
MOVQ" (%4, %%"REG_a"), "MM"1 \n\t"
|
||||
MOVQ" "MM"7, (%1, %%"REG_a") \n\t" // 0
|
||||
"pandn "MM"1, "MM"0 \n\t"
|
||||
PMAXW(MM"0", MM"3")
|
||||
"add $"MMREG_WIDTH", %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
PMAX(MM"3", MM"0")
|
||||
"movd "MM"3, %%"REG_a" \n\t"
|
||||
"movzb %%al, %%"REG_a" \n\t" // last_non_zero_p1
|
||||
: "+a" (last_non_zero_p1)
|
||||
: "r" (block+64), "r" (qmat), "r" (bias),
|
||||
"r" (inv_zigzag_direct16+64), "r" (temp_block+64)
|
||||
);
|
||||
}else{ // FMT_H263
|
||||
asm volatile(
|
||||
"movd %%"REG_a", "MM"3 \n\t" // last_non_zero_p1
|
||||
SPREADW(MM"3")
|
||||
"pxor "MM"7, "MM"7 \n\t" // 0
|
||||
"pxor "MM"4, "MM"4 \n\t" // 0
|
||||
"mov $-128, %%"REG_a" \n\t"
|
||||
ASMALIGN(4)
|
||||
"1: \n\t"
|
||||
MOVQ" (%1, %%"REG_a"), "MM"0 \n\t" // block[i]
|
||||
SAVE_SIGN(MM"1", MM"0") // ABS(block[i])
|
||||
MOVQ" (%3, %%"REG_a"), "MM"6 \n\t" // bias[0]
|
||||
"paddusw "MM"6, "MM"0 \n\t" // ABS(block[i]) + bias[0]
|
||||
MOVQ" (%2, %%"REG_a"), "MM"5 \n\t" // qmat[i]
|
||||
"pmulhw "MM"5, "MM"0 \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16
|
||||
"por "MM"0, "MM"4 \n\t"
|
||||
RESTORE_SIGN(MM"1", MM"0") // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
|
||||
MOVQ" "MM"0, (%5, %%"REG_a") \n\t"
|
||||
"pcmpeqw "MM"7, "MM"0 \n\t" // out==0 ? 0xFF : 0x00
|
||||
MOVQ" (%4, %%"REG_a"), "MM"1 \n\t"
|
||||
MOVQ" "MM"7, (%1, %%"REG_a") \n\t" // 0
|
||||
"pandn "MM"1, "MM"0 \n\t"
|
||||
PMAXW(MM"0", MM"3")
|
||||
"add $"MMREG_WIDTH", %%"REG_a" \n\t"
|
||||
" js 1b \n\t"
|
||||
PMAX(MM"3", MM"0")
|
||||
"movd "MM"3, %%"REG_a" \n\t"
|
||||
"movzb %%al, %%"REG_a" \n\t" // last_non_zero_p1
|
||||
: "+a" (last_non_zero_p1)
|
||||
: "r" (block+64), "r" (qmat+64), "r" (bias+64),
|
||||
"r" (inv_zigzag_direct16+64), "r" (temp_block+64)
|
||||
);
|
||||
}
|
||||
asm volatile(
|
||||
"movd %1, "MM"1 \n\t" // max_qcoeff
|
||||
SPREADW(MM"1")
|
||||
"psubusw "MM"1, "MM"4 \n\t"
|
||||
"packuswb "MM"4, "MM"4 \n\t"
|
||||
#ifdef HAVE_SSE2
|
||||
"packuswb "MM"4, "MM"4 \n\t"
|
||||
#endif
|
||||
"movd "MM"4, %0 \n\t" // *overflow
|
||||
: "=g" (*overflow)
|
||||
: "g" (s->max_qcoeff)
|
||||
);
|
||||
|
||||
if(s->mb_intra) block[0]= level;
|
||||
else block[0]= temp_block[0];
|
||||
|
||||
if(s->dsp.idct_permutation_type == FF_SIMPLE_IDCT_PERM){
|
||||
if(last_non_zero_p1 <= 1) goto end;
|
||||
block[0x08] = temp_block[0x01]; block[0x10] = temp_block[0x08];
|
||||
block[0x20] = temp_block[0x10];
|
||||
if(last_non_zero_p1 <= 4) goto end;
|
||||
block[0x18] = temp_block[0x09]; block[0x04] = temp_block[0x02];
|
||||
block[0x09] = temp_block[0x03];
|
||||
if(last_non_zero_p1 <= 7) goto end;
|
||||
block[0x14] = temp_block[0x0A]; block[0x28] = temp_block[0x11];
|
||||
block[0x12] = temp_block[0x18]; block[0x02] = temp_block[0x20];
|
||||
if(last_non_zero_p1 <= 11) goto end;
|
||||
block[0x1A] = temp_block[0x19]; block[0x24] = temp_block[0x12];
|
||||
block[0x19] = temp_block[0x0B]; block[0x01] = temp_block[0x04];
|
||||
block[0x0C] = temp_block[0x05];
|
||||
if(last_non_zero_p1 <= 16) goto end;
|
||||
block[0x11] = temp_block[0x0C]; block[0x29] = temp_block[0x13];
|
||||
block[0x16] = temp_block[0x1A]; block[0x0A] = temp_block[0x21];
|
||||
block[0x30] = temp_block[0x28]; block[0x22] = temp_block[0x30];
|
||||
block[0x38] = temp_block[0x29]; block[0x06] = temp_block[0x22];
|
||||
if(last_non_zero_p1 <= 24) goto end;
|
||||
block[0x1B] = temp_block[0x1B]; block[0x21] = temp_block[0x14];
|
||||
block[0x1C] = temp_block[0x0D]; block[0x05] = temp_block[0x06];
|
||||
block[0x0D] = temp_block[0x07]; block[0x15] = temp_block[0x0E];
|
||||
block[0x2C] = temp_block[0x15]; block[0x13] = temp_block[0x1C];
|
||||
if(last_non_zero_p1 <= 32) goto end;
|
||||
block[0x0B] = temp_block[0x23]; block[0x34] = temp_block[0x2A];
|
||||
block[0x2A] = temp_block[0x31]; block[0x32] = temp_block[0x38];
|
||||
block[0x3A] = temp_block[0x39]; block[0x26] = temp_block[0x32];
|
||||
block[0x39] = temp_block[0x2B]; block[0x03] = temp_block[0x24];
|
||||
if(last_non_zero_p1 <= 40) goto end;
|
||||
block[0x1E] = temp_block[0x1D]; block[0x25] = temp_block[0x16];
|
||||
block[0x1D] = temp_block[0x0F]; block[0x2D] = temp_block[0x17];
|
||||
block[0x17] = temp_block[0x1E]; block[0x0E] = temp_block[0x25];
|
||||
block[0x31] = temp_block[0x2C]; block[0x2B] = temp_block[0x33];
|
||||
if(last_non_zero_p1 <= 48) goto end;
|
||||
block[0x36] = temp_block[0x3A]; block[0x3B] = temp_block[0x3B];
|
||||
block[0x23] = temp_block[0x34]; block[0x3C] = temp_block[0x2D];
|
||||
block[0x07] = temp_block[0x26]; block[0x1F] = temp_block[0x1F];
|
||||
block[0x0F] = temp_block[0x27]; block[0x35] = temp_block[0x2E];
|
||||
if(last_non_zero_p1 <= 56) goto end;
|
||||
block[0x2E] = temp_block[0x35]; block[0x33] = temp_block[0x3C];
|
||||
block[0x3E] = temp_block[0x3D]; block[0x27] = temp_block[0x36];
|
||||
block[0x3D] = temp_block[0x2F]; block[0x2F] = temp_block[0x37];
|
||||
block[0x37] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F];
|
||||
}else if(s->dsp.idct_permutation_type == FF_LIBMPEG2_IDCT_PERM){
|
||||
if(last_non_zero_p1 <= 1) goto end;
|
||||
block[0x04] = temp_block[0x01];
|
||||
block[0x08] = temp_block[0x08]; block[0x10] = temp_block[0x10];
|
||||
if(last_non_zero_p1 <= 4) goto end;
|
||||
block[0x0C] = temp_block[0x09]; block[0x01] = temp_block[0x02];
|
||||
block[0x05] = temp_block[0x03];
|
||||
if(last_non_zero_p1 <= 7) goto end;
|
||||
block[0x09] = temp_block[0x0A]; block[0x14] = temp_block[0x11];
|
||||
block[0x18] = temp_block[0x18]; block[0x20] = temp_block[0x20];
|
||||
if(last_non_zero_p1 <= 11) goto end;
|
||||
block[0x1C] = temp_block[0x19];
|
||||
block[0x11] = temp_block[0x12]; block[0x0D] = temp_block[0x0B];
|
||||
block[0x02] = temp_block[0x04]; block[0x06] = temp_block[0x05];
|
||||
if(last_non_zero_p1 <= 16) goto end;
|
||||
block[0x0A] = temp_block[0x0C]; block[0x15] = temp_block[0x13];
|
||||
block[0x19] = temp_block[0x1A]; block[0x24] = temp_block[0x21];
|
||||
block[0x28] = temp_block[0x28]; block[0x30] = temp_block[0x30];
|
||||
block[0x2C] = temp_block[0x29]; block[0x21] = temp_block[0x22];
|
||||
if(last_non_zero_p1 <= 24) goto end;
|
||||
block[0x1D] = temp_block[0x1B]; block[0x12] = temp_block[0x14];
|
||||
block[0x0E] = temp_block[0x0D]; block[0x03] = temp_block[0x06];
|
||||
block[0x07] = temp_block[0x07]; block[0x0B] = temp_block[0x0E];
|
||||
block[0x16] = temp_block[0x15]; block[0x1A] = temp_block[0x1C];
|
||||
if(last_non_zero_p1 <= 32) goto end;
|
||||
block[0x25] = temp_block[0x23]; block[0x29] = temp_block[0x2A];
|
||||
block[0x34] = temp_block[0x31]; block[0x38] = temp_block[0x38];
|
||||
block[0x3C] = temp_block[0x39]; block[0x31] = temp_block[0x32];
|
||||
block[0x2D] = temp_block[0x2B]; block[0x22] = temp_block[0x24];
|
||||
if(last_non_zero_p1 <= 40) goto end;
|
||||
block[0x1E] = temp_block[0x1D]; block[0x13] = temp_block[0x16];
|
||||
block[0x0F] = temp_block[0x0F]; block[0x17] = temp_block[0x17];
|
||||
block[0x1B] = temp_block[0x1E]; block[0x26] = temp_block[0x25];
|
||||
block[0x2A] = temp_block[0x2C]; block[0x35] = temp_block[0x33];
|
||||
if(last_non_zero_p1 <= 48) goto end;
|
||||
block[0x39] = temp_block[0x3A]; block[0x3D] = temp_block[0x3B];
|
||||
block[0x32] = temp_block[0x34]; block[0x2E] = temp_block[0x2D];
|
||||
block[0x23] = temp_block[0x26]; block[0x1F] = temp_block[0x1F];
|
||||
block[0x27] = temp_block[0x27]; block[0x2B] = temp_block[0x2E];
|
||||
if(last_non_zero_p1 <= 56) goto end;
|
||||
block[0x36] = temp_block[0x35]; block[0x3A] = temp_block[0x3C];
|
||||
block[0x3E] = temp_block[0x3D]; block[0x33] = temp_block[0x36];
|
||||
block[0x2F] = temp_block[0x2F]; block[0x37] = temp_block[0x37];
|
||||
block[0x3B] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F];
|
||||
}else{
|
||||
if(last_non_zero_p1 <= 1) goto end;
|
||||
block[0x01] = temp_block[0x01];
|
||||
block[0x08] = temp_block[0x08]; block[0x10] = temp_block[0x10];
|
||||
if(last_non_zero_p1 <= 4) goto end;
|
||||
block[0x09] = temp_block[0x09]; block[0x02] = temp_block[0x02];
|
||||
block[0x03] = temp_block[0x03];
|
||||
if(last_non_zero_p1 <= 7) goto end;
|
||||
block[0x0A] = temp_block[0x0A]; block[0x11] = temp_block[0x11];
|
||||
block[0x18] = temp_block[0x18]; block[0x20] = temp_block[0x20];
|
||||
if(last_non_zero_p1 <= 11) goto end;
|
||||
block[0x19] = temp_block[0x19];
|
||||
block[0x12] = temp_block[0x12]; block[0x0B] = temp_block[0x0B];
|
||||
block[0x04] = temp_block[0x04]; block[0x05] = temp_block[0x05];
|
||||
if(last_non_zero_p1 <= 16) goto end;
|
||||
block[0x0C] = temp_block[0x0C]; block[0x13] = temp_block[0x13];
|
||||
block[0x1A] = temp_block[0x1A]; block[0x21] = temp_block[0x21];
|
||||
block[0x28] = temp_block[0x28]; block[0x30] = temp_block[0x30];
|
||||
block[0x29] = temp_block[0x29]; block[0x22] = temp_block[0x22];
|
||||
if(last_non_zero_p1 <= 24) goto end;
|
||||
block[0x1B] = temp_block[0x1B]; block[0x14] = temp_block[0x14];
|
||||
block[0x0D] = temp_block[0x0D]; block[0x06] = temp_block[0x06];
|
||||
block[0x07] = temp_block[0x07]; block[0x0E] = temp_block[0x0E];
|
||||
block[0x15] = temp_block[0x15]; block[0x1C] = temp_block[0x1C];
|
||||
if(last_non_zero_p1 <= 32) goto end;
|
||||
block[0x23] = temp_block[0x23]; block[0x2A] = temp_block[0x2A];
|
||||
block[0x31] = temp_block[0x31]; block[0x38] = temp_block[0x38];
|
||||
block[0x39] = temp_block[0x39]; block[0x32] = temp_block[0x32];
|
||||
block[0x2B] = temp_block[0x2B]; block[0x24] = temp_block[0x24];
|
||||
if(last_non_zero_p1 <= 40) goto end;
|
||||
block[0x1D] = temp_block[0x1D]; block[0x16] = temp_block[0x16];
|
||||
block[0x0F] = temp_block[0x0F]; block[0x17] = temp_block[0x17];
|
||||
block[0x1E] = temp_block[0x1E]; block[0x25] = temp_block[0x25];
|
||||
block[0x2C] = temp_block[0x2C]; block[0x33] = temp_block[0x33];
|
||||
if(last_non_zero_p1 <= 48) goto end;
|
||||
block[0x3A] = temp_block[0x3A]; block[0x3B] = temp_block[0x3B];
|
||||
block[0x34] = temp_block[0x34]; block[0x2D] = temp_block[0x2D];
|
||||
block[0x26] = temp_block[0x26]; block[0x1F] = temp_block[0x1F];
|
||||
block[0x27] = temp_block[0x27]; block[0x2E] = temp_block[0x2E];
|
||||
if(last_non_zero_p1 <= 56) goto end;
|
||||
block[0x35] = temp_block[0x35]; block[0x3C] = temp_block[0x3C];
|
||||
block[0x3D] = temp_block[0x3D]; block[0x36] = temp_block[0x36];
|
||||
block[0x2F] = temp_block[0x2F]; block[0x37] = temp_block[0x37];
|
||||
block[0x3E] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F];
|
||||
}
|
||||
end:
|
||||
/*
|
||||
for(i=0; i<last_non_zero_p1; i++)
|
||||
{
|
||||
int j= zigzag_direct_noperm[i];
|
||||
block[block_permute_op(j)]= temp_block[j];
|
||||
}
|
||||
*/
|
||||
|
||||
return last_non_zero_p1 - 1;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,871 @@
|
||||
/*
|
||||
* MMX and SSE2 optimized snow DSP utils
|
||||
* Copyright (c) 2005-2006 Robert Edele <[email protected]>
|
||||
*
|
||||
* 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 "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/snow.h"
|
||||
|
||||
void ff_snow_horizontal_compose97i_sse2(IDWTELEM *b, int width){
|
||||
const int w2= (width+1)>>1;
|
||||
DECLARE_ALIGNED_16(IDWTELEM, temp[width>>1]);
|
||||
const int w_l= (width>>1);
|
||||
const int w_r= w2 - 1;
|
||||
int i;
|
||||
|
||||
{ // Lift 0
|
||||
IDWTELEM * const ref = b + w2 - 1;
|
||||
IDWTELEM b_0 = b[0]; //By allowing the first entry in b[0] to be calculated twice
|
||||
// (the first time erroneously), we allow the SSE2 code to run an extra pass.
|
||||
// The savings in code and time are well worth having to store this value and
|
||||
// calculate b[0] correctly afterwards.
|
||||
|
||||
i = 0;
|
||||
asm volatile(
|
||||
"pcmpeqd %%xmm7, %%xmm7 \n\t"
|
||||
"pcmpeqd %%xmm3, %%xmm3 \n\t"
|
||||
"psllw $1, %%xmm3 \n\t"
|
||||
"paddw %%xmm7, %%xmm3 \n\t"
|
||||
"psllw $13, %%xmm3 \n\t"
|
||||
::);
|
||||
for(; i<w_l-15; i+=16){
|
||||
asm volatile(
|
||||
"movdqu (%1), %%xmm1 \n\t"
|
||||
"movdqu 16(%1), %%xmm5 \n\t"
|
||||
"movdqu 2(%1), %%xmm2 \n\t"
|
||||
"movdqu 18(%1), %%xmm6 \n\t"
|
||||
"paddw %%xmm1, %%xmm2 \n\t"
|
||||
"paddw %%xmm5, %%xmm6 \n\t"
|
||||
"paddw %%xmm7, %%xmm2 \n\t"
|
||||
"paddw %%xmm7, %%xmm6 \n\t"
|
||||
"pmulhw %%xmm3, %%xmm2 \n\t"
|
||||
"pmulhw %%xmm3, %%xmm6 \n\t"
|
||||
"paddw (%0), %%xmm2 \n\t"
|
||||
"paddw 16(%0), %%xmm6 \n\t"
|
||||
"movdqa %%xmm2, (%0) \n\t"
|
||||
"movdqa %%xmm6, 16(%0) \n\t"
|
||||
:: "r"(&b[i]), "r"(&ref[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS);
|
||||
b[0] = b_0 - ((W_DM * 2 * ref[1]+W_DO)>>W_DS);
|
||||
}
|
||||
|
||||
{ // Lift 1
|
||||
IDWTELEM * const dst = b+w2;
|
||||
|
||||
i = 0;
|
||||
for(; (((x86_reg)&dst[i]) & 0x1F) && i<w_r; i++){
|
||||
dst[i] = dst[i] - (b[i] + b[i + 1]);
|
||||
}
|
||||
for(; i<w_r-15; i+=16){
|
||||
asm volatile(
|
||||
"movdqu (%1), %%xmm1 \n\t"
|
||||
"movdqu 16(%1), %%xmm5 \n\t"
|
||||
"movdqu 2(%1), %%xmm2 \n\t"
|
||||
"movdqu 18(%1), %%xmm6 \n\t"
|
||||
"paddw %%xmm1, %%xmm2 \n\t"
|
||||
"paddw %%xmm5, %%xmm6 \n\t"
|
||||
"movdqa (%0), %%xmm0 \n\t"
|
||||
"movdqa 16(%0), %%xmm4 \n\t"
|
||||
"psubw %%xmm2, %%xmm0 \n\t"
|
||||
"psubw %%xmm6, %%xmm4 \n\t"
|
||||
"movdqa %%xmm0, (%0) \n\t"
|
||||
"movdqa %%xmm4, 16(%0) \n\t"
|
||||
:: "r"(&dst[i]), "r"(&b[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS);
|
||||
}
|
||||
|
||||
{ // Lift 2
|
||||
IDWTELEM * const ref = b+w2 - 1;
|
||||
IDWTELEM b_0 = b[0];
|
||||
|
||||
i = 0;
|
||||
asm volatile(
|
||||
"psllw $15, %%xmm7 \n\t"
|
||||
"pcmpeqw %%xmm6, %%xmm6 \n\t"
|
||||
"psrlw $13, %%xmm6 \n\t"
|
||||
"paddw %%xmm7, %%xmm6 \n\t"
|
||||
::);
|
||||
for(; i<w_l-15; i+=16){
|
||||
asm volatile(
|
||||
"movdqu (%1), %%xmm0 \n\t"
|
||||
"movdqu 16(%1), %%xmm4 \n\t"
|
||||
"movdqu 2(%1), %%xmm1 \n\t"
|
||||
"movdqu 18(%1), %%xmm5 \n\t" //FIXME try aligned reads and shifts
|
||||
"paddw %%xmm6, %%xmm0 \n\t"
|
||||
"paddw %%xmm6, %%xmm4 \n\t"
|
||||
"paddw %%xmm7, %%xmm1 \n\t"
|
||||
"paddw %%xmm7, %%xmm5 \n\t"
|
||||
"pavgw %%xmm1, %%xmm0 \n\t"
|
||||
"pavgw %%xmm5, %%xmm4 \n\t"
|
||||
"psubw %%xmm7, %%xmm0 \n\t"
|
||||
"psubw %%xmm7, %%xmm4 \n\t"
|
||||
"psraw $1, %%xmm0 \n\t"
|
||||
"psraw $1, %%xmm4 \n\t"
|
||||
"movdqa (%0), %%xmm1 \n\t"
|
||||
"movdqa 16(%0), %%xmm5 \n\t"
|
||||
"paddw %%xmm1, %%xmm0 \n\t"
|
||||
"paddw %%xmm5, %%xmm4 \n\t"
|
||||
"psraw $2, %%xmm0 \n\t"
|
||||
"psraw $2, %%xmm4 \n\t"
|
||||
"paddw %%xmm1, %%xmm0 \n\t"
|
||||
"paddw %%xmm5, %%xmm4 \n\t"
|
||||
"movdqa %%xmm0, (%0) \n\t"
|
||||
"movdqa %%xmm4, 16(%0) \n\t"
|
||||
:: "r"(&b[i]), "r"(&ref[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l);
|
||||
b[0] = b_0 + ((2 * ref[1] + W_BO-1 + 4 * b_0) >> W_BS);
|
||||
}
|
||||
|
||||
{ // Lift 3
|
||||
IDWTELEM * const src = b+w2;
|
||||
|
||||
i = 0;
|
||||
for(; (((x86_reg)&temp[i]) & 0x1F) && i<w_r; i++){
|
||||
temp[i] = src[i] - ((-W_AM*(b[i] + b[i+1]))>>W_AS);
|
||||
}
|
||||
for(; i<w_r-7; i+=8){
|
||||
asm volatile(
|
||||
"movdqu 2(%1), %%xmm2 \n\t"
|
||||
"movdqu 18(%1), %%xmm6 \n\t"
|
||||
"paddw (%1), %%xmm2 \n\t"
|
||||
"paddw 16(%1), %%xmm6 \n\t"
|
||||
"movdqu (%0), %%xmm0 \n\t"
|
||||
"movdqu 16(%0), %%xmm4 \n\t"
|
||||
"paddw %%xmm2, %%xmm0 \n\t"
|
||||
"paddw %%xmm6, %%xmm4 \n\t"
|
||||
"psraw $1, %%xmm2 \n\t"
|
||||
"psraw $1, %%xmm6 \n\t"
|
||||
"paddw %%xmm0, %%xmm2 \n\t"
|
||||
"paddw %%xmm4, %%xmm6 \n\t"
|
||||
"movdqa %%xmm2, (%2) \n\t"
|
||||
"movdqa %%xmm6, 16(%2) \n\t"
|
||||
:: "r"(&src[i]), "r"(&b[i]), "r"(&temp[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -W_AM, W_AO+1, W_AS);
|
||||
}
|
||||
|
||||
{
|
||||
snow_interleave_line_header(&i, width, b, temp);
|
||||
|
||||
for (; (i & 0x3E) != 0x3E; i-=2){
|
||||
b[i+1] = temp[i>>1];
|
||||
b[i] = b[i>>1];
|
||||
}
|
||||
for (i-=62; i>=0; i-=64){
|
||||
asm volatile(
|
||||
"movdqa (%1), %%xmm0 \n\t"
|
||||
"movdqa 16(%1), %%xmm2 \n\t"
|
||||
"movdqa 32(%1), %%xmm4 \n\t"
|
||||
"movdqa 48(%1), %%xmm6 \n\t"
|
||||
"movdqa (%1), %%xmm1 \n\t"
|
||||
"movdqa 16(%1), %%xmm3 \n\t"
|
||||
"movdqa 32(%1), %%xmm5 \n\t"
|
||||
"movdqa 48(%1), %%xmm7 \n\t"
|
||||
"punpcklwd (%2), %%xmm0 \n\t"
|
||||
"punpcklwd 16(%2), %%xmm2 \n\t"
|
||||
"punpcklwd 32(%2), %%xmm4 \n\t"
|
||||
"punpcklwd 48(%2), %%xmm6 \n\t"
|
||||
"movdqa %%xmm0, (%0) \n\t"
|
||||
"movdqa %%xmm2, 32(%0) \n\t"
|
||||
"movdqa %%xmm4, 64(%0) \n\t"
|
||||
"movdqa %%xmm6, 96(%0) \n\t"
|
||||
"punpckhwd (%2), %%xmm1 \n\t"
|
||||
"punpckhwd 16(%2), %%xmm3 \n\t"
|
||||
"punpckhwd 32(%2), %%xmm5 \n\t"
|
||||
"punpckhwd 48(%2), %%xmm7 \n\t"
|
||||
"movdqa %%xmm1, 16(%0) \n\t"
|
||||
"movdqa %%xmm3, 48(%0) \n\t"
|
||||
"movdqa %%xmm5, 80(%0) \n\t"
|
||||
"movdqa %%xmm7, 112(%0) \n\t"
|
||||
:: "r"(&(b)[i]), "r"(&(b)[i>>1]), "r"(&(temp)[i>>1])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ff_snow_horizontal_compose97i_mmx(IDWTELEM *b, int width){
|
||||
const int w2= (width+1)>>1;
|
||||
IDWTELEM temp[width >> 1];
|
||||
const int w_l= (width>>1);
|
||||
const int w_r= w2 - 1;
|
||||
int i;
|
||||
|
||||
{ // Lift 0
|
||||
IDWTELEM * const ref = b + w2 - 1;
|
||||
|
||||
i = 1;
|
||||
b[0] = b[0] - ((W_DM * 2 * ref[1]+W_DO)>>W_DS);
|
||||
asm volatile(
|
||||
"pcmpeqw %%mm7, %%mm7 \n\t"
|
||||
"pcmpeqw %%mm3, %%mm3 \n\t"
|
||||
"psllw $1, %%mm3 \n\t"
|
||||
"paddw %%mm7, %%mm3 \n\t"
|
||||
"psllw $13, %%mm3 \n\t"
|
||||
::);
|
||||
for(; i<w_l-7; i+=8){
|
||||
asm volatile(
|
||||
"movq (%1), %%mm2 \n\t"
|
||||
"movq 8(%1), %%mm6 \n\t"
|
||||
"paddw 2(%1), %%mm2 \n\t"
|
||||
"paddw 10(%1), %%mm6 \n\t"
|
||||
"paddw %%mm7, %%mm2 \n\t"
|
||||
"paddw %%mm7, %%mm6 \n\t"
|
||||
"pmulhw %%mm3, %%mm2 \n\t"
|
||||
"pmulhw %%mm3, %%mm6 \n\t"
|
||||
"paddw (%0), %%mm2 \n\t"
|
||||
"paddw 8(%0), %%mm6 \n\t"
|
||||
"movq %%mm2, (%0) \n\t"
|
||||
"movq %%mm6, 8(%0) \n\t"
|
||||
:: "r"(&b[i]), "r"(&ref[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS);
|
||||
}
|
||||
|
||||
{ // Lift 1
|
||||
IDWTELEM * const dst = b+w2;
|
||||
|
||||
i = 0;
|
||||
for(; i<w_r-7; i+=8){
|
||||
asm volatile(
|
||||
"movq (%1), %%mm2 \n\t"
|
||||
"movq 8(%1), %%mm6 \n\t"
|
||||
"paddw 2(%1), %%mm2 \n\t"
|
||||
"paddw 10(%1), %%mm6 \n\t"
|
||||
"movq (%0), %%mm0 \n\t"
|
||||
"movq 8(%0), %%mm4 \n\t"
|
||||
"psubw %%mm2, %%mm0 \n\t"
|
||||
"psubw %%mm6, %%mm4 \n\t"
|
||||
"movq %%mm0, (%0) \n\t"
|
||||
"movq %%mm4, 8(%0) \n\t"
|
||||
:: "r"(&dst[i]), "r"(&b[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS);
|
||||
}
|
||||
|
||||
{ // Lift 2
|
||||
IDWTELEM * const ref = b+w2 - 1;
|
||||
|
||||
i = 1;
|
||||
b[0] = b[0] + (((2 * ref[1] + W_BO) + 4 * b[0]) >> W_BS);
|
||||
asm volatile(
|
||||
"psllw $15, %%mm7 \n\t"
|
||||
"pcmpeqw %%mm6, %%mm6 \n\t"
|
||||
"psrlw $13, %%mm6 \n\t"
|
||||
"paddw %%mm7, %%mm6 \n\t"
|
||||
::);
|
||||
for(; i<w_l-7; i+=8){
|
||||
asm volatile(
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm4 \n\t"
|
||||
"movq 2(%1), %%mm1 \n\t"
|
||||
"movq 10(%1), %%mm5 \n\t"
|
||||
"paddw %%mm6, %%mm0 \n\t"
|
||||
"paddw %%mm6, %%mm4 \n\t"
|
||||
"paddw %%mm7, %%mm1 \n\t"
|
||||
"paddw %%mm7, %%mm5 \n\t"
|
||||
"pavgw %%mm1, %%mm0 \n\t"
|
||||
"pavgw %%mm5, %%mm4 \n\t"
|
||||
"psubw %%mm7, %%mm0 \n\t"
|
||||
"psubw %%mm7, %%mm4 \n\t"
|
||||
"psraw $1, %%mm0 \n\t"
|
||||
"psraw $1, %%mm4 \n\t"
|
||||
"movq (%0), %%mm1 \n\t"
|
||||
"movq 8(%0), %%mm5 \n\t"
|
||||
"paddw %%mm1, %%mm0 \n\t"
|
||||
"paddw %%mm5, %%mm4 \n\t"
|
||||
"psraw $2, %%mm0 \n\t"
|
||||
"psraw $2, %%mm4 \n\t"
|
||||
"paddw %%mm1, %%mm0 \n\t"
|
||||
"paddw %%mm5, %%mm4 \n\t"
|
||||
"movq %%mm0, (%0) \n\t"
|
||||
"movq %%mm4, 8(%0) \n\t"
|
||||
:: "r"(&b[i]), "r"(&ref[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l);
|
||||
}
|
||||
|
||||
{ // Lift 3
|
||||
IDWTELEM * const src = b+w2;
|
||||
i = 0;
|
||||
|
||||
for(; i<w_r-7; i+=8){
|
||||
asm volatile(
|
||||
"movq 2(%1), %%mm2 \n\t"
|
||||
"movq 10(%1), %%mm6 \n\t"
|
||||
"paddw (%1), %%mm2 \n\t"
|
||||
"paddw 8(%1), %%mm6 \n\t"
|
||||
"movq (%0), %%mm0 \n\t"
|
||||
"movq 8(%0), %%mm4 \n\t"
|
||||
"paddw %%mm2, %%mm0 \n\t"
|
||||
"paddw %%mm6, %%mm4 \n\t"
|
||||
"psraw $1, %%mm2 \n\t"
|
||||
"psraw $1, %%mm6 \n\t"
|
||||
"paddw %%mm0, %%mm2 \n\t"
|
||||
"paddw %%mm4, %%mm6 \n\t"
|
||||
"movq %%mm2, (%2) \n\t"
|
||||
"movq %%mm6, 8(%2) \n\t"
|
||||
:: "r"(&src[i]), "r"(&b[i]), "r"(&temp[i])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -W_AM, W_AO+1, W_AS);
|
||||
}
|
||||
|
||||
{
|
||||
snow_interleave_line_header(&i, width, b, temp);
|
||||
|
||||
for (; (i & 0x1E) != 0x1E; i-=2){
|
||||
b[i+1] = temp[i>>1];
|
||||
b[i] = b[i>>1];
|
||||
}
|
||||
for (i-=30; i>=0; i-=32){
|
||||
asm volatile(
|
||||
"movq (%1), %%mm0 \n\t"
|
||||
"movq 8(%1), %%mm2 \n\t"
|
||||
"movq 16(%1), %%mm4 \n\t"
|
||||
"movq 24(%1), %%mm6 \n\t"
|
||||
"movq (%1), %%mm1 \n\t"
|
||||
"movq 8(%1), %%mm3 \n\t"
|
||||
"movq 16(%1), %%mm5 \n\t"
|
||||
"movq 24(%1), %%mm7 \n\t"
|
||||
"punpcklwd (%2), %%mm0 \n\t"
|
||||
"punpcklwd 8(%2), %%mm2 \n\t"
|
||||
"punpcklwd 16(%2), %%mm4 \n\t"
|
||||
"punpcklwd 24(%2), %%mm6 \n\t"
|
||||
"movq %%mm0, (%0) \n\t"
|
||||
"movq %%mm2, 16(%0) \n\t"
|
||||
"movq %%mm4, 32(%0) \n\t"
|
||||
"movq %%mm6, 48(%0) \n\t"
|
||||
"punpckhwd (%2), %%mm1 \n\t"
|
||||
"punpckhwd 8(%2), %%mm3 \n\t"
|
||||
"punpckhwd 16(%2), %%mm5 \n\t"
|
||||
"punpckhwd 24(%2), %%mm7 \n\t"
|
||||
"movq %%mm1, 8(%0) \n\t"
|
||||
"movq %%mm3, 24(%0) \n\t"
|
||||
"movq %%mm5, 40(%0) \n\t"
|
||||
"movq %%mm7, 56(%0) \n\t"
|
||||
:: "r"(&b[i]), "r"(&b[i>>1]), "r"(&temp[i>>1])
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_7REGS
|
||||
#define snow_vertical_compose_sse2_load_add(op,r,t0,t1,t2,t3)\
|
||||
""op" ("r",%%"REG_d"), %%"t0" \n\t"\
|
||||
""op" 16("r",%%"REG_d"), %%"t1" \n\t"\
|
||||
""op" 32("r",%%"REG_d"), %%"t2" \n\t"\
|
||||
""op" 48("r",%%"REG_d"), %%"t3" \n\t"
|
||||
|
||||
#define snow_vertical_compose_sse2_load(r,t0,t1,t2,t3)\
|
||||
snow_vertical_compose_sse2_load_add("movdqa",r,t0,t1,t2,t3)
|
||||
|
||||
#define snow_vertical_compose_sse2_add(r,t0,t1,t2,t3)\
|
||||
snow_vertical_compose_sse2_load_add("paddw",r,t0,t1,t2,t3)
|
||||
|
||||
#define snow_vertical_compose_r2r_sub(s0,s1,s2,s3,t0,t1,t2,t3)\
|
||||
"psubw %%"s0", %%"t0" \n\t"\
|
||||
"psubw %%"s1", %%"t1" \n\t"\
|
||||
"psubw %%"s2", %%"t2" \n\t"\
|
||||
"psubw %%"s3", %%"t3" \n\t"
|
||||
|
||||
#define snow_vertical_compose_sse2_store(w,s0,s1,s2,s3)\
|
||||
"movdqa %%"s0", ("w",%%"REG_d") \n\t"\
|
||||
"movdqa %%"s1", 16("w",%%"REG_d") \n\t"\
|
||||
"movdqa %%"s2", 32("w",%%"REG_d") \n\t"\
|
||||
"movdqa %%"s3", 48("w",%%"REG_d") \n\t"
|
||||
|
||||
#define snow_vertical_compose_sra(n,t0,t1,t2,t3)\
|
||||
"psraw $"n", %%"t0" \n\t"\
|
||||
"psraw $"n", %%"t1" \n\t"\
|
||||
"psraw $"n", %%"t2" \n\t"\
|
||||
"psraw $"n", %%"t3" \n\t"
|
||||
|
||||
#define snow_vertical_compose_r2r_add(s0,s1,s2,s3,t0,t1,t2,t3)\
|
||||
"paddw %%"s0", %%"t0" \n\t"\
|
||||
"paddw %%"s1", %%"t1" \n\t"\
|
||||
"paddw %%"s2", %%"t2" \n\t"\
|
||||
"paddw %%"s3", %%"t3" \n\t"
|
||||
|
||||
#define snow_vertical_compose_r2r_pmulhw(s0,s1,s2,s3,t0,t1,t2,t3)\
|
||||
"pmulhw %%"s0", %%"t0" \n\t"\
|
||||
"pmulhw %%"s1", %%"t1" \n\t"\
|
||||
"pmulhw %%"s2", %%"t2" \n\t"\
|
||||
"pmulhw %%"s3", %%"t3" \n\t"
|
||||
|
||||
#define snow_vertical_compose_sse2_move(s0,s1,s2,s3,t0,t1,t2,t3)\
|
||||
"movdqa %%"s0", %%"t0" \n\t"\
|
||||
"movdqa %%"s1", %%"t1" \n\t"\
|
||||
"movdqa %%"s2", %%"t2" \n\t"\
|
||||
"movdqa %%"s3", %%"t3" \n\t"
|
||||
|
||||
void ff_snow_vertical_compose97i_sse2(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){
|
||||
x86_reg i = width;
|
||||
|
||||
while(i & 0x1F)
|
||||
{
|
||||
i--;
|
||||
b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS;
|
||||
b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS;
|
||||
b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS;
|
||||
b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS;
|
||||
}
|
||||
i+=i;
|
||||
|
||||
asm volatile (
|
||||
"jmp 2f \n\t"
|
||||
"1: \n\t"
|
||||
snow_vertical_compose_sse2_load("%4","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_add("%6","xmm0","xmm2","xmm4","xmm6")
|
||||
|
||||
|
||||
"pcmpeqw %%xmm0, %%xmm0 \n\t"
|
||||
"pcmpeqw %%xmm2, %%xmm2 \n\t"
|
||||
"paddw %%xmm2, %%xmm2 \n\t"
|
||||
"paddw %%xmm0, %%xmm2 \n\t"
|
||||
"psllw $13, %%xmm2 \n\t"
|
||||
snow_vertical_compose_r2r_add("xmm0","xmm0","xmm0","xmm0","xmm1","xmm3","xmm5","xmm7")
|
||||
snow_vertical_compose_r2r_pmulhw("xmm2","xmm2","xmm2","xmm2","xmm1","xmm3","xmm5","xmm7")
|
||||
snow_vertical_compose_sse2_add("%5","xmm1","xmm3","xmm5","xmm7")
|
||||
snow_vertical_compose_sse2_store("%5","xmm1","xmm3","xmm5","xmm7")
|
||||
snow_vertical_compose_sse2_load("%4","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_add("%3","xmm1","xmm3","xmm5","xmm7")
|
||||
snow_vertical_compose_r2r_sub("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_store("%4","xmm0","xmm2","xmm4","xmm6")
|
||||
|
||||
"pcmpeqw %%xmm7, %%xmm7 \n\t"
|
||||
"pcmpeqw %%xmm5, %%xmm5 \n\t"
|
||||
"psllw $15, %%xmm7 \n\t"
|
||||
"psrlw $13, %%xmm5 \n\t"
|
||||
"paddw %%xmm7, %%xmm5 \n\t"
|
||||
snow_vertical_compose_r2r_add("xmm5","xmm5","xmm5","xmm5","xmm0","xmm2","xmm4","xmm6")
|
||||
"movq (%2,%%"REG_d"), %%xmm1 \n\t"
|
||||
"movq 8(%2,%%"REG_d"), %%xmm3 \n\t"
|
||||
"paddw %%xmm7, %%xmm1 \n\t"
|
||||
"paddw %%xmm7, %%xmm3 \n\t"
|
||||
"pavgw %%xmm1, %%xmm0 \n\t"
|
||||
"pavgw %%xmm3, %%xmm2 \n\t"
|
||||
"movq 16(%2,%%"REG_d"), %%xmm1 \n\t"
|
||||
"movq 24(%2,%%"REG_d"), %%xmm3 \n\t"
|
||||
"paddw %%xmm7, %%xmm1 \n\t"
|
||||
"paddw %%xmm7, %%xmm3 \n\t"
|
||||
"pavgw %%xmm1, %%xmm4 \n\t"
|
||||
"pavgw %%xmm3, %%xmm6 \n\t"
|
||||
snow_vertical_compose_r2r_sub("xmm7","xmm7","xmm7","xmm7","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sra("1","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_add("%3","xmm0","xmm2","xmm4","xmm6")
|
||||
|
||||
snow_vertical_compose_sra("2","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_add("%3","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_store("%3","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_add("%1","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_move("xmm0","xmm2","xmm4","xmm6","xmm1","xmm3","xmm5","xmm7")
|
||||
snow_vertical_compose_sra("1","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_r2r_add("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_add("%2","xmm0","xmm2","xmm4","xmm6")
|
||||
snow_vertical_compose_sse2_store("%2","xmm0","xmm2","xmm4","xmm6")
|
||||
|
||||
"2: \n\t"
|
||||
"sub $64, %%"REG_d" \n\t"
|
||||
"jge 1b \n\t"
|
||||
:"+d"(i)
|
||||
:"r"(b0),"r"(b1),"r"(b2),"r"(b3),"r"(b4),"r"(b5));
|
||||
}
|
||||
|
||||
#define snow_vertical_compose_mmx_load_add(op,r,t0,t1,t2,t3)\
|
||||
""op" ("r",%%"REG_d"), %%"t0" \n\t"\
|
||||
""op" 8("r",%%"REG_d"), %%"t1" \n\t"\
|
||||
""op" 16("r",%%"REG_d"), %%"t2" \n\t"\
|
||||
""op" 24("r",%%"REG_d"), %%"t3" \n\t"
|
||||
|
||||
#define snow_vertical_compose_mmx_load(r,t0,t1,t2,t3)\
|
||||
snow_vertical_compose_mmx_load_add("movq",r,t0,t1,t2,t3)
|
||||
|
||||
#define snow_vertical_compose_mmx_add(r,t0,t1,t2,t3)\
|
||||
snow_vertical_compose_mmx_load_add("paddw",r,t0,t1,t2,t3)
|
||||
|
||||
#define snow_vertical_compose_mmx_store(w,s0,s1,s2,s3)\
|
||||
"movq %%"s0", ("w",%%"REG_d") \n\t"\
|
||||
"movq %%"s1", 8("w",%%"REG_d") \n\t"\
|
||||
"movq %%"s2", 16("w",%%"REG_d") \n\t"\
|
||||
"movq %%"s3", 24("w",%%"REG_d") \n\t"
|
||||
|
||||
#define snow_vertical_compose_mmx_move(s0,s1,s2,s3,t0,t1,t2,t3)\
|
||||
"movq %%"s0", %%"t0" \n\t"\
|
||||
"movq %%"s1", %%"t1" \n\t"\
|
||||
"movq %%"s2", %%"t2" \n\t"\
|
||||
"movq %%"s3", %%"t3" \n\t"
|
||||
|
||||
|
||||
void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){
|
||||
x86_reg i = width;
|
||||
while(i & 15)
|
||||
{
|
||||
i--;
|
||||
b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS;
|
||||
b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS;
|
||||
b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS;
|
||||
b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS;
|
||||
}
|
||||
i+=i;
|
||||
asm volatile(
|
||||
"jmp 2f \n\t"
|
||||
"1: \n\t"
|
||||
|
||||
snow_vertical_compose_mmx_load("%4","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_mmx_add("%6","mm1","mm3","mm5","mm7")
|
||||
"pcmpeqw %%mm0, %%mm0 \n\t"
|
||||
"pcmpeqw %%mm2, %%mm2 \n\t"
|
||||
"paddw %%mm2, %%mm2 \n\t"
|
||||
"paddw %%mm0, %%mm2 \n\t"
|
||||
"psllw $13, %%mm2 \n\t"
|
||||
snow_vertical_compose_r2r_add("mm0","mm0","mm0","mm0","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_r2r_pmulhw("mm2","mm2","mm2","mm2","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_mmx_add("%5","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_mmx_store("%5","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_mmx_load("%4","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_add("%3","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_r2r_sub("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_store("%4","mm0","mm2","mm4","mm6")
|
||||
"pcmpeqw %%mm7, %%mm7 \n\t"
|
||||
"pcmpeqw %%mm5, %%mm5 \n\t"
|
||||
"psllw $15, %%mm7 \n\t"
|
||||
"psrlw $13, %%mm5 \n\t"
|
||||
"paddw %%mm7, %%mm5 \n\t"
|
||||
snow_vertical_compose_r2r_add("mm5","mm5","mm5","mm5","mm0","mm2","mm4","mm6")
|
||||
"movq (%2,%%"REG_d"), %%mm1 \n\t"
|
||||
"movq 8(%2,%%"REG_d"), %%mm3 \n\t"
|
||||
"paddw %%mm7, %%mm1 \n\t"
|
||||
"paddw %%mm7, %%mm3 \n\t"
|
||||
"pavgw %%mm1, %%mm0 \n\t"
|
||||
"pavgw %%mm3, %%mm2 \n\t"
|
||||
"movq 16(%2,%%"REG_d"), %%mm1 \n\t"
|
||||
"movq 24(%2,%%"REG_d"), %%mm3 \n\t"
|
||||
"paddw %%mm7, %%mm1 \n\t"
|
||||
"paddw %%mm7, %%mm3 \n\t"
|
||||
"pavgw %%mm1, %%mm4 \n\t"
|
||||
"pavgw %%mm3, %%mm6 \n\t"
|
||||
snow_vertical_compose_r2r_sub("mm7","mm7","mm7","mm7","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_sra("1","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_add("%3","mm0","mm2","mm4","mm6")
|
||||
|
||||
snow_vertical_compose_sra("2","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_add("%3","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_store("%3","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_add("%1","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_move("mm0","mm2","mm4","mm6","mm1","mm3","mm5","mm7")
|
||||
snow_vertical_compose_sra("1","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_r2r_add("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_add("%2","mm0","mm2","mm4","mm6")
|
||||
snow_vertical_compose_mmx_store("%2","mm0","mm2","mm4","mm6")
|
||||
|
||||
"2: \n\t"
|
||||
"sub $32, %%"REG_d" \n\t"
|
||||
"jge 1b \n\t"
|
||||
:"+d"(i)
|
||||
:"r"(b0),"r"(b1),"r"(b2),"r"(b3),"r"(b4),"r"(b5));
|
||||
}
|
||||
#endif //HAVE_7REGS
|
||||
|
||||
#define snow_inner_add_yblock_sse2_header \
|
||||
IDWTELEM * * dst_array = sb->line + src_y;\
|
||||
x86_reg tmp;\
|
||||
asm volatile(\
|
||||
"mov %7, %%"REG_c" \n\t"\
|
||||
"mov %6, %2 \n\t"\
|
||||
"mov %4, %%"REG_S" \n\t"\
|
||||
"pxor %%xmm7, %%xmm7 \n\t" /* 0 */\
|
||||
"pcmpeqd %%xmm3, %%xmm3 \n\t"\
|
||||
"psllw $15, %%xmm3 \n\t"\
|
||||
"psrlw $12, %%xmm3 \n\t" /* FRAC_BITS >> 1 */\
|
||||
"1: \n\t"\
|
||||
"mov %1, %%"REG_D" \n\t"\
|
||||
"mov (%%"REG_D"), %%"REG_D" \n\t"\
|
||||
"add %3, %%"REG_D" \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_sse2_start_8(out_reg1, out_reg2, ptr_offset, s_offset)\
|
||||
"mov "PTR_SIZE"*"ptr_offset"(%%"REG_a"), %%"REG_d"; \n\t"\
|
||||
"movq (%%"REG_d"), %%"out_reg1" \n\t"\
|
||||
"movq (%%"REG_d", %%"REG_c"), %%"out_reg2" \n\t"\
|
||||
"punpcklbw %%xmm7, %%"out_reg1" \n\t"\
|
||||
"punpcklbw %%xmm7, %%"out_reg2" \n\t"\
|
||||
"movq "s_offset"(%%"REG_S"), %%xmm0 \n\t"\
|
||||
"movq "s_offset"+16(%%"REG_S"), %%xmm4 \n\t"\
|
||||
"punpcklbw %%xmm7, %%xmm0 \n\t"\
|
||||
"punpcklbw %%xmm7, %%xmm4 \n\t"\
|
||||
"pmullw %%xmm0, %%"out_reg1" \n\t"\
|
||||
"pmullw %%xmm4, %%"out_reg2" \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_sse2_start_16(out_reg1, out_reg2, ptr_offset, s_offset)\
|
||||
"mov "PTR_SIZE"*"ptr_offset"(%%"REG_a"), %%"REG_d"; \n\t"\
|
||||
"movq (%%"REG_d"), %%"out_reg1" \n\t"\
|
||||
"movq 8(%%"REG_d"), %%"out_reg2" \n\t"\
|
||||
"punpcklbw %%xmm7, %%"out_reg1" \n\t"\
|
||||
"punpcklbw %%xmm7, %%"out_reg2" \n\t"\
|
||||
"movq "s_offset"(%%"REG_S"), %%xmm0 \n\t"\
|
||||
"movq "s_offset"+8(%%"REG_S"), %%xmm4 \n\t"\
|
||||
"punpcklbw %%xmm7, %%xmm0 \n\t"\
|
||||
"punpcklbw %%xmm7, %%xmm4 \n\t"\
|
||||
"pmullw %%xmm0, %%"out_reg1" \n\t"\
|
||||
"pmullw %%xmm4, %%"out_reg2" \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_sse2_accum_8(ptr_offset, s_offset) \
|
||||
snow_inner_add_yblock_sse2_start_8("xmm2", "xmm6", ptr_offset, s_offset)\
|
||||
"paddusw %%xmm2, %%xmm1 \n\t"\
|
||||
"paddusw %%xmm6, %%xmm5 \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_sse2_accum_16(ptr_offset, s_offset) \
|
||||
snow_inner_add_yblock_sse2_start_16("xmm2", "xmm6", ptr_offset, s_offset)\
|
||||
"paddusw %%xmm2, %%xmm1 \n\t"\
|
||||
"paddusw %%xmm6, %%xmm5 \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_sse2_end_common1\
|
||||
"add $32, %%"REG_S" \n\t"\
|
||||
"add %%"REG_c", %0 \n\t"\
|
||||
"add %%"REG_c", "PTR_SIZE"*3(%%"REG_a");\n\t"\
|
||||
"add %%"REG_c", "PTR_SIZE"*2(%%"REG_a");\n\t"\
|
||||
"add %%"REG_c", "PTR_SIZE"*1(%%"REG_a");\n\t"\
|
||||
"add %%"REG_c", (%%"REG_a") \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_sse2_end_common2\
|
||||
"jnz 1b \n\t"\
|
||||
:"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\
|
||||
:\
|
||||
"rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"((x86_reg)b_h),"m"((x86_reg)src_stride):\
|
||||
"%"REG_c"","%"REG_S"","%"REG_D"","%"REG_d"");
|
||||
|
||||
#define snow_inner_add_yblock_sse2_end_8\
|
||||
"sal $1, %%"REG_c" \n\t"\
|
||||
"add $"PTR_SIZE"*2, %1 \n\t"\
|
||||
snow_inner_add_yblock_sse2_end_common1\
|
||||
"sar $1, %%"REG_c" \n\t"\
|
||||
"sub $2, %2 \n\t"\
|
||||
snow_inner_add_yblock_sse2_end_common2
|
||||
|
||||
#define snow_inner_add_yblock_sse2_end_16\
|
||||
"add $"PTR_SIZE"*1, %1 \n\t"\
|
||||
snow_inner_add_yblock_sse2_end_common1\
|
||||
"dec %2 \n\t"\
|
||||
snow_inner_add_yblock_sse2_end_common2
|
||||
|
||||
static void inner_add_yblock_bw_8_obmc_16_bh_even_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h,
|
||||
int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){
|
||||
snow_inner_add_yblock_sse2_header
|
||||
snow_inner_add_yblock_sse2_start_8("xmm1", "xmm5", "3", "0")
|
||||
snow_inner_add_yblock_sse2_accum_8("2", "8")
|
||||
snow_inner_add_yblock_sse2_accum_8("1", "128")
|
||||
snow_inner_add_yblock_sse2_accum_8("0", "136")
|
||||
|
||||
"mov %0, %%"REG_d" \n\t"
|
||||
"movdqa (%%"REG_D"), %%xmm0 \n\t"
|
||||
"movdqa %%xmm1, %%xmm2 \n\t"
|
||||
|
||||
"punpckhwd %%xmm7, %%xmm1 \n\t"
|
||||
"punpcklwd %%xmm7, %%xmm2 \n\t"
|
||||
"paddd %%xmm2, %%xmm0 \n\t"
|
||||
"movdqa 16(%%"REG_D"), %%xmm2 \n\t"
|
||||
"paddd %%xmm1, %%xmm2 \n\t"
|
||||
"paddd %%xmm3, %%xmm0 \n\t"
|
||||
"paddd %%xmm3, %%xmm2 \n\t"
|
||||
|
||||
"mov %1, %%"REG_D" \n\t"
|
||||
"mov "PTR_SIZE"(%%"REG_D"), %%"REG_D";\n\t"
|
||||
"add %3, %%"REG_D" \n\t"
|
||||
|
||||
"movdqa (%%"REG_D"), %%xmm4 \n\t"
|
||||
"movdqa %%xmm5, %%xmm6 \n\t"
|
||||
"punpckhwd %%xmm7, %%xmm5 \n\t"
|
||||
"punpcklwd %%xmm7, %%xmm6 \n\t"
|
||||
"paddd %%xmm6, %%xmm4 \n\t"
|
||||
"movdqa 16(%%"REG_D"), %%xmm6 \n\t"
|
||||
"paddd %%xmm5, %%xmm6 \n\t"
|
||||
"paddd %%xmm3, %%xmm4 \n\t"
|
||||
"paddd %%xmm3, %%xmm6 \n\t"
|
||||
|
||||
"psrad $8, %%xmm0 \n\t" /* FRAC_BITS. */
|
||||
"psrad $8, %%xmm2 \n\t" /* FRAC_BITS. */
|
||||
"packssdw %%xmm2, %%xmm0 \n\t"
|
||||
"packuswb %%xmm7, %%xmm0 \n\t"
|
||||
"movq %%xmm0, (%%"REG_d") \n\t"
|
||||
|
||||
"psrad $8, %%xmm4 \n\t" /* FRAC_BITS. */
|
||||
"psrad $8, %%xmm6 \n\t" /* FRAC_BITS. */
|
||||
"packssdw %%xmm6, %%xmm4 \n\t"
|
||||
"packuswb %%xmm7, %%xmm4 \n\t"
|
||||
"movq %%xmm4, (%%"REG_d",%%"REG_c");\n\t"
|
||||
snow_inner_add_yblock_sse2_end_8
|
||||
}
|
||||
|
||||
static void inner_add_yblock_bw_16_obmc_32_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h,
|
||||
int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){
|
||||
snow_inner_add_yblock_sse2_header
|
||||
snow_inner_add_yblock_sse2_start_16("xmm1", "xmm5", "3", "0")
|
||||
snow_inner_add_yblock_sse2_accum_16("2", "16")
|
||||
snow_inner_add_yblock_sse2_accum_16("1", "512")
|
||||
snow_inner_add_yblock_sse2_accum_16("0", "528")
|
||||
|
||||
"mov %0, %%"REG_d" \n\t"
|
||||
"psrlw $4, %%xmm1 \n\t"
|
||||
"psrlw $4, %%xmm5 \n\t"
|
||||
"paddw (%%"REG_D"), %%xmm1 \n\t"
|
||||
"paddw 16(%%"REG_D"), %%xmm5 \n\t"
|
||||
"paddw %%xmm3, %%xmm1 \n\t"
|
||||
"paddw %%xmm3, %%xmm5 \n\t"
|
||||
"psraw $4, %%xmm1 \n\t" /* FRAC_BITS. */
|
||||
"psraw $4, %%xmm5 \n\t" /* FRAC_BITS. */
|
||||
"packuswb %%xmm5, %%xmm1 \n\t"
|
||||
|
||||
"movdqu %%xmm1, (%%"REG_d") \n\t"
|
||||
|
||||
snow_inner_add_yblock_sse2_end_16
|
||||
}
|
||||
|
||||
#define snow_inner_add_yblock_mmx_header \
|
||||
IDWTELEM * * dst_array = sb->line + src_y;\
|
||||
x86_reg tmp;\
|
||||
asm volatile(\
|
||||
"mov %7, %%"REG_c" \n\t"\
|
||||
"mov %6, %2 \n\t"\
|
||||
"mov %4, %%"REG_S" \n\t"\
|
||||
"pxor %%mm7, %%mm7 \n\t" /* 0 */\
|
||||
"pcmpeqd %%mm3, %%mm3 \n\t"\
|
||||
"psllw $15, %%mm3 \n\t"\
|
||||
"psrlw $12, %%mm3 \n\t" /* FRAC_BITS >> 1 */\
|
||||
"1: \n\t"\
|
||||
"mov %1, %%"REG_D" \n\t"\
|
||||
"mov (%%"REG_D"), %%"REG_D" \n\t"\
|
||||
"add %3, %%"REG_D" \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_mmx_start(out_reg1, out_reg2, ptr_offset, s_offset, d_offset)\
|
||||
"mov "PTR_SIZE"*"ptr_offset"(%%"REG_a"), %%"REG_d"; \n\t"\
|
||||
"movd "d_offset"(%%"REG_d"), %%"out_reg1" \n\t"\
|
||||
"movd "d_offset"+4(%%"REG_d"), %%"out_reg2" \n\t"\
|
||||
"punpcklbw %%mm7, %%"out_reg1" \n\t"\
|
||||
"punpcklbw %%mm7, %%"out_reg2" \n\t"\
|
||||
"movd "s_offset"(%%"REG_S"), %%mm0 \n\t"\
|
||||
"movd "s_offset"+4(%%"REG_S"), %%mm4 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm0 \n\t"\
|
||||
"punpcklbw %%mm7, %%mm4 \n\t"\
|
||||
"pmullw %%mm0, %%"out_reg1" \n\t"\
|
||||
"pmullw %%mm4, %%"out_reg2" \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_mmx_accum(ptr_offset, s_offset, d_offset) \
|
||||
snow_inner_add_yblock_mmx_start("mm2", "mm6", ptr_offset, s_offset, d_offset)\
|
||||
"paddusw %%mm2, %%mm1 \n\t"\
|
||||
"paddusw %%mm6, %%mm5 \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_mmx_mix(read_offset, write_offset)\
|
||||
"mov %0, %%"REG_d" \n\t"\
|
||||
"psrlw $4, %%mm1 \n\t"\
|
||||
"psrlw $4, %%mm5 \n\t"\
|
||||
"paddw "read_offset"(%%"REG_D"), %%mm1 \n\t"\
|
||||
"paddw "read_offset"+8(%%"REG_D"), %%mm5 \n\t"\
|
||||
"paddw %%mm3, %%mm1 \n\t"\
|
||||
"paddw %%mm3, %%mm5 \n\t"\
|
||||
"psraw $4, %%mm1 \n\t"\
|
||||
"psraw $4, %%mm5 \n\t"\
|
||||
"packuswb %%mm5, %%mm1 \n\t"\
|
||||
"movq %%mm1, "write_offset"(%%"REG_d") \n\t"
|
||||
|
||||
#define snow_inner_add_yblock_mmx_end(s_step)\
|
||||
"add $"s_step", %%"REG_S" \n\t"\
|
||||
"add %%"REG_c", "PTR_SIZE"*3(%%"REG_a");\n\t"\
|
||||
"add %%"REG_c", "PTR_SIZE"*2(%%"REG_a");\n\t"\
|
||||
"add %%"REG_c", "PTR_SIZE"*1(%%"REG_a");\n\t"\
|
||||
"add %%"REG_c", (%%"REG_a") \n\t"\
|
||||
"add $"PTR_SIZE"*1, %1 \n\t"\
|
||||
"add %%"REG_c", %0 \n\t"\
|
||||
"dec %2 \n\t"\
|
||||
"jnz 1b \n\t"\
|
||||
:"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\
|
||||
:\
|
||||
"rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"((x86_reg)b_h),"m"((x86_reg)src_stride):\
|
||||
"%"REG_c"","%"REG_S"","%"REG_D"","%"REG_d"");
|
||||
|
||||
static void inner_add_yblock_bw_8_obmc_16_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h,
|
||||
int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){
|
||||
snow_inner_add_yblock_mmx_header
|
||||
snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0")
|
||||
snow_inner_add_yblock_mmx_accum("2", "8", "0")
|
||||
snow_inner_add_yblock_mmx_accum("1", "128", "0")
|
||||
snow_inner_add_yblock_mmx_accum("0", "136", "0")
|
||||
snow_inner_add_yblock_mmx_mix("0", "0")
|
||||
snow_inner_add_yblock_mmx_end("16")
|
||||
}
|
||||
|
||||
static void inner_add_yblock_bw_16_obmc_32_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h,
|
||||
int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){
|
||||
snow_inner_add_yblock_mmx_header
|
||||
snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0")
|
||||
snow_inner_add_yblock_mmx_accum("2", "16", "0")
|
||||
snow_inner_add_yblock_mmx_accum("1", "512", "0")
|
||||
snow_inner_add_yblock_mmx_accum("0", "528", "0")
|
||||
snow_inner_add_yblock_mmx_mix("0", "0")
|
||||
|
||||
snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "8", "8")
|
||||
snow_inner_add_yblock_mmx_accum("2", "24", "8")
|
||||
snow_inner_add_yblock_mmx_accum("1", "520", "8")
|
||||
snow_inner_add_yblock_mmx_accum("0", "536", "8")
|
||||
snow_inner_add_yblock_mmx_mix("16", "8")
|
||||
snow_inner_add_yblock_mmx_end("32")
|
||||
}
|
||||
|
||||
void ff_snow_inner_add_yblock_sse2(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h,
|
||||
int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){
|
||||
|
||||
if (b_w == 16)
|
||||
inner_add_yblock_bw_16_obmc_32_sse2(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
else if (b_w == 8 && obmc_stride == 16) {
|
||||
if (!(b_h & 1))
|
||||
inner_add_yblock_bw_8_obmc_16_bh_even_sse2(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
else
|
||||
inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
} else
|
||||
ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
}
|
||||
|
||||
void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h,
|
||||
int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){
|
||||
if (b_w == 16)
|
||||
inner_add_yblock_bw_16_obmc_32_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
else if (b_w == 8 && obmc_stride == 16)
|
||||
inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
else
|
||||
ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
|
||||
}
|
||||
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* VC-1 and WMV3 - DSP functions MMX-optimized
|
||||
* Copyright (c) 2007 Christophe GISQUET <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "libavutil/x86_cpu.h"
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "dsputil_mmx.h"
|
||||
|
||||
/** Add rounder from mm7 to mm3 and pack result at destination */
|
||||
#define NORMALIZE_MMX(SHIFT) \
|
||||
"paddw %%mm7, %%mm3 \n\t" /* +bias-r */ \
|
||||
"paddw %%mm7, %%mm4 \n\t" /* +bias-r */ \
|
||||
"psraw "SHIFT", %%mm3 \n\t" \
|
||||
"psraw "SHIFT", %%mm4 \n\t"
|
||||
|
||||
#define TRANSFER_DO_PACK \
|
||||
"packuswb %%mm4, %%mm3 \n\t" \
|
||||
"movq %%mm3, (%2) \n\t"
|
||||
|
||||
#define TRANSFER_DONT_PACK \
|
||||
"movq %%mm3, 0(%2) \n\t" \
|
||||
"movq %%mm4, 8(%2) \n\t"
|
||||
|
||||
/** @see MSPEL_FILTER13_CORE for use as UNPACK macro */
|
||||
#define DO_UNPACK(reg) "punpcklbw %%mm0, " reg "\n\t"
|
||||
#define DONT_UNPACK(reg)
|
||||
|
||||
/** Compute the rounder 32-r or 8-r and unpacks it to mm7 */
|
||||
#define LOAD_ROUNDER_MMX(ROUND) \
|
||||
"movd "ROUND", %%mm7 \n\t" \
|
||||
"punpcklwd %%mm7, %%mm7 \n\t" \
|
||||
"punpckldq %%mm7, %%mm7 \n\t"
|
||||
|
||||
#define SHIFT2_LINE(OFF, R0,R1,R2,R3) \
|
||||
"paddw %%mm"#R2", %%mm"#R1" \n\t" \
|
||||
"movd (%0,%3), %%mm"#R0" \n\t" \
|
||||
"pmullw %%mm6, %%mm"#R1" \n\t" \
|
||||
"punpcklbw %%mm0, %%mm"#R0" \n\t" \
|
||||
"movd (%0,%2), %%mm"#R3" \n\t" \
|
||||
"psubw %%mm"#R0", %%mm"#R1" \n\t" \
|
||||
"punpcklbw %%mm0, %%mm"#R3" \n\t" \
|
||||
"paddw %%mm7, %%mm"#R1" \n\t" \
|
||||
"psubw %%mm"#R3", %%mm"#R1" \n\t" \
|
||||
"psraw %4, %%mm"#R1" \n\t" \
|
||||
"movq %%mm"#R1", "#OFF"(%1) \n\t" \
|
||||
"add %2, %0 \n\t"
|
||||
|
||||
DECLARE_ALIGNED_16(const uint64_t, ff_pw_9) = 0x0009000900090009ULL;
|
||||
|
||||
/** Sacrifying mm6 allows to pipeline loads from src */
|
||||
static void vc1_put_ver_16b_shift2_mmx(int16_t *dst,
|
||||
const uint8_t *src, x86_reg stride,
|
||||
int rnd, int64_t shift)
|
||||
{
|
||||
asm volatile(
|
||||
"mov $3, %%"REG_c" \n\t"
|
||||
LOAD_ROUNDER_MMX("%5")
|
||||
"movq "MANGLE(ff_pw_9)", %%mm6 \n\t"
|
||||
"1: \n\t"
|
||||
"movd (%0), %%mm2 \n\t"
|
||||
"add %2, %0 \n\t"
|
||||
"movd (%0), %%mm3 \n\t"
|
||||
"punpcklbw %%mm0, %%mm2 \n\t"
|
||||
"punpcklbw %%mm0, %%mm3 \n\t"
|
||||
SHIFT2_LINE( 0, 1, 2, 3, 4)
|
||||
SHIFT2_LINE( 24, 2, 3, 4, 1)
|
||||
SHIFT2_LINE( 48, 3, 4, 1, 2)
|
||||
SHIFT2_LINE( 72, 4, 1, 2, 3)
|
||||
SHIFT2_LINE( 96, 1, 2, 3, 4)
|
||||
SHIFT2_LINE(120, 2, 3, 4, 1)
|
||||
SHIFT2_LINE(144, 3, 4, 1, 2)
|
||||
SHIFT2_LINE(168, 4, 1, 2, 3)
|
||||
"sub %6, %0 \n\t"
|
||||
"add $8, %1 \n\t"
|
||||
"dec %%"REG_c" \n\t"
|
||||
"jnz 1b \n\t"
|
||||
: "+r"(src), "+r"(dst)
|
||||
: "r"(stride), "r"(-2*stride),
|
||||
"m"(shift), "m"(rnd), "r"(9*stride-4)
|
||||
: "%"REG_c, "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data is already unpacked, so some operations can directly be made from
|
||||
* memory.
|
||||
*/
|
||||
static void vc1_put_hor_16b_shift2_mmx(uint8_t *dst, x86_reg stride,
|
||||
const int16_t *src, int rnd)
|
||||
{
|
||||
int h = 8;
|
||||
|
||||
src -= 1;
|
||||
rnd -= (-1+9+9-1)*1024; /* Add -1024 bias */
|
||||
asm volatile(
|
||||
LOAD_ROUNDER_MMX("%4")
|
||||
"movq "MANGLE(ff_pw_128)", %%mm6\n\t"
|
||||
"movq "MANGLE(ff_pw_9)", %%mm5 \n\t"
|
||||
"1: \n\t"
|
||||
"movq 2*0+0(%1), %%mm1 \n\t"
|
||||
"movq 2*0+8(%1), %%mm2 \n\t"
|
||||
"movq 2*1+0(%1), %%mm3 \n\t"
|
||||
"movq 2*1+8(%1), %%mm4 \n\t"
|
||||
"paddw 2*3+0(%1), %%mm1 \n\t"
|
||||
"paddw 2*3+8(%1), %%mm2 \n\t"
|
||||
"paddw 2*2+0(%1), %%mm3 \n\t"
|
||||
"paddw 2*2+8(%1), %%mm4 \n\t"
|
||||
"pmullw %%mm5, %%mm3 \n\t"
|
||||
"pmullw %%mm5, %%mm4 \n\t"
|
||||
"psubw %%mm1, %%mm3 \n\t"
|
||||
"psubw %%mm2, %%mm4 \n\t"
|
||||
NORMALIZE_MMX("$7")
|
||||
/* Remove bias */
|
||||
"paddw %%mm6, %%mm3 \n\t"
|
||||
"paddw %%mm6, %%mm4 \n\t"
|
||||
TRANSFER_DO_PACK
|
||||
"add $24, %1 \n\t"
|
||||
"add %3, %2 \n\t"
|
||||
"decl %0 \n\t"
|
||||
"jnz 1b \n\t"
|
||||
: "+r"(h), "+r" (src), "+r" (dst)
|
||||
: "r"(stride), "m"(rnd)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Purely vertical or horizontal 1/2 shift interpolation.
|
||||
* Sacrify mm6 for *9 factor.
|
||||
*/
|
||||
static void vc1_put_shift2_mmx(uint8_t *dst, const uint8_t *src,
|
||||
x86_reg stride, int rnd, x86_reg offset)
|
||||
{
|
||||
rnd = 8-rnd;
|
||||
asm volatile(
|
||||
"mov $8, %%"REG_c" \n\t"
|
||||
LOAD_ROUNDER_MMX("%5")
|
||||
"movq "MANGLE(ff_pw_9)", %%mm6\n\t"
|
||||
"1: \n\t"
|
||||
"movd 0(%0 ), %%mm3 \n\t"
|
||||
"movd 4(%0 ), %%mm4 \n\t"
|
||||
"movd 0(%0,%2), %%mm1 \n\t"
|
||||
"movd 4(%0,%2), %%mm2 \n\t"
|
||||
"add %2, %0 \n\t"
|
||||
"punpcklbw %%mm0, %%mm3 \n\t"
|
||||
"punpcklbw %%mm0, %%mm4 \n\t"
|
||||
"punpcklbw %%mm0, %%mm1 \n\t"
|
||||
"punpcklbw %%mm0, %%mm2 \n\t"
|
||||
"paddw %%mm1, %%mm3 \n\t"
|
||||
"paddw %%mm2, %%mm4 \n\t"
|
||||
"movd 0(%0,%3), %%mm1 \n\t"
|
||||
"movd 4(%0,%3), %%mm2 \n\t"
|
||||
"pmullw %%mm6, %%mm3 \n\t" /* 0,9,9,0*/
|
||||
"pmullw %%mm6, %%mm4 \n\t" /* 0,9,9,0*/
|
||||
"punpcklbw %%mm0, %%mm1 \n\t"
|
||||
"punpcklbw %%mm0, %%mm2 \n\t"
|
||||
"psubw %%mm1, %%mm3 \n\t" /*-1,9,9,0*/
|
||||
"psubw %%mm2, %%mm4 \n\t" /*-1,9,9,0*/
|
||||
"movd 0(%0,%2), %%mm1 \n\t"
|
||||
"movd 4(%0,%2), %%mm2 \n\t"
|
||||
"punpcklbw %%mm0, %%mm1 \n\t"
|
||||
"punpcklbw %%mm0, %%mm2 \n\t"
|
||||
"psubw %%mm1, %%mm3 \n\t" /*-1,9,9,-1*/
|
||||
"psubw %%mm2, %%mm4 \n\t" /*-1,9,9,-1*/
|
||||
NORMALIZE_MMX("$4")
|
||||
"packuswb %%mm4, %%mm3 \n\t"
|
||||
"movq %%mm3, (%1) \n\t"
|
||||
"add %6, %0 \n\t"
|
||||
"add %4, %1 \n\t"
|
||||
"dec %%"REG_c" \n\t"
|
||||
"jnz 1b \n\t"
|
||||
: "+r"(src), "+r"(dst)
|
||||
: "r"(offset), "r"(-2*offset), "g"(stride), "m"(rnd),
|
||||
"g"(stride-offset)
|
||||
: "%"REG_c, "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter coefficients made global to allow access by all 1 or 3 quarter shift
|
||||
* interpolation functions.
|
||||
*/
|
||||
DECLARE_ALIGNED_16(const uint64_t, ff_pw_53) = 0x0035003500350035ULL;
|
||||
DECLARE_ALIGNED_16(const uint64_t, ff_pw_18) = 0x0012001200120012ULL;
|
||||
|
||||
/**
|
||||
* Core of the 1/4 and 3/4 shift bicubic interpolation.
|
||||
*
|
||||
* @param UNPACK Macro unpacking arguments from 8 to 16bits (can be empty).
|
||||
* @param MOVQ "movd 1" or "movq 2", if data read is already unpacked.
|
||||
* @param A1 Address of 1st tap (beware of unpacked/packed).
|
||||
* @param A2 Address of 2nd tap
|
||||
* @param A3 Address of 3rd tap
|
||||
* @param A4 Address of 4th tap
|
||||
*/
|
||||
#define MSPEL_FILTER13_CORE(UNPACK, MOVQ, A1, A2, A3, A4) \
|
||||
MOVQ "*0+"A1", %%mm1 \n\t" \
|
||||
MOVQ "*4+"A1", %%mm2 \n\t" \
|
||||
UNPACK("%%mm1") \
|
||||
UNPACK("%%mm2") \
|
||||
"pmullw "MANGLE(ff_pw_3)", %%mm1\n\t" \
|
||||
"pmullw "MANGLE(ff_pw_3)", %%mm2\n\t" \
|
||||
MOVQ "*0+"A2", %%mm3 \n\t" \
|
||||
MOVQ "*4+"A2", %%mm4 \n\t" \
|
||||
UNPACK("%%mm3") \
|
||||
UNPACK("%%mm4") \
|
||||
"pmullw %%mm6, %%mm3 \n\t" /* *18 */ \
|
||||
"pmullw %%mm6, %%mm4 \n\t" /* *18 */ \
|
||||
"psubw %%mm1, %%mm3 \n\t" /* 18,-3 */ \
|
||||
"psubw %%mm2, %%mm4 \n\t" /* 18,-3 */ \
|
||||
MOVQ "*0+"A4", %%mm1 \n\t" \
|
||||
MOVQ "*4+"A4", %%mm2 \n\t" \
|
||||
UNPACK("%%mm1") \
|
||||
UNPACK("%%mm2") \
|
||||
"psllw $2, %%mm1 \n\t" /* 4* */ \
|
||||
"psllw $2, %%mm2 \n\t" /* 4* */ \
|
||||
"psubw %%mm1, %%mm3 \n\t" /* -4,18,-3 */ \
|
||||
"psubw %%mm2, %%mm4 \n\t" /* -4,18,-3 */ \
|
||||
MOVQ "*0+"A3", %%mm1 \n\t" \
|
||||
MOVQ "*4+"A3", %%mm2 \n\t" \
|
||||
UNPACK("%%mm1") \
|
||||
UNPACK("%%mm2") \
|
||||
"pmullw %%mm5, %%mm1 \n\t" /* *53 */ \
|
||||
"pmullw %%mm5, %%mm2 \n\t" /* *53 */ \
|
||||
"paddw %%mm1, %%mm3 \n\t" /* 4,53,18,-3 */ \
|
||||
"paddw %%mm2, %%mm4 \n\t" /* 4,53,18,-3 */
|
||||
|
||||
/**
|
||||
* Macro to build the vertical 16bits version of vc1_put_shift[13].
|
||||
* Here, offset=src_stride. Parameters passed A1 to A4 must use
|
||||
* %3 (src_stride) and %4 (3*src_stride).
|
||||
*
|
||||
* @param NAME Either 1 or 3
|
||||
* @see MSPEL_FILTER13_CORE for information on A1->A4
|
||||
*/
|
||||
#define MSPEL_FILTER13_VER_16B(NAME, A1, A2, A3, A4) \
|
||||
static void \
|
||||
vc1_put_ver_16b_ ## NAME ## _mmx(int16_t *dst, const uint8_t *src, \
|
||||
x86_reg src_stride, \
|
||||
int rnd, int64_t shift) \
|
||||
{ \
|
||||
int h = 8; \
|
||||
src -= src_stride; \
|
||||
asm volatile( \
|
||||
LOAD_ROUNDER_MMX("%5") \
|
||||
"movq "MANGLE(ff_pw_53)", %%mm5\n\t" \
|
||||
"movq "MANGLE(ff_pw_18)", %%mm6\n\t" \
|
||||
ASMALIGN(3) \
|
||||
"1: \n\t" \
|
||||
MSPEL_FILTER13_CORE(DO_UNPACK, "movd 1", A1, A2, A3, A4) \
|
||||
NORMALIZE_MMX("%6") \
|
||||
TRANSFER_DONT_PACK \
|
||||
/* Last 3 (in fact 4) bytes on the line */ \
|
||||
"movd 8+"A1", %%mm1 \n\t" \
|
||||
DO_UNPACK("%%mm1") \
|
||||
"movq %%mm1, %%mm3 \n\t" \
|
||||
"paddw %%mm1, %%mm1 \n\t" \
|
||||
"paddw %%mm3, %%mm1 \n\t" /* 3* */ \
|
||||
"movd 8+"A2", %%mm3 \n\t" \
|
||||
DO_UNPACK("%%mm3") \
|
||||
"pmullw %%mm6, %%mm3 \n\t" /* *18 */ \
|
||||
"psubw %%mm1, %%mm3 \n\t" /*18,-3 */ \
|
||||
"movd 8+"A3", %%mm1 \n\t" \
|
||||
DO_UNPACK("%%mm1") \
|
||||
"pmullw %%mm5, %%mm1 \n\t" /* *53 */ \
|
||||
"paddw %%mm1, %%mm3 \n\t" /*53,18,-3 */ \
|
||||
"movd 8+"A4", %%mm1 \n\t" \
|
||||
DO_UNPACK("%%mm1") \
|
||||
"psllw $2, %%mm1 \n\t" /* 4* */ \
|
||||
"psubw %%mm1, %%mm3 \n\t" \
|
||||
"paddw %%mm7, %%mm3 \n\t" \
|
||||
"psraw %6, %%mm3 \n\t" \
|
||||
"movq %%mm3, 16(%2) \n\t" \
|
||||
"add %3, %1 \n\t" \
|
||||
"add $24, %2 \n\t" \
|
||||
"decl %0 \n\t" \
|
||||
"jnz 1b \n\t" \
|
||||
: "+r"(h), "+r" (src), "+r" (dst) \
|
||||
: "r"(src_stride), "r"(3*src_stride), \
|
||||
"m"(rnd), "m"(shift) \
|
||||
: "memory" \
|
||||
); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro to build the horizontal 16bits version of vc1_put_shift[13].
|
||||
* Here, offset=16bits, so parameters passed A1 to A4 should be simple.
|
||||
*
|
||||
* @param NAME Either 1 or 3
|
||||
* @see MSPEL_FILTER13_CORE for information on A1->A4
|
||||
*/
|
||||
#define MSPEL_FILTER13_HOR_16B(NAME, A1, A2, A3, A4) \
|
||||
static void \
|
||||
vc1_put_hor_16b_ ## NAME ## _mmx(uint8_t *dst, x86_reg stride, \
|
||||
const int16_t *src, int rnd) \
|
||||
{ \
|
||||
int h = 8; \
|
||||
src -= 1; \
|
||||
rnd -= (-4+58+13-3)*256; /* Add -256 bias */ \
|
||||
asm volatile( \
|
||||
LOAD_ROUNDER_MMX("%4") \
|
||||
"movq "MANGLE(ff_pw_18)", %%mm6 \n\t" \
|
||||
"movq "MANGLE(ff_pw_53)", %%mm5 \n\t" \
|
||||
ASMALIGN(3) \
|
||||
"1: \n\t" \
|
||||
MSPEL_FILTER13_CORE(DONT_UNPACK, "movq 2", A1, A2, A3, A4) \
|
||||
NORMALIZE_MMX("$7") \
|
||||
/* Remove bias */ \
|
||||
"paddw "MANGLE(ff_pw_128)", %%mm3 \n\t" \
|
||||
"paddw "MANGLE(ff_pw_128)", %%mm4 \n\t" \
|
||||
TRANSFER_DO_PACK \
|
||||
"add $24, %1 \n\t" \
|
||||
"add %3, %2 \n\t" \
|
||||
"decl %0 \n\t" \
|
||||
"jnz 1b \n\t" \
|
||||
: "+r"(h), "+r" (src), "+r" (dst) \
|
||||
: "r"(stride), "m"(rnd) \
|
||||
: "memory" \
|
||||
); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro to build the 8bits, any direction, version of vc1_put_shift[13].
|
||||
* Here, offset=src_stride. Parameters passed A1 to A4 must use
|
||||
* %3 (offset) and %4 (3*offset).
|
||||
*
|
||||
* @param NAME Either 1 or 3
|
||||
* @see MSPEL_FILTER13_CORE for information on A1->A4
|
||||
*/
|
||||
#define MSPEL_FILTER13_8B(NAME, A1, A2, A3, A4) \
|
||||
static void \
|
||||
vc1_put_## NAME ## _mmx(uint8_t *dst, const uint8_t *src, \
|
||||
x86_reg stride, int rnd, x86_reg offset) \
|
||||
{ \
|
||||
int h = 8; \
|
||||
src -= offset; \
|
||||
rnd = 32-rnd; \
|
||||
asm volatile ( \
|
||||
LOAD_ROUNDER_MMX("%6") \
|
||||
"movq "MANGLE(ff_pw_53)", %%mm5 \n\t" \
|
||||
"movq "MANGLE(ff_pw_18)", %%mm6 \n\t" \
|
||||
ASMALIGN(3) \
|
||||
"1: \n\t" \
|
||||
MSPEL_FILTER13_CORE(DO_UNPACK, "movd 1", A1, A2, A3, A4) \
|
||||
NORMALIZE_MMX("$6") \
|
||||
TRANSFER_DO_PACK \
|
||||
"add %5, %1 \n\t" \
|
||||
"add %5, %2 \n\t" \
|
||||
"decl %0 \n\t" \
|
||||
"jnz 1b \n\t" \
|
||||
: "+r"(h), "+r" (src), "+r" (dst) \
|
||||
: "r"(offset), "r"(3*offset), "g"(stride), "m"(rnd) \
|
||||
: "memory" \
|
||||
); \
|
||||
}
|
||||
|
||||
/** 1/4 shift bicubic interpolation */
|
||||
MSPEL_FILTER13_8B (shift1, "0(%1,%4 )", "0(%1,%3,2)", "0(%1,%3 )", "0(%1 )")
|
||||
MSPEL_FILTER13_VER_16B(shift1, "0(%1,%4 )", "0(%1,%3,2)", "0(%1,%3 )", "0(%1 )")
|
||||
MSPEL_FILTER13_HOR_16B(shift1, "2*3(%1)", "2*2(%1)", "2*1(%1)", "2*0(%1)")
|
||||
|
||||
/** 3/4 shift bicubic interpolation */
|
||||
MSPEL_FILTER13_8B (shift3, "0(%1 )", "0(%1,%3 )", "0(%1,%3,2)", "0(%1,%4 )")
|
||||
MSPEL_FILTER13_VER_16B(shift3, "0(%1 )", "0(%1,%3 )", "0(%1,%3,2)", "0(%1,%4 )")
|
||||
MSPEL_FILTER13_HOR_16B(shift3, "2*0(%1)", "2*1(%1)", "2*2(%1)", "2*3(%1)")
|
||||
|
||||
typedef void (*vc1_mspel_mc_filter_ver_16bits)(int16_t *dst, const uint8_t *src, x86_reg src_stride, int rnd, int64_t shift);
|
||||
typedef void (*vc1_mspel_mc_filter_hor_16bits)(uint8_t *dst, x86_reg dst_stride, const int16_t *src, int rnd);
|
||||
typedef void (*vc1_mspel_mc_filter_8bits)(uint8_t *dst, const uint8_t *src, x86_reg stride, int rnd, x86_reg offset);
|
||||
|
||||
/**
|
||||
* Interpolates fractional pel values by applying proper vertical then
|
||||
* horizontal filter.
|
||||
*
|
||||
* @param dst Destination buffer for interpolated pels.
|
||||
* @param src Source buffer.
|
||||
* @param stride Stride for both src and dst buffers.
|
||||
* @param hmode Horizontal filter (expressed in quarter pixels shift).
|
||||
* @param hmode Vertical filter.
|
||||
* @param rnd Rounding bias.
|
||||
*/
|
||||
static void vc1_mspel_mc(uint8_t *dst, const uint8_t *src, int stride,
|
||||
int hmode, int vmode, int rnd)
|
||||
{
|
||||
static const vc1_mspel_mc_filter_ver_16bits vc1_put_shift_ver_16bits[] =
|
||||
{ NULL, vc1_put_ver_16b_shift1_mmx, vc1_put_ver_16b_shift2_mmx, vc1_put_ver_16b_shift3_mmx };
|
||||
static const vc1_mspel_mc_filter_hor_16bits vc1_put_shift_hor_16bits[] =
|
||||
{ NULL, vc1_put_hor_16b_shift1_mmx, vc1_put_hor_16b_shift2_mmx, vc1_put_hor_16b_shift3_mmx };
|
||||
static const vc1_mspel_mc_filter_8bits vc1_put_shift_8bits[] =
|
||||
{ NULL, vc1_put_shift1_mmx, vc1_put_shift2_mmx, vc1_put_shift3_mmx };
|
||||
|
||||
asm volatile(
|
||||
"pxor %%mm0, %%mm0 \n\t"
|
||||
::: "memory"
|
||||
);
|
||||
|
||||
if (vmode) { /* Vertical filter to apply */
|
||||
if (hmode) { /* Horizontal filter to apply, output to tmp */
|
||||
static const int shift_value[] = { 0, 5, 1, 5 };
|
||||
int shift = (shift_value[hmode]+shift_value[vmode])>>1;
|
||||
int r;
|
||||
DECLARE_ALIGNED_16(int16_t, tmp[12*8]);
|
||||
|
||||
r = (1<<(shift-1)) + rnd-1;
|
||||
vc1_put_shift_ver_16bits[vmode](tmp, src-1, stride, r, shift);
|
||||
|
||||
vc1_put_shift_hor_16bits[hmode](dst, stride, tmp+1, 64-rnd);
|
||||
return;
|
||||
}
|
||||
else { /* No horizontal filter, output 8 lines to dst */
|
||||
vc1_put_shift_8bits[vmode](dst, src, stride, 1-rnd, stride);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Horizontal mode with no vertical mode */
|
||||
vc1_put_shift_8bits[hmode](dst, src, stride, rnd, 1);
|
||||
}
|
||||
|
||||
void ff_put_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, int stride, int rnd);
|
||||
|
||||
/** Macro to ease bicubic filter interpolation functions declarations */
|
||||
#define DECLARE_FUNCTION(a, b) \
|
||||
static void put_vc1_mspel_mc ## a ## b ## _mmx(uint8_t *dst, const uint8_t *src, int stride, int rnd) { \
|
||||
vc1_mspel_mc(dst, src, stride, a, b, rnd); \
|
||||
}
|
||||
|
||||
DECLARE_FUNCTION(0, 1)
|
||||
DECLARE_FUNCTION(0, 2)
|
||||
DECLARE_FUNCTION(0, 3)
|
||||
|
||||
DECLARE_FUNCTION(1, 0)
|
||||
DECLARE_FUNCTION(1, 1)
|
||||
DECLARE_FUNCTION(1, 2)
|
||||
DECLARE_FUNCTION(1, 3)
|
||||
|
||||
DECLARE_FUNCTION(2, 0)
|
||||
DECLARE_FUNCTION(2, 1)
|
||||
DECLARE_FUNCTION(2, 2)
|
||||
DECLARE_FUNCTION(2, 3)
|
||||
|
||||
DECLARE_FUNCTION(3, 0)
|
||||
DECLARE_FUNCTION(3, 1)
|
||||
DECLARE_FUNCTION(3, 2)
|
||||
DECLARE_FUNCTION(3, 3)
|
||||
|
||||
void ff_vc1dsp_init_mmx(DSPContext* dsp, AVCodecContext *avctx) {
|
||||
dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_vc1_mspel_mc00_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[ 4] = put_vc1_mspel_mc01_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[ 8] = put_vc1_mspel_mc02_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[12] = put_vc1_mspel_mc03_mmx;
|
||||
|
||||
dsp->put_vc1_mspel_pixels_tab[ 1] = put_vc1_mspel_mc10_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[ 5] = put_vc1_mspel_mc11_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[ 9] = put_vc1_mspel_mc12_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[13] = put_vc1_mspel_mc13_mmx;
|
||||
|
||||
dsp->put_vc1_mspel_pixels_tab[ 2] = put_vc1_mspel_mc20_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[ 6] = put_vc1_mspel_mc21_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[10] = put_vc1_mspel_mc22_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[14] = put_vc1_mspel_mc23_mmx;
|
||||
|
||||
dsp->put_vc1_mspel_pixels_tab[ 3] = put_vc1_mspel_mc30_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[ 7] = put_vc1_mspel_mc31_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[11] = put_vc1_mspel_mc32_mmx;
|
||||
dsp->put_vc1_mspel_pixels_tab[15] = put_vc1_mspel_mc33_mmx;
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (C) 2004 the ffmpeg project
|
||||
*
|
||||
* 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 vp3dsp_mmx.c
|
||||
* MMX-optimized functions cribbed from the original VP3 source code.
|
||||
*/
|
||||
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "mmx.h"
|
||||
|
||||
#define IdctAdjustBeforeShift 8
|
||||
|
||||
/* (12 * 4) 2-byte memory locations ( = 96 bytes total)
|
||||
* idct_constants[0..15] = Mask table (M(I))
|
||||
* idct_constants[16..43] = Cosine table (C(I))
|
||||
* idct_constants[44..47] = 8
|
||||
*/
|
||||
static uint16_t idct_constants[(4 + 7 + 1) * 4];
|
||||
static const uint16_t idct_cosine_table[7] = {
|
||||
64277, 60547, 54491, 46341, 36410, 25080, 12785
|
||||
};
|
||||
|
||||
#define r0 mm0
|
||||
#define r1 mm1
|
||||
#define r2 mm2
|
||||
#define r3 mm3
|
||||
#define r4 mm4
|
||||
#define r5 mm5
|
||||
#define r6 mm6
|
||||
#define r7 mm7
|
||||
|
||||
/* from original comments: The Macro does IDct on 4 1-D Dcts */
|
||||
#define BeginIDCT() { \
|
||||
movq_m2r(*I(3), r2); \
|
||||
movq_m2r(*C(3), r6); \
|
||||
movq_r2r(r2, r4); \
|
||||
movq_m2r(*J(5), r7); \
|
||||
pmulhw_r2r(r6, r4); /* r4 = c3*i3 - i3 */ \
|
||||
movq_m2r(*C(5), r1); \
|
||||
pmulhw_r2r(r7, r6); /* r6 = c3*i5 - i5 */ \
|
||||
movq_r2r(r1, r5); \
|
||||
pmulhw_r2r(r2, r1); /* r1 = c5*i3 - i3 */ \
|
||||
movq_m2r(*I(1), r3); \
|
||||
pmulhw_r2r(r7, r5); /* r5 = c5*i5 - i5 */ \
|
||||
movq_m2r(*C(1), r0); /* (all registers are in use) */ \
|
||||
paddw_r2r(r2, r4); /* r4 = c3*i3 */ \
|
||||
paddw_r2r(r7, r6); /* r6 = c3*i5 */ \
|
||||
paddw_r2r(r1, r2); /* r2 = c5*i3 */ \
|
||||
movq_m2r(*J(7), r1); \
|
||||
paddw_r2r(r5, r7); /* r7 = c5*i5 */ \
|
||||
movq_r2r(r0, r5); /* r5 = c1 */ \
|
||||
pmulhw_r2r(r3, r0); /* r0 = c1*i1 - i1 */ \
|
||||
paddsw_r2r(r7, r4); /* r4 = C = c3*i3 + c5*i5 */ \
|
||||
pmulhw_r2r(r1, r5); /* r5 = c1*i7 - i7 */ \
|
||||
movq_m2r(*C(7), r7); \
|
||||
psubsw_r2r(r2, r6); /* r6 = D = c3*i5 - c5*i3 */ \
|
||||
paddw_r2r(r3, r0); /* r0 = c1*i1 */ \
|
||||
pmulhw_r2r(r7, r3); /* r3 = c7*i1 */ \
|
||||
movq_m2r(*I(2), r2); \
|
||||
pmulhw_r2r(r1, r7); /* r7 = c7*i7 */ \
|
||||
paddw_r2r(r1, r5); /* r5 = c1*i7 */ \
|
||||
movq_r2r(r2, r1); /* r1 = i2 */ \
|
||||
pmulhw_m2r(*C(2), r2); /* r2 = c2*i2 - i2 */ \
|
||||
psubsw_r2r(r5, r3); /* r3 = B = c7*i1 - c1*i7 */ \
|
||||
movq_m2r(*J(6), r5); \
|
||||
paddsw_r2r(r7, r0); /* r0 = A = c1*i1 + c7*i7 */ \
|
||||
movq_r2r(r5, r7); /* r7 = i6 */ \
|
||||
psubsw_r2r(r4, r0); /* r0 = A - C */ \
|
||||
pmulhw_m2r(*C(2), r5); /* r5 = c2*i6 - i6 */ \
|
||||
paddw_r2r(r1, r2); /* r2 = c2*i2 */ \
|
||||
pmulhw_m2r(*C(6), r1); /* r1 = c6*i2 */ \
|
||||
paddsw_r2r(r4, r4); /* r4 = C + C */ \
|
||||
paddsw_r2r(r0, r4); /* r4 = C. = A + C */ \
|
||||
psubsw_r2r(r6, r3); /* r3 = B - D */ \
|
||||
paddw_r2r(r7, r5); /* r5 = c2*i6 */ \
|
||||
paddsw_r2r(r6, r6); /* r6 = D + D */ \
|
||||
pmulhw_m2r(*C(6), r7); /* r7 = c6*i6 */ \
|
||||
paddsw_r2r(r3, r6); /* r6 = D. = B + D */ \
|
||||
movq_r2m(r4, *I(1)); /* save C. at I(1) */ \
|
||||
psubsw_r2r(r5, r1); /* r1 = H = c6*i2 - c2*i6 */ \
|
||||
movq_m2r(*C(4), r4); \
|
||||
movq_r2r(r3, r5); /* r5 = B - D */ \
|
||||
pmulhw_r2r(r4, r3); /* r3 = (c4 - 1) * (B - D) */ \
|
||||
paddsw_r2r(r2, r7); /* r7 = G = c6*i6 + c2*i2 */ \
|
||||
movq_r2m(r6, *I(2)); /* save D. at I(2) */ \
|
||||
movq_r2r(r0, r2); /* r2 = A - C */ \
|
||||
movq_m2r(*I(0), r6); \
|
||||
pmulhw_r2r(r4, r0); /* r0 = (c4 - 1) * (A - C) */ \
|
||||
paddw_r2r(r3, r5); /* r5 = B. = c4 * (B - D) */ \
|
||||
movq_m2r(*J(4), r3); \
|
||||
psubsw_r2r(r1, r5); /* r5 = B.. = B. - H */ \
|
||||
paddw_r2r(r0, r2); /* r0 = A. = c4 * (A - C) */ \
|
||||
psubsw_r2r(r3, r6); /* r6 = i0 - i4 */ \
|
||||
movq_r2r(r6, r0); \
|
||||
pmulhw_r2r(r4, r6); /* r6 = (c4 - 1) * (i0 - i4) */ \
|
||||
paddsw_r2r(r3, r3); /* r3 = i4 + i4 */ \
|
||||
paddsw_r2r(r1, r1); /* r1 = H + H */ \
|
||||
paddsw_r2r(r0, r3); /* r3 = i0 + i4 */ \
|
||||
paddsw_r2r(r5, r1); /* r1 = H. = B + H */ \
|
||||
pmulhw_r2r(r3, r4); /* r4 = (c4 - 1) * (i0 + i4) */ \
|
||||
paddsw_r2r(r0, r6); /* r6 = F = c4 * (i0 - i4) */ \
|
||||
psubsw_r2r(r2, r6); /* r6 = F. = F - A. */ \
|
||||
paddsw_r2r(r2, r2); /* r2 = A. + A. */ \
|
||||
movq_m2r(*I(1), r0); /* r0 = C. */ \
|
||||
paddsw_r2r(r6, r2); /* r2 = A.. = F + A. */ \
|
||||
paddw_r2r(r3, r4); /* r4 = E = c4 * (i0 + i4) */ \
|
||||
psubsw_r2r(r1, r2); /* r2 = R2 = A.. - H. */ \
|
||||
}
|
||||
|
||||
/* RowIDCT gets ready to transpose */
|
||||
#define RowIDCT() { \
|
||||
\
|
||||
BeginIDCT(); \
|
||||
\
|
||||
movq_m2r(*I(2), r3); /* r3 = D. */ \
|
||||
psubsw_r2r(r7, r4); /* r4 = E. = E - G */ \
|
||||
paddsw_r2r(r1, r1); /* r1 = H. + H. */ \
|
||||
paddsw_r2r(r7, r7); /* r7 = G + G */ \
|
||||
paddsw_r2r(r2, r1); /* r1 = R1 = A.. + H. */ \
|
||||
paddsw_r2r(r4, r7); /* r7 = G. = E + G */ \
|
||||
psubsw_r2r(r3, r4); /* r4 = R4 = E. - D. */ \
|
||||
paddsw_r2r(r3, r3); \
|
||||
psubsw_r2r(r5, r6); /* r6 = R6 = F. - B.. */ \
|
||||
paddsw_r2r(r5, r5); \
|
||||
paddsw_r2r(r4, r3); /* r3 = R3 = E. + D. */ \
|
||||
paddsw_r2r(r6, r5); /* r5 = R5 = F. + B.. */ \
|
||||
psubsw_r2r(r0, r7); /* r7 = R7 = G. - C. */ \
|
||||
paddsw_r2r(r0, r0); \
|
||||
movq_r2m(r1, *I(1)); /* save R1 */ \
|
||||
paddsw_r2r(r7, r0); /* r0 = R0 = G. + C. */ \
|
||||
}
|
||||
|
||||
/* Column IDCT normalizes and stores final results */
|
||||
#define ColumnIDCT() { \
|
||||
\
|
||||
BeginIDCT(); \
|
||||
\
|
||||
paddsw_m2r(*Eight, r2); /* adjust R2 (and R1) for shift */ \
|
||||
paddsw_r2r(r1, r1); /* r1 = H. + H. */ \
|
||||
paddsw_r2r(r2, r1); /* r1 = R1 = A.. + H. */ \
|
||||
psraw_i2r(4, r2); /* r2 = NR2 */ \
|
||||
psubsw_r2r(r7, r4); /* r4 = E. = E - G */ \
|
||||
psraw_i2r(4, r1); /* r1 = NR1 */ \
|
||||
movq_m2r(*I(2), r3); /* r3 = D. */ \
|
||||
paddsw_r2r(r7, r7); /* r7 = G + G */ \
|
||||
movq_r2m(r2, *I(2)); /* store NR2 at I2 */ \
|
||||
paddsw_r2r(r4, r7); /* r7 = G. = E + G */ \
|
||||
movq_r2m(r1, *I(1)); /* store NR1 at I1 */ \
|
||||
psubsw_r2r(r3, r4); /* r4 = R4 = E. - D. */ \
|
||||
paddsw_m2r(*Eight, r4); /* adjust R4 (and R3) for shift */ \
|
||||
paddsw_r2r(r3, r3); /* r3 = D. + D. */ \
|
||||
paddsw_r2r(r4, r3); /* r3 = R3 = E. + D. */ \
|
||||
psraw_i2r(4, r4); /* r4 = NR4 */ \
|
||||
psubsw_r2r(r5, r6); /* r6 = R6 = F. - B.. */ \
|
||||
psraw_i2r(4, r3); /* r3 = NR3 */ \
|
||||
paddsw_m2r(*Eight, r6); /* adjust R6 (and R5) for shift */ \
|
||||
paddsw_r2r(r5, r5); /* r5 = B.. + B.. */ \
|
||||
paddsw_r2r(r6, r5); /* r5 = R5 = F. + B.. */ \
|
||||
psraw_i2r(4, r6); /* r6 = NR6 */ \
|
||||
movq_r2m(r4, *J(4)); /* store NR4 at J4 */ \
|
||||
psraw_i2r(4, r5); /* r5 = NR5 */ \
|
||||
movq_r2m(r3, *I(3)); /* store NR3 at I3 */ \
|
||||
psubsw_r2r(r0, r7); /* r7 = R7 = G. - C. */ \
|
||||
paddsw_m2r(*Eight, r7); /* adjust R7 (and R0) for shift */ \
|
||||
paddsw_r2r(r0, r0); /* r0 = C. + C. */ \
|
||||
paddsw_r2r(r7, r0); /* r0 = R0 = G. + C. */ \
|
||||
psraw_i2r(4, r7); /* r7 = NR7 */ \
|
||||
movq_r2m(r6, *J(6)); /* store NR6 at J6 */ \
|
||||
psraw_i2r(4, r0); /* r0 = NR0 */ \
|
||||
movq_r2m(r5, *J(5)); /* store NR5 at J5 */ \
|
||||
movq_r2m(r7, *J(7)); /* store NR7 at J7 */ \
|
||||
movq_r2m(r0, *I(0)); /* store NR0 at I0 */ \
|
||||
}
|
||||
|
||||
/* Following macro does two 4x4 transposes in place.
|
||||
|
||||
At entry (we assume):
|
||||
|
||||
r0 = a3 a2 a1 a0
|
||||
I(1) = b3 b2 b1 b0
|
||||
r2 = c3 c2 c1 c0
|
||||
r3 = d3 d2 d1 d0
|
||||
|
||||
r4 = e3 e2 e1 e0
|
||||
r5 = f3 f2 f1 f0
|
||||
r6 = g3 g2 g1 g0
|
||||
r7 = h3 h2 h1 h0
|
||||
|
||||
At exit, we have:
|
||||
|
||||
I(0) = d0 c0 b0 a0
|
||||
I(1) = d1 c1 b1 a1
|
||||
I(2) = d2 c2 b2 a2
|
||||
I(3) = d3 c3 b3 a3
|
||||
|
||||
J(4) = h0 g0 f0 e0
|
||||
J(5) = h1 g1 f1 e1
|
||||
J(6) = h2 g2 f2 e2
|
||||
J(7) = h3 g3 f3 e3
|
||||
|
||||
I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3.
|
||||
J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7.
|
||||
|
||||
Since r1 is free at entry, we calculate the Js first. */
|
||||
|
||||
#define Transpose() { \
|
||||
movq_r2r(r4, r1); /* r1 = e3 e2 e1 e0 */ \
|
||||
punpcklwd_r2r(r5, r4); /* r4 = f1 e1 f0 e0 */ \
|
||||
movq_r2m(r0, *I(0)); /* save a3 a2 a1 a0 */ \
|
||||
punpckhwd_r2r(r5, r1); /* r1 = f3 e3 f2 e2 */ \
|
||||
movq_r2r(r6, r0); /* r0 = g3 g2 g1 g0 */ \
|
||||
punpcklwd_r2r(r7, r6); /* r6 = h1 g1 h0 g0 */ \
|
||||
movq_r2r(r4, r5); /* r5 = f1 e1 f0 e0 */ \
|
||||
punpckldq_r2r(r6, r4); /* r4 = h0 g0 f0 e0 = R4 */ \
|
||||
punpckhdq_r2r(r6, r5); /* r5 = h1 g1 f1 e1 = R5 */ \
|
||||
movq_r2r(r1, r6); /* r6 = f3 e3 f2 e2 */ \
|
||||
movq_r2m(r4, *J(4)); \
|
||||
punpckhwd_r2r(r7, r0); /* r0 = h3 g3 h2 g2 */ \
|
||||
movq_r2m(r5, *J(5)); \
|
||||
punpckhdq_r2r(r0, r6); /* r6 = h3 g3 f3 e3 = R7 */ \
|
||||
movq_m2r(*I(0), r4); /* r4 = a3 a2 a1 a0 */ \
|
||||
punpckldq_r2r(r0, r1); /* r1 = h2 g2 f2 e2 = R6 */ \
|
||||
movq_m2r(*I(1), r5); /* r5 = b3 b2 b1 b0 */ \
|
||||
movq_r2r(r4, r0); /* r0 = a3 a2 a1 a0 */ \
|
||||
movq_r2m(r6, *J(7)); \
|
||||
punpcklwd_r2r(r5, r0); /* r0 = b1 a1 b0 a0 */ \
|
||||
movq_r2m(r1, *J(6)); \
|
||||
punpckhwd_r2r(r5, r4); /* r4 = b3 a3 b2 a2 */ \
|
||||
movq_r2r(r2, r5); /* r5 = c3 c2 c1 c0 */ \
|
||||
punpcklwd_r2r(r3, r2); /* r2 = d1 c1 d0 c0 */ \
|
||||
movq_r2r(r0, r1); /* r1 = b1 a1 b0 a0 */ \
|
||||
punpckldq_r2r(r2, r0); /* r0 = d0 c0 b0 a0 = R0 */ \
|
||||
punpckhdq_r2r(r2, r1); /* r1 = d1 c1 b1 a1 = R1 */ \
|
||||
movq_r2r(r4, r2); /* r2 = b3 a3 b2 a2 */ \
|
||||
movq_r2m(r0, *I(0)); \
|
||||
punpckhwd_r2r(r3, r5); /* r5 = d3 c3 d2 c2 */ \
|
||||
movq_r2m(r1, *I(1)); \
|
||||
punpckhdq_r2r(r5, r4); /* r4 = d3 c3 b3 a3 = R3 */ \
|
||||
punpckldq_r2r(r5, r2); /* r2 = d2 c2 b2 a2 = R2 */ \
|
||||
movq_r2m(r4, *I(3)); \
|
||||
movq_r2m(r2, *I(2)); \
|
||||
}
|
||||
|
||||
void ff_vp3_dsp_init_mmx(void)
|
||||
{
|
||||
int j = 16;
|
||||
uint16_t *p;
|
||||
|
||||
j = 1;
|
||||
do {
|
||||
p = idct_constants + ((j + 3) << 2);
|
||||
p[0] = p[1] = p[2] = p[3] = idct_cosine_table[j - 1];
|
||||
} while (++j <= 7);
|
||||
|
||||
idct_constants[44] = idct_constants[45] =
|
||||
idct_constants[46] = idct_constants[47] = IdctAdjustBeforeShift;
|
||||
}
|
||||
|
||||
void ff_vp3_idct_mmx(int16_t *output_data)
|
||||
{
|
||||
/* eax = quantized input
|
||||
* ebx = dequantizer matrix
|
||||
* ecx = IDCT constants
|
||||
* M(I) = ecx + MaskOffset(0) + I * 8
|
||||
* C(I) = ecx + CosineOffset(32) + (I-1) * 8
|
||||
* edx = output
|
||||
* r0..r7 = mm0..mm7
|
||||
*/
|
||||
|
||||
#define C(x) (idct_constants + 16 + (x - 1) * 4)
|
||||
#define Eight (idct_constants + 44)
|
||||
|
||||
/* at this point, function has completed dequantization + dezigzag +
|
||||
* partial transposition; now do the idct itself */
|
||||
#define I(K) (output_data + K * 8)
|
||||
#define J(K) (output_data + ((K - 4) * 8) + 4)
|
||||
|
||||
RowIDCT();
|
||||
Transpose();
|
||||
|
||||
#undef I
|
||||
#undef J
|
||||
#define I(K) (output_data + (K * 8) + 32)
|
||||
#define J(K) (output_data + ((K - 4) * 8) + 36)
|
||||
|
||||
RowIDCT();
|
||||
Transpose();
|
||||
|
||||
#undef I
|
||||
#undef J
|
||||
#define I(K) (output_data + K * 8)
|
||||
#define J(K) (output_data + K * 8)
|
||||
|
||||
ColumnIDCT();
|
||||
|
||||
#undef I
|
||||
#undef J
|
||||
#define I(K) (output_data + (K * 8) + 4)
|
||||
#define J(K) (output_data + (K * 8) + 4)
|
||||
|
||||
ColumnIDCT();
|
||||
|
||||
#undef I
|
||||
#undef J
|
||||
|
||||
}
|
||||
|
||||
void ff_vp3_idct_put_mmx(uint8_t *dest, int line_size, DCTELEM *block)
|
||||
{
|
||||
ff_vp3_idct_mmx(block);
|
||||
put_signed_pixels_clamped_mmx(block, dest, line_size);
|
||||
}
|
||||
|
||||
void ff_vp3_idct_add_mmx(uint8_t *dest, int line_size, DCTELEM *block)
|
||||
{
|
||||
ff_vp3_idct_mmx(block);
|
||||
add_pixels_clamped_mmx(block, dest, line_size);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* vp3dsp MMX function declarations
|
||||
* Copyright (c) 2007 Aurelien Jacobs <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_VP3DSP_MMX_H
|
||||
#define FFMPEG_VP3DSP_MMX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
void ff_vp3_idct_mmx(int16_t *data);
|
||||
void ff_vp3_idct_put_mmx(uint8_t *dest, int line_size, DCTELEM *block);
|
||||
void ff_vp3_idct_add_mmx(uint8_t *dest, int line_size, DCTELEM *block);
|
||||
void ff_vp3_dsp_init_mmx(void);
|
||||
|
||||
#endif /* FFMPEG_VP3DSP_MMX_H */
|
||||
@@ -0,0 +1,839 @@
|
||||
/*
|
||||
* Copyright (C) 2004 the ffmpeg project
|
||||
*
|
||||
* 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 vp3dsp_sse2.c
|
||||
* SSE2-optimized functions cribbed from the original VP3 source code.
|
||||
*/
|
||||
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "mmx.h"
|
||||
|
||||
static DECLARE_ALIGNED_16(const unsigned short, SSE2_dequant_const[]) =
|
||||
{
|
||||
0,65535,65535,0,0,0,0,0, // 0x0000 0000 0000 0000 0000 FFFF FFFF 0000
|
||||
0,0,0,0,65535,65535,0,0, // 0x0000 0000 FFFF FFFF 0000 0000 0000 0000
|
||||
65535,65535,65535,0,0,0,0,0,// 0x0000 0000 0000 0000 0000 FFFF FFFF FFFF
|
||||
0,0,0,65535,0,0,0,0, // 0x0000 0000 0000 0000 FFFF 0000 0000 0000
|
||||
0,0,0,65535,65535,0,0,0, // 0x0000 0000 0000 FFFF FFFF 0000 0000 0000
|
||||
65535,0,0,0,0,65535,0,0, // 0x0000 0000 FFFF 0000 0000 0000 0000 FFFF
|
||||
0,0,65535,65535, 0,0,0,0 // 0x0000 0000 0000 0000 FFFF FFFF 0000 0000
|
||||
};
|
||||
|
||||
static DECLARE_ALIGNED_16(const unsigned int, eight_data[]) =
|
||||
{
|
||||
0x00080008,
|
||||
0x00080008,
|
||||
0x00080008,
|
||||
0x00080008
|
||||
};
|
||||
|
||||
static DECLARE_ALIGNED_16(const unsigned short, SSE2_idct_data[7 * 8]) =
|
||||
{
|
||||
64277,64277,64277,64277,64277,64277,64277,64277,
|
||||
60547,60547,60547,60547,60547,60547,60547,60547,
|
||||
54491,54491,54491,54491,54491,54491,54491,54491,
|
||||
46341,46341,46341,46341,46341,46341,46341,46341,
|
||||
36410,36410,36410,36410,36410,36410,36410,36410,
|
||||
25080,25080,25080,25080,25080,25080,25080,25080,
|
||||
12785,12785,12785,12785,12785,12785,12785,12785
|
||||
};
|
||||
|
||||
|
||||
#define SSE2_Column_IDCT() { \
|
||||
\
|
||||
movdqa_m2r(*I(3), xmm2); /* xmm2 = i3 */ \
|
||||
movdqa_m2r(*C(3), xmm6); /* xmm6 = c3 */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm4); /* xmm4 = i3 */ \
|
||||
movdqa_m2r(*I(5), xmm7); /* xmm7 = i5 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm6, xmm4); /* xmm4 = c3 * i3 - i3 */ \
|
||||
movdqa_m2r(*C(5), xmm1); /* xmm1 = c5 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 - i5 */ \
|
||||
movdqa_r2r(xmm1, xmm5); /* xmm5 = c5 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm2, xmm1); /* xmm1 = c5 * i3 - i3 */ \
|
||||
movdqa_m2r(*I(1), xmm3); /* xmm3 = i1 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm7, xmm5); /* xmm5 = c5 * i5 - i5 */ \
|
||||
movdqa_m2r(*C(1), xmm0); /* xmm0 = c1 */ \
|
||||
\
|
||||
/* all registers are in use */ \
|
||||
\
|
||||
paddw_r2r(xmm2, xmm4); /* xmm4 = c3 * i3 */ \
|
||||
paddw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 */ \
|
||||
\
|
||||
paddw_r2r(xmm1, xmm2); /* xmm2 = c5 * i3 */ \
|
||||
movdqa_m2r(*I(7), xmm1); /* xmm1 = i7 */ \
|
||||
\
|
||||
paddw_r2r(xmm5, xmm7); /* xmm7 = c5 * i5 */ \
|
||||
movdqa_r2r(xmm0, xmm5); /* xmm5 = c1 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 - i1 */ \
|
||||
paddsw_r2r(xmm7, xmm4); /* xmm4 = c3 * i3 + c5 * i5 = C */ \
|
||||
\
|
||||
pmulhw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 - i7 */ \
|
||||
movdqa_m2r(*C(7), xmm7); /* xmm7 = c7 */ \
|
||||
\
|
||||
psubsw_r2r(xmm2, xmm6); /* xmm6 = c3 * i5 - c5 * i3 = D */ \
|
||||
paddw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm7, xmm3); /* xmm3 = c7 * i1 */ \
|
||||
movdqa_m2r(*I(2), xmm2); /* xmm2 = i2 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm1, xmm7); /* xmm7 = c7 * i7 */ \
|
||||
paddw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm1); /* xmm1 = i2 */ \
|
||||
pmulhw_m2r(*C(2), xmm2); /* xmm2 = i2 * c2 -i2 */ \
|
||||
\
|
||||
psubsw_r2r(xmm5, xmm3); /* xmm3 = c7 * i1 - c1 * i7 = B */ \
|
||||
movdqa_m2r(*I(6), xmm5); /* xmm5 = i6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm7, xmm0); /* xmm0 = c1 * i1 + c7 * i7 = A */ \
|
||||
movdqa_r2r(xmm5, xmm7); /* xmm7 = i6 */ \
|
||||
\
|
||||
psubsw_r2r(xmm4, xmm0); /* xmm0 = A - C */ \
|
||||
pmulhw_m2r(*C(2), xmm5); /* xmm5 = c2 * i6 - i6 */ \
|
||||
\
|
||||
paddw_r2r(xmm1, xmm2); /* xmm2 = i2 * c2 */ \
|
||||
pmulhw_m2r(*C(6), xmm1); /* xmm1 = c6 * i2 */ \
|
||||
\
|
||||
paddsw_r2r(xmm4, xmm4); /* xmm4 = C + C */ \
|
||||
paddsw_r2r(xmm0, xmm4); /* xmm4 = A + C = C. */ \
|
||||
\
|
||||
psubsw_r2r(xmm6, xmm3); /* xmm3 = B - D */ \
|
||||
paddw_r2r(xmm7, xmm5); /* xmm5 = c2 * i6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm6, xmm6); /* xmm6 = D + D */ \
|
||||
pmulhw_m2r(*C(6), xmm7); /* xmm7 = c6 * i6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm3, xmm6); /* xmm6 = B + D = D. */ \
|
||||
movdqa_r2m(xmm4, *I(1)); /* Save C. at I(1) */ \
|
||||
\
|
||||
psubsw_r2r(xmm5, xmm1); /* xmm1 = c6 * i2 - c2 * i6 = H */ \
|
||||
movdqa_m2r(*C(4), xmm4); /* xmm4 = c4 */ \
|
||||
\
|
||||
movdqa_r2r(xmm3, xmm5); /* xmm5 = B - D */ \
|
||||
pmulhw_r2r(xmm4, xmm3); /* xmm3 = ( c4 -1 ) * ( B - D ) */ \
|
||||
\
|
||||
paddsw_r2r(xmm2, xmm7); /* xmm7 = c2 * i2 + c6 * i6 = G */ \
|
||||
movdqa_r2m(xmm6, *I(2)); /* Save D. at I(2) */ \
|
||||
\
|
||||
movdqa_r2r(xmm0, xmm2); /* xmm2 = A - C */ \
|
||||
movdqa_m2r(*I(0), xmm6); /* xmm6 = i0 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm4, xmm0); /* xmm0 = ( c4 - 1 ) * ( A - C ) = A. */ \
|
||||
paddw_r2r(xmm3, xmm5); /* xmm5 = c4 * ( B - D ) = B. */ \
|
||||
\
|
||||
movdqa_m2r(*I(4), xmm3); /* xmm3 = i4 */ \
|
||||
psubsw_r2r(xmm1, xmm5); /* xmm5 = B. - H = B.. */ \
|
||||
\
|
||||
paddw_r2r(xmm0, xmm2); /* xmm2 = c4 * ( A - C) = A. */ \
|
||||
psubsw_r2r(xmm3, xmm6); /* xmm6 = i0 - i4 */ \
|
||||
\
|
||||
movdqa_r2r(xmm6, xmm0); /* xmm0 = i0 - i4 */ \
|
||||
pmulhw_r2r(xmm4, xmm6); /* xmm6 = (c4 - 1) * (i0 - i4) = F */ \
|
||||
\
|
||||
paddsw_r2r(xmm3, xmm3); /* xmm3 = i4 + i4 */ \
|
||||
paddsw_r2r(xmm1, xmm1); /* xmm1 = H + H */ \
|
||||
\
|
||||
paddsw_r2r(xmm0, xmm3); /* xmm3 = i0 + i4 */ \
|
||||
paddsw_r2r(xmm5, xmm1); /* xmm1 = B. + H = H. */ \
|
||||
\
|
||||
pmulhw_r2r(xmm3, xmm4); /* xmm4 = ( c4 - 1 ) * ( i0 + i4 ) */ \
|
||||
paddw_r2r(xmm0, xmm6); /* xmm6 = c4 * ( i0 - i4 ) */ \
|
||||
\
|
||||
psubsw_r2r(xmm2, xmm6); /* xmm6 = F - A. = F. */ \
|
||||
paddsw_r2r(xmm2, xmm2); /* xmm2 = A. + A. */ \
|
||||
\
|
||||
movdqa_m2r(*I(1), xmm0); /* Load C. from I(1) */ \
|
||||
paddsw_r2r(xmm6, xmm2); /* xmm2 = F + A. = A.. */ \
|
||||
\
|
||||
paddw_r2r(xmm3, xmm4); /* xmm4 = c4 * ( i0 + i4 ) = 3 */ \
|
||||
psubsw_r2r(xmm1, xmm2); /* xmm2 = A.. - H. = R2 */ \
|
||||
\
|
||||
paddsw_m2r(*Eight, xmm2); /* Adjust R2 and R1 before shifting */ \
|
||||
paddsw_r2r(xmm1, xmm1); /* xmm1 = H. + H. */ \
|
||||
\
|
||||
paddsw_r2r(xmm2, xmm1); /* xmm1 = A.. + H. = R1 */ \
|
||||
psraw_i2r(4, xmm2); /* xmm2 = op2 */ \
|
||||
\
|
||||
psubsw_r2r(xmm7, xmm4); /* xmm4 = E - G = E. */ \
|
||||
psraw_i2r(4, xmm1); /* xmm1 = op1 */ \
|
||||
\
|
||||
movdqa_m2r(*I(2), xmm3); /* Load D. from I(2) */ \
|
||||
paddsw_r2r(xmm7, xmm7); /* xmm7 = G + G */ \
|
||||
\
|
||||
movdqa_r2m(xmm2, *O(2)); /* Write out op2 */ \
|
||||
paddsw_r2r(xmm4, xmm7); /* xmm7 = E + G = G. */ \
|
||||
\
|
||||
movdqa_r2m(xmm1, *O(1)); /* Write out op1 */ \
|
||||
psubsw_r2r(xmm3, xmm4); /* xmm4 = E. - D. = R4 */ \
|
||||
\
|
||||
paddsw_m2r(*Eight, xmm4); /* Adjust R4 and R3 before shifting */ \
|
||||
paddsw_r2r(xmm3, xmm3); /* xmm3 = D. + D. */ \
|
||||
\
|
||||
paddsw_r2r(xmm4, xmm3); /* xmm3 = E. + D. = R3 */ \
|
||||
psraw_i2r(4, xmm4); /* xmm4 = op4 */ \
|
||||
\
|
||||
psubsw_r2r(xmm5, xmm6); /* xmm6 = F. - B..= R6 */ \
|
||||
psraw_i2r(4, xmm3); /* xmm3 = op3 */ \
|
||||
\
|
||||
paddsw_m2r(*Eight, xmm6); /* Adjust R6 and R5 before shifting */ \
|
||||
paddsw_r2r(xmm5, xmm5); /* xmm5 = B.. + B.. */ \
|
||||
\
|
||||
paddsw_r2r(xmm6, xmm5); /* xmm5 = F. + B.. = R5 */ \
|
||||
psraw_i2r(4, xmm6); /* xmm6 = op6 */ \
|
||||
\
|
||||
movdqa_r2m(xmm4, *O(4)); /* Write out op4 */ \
|
||||
psraw_i2r(4, xmm5); /* xmm5 = op5 */ \
|
||||
\
|
||||
movdqa_r2m(xmm3, *O(3)); /* Write out op3 */ \
|
||||
psubsw_r2r(xmm0, xmm7); /* xmm7 = G. - C. = R7 */ \
|
||||
\
|
||||
paddsw_m2r(*Eight, xmm7); /* Adjust R7 and R0 before shifting */ \
|
||||
paddsw_r2r(xmm0, xmm0); /* xmm0 = C. + C. */ \
|
||||
\
|
||||
paddsw_r2r(xmm7, xmm0); /* xmm0 = G. + C. */ \
|
||||
psraw_i2r(4, xmm7); /* xmm7 = op7 */ \
|
||||
\
|
||||
movdqa_r2m(xmm6, *O(6)); /* Write out op6 */ \
|
||||
psraw_i2r(4, xmm0); /* xmm0 = op0 */ \
|
||||
\
|
||||
movdqa_r2m(xmm5, *O(5)); /* Write out op5 */ \
|
||||
movdqa_r2m(xmm7, *O(7)); /* Write out op7 */ \
|
||||
\
|
||||
movdqa_r2m(xmm0, *O(0)); /* Write out op0 */ \
|
||||
\
|
||||
} /* End of SSE2_Column_IDCT macro */
|
||||
|
||||
|
||||
#define SSE2_Row_IDCT() { \
|
||||
\
|
||||
movdqa_m2r(*I(3), xmm2); /* xmm2 = i3 */ \
|
||||
movdqa_m2r(*C(3), xmm6); /* xmm6 = c3 */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm4); /* xmm4 = i3 */ \
|
||||
movdqa_m2r(*I(5), xmm7); /* xmm7 = i5 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm6, xmm4); /* xmm4 = c3 * i3 - i3 */ \
|
||||
movdqa_m2r(*C(5), xmm1); /* xmm1 = c5 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 - i5 */ \
|
||||
movdqa_r2r(xmm1, xmm5); /* xmm5 = c5 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm2, xmm1); /* xmm1 = c5 * i3 - i3 */ \
|
||||
movdqa_m2r(*I(1), xmm3); /* xmm3 = i1 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm7, xmm5); /* xmm5 = c5 * i5 - i5 */ \
|
||||
movdqa_m2r(*C(1), xmm0); /* xmm0 = c1 */ \
|
||||
\
|
||||
/* all registers are in use */ \
|
||||
\
|
||||
paddw_r2r(xmm2, xmm4); /* xmm4 = c3 * i3 */ \
|
||||
paddw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 */ \
|
||||
\
|
||||
paddw_r2r(xmm1, xmm2); /* xmm2 = c5 * i3 */ \
|
||||
movdqa_m2r(*I(7), xmm1); /* xmm1 = i7 */ \
|
||||
\
|
||||
paddw_r2r(xmm5, xmm7); /* xmm7 = c5 * i5 */ \
|
||||
movdqa_r2r(xmm0, xmm5); /* xmm5 = c1 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 - i1 */ \
|
||||
paddsw_r2r(xmm7, xmm4); /* xmm4 = c3 * i3 + c5 * i5 = C */ \
|
||||
\
|
||||
pmulhw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 - i7 */ \
|
||||
movdqa_m2r(*C(7), xmm7); /* xmm7 = c7 */ \
|
||||
\
|
||||
psubsw_r2r(xmm2, xmm6); /* xmm6 = c3 * i5 - c5 * i3 = D */ \
|
||||
paddw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm7, xmm3); /* xmm3 = c7 * i1 */ \
|
||||
movdqa_m2r(*I(2), xmm2); /* xmm2 = i2 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm1, xmm7); /* xmm7 = c7 * i7 */ \
|
||||
paddw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm1); /* xmm1 = i2 */ \
|
||||
pmulhw_m2r(*C(2), xmm2); /* xmm2 = i2 * c2 -i2 */ \
|
||||
\
|
||||
psubsw_r2r(xmm5, xmm3); /* xmm3 = c7 * i1 - c1 * i7 = B */ \
|
||||
movdqa_m2r(*I(6), xmm5); /* xmm5 = i6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm7, xmm0); /* xmm0 = c1 * i1 + c7 * i7 = A */ \
|
||||
movdqa_r2r(xmm5, xmm7); /* xmm7 = i6 */ \
|
||||
\
|
||||
psubsw_r2r(xmm4, xmm0); /* xmm0 = A - C */ \
|
||||
pmulhw_m2r(*C(2), xmm5); /* xmm5 = c2 * i6 - i6 */ \
|
||||
\
|
||||
paddw_r2r(xmm1, xmm2); /* xmm2 = i2 * c2 */ \
|
||||
pmulhw_m2r(*C(6), xmm1); /* xmm1 = c6 * i2 */ \
|
||||
\
|
||||
paddsw_r2r(xmm4, xmm4); /* xmm4 = C + C */ \
|
||||
paddsw_r2r(xmm0, xmm4); /* xmm4 = A + C = C. */ \
|
||||
\
|
||||
psubsw_r2r(xmm6, xmm3); /* xmm3 = B - D */ \
|
||||
paddw_r2r(xmm7, xmm5); /* xmm5 = c2 * i6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm6, xmm6); /* xmm6 = D + D */ \
|
||||
pmulhw_m2r(*C(6), xmm7); /* xmm7 = c6 * i6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm3, xmm6); /* xmm6 = B + D = D. */ \
|
||||
movdqa_r2m(xmm4, *I(1)); /* Save C. at I(1) */ \
|
||||
\
|
||||
psubsw_r2r(xmm5, xmm1); /* xmm1 = c6 * i2 - c2 * i6 = H */ \
|
||||
movdqa_m2r(*C(4), xmm4); /* xmm4 = c4 */ \
|
||||
\
|
||||
movdqa_r2r(xmm3, xmm5); /* xmm5 = B - D */ \
|
||||
pmulhw_r2r(xmm4, xmm3); /* xmm3 = ( c4 -1 ) * ( B - D ) */ \
|
||||
\
|
||||
paddsw_r2r(xmm2, xmm7); /* xmm7 = c2 * i2 + c6 * i6 = G */ \
|
||||
movdqa_r2m(xmm6, *I(2)); /* Save D. at I(2) */ \
|
||||
\
|
||||
movdqa_r2r(xmm0, xmm2); /* xmm2 = A - C */ \
|
||||
movdqa_m2r(*I(0), xmm6); /* xmm6 = i0 */ \
|
||||
\
|
||||
pmulhw_r2r(xmm4, xmm0); /* xmm0 = ( c4 - 1 ) * ( A - C ) = A. */ \
|
||||
paddw_r2r(xmm3, xmm5); /* xmm5 = c4 * ( B - D ) = B. */ \
|
||||
\
|
||||
movdqa_m2r(*I(4), xmm3); /* xmm3 = i4 */ \
|
||||
psubsw_r2r(xmm1, xmm5); /* xmm5 = B. - H = B.. */ \
|
||||
\
|
||||
paddw_r2r(xmm0, xmm2); /* xmm2 = c4 * ( A - C) = A. */ \
|
||||
psubsw_r2r(xmm3, xmm6); /* xmm6 = i0 - i4 */ \
|
||||
\
|
||||
movdqa_r2r(xmm6, xmm0); /* xmm0 = i0 - i4 */ \
|
||||
pmulhw_r2r(xmm4, xmm6); /* xmm6 = ( c4 - 1 ) * ( i0 - i4 ) = F */ \
|
||||
\
|
||||
paddsw_r2r(xmm3, xmm3); /* xmm3 = i4 + i4 */ \
|
||||
paddsw_r2r(xmm1, xmm1); /* xmm1 = H + H */ \
|
||||
\
|
||||
paddsw_r2r(xmm0, xmm3); /* xmm3 = i0 + i4 */ \
|
||||
paddsw_r2r(xmm5, xmm1); /* xmm1 = B. + H = H. */ \
|
||||
\
|
||||
pmulhw_r2r(xmm3, xmm4); /* xmm4 = ( c4 - 1 ) * ( i0 + i4 ) */ \
|
||||
paddw_r2r(xmm0, xmm6); /* xmm6 = c4 * ( i0 - i4 ) */ \
|
||||
\
|
||||
psubsw_r2r(xmm2, xmm6); /* xmm6 = F - A. = F. */ \
|
||||
paddsw_r2r(xmm2, xmm2); /* xmm2 = A. + A. */ \
|
||||
\
|
||||
movdqa_m2r(*I(1), xmm0); /* Load C. from I(1) */ \
|
||||
paddsw_r2r(xmm6, xmm2); /* xmm2 = F + A. = A.. */ \
|
||||
\
|
||||
paddw_r2r(xmm3, xmm4); /* xmm4 = c4 * ( i0 + i4 ) = 3 */ \
|
||||
psubsw_r2r(xmm1, xmm2); /* xmm2 = A.. - H. = R2 */ \
|
||||
\
|
||||
paddsw_r2r(xmm1, xmm1); /* xmm1 = H. + H. */ \
|
||||
paddsw_r2r(xmm2, xmm1); /* xmm1 = A.. + H. = R1 */ \
|
||||
\
|
||||
psubsw_r2r(xmm7, xmm4); /* xmm4 = E - G = E. */ \
|
||||
\
|
||||
movdqa_m2r(*I(2), xmm3); /* Load D. from I(2) */ \
|
||||
paddsw_r2r(xmm7, xmm7); /* xmm7 = G + G */ \
|
||||
\
|
||||
movdqa_r2m(xmm2, *I(2)); /* Write out op2 */ \
|
||||
paddsw_r2r(xmm4, xmm7); /* xmm7 = E + G = G. */ \
|
||||
\
|
||||
movdqa_r2m(xmm1, *I(1)); /* Write out op1 */ \
|
||||
psubsw_r2r(xmm3, xmm4); /* xmm4 = E. - D. = R4 */ \
|
||||
\
|
||||
paddsw_r2r(xmm3, xmm3); /* xmm3 = D. + D. */ \
|
||||
\
|
||||
paddsw_r2r(xmm4, xmm3); /* xmm3 = E. + D. = R3 */ \
|
||||
\
|
||||
psubsw_r2r(xmm5, xmm6); /* xmm6 = F. - B..= R6 */ \
|
||||
\
|
||||
paddsw_r2r(xmm5, xmm5); /* xmm5 = B.. + B.. */ \
|
||||
\
|
||||
paddsw_r2r(xmm6, xmm5); /* xmm5 = F. + B.. = R5 */ \
|
||||
\
|
||||
movdqa_r2m(xmm4, *I(4)); /* Write out op4 */ \
|
||||
\
|
||||
movdqa_r2m(xmm3, *I(3)); /* Write out op3 */ \
|
||||
psubsw_r2r(xmm0, xmm7); /* xmm7 = G. - C. = R7 */ \
|
||||
\
|
||||
paddsw_r2r(xmm0, xmm0); /* xmm0 = C. + C. */ \
|
||||
\
|
||||
paddsw_r2r(xmm7, xmm0); /* xmm0 = G. + C. */ \
|
||||
\
|
||||
movdqa_r2m(xmm6, *I(6)); /* Write out op6 */ \
|
||||
\
|
||||
movdqa_r2m(xmm5, *I(5)); /* Write out op5 */ \
|
||||
movdqa_r2m(xmm7, *I(7)); /* Write out op7 */ \
|
||||
\
|
||||
movdqa_r2m(xmm0, *I(0)); /* Write out op0 */ \
|
||||
\
|
||||
} /* End of SSE2_Row_IDCT macro */
|
||||
|
||||
|
||||
#define SSE2_Transpose() { \
|
||||
\
|
||||
movdqa_m2r(*I(4), xmm4); /* xmm4=e7e6e5e4e3e2e1e0 */ \
|
||||
movdqa_m2r(*I(5), xmm0); /* xmm4=f7f6f5f4f3f2f1f0 */ \
|
||||
\
|
||||
movdqa_r2r(xmm4, xmm5); /* make a copy */ \
|
||||
punpcklwd_r2r(xmm0, xmm4); /* xmm4=f3e3f2e2f1e1f0e0 */ \
|
||||
\
|
||||
punpckhwd_r2r(xmm0, xmm5); /* xmm5=f7e7f6e6f5e5f4e4 */ \
|
||||
movdqa_m2r(*I(6), xmm6); /* xmm6=g7g6g5g4g3g2g1g0 */ \
|
||||
\
|
||||
movdqa_m2r(*I(7), xmm0); /* xmm0=h7h6h5h4h3h2h1h0 */ \
|
||||
movdqa_r2r(xmm6, xmm7); /* make a copy */ \
|
||||
\
|
||||
punpcklwd_r2r(xmm0, xmm6); /* xmm6=h3g3h3g2h1g1h0g0 */ \
|
||||
punpckhwd_r2r(xmm0, xmm7); /* xmm7=h7g7h6g6h5g5h4g4 */ \
|
||||
\
|
||||
movdqa_r2r(xmm4, xmm3); /* make a copy */ \
|
||||
punpckldq_r2r(xmm6, xmm4); /* xmm4=h1g1f1e1h0g0f0e0 */ \
|
||||
\
|
||||
punpckhdq_r2r(xmm6, xmm3); /* xmm3=h3g3g3e3h2g2f2e2 */ \
|
||||
movdqa_r2m(xmm3, *I(6)); /* save h3g3g3e3h2g2f2e2 */ \
|
||||
/* Free xmm6 */ \
|
||||
movdqa_r2r(xmm5, xmm6); /* make a copy */ \
|
||||
punpckldq_r2r(xmm7, xmm5); /* xmm5=h5g5f5e5h4g4f4e4 */ \
|
||||
\
|
||||
punpckhdq_r2r(xmm7, xmm6); /* xmm6=h7g7f7e7h6g6f6e6 */ \
|
||||
movdqa_m2r(*I(0), xmm0); /* xmm0=a7a6a5a4a3a2a1a0 */ \
|
||||
/* Free xmm7 */ \
|
||||
movdqa_m2r(*I(1), xmm1); /* xmm1=b7b6b5b4b3b2b1b0 */ \
|
||||
movdqa_r2r(xmm0, xmm7); /* make a copy */ \
|
||||
\
|
||||
punpcklwd_r2r(xmm1, xmm0); /* xmm0=b3a3b2a2b1a1b0a0 */ \
|
||||
punpckhwd_r2r(xmm1, xmm7); /* xmm7=b7a7b6a6b5a5b4a4 */ \
|
||||
/* Free xmm1 */ \
|
||||
movdqa_m2r(*I(2), xmm2); /* xmm2=c7c6c5c4c3c2c1c0 */ \
|
||||
movdqa_m2r(*I(3), xmm3); /* xmm3=d7d6d5d4d3d2d1d0 */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm1); /* make a copy */ \
|
||||
punpcklwd_r2r(xmm3, xmm2); /* xmm2=d3c3d2c2d1c1d0c0 */ \
|
||||
\
|
||||
punpckhwd_r2r(xmm3, xmm1); /* xmm1=d7c7d6c6d5c5d4c4 */ \
|
||||
movdqa_r2r(xmm0, xmm3); /* make a copy */ \
|
||||
\
|
||||
punpckldq_r2r(xmm2, xmm0); /* xmm0=d1c1b1a1d0c0b0a0 */ \
|
||||
punpckhdq_r2r(xmm2, xmm3); /* xmm3=d3c3b3a3d2c2b2a2 */ \
|
||||
/* Free xmm2 */ \
|
||||
movdqa_r2r(xmm7, xmm2); /* make a copy */ \
|
||||
punpckldq_r2r(xmm1, xmm2); /* xmm2=d5c5b5a5d4c4b4a4 */ \
|
||||
\
|
||||
punpckhdq_r2r(xmm1, xmm7); /* xmm7=d7c7b7a7d6c6b6a6 */ \
|
||||
movdqa_r2r(xmm0, xmm1); /* make a copy */ \
|
||||
\
|
||||
punpcklqdq_r2r(xmm4, xmm0); /* xmm0=h0g0f0e0d0c0b0a0 */ \
|
||||
punpckhqdq_r2r(xmm4, xmm1); /* xmm1=h1g1g1e1d1c1b1a1 */ \
|
||||
\
|
||||
movdqa_r2m(xmm0, *I(0)); /* save I(0) */ \
|
||||
movdqa_r2m(xmm1, *I(1)); /* save I(1) */ \
|
||||
\
|
||||
movdqa_m2r(*I(6), xmm0); /* load h3g3g3e3h2g2f2e2 */ \
|
||||
movdqa_r2r(xmm3, xmm1); /* make a copy */ \
|
||||
\
|
||||
punpcklqdq_r2r(xmm0, xmm1); /* xmm1=h2g2f2e2d2c2b2a2 */ \
|
||||
punpckhqdq_r2r(xmm0, xmm3); /* xmm3=h3g3f3e3d3c3b3a3 */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm4); /* make a copy */ \
|
||||
punpcklqdq_r2r(xmm5, xmm4); /* xmm4=h4g4f4e4d4c4b4a4 */ \
|
||||
\
|
||||
punpckhqdq_r2r(xmm5, xmm2); /* xmm2=h5g5f5e5d5c5b5a5 */ \
|
||||
movdqa_r2m(xmm1, *I(2)); /* save I(2) */ \
|
||||
\
|
||||
movdqa_r2m(xmm3, *I(3)); /* save I(3) */ \
|
||||
movdqa_r2m(xmm4, *I(4)); /* save I(4) */ \
|
||||
\
|
||||
movdqa_r2m(xmm2, *I(5)); /* save I(5) */ \
|
||||
movdqa_r2r(xmm7, xmm5); /* make a copy */ \
|
||||
\
|
||||
punpcklqdq_r2r(xmm6, xmm5); /* xmm5=h6g6f6e6d6c6b6a6 */ \
|
||||
punpckhqdq_r2r(xmm6, xmm7); /* xmm7=h7g7f7e7d7c7b7a7 */ \
|
||||
\
|
||||
movdqa_r2m(xmm5, *I(6)); /* save I(6) */ \
|
||||
movdqa_r2m(xmm7, *I(7)); /* save I(7) */ \
|
||||
\
|
||||
} /* End of Transpose Macro */
|
||||
|
||||
|
||||
#define SSE2_Dequantize() { \
|
||||
movdqa_m2r(*(eax), xmm0); \
|
||||
\
|
||||
pmullw_m2r(*(ebx), xmm0); /* xmm0 = 07 06 05 04 03 02 01 00 */ \
|
||||
movdqa_m2r(*(eax + 16), xmm1); \
|
||||
\
|
||||
pmullw_m2r(*(ebx + 16), xmm1); /* xmm1 = 17 16 15 14 13 12 11 10 */ \
|
||||
pshuflw_r2r(xmm0, xmm3, 0x078); /* xmm3 = 07 06 05 04 01 03 02 00 */ \
|
||||
\
|
||||
movdqa_r2r(xmm1, xmm2); /* xmm2 = 17 16 15 14 13 12 11 10 */ \
|
||||
movdqa_m2r(*(ecx), xmm7); /* xmm7 = -- -- -- -- -- FF FF -- */ \
|
||||
\
|
||||
movdqa_m2r(*(eax + 32), xmm4); \
|
||||
movdqa_m2r(*(eax + 64), xmm5); \
|
||||
\
|
||||
pmullw_m2r(*(ebx + 32), xmm4); /* xmm4 = 27 26 25 24 23 22 21 20 */ \
|
||||
pmullw_m2r(*(ebx + 64), xmm5); /* xmm5 = 47 46 45 44 43 42 41 40 */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 16), xmm6); /* xmm6 = -- -- FF FF -- -- -- -- */ \
|
||||
pand_r2r(xmm2, xmm7); /* xmm7 = -- -- -- -- -- 12 11 -- */ \
|
||||
\
|
||||
pand_r2r(xmm4, xmm6); /* xmm6 = -- -- 25 24 -- -- -- -- */ \
|
||||
pxor_r2r(xmm7, xmm2); /* xmm2 = 17 16 15 14 13 -- -- 10 */ \
|
||||
\
|
||||
pxor_r2r(xmm6, xmm4); /* xmm4 = 27 26 -- -- 23 22 21 20 */ \
|
||||
pslldq_i2r(4, xmm7); /* xmm7 = -- -- -- 12 11 -- -- -- */ \
|
||||
\
|
||||
pslldq_i2r(2, xmm6); /* xmm6 = -- 25 24 -- -- -- -- -- */ \
|
||||
por_r2r(xmm6, xmm7); /* xmm7 = -- 25 24 12 11 -- -- -- */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 32), xmm0); /* xmm0 = -- -- -- -- -- FF FF FF */ \
|
||||
movdqa_m2r(*(ecx + 48), xmm6); /* xmm6 = -- -- -- -- FF -- -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm3, xmm0); /* xmm0 = -- -- -- -- -- 03 02 00 */ \
|
||||
pand_r2r(xmm5, xmm6); /* xmm6 = -- -- -- -- 43 -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm0, xmm3); /* xmm3 = 07 06 05 04 01 -- -- -- */ \
|
||||
pxor_r2r(xmm6, xmm5); /* xmm5 = 47 46 45 44 -- 42 41 40 */ \
|
||||
\
|
||||
por_r2r(xmm7, xmm0); /* xmm0 = -- 25 24 12 11 03 02 00 */ \
|
||||
pslldq_i2r(8, xmm6); /* xmm6 = 43 -- -- -- -- -- -- -- */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm0); /* xmm0 = 43 25 24 12 11 03 02 00 */ \
|
||||
/* 02345 in use */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 64 ), xmm1); /* xmm1 = -- -- -- FF FF -- -- -- */ \
|
||||
pshuflw_r2r(xmm5, xmm5, 0x0B4); /* xmm5 = 47 46 45 44 42 -- 41 40 */ \
|
||||
\
|
||||
movdqa_r2r(xmm1, xmm7); /* xmm7 = -- -- -- FF FF -- -- -- */ \
|
||||
movdqa_r2r(xmm1, xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
|
||||
\
|
||||
movdqa_r2m(xmm0, *(eax)); /* write 43 25 24 12 11 03 02 00 */ \
|
||||
pshufhw_r2r(xmm4, xmm4, 0x0C2); /* xmm4 = 27 -- -- 26 23 22 21 20 */ \
|
||||
\
|
||||
pand_r2r(xmm4, xmm7); /* xmm7 = -- -- -- 26 23 -- -- -- */ \
|
||||
pand_r2r(xmm5, xmm1); /* xmm1 = -- -- -- 44 42 -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm7, xmm4); /* xmm4 = 27 -- -- -- -- 22 21 20 */ \
|
||||
pxor_r2r(xmm1, xmm5); /* xmm5 = 47 46 45 -- -- -- 41 40 */ \
|
||||
\
|
||||
pshuflw_r2r(xmm2, xmm2, 0x0C6); /* xmm2 = 17 16 15 14 13 10 -- -- */ \
|
||||
movdqa_r2r(xmm6, xmm0); /* xmm0 = -- -- -- FF FF -- -- -- */ \
|
||||
\
|
||||
pslldq_i2r(2, xmm7); /* xmm7 = -- -- 26 23 -- -- -- -- */ \
|
||||
pslldq_i2r(6, xmm1); /* xmm1 = 44 42 -- -- -- -- -- -- */ \
|
||||
\
|
||||
psrldq_i2r(2, xmm0); /* xmm0 = -- -- -- -- FF FF -- -- */ \
|
||||
pand_r2r(xmm3, xmm6); /* xmm6 = -- -- -- 04 01 -- -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm2, xmm0); /* xmm0 = -- -- -- -- 13 10 -- -- */ \
|
||||
pxor_r2r(xmm6, xmm3); /* xmm3 = 07 06 05 -- -- -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm0, xmm2); /* xmm2 = 17 16 15 14 -- -- -- -- */ \
|
||||
psrldq_i2r(6, xmm6); /* xmm0 = -- -- -- -- -- -- 04 01 */ \
|
||||
\
|
||||
por_r2r(xmm7, xmm1); /* xmm1 = 44 42 26 23 -- -- -- -- */ \
|
||||
por_r2r(xmm6, xmm0); /* xmm1 = -- -- -- -- 13 10 04 01 */ \
|
||||
/* 12345 in use */ \
|
||||
por_r2r(xmm0, xmm1); /* xmm1 = 44 42 26 23 13 10 04 01 */ \
|
||||
pshuflw_r2r(xmm4, xmm4, 0x093); /* xmm4 = 27 -- -- -- 22 21 20 -- */ \
|
||||
\
|
||||
pshufhw_r2r(xmm4, xmm4, 0x093); /* xmm4 = -- -- -- 27 22 21 20 -- */ \
|
||||
movdqa_r2m(xmm1, *(eax + 16)); /* write 44 42 26 23 13 10 04 01 */ \
|
||||
\
|
||||
pshufhw_r2r(xmm3, xmm3, 0x0D2); /* xmm3 = 07 05 -- 06 -- -- -- -- */ \
|
||||
movdqa_m2r(*(ecx + 64), xmm0); /* xmm0 = -- -- -- FF FF -- -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm3, xmm0); /* xmm0 = -- -- -- 06 -- -- -- -- */ \
|
||||
psrldq_i2r(12, xmm3); /* xmm3 = -- -- -- -- -- -- 07 05 */ \
|
||||
\
|
||||
psrldq_i2r(8, xmm0); /* xmm0 = -- -- -- -- -- -- -- 06 */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 64), xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
|
||||
movdqa_m2r(*(ecx + 96), xmm7); /* xmm7 = -- -- -- -- FF FF -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm4, xmm6); /* xmm6 = -- -- -- 27 22 -- -- -- */ \
|
||||
pxor_r2r(xmm6, xmm4); /* xmm4 = -- -- -- -- -- 21 20 -- */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm3); /* xmm3 = -- -- -- 27 22 -- 07 05 */ \
|
||||
pand_r2r(xmm4, xmm7); /* xmm7 = -- -- -- -- -- 21 -- -- */ \
|
||||
\
|
||||
por_r2r(xmm7, xmm0); /* xmm0 = -- -- -- -- -- 21 -- 06 */ \
|
||||
pxor_r2r(xmm7, xmm4); /* xmm4 = -- -- -- -- -- -- 20 -- */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 16 ), xmm6); /* xmm6 = -- -- FF FF -- -- -- -- */ \
|
||||
movdqa_m2r(*(ecx + 64 ), xmm1); /* xmm1 = -- -- -- FF FF -- -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm2, xmm6); /* xmm6 = -- -- 15 14 -- -- -- -- */ \
|
||||
pand_r2r(xmm6, xmm1); /* xmm1 = -- -- -- 14 -- -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm6, xmm2); /* xmm2 = 17 16 -- -- -- -- -- -- */ \
|
||||
pxor_r2r(xmm1, xmm6); /* xmm6 = -- -- 15 -- -- -- -- -- */ \
|
||||
\
|
||||
psrldq_i2r(4, xmm1); /* xmm1 = -- -- -- -- -- 14 -- -- */ \
|
||||
\
|
||||
psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- 15 -- */ \
|
||||
por_r2r(xmm1, xmm3); /* xmm3 = -- -- -- 27 22 14 07 05 */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm0); /* xmm0 = -- -- -- -- -- 21 15 06 */ \
|
||||
pshufhw_r2r(xmm5, xmm5, 0x0E1); /* xmm5 = 47 46 -- 45 -- -- 41 40 */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 64), xmm1); /* xmm1 = -- -- -- FF FF -- -- -- */ \
|
||||
pshuflw_r2r(xmm5, xmm5, 0x072); /* xmm5 = 47 46 -- 45 41 -- 40 -- */ \
|
||||
\
|
||||
movdqa_r2r(xmm1, xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
|
||||
pand_r2r(xmm5, xmm1); /* xmm1 = -- -- -- 45 41 -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm1, xmm5); /* xmm5 = 47 46 -- -- -- -- 40 -- */ \
|
||||
pslldq_i2r(4, xmm1); /* xmm1 = -- 45 41 -- -- -- -- -- */ \
|
||||
\
|
||||
pshufd_r2r(xmm5, xmm5, 0x09C); /* xmm5 = -- -- -- -- 47 46 40 -- */ \
|
||||
por_r2r(xmm1, xmm3); /* xmm3 = -- 45 41 27 22 14 07 05 */ \
|
||||
\
|
||||
movdqa_m2r(*(eax + 96), xmm1); /* xmm1 = 67 66 65 64 63 62 61 60 */ \
|
||||
pmullw_m2r(*(ebx + 96), xmm1); \
|
||||
\
|
||||
movdqa_m2r(*(ecx), xmm7); /* xmm7 = -- -- -- -- -- FF FF -- */ \
|
||||
\
|
||||
psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- -- FF */ \
|
||||
pand_r2r(xmm5, xmm7); /* xmm7 = -- -- -- -- -- 46 40 -- */ \
|
||||
\
|
||||
pand_r2r(xmm1, xmm6); /* xmm6 = -- -- -- -- -- -- -- 60 */ \
|
||||
pxor_r2r(xmm7, xmm5); /* xmm5 = -- -- -- -- 47 -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm6, xmm1); /* xmm1 = 67 66 65 64 63 62 61 -- */ \
|
||||
pslldq_i2r(2, xmm5); /* xmm5 = -- -- -- 47 -- -- -- -- */ \
|
||||
\
|
||||
pslldq_i2r(14, xmm6); /* xmm6 = 60 -- -- -- -- -- -- -- */ \
|
||||
por_r2r(xmm5, xmm4); /* xmm4 = -- -- -- 47 -- -- 20 -- */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm3); /* xmm3 = 60 45 41 27 22 14 07 05 */ \
|
||||
pslldq_i2r(6, xmm7); /* xmm7 = -- -- 46 40 -- -- -- -- */ \
|
||||
\
|
||||
movdqa_r2m(xmm3, *(eax+32)); /* write 60 45 41 27 22 14 07 05 */ \
|
||||
por_r2r(xmm7, xmm0); /* xmm0 = -- -- 46 40 -- 21 15 06 */ \
|
||||
/* 0, 1, 2, 4 in use */ \
|
||||
movdqa_m2r(*(eax + 48), xmm3); /* xmm3 = 37 36 35 34 33 32 31 30 */ \
|
||||
movdqa_m2r(*(eax + 80), xmm5); /* xmm5 = 57 56 55 54 53 52 51 50 */ \
|
||||
\
|
||||
pmullw_m2r(*(ebx + 48), xmm3); \
|
||||
pmullw_m2r(*(ebx + 80), xmm5); \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 64), xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
|
||||
movdqa_m2r(*(ecx + 64), xmm7); /* xmm7 = -- -- -- FF FF -- -- -- */ \
|
||||
\
|
||||
psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- -- FF */ \
|
||||
pslldq_i2r(8, xmm7); /* xmm7 = FF -- -- -- -- -- -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm3, xmm6); /* xmm6 = -- -- -- -- -- -- -- 30 */ \
|
||||
pand_r2r(xmm5, xmm7); /* xmm7 = 57 -- -- -- -- -- -- -- */ \
|
||||
\
|
||||
pxor_r2r(xmm6, xmm3); /* xmm3 = 37 36 35 34 33 32 31 -- */ \
|
||||
pxor_r2r(xmm7, xmm5); /* xmm5 = __ 56 55 54 53 52 51 50 */ \
|
||||
\
|
||||
pslldq_i2r(6, xmm6); /* xmm6 = -- -- -- -- 30 -- -- -- */ \
|
||||
psrldq_i2r(2, xmm7); /* xmm7 = -- 57 -- -- -- -- -- -- */ \
|
||||
\
|
||||
por_r2r(xmm7, xmm6); /* xmm6 = -- 57 -- -- 30 -- -- -- */ \
|
||||
movdqa_m2r(*(ecx), xmm7); /* xmm7 = -- -- -- -- -- FF FF -- */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm0); /* xmm0 = -- 57 46 40 30 21 15 06 */ \
|
||||
psrldq_i2r(2, xmm7); /* xmm7 = -- -- -- -- -- -- FF FF */ \
|
||||
\
|
||||
movdqa_r2r(xmm2, xmm6); /* xmm6 = 17 16 -- -- -- -- -- -- */ \
|
||||
pand_r2r(xmm1, xmm7); /* xmm7 = -- -- -- -- -- -- 61 -- */ \
|
||||
\
|
||||
pslldq_i2r(2, xmm6); /* xmm6 = 16 -- -- -- -- -- -- -- */ \
|
||||
psrldq_i2r(14, xmm2); /* xmm2 = -- -- -- -- -- -- -- 17 */ \
|
||||
\
|
||||
pxor_r2r(xmm7, xmm1); /* xmm1 = 67 66 65 64 63 62 -- -- */ \
|
||||
pslldq_i2r(12, xmm7); /* xmm7 = 61 -- -- -- -- -- -- -- */ \
|
||||
\
|
||||
psrldq_i2r(14, xmm6); /* xmm6 = -- -- -- -- -- -- -- 16 */ \
|
||||
por_r2r(xmm6, xmm4); /* xmm4 = -- -- -- 47 -- -- 20 16 */ \
|
||||
\
|
||||
por_r2r(xmm7, xmm0); /* xmm0 = 61 57 46 40 30 21 15 06 */ \
|
||||
movdqa_m2r(*(ecx), xmm6); /* xmm6 = -- -- -- -- -- FF FF -- */ \
|
||||
\
|
||||
psrldq_i2r(2, xmm6); /* xmm6 = -- -- -- -- -- -- FF FF */ \
|
||||
movdqa_r2m(xmm0, *(eax+48)); /* write 61 57 46 40 30 21 15 06 */ \
|
||||
/* 1, 2, 3, 4, 5 in use */\
|
||||
movdqa_m2r(*(ecx), xmm0); /* xmm0 = -- -- -- -- -- FF FF -- */ \
|
||||
pand_r2r(xmm3, xmm6); /* xmm6 = -- -- -- -- -- -- 31 -- */ \
|
||||
\
|
||||
movdqa_r2r(xmm3, xmm7); /* xmm7 = 37 36 35 34 33 32 31 -- */ \
|
||||
pxor_r2r(xmm6, xmm3); /* xmm3 = 37 36 35 34 33 32 -- -- */ \
|
||||
\
|
||||
pslldq_i2r(2, xmm3); /* xmm3 = 36 35 34 33 32 -- -- -- */ \
|
||||
pand_r2r(xmm1, xmm0); /* xmm0 = -- -- -- -- -- 62 -- -- */ \
|
||||
\
|
||||
psrldq_i2r(14, xmm7); /* xmm7 = -- -- -- -- -- -- -- 37 */ \
|
||||
pxor_r2r(xmm0, xmm1); /* xmm1 = 67 66 65 64 63 -- -- -- */ \
|
||||
\
|
||||
por_r2r(xmm7, xmm6); /* xmm6 = -- -- -- -- -- -- 31 37 */ \
|
||||
movdqa_m2r(*(ecx + 64), xmm7); /* xmm7 = -- -- -- FF FF -- -- -- */ \
|
||||
\
|
||||
pshuflw_r2r(xmm6, xmm6, 0x01E); /* xmm6 = -- -- -- -- 37 31 -- -- */ \
|
||||
pslldq_i2r(6, xmm7); /* xmm7 = FF FF -- -- -- -- -- -- */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm4); /* xmm4 = -- -- -- 47 37 31 20 16 */ \
|
||||
pand_r2r(xmm5, xmm7); /* xmm7 = -- 56 -- -- -- -- -- -- */ \
|
||||
\
|
||||
pslldq_i2r(8, xmm0); /* xmm0 = -- 62 -- -- -- -- -- -- */ \
|
||||
pxor_r2r(xmm7, xmm5); /* xmm5 = -- -- 55 54 53 52 51 50 */ \
|
||||
\
|
||||
psrldq_i2r(2, xmm7); /* xmm7 = -- -- 56 -- -- -- -- -- */ \
|
||||
\
|
||||
pshufhw_r2r(xmm3, xmm3, 0x087); /* xmm3 = 35 33 34 36 32 -- -- -- */ \
|
||||
por_r2r(xmm7, xmm0); /* xmm0 = -- 62 56 -- -- -- -- -- */ \
|
||||
\
|
||||
movdqa_m2r(*(eax + 112), xmm7); /* xmm7 = 77 76 75 74 73 72 71 70 */ \
|
||||
pmullw_m2r(*(ebx + 112), xmm7); \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 64), xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
|
||||
por_r2r(xmm0, xmm4); /* xmm4 = -- 62 56 47 37 31 20 16 */ \
|
||||
\
|
||||
pshuflw_r2r(xmm7, xmm7, 0x0E1); /* xmm7 = 77 76 75 74 73 72 70 71 */ \
|
||||
psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- -- FF */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx + 64), xmm0); /* xmm0 = -- -- -- FF FF -- -- -- */ \
|
||||
pand_r2r(xmm7, xmm6); /* xmm6 = -- -- -- -- -- -- -- 71 */ \
|
||||
\
|
||||
pand_r2r(xmm3, xmm0); /* xmm0 = -- -- -- 36 32 -- -- -- */ \
|
||||
pxor_r2r(xmm6, xmm7); /* xmm7 = 77 76 75 74 73 72 70 -- */ \
|
||||
\
|
||||
pxor_r2r(xmm0, xmm3); /* xmm3 = 35 33 34 -- -- -- -- -- */ \
|
||||
pslldq_i2r(14, xmm6); /* xmm6 = 71 -- -- -- -- -- -- -- */ \
|
||||
\
|
||||
psrldq_i2r(4, xmm0); /* xmm0 = -- -- -- -- -- 36 32 -- */ \
|
||||
por_r2r(xmm6, xmm4); /* xmm4 = 71 62 56 47 37 31 20 16 */ \
|
||||
\
|
||||
por_r2r(xmm0, xmm2); /* xmm2 = -- -- -- -- -- 36 32 17 */ \
|
||||
movdqa_r2m(xmm4, *(eax + 64)); /* write 71 62 56 47 37 31 20 16 */ \
|
||||
/* 1, 2, 3, 5, 7 in use */ \
|
||||
movdqa_m2r(*(ecx + 80), xmm6); /* xmm6 = -- -- FF -- -- -- -- FF */ \
|
||||
pshufhw_r2r(xmm7, xmm7, 0x0D2); /* xmm7 = 77 75 74 76 73 72 70 __ */ \
|
||||
\
|
||||
movdqa_m2r(*(ecx), xmm4); /* xmm4 = -- -- -- -- -- FF FF -- */ \
|
||||
movdqa_m2r(*(ecx+48), xmm0); /* xmm0 = -- -- -- -- FF -- -- -- */ \
|
||||
\
|
||||
pand_r2r(xmm5, xmm6); /* xmm6 = -- -- 55 -- -- -- -- 50 */ \
|
||||
pand_r2r(xmm7, xmm4); /* xmm4 = -- -- -- -- -- 72 70 -- */ \
|
||||
\
|
||||
pand_r2r(xmm1, xmm0); /* xmm0 = -- -- -- -- 63 -- -- -- */ \
|
||||
pxor_r2r(xmm6, xmm5); /* xmm5 = -- -- -- 54 53 52 51 -- */ \
|
||||
\
|
||||
pxor_r2r(xmm4, xmm7); /* xmm7 = 77 75 74 76 73 -- -- -- */ \
|
||||
pxor_r2r(xmm0, xmm1); /* xmm1 = 67 66 65 64 -- -- -- -- */ \
|
||||
\
|
||||
pshuflw_r2r(xmm6, xmm6, 0x02B); /* xmm6 = -- -- 55 -- 50 -- -- -- */ \
|
||||
pslldq_i2r(10, xmm4); /* xmm4 = 72 20 -- -- -- -- -- -- */ \
|
||||
\
|
||||
pshufhw_r2r(xmm6, xmm6, 0x0B1); /* xmm6 = -- -- -- 55 50 -- -- -- */ \
|
||||
pslldq_i2r(4, xmm0); /* xmm0 = -- -- 63 -- -- -- -- -- */ \
|
||||
\
|
||||
por_r2r(xmm4, xmm6); /* xmm6 = 72 70 -- 55 50 -- -- -- */ \
|
||||
por_r2r(xmm0, xmm2); /* xmm2 = -- -- 63 -- -- 36 32 17 */ \
|
||||
\
|
||||
por_r2r(xmm6, xmm2); /* xmm2 = 72 70 64 55 50 36 32 17 */ \
|
||||
pshufhw_r2r(xmm1, xmm1, 0x0C9); /* xmm1 = 67 64 66 65 -- -- -- -- */ \
|
||||
\
|
||||
movdqa_r2r(xmm3, xmm6); /* xmm6 = 35 33 34 -- -- -- -- -- */ \
|
||||
movdqa_r2m(xmm2, *(eax+80)); /* write 72 70 64 55 50 36 32 17 */ \
|
||||
\
|
||||
psrldq_i2r(12, xmm6); /* xmm6 = -- -- -- -- -- -- 35 33 */ \
|
||||
pslldq_i2r(4, xmm3); /* xmm3 = 34 -- -- -- -- -- -- -- */ \
|
||||
\
|
||||
pshuflw_r2r(xmm5, xmm5, 0x04E); /* xmm5 = -- -- -- 54 51 -- 53 52 */ \
|
||||
movdqa_r2r(xmm7, xmm4); /* xmm4 = 77 75 74 76 73 -- -- -- */ \
|
||||
\
|
||||
movdqa_r2r(xmm5, xmm2); /* xmm2 = -- -- -- 54 51 -- 53 52 */ \
|
||||
psrldq_i2r(10, xmm7); /* xmm7 = -- -- -- -- -- 77 75 74 */ \
|
||||
\
|
||||
pslldq_i2r(6, xmm4); /* xmm4 = 76 73 -- -- -- -- -- -- */ \
|
||||
pslldq_i2r(12, xmm2); /* xmm2 = 53 52 -- -- -- -- -- -- */ \
|
||||
\
|
||||
movdqa_r2r(xmm1, xmm0); /* xmm0 = 67 64 66 65 -- -- -- -- */ \
|
||||
psrldq_i2r(12, xmm1); /* xmm1 = -- -- -- -- -- -- 67 64 */ \
|
||||
\
|
||||
psrldq_i2r(6, xmm5); /* xmm5 = -- -- -- -- -- -- 54 51 */ \
|
||||
psrldq_i2r(14, xmm3); /* xmm3 = -- -- -- -- -- -- -- 34 */ \
|
||||
\
|
||||
pslldq_i2r(10, xmm7); /* xmm7 = 77 75 74 -- -- -- -- -- */ \
|
||||
por_r2r(xmm6, xmm4); /* xmm4 = 76 73 -- -- -- -- 35 33 */ \
|
||||
\
|
||||
psrldq_i2r(10, xmm2); /* xmm2 = -- -- -- -- -- 53 52 -- */ \
|
||||
pslldq_i2r(4, xmm0); /* xmm0 = 66 65 -- -- -- -- -- -- */ \
|
||||
\
|
||||
pslldq_i2r(8, xmm1); /* xmm1 = -- -- 67 64 -- -- -- -- */ \
|
||||
por_r2r(xmm7, xmm3); /* xmm3 = 77 75 74 -- -- -- -- 34 */ \
|
||||
\
|
||||
psrldq_i2r(6, xmm0); /* xmm0 = -- -- -- 66 65 -- -- -- */ \
|
||||
pslldq_i2r(4, xmm5); /* xmm5 = -- -- -- -- 54 51 -- -- */ \
|
||||
\
|
||||
por_r2r(xmm1, xmm4); /* xmm4 = 76 73 67 64 -- -- 35 33 */ \
|
||||
por_r2r(xmm2, xmm3); /* xmm3 = 77 75 74 -- -- 53 52 34 */ \
|
||||
\
|
||||
por_r2r(xmm5, xmm4); /* xmm4 = 76 73 67 64 54 51 35 33 */ \
|
||||
por_r2r(xmm0, xmm3); /* xmm3 = 77 75 74 66 65 53 52 34 */ \
|
||||
\
|
||||
movdqa_r2m(xmm4, *(eax+96)); /* write 76 73 67 64 54 51 35 33 */ \
|
||||
movdqa_r2m(xmm3, *(eax+112)); /* write 77 75 74 66 65 53 52 34 */ \
|
||||
\
|
||||
} /* end of SSE2_Dequantize Macro */
|
||||
|
||||
|
||||
void ff_vp3_idct_sse2(int16_t *input_data)
|
||||
{
|
||||
unsigned char *input_bytes = (unsigned char *)input_data;
|
||||
unsigned char *output_data_bytes = (unsigned char *)input_data;
|
||||
const unsigned char *idct_data_bytes = (const unsigned char *)SSE2_idct_data;
|
||||
const unsigned char *Eight = (const unsigned char *)eight_data;
|
||||
|
||||
#define eax input_bytes
|
||||
//#define ebx dequant_matrix_bytes
|
||||
#define ecx dequant_const_bytes
|
||||
#define edx idct_data_bytes
|
||||
|
||||
#define I(i) (eax + 16 * i)
|
||||
#define O(i) (ebx + 16 * i)
|
||||
#define C(i) (edx + 16 * (i-1))
|
||||
|
||||
// SSE2_Dequantize();
|
||||
|
||||
#undef ebx
|
||||
#define ebx output_data_bytes
|
||||
|
||||
SSE2_Row_IDCT();
|
||||
|
||||
SSE2_Transpose();
|
||||
|
||||
SSE2_Column_IDCT();
|
||||
}
|
||||
|
||||
void ff_vp3_idct_put_sse2(uint8_t *dest, int line_size, DCTELEM *block)
|
||||
{
|
||||
ff_vp3_idct_sse2(block);
|
||||
put_signed_pixels_clamped_mmx(block, dest, line_size);
|
||||
}
|
||||
|
||||
void ff_vp3_idct_add_sse2(uint8_t *dest, int line_size, DCTELEM *block)
|
||||
{
|
||||
ff_vp3_idct_sse2(block);
|
||||
add_pixels_clamped_mmx(block, dest, line_size);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* vp3dsp SSE2 function declarations
|
||||
* Copyright (c) 2007 Aurelien Jacobs <[email protected]>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_VP3DSP_SSE2_H
|
||||
#define FFMPEG_VP3DSP_SSE2_H
|
||||
|
||||
#include "libavcodec/dsputil.h"
|
||||
|
||||
void ff_vp3_idct_sse2(int16_t *input_data);
|
||||
void ff_vp3_idct_put_sse2(uint8_t *dest, int line_size, DCTELEM *block);
|
||||
void ff_vp3_idct_add_sse2(uint8_t *dest, int line_size, DCTELEM *block);
|
||||
|
||||
#endif /* FFMPEG_VP3DSP_SSE2_H */
|
||||
@@ -0,0 +1,546 @@
|
||||
;*****************************************************************************
|
||||
;* x86inc.asm
|
||||
;*****************************************************************************
|
||||
;* Copyright (C) 2005-2008 Loren Merritt <[email protected]>
|
||||
;*
|
||||
;* 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
|
||||
;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
;*****************************************************************************
|
||||
|
||||
; FIXME: All of the 64bit asm functions that take a stride as an argument
|
||||
; via register, assume that the high dword of that register is filled with 0.
|
||||
; This is true in practice (since we never do any 64bit arithmetic on strides,
|
||||
; and x264's strides are all positive), but is not guaranteed by the ABI.
|
||||
|
||||
; Name of the .rodata section.
|
||||
; Kludge: Something on OS X fails to align .rodata even given an align attribute,
|
||||
; so use a different read-only section.
|
||||
%macro SECTION_RODATA 0
|
||||
%ifidn __OUTPUT_FORMAT__,macho64
|
||||
SECTION .text align=16
|
||||
%elifidn __OUTPUT_FORMAT__,macho
|
||||
SECTION .text align=16
|
||||
fakegot:
|
||||
%else
|
||||
SECTION .rodata align=16
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; PIC support macros. All these macros are totally harmless when PIC is
|
||||
; not defined but can ruin everything if misused in PIC mode. On x86_32, shared
|
||||
; objects cannot directly access global variables by address, they need to
|
||||
; go through the GOT (global offset table). Most OSes do not care about it
|
||||
; and let you load non-shared .so objects (Linux, Win32...). However, OS X
|
||||
; requires PIC code in its .dylib objects.
|
||||
;
|
||||
; - GLOBAL should be used as a suffix for global addressing, eg.
|
||||
; picgetgot ebx
|
||||
; mov eax, [foo GLOBAL]
|
||||
; instead of
|
||||
; mov eax, [foo]
|
||||
;
|
||||
; - picgetgot computes the GOT address into the given register in PIC
|
||||
; mode, otherwise does nothing. You need to do this before using GLOBAL.
|
||||
; Before in both execution order and compiled code order (so GLOBAL knows
|
||||
; which register the GOT is in).
|
||||
|
||||
%ifndef PIC
|
||||
%define GLOBAL
|
||||
%macro picgetgot 1
|
||||
%endmacro
|
||||
%elifdef ARCH_X86_64
|
||||
%define PIC64
|
||||
%define GLOBAL wrt rip
|
||||
%macro picgetgot 1
|
||||
%endmacro
|
||||
%else
|
||||
%define PIC32
|
||||
%ifidn __OUTPUT_FORMAT__,macho
|
||||
; There is no real global offset table on OS X, but we still
|
||||
; need to reference our variables by offset.
|
||||
%macro picgetgot 1
|
||||
call %%getgot
|
||||
%%getgot:
|
||||
pop %1
|
||||
add %1, $$ - %%getgot
|
||||
%undef GLOBAL
|
||||
%define GLOBAL + %1 - fakegot
|
||||
%endmacro
|
||||
%else ; elf
|
||||
extern _GLOBAL_OFFSET_TABLE_
|
||||
%macro picgetgot 1
|
||||
call %%getgot
|
||||
%%getgot:
|
||||
pop %1
|
||||
add %1, _GLOBAL_OFFSET_TABLE_ + $$ - %%getgot wrt ..gotpc
|
||||
%undef GLOBAL
|
||||
%define GLOBAL + %1 wrt ..gotoff
|
||||
%endmacro
|
||||
%endif
|
||||
%endif
|
||||
|
||||
; Macros to eliminate most code duplication between x86_32 and x86_64:
|
||||
; Currently this works only for leaf functions which load all their arguments
|
||||
; into registers at the start, and make no other use of the stack. Luckily that
|
||||
; covers most of x264's asm.
|
||||
|
||||
; PROLOGUE:
|
||||
; %1 = number of arguments. loads them from stack if needed.
|
||||
; %2 = number of registers used, not including PIC. pushes callee-saved regs if needed.
|
||||
; %3 = whether global constants are used in this function. inits x86_32 PIC if needed.
|
||||
; %4 = list of names to define to registers
|
||||
; PROLOGUE can also be invoked by adding the same options to cglobal
|
||||
|
||||
; e.g.
|
||||
; cglobal foo, 2,3,0, dst, src, tmp
|
||||
; declares a function (foo), taking two args (dst and src), one local variable (tmp), and not using globals
|
||||
|
||||
; TODO Some functions can use some args directly from the stack. If they're the
|
||||
; last args then you can just not declare them, but if they're in the middle
|
||||
; we need more flexible macro.
|
||||
|
||||
; RET:
|
||||
; Pops anything that was pushed by PROLOGUE
|
||||
|
||||
; REP_RET:
|
||||
; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons
|
||||
; which are slow when a normal ret follows a branch.
|
||||
|
||||
%macro DECLARE_REG 6
|
||||
%define r%1q %2
|
||||
%define r%1d %3
|
||||
%define r%1w %4
|
||||
%define r%1b %5
|
||||
%define r%1m %6
|
||||
%define r%1 %2
|
||||
%endmacro
|
||||
|
||||
%macro DECLARE_REG_SIZE 2
|
||||
%define r%1q r%1
|
||||
%define e%1q r%1
|
||||
%define r%1d e%1
|
||||
%define e%1d e%1
|
||||
%define r%1w %1
|
||||
%define e%1w %1
|
||||
%define r%1b %2
|
||||
%define e%1b %2
|
||||
%ifndef ARCH_X86_64
|
||||
%define r%1 e%1
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
DECLARE_REG_SIZE ax, al
|
||||
DECLARE_REG_SIZE bx, bl
|
||||
DECLARE_REG_SIZE cx, cl
|
||||
DECLARE_REG_SIZE dx, dl
|
||||
DECLARE_REG_SIZE si, sil
|
||||
DECLARE_REG_SIZE di, dil
|
||||
DECLARE_REG_SIZE bp, bpl
|
||||
|
||||
%ifdef ARCH_X86_64
|
||||
%define gprsize 8
|
||||
%else
|
||||
%define gprsize 4
|
||||
%endif
|
||||
|
||||
%macro PUSH 1
|
||||
push %1
|
||||
%assign stack_offset stack_offset+gprsize
|
||||
%endmacro
|
||||
|
||||
%macro POP 1
|
||||
pop %1
|
||||
%assign stack_offset stack_offset-gprsize
|
||||
%endmacro
|
||||
|
||||
%macro SUB 2
|
||||
sub %1, %2
|
||||
%ifidn %1, rsp
|
||||
%assign stack_offset stack_offset+(%2)
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro ADD 2
|
||||
add %1, %2
|
||||
%ifidn %1, rsp
|
||||
%assign stack_offset stack_offset-(%2)
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro movifnidn 2
|
||||
%ifnidn %1, %2
|
||||
mov %1, %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro movsxdifnidn 2
|
||||
%ifnidn %1, %2
|
||||
movsxd %1, %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro ASSERT 1
|
||||
%if (%1) == 0
|
||||
%error assert failed
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro DEFINE_ARGS 0-*
|
||||
%ifdef n_arg_names
|
||||
%assign %%i 0
|
||||
%rep n_arg_names
|
||||
CAT_UNDEF arg_name %+ %%i, q
|
||||
CAT_UNDEF arg_name %+ %%i, d
|
||||
CAT_UNDEF arg_name %+ %%i, w
|
||||
CAT_UNDEF arg_name %+ %%i, b
|
||||
CAT_UNDEF arg_name, %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
%endif
|
||||
|
||||
%assign %%i 0
|
||||
%rep %0
|
||||
%xdefine %1q r %+ %%i %+ q
|
||||
%xdefine %1d r %+ %%i %+ d
|
||||
%xdefine %1w r %+ %%i %+ w
|
||||
%xdefine %1b r %+ %%i %+ b
|
||||
CAT_XDEFINE arg_name, %%i, %1
|
||||
%assign %%i %%i+1
|
||||
%rotate 1
|
||||
%endrep
|
||||
%assign n_arg_names %%i
|
||||
%endmacro
|
||||
|
||||
%ifdef ARCH_X86_64 ;==========================================================
|
||||
%ifidn __OUTPUT_FORMAT__,win32
|
||||
|
||||
DECLARE_REG 0, rcx, ecx, cx, cl, ecx
|
||||
DECLARE_REG 1, rdx, edx, dx, dl, edx
|
||||
DECLARE_REG 2, r8, r8d, r8w, r8b, r8d
|
||||
DECLARE_REG 3, r9, r9d, r9w, r9b, r9d
|
||||
DECLARE_REG 4, rdi, edi, di, dil, [rsp + stack_offset + 40]
|
||||
DECLARE_REG 5, rsi, esi, si, sil, [rsp + stack_offset + 48]
|
||||
DECLARE_REG 6, rax, eax, ax, al, [rsp + stack_offset + 56]
|
||||
%define r7m [rsp + stack_offset + 64]
|
||||
%define r8m [rsp + stack_offset + 72]
|
||||
|
||||
%macro LOAD_IF_USED 2 ; reg_id, number_of_args
|
||||
%if %1 < %2
|
||||
mov r%1, [rsp + 8 + %1*8]
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%else ;=======================================================================
|
||||
|
||||
DECLARE_REG 0, rdi, edi, di, dil, edi
|
||||
DECLARE_REG 1, rsi, esi, si, sil, esi
|
||||
DECLARE_REG 2, rdx, edx, dx, dl, edx
|
||||
DECLARE_REG 3, rcx, ecx, cx, cl, ecx
|
||||
DECLARE_REG 4, r8, r8d, r8w, r8b, r8d
|
||||
DECLARE_REG 5, r9, r9d, r9w, r9b, r9d
|
||||
DECLARE_REG 6, rax, eax, ax, al, [rsp + stack_offset + 8]
|
||||
%define r7m [rsp + stack_offset + 16]
|
||||
%define r8m [rsp + stack_offset + 24]
|
||||
|
||||
%macro LOAD_IF_USED 2 ; reg_id, number_of_args
|
||||
%if %1 < %2
|
||||
mov r%1, [rsp - 40 + %1*8]
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%endif ; !WIN64
|
||||
|
||||
%macro PROLOGUE 2-4+ 0 ; #args, #regs, pic, arg_names...
|
||||
ASSERT %2 >= %1
|
||||
ASSERT %2 <= 7
|
||||
%assign stack_offset 0
|
||||
%ifidn __OUTPUT_FORMAT__,win32
|
||||
LOAD_IF_USED 4, %1
|
||||
LOAD_IF_USED 5, %1
|
||||
%endif
|
||||
LOAD_IF_USED 6, %1
|
||||
DEFINE_ARGS %4
|
||||
%endmacro
|
||||
|
||||
%macro RET 0
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
%macro REP_RET 0
|
||||
rep ret
|
||||
%endmacro
|
||||
|
||||
%else ; X86_32 ;==============================================================
|
||||
|
||||
DECLARE_REG 0, eax, eax, ax, al, [esp + stack_offset + 4]
|
||||
DECLARE_REG 1, ecx, ecx, cx, cl, [esp + stack_offset + 8]
|
||||
DECLARE_REG 2, edx, edx, dx, dl, [esp + stack_offset + 12]
|
||||
DECLARE_REG 3, ebx, ebx, bx, bl, [esp + stack_offset + 16]
|
||||
DECLARE_REG 4, esi, esi, si, null, [esp + stack_offset + 20]
|
||||
DECLARE_REG 5, edi, edi, di, null, [esp + stack_offset + 24]
|
||||
DECLARE_REG 6, ebp, ebp, bp, null, [esp + stack_offset + 28]
|
||||
%define r7m [esp + stack_offset + 32]
|
||||
%define r8m [esp + stack_offset + 36]
|
||||
%define rsp esp
|
||||
|
||||
%macro PUSH_IF_USED 1 ; reg_id
|
||||
%if %1 < regs_used
|
||||
push r%1
|
||||
%assign stack_offset stack_offset+4
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro POP_IF_USED 1 ; reg_id
|
||||
%if %1 < regs_used
|
||||
pop r%1
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro LOAD_IF_USED 2 ; reg_id, number_of_args
|
||||
%if %1 < %2
|
||||
mov r%1, [esp + stack_offset + 4 + %1*4]
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro PROLOGUE 2-4+ 0 ; #args, #regs, pic, arg_names...
|
||||
ASSERT %2 >= %1
|
||||
%assign stack_offset 0
|
||||
%assign regs_used %2
|
||||
%ifdef PIC
|
||||
%if %3
|
||||
%assign regs_used regs_used+1
|
||||
%endif
|
||||
%endif
|
||||
ASSERT regs_used <= 7
|
||||
PUSH_IF_USED 3
|
||||
PUSH_IF_USED 4
|
||||
PUSH_IF_USED 5
|
||||
PUSH_IF_USED 6
|
||||
LOAD_IF_USED 0, %1
|
||||
LOAD_IF_USED 1, %1
|
||||
LOAD_IF_USED 2, %1
|
||||
LOAD_IF_USED 3, %1
|
||||
LOAD_IF_USED 4, %1
|
||||
LOAD_IF_USED 5, %1
|
||||
LOAD_IF_USED 6, %1
|
||||
%if %3
|
||||
picgetgot r%2
|
||||
%endif
|
||||
DEFINE_ARGS %4
|
||||
%endmacro
|
||||
|
||||
%macro RET 0
|
||||
POP_IF_USED 6
|
||||
POP_IF_USED 5
|
||||
POP_IF_USED 4
|
||||
POP_IF_USED 3
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
%macro REP_RET 0
|
||||
%if regs_used > 3
|
||||
RET
|
||||
%else
|
||||
rep ret
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%endif ;======================================================================
|
||||
|
||||
|
||||
|
||||
;=============================================================================
|
||||
; arch-independent part
|
||||
;=============================================================================
|
||||
|
||||
%assign function_align 16
|
||||
|
||||
; Symbol prefix for C linkage
|
||||
%macro cglobal 1-2+
|
||||
%ifidn __OUTPUT_FORMAT__,elf
|
||||
%ifdef PREFIX
|
||||
global _%1:function hidden
|
||||
%define %1 _%1
|
||||
%else
|
||||
global %1:function hidden
|
||||
%endif
|
||||
%else
|
||||
%ifdef PREFIX
|
||||
global _%1
|
||||
%define %1 _%1
|
||||
%else
|
||||
global %1
|
||||
%endif
|
||||
%endif
|
||||
align function_align
|
||||
%1:
|
||||
RESET_MM_PERMUTATION ; not really needed, but makes disassembly somewhat nicer
|
||||
%if %0 > 1
|
||||
PROLOGUE %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro cextern 1
|
||||
%ifdef PREFIX
|
||||
extern _%1
|
||||
%define %1 _%1
|
||||
%else
|
||||
extern %1
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; This is needed for ELF, otherwise the GNU linker assumes the stack is
|
||||
; executable by default.
|
||||
%ifidn __OUTPUT_FORMAT__,elf
|
||||
SECTION .note.GNU-stack noalloc noexec nowrite progbits
|
||||
%endif
|
||||
|
||||
%assign FENC_STRIDE 16
|
||||
%assign FDEC_STRIDE 32
|
||||
|
||||
; merge mmx and sse*
|
||||
|
||||
%macro CAT_XDEFINE 3
|
||||
%xdefine %1%2 %3
|
||||
%endmacro
|
||||
|
||||
%macro CAT_UNDEF 2
|
||||
%undef %1%2
|
||||
%endmacro
|
||||
|
||||
%macro INIT_MMX 0
|
||||
%define RESET_MM_PERMUTATION INIT_MMX
|
||||
%define mmsize 8
|
||||
%define num_mmregs 8
|
||||
%define mova movq
|
||||
%define movu movq
|
||||
%define movh movd
|
||||
%define movnt movntq
|
||||
%assign %%i 0
|
||||
%rep 8
|
||||
CAT_XDEFINE m, %%i, mm %+ %%i
|
||||
CAT_XDEFINE nmm, %%i, %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
%rep 8
|
||||
CAT_UNDEF m, %%i
|
||||
CAT_UNDEF nmm, %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro INIT_XMM 0
|
||||
%define RESET_MM_PERMUTATION INIT_XMM
|
||||
%define mmsize 16
|
||||
%define num_mmregs 8
|
||||
%ifdef ARCH_X86_64
|
||||
%define num_mmregs 16
|
||||
%endif
|
||||
%define mova movdqa
|
||||
%define movu movdqu
|
||||
%define movh movq
|
||||
%define movnt movntdq
|
||||
%assign %%i 0
|
||||
%rep num_mmregs
|
||||
CAT_XDEFINE m, %%i, xmm %+ %%i
|
||||
CAT_XDEFINE nxmm, %%i, %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
INIT_MMX
|
||||
|
||||
; I often want to use macros that permute their arguments. e.g. there's no
|
||||
; efficient way to implement butterfly or transpose or dct without swapping some
|
||||
; arguments.
|
||||
;
|
||||
; I would like to not have to manually keep track of the permutations:
|
||||
; If I insert a permutation in the middle of a function, it should automatically
|
||||
; change everything that follows. For more complex macros I may also have multiple
|
||||
; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations.
|
||||
;
|
||||
; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that
|
||||
; permutes its arguments. It's equivalent to exchanging the contents of the
|
||||
; registers, except that this way you exchange the register names instead, so it
|
||||
; doesn't cost any cycles.
|
||||
|
||||
%macro PERMUTE 2-* ; takes a list of pairs to swap
|
||||
%rep %0/2
|
||||
%xdefine tmp%2 m%2
|
||||
%xdefine ntmp%2 nm%2
|
||||
%rotate 2
|
||||
%endrep
|
||||
%rep %0/2
|
||||
%xdefine m%1 tmp%2
|
||||
%xdefine nm%1 ntmp%2
|
||||
%undef tmp%2
|
||||
%undef ntmp%2
|
||||
%rotate 2
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro SWAP 2-* ; swaps a single chain (sometimes more concise than pairs)
|
||||
%rep %0-1
|
||||
%ifdef m%1
|
||||
%xdefine tmp m%1
|
||||
%xdefine m%1 m%2
|
||||
%xdefine m%2 tmp
|
||||
CAT_XDEFINE n, m%1, %1
|
||||
CAT_XDEFINE n, m%2, %2
|
||||
%else
|
||||
; If we were called as "SWAP m0,m1" rather than "SWAP 0,1" infer the original numbers here.
|
||||
; Be careful using this mode in nested macros though, as in some cases there may be
|
||||
; other copies of m# that have already been dereferenced and don't get updated correctly.
|
||||
%xdefine %%n1 n %+ %1
|
||||
%xdefine %%n2 n %+ %2
|
||||
%xdefine tmp m %+ %%n1
|
||||
CAT_XDEFINE m, %%n1, m %+ %%n2
|
||||
CAT_XDEFINE m, %%n2, tmp
|
||||
CAT_XDEFINE n, m %+ %%n1, %%n1
|
||||
CAT_XDEFINE n, m %+ %%n2, %%n2
|
||||
%endif
|
||||
%undef tmp
|
||||
%rotate 1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro SAVE_MM_PERMUTATION 1
|
||||
%assign %%i 0
|
||||
%rep num_mmregs
|
||||
CAT_XDEFINE %1_m, %%i, m %+ %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro LOAD_MM_PERMUTATION 1
|
||||
%assign %%i 0
|
||||
%rep num_mmregs
|
||||
CAT_XDEFINE m, %%i, %1_m %+ %%i
|
||||
%assign %%i %%i+1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro call 1
|
||||
call %1
|
||||
%ifdef %1_m0
|
||||
LOAD_MM_PERMUTATION %1
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; substitutions which are functionally identical but reduce code size
|
||||
%define movdqa movaps
|
||||
%define movdqu movups
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
/*
|
||||
* Id Quake II CIN Video Decoder
|
||||
* id Quake II CIN Video Decoder
|
||||
* Copyright (C) 2003 the ffmpeg project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file idcinvideo.c
|
||||
* Id Quake II Cin Video Decoder by Dr. Tim Ferguson
|
||||
* For more information about the Id CIN format, visit:
|
||||
* id Quake II Cin Video Decoder by Dr. Tim Ferguson
|
||||
* For more information about the id CIN format, visit:
|
||||
* http://www.csse.monash.edu.au/~timf/
|
||||
*
|
||||
* This video decoder outputs PAL8 colorspace data. Interacting with this
|
||||
@@ -31,7 +32,7 @@
|
||||
* the demuxer must use the same extradata space to transmit an
|
||||
* AVPaletteControl structure.
|
||||
*
|
||||
* Id CIN video is purely Huffman-coded, intraframe-only codec. It achieves
|
||||
* id CIN video is purely Huffman-coded, intraframe-only codec. It achieves
|
||||
* a little more compression by exploiting the fact that adjacent pixels
|
||||
* tend to be similar.
|
||||
*
|
||||
@@ -48,9 +49,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
#define HUFFMAN_TABLE_SIZE 64 * 1024
|
||||
#define HUF_TOKENS 256
|
||||
@@ -66,10 +65,9 @@ typedef struct
|
||||
typedef struct IdcinContext {
|
||||
|
||||
AVCodecContext *avctx;
|
||||
DSPContext dsp;
|
||||
AVFrame frame;
|
||||
|
||||
unsigned char *buf;
|
||||
const unsigned char *buf;
|
||||
int size;
|
||||
|
||||
hnode_t huff_nodes[256][HUF_TOKENS*2];
|
||||
@@ -115,7 +113,7 @@ static int huff_smallest_node(hnode_t *hnodes, int num_hnodes) {
|
||||
* num_huff_nodes[prev] - contains the index to the root node of the tree.
|
||||
* That is: huff_nodes[prev][num_huff_nodes[prev]] is the root node.
|
||||
*/
|
||||
static void huff_build_tree(IdcinContext *s, int prev) {
|
||||
static av_cold void huff_build_tree(IdcinContext *s, int prev) {
|
||||
hnode_t *node, *hnodes;
|
||||
int num_hnodes, i;
|
||||
|
||||
@@ -145,20 +143,18 @@ static void huff_build_tree(IdcinContext *s, int prev) {
|
||||
s->num_huff_nodes[prev] = num_hnodes - 1;
|
||||
}
|
||||
|
||||
static int idcin_decode_init(AVCodecContext *avctx)
|
||||
static av_cold int idcin_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
IdcinContext *s = (IdcinContext *)avctx->priv_data;
|
||||
IdcinContext *s = avctx->priv_data;
|
||||
int i, j, histogram_index = 0;
|
||||
unsigned char *histograms;
|
||||
|
||||
s->avctx = avctx;
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
avctx->has_b_frames = 0;
|
||||
dsputil_init(&s->dsp, avctx);
|
||||
|
||||
/* make sure the Huffman tables make it */
|
||||
if (s->avctx->extradata_size != HUFFMAN_TABLE_SIZE) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, " Id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE);
|
||||
av_log(s->avctx, AV_LOG_ERROR, " id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -192,7 +188,7 @@ static void idcin_decode_vlcs(IdcinContext *s)
|
||||
|
||||
while(node_num >= HUF_TOKENS) {
|
||||
if(!bit_pos) {
|
||||
if(dat_pos > s->size) {
|
||||
if(dat_pos >= s->size) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n");
|
||||
return;
|
||||
}
|
||||
@@ -213,9 +209,9 @@ static void idcin_decode_vlcs(IdcinContext *s)
|
||||
|
||||
static int idcin_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
uint8_t *buf, int buf_size)
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
IdcinContext *s = (IdcinContext *)avctx->priv_data;
|
||||
IdcinContext *s = avctx->priv_data;
|
||||
AVPaletteControl *palette_control = avctx->palctrl;
|
||||
|
||||
s->buf = buf;
|
||||
@@ -225,7 +221,7 @@ static int idcin_decode_frame(AVCodecContext *avctx,
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
|
||||
if (avctx->get_buffer(avctx, &s->frame)) {
|
||||
av_log(avctx, AV_LOG_ERROR, " Id CIN Video: get_buffer() failed\n");
|
||||
av_log(avctx, AV_LOG_ERROR, " id CIN Video: get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -246,9 +242,9 @@ static int idcin_decode_frame(AVCodecContext *avctx,
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int idcin_decode_end(AVCodecContext *avctx)
|
||||
static av_cold int idcin_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
IdcinContext *s = (IdcinContext *)avctx->priv_data;
|
||||
IdcinContext *s = avctx->priv_data;
|
||||
|
||||
if (s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
@@ -266,5 +262,6 @@ AVCodec idcin_decoder = {
|
||||
idcin_decode_end,
|
||||
idcin_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"),
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,829 @@
|
||||
/*
|
||||
* IMC compatible decoder
|
||||
* Copyright (c) 2002-2004 Maxim Poliakovski
|
||||
* Copyright (c) 2006 Benjamin Larsson
|
||||
* Copyright (c) 2006 Konstantin Shishkov
|
||||
*
|
||||
* 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 imc.c IMC - Intel Music Coder
|
||||
* A mdct based codec using a 256 points large transform
|
||||
* divied into 32 bands with some mix of scale factors.
|
||||
* Only mono is supported.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ALT_BITSTREAM_READER
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
#include "imcdata.h"
|
||||
|
||||
#define IMC_BLOCK_SIZE 64
|
||||
#define IMC_FRAME_ID 0x21
|
||||
#define BANDS 32
|
||||
#define COEFFS 256
|
||||
|
||||
typedef struct {
|
||||
float old_floor[BANDS];
|
||||
float flcoeffs1[BANDS];
|
||||
float flcoeffs2[BANDS];
|
||||
float flcoeffs3[BANDS];
|
||||
float flcoeffs4[BANDS];
|
||||
float flcoeffs5[BANDS];
|
||||
float flcoeffs6[BANDS];
|
||||
float CWdecoded[COEFFS];
|
||||
|
||||
/** MDCT tables */
|
||||
//@{
|
||||
float mdct_sine_window[COEFFS];
|
||||
float post_cos[COEFFS];
|
||||
float post_sin[COEFFS];
|
||||
float pre_coef1[COEFFS];
|
||||
float pre_coef2[COEFFS];
|
||||
float last_fft_im[COEFFS];
|
||||
//@}
|
||||
|
||||
int bandWidthT[BANDS]; ///< codewords per band
|
||||
int bitsBandT[BANDS]; ///< how many bits per codeword in band
|
||||
int CWlengthT[COEFFS]; ///< how many bits in each codeword
|
||||
int levlCoeffBuf[BANDS];
|
||||
int bandFlagsBuf[BANDS]; ///< flags for each band
|
||||
int sumLenArr[BANDS]; ///< bits for all coeffs in band
|
||||
int skipFlagRaw[BANDS]; ///< skip flags are stored in raw form or not
|
||||
int skipFlagBits[BANDS]; ///< bits used to code skip flags
|
||||
int skipFlagCount[BANDS]; ///< skipped coeffients per band
|
||||
int skipFlags[COEFFS]; ///< skip coefficient decoding or not
|
||||
int codewords[COEFFS]; ///< raw codewords read from bitstream
|
||||
float sqrt_tab[30];
|
||||
GetBitContext gb;
|
||||
int decoder_reset;
|
||||
float one_div_log2;
|
||||
|
||||
DSPContext dsp;
|
||||
FFTContext fft;
|
||||
DECLARE_ALIGNED_16(FFTComplex, samples[COEFFS/2]);
|
||||
DECLARE_ALIGNED_16(float, out_samples[COEFFS]);
|
||||
} IMCContext;
|
||||
|
||||
static VLC huffman_vlc[4][4];
|
||||
|
||||
#define VLC_TABLES_SIZE 9512
|
||||
|
||||
static const int vlc_offsets[17] = {
|
||||
0, 640, 1156, 1732, 2308, 2852, 3396, 3924,
|
||||
4452, 5220, 5860, 6628, 7268, 7908, 8424, 8936, VLC_TABLES_SIZE};
|
||||
|
||||
static VLC_TYPE vlc_tables[VLC_TABLES_SIZE][2];
|
||||
|
||||
static av_cold int imc_decode_init(AVCodecContext * avctx)
|
||||
{
|
||||
int i, j;
|
||||
IMCContext *q = avctx->priv_data;
|
||||
double r1, r2;
|
||||
|
||||
q->decoder_reset = 1;
|
||||
|
||||
for(i = 0; i < BANDS; i++)
|
||||
q->old_floor[i] = 1.0;
|
||||
|
||||
/* Build mdct window, a simple sine window normalized with sqrt(2) */
|
||||
ff_sine_window_init(q->mdct_sine_window, COEFFS);
|
||||
for(i = 0; i < COEFFS; i++)
|
||||
q->mdct_sine_window[i] *= sqrt(2.0);
|
||||
for(i = 0; i < COEFFS/2; i++){
|
||||
q->post_cos[i] = cos(i / 256.0 * M_PI);
|
||||
q->post_sin[i] = sin(i / 256.0 * M_PI);
|
||||
|
||||
r1 = sin((i * 4.0 + 1.0) / 1024.0 * M_PI);
|
||||
r2 = cos((i * 4.0 + 1.0) / 1024.0 * M_PI);
|
||||
|
||||
if (i & 0x1)
|
||||
{
|
||||
q->pre_coef1[i] = (r1 + r2) * sqrt(2.0);
|
||||
q->pre_coef2[i] = -(r1 - r2) * sqrt(2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
q->pre_coef1[i] = -(r1 + r2) * sqrt(2.0);
|
||||
q->pre_coef2[i] = (r1 - r2) * sqrt(2.0);
|
||||
}
|
||||
|
||||
q->last_fft_im[i] = 0;
|
||||
}
|
||||
|
||||
/* Generate a square root table */
|
||||
|
||||
for(i = 0; i < 30; i++) {
|
||||
q->sqrt_tab[i] = sqrt(i);
|
||||
}
|
||||
|
||||
/* initialize the VLC tables */
|
||||
for(i = 0; i < 4 ; i++) {
|
||||
for(j = 0; j < 4; j++) {
|
||||
huffman_vlc[i][j].table = vlc_tables[vlc_offsets[i * 4 + j]];
|
||||
huffman_vlc[i][j].table_allocated = vlc_offsets[i * 4 + j + 1] - vlc_offsets[i * 4 + j];
|
||||
init_vlc(&huffman_vlc[i][j], 9, imc_huffman_sizes[i],
|
||||
imc_huffman_lens[i][j], 1, 1,
|
||||
imc_huffman_bits[i][j], 2, 2, INIT_VLC_USE_NEW_STATIC);
|
||||
}
|
||||
}
|
||||
q->one_div_log2 = 1/log(2);
|
||||
|
||||
ff_fft_init(&q->fft, 7, 1);
|
||||
dsputil_init(&q->dsp, avctx);
|
||||
avctx->sample_fmt = SAMPLE_FMT_S16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imc_calculate_coeffs(IMCContext* q, float* flcoeffs1, float* flcoeffs2, int* bandWidthT,
|
||||
float* flcoeffs3, float* flcoeffs5)
|
||||
{
|
||||
float workT1[BANDS];
|
||||
float workT2[BANDS];
|
||||
float workT3[BANDS];
|
||||
float snr_limit = 1.e-30;
|
||||
float accum = 0.0;
|
||||
int i, cnt2;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
flcoeffs5[i] = workT2[i] = 0.0;
|
||||
if (bandWidthT[i]){
|
||||
workT1[i] = flcoeffs1[i] * flcoeffs1[i];
|
||||
flcoeffs3[i] = 2.0 * flcoeffs2[i];
|
||||
} else {
|
||||
workT1[i] = 0.0;
|
||||
flcoeffs3[i] = -30000.0;
|
||||
}
|
||||
workT3[i] = bandWidthT[i] * workT1[i] * 0.01;
|
||||
if (workT3[i] <= snr_limit)
|
||||
workT3[i] = 0.0;
|
||||
}
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
for(cnt2 = i; cnt2 < cyclTab[i]; cnt2++)
|
||||
flcoeffs5[cnt2] = flcoeffs5[cnt2] + workT3[i];
|
||||
workT2[cnt2-1] = workT2[cnt2-1] + workT3[i];
|
||||
}
|
||||
|
||||
for(i = 1; i < BANDS; i++) {
|
||||
accum = (workT2[i-1] + accum) * imc_weights1[i-1];
|
||||
flcoeffs5[i] += accum;
|
||||
}
|
||||
|
||||
for(i = 0; i < BANDS; i++)
|
||||
workT2[i] = 0.0;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
for(cnt2 = i-1; cnt2 > cyclTab2[i]; cnt2--)
|
||||
flcoeffs5[cnt2] += workT3[i];
|
||||
workT2[cnt2+1] += workT3[i];
|
||||
}
|
||||
|
||||
accum = 0.0;
|
||||
|
||||
for(i = BANDS-2; i >= 0; i--) {
|
||||
accum = (workT2[i+1] + accum) * imc_weights2[i];
|
||||
flcoeffs5[i] += accum;
|
||||
//there is missing code here, but it seems to never be triggered
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void imc_read_level_coeffs(IMCContext* q, int stream_format_code, int* levlCoeffs)
|
||||
{
|
||||
int i;
|
||||
VLC *hufftab[4];
|
||||
int start = 0;
|
||||
const uint8_t *cb_sel;
|
||||
int s;
|
||||
|
||||
s = stream_format_code >> 1;
|
||||
hufftab[0] = &huffman_vlc[s][0];
|
||||
hufftab[1] = &huffman_vlc[s][1];
|
||||
hufftab[2] = &huffman_vlc[s][2];
|
||||
hufftab[3] = &huffman_vlc[s][3];
|
||||
cb_sel = imc_cb_select[s];
|
||||
|
||||
if(stream_format_code & 4)
|
||||
start = 1;
|
||||
if(start)
|
||||
levlCoeffs[0] = get_bits(&q->gb, 7);
|
||||
for(i = start; i < BANDS; i++){
|
||||
levlCoeffs[i] = get_vlc2(&q->gb, hufftab[cb_sel[i]]->table, hufftab[cb_sel[i]]->bits, 2);
|
||||
if(levlCoeffs[i] == 17)
|
||||
levlCoeffs[i] += get_bits(&q->gb, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void imc_decode_level_coefficients(IMCContext* q, int* levlCoeffBuf, float* flcoeffs1,
|
||||
float* flcoeffs2)
|
||||
{
|
||||
int i, level;
|
||||
float tmp, tmp2;
|
||||
//maybe some frequency division thingy
|
||||
|
||||
flcoeffs1[0] = 20000.0 / pow (2, levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125
|
||||
flcoeffs2[0] = log(flcoeffs1[0])/log(2);
|
||||
tmp = flcoeffs1[0];
|
||||
tmp2 = flcoeffs2[0];
|
||||
|
||||
for(i = 1; i < BANDS; i++) {
|
||||
level = levlCoeffBuf[i];
|
||||
if (level == 16) {
|
||||
flcoeffs1[i] = 1.0;
|
||||
flcoeffs2[i] = 0.0;
|
||||
} else {
|
||||
if (level < 17)
|
||||
level -=7;
|
||||
else if (level <= 24)
|
||||
level -=32;
|
||||
else
|
||||
level -=16;
|
||||
|
||||
tmp *= imc_exp_tab[15 + level];
|
||||
tmp2 += 0.83048 * level; // 0.83048 = log2(10) * 0.25
|
||||
flcoeffs1[i] = tmp;
|
||||
flcoeffs2[i] = tmp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void imc_decode_level_coefficients2(IMCContext* q, int* levlCoeffBuf, float* old_floor, float* flcoeffs1,
|
||||
float* flcoeffs2) {
|
||||
int i;
|
||||
//FIXME maybe flag_buf = noise coding and flcoeffs1 = new scale factors
|
||||
// and flcoeffs2 old scale factors
|
||||
// might be incomplete due to a missing table that is in the binary code
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
flcoeffs1[i] = 0;
|
||||
if(levlCoeffBuf[i] < 16) {
|
||||
flcoeffs1[i] = imc_exp_tab2[levlCoeffBuf[i]] * old_floor[i];
|
||||
flcoeffs2[i] = (levlCoeffBuf[i]-7) * 0.83048 + flcoeffs2[i]; // 0.83048 = log2(10) * 0.25
|
||||
} else {
|
||||
flcoeffs1[i] = old_floor[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bit allocation depending on bits available
|
||||
*/
|
||||
static int bit_allocation (IMCContext* q, int stream_format_code, int freebits, int flag) {
|
||||
int i, j;
|
||||
const float limit = -1.e20;
|
||||
float highest = 0.0;
|
||||
int indx;
|
||||
int t1 = 0;
|
||||
int t2 = 1;
|
||||
float summa = 0.0;
|
||||
int iacc = 0;
|
||||
int summer = 0;
|
||||
int rres, cwlen;
|
||||
float lowest = 1.e10;
|
||||
int low_indx = 0;
|
||||
float workT[32];
|
||||
int flg;
|
||||
int found_indx = 0;
|
||||
|
||||
for(i = 0; i < BANDS; i++)
|
||||
highest = FFMAX(highest, q->flcoeffs1[i]);
|
||||
|
||||
for(i = 0; i < BANDS-1; i++) {
|
||||
q->flcoeffs4[i] = q->flcoeffs3[i] - log(q->flcoeffs5[i])/log(2);
|
||||
}
|
||||
q->flcoeffs4[BANDS - 1] = limit;
|
||||
|
||||
highest = highest * 0.25;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
indx = -1;
|
||||
if ((band_tab[i+1] - band_tab[i]) == q->bandWidthT[i])
|
||||
indx = 0;
|
||||
|
||||
if ((band_tab[i+1] - band_tab[i]) > q->bandWidthT[i])
|
||||
indx = 1;
|
||||
|
||||
if (((band_tab[i+1] - band_tab[i])/2) >= q->bandWidthT[i])
|
||||
indx = 2;
|
||||
|
||||
if (indx == -1)
|
||||
return -1;
|
||||
|
||||
q->flcoeffs4[i] = q->flcoeffs4[i] + xTab[(indx*2 + (q->flcoeffs1[i] < highest)) * 2 + flag];
|
||||
}
|
||||
|
||||
if (stream_format_code & 0x2) {
|
||||
q->flcoeffs4[0] = limit;
|
||||
q->flcoeffs4[1] = limit;
|
||||
q->flcoeffs4[2] = limit;
|
||||
q->flcoeffs4[3] = limit;
|
||||
}
|
||||
|
||||
for(i = (stream_format_code & 0x2)?4:0; i < BANDS-1; i++) {
|
||||
iacc += q->bandWidthT[i];
|
||||
summa += q->bandWidthT[i] * q->flcoeffs4[i];
|
||||
}
|
||||
q->bandWidthT[BANDS-1] = 0;
|
||||
summa = (summa * 0.5 - freebits) / iacc;
|
||||
|
||||
|
||||
for(i = 0; i < BANDS/2; i++) {
|
||||
rres = summer - freebits;
|
||||
if((rres >= -8) && (rres <= 8)) break;
|
||||
|
||||
summer = 0;
|
||||
iacc = 0;
|
||||
|
||||
for(j = (stream_format_code & 0x2)?4:0; j < BANDS; j++) {
|
||||
cwlen = av_clip((int)((q->flcoeffs4[j] * 0.5) - summa + 0.5), 0, 6);
|
||||
|
||||
q->bitsBandT[j] = cwlen;
|
||||
summer += q->bandWidthT[j] * cwlen;
|
||||
|
||||
if (cwlen > 0)
|
||||
iacc += q->bandWidthT[j];
|
||||
}
|
||||
|
||||
flg = t2;
|
||||
t2 = 1;
|
||||
if (freebits < summer)
|
||||
t2 = -1;
|
||||
if (i == 0)
|
||||
flg = t2;
|
||||
if(flg != t2)
|
||||
t1++;
|
||||
|
||||
summa = (float)(summer - freebits) / ((t1 + 1) * iacc) + summa;
|
||||
}
|
||||
|
||||
for(i = (stream_format_code & 0x2)?4:0; i < BANDS; i++) {
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++)
|
||||
q->CWlengthT[j] = q->bitsBandT[i];
|
||||
}
|
||||
|
||||
if (freebits > summer) {
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
workT[i] = (q->bitsBandT[i] == 6) ? -1.e20 : (q->bitsBandT[i] * -2 + q->flcoeffs4[i] - 0.415);
|
||||
}
|
||||
|
||||
highest = 0.0;
|
||||
|
||||
do{
|
||||
if (highest <= -1.e20)
|
||||
break;
|
||||
|
||||
found_indx = 0;
|
||||
highest = -1.e20;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
if (workT[i] > highest) {
|
||||
highest = workT[i];
|
||||
found_indx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (highest > -1.e20) {
|
||||
workT[found_indx] -= 2.0;
|
||||
if (++(q->bitsBandT[found_indx]) == 6)
|
||||
workT[found_indx] = -1.e20;
|
||||
|
||||
for(j = band_tab[found_indx]; j < band_tab[found_indx+1] && (freebits > summer); j++){
|
||||
q->CWlengthT[j]++;
|
||||
summer++;
|
||||
}
|
||||
}
|
||||
}while (freebits > summer);
|
||||
}
|
||||
if (freebits < summer) {
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
workT[i] = q->bitsBandT[i] ? (q->bitsBandT[i] * -2 + q->flcoeffs4[i] + 1.585) : 1.e20;
|
||||
}
|
||||
if (stream_format_code & 0x2) {
|
||||
workT[0] = 1.e20;
|
||||
workT[1] = 1.e20;
|
||||
workT[2] = 1.e20;
|
||||
workT[3] = 1.e20;
|
||||
}
|
||||
while (freebits < summer){
|
||||
lowest = 1.e10;
|
||||
low_indx = 0;
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
if (workT[i] < lowest) {
|
||||
lowest = workT[i];
|
||||
low_indx = i;
|
||||
}
|
||||
}
|
||||
//if(lowest >= 1.e10) break;
|
||||
workT[low_indx] = lowest + 2.0;
|
||||
|
||||
if (!(--q->bitsBandT[low_indx]))
|
||||
workT[low_indx] = 1.e20;
|
||||
|
||||
for(j = band_tab[low_indx]; j < band_tab[low_indx+1] && (freebits < summer); j++){
|
||||
if(q->CWlengthT[j] > 0){
|
||||
q->CWlengthT[j]--;
|
||||
summer--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imc_get_skip_coeff(IMCContext* q) {
|
||||
int i, j;
|
||||
|
||||
memset(q->skipFlagBits, 0, sizeof(q->skipFlagBits));
|
||||
memset(q->skipFlagCount, 0, sizeof(q->skipFlagCount));
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
if (!q->bandFlagsBuf[i] || !q->bandWidthT[i])
|
||||
continue;
|
||||
|
||||
if (!q->skipFlagRaw[i]) {
|
||||
q->skipFlagBits[i] = band_tab[i+1] - band_tab[i];
|
||||
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++) {
|
||||
if ((q->skipFlags[j] = get_bits1(&q->gb)))
|
||||
q->skipFlagCount[i]++;
|
||||
}
|
||||
} else {
|
||||
for(j = band_tab[i]; j < (band_tab[i+1]-1); j += 2) {
|
||||
if(!get_bits1(&q->gb)){//0
|
||||
q->skipFlagBits[i]++;
|
||||
q->skipFlags[j]=1;
|
||||
q->skipFlags[j+1]=1;
|
||||
q->skipFlagCount[i] += 2;
|
||||
}else{
|
||||
if(get_bits1(&q->gb)){//11
|
||||
q->skipFlagBits[i] +=2;
|
||||
q->skipFlags[j]=0;
|
||||
q->skipFlags[j+1]=1;
|
||||
q->skipFlagCount[i]++;
|
||||
}else{
|
||||
q->skipFlagBits[i] +=3;
|
||||
q->skipFlags[j+1]=0;
|
||||
if(!get_bits1(&q->gb)){//100
|
||||
q->skipFlags[j]=1;
|
||||
q->skipFlagCount[i]++;
|
||||
}else{//101
|
||||
q->skipFlags[j]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j < band_tab[i+1]) {
|
||||
q->skipFlagBits[i]++;
|
||||
if ((q->skipFlags[j] = get_bits1(&q->gb)))
|
||||
q->skipFlagCount[i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase highest' band coefficient sizes as some bits won't be used
|
||||
*/
|
||||
static void imc_adjust_bit_allocation (IMCContext* q, int summer) {
|
||||
float workT[32];
|
||||
int corrected = 0;
|
||||
int i, j;
|
||||
float highest = 0;
|
||||
int found_indx=0;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
workT[i] = (q->bitsBandT[i] == 6) ? -1.e20 : (q->bitsBandT[i] * -2 + q->flcoeffs4[i] - 0.415);
|
||||
}
|
||||
|
||||
while (corrected < summer) {
|
||||
if(highest <= -1.e20)
|
||||
break;
|
||||
|
||||
highest = -1.e20;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
if (workT[i] > highest) {
|
||||
highest = workT[i];
|
||||
found_indx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (highest > -1.e20) {
|
||||
workT[found_indx] -= 2.0;
|
||||
if (++(q->bitsBandT[found_indx]) == 6)
|
||||
workT[found_indx] = -1.e20;
|
||||
|
||||
for(j = band_tab[found_indx]; j < band_tab[found_indx+1] && (corrected < summer); j++) {
|
||||
if (!q->skipFlags[j] && (q->CWlengthT[j] < 6)) {
|
||||
q->CWlengthT[j]++;
|
||||
corrected++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void imc_imdct256(IMCContext *q) {
|
||||
int i;
|
||||
float re, im;
|
||||
|
||||
/* prerotation */
|
||||
for(i=0; i < COEFFS/2; i++){
|
||||
q->samples[i].re = -(q->pre_coef1[i] * q->CWdecoded[COEFFS-1-i*2]) -
|
||||
(q->pre_coef2[i] * q->CWdecoded[i*2]);
|
||||
q->samples[i].im = (q->pre_coef2[i] * q->CWdecoded[COEFFS-1-i*2]) -
|
||||
(q->pre_coef1[i] * q->CWdecoded[i*2]);
|
||||
}
|
||||
|
||||
/* FFT */
|
||||
ff_fft_permute(&q->fft, q->samples);
|
||||
ff_fft_calc (&q->fft, q->samples);
|
||||
|
||||
/* postrotation, window and reorder */
|
||||
for(i = 0; i < COEFFS/2; i++){
|
||||
re = (q->samples[i].re * q->post_cos[i]) + (-q->samples[i].im * q->post_sin[i]);
|
||||
im = (-q->samples[i].im * q->post_cos[i]) - (q->samples[i].re * q->post_sin[i]);
|
||||
q->out_samples[i*2] = (q->mdct_sine_window[COEFFS-1-i*2] * q->last_fft_im[i]) + (q->mdct_sine_window[i*2] * re);
|
||||
q->out_samples[COEFFS-1-i*2] = (q->mdct_sine_window[i*2] * q->last_fft_im[i]) - (q->mdct_sine_window[COEFFS-1-i*2] * re);
|
||||
q->last_fft_im[i] = im;
|
||||
}
|
||||
}
|
||||
|
||||
static int inverse_quant_coeff (IMCContext* q, int stream_format_code) {
|
||||
int i, j;
|
||||
int middle_value, cw_len, max_size;
|
||||
const float* quantizer;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++) {
|
||||
q->CWdecoded[j] = 0;
|
||||
cw_len = q->CWlengthT[j];
|
||||
|
||||
if (cw_len <= 0 || q->skipFlags[j])
|
||||
continue;
|
||||
|
||||
max_size = 1 << cw_len;
|
||||
middle_value = max_size >> 1;
|
||||
|
||||
if (q->codewords[j] >= max_size || q->codewords[j] < 0)
|
||||
return -1;
|
||||
|
||||
if (cw_len >= 4){
|
||||
quantizer = imc_quantizer2[(stream_format_code & 2) >> 1];
|
||||
if (q->codewords[j] >= middle_value)
|
||||
q->CWdecoded[j] = quantizer[q->codewords[j] - 8] * q->flcoeffs6[i];
|
||||
else
|
||||
q->CWdecoded[j] = -quantizer[max_size - q->codewords[j] - 8 - 1] * q->flcoeffs6[i];
|
||||
}else{
|
||||
quantizer = imc_quantizer1[((stream_format_code & 2) >> 1) | (q->bandFlagsBuf[i] << 1)];
|
||||
if (q->codewords[j] >= middle_value)
|
||||
q->CWdecoded[j] = quantizer[q->codewords[j] - 1] * q->flcoeffs6[i];
|
||||
else
|
||||
q->CWdecoded[j] = -quantizer[max_size - 2 - q->codewords[j]] * q->flcoeffs6[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int imc_get_coeffs (IMCContext* q) {
|
||||
int i, j, cw_len, cw;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
if(!q->sumLenArr[i]) continue;
|
||||
if (q->bandFlagsBuf[i] || q->bandWidthT[i]) {
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++) {
|
||||
cw_len = q->CWlengthT[j];
|
||||
cw = 0;
|
||||
|
||||
if (get_bits_count(&q->gb) + cw_len > 512){
|
||||
//av_log(NULL,0,"Band %i coeff %i cw_len %i\n",i,j,cw_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(cw_len && (!q->bandFlagsBuf[i] || !q->skipFlags[j]))
|
||||
cw = get_bits(&q->gb, cw_len);
|
||||
|
||||
q->codewords[j] = cw;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imc_decode_frame(AVCodecContext * avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t * buf, int buf_size)
|
||||
{
|
||||
|
||||
IMCContext *q = avctx->priv_data;
|
||||
|
||||
int stream_format_code;
|
||||
int imc_hdr, i, j;
|
||||
int flag;
|
||||
int bits, summer;
|
||||
int counter, bitscount;
|
||||
uint16_t buf16[IMC_BLOCK_SIZE / 2];
|
||||
|
||||
if (buf_size < IMC_BLOCK_SIZE) {
|
||||
av_log(avctx, AV_LOG_ERROR, "imc frame too small!\n");
|
||||
return -1;
|
||||
}
|
||||
for(i = 0; i < IMC_BLOCK_SIZE / 2; i++)
|
||||
buf16[i] = bswap_16(((const uint16_t*)buf)[i]);
|
||||
|
||||
init_get_bits(&q->gb, (const uint8_t*)buf16, IMC_BLOCK_SIZE * 8);
|
||||
|
||||
/* Check the frame header */
|
||||
imc_hdr = get_bits(&q->gb, 9);
|
||||
if (imc_hdr != IMC_FRAME_ID) {
|
||||
av_log(avctx, AV_LOG_ERROR, "imc frame header check failed!\n");
|
||||
av_log(avctx, AV_LOG_ERROR, "got %x instead of 0x21.\n", imc_hdr);
|
||||
return -1;
|
||||
}
|
||||
stream_format_code = get_bits(&q->gb, 3);
|
||||
|
||||
if(stream_format_code & 1){
|
||||
av_log(avctx, AV_LOG_ERROR, "Stream code format %X is not supported\n", stream_format_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// av_log(avctx, AV_LOG_DEBUG, "stream_format_code = %d\n", stream_format_code);
|
||||
|
||||
if (stream_format_code & 0x04)
|
||||
q->decoder_reset = 1;
|
||||
|
||||
if(q->decoder_reset) {
|
||||
memset(q->out_samples, 0, sizeof(q->out_samples));
|
||||
for(i = 0; i < BANDS; i++)q->old_floor[i] = 1.0;
|
||||
for(i = 0; i < COEFFS; i++)q->CWdecoded[i] = 0;
|
||||
q->decoder_reset = 0;
|
||||
}
|
||||
|
||||
flag = get_bits1(&q->gb);
|
||||
imc_read_level_coeffs(q, stream_format_code, q->levlCoeffBuf);
|
||||
|
||||
if (stream_format_code & 0x4)
|
||||
imc_decode_level_coefficients(q, q->levlCoeffBuf, q->flcoeffs1, q->flcoeffs2);
|
||||
else
|
||||
imc_decode_level_coefficients2(q, q->levlCoeffBuf, q->old_floor, q->flcoeffs1, q->flcoeffs2);
|
||||
|
||||
memcpy(q->old_floor, q->flcoeffs1, 32 * sizeof(float));
|
||||
|
||||
counter = 0;
|
||||
for (i=0 ; i<BANDS ; i++) {
|
||||
if (q->levlCoeffBuf[i] == 16) {
|
||||
q->bandWidthT[i] = 0;
|
||||
counter++;
|
||||
} else
|
||||
q->bandWidthT[i] = band_tab[i+1] - band_tab[i];
|
||||
}
|
||||
memset(q->bandFlagsBuf, 0, BANDS * sizeof(int));
|
||||
for(i = 0; i < BANDS-1; i++) {
|
||||
if (q->bandWidthT[i])
|
||||
q->bandFlagsBuf[i] = get_bits1(&q->gb);
|
||||
}
|
||||
|
||||
imc_calculate_coeffs(q, q->flcoeffs1, q->flcoeffs2, q->bandWidthT, q->flcoeffs3, q->flcoeffs5);
|
||||
|
||||
bitscount = 0;
|
||||
/* first 4 bands will be assigned 5 bits per coefficient */
|
||||
if (stream_format_code & 0x2) {
|
||||
bitscount += 15;
|
||||
|
||||
q->bitsBandT[0] = 5;
|
||||
q->CWlengthT[0] = 5;
|
||||
q->CWlengthT[1] = 5;
|
||||
q->CWlengthT[2] = 5;
|
||||
for(i = 1; i < 4; i++){
|
||||
bits = (q->levlCoeffBuf[i] == 16) ? 0 : 5;
|
||||
q->bitsBandT[i] = bits;
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++) {
|
||||
q->CWlengthT[j] = bits;
|
||||
bitscount += bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bit_allocation (q, stream_format_code, 512 - bitscount - get_bits_count(&q->gb), flag) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Bit allocations failed\n");
|
||||
q->decoder_reset = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
q->sumLenArr[i] = 0;
|
||||
q->skipFlagRaw[i] = 0;
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++)
|
||||
q->sumLenArr[i] += q->CWlengthT[j];
|
||||
if (q->bandFlagsBuf[i])
|
||||
if( (((band_tab[i+1] - band_tab[i]) * 1.5) > q->sumLenArr[i]) && (q->sumLenArr[i] > 0))
|
||||
q->skipFlagRaw[i] = 1;
|
||||
}
|
||||
|
||||
imc_get_skip_coeff(q);
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
q->flcoeffs6[i] = q->flcoeffs1[i];
|
||||
/* band has flag set and at least one coded coefficient */
|
||||
if (q->bandFlagsBuf[i] && (band_tab[i+1] - band_tab[i]) != q->skipFlagCount[i]){
|
||||
q->flcoeffs6[i] *= q->sqrt_tab[band_tab[i+1] - band_tab[i]] /
|
||||
q->sqrt_tab[(band_tab[i+1] - band_tab[i] - q->skipFlagCount[i])];
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate bits left, bits needed and adjust bit allocation */
|
||||
bits = summer = 0;
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
if (q->bandFlagsBuf[i]) {
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++) {
|
||||
if(q->skipFlags[j]) {
|
||||
summer += q->CWlengthT[j];
|
||||
q->CWlengthT[j] = 0;
|
||||
}
|
||||
}
|
||||
bits += q->skipFlagBits[i];
|
||||
summer -= q->skipFlagBits[i];
|
||||
}
|
||||
}
|
||||
imc_adjust_bit_allocation(q, summer);
|
||||
|
||||
for(i = 0; i < BANDS; i++) {
|
||||
q->sumLenArr[i] = 0;
|
||||
|
||||
for(j = band_tab[i]; j < band_tab[i+1]; j++)
|
||||
if (!q->skipFlags[j])
|
||||
q->sumLenArr[i] += q->CWlengthT[j];
|
||||
}
|
||||
|
||||
memset(q->codewords, 0, sizeof(q->codewords));
|
||||
|
||||
if(imc_get_coeffs(q) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Read coefficients failed\n");
|
||||
q->decoder_reset = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(inverse_quant_coeff(q, stream_format_code) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Inverse quantization of coefficients failed\n");
|
||||
q->decoder_reset = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(q->skipFlags, 0, sizeof(q->skipFlags));
|
||||
|
||||
imc_imdct256(q);
|
||||
|
||||
q->dsp.float_to_int16(data, q->out_samples, COEFFS);
|
||||
|
||||
*data_size = COEFFS * sizeof(int16_t);
|
||||
|
||||
return IMC_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
static av_cold int imc_decode_close(AVCodecContext * avctx)
|
||||
{
|
||||
IMCContext *q = avctx->priv_data;
|
||||
|
||||
ff_fft_end(&q->fft);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AVCodec imc_decoder = {
|
||||
.name = "imc",
|
||||
.type = CODEC_TYPE_AUDIO,
|
||||
.id = CODEC_ID_IMC,
|
||||
.priv_data_size = sizeof(IMCContext),
|
||||
.init = imc_decode_init,
|
||||
.close = imc_decode_close,
|
||||
.decode = imc_decode_frame,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"),
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* IMC compatible decoder
|
||||
* Copyright (c) 2002-2004 Maxim Poliakovski
|
||||
* Copyright (c) 2006 Benjamin Larsson
|
||||
* Copyright (c) 2006 Konstantin Shishkov
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_IMCDATA_H
|
||||
#define FFMPEG_IMCDATA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint16_t band_tab[33] = {
|
||||
0, 3, 6, 9, 12, 16, 20, 24, 29, 34, 40,
|
||||
46, 53, 60, 68, 76, 84, 93, 102, 111, 121, 131,
|
||||
141, 151, 162, 173, 184, 195, 207, 219, 231, 243, 256,
|
||||
};
|
||||
|
||||
|
||||
static const int8_t cyclTab[32] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32, 32,
|
||||
};
|
||||
|
||||
static const int8_t cyclTab2[32] = {
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, 26, 27, 28, 29};
|
||||
|
||||
static const float imc_weights1[31] = {
|
||||
0.119595, 0.123124, 0.129192, 9.97377e-2, 8.1923e-2, 9.61153e-2, 8.77885e-2, 8.61174e-2,
|
||||
9.00882e-2, 9.91658e-2, 0.112991, 0.131126, 0.152886, 0.177292, 0.221782, 0.244917, 0.267386,
|
||||
0.306816, 0.323046, 0.33729, 0.366773, 0.392557, 0.398076, 0.403302, 0.42451, 0.444777,
|
||||
0.449188, 0.455445, 0.477853, 0.500669, 0.510395};
|
||||
|
||||
static const float imc_weights2[31] = {
|
||||
3.23466e-3, 3.49886e-3, 3.98413e-3, 1.98116e-3, 1.16465e-3, 1.79283e-3, 1.40372e-3, 1.33274e-3,
|
||||
1.50523e-3, 1.95064e-3, 2.77472e-3, 4.14725e-3, 6.2776e-3, 9.36401e-3, 1.71397e-2, 2.24052e-2,
|
||||
2.83971e-2, 4.11689e-2, 4.73165e-2, 5.31631e-2, 6.66614e-2, 8.00824e-2, 8.31588e-2, 8.61397e-2,
|
||||
9.89229e-2, 0.112197, 0.115227, 0.119613, 0.136174, 0.15445, 0.162685};
|
||||
|
||||
static const float imc_quantizer1[4][8] = {
|
||||
{ 8.4431201e-1, 4.7358301e-1, 1.448354, 2.7073899e-1, 7.4449003e-1, 1.241991, 1.845484, 0.0},
|
||||
{ 8.6876702e-1, 4.7659001e-1, 1.478224, 2.5672799e-1, 7.55777e-1, 1.3229851, 2.03438, 0.0},
|
||||
{ 7.5891501e-1, 6.2272799e-1, 1.271322, 3.47904e-1, 7.5317699e-1, 1.150767, 1.628476, 0.0},
|
||||
{ 7.65257e-1, 6.44647e-1, 1.263824, 3.4548101e-1, 7.6384902e-1, 1.214466, 1.7638789, 0.0},
|
||||
};
|
||||
|
||||
static const float imc_quantizer2[2][56] = {
|
||||
{ 1.39236e-1, 3.50548e-1, 5.9547901e-1, 8.5772401e-1, 1.121545, 1.3882281, 1.695882, 2.1270809,
|
||||
7.2221003e-2, 1.85177e-1, 2.9521701e-1, 4.12568e-1, 5.4068601e-1, 6.7679501e-1, 8.1196898e-1, 9.4765198e-1,
|
||||
1.0779999, 1.203415, 1.337265, 1.481871, 1.639982, 1.814766, 2.0701399, 2.449862,
|
||||
3.7533998e-2, 1.02722e-1, 1.6021401e-1, 2.16043e-1, 2.7231601e-1, 3.3025399e-1, 3.9022601e-1, 4.52849e-1,
|
||||
5.1794899e-1, 5.8529502e-1, 6.53956e-1, 7.2312802e-1, 7.9150802e-1, 8.5891002e-1, 9.28141e-1, 9.9706203e-1,
|
||||
1.062153, 1.12564, 1.189834, 1.256122, 1.324469, 1.3955311, 1.468906, 1.545084,
|
||||
1.6264729, 1.711524, 1.802705, 1.91023, 2.0533991, 2.22333, 2.4830019, 3.253329 },
|
||||
{ 1.11654e-1, 3.54469e-1, 6.4232099e-1, 9.6128798e-1, 1.295053, 1.61777, 1.989839, 2.51107,
|
||||
5.7721999e-2, 1.69879e-1, 2.97589e-1, 4.3858799e-1, 5.9039903e-1, 7.4934798e-1, 9.1628098e-1, 1.087297,
|
||||
1.262751, 1.4288321, 1.6040879, 1.79067, 2.000668, 2.2394669, 2.649332, 5.2760072,
|
||||
2.9722e-2, 8.7316997e-2, 1.4445201e-1, 2.04247e-1, 2.6879501e-1, 3.3716801e-1, 4.08811e-1, 4.8306999e-1,
|
||||
5.6049401e-1, 6.3955498e-1, 7.2044599e-1, 8.0427998e-1, 8.8933599e-1, 9.7537601e-1, 1.062461, 1.1510431,
|
||||
1.240236, 1.326715, 1.412513, 1.500502, 1.591749, 1.686413, 1.785239, 1.891233,
|
||||
2.0051291, 2.127681, 2.2709141, 2.475826, 2.7219379, 3.101985, 4.686213, 6.2287788},
|
||||
};
|
||||
|
||||
|
||||
static const float xTab[14] = {7.6, 3.6, 4.4, 3.7, 6.1, 5.1, 2.3, 1.6, 6.2, 1.5, 1.8, 1.2, 0, 0}; //10014048
|
||||
|
||||
/* precomputed table for 10^(i/4), i=-15..16 */
|
||||
static const float imc_exp_tab[32] = {
|
||||
1.778280e-4, 3.162278e-4, 5.623413e-4, 1.000000e-3,
|
||||
1.778280e-3, 3.162278e-3, 5.623413e-3, 1.000000e-2,
|
||||
1.778280e-2, 3.162278e-2, 5.623413e-2, 1.000000e-1,
|
||||
1.778280e-1, 3.162278e-1, 5.623413e-1, 1.000000e00,
|
||||
1.778280e00, 3.162278e00, 5.623413e00, 1.000000e01,
|
||||
1.778280e01, 3.162278e01, 5.623413e01, 1.000000e02,
|
||||
1.778280e02, 3.162278e02, 5.623413e02, 1.000000e03,
|
||||
1.778280e03, 3.162278e03, 5.623413e03, 1.000000e04
|
||||
};
|
||||
static const float * const imc_exp_tab2 = imc_exp_tab + 8;
|
||||
|
||||
|
||||
static const uint8_t imc_cb_select[4][32] = {
|
||||
{ 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2 },
|
||||
{ 0, 2, 0, 3, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2 },
|
||||
{ 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const uint8_t imc_huffman_sizes[4] = {
|
||||
17, 17, 18, 18
|
||||
};
|
||||
|
||||
static const uint8_t imc_huffman_lens[4][4][18] = {
|
||||
{
|
||||
{ 16, 15, 13, 11, 8, 5, 3, 1, 2, 4, 6, 9, 10, 12, 14, 16, 7, 0 },
|
||||
{ 10, 8, 7, 6, 4, 4, 3, 2, 2, 3, 4, 6, 7, 9, 11, 11, 7, 0 },
|
||||
{ 15, 15, 14, 11, 8, 6, 4, 2, 1, 4, 5, 7, 9, 10, 12, 13, 4, 0 },
|
||||
{ 13, 11, 10, 8, 6, 4, 2, 2, 2, 3, 5, 7, 9, 12, 15, 15, 14, 0 },
|
||||
},
|
||||
{
|
||||
{ 14, 12, 10, 8, 7, 4, 2, 2, 2, 3, 5, 7, 9, 11, 13, 14, 7, 0 },
|
||||
{ 14, 13, 11, 8, 6, 4, 3, 2, 2, 3, 5, 7, 9, 10, 12, 14, 3, 0 },
|
||||
{ 13, 12, 10, 7, 5, 4, 3, 2, 2, 3, 4, 6, 8, 9, 11, 13, 4, 0 },
|
||||
{ 13, 12, 10, 7, 5, 4, 3, 2, 2, 3, 4, 6, 8, 9, 11, 13, 4, 0 },
|
||||
},
|
||||
{
|
||||
{ 16, 14, 12, 10, 8, 5, 3, 1, 2, 4, 7, 9, 11, 13, 15, 17, 6, 17 },
|
||||
{ 15, 13, 11, 8, 6, 4, 2, 2, 2, 3, 5, 7, 10, 12, 14, 16, 9, 16 },
|
||||
{ 14, 12, 11, 9, 8, 6, 3, 1, 2, 5, 7, 10, 13, 15, 16, 17, 4, 17 },
|
||||
{ 16, 14, 12, 9, 7, 5, 2, 2, 2, 3, 4, 6, 8, 11, 13, 15, 10, 16 },
|
||||
},
|
||||
{
|
||||
{ 13, 11, 10, 8, 7, 5, 2, 2, 2, 4, 6, 9, 12, 14, 15, 16, 3, 16 },
|
||||
{ 11, 11, 10, 9, 8, 7, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 5 },
|
||||
{ 9, 9, 7, 6, 5, 4, 3, 3, 2, 3, 4, 5, 4, 5, 5, 6, 8, 6 },
|
||||
{ 13, 12, 10, 8, 5, 3, 3, 2, 2, 3, 4, 7, 9, 11, 14, 15, 6, 15 },
|
||||
}
|
||||
};
|
||||
|
||||
static const uint16_t imc_huffman_bits[4][4][18] = {
|
||||
{
|
||||
{ 0xCC32, 0x6618, 0x1987, 0x0660, 0x00CD, 0x0018, 0x0007, 0x0000, 0x0002, 0x000D, 0x0032, 0x0199, 0x0331, 0x0CC2, 0x330D, 0xCC33, 0x0067, 0x0000 },
|
||||
{ 0x02FE, 0x00BE, 0x005E, 0x002D, 0x000A, 0x0009, 0x0003, 0x0003, 0x0000, 0x0002, 0x0008, 0x002C, 0x005D, 0x017E, 0x05FE, 0x05FF, 0x005C, 0x0000 },
|
||||
{ 0x5169, 0x5168, 0x28B5, 0x0517, 0x00A3, 0x0029, 0x0008, 0x0003, 0x0000, 0x0009, 0x0015, 0x0050, 0x0144, 0x028A, 0x0A2C, 0x145B, 0x000B, 0x0000 },
|
||||
{ 0x1231, 0x048D, 0x0247, 0x0090, 0x0025, 0x0008, 0x0001, 0x0003, 0x0000, 0x0005, 0x0013, 0x0049, 0x0122, 0x0919, 0x48C3, 0x48C2, 0x2460, 0x0000 },
|
||||
},
|
||||
{
|
||||
{ 0x2D1D, 0x0B46, 0x02D0, 0x00B5, 0x0059, 0x000A, 0x0003, 0x0001, 0x0000, 0x0004, 0x0017, 0x005B, 0x0169, 0x05A2, 0x168F, 0x2D1C, 0x0058, 0x0000 },
|
||||
{ 0x1800, 0x0C01, 0x0301, 0x0061, 0x0019, 0x0007, 0x0004, 0x0003, 0x0000, 0x0005, 0x000D, 0x0031, 0x00C1, 0x0181, 0x0601, 0x1801, 0x0002, 0x0000 },
|
||||
{ 0x1556, 0x0AAA, 0x02AB, 0x0054, 0x0014, 0x000B, 0x0002, 0x0003, 0x0000, 0x0003, 0x0008, 0x002B, 0x00AB, 0x0154, 0x0554, 0x1557, 0x0009, 0x0000 },
|
||||
{ 0x1556, 0x0AAA, 0x02AB, 0x0054, 0x0014, 0x000B, 0x0002, 0x0003, 0x0000, 0x0003, 0x0008, 0x002B, 0x00AB, 0x0154, 0x0554, 0x1557, 0x0009, 0x0000 },
|
||||
},
|
||||
{
|
||||
{ 0x2993, 0x0A65, 0x0298, 0x00A7, 0x0028, 0x0004, 0x0000, 0x0001, 0x0001, 0x0003, 0x0015, 0x0052, 0x014D, 0x0533, 0x14C8, 0x5324, 0x000B, 0x5325 },
|
||||
{ 0x09B8, 0x026F, 0x009A, 0x0012, 0x0005, 0x0000, 0x0001, 0x0002, 0x0003, 0x0001, 0x0003, 0x0008, 0x004C, 0x0136, 0x04DD, 0x1373, 0x0027, 0x1372 },
|
||||
{ 0x0787, 0x01E0, 0x00F1, 0x003D, 0x001F, 0x0006, 0x0001, 0x0001, 0x0001, 0x0002, 0x000E, 0x0079, 0x03C2, 0x0F0D, 0x1E19, 0x3C30, 0x0000, 0x3C31 },
|
||||
{ 0x4B06, 0x12C0, 0x04B1, 0x0097, 0x0024, 0x0008, 0x0002, 0x0003, 0x0000, 0x0003, 0x0005, 0x0013, 0x004A, 0x0259, 0x0961, 0x2582, 0x012D, 0x4B07 },
|
||||
},
|
||||
{
|
||||
{ 0x0A5A, 0x0297, 0x014A, 0x0053, 0x0028, 0x000B, 0x0003, 0x0000, 0x0002, 0x0004, 0x0015, 0x00A4, 0x052C, 0x14B7, 0x296C, 0x52DB, 0x0003, 0x52DA },
|
||||
{ 0x0193, 0x0192, 0x00C8, 0x0065, 0x0033, 0x0018, 0x0007, 0x0004, 0x0000, 0x0004, 0x0005, 0x0007, 0x0006, 0x0003, 0x0005, 0x0005, 0x000D, 0x0004 },
|
||||
{ 0x0012, 0x0013, 0x0005, 0x0003, 0x0000, 0x0003, 0x0005, 0x0004, 0x0003, 0x0003, 0x0005, 0x0005, 0x0004, 0x0004, 0x0003, 0x0005, 0x0008, 0x0004 },
|
||||
{ 0x0D66, 0x06B2, 0x01AD, 0x006A, 0x000C, 0x0005, 0x0004, 0x0000, 0x0003, 0x0002, 0x0007, 0x0034, 0x00D7, 0x0358, 0x1ACF, 0x359C, 0x001B, 0x359D },
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FFMPEG_IMCDATA_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Misc image conversion routines
|
||||
* most functionality is exported to the public API, see avcodec.h
|
||||
*
|
||||
* Copyright (c) 2008 Vitor Sessak
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_IMGCONVERT_H
|
||||
#define FFMPEG_IMGCONVERT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "avcodec.h"
|
||||
|
||||
int ff_fill_linesize(AVPicture *picture, int pix_fmt, int width);
|
||||
|
||||
int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, int pix_fmt, int height);
|
||||
|
||||
int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane);
|
||||
|
||||
#endif /* FFMPEG_IMGCONVERT_H */
|
||||
@@ -1,22 +1,28 @@
|
||||
/*
|
||||
* Templates for image convertion routines
|
||||
* templates for image conversion routines
|
||||
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* This header intentionally has no multiple inclusion guards. It is meant to
|
||||
* be included multiple times and generates different code depending on the
|
||||
* value of certain #defines. */
|
||||
|
||||
#ifndef RGB_OUT
|
||||
#define RGB_OUT(d, r, g, b) RGBA_OUT(d, r, g, b, 0xff)
|
||||
#endif
|
||||
@@ -27,7 +33,7 @@ static void glue(yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
|
||||
uint8_t *d, *d1, *d2;
|
||||
int w, y, cb, cr, r_add, g_add, b_add, width2;
|
||||
uint8_t *cm = cropTbl + MAX_NEG_CROP;
|
||||
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
|
||||
unsigned int r, g, b;
|
||||
|
||||
d = dst->data[0];
|
||||
@@ -121,7 +127,7 @@ static void glue(yuvj420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
|
||||
uint8_t *d, *d1, *d2;
|
||||
int w, y, cb, cr, r_add, g_add, b_add, width2;
|
||||
uint8_t *cm = cropTbl + MAX_NEG_CROP;
|
||||
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
|
||||
unsigned int r, g, b;
|
||||
|
||||
d = dst->data[0];
|
||||
@@ -408,16 +414,20 @@ static void glue(pal8_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(FMT_RGBA32) && defined(RGBA_OUT)
|
||||
// RGB24 has optimized routines
|
||||
#if !defined(FMT_RGB32) && !defined(FMT_RGB24)
|
||||
/* alpha support */
|
||||
|
||||
static void glue(rgba32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
static void glue(rgb32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
int width, int height)
|
||||
{
|
||||
const uint8_t *s;
|
||||
uint8_t *d;
|
||||
int src_wrap, dst_wrap, j, y;
|
||||
unsigned int v, r, g, b, a;
|
||||
unsigned int v, r, g, b;
|
||||
#ifdef RGBA_OUT
|
||||
unsigned int a;
|
||||
#endif
|
||||
|
||||
s = src->data[0];
|
||||
src_wrap = src->linesize[0] - width * 4;
|
||||
@@ -428,11 +438,15 @@ static void glue(rgba32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
for(y=0;y<height;y++) {
|
||||
for(j = 0;j < width; j++) {
|
||||
v = ((const uint32_t *)(s))[0];
|
||||
a = (v >> 24) & 0xff;
|
||||
r = (v >> 16) & 0xff;
|
||||
g = (v >> 8) & 0xff;
|
||||
b = v & 0xff;
|
||||
#ifdef RGBA_OUT
|
||||
a = (v >> 24) & 0xff;
|
||||
RGBA_OUT(d, r, g, b, a);
|
||||
#else
|
||||
RGB_OUT(d, r, g, b);
|
||||
#endif
|
||||
s += 4;
|
||||
d += BPP;
|
||||
}
|
||||
@@ -441,13 +455,16 @@ static void glue(rgba32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
|
||||
}
|
||||
}
|
||||
|
||||
static void glue(RGB_NAME, _to_rgba32)(AVPicture *dst, const AVPicture *src,
|
||||
static void glue(RGB_NAME, _to_rgb32)(AVPicture *dst, const AVPicture *src,
|
||||
int width, int height)
|
||||
{
|
||||
const uint8_t *s;
|
||||
uint8_t *d;
|
||||
int src_wrap, dst_wrap, j, y;
|
||||
unsigned int r, g, b, a;
|
||||
unsigned int r, g, b;
|
||||
#ifdef RGBA_IN
|
||||
unsigned int a;
|
||||
#endif
|
||||
|
||||
s = src->data[0];
|
||||
src_wrap = src->linesize[0] - width * BPP;
|
||||
@@ -457,8 +474,13 @@ static void glue(RGB_NAME, _to_rgba32)(AVPicture *dst, const AVPicture *src,
|
||||
|
||||
for(y=0;y<height;y++) {
|
||||
for(j = 0;j < width; j++) {
|
||||
#ifdef RGBA_IN
|
||||
RGBA_IN(r, g, b, a, s);
|
||||
((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
#else
|
||||
RGB_IN(r, g, b, s);
|
||||
((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
|
||||
#endif
|
||||
d += 4;
|
||||
s += BPP;
|
||||
}
|
||||
@@ -467,7 +489,7 @@ static void glue(RGB_NAME, _to_rgba32)(AVPicture *dst, const AVPicture *src,
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined(FMT_RGBA32) && defined(RGBA_IN) */
|
||||
#endif /* !defined(FMT_RGB32) */
|
||||
|
||||
#ifndef FMT_RGB24
|
||||
|
||||
@@ -537,7 +559,7 @@ static void yuv444p_to_rgb24(AVPicture *dst, const AVPicture *src,
|
||||
const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
|
||||
uint8_t *d, *d1;
|
||||
int w, y, cb, cr, r_add, g_add, b_add;
|
||||
uint8_t *cm = cropTbl + MAX_NEG_CROP;
|
||||
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
|
||||
unsigned int r, g, b;
|
||||
|
||||
d = dst->data[0];
|
||||
@@ -570,7 +592,7 @@ static void yuvj444p_to_rgb24(AVPicture *dst, const AVPicture *src,
|
||||
const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
|
||||
uint8_t *d, *d1;
|
||||
int w, y, cb, cr, r_add, g_add, b_add;
|
||||
uint8_t *cm = cropTbl + MAX_NEG_CROP;
|
||||
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
|
||||
unsigned int r, g, b;
|
||||
|
||||
d = dst->data[0];
|
||||
@@ -770,7 +792,7 @@ static void rgb24_to_yuvj444p(AVPicture *dst, const AVPicture *src,
|
||||
|
||||
#endif /* FMT_RGB24 */
|
||||
|
||||
#if defined(FMT_RGB24) || defined(FMT_RGBA32)
|
||||
#if defined(FMT_RGB24) || defined(FMT_RGB32)
|
||||
|
||||
static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src,
|
||||
int width, int height)
|
||||
@@ -787,7 +809,7 @@ static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src,
|
||||
q = dst->data[0];
|
||||
dst_wrap = dst->linesize[0] - width;
|
||||
has_alpha = 0;
|
||||
|
||||
|
||||
for(y=0;y<height;y++) {
|
||||
for(x=0;x<width;x++) {
|
||||
#ifdef RGBA_IN
|
||||
@@ -816,12 +838,12 @@ static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src,
|
||||
build_rgb_palette(dst->data[1], has_alpha);
|
||||
}
|
||||
|
||||
#endif /* defined(FMT_RGB24) || defined(FMT_RGBA32) */
|
||||
|
||||
#endif /* defined(FMT_RGB24) || defined(FMT_RGB32) */
|
||||
|
||||
#ifdef RGBA_IN
|
||||
|
||||
static int glue(get_alpha_info_, RGB_NAME)(const AVPicture *src,
|
||||
int width, int height)
|
||||
int width, int height)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int src_wrap, ret, x, y;
|
||||
@@ -854,4 +876,4 @@ static int glue(get_alpha_info_, RGB_NAME)(const AVPicture *src,
|
||||
#undef BPP
|
||||
#undef RGB_NAME
|
||||
#undef FMT_RGB24
|
||||
#undef FMT_RGBA32
|
||||
#undef FMT_RGB32
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
/*
|
||||
* High quality image resampling with polyphase filters
|
||||
* High quality image resampling with polyphase filters
|
||||
* Copyright (c) 2001 Fabrice Bellard.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file imgresample.c
|
||||
* High quality image resampling with polyphase filters .
|
||||
*/
|
||||
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
#include "swscale.h"
|
||||
|
||||
#ifdef USE_FASTMEMCPY
|
||||
#include "fastmemcpy.h"
|
||||
#ifdef HAVE_ALTIVEC
|
||||
#include "ppc/imgresample_altivec.h"
|
||||
#endif
|
||||
|
||||
#define NB_COMPONENTS 3
|
||||
@@ -44,14 +47,25 @@
|
||||
|
||||
#define LINE_BUF_HEIGHT (NB_TAPS * 4)
|
||||
|
||||
struct SwsContext {
|
||||
const AVClass *av_class;
|
||||
struct ImgReSampleContext *resampling_ctx;
|
||||
enum PixelFormat src_pix_fmt, dst_pix_fmt;
|
||||
};
|
||||
|
||||
struct ImgReSampleContext {
|
||||
int iwidth, iheight, owidth, oheight, topBand, bottomBand, leftBand, rightBand;
|
||||
int iwidth, iheight, owidth, oheight;
|
||||
int topBand, bottomBand, leftBand, rightBand;
|
||||
int padtop, padbottom, padleft, padright;
|
||||
int pad_owidth, pad_oheight;
|
||||
int h_incr, v_incr;
|
||||
int16_t h_filters[NB_PHASES][NB_TAPS] __align8; /* horizontal filters */
|
||||
int16_t v_filters[NB_PHASES][NB_TAPS] __align8; /* vertical filters */
|
||||
DECLARE_ALIGNED_8(int16_t, h_filters[NB_PHASES][NB_TAPS]); /* horizontal filters */
|
||||
DECLARE_ALIGNED_8(int16_t, v_filters[NB_PHASES][NB_TAPS]); /* vertical filters */
|
||||
uint8_t *line_buf;
|
||||
};
|
||||
|
||||
void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
|
||||
|
||||
static inline int get_phase(int pos)
|
||||
{
|
||||
return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
|
||||
@@ -59,8 +73,8 @@ static inline int get_phase(int pos)
|
||||
|
||||
/* This function must be optimized */
|
||||
static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
int src_width, int src_start, int src_incr,
|
||||
int16_t *filters)
|
||||
int src_width, int src_start, int src_incr,
|
||||
int16_t *filters)
|
||||
{
|
||||
int src_pos, phase, sum, i;
|
||||
const uint8_t *s;
|
||||
@@ -103,7 +117,7 @@ static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
|
||||
/* This function must be optimized */
|
||||
static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
int wrap, int16_t *filter)
|
||||
int wrap, int16_t *filter)
|
||||
{
|
||||
int sum, i;
|
||||
const uint8_t *s;
|
||||
@@ -158,18 +172,18 @@ static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
src_pos += src_incr;\
|
||||
}
|
||||
|
||||
#define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016Lx\n", tmp.uq);
|
||||
#define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016"PRIx64"\n", tmp.uq);
|
||||
|
||||
/* XXX: do four pixels at a time */
|
||||
static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
|
||||
const uint8_t *src, int src_width,
|
||||
const uint8_t *src, int src_width,
|
||||
int src_start, int src_incr, int16_t *filters)
|
||||
{
|
||||
int src_pos, phase;
|
||||
const uint8_t *s;
|
||||
int16_t *filter;
|
||||
mmx_t tmp;
|
||||
|
||||
|
||||
src_pos = src_start;
|
||||
pxor_r2r(mm7, mm7);
|
||||
|
||||
@@ -207,13 +221,13 @@ static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
|
||||
}
|
||||
|
||||
static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
int wrap, int16_t *filter)
|
||||
int wrap, int16_t *filter)
|
||||
{
|
||||
int sum, i, v;
|
||||
const uint8_t *s;
|
||||
mmx_t tmp;
|
||||
mmx_t coefs[4];
|
||||
|
||||
|
||||
for(i=0;i<4;i++) {
|
||||
v = filter[i];
|
||||
coefs[i].uw[0] = v;
|
||||
@@ -221,7 +235,7 @@ static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
coefs[i].uw[2] = v;
|
||||
coefs[i].uw[3] = v;
|
||||
}
|
||||
|
||||
|
||||
pxor_r2r(mm7, mm7);
|
||||
s = src;
|
||||
while (dst_width >= 4) {
|
||||
@@ -243,7 +257,7 @@ static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
paddw_r2r(mm3, mm2);
|
||||
paddw_r2r(mm2, mm0);
|
||||
psraw_i2r(FILTER_BITS, mm0);
|
||||
|
||||
|
||||
packuswb_r2r(mm7, mm0);
|
||||
movq_r2m(mm0, tmp);
|
||||
|
||||
@@ -269,138 +283,11 @@ static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
}
|
||||
emms();
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_MMX */
|
||||
|
||||
#ifdef HAVE_ALTIVEC
|
||||
typedef union {
|
||||
vector unsigned char v;
|
||||
unsigned char c[16];
|
||||
} vec_uc_t;
|
||||
|
||||
typedef union {
|
||||
vector signed short v;
|
||||
signed short s[8];
|
||||
} vec_ss_t;
|
||||
|
||||
void v_resample16_altivec(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
int wrap, int16_t *filter)
|
||||
{
|
||||
int sum, i;
|
||||
const uint8_t *s;
|
||||
vector unsigned char *tv, tmp, dstv, zero;
|
||||
vec_ss_t srchv[4], srclv[4], fv[4];
|
||||
vector signed short zeros, sumhv, sumlv;
|
||||
s = src;
|
||||
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
/*
|
||||
The vec_madds later on does an implicit >>15 on the result.
|
||||
Since FILTER_BITS is 8, and we have 15 bits of magnitude in
|
||||
a signed short, we have just enough bits to pre-shift our
|
||||
filter constants <<7 to compensate for vec_madds.
|
||||
*/
|
||||
fv[i].s[0] = filter[i] << (15-FILTER_BITS);
|
||||
fv[i].v = vec_splat(fv[i].v, 0);
|
||||
}
|
||||
|
||||
zero = vec_splat_u8(0);
|
||||
zeros = vec_splat_s16(0);
|
||||
|
||||
|
||||
/*
|
||||
When we're resampling, we'd ideally like both our input buffers,
|
||||
and output buffers to be 16-byte aligned, so we can do both aligned
|
||||
reads and writes. Sadly we can't always have this at the moment, so
|
||||
we opt for aligned writes, as unaligned writes have a huge overhead.
|
||||
To do this, do enough scalar resamples to get dst 16-byte aligned.
|
||||
*/
|
||||
i = (-(int)dst) & 0xf;
|
||||
while(i>0) {
|
||||
sum = s[0 * wrap] * filter[0] +
|
||||
s[1 * wrap] * filter[1] +
|
||||
s[2 * wrap] * filter[2] +
|
||||
s[3 * wrap] * filter[3];
|
||||
sum = sum >> FILTER_BITS;
|
||||
if (sum<0) sum = 0; else if (sum>255) sum=255;
|
||||
dst[0] = sum;
|
||||
dst++;
|
||||
s++;
|
||||
dst_width--;
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Do our altivec resampling on 16 pixels at once. */
|
||||
while(dst_width>=16) {
|
||||
/*
|
||||
Read 16 (potentially unaligned) bytes from each of
|
||||
4 lines into 4 vectors, and split them into shorts.
|
||||
Interleave the multipy/accumulate for the resample
|
||||
filter with the loads to hide the 3 cycle latency
|
||||
the vec_madds have.
|
||||
*/
|
||||
tv = (vector unsigned char *) &s[0 * wrap];
|
||||
tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[i * wrap]));
|
||||
srchv[0].v = (vector signed short) vec_mergeh(zero, tmp);
|
||||
srclv[0].v = (vector signed short) vec_mergel(zero, tmp);
|
||||
sumhv = vec_madds(srchv[0].v, fv[0].v, zeros);
|
||||
sumlv = vec_madds(srclv[0].v, fv[0].v, zeros);
|
||||
|
||||
tv = (vector unsigned char *) &s[1 * wrap];
|
||||
tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[1 * wrap]));
|
||||
srchv[1].v = (vector signed short) vec_mergeh(zero, tmp);
|
||||
srclv[1].v = (vector signed short) vec_mergel(zero, tmp);
|
||||
sumhv = vec_madds(srchv[1].v, fv[1].v, sumhv);
|
||||
sumlv = vec_madds(srclv[1].v, fv[1].v, sumlv);
|
||||
|
||||
tv = (vector unsigned char *) &s[2 * wrap];
|
||||
tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[2 * wrap]));
|
||||
srchv[2].v = (vector signed short) vec_mergeh(zero, tmp);
|
||||
srclv[2].v = (vector signed short) vec_mergel(zero, tmp);
|
||||
sumhv = vec_madds(srchv[2].v, fv[2].v, sumhv);
|
||||
sumlv = vec_madds(srclv[2].v, fv[2].v, sumlv);
|
||||
|
||||
tv = (vector unsigned char *) &s[3 * wrap];
|
||||
tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[3 * wrap]));
|
||||
srchv[3].v = (vector signed short) vec_mergeh(zero, tmp);
|
||||
srclv[3].v = (vector signed short) vec_mergel(zero, tmp);
|
||||
sumhv = vec_madds(srchv[3].v, fv[3].v, sumhv);
|
||||
sumlv = vec_madds(srclv[3].v, fv[3].v, sumlv);
|
||||
|
||||
/*
|
||||
Pack the results into our destination vector,
|
||||
and do an aligned write of that back to memory.
|
||||
*/
|
||||
dstv = vec_packsu(sumhv, sumlv) ;
|
||||
vec_st(dstv, 0, (vector unsigned char *) dst);
|
||||
|
||||
dst+=16;
|
||||
s+=16;
|
||||
dst_width-=16;
|
||||
}
|
||||
|
||||
/*
|
||||
If there are any leftover pixels, resample them
|
||||
with the slow scalar method.
|
||||
*/
|
||||
while(dst_width>0) {
|
||||
sum = s[0 * wrap] * filter[0] +
|
||||
s[1 * wrap] * filter[1] +
|
||||
s[2 * wrap] * filter[2] +
|
||||
s[3 * wrap] * filter[3];
|
||||
sum = sum >> FILTER_BITS;
|
||||
if (sum<0) sum = 0; else if (sum>255) sum=255;
|
||||
dst[0] = sum;
|
||||
dst++;
|
||||
s++;
|
||||
dst_width--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* slow version to handle limit cases. Does not need optimisation */
|
||||
/* slow version to handle limit cases. Does not need optimization */
|
||||
static void h_resample_slow(uint8_t *dst, int dst_width,
|
||||
const uint8_t *src, int src_width,
|
||||
const uint8_t *src, int src_width,
|
||||
int src_start, int src_incr, int16_t *filters)
|
||||
{
|
||||
int src_pos, phase, sum, j, v, i;
|
||||
@@ -436,8 +323,8 @@ static void h_resample_slow(uint8_t *dst, int dst_width,
|
||||
}
|
||||
|
||||
static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
int src_width, int src_start, int src_incr,
|
||||
int16_t *filters)
|
||||
int src_width, int src_start, int src_incr,
|
||||
int16_t *filters)
|
||||
{
|
||||
int n, src_end;
|
||||
|
||||
@@ -450,29 +337,29 @@ static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
|
||||
}
|
||||
src_end = src_start + dst_width * src_incr;
|
||||
if (src_end > ((src_width - NB_TAPS) << POS_FRAC_BITS)) {
|
||||
n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
|
||||
n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
|
||||
src_incr;
|
||||
} else {
|
||||
n = dst_width;
|
||||
}
|
||||
#ifdef HAVE_MMX
|
||||
if ((mm_flags & MM_MMX) && NB_TAPS == 4)
|
||||
h_resample_fast4_mmx(dst, n,
|
||||
h_resample_fast4_mmx(dst, n,
|
||||
src, src_width, src_start, src_incr, filters);
|
||||
else
|
||||
#endif
|
||||
h_resample_fast(dst, n,
|
||||
h_resample_fast(dst, n,
|
||||
src, src_width, src_start, src_incr, filters);
|
||||
if (n < dst_width) {
|
||||
dst += n;
|
||||
dst_width -= n;
|
||||
src_start += n * src_incr;
|
||||
h_resample_slow(dst, dst_width,
|
||||
h_resample_slow(dst, dst_width,
|
||||
src, src_width, src_start, src_incr, filters);
|
||||
}
|
||||
}
|
||||
|
||||
static void component_resample(ImgReSampleContext *s,
|
||||
static void component_resample(ImgReSampleContext *s,
|
||||
uint8_t *output, int owrap, int owidth, int oheight,
|
||||
uint8_t *input, int iwrap, int iwidth, int iheight)
|
||||
{
|
||||
@@ -481,7 +368,7 @@ static void component_resample(ImgReSampleContext *s,
|
||||
|
||||
last_src_y = - FCENTER - 1;
|
||||
/* position of the bottom of the filter in the source image */
|
||||
src_y = (last_src_y + NB_TAPS) * POS_FRAC;
|
||||
src_y = (last_src_y + NB_TAPS) * POS_FRAC;
|
||||
ring_y = NB_TAPS; /* position in ring buffer */
|
||||
for(y=0;y<oheight;y++) {
|
||||
/* apply horizontal filter on new lines from input if needed */
|
||||
@@ -501,10 +388,10 @@ static void component_resample(ImgReSampleContext *s,
|
||||
src_line = input + y1 * iwrap;
|
||||
new_line = s->line_buf + ring_y * owidth;
|
||||
/* apply filter and handle limit cases correctly */
|
||||
h_resample(new_line, owidth,
|
||||
src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
|
||||
h_resample(new_line, owidth,
|
||||
src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
|
||||
&s->h_filters[0][0]);
|
||||
/* handle ring buffer wraping */
|
||||
/* handle ring buffer wrapping */
|
||||
if (ring_y >= LINE_BUF_HEIGHT) {
|
||||
memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
|
||||
new_line, owidth);
|
||||
@@ -515,8 +402,8 @@ static void component_resample(ImgReSampleContext *s,
|
||||
#ifdef HAVE_MMX
|
||||
/* desactivated MMX because loss of precision */
|
||||
if ((mm_flags & MM_MMX) && NB_TAPS == 4 && 0)
|
||||
v_resample4_mmx(output, owidth,
|
||||
s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
|
||||
v_resample4_mmx(output, owidth,
|
||||
s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
|
||||
&s->v_filters[phase_y][0]);
|
||||
else
|
||||
#endif
|
||||
@@ -527,100 +414,94 @@ static void component_resample(ImgReSampleContext *s,
|
||||
&s->v_filters[phase_y][0]);
|
||||
else
|
||||
#endif
|
||||
v_resample(output, owidth,
|
||||
s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
|
||||
v_resample(output, owidth,
|
||||
s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
|
||||
&s->v_filters[phase_y][0]);
|
||||
|
||||
|
||||
src_y += s->v_incr;
|
||||
|
||||
output += owrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: the following filter is quite naive, but it seems to suffice
|
||||
for 4 taps */
|
||||
static void build_filter(int16_t *filter, float factor)
|
||||
{
|
||||
int ph, i, v;
|
||||
float x, y, tab[NB_TAPS], norm, mult;
|
||||
|
||||
/* if upsampling, only need to interpolate, no filter */
|
||||
if (factor > 1.0)
|
||||
factor = 1.0;
|
||||
|
||||
for(ph=0;ph<NB_PHASES;ph++) {
|
||||
norm = 0;
|
||||
for(i=0;i<NB_TAPS;i++) {
|
||||
|
||||
x = M_PI * ((float)(i - FCENTER) - (float)ph / NB_PHASES) * factor;
|
||||
if (x == 0)
|
||||
y = 1.0;
|
||||
else
|
||||
y = sin(x) / x;
|
||||
tab[i] = y;
|
||||
norm += y;
|
||||
}
|
||||
|
||||
/* normalize so that an uniform color remains the same */
|
||||
mult = (float)(1 << FILTER_BITS) / norm;
|
||||
for(i=0;i<NB_TAPS;i++) {
|
||||
v = (int)(tab[i] * mult);
|
||||
filter[ph * NB_TAPS + i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImgReSampleContext *img_resample_init(int owidth, int oheight,
|
||||
int iwidth, int iheight)
|
||||
{
|
||||
return img_resample_full_init(owidth, oheight, iwidth, iheight, 0, 0, 0, 0);
|
||||
return img_resample_full_init(owidth, oheight, iwidth, iheight,
|
||||
0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
|
||||
int iwidth, int iheight,
|
||||
int topBand, int bottomBand,
|
||||
int leftBand, int rightBand)
|
||||
int leftBand, int rightBand,
|
||||
int padtop, int padbottom,
|
||||
int padleft, int padright)
|
||||
{
|
||||
ImgReSampleContext *s;
|
||||
|
||||
if (!owidth || !oheight || !iwidth || !iheight)
|
||||
return NULL;
|
||||
|
||||
s = av_mallocz(sizeof(ImgReSampleContext));
|
||||
if (!s)
|
||||
return NULL;
|
||||
s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
|
||||
if (!s->line_buf)
|
||||
if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS))
|
||||
goto fail;
|
||||
|
||||
s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
|
||||
if (!s->line_buf)
|
||||
goto fail;
|
||||
|
||||
s->owidth = owidth;
|
||||
s->oheight = oheight;
|
||||
s->iwidth = iwidth;
|
||||
s->iheight = iheight;
|
||||
|
||||
s->topBand = topBand;
|
||||
s->bottomBand = bottomBand;
|
||||
s->leftBand = leftBand;
|
||||
s->rightBand = rightBand;
|
||||
|
||||
s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / owidth;
|
||||
s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / oheight;
|
||||
|
||||
build_filter(&s->h_filters[0][0], (float) owidth / (float) (iwidth - leftBand - rightBand));
|
||||
build_filter(&s->v_filters[0][0], (float) oheight / (float) (iheight - topBand - bottomBand));
|
||||
|
||||
s->padtop = padtop;
|
||||
s->padbottom = padbottom;
|
||||
s->padleft = padleft;
|
||||
s->padright = padright;
|
||||
|
||||
s->pad_owidth = owidth - (padleft + padright);
|
||||
s->pad_oheight = oheight - (padtop + padbottom);
|
||||
|
||||
s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / s->pad_owidth;
|
||||
s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / s->pad_oheight;
|
||||
|
||||
av_build_filter(&s->h_filters[0][0], (float) s->pad_owidth /
|
||||
(float) (iwidth - leftBand - rightBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
|
||||
av_build_filter(&s->v_filters[0][0], (float) s->pad_oheight /
|
||||
(float) (iheight - topBand - bottomBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
|
||||
|
||||
return s;
|
||||
fail:
|
||||
fail:
|
||||
av_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void img_resample(ImgReSampleContext *s,
|
||||
void img_resample(ImgReSampleContext *s,
|
||||
AVPicture *output, const AVPicture *input)
|
||||
{
|
||||
int i, shift;
|
||||
uint8_t* optr;
|
||||
|
||||
for(i=0;i<3;i++) {
|
||||
for (i=0;i<3;i++) {
|
||||
shift = (i == 0) ? 0 : 1;
|
||||
component_resample(s, output->data[i], output->linesize[i],
|
||||
s->owidth >> shift, s->oheight >> shift,
|
||||
input->data[i] + (input->linesize[i] * (s->topBand >> shift)) + (s->leftBand >> shift),
|
||||
input->linesize[i], ((s->iwidth - s->leftBand - s->rightBand) >> shift),
|
||||
|
||||
optr = output->data[i] + (((output->linesize[i] *
|
||||
s->padtop) + s->padleft) >> shift);
|
||||
|
||||
component_resample(s, optr, output->linesize[i],
|
||||
s->pad_owidth >> shift, s->pad_oheight >> shift,
|
||||
input->data[i] + (input->linesize[i] *
|
||||
(s->topBand >> shift)) + (s->leftBand >> shift),
|
||||
input->linesize[i], ((s->iwidth - s->leftBand -
|
||||
s->rightBand) >> shift),
|
||||
(s->iheight - s->topBand - s->bottomBand) >> shift);
|
||||
}
|
||||
}
|
||||
@@ -631,22 +512,192 @@ void img_resample_close(ImgReSampleContext *s)
|
||||
av_free(s);
|
||||
}
|
||||
|
||||
static const char *context_to_name(void* ptr)
|
||||
{
|
||||
return "imgconvert";
|
||||
}
|
||||
|
||||
static const AVClass context_class = { "imgresample", context_to_name, NULL };
|
||||
|
||||
struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
|
||||
int dstW, int dstH, int dstFormat,
|
||||
int flags, SwsFilter *srcFilter,
|
||||
SwsFilter *dstFilter, double *param)
|
||||
{
|
||||
struct SwsContext *ctx;
|
||||
|
||||
ctx = av_malloc(sizeof(struct SwsContext));
|
||||
if (!ctx) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
ctx->av_class = &context_class;
|
||||
|
||||
if ((srcH != dstH) || (srcW != dstW)) {
|
||||
if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
|
||||
av_log(ctx, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
|
||||
}
|
||||
ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
|
||||
} else {
|
||||
ctx->resampling_ctx = av_malloc(sizeof(ImgReSampleContext));
|
||||
ctx->resampling_ctx->iheight = srcH;
|
||||
ctx->resampling_ctx->iwidth = srcW;
|
||||
ctx->resampling_ctx->oheight = dstH;
|
||||
ctx->resampling_ctx->owidth = dstW;
|
||||
}
|
||||
ctx->src_pix_fmt = srcFormat;
|
||||
ctx->dst_pix_fmt = dstFormat;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void sws_freeContext(struct SwsContext *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
|
||||
(ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
|
||||
img_resample_close(ctx->resampling_ctx);
|
||||
} else {
|
||||
av_free(ctx->resampling_ctx);
|
||||
}
|
||||
av_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if context is valid or reallocs a new one instead.
|
||||
* If context is NULL, just calls sws_getContext() to get a new one.
|
||||
* Otherwise, checks if the parameters are the same already saved in context.
|
||||
* If that is the case, returns the current context.
|
||||
* Otherwise, frees context and gets a new one.
|
||||
*
|
||||
* Be warned that srcFilter, dstFilter are not checked, they are
|
||||
* asumed to remain valid.
|
||||
*/
|
||||
struct SwsContext *sws_getCachedContext(struct SwsContext *ctx,
|
||||
int srcW, int srcH, int srcFormat,
|
||||
int dstW, int dstH, int dstFormat, int flags,
|
||||
SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
|
||||
{
|
||||
if (ctx != NULL) {
|
||||
if ((ctx->resampling_ctx->iwidth != srcW) ||
|
||||
(ctx->resampling_ctx->iheight != srcH) ||
|
||||
(ctx->src_pix_fmt != srcFormat) ||
|
||||
(ctx->resampling_ctx->owidth != dstW) ||
|
||||
(ctx->resampling_ctx->oheight != dstH) ||
|
||||
(ctx->dst_pix_fmt != dstFormat))
|
||||
{
|
||||
sws_freeContext(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
}
|
||||
if (ctx == NULL) {
|
||||
return sws_getContext(srcW, srcH, srcFormat,
|
||||
dstW, dstH, dstFormat, flags,
|
||||
srcFilter, dstFilter, param);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[],
|
||||
int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
|
||||
{
|
||||
AVPicture src_pict, dst_pict;
|
||||
int i, res = 0;
|
||||
AVPicture picture_format_temp;
|
||||
AVPicture picture_resample_temp, *formatted_picture, *resampled_picture;
|
||||
uint8_t *buf1 = NULL, *buf2 = NULL;
|
||||
enum PixelFormat current_pix_fmt;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
src_pict.data[i] = src[i];
|
||||
src_pict.linesize[i] = srcStride[i];
|
||||
dst_pict.data[i] = dst[i];
|
||||
dst_pict.linesize[i] = dstStride[i];
|
||||
}
|
||||
if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
|
||||
(ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
|
||||
/* We have to rescale the picture, but only YUV420P rescaling is supported... */
|
||||
|
||||
if (ctx->src_pix_fmt != PIX_FMT_YUV420P) {
|
||||
int size;
|
||||
|
||||
/* create temporary picture for rescaling input*/
|
||||
size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
|
||||
buf1 = av_malloc(size);
|
||||
if (!buf1) {
|
||||
res = -1;
|
||||
goto the_end;
|
||||
}
|
||||
formatted_picture = &picture_format_temp;
|
||||
avpicture_fill((AVPicture*)formatted_picture, buf1,
|
||||
PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
|
||||
|
||||
if (img_convert((AVPicture*)formatted_picture, PIX_FMT_YUV420P,
|
||||
&src_pict, ctx->src_pix_fmt,
|
||||
ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight) < 0) {
|
||||
|
||||
av_log(ctx, AV_LOG_ERROR, "pixel format conversion not handled\n");
|
||||
res = -1;
|
||||
goto the_end;
|
||||
}
|
||||
} else {
|
||||
formatted_picture = &src_pict;
|
||||
}
|
||||
|
||||
if (ctx->dst_pix_fmt != PIX_FMT_YUV420P) {
|
||||
int size;
|
||||
|
||||
/* create temporary picture for rescaling output*/
|
||||
size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
|
||||
buf2 = av_malloc(size);
|
||||
if (!buf2) {
|
||||
res = -1;
|
||||
goto the_end;
|
||||
}
|
||||
resampled_picture = &picture_resample_temp;
|
||||
avpicture_fill((AVPicture*)resampled_picture, buf2,
|
||||
PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
|
||||
|
||||
} else {
|
||||
resampled_picture = &dst_pict;
|
||||
}
|
||||
|
||||
/* ...and finally rescale!!! */
|
||||
img_resample(ctx->resampling_ctx, resampled_picture, formatted_picture);
|
||||
current_pix_fmt = PIX_FMT_YUV420P;
|
||||
} else {
|
||||
resampled_picture = &src_pict;
|
||||
current_pix_fmt = ctx->src_pix_fmt;
|
||||
}
|
||||
|
||||
if (current_pix_fmt != ctx->dst_pix_fmt) {
|
||||
if (img_convert(&dst_pict, ctx->dst_pix_fmt,
|
||||
resampled_picture, current_pix_fmt,
|
||||
ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight) < 0) {
|
||||
|
||||
av_log(ctx, AV_LOG_ERROR, "pixel format conversion not handled\n");
|
||||
|
||||
res = -1;
|
||||
goto the_end;
|
||||
}
|
||||
} else if (resampled_picture != &dst_pict) {
|
||||
av_picture_copy(&dst_pict, resampled_picture, current_pix_fmt,
|
||||
ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
|
||||
}
|
||||
|
||||
the_end:
|
||||
av_free(buf1);
|
||||
av_free(buf2);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void *av_mallocz(int size)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = malloc(size);
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void av_free(void *ptr)
|
||||
{
|
||||
/* XXX: this test should not be needed on most libcs */
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
}
|
||||
#include <stdio.h>
|
||||
#undef exit
|
||||
|
||||
/* input */
|
||||
#define XSIZE 256
|
||||
@@ -661,11 +712,13 @@ uint8_t img2[XSIZE1 * YSIZE1];
|
||||
|
||||
void save_pgm(const char *filename, uint8_t *img, int xsize, int ysize)
|
||||
{
|
||||
#undef fprintf
|
||||
FILE *f;
|
||||
f=fopen(filename,"w");
|
||||
fprintf(f,"P5\n%d %d\n%d\n", xsize, ysize, 255);
|
||||
fwrite(img,1, xsize * ysize,f);
|
||||
fclose(f);
|
||||
#define fprintf please_use_av_log
|
||||
}
|
||||
|
||||
static void dump_filter(int16_t *filter)
|
||||
@@ -673,11 +726,11 @@ static void dump_filter(int16_t *filter)
|
||||
int i, ph;
|
||||
|
||||
for(ph=0;ph<NB_PHASES;ph++) {
|
||||
printf("%2d: ", ph);
|
||||
av_log(NULL, AV_LOG_INFO, "%2d: ", ph);
|
||||
for(i=0;i<NB_TAPS;i++) {
|
||||
printf(" %5.2f", filter[ph * NB_TAPS + i] / 256.0);
|
||||
av_log(NULL, AV_LOG_INFO, " %5.2f", filter[ph * NB_TAPS + i] / 256.0);
|
||||
}
|
||||
printf("\n");
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,20 +756,20 @@ int main(int argc, char **argv)
|
||||
else
|
||||
v = 0x00;
|
||||
} else if (x < XSIZE/4) {
|
||||
if (x & 1)
|
||||
if (x & 1)
|
||||
v = 0xff;
|
||||
else
|
||||
else
|
||||
v = 0;
|
||||
} else if (y < XSIZE/4) {
|
||||
if (y & 1)
|
||||
if (y & 1)
|
||||
v = 0xff;
|
||||
else
|
||||
else
|
||||
v = 0;
|
||||
} else {
|
||||
if (y < YSIZE*3/8) {
|
||||
if ((y+x) & 1)
|
||||
if ((y+x) & 1)
|
||||
v = 0xff;
|
||||
else
|
||||
else
|
||||
v = 0;
|
||||
} else {
|
||||
if (((x+3) % 4) <= 1 &&
|
||||
@@ -741,20 +794,20 @@ int main(int argc, char **argv)
|
||||
fact = factors[i];
|
||||
xsize = (int)(XSIZE * fact);
|
||||
ysize = (int)((YSIZE - 100) * fact);
|
||||
s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50, 0, 0);
|
||||
printf("Factor=%0.2f\n", fact);
|
||||
s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50, 0, 0, 0, 0, 0, 0);
|
||||
av_log(NULL, AV_LOG_INFO, "Factor=%0.2f\n", fact);
|
||||
dump_filter(&s->h_filters[0][0]);
|
||||
component_resample(s, img1, xsize, xsize, ysize,
|
||||
img + 50 * XSIZE, XSIZE, XSIZE, YSIZE - 100);
|
||||
img_resample_close(s);
|
||||
|
||||
sprintf(buf, "/tmp/out%d.pgm", i);
|
||||
snprintf(buf, sizeof(buf), "/tmp/out%d.pgm", i);
|
||||
save_pgm(buf, img1, xsize, ysize);
|
||||
}
|
||||
|
||||
/* mmx test */
|
||||
#ifdef HAVE_MMX
|
||||
printf("MMX test\n");
|
||||
av_log(NULL, AV_LOG_INFO, "MMX test\n");
|
||||
fact = 0.72;
|
||||
xsize = (int)(XSIZE * fact);
|
||||
ysize = (int)(YSIZE * fact);
|
||||
@@ -768,12 +821,12 @@ int main(int argc, char **argv)
|
||||
component_resample(s, img2, xsize, xsize, ysize,
|
||||
img, XSIZE, XSIZE, YSIZE);
|
||||
if (memcmp(img1, img2, xsize * ysize) != 0) {
|
||||
fprintf(stderr, "mmx error\n");
|
||||
av_log(NULL, AV_LOG_ERROR, "mmx error\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("MMX OK\n");
|
||||
#endif
|
||||
av_log(NULL, AV_LOG_INFO, "MMX OK\n");
|
||||
#endif /* HAVE_MMX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* TEST */
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* imx dump header bitstream filter
|
||||
* Copyright (c) 2007 Baptiste Coudurier.
|
||||
*
|
||||
* 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 imx_dump_header_bsf.c
|
||||
* imx dump header bitstream filter
|
||||
* modifies bitstream to fit in mov and be decoded by final cut pro decoder
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
|
||||
static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size, int keyframe)
|
||||
{
|
||||
/* MXF essence element key */
|
||||
static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 };
|
||||
uint8_t *poutbufp;
|
||||
|
||||
if (avctx->codec_id != CODEC_ID_MPEG2VIDEO) {
|
||||
av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*poutbuf = av_malloc(buf_size + 20 + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
poutbufp = *poutbuf;
|
||||
bytestream_put_buffer(&poutbufp, imx_header, 16);
|
||||
bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */
|
||||
bytestream_put_be24(&poutbufp, buf_size);
|
||||
bytestream_put_buffer(&poutbufp, buf, buf_size);
|
||||
*poutbuf_size = poutbufp - *poutbuf;
|
||||
return 1;
|
||||
}
|
||||
|
||||
AVBitStreamFilter imx_dump_header_bsf = {
|
||||
"imxdump",
|
||||
0,
|
||||
imx_dump_header,
|
||||
};
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Intel Indeo 2 codec
|
||||
* Copyright (c) 2005 Konstantin Shishkov
|
||||
*
|
||||
* 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 indeo2.c
|
||||
* Intel Indeo 2 decoder.
|
||||
*/
|
||||
#define ALT_BITSTREAM_READER_LE
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
#include "indeo2data.h"
|
||||
|
||||
typedef struct Ir2Context{
|
||||
AVCodecContext *avctx;
|
||||
AVFrame picture;
|
||||
GetBitContext gb;
|
||||
int decode_delta;
|
||||
} Ir2Context;
|
||||
|
||||
#define CODE_VLC_BITS 14
|
||||
static VLC ir2_vlc;
|
||||
|
||||
/* Indeo 2 codes are in range 0x01..0x7F and 0x81..0x90 */
|
||||
static inline int ir2_get_code(GetBitContext *gb)
|
||||
{
|
||||
return get_vlc2(gb, ir2_vlc.table, CODE_VLC_BITS, 1) + 1;
|
||||
}
|
||||
|
||||
static int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst, int stride,
|
||||
const uint8_t *table)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int out = 0;
|
||||
int c;
|
||||
int t;
|
||||
|
||||
if(width&1)
|
||||
return -1;
|
||||
|
||||
/* first line contain absolute values, other lines contain deltas */
|
||||
while (out < width){
|
||||
c = ir2_get_code(&ctx->gb);
|
||||
if(c >= 0x80) { /* we have a run */
|
||||
c -= 0x7F;
|
||||
if(out + c*2 > width)
|
||||
return -1;
|
||||
for (i = 0; i < c * 2; i++)
|
||||
dst[out++] = 0x80;
|
||||
} else { /* copy two values from table */
|
||||
dst[out++] = table[c * 2];
|
||||
dst[out++] = table[(c * 2) + 1];
|
||||
}
|
||||
}
|
||||
dst += stride;
|
||||
|
||||
for (j = 1; j < height; j++){
|
||||
out = 0;
|
||||
while (out < width){
|
||||
c = ir2_get_code(&ctx->gb);
|
||||
if(c >= 0x80) { /* we have a skip */
|
||||
c -= 0x7F;
|
||||
if(out + c*2 > width)
|
||||
return -1;
|
||||
for (i = 0; i < c * 2; i++) {
|
||||
dst[out] = dst[out - stride];
|
||||
out++;
|
||||
}
|
||||
} else { /* add two deltas from table */
|
||||
t = dst[out - stride] + (table[c * 2] - 128);
|
||||
t= av_clip_uint8(t);
|
||||
dst[out] = t;
|
||||
out++;
|
||||
t = dst[out - stride] + (table[(c * 2) + 1] - 128);
|
||||
t= av_clip_uint8(t);
|
||||
dst[out] = t;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
dst += stride;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir2_decode_plane_inter(Ir2Context *ctx, int width, int height, uint8_t *dst, int stride,
|
||||
const uint8_t *table)
|
||||
{
|
||||
int j;
|
||||
int out = 0;
|
||||
int c;
|
||||
int t;
|
||||
|
||||
if(width&1)
|
||||
return -1;
|
||||
|
||||
for (j = 0; j < height; j++){
|
||||
out = 0;
|
||||
while (out < width){
|
||||
c = ir2_get_code(&ctx->gb);
|
||||
if(c >= 0x80) { /* we have a skip */
|
||||
c -= 0x7F;
|
||||
out += c * 2;
|
||||
} else { /* add two deltas from table */
|
||||
t = dst[out] + (((table[c * 2] - 128)*3) >> 2);
|
||||
t= av_clip_uint8(t);
|
||||
dst[out] = t;
|
||||
out++;
|
||||
t = dst[out] + (((table[(c * 2) + 1] - 128)*3) >> 2);
|
||||
t= av_clip_uint8(t);
|
||||
dst[out] = t;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
dst += stride;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir2_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
Ir2Context * const s = avctx->priv_data;
|
||||
AVFrame *picture = data;
|
||||
AVFrame * const p= (AVFrame*)&s->picture;
|
||||
int start;
|
||||
|
||||
if(p->data[0])
|
||||
avctx->release_buffer(avctx, p);
|
||||
|
||||
p->reference = 1;
|
||||
p->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
|
||||
if (avctx->reget_buffer(avctx, p)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->decode_delta = buf[18];
|
||||
|
||||
/* decide whether frame uses deltas or not */
|
||||
#ifndef ALT_BITSTREAM_READER_LE
|
||||
for (i = 0; i < buf_size; i++)
|
||||
buf[i] = ff_reverse[buf[i]];
|
||||
#endif
|
||||
start = 48; /* hardcoded for now */
|
||||
|
||||
init_get_bits(&s->gb, buf + start, buf_size - start);
|
||||
|
||||
if (s->decode_delta) { /* intraframe */
|
||||
ir2_decode_plane(s, avctx->width, avctx->height,
|
||||
s->picture.data[0], s->picture.linesize[0], ir2_luma_table);
|
||||
/* swapped U and V */
|
||||
ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2,
|
||||
s->picture.data[2], s->picture.linesize[2], ir2_luma_table);
|
||||
ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2,
|
||||
s->picture.data[1], s->picture.linesize[1], ir2_luma_table);
|
||||
} else { /* interframe */
|
||||
ir2_decode_plane_inter(s, avctx->width, avctx->height,
|
||||
s->picture.data[0], s->picture.linesize[0], ir2_luma_table);
|
||||
/* swapped U and V */
|
||||
ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2,
|
||||
s->picture.data[2], s->picture.linesize[2], ir2_luma_table);
|
||||
ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2,
|
||||
s->picture.data[1], s->picture.linesize[1], ir2_luma_table);
|
||||
}
|
||||
|
||||
*picture= *(AVFrame*)&s->picture;
|
||||
*data_size = sizeof(AVPicture);
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static av_cold int ir2_decode_init(AVCodecContext *avctx){
|
||||
Ir2Context * const ic = avctx->priv_data;
|
||||
|
||||
ic->avctx = avctx;
|
||||
|
||||
avctx->pix_fmt= PIX_FMT_YUV410P;
|
||||
|
||||
if (!ir2_vlc.table)
|
||||
#ifdef ALT_BITSTREAM_READER_LE
|
||||
init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES,
|
||||
&ir2_codes[0][1], 4, 2,
|
||||
&ir2_codes[0][0], 4, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
|
||||
#else
|
||||
init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES,
|
||||
&ir2_codes[0][1], 4, 2,
|
||||
&ir2_codes[0][0], 4, 2, INIT_VLC_USE_STATIC);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec indeo2_decoder = {
|
||||
"indeo2",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_INDEO2,
|
||||
sizeof(Ir2Context),
|
||||
ir2_decode_init,
|
||||
NULL,
|
||||
NULL,
|
||||
ir2_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 2"),
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Intel Indeo 2 codec
|
||||
* copyright (c) 2005 Konstantin Shishkov
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_INDEO2DATA_H
|
||||
#define FFMPEG_INDEO2DATA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define IR2_CODES 143
|
||||
static const uint16_t ir2_codes[IR2_CODES][2] = {
|
||||
#ifdef ALT_BITSTREAM_READER_LE
|
||||
{0x0000, 3}, {0x0004, 3}, {0x0006, 3}, {0x0001, 5},
|
||||
{0x0009, 5}, {0x0019, 5}, {0x000D, 5}, {0x001D, 5},
|
||||
{0x0023, 6}, {0x0013, 6}, {0x0033, 6}, {0x000B, 6},
|
||||
{0x002B, 6}, {0x001B, 6}, {0x0007, 8}, {0x0087, 8},
|
||||
{0x0027, 8}, {0x00A7, 8}, {0x0067, 8}, {0x00E7, 8},
|
||||
{0x0097, 8}, {0x0057, 8}, {0x0037, 8}, {0x00B7, 8},
|
||||
{0x00F7, 8}, {0x000F, 9}, {0x008F, 9}, {0x018F, 9},
|
||||
{0x014F, 9}, {0x00CF, 9}, {0x002F, 9}, {0x012F, 9},
|
||||
{0x01AF, 9}, {0x006F, 9}, {0x00EF, 9}, {0x01EF, 9},
|
||||
{0x001F, 10}, {0x021F, 10}, {0x011F, 10}, {0x031F, 10},
|
||||
{0x009F, 10}, {0x029F, 10}, {0x019F, 10}, {0x039F, 10},
|
||||
{0x005F, 10}, {0x025F, 10}, {0x015F, 10}, {0x035F, 10},
|
||||
{0x00DF, 10}, {0x02DF, 10}, {0x01DF, 10}, {0x03DF, 10},
|
||||
{0x003F, 13}, {0x103F, 13}, {0x083F, 13}, {0x183F, 13},
|
||||
{0x043F, 13}, {0x143F, 13}, {0x0C3F, 13}, {0x1C3F, 13},
|
||||
{0x023F, 13}, {0x123F, 13}, {0x0A3F, 13}, {0x1A3F, 13},
|
||||
{0x063F, 13}, {0x163F, 13}, {0x0E3F, 13}, {0x1E3F, 13},
|
||||
{0x013F, 13}, {0x113F, 13}, {0x093F, 13}, {0x193F, 13},
|
||||
{0x053F, 13}, {0x153F, 13}, {0x0D3F, 13}, {0x1D3F, 13},
|
||||
{0x033F, 13}, {0x133F, 13}, {0x0B3F, 13}, {0x1B3F, 13},
|
||||
{0x073F, 13}, {0x173F, 13}, {0x0F3F, 13}, {0x1F3F, 13},
|
||||
{0x00BF, 13}, {0x10BF, 13}, {0x08BF, 13}, {0x18BF, 13},
|
||||
{0x04BF, 13}, {0x14BF, 13}, {0x0CBF, 13}, {0x1CBF, 13},
|
||||
{0x02BF, 13}, {0x12BF, 13}, {0x0ABF, 13}, {0x1ABF, 13},
|
||||
{0x06BF, 13}, {0x16BF, 13}, {0x0EBF, 13}, {0x1EBF, 13},
|
||||
{0x01BF, 13}, {0x11BF, 13}, {0x09BF, 13}, {0x19BF, 13},
|
||||
{0x05BF, 13}, {0x15BF, 13}, {0x0DBF, 13}, {0x1DBF, 13},
|
||||
{0x03BF, 13}, {0x13BF, 13}, {0x0BBF, 13}, {0x1BBF, 13},
|
||||
{0x07BF, 13}, {0x17BF, 13}, {0x0FBF, 13}, {0x1FBF, 13},
|
||||
{0x007F, 14}, {0x207F, 14}, {0x107F, 14}, {0x307F, 14},
|
||||
{0x087F, 14}, {0x287F, 14}, {0x187F, 14}, {0x387F, 14},
|
||||
{0x047F, 14}, {0x247F, 14}, {0x147F, 14}, {0x0002, 3},
|
||||
{0x0011, 5}, {0x0005, 5}, {0x0015, 5}, {0x0003, 6},
|
||||
{0x003B, 6}, {0x0047, 8}, {0x00C7, 8}, {0x0017, 8},
|
||||
{0x00D7, 8}, {0x0077, 8}, {0x010F, 9}, {0x004F, 9},
|
||||
{0x01CF, 9}, {0x00AF, 9}, {0x016F, 9},
|
||||
#else
|
||||
{0x0000, 3}, {0x0001, 3}, {0x0003, 3}, {0x0010, 5},
|
||||
{0x0012, 5}, {0x0013, 5}, {0x0016, 5}, {0x0017, 5},
|
||||
{0x0031, 6}, {0x0032, 6}, {0x0033, 6}, {0x0034, 6},
|
||||
{0x0035, 6}, {0x0036, 6}, {0x00E0, 8}, {0x00E1, 8},
|
||||
{0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, {0x00E7, 8},
|
||||
{0x00E9, 8}, {0x00EA, 8}, {0x00EC, 8}, {0x00ED, 8},
|
||||
{0x00EF, 8}, {0x01E0, 9}, {0x01E2, 9}, {0x01E3, 9},
|
||||
{0x01E5, 9}, {0x01E6, 9}, {0x01E8, 9}, {0x01E9, 9},
|
||||
{0x01EB, 9}, {0x01EC, 9}, {0x01EE, 9}, {0x01EF, 9},
|
||||
{0x03E0, 10}, {0x03E1, 10}, {0x03E2, 10}, {0x03E3, 10},
|
||||
{0x03E4, 10}, {0x03E5, 10}, {0x03E6, 10}, {0x03E7, 10},
|
||||
{0x03E8, 10}, {0x03E9, 10}, {0x03EA, 10}, {0x03EB, 10},
|
||||
{0x03EC, 10}, {0x03ED, 10}, {0x03EE, 10}, {0x03EF, 10},
|
||||
{0x1F80, 13}, {0x1F81, 13}, {0x1F82, 13}, {0x1F83, 13},
|
||||
{0x1F84, 13}, {0x1F85, 13}, {0x1F86, 13}, {0x1F87, 13},
|
||||
{0x1F88, 13}, {0x1F89, 13}, {0x1F8A, 13}, {0x1F8B, 13},
|
||||
{0x1F8C, 13}, {0x1F8D, 13}, {0x1F8E, 13}, {0x1F8F, 13},
|
||||
{0x1F90, 13}, {0x1F91, 13}, {0x1F92, 13}, {0x1F93, 13},
|
||||
{0x1F94, 13}, {0x1F95, 13}, {0x1F96, 13}, {0x1F97, 13},
|
||||
{0x1F98, 13}, {0x1F99, 13}, {0x1F9A, 13}, {0x1F9B, 13},
|
||||
{0x1F9C, 13}, {0x1F9D, 13}, {0x1F9E, 13}, {0x1F9F, 13},
|
||||
{0x1FA0, 13}, {0x1FA1, 13}, {0x1FA2, 13}, {0x1FA3, 13},
|
||||
{0x1FA4, 13}, {0x1FA5, 13}, {0x1FA6, 13}, {0x1FA7, 13},
|
||||
{0x1FA8, 13}, {0x1FA9, 13}, {0x1FAA, 13}, {0x1FAB, 13},
|
||||
{0x1FAC, 13}, {0x1FAD, 13}, {0x1FAE, 13}, {0x1FAF, 13},
|
||||
{0x1FB0, 13}, {0x1FB1, 13}, {0x1FB2, 13}, {0x1FB3, 13},
|
||||
{0x1FB4, 13}, {0x1FB5, 13}, {0x1FB6, 13}, {0x1FB7, 13},
|
||||
{0x1FB8, 13}, {0x1FB9, 13}, {0x1FBA, 13}, {0x1FBB, 13},
|
||||
{0x1FBC, 13}, {0x1FBD, 13}, {0x1FBE, 13}, {0x1FBF, 13},
|
||||
{0x3F80, 14}, {0x3F81, 14}, {0x3F82, 14}, {0x3F83, 14},
|
||||
{0x3F84, 14}, {0x3F85, 14}, {0x3F86, 14}, {0x3F87, 14},
|
||||
{0x3F88, 14}, {0x3F89, 14}, {0x3F8A, 14}, {0x0002, 3},
|
||||
{0x0011, 5}, {0x0014, 5}, {0x0015, 5}, {0x0030, 6},
|
||||
{0x0037, 6}, {0x00E2, 8}, {0x00E3, 8}, {0x00E8, 8},
|
||||
{0x00EB, 8}, {0x00EE, 8}, {0x01E1, 9}, {0x01E4, 9},
|
||||
{0x01E7, 9}, {0x01EA, 9}, {0x01ED, 9}
|
||||
#endif
|
||||
};
|
||||
|
||||
static const uint8_t ir2_luma_table[256] = {
|
||||
0x80, 0x80, 0x84, 0x84, 0x7C, 0x7C, 0x7F, 0x85,
|
||||
0x81, 0x7B, 0x85, 0x7F, 0x7B, 0x81, 0x8C, 0x8C,
|
||||
0x74, 0x74, 0x83, 0x8D, 0x7D, 0x73, 0x8D, 0x83,
|
||||
0x73, 0x7D, 0x77, 0x89, 0x89, 0x77, 0x89, 0x77,
|
||||
0x77, 0x89, 0x8C, 0x95, 0x74, 0x6B, 0x95, 0x8C,
|
||||
0x6B, 0x74, 0x7C, 0x90, 0x84, 0x70, 0x90, 0x7C,
|
||||
0x70, 0x84, 0x96, 0x96, 0x6A, 0x6A, 0x82, 0x98,
|
||||
0x7E, 0x68, 0x98, 0x82, 0x68, 0x7E, 0x97, 0xA2,
|
||||
0x69, 0x5E, 0xA2, 0x97, 0x5E, 0x69, 0xA2, 0xA2,
|
||||
0x5E, 0x5E, 0x8B, 0xA3, 0x75, 0x5D, 0xA3, 0x8B,
|
||||
0x5D, 0x75, 0x71, 0x95, 0x8F, 0x6B, 0x95, 0x71,
|
||||
0x6B, 0x8F, 0x78, 0x9D, 0x88, 0x63, 0x9D, 0x78,
|
||||
0x63, 0x88, 0x7F, 0xA7, 0x81, 0x59, 0xA7, 0x7F,
|
||||
0x59, 0x81, 0xA4, 0xB1, 0x5C, 0x4F, 0xB1, 0xA4,
|
||||
0x4F, 0x5C, 0x96, 0xB1, 0x6A, 0x4F, 0xB1, 0x96,
|
||||
0x4F, 0x6A, 0xB2, 0xB2, 0x4E, 0x4E, 0x65, 0x9B,
|
||||
0x9B, 0x65, 0x9B, 0x65, 0x65, 0x9B, 0x89, 0xB4,
|
||||
0x77, 0x4C, 0xB4, 0x89, 0x4C, 0x77, 0x6A, 0xA3,
|
||||
0x96, 0x5D, 0xA3, 0x6A, 0x5D, 0x96, 0x73, 0xAC,
|
||||
0x8D, 0x54, 0xAC, 0x73, 0x54, 0x8D, 0xB4, 0xC3,
|
||||
0x4C, 0x3D, 0xC3, 0xB4, 0x3D, 0x4C, 0xA4, 0xC3,
|
||||
0x5C, 0x3D, 0xC3, 0xA4, 0x3D, 0x5C, 0xC4, 0xC4,
|
||||
0x3C, 0x3C, 0x96, 0xC6, 0x6A, 0x3A, 0xC6, 0x96,
|
||||
0x3A, 0x6A, 0x7C, 0xBA, 0x84, 0x46, 0xBA, 0x7C,
|
||||
0x46, 0x84, 0x5B, 0xAB, 0xA5, 0x55, 0xAB, 0x5B,
|
||||
0x55, 0xA5, 0x63, 0xB4, 0x9D, 0x4C, 0xB4, 0x63,
|
||||
0x4C, 0x9D, 0x86, 0xCA, 0x7A, 0x36, 0xCA, 0x86,
|
||||
0x36, 0x7A, 0xB6, 0xD7, 0x4A, 0x29, 0xD7, 0xB6,
|
||||
0x29, 0x4A, 0xC8, 0xD7, 0x38, 0x29, 0xD7, 0xC8,
|
||||
0x29, 0x38, 0xA4, 0xD8, 0x5C, 0x28, 0xD8, 0xA4,
|
||||
0x28, 0x5C, 0x6C, 0xC1, 0x94, 0x3F, 0xC1, 0x6C,
|
||||
0x3F, 0x94, 0xD9, 0xD9, 0x27, 0x27, 0x80, 0x80
|
||||
};
|
||||
|
||||
#endif /* FFMPEG_INDEO2DATA_H */
|
||||
@@ -2,19 +2,21 @@
|
||||
* Intel Indeo 3 (IV31, IV32, etc.) video decoder for ffmpeg
|
||||
* written, produced, and directed by Alan Smithee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -22,10 +24,9 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
#include "mpegvideo.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
#include "indeo3data.h"
|
||||
|
||||
@@ -53,15 +54,15 @@ typedef struct Indeo3DecodeContext {
|
||||
unsigned short *corrector_type;
|
||||
} Indeo3DecodeContext;
|
||||
|
||||
static int corrector_type_0[24] = {
|
||||
static const int corrector_type_0[24] = {
|
||||
195, 159, 133, 115, 101, 93, 87, 77,
|
||||
195, 159, 133, 115, 101, 93, 87, 77,
|
||||
128, 79, 79, 79, 79, 79, 79, 79
|
||||
};
|
||||
|
||||
static int corrector_type_2[8] = { 9, 7, 6, 8, 5, 4, 3, 2 };
|
||||
static const int corrector_type_2[8] = { 9, 7, 6, 8, 5, 4, 3, 2 };
|
||||
|
||||
static void build_modpred(Indeo3DecodeContext *s)
|
||||
static av_cold void build_modpred(Indeo3DecodeContext *s)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@@ -70,13 +71,13 @@ static void build_modpred(Indeo3DecodeContext *s)
|
||||
for (i=0; i < 128; ++i) {
|
||||
s->ModPred[i+0*128] = (i > 126) ? 254 : 2*((i + 1) - ((i + 1) % 2));
|
||||
s->ModPred[i+1*128] = (i == 7) ? 20 : ((i == 119 || i == 120)
|
||||
? 236 : 2*((i + 2) - ((i + 1) % 3)));
|
||||
? 236 : 2*((i + 2) - ((i + 1) % 3)));
|
||||
s->ModPred[i+2*128] = (i > 125) ? 248 : 2*((i + 2) - ((i + 2) % 4));
|
||||
s->ModPred[i+3*128] = 2*((i + 1) - ((i - 3) % 5));
|
||||
s->ModPred[i+3*128] = 2*((i + 1) - ((i - 3) % 5));
|
||||
s->ModPred[i+4*128] = (i == 8) ? 20 : 2*((i + 1) - ((i - 3) % 6));
|
||||
s->ModPred[i+5*128] = 2*((i + 4) - ((i + 3) % 7));
|
||||
s->ModPred[i+5*128] = 2*((i + 4) - ((i + 3) % 7));
|
||||
s->ModPred[i+6*128] = (i > 123) ? 240 : 2*((i + 4) - ((i + 4) % 8));
|
||||
s->ModPred[i+7*128] = 2*((i + 5) - ((i + 4) % 9));
|
||||
s->ModPred[i+7*128] = 2*((i + 5) - ((i + 4) % 9));
|
||||
}
|
||||
|
||||
s->corrector_type = (unsigned short *) av_malloc (24 * 256 * sizeof(unsigned short));
|
||||
@@ -84,31 +85,30 @@ static void build_modpred(Indeo3DecodeContext *s)
|
||||
for (i=0; i < 24; ++i) {
|
||||
for (j=0; j < 256; ++j) {
|
||||
s->corrector_type[i*256+j] = (j < corrector_type_0[i])
|
||||
? 1 : ((j < 248 || (i == 16 && j == 248))
|
||||
? 0 : corrector_type_2[j - 248]);
|
||||
? 1 : ((j < 248 || (i == 16 && j == 248))
|
||||
? 0 : corrector_type_2[j - 248]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iv_Decode_Chunk(Indeo3DecodeContext *s, unsigned char *cur,
|
||||
unsigned char *ref, int width, int height, unsigned char *buf1,
|
||||
long fflags2, unsigned char *hdr,
|
||||
unsigned char *buf2, int min_width_160);
|
||||
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
static void iv_Decode_Chunk(Indeo3DecodeContext *s, unsigned char *cur,
|
||||
unsigned char *ref, int width, int height, const unsigned char *buf1,
|
||||
long fflags2, const unsigned char *hdr,
|
||||
const unsigned char *buf2, int min_width_160);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
static void iv_alloc_frames(Indeo3DecodeContext *s)
|
||||
static av_cold void iv_alloc_frames(Indeo3DecodeContext *s)
|
||||
{
|
||||
int luma_width, luma_height, luma_pixels, chroma_width, chroma_height,
|
||||
chroma_pixels, bufsize, i;
|
||||
chroma_pixels, i;
|
||||
unsigned int bufsize;
|
||||
|
||||
luma_width = (s->width + 3) & (~3);
|
||||
luma_height = (s->height + 3) & (~3);
|
||||
|
||||
s->iv_frame[0].y_w = s->iv_frame[0].y_h =
|
||||
s->iv_frame[0].y_w = s->iv_frame[0].y_h =
|
||||
s->iv_frame[0].the_buf_size = 0;
|
||||
s->iv_frame[1].y_w = s->iv_frame[1].y_h =
|
||||
s->iv_frame[1].y_w = s->iv_frame[1].y_h =
|
||||
s->iv_frame[1].the_buf_size = 0;
|
||||
s->iv_frame[1].the_buf = NULL;
|
||||
|
||||
@@ -117,11 +117,11 @@ static void iv_alloc_frames(Indeo3DecodeContext *s)
|
||||
luma_pixels = luma_width * luma_height;
|
||||
chroma_pixels = chroma_width * chroma_height;
|
||||
|
||||
bufsize = luma_pixels * 2 + luma_width * 3 +
|
||||
bufsize = luma_pixels * 2 + luma_width * 3 +
|
||||
(chroma_pixels + chroma_width) * 4;
|
||||
|
||||
if((s->iv_frame[0].the_buf =
|
||||
(s->iv_frame[0].the_buf_size == 0 ? av_malloc(bufsize) :
|
||||
if((s->iv_frame[0].the_buf =
|
||||
(s->iv_frame[0].the_buf_size == 0 ? av_malloc(bufsize) :
|
||||
av_realloc(s->iv_frame[0].the_buf, bufsize))) == NULL)
|
||||
return;
|
||||
s->iv_frame[0].y_w = s->iv_frame[1].y_w = luma_width;
|
||||
@@ -143,7 +143,7 @@ static void iv_alloc_frames(Indeo3DecodeContext *s)
|
||||
s->iv_frame[1].Vbuf = s->iv_frame[0].the_buf + i;
|
||||
|
||||
for(i = 1; i <= luma_width; i++)
|
||||
s->iv_frame[0].Ybuf[-i] = s->iv_frame[1].Ybuf[-i] =
|
||||
s->iv_frame[0].Ybuf[-i] = s->iv_frame[1].Ybuf[-i] =
|
||||
s->iv_frame[0].Ubuf[-i] = 0x80;
|
||||
|
||||
for(i = 1; i <= chroma_width; i++) {
|
||||
@@ -155,14 +155,14 @@ static void iv_alloc_frames(Indeo3DecodeContext *s)
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
static void iv_free_func(Indeo3DecodeContext *s)
|
||||
static av_cold void iv_free_func(Indeo3DecodeContext *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0 ; i < 2 ; i++) {
|
||||
if(s->iv_frame[i].the_buf != NULL)
|
||||
if(s->iv_frame[i].the_buf != NULL)
|
||||
av_free(s->iv_frame[i].the_buf);
|
||||
s->iv_frame[i].Ybuf = s->iv_frame[i].Ubuf =
|
||||
s->iv_frame[i].Ybuf = s->iv_frame[i].Ubuf =
|
||||
s->iv_frame[i].Vbuf = NULL;
|
||||
s->iv_frame[i].the_buf = NULL;
|
||||
s->iv_frame[i].the_buf_size = 0;
|
||||
@@ -175,35 +175,33 @@ static void iv_free_func(Indeo3DecodeContext *s)
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
|
||||
unsigned char *buf, int buf_size)
|
||||
static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
|
||||
const unsigned char *buf, int buf_size)
|
||||
{
|
||||
unsigned int hdr_width, hdr_height,
|
||||
chroma_width, chroma_height;
|
||||
unsigned long fflags1, fflags2, fflags3, offs1, offs2, offs3, offs;
|
||||
unsigned char *hdr_pos, *buf_pos;
|
||||
const unsigned char *hdr_pos, *buf_pos;
|
||||
|
||||
buf_pos = buf;
|
||||
buf_pos += 18;
|
||||
|
||||
fflags1 = le2me_16(*(uint16_t *)buf_pos);
|
||||
buf_pos += 2;
|
||||
fflags3 = le2me_32(*(uint32_t *)buf_pos);
|
||||
buf_pos += 4;
|
||||
fflags1 = bytestream_get_le16(&buf_pos);
|
||||
fflags3 = bytestream_get_le32(&buf_pos);
|
||||
fflags2 = *buf_pos++;
|
||||
buf_pos += 3;
|
||||
hdr_height = le2me_16(*(uint16_t *)buf_pos);
|
||||
buf_pos += 2;
|
||||
hdr_width = le2me_16(*(uint16_t *)buf_pos);
|
||||
buf_pos += 2;
|
||||
hdr_height = bytestream_get_le16(&buf_pos);
|
||||
hdr_width = bytestream_get_le16(&buf_pos);
|
||||
|
||||
if(avcodec_check_dimensions(NULL, hdr_width, hdr_height))
|
||||
return -1;
|
||||
|
||||
chroma_height = ((hdr_height >> 2) + 3) & 0x7ffc;
|
||||
chroma_width = ((hdr_width >> 2) + 3) & 0x7ffc;
|
||||
offs1 = le2me_32(*(uint32_t *)buf_pos);
|
||||
offs1 = bytestream_get_le32(&buf_pos);
|
||||
offs2 = bytestream_get_le32(&buf_pos);
|
||||
offs3 = bytestream_get_le32(&buf_pos);
|
||||
buf_pos += 4;
|
||||
offs2 = le2me_32(*(uint32_t *)buf_pos);
|
||||
buf_pos += 4;
|
||||
offs3 = le2me_32(*(uint32_t *)buf_pos);
|
||||
buf_pos += 8;
|
||||
hdr_pos = buf_pos;
|
||||
if(fflags3 == 0x80) return 4;
|
||||
|
||||
@@ -216,28 +214,30 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
|
||||
}
|
||||
|
||||
buf_pos = buf + 16 + offs1;
|
||||
offs = le2me_32(*(uint32_t *)buf_pos);
|
||||
buf_pos += 4;
|
||||
offs = bytestream_get_le32(&buf_pos);
|
||||
|
||||
iv_Decode_Chunk(s, s->cur_frame->Ybuf, s->ref_frame->Ybuf, hdr_width,
|
||||
hdr_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
|
||||
min(hdr_width, 160));
|
||||
iv_Decode_Chunk(s, s->cur_frame->Ybuf, s->ref_frame->Ybuf, hdr_width,
|
||||
hdr_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
|
||||
FFMIN(hdr_width, 160));
|
||||
|
||||
if (!(s->avctx->flags & CODEC_FLAG_GRAY))
|
||||
{
|
||||
|
||||
buf_pos = buf + 16 + offs2;
|
||||
offs = le2me_32(*(uint32_t *)buf_pos);
|
||||
buf_pos += 4;
|
||||
offs = bytestream_get_le32(&buf_pos);
|
||||
|
||||
iv_Decode_Chunk(s, s->cur_frame->Vbuf, s->ref_frame->Vbuf, chroma_width,
|
||||
chroma_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
|
||||
min(chroma_width, 40));
|
||||
iv_Decode_Chunk(s, s->cur_frame->Vbuf, s->ref_frame->Vbuf, chroma_width,
|
||||
chroma_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
|
||||
FFMIN(chroma_width, 40));
|
||||
|
||||
buf_pos = buf + 16 + offs3;
|
||||
offs = le2me_32(*(uint32_t *)buf_pos);
|
||||
buf_pos += 4;
|
||||
offs = bytestream_get_le32(&buf_pos);
|
||||
|
||||
iv_Decode_Chunk(s, s->cur_frame->Ubuf, s->ref_frame->Ubuf, chroma_width,
|
||||
chroma_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
|
||||
min(chroma_width, 40));
|
||||
iv_Decode_Chunk(s, s->cur_frame->Ubuf, s->ref_frame->Ubuf, chroma_width,
|
||||
chroma_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
|
||||
FFMIN(chroma_width, 40));
|
||||
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
@@ -297,14 +297,14 @@ typedef struct {
|
||||
lp2 = 4;
|
||||
|
||||
static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
unsigned char *cur, unsigned char *ref, int width, int height,
|
||||
unsigned char *buf1, long fflags2, unsigned char *hdr,
|
||||
unsigned char *buf2, int min_width_160)
|
||||
unsigned char *cur, unsigned char *ref, int width, int height,
|
||||
const unsigned char *buf1, long fflags2, const unsigned char *hdr,
|
||||
const unsigned char *buf2, int min_width_160)
|
||||
{
|
||||
unsigned char bit_buf;
|
||||
unsigned long bit_pos, lv, lv1, lv2;
|
||||
long *width_tbl, width_tbl_arr[10];
|
||||
char *ref_vectors;
|
||||
const signed char *ref_vectors;
|
||||
unsigned char *cur_frm_pos, *ref_frm_pos, *cp, *cp2;
|
||||
uint32_t *cur_lp, *ref_lp;
|
||||
const uint32_t *correction_lp[2], *correctionloworder_lp[2], *correctionhighorder_lp[2];
|
||||
@@ -312,13 +312,14 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
ustr_t strip_tbl[20], *strip;
|
||||
int i, j, k, lp1, lp2, flag1, cmd, blks_width, blks_height, region_160_width,
|
||||
rle_v1, rle_v2, rle_v3;
|
||||
unsigned short res;
|
||||
|
||||
bit_buf = 0;
|
||||
ref_vectors = NULL;
|
||||
|
||||
width_tbl = width_tbl_arr + 1;
|
||||
i = (width < 0 ? width + 3 : width)/4;
|
||||
for(j = -1; j < 8; j++)
|
||||
for(j = -1; j < 8; j++)
|
||||
width_tbl[j] = i * j;
|
||||
|
||||
strip = strip_tbl;
|
||||
@@ -368,7 +369,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
} else if(cmd == 3) {
|
||||
if(strip->usl7 == 0) {
|
||||
strip->usl7 = 1;
|
||||
ref_vectors = buf2 + (*buf1 * 2);
|
||||
ref_vectors = (const signed char*)buf2 + (*buf1 * 2);
|
||||
buf1++;
|
||||
continue;
|
||||
}
|
||||
@@ -376,7 +377,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
cur_frm_pos = cur + width * strip->ypos + strip->xpos;
|
||||
|
||||
if((blks_width = strip->width) < 0)
|
||||
if((blks_width = strip->width) < 0)
|
||||
blks_width += 3;
|
||||
blks_width >>= 2;
|
||||
blks_height = strip->height;
|
||||
@@ -384,7 +385,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
if(ref_vectors != NULL) {
|
||||
ref_frm_pos = ref + (ref_vectors[0] + strip->ypos) * width +
|
||||
ref_vectors[1] + strip->xpos;
|
||||
} else
|
||||
} else
|
||||
ref_frm_pos = cur_frm_pos - width_tbl[4];
|
||||
|
||||
if(cmd == 2) {
|
||||
@@ -403,7 +404,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
cur_frm_pos += 4;
|
||||
ref_frm_pos += 4;
|
||||
}
|
||||
} else if(cmd != 1)
|
||||
} else if(cmd != 1)
|
||||
return;
|
||||
} else {
|
||||
k = *buf1 >> 4;
|
||||
@@ -414,9 +415,9 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
if((lv - 8) <= 7 && (k == 0 || k == 3 || k == 10)) {
|
||||
cp2 = s->ModPred + ((lv - 8) << 7);
|
||||
cp = ref_frm_pos;
|
||||
for(i = 0; i < blks_width << 2; i++) {
|
||||
for(i = 0; i < blks_width << 2; i++) {
|
||||
int v = *cp >> 1;
|
||||
*(cp++) = cp2[v];
|
||||
*(cp++) = cp2[v];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,14 +447,15 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
switch(correction_type_sp[0][k]) {
|
||||
case 0:
|
||||
*cur_lp = ((*ref_lp >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
*cur_lp = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
|
||||
lp2++;
|
||||
break;
|
||||
case 1:
|
||||
((unsigned short *)cur_lp)[0] = ((((unsigned short *)(ref_lp))[0] >> 1)
|
||||
+ correction_lp[lp2 & 0x01][*buf1++]) << 1;
|
||||
((unsigned short *)cur_lp)[1] = ((((unsigned short *)(ref_lp))[1] >> 1)
|
||||
+ correction_lp[lp2 & 0x01][k]) << 1;
|
||||
res = ((le2me_16(((unsigned short *)(ref_lp))[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
|
||||
((unsigned short *)cur_lp)[0] = le2me_16(res);
|
||||
res = ((le2me_16(((unsigned short *)(ref_lp))[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
((unsigned short *)cur_lp)[1] = le2me_16(res);
|
||||
buf1++;
|
||||
lp2++;
|
||||
break;
|
||||
case 2:
|
||||
@@ -494,7 +496,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if(rle_v3 != 0)
|
||||
if(rle_v3 != 0)
|
||||
rle_v3 = 0;
|
||||
else {
|
||||
buf1--;
|
||||
@@ -518,7 +520,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
LV1_CHECK(buf1,rle_v3,lv1,lp2)
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -534,7 +536,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
case 4:
|
||||
case 3: /********** CASE 3 **********/
|
||||
if(ref_vectors != NULL)
|
||||
if(ref_vectors != NULL)
|
||||
return;
|
||||
flag1 = 1;
|
||||
|
||||
@@ -548,23 +550,25 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
switch(correction_type_sp[lp2 & 0x01][k]) {
|
||||
case 0:
|
||||
cur_lp[width_tbl[1]] = ((*ref_lp >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[width_tbl[1]] = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
|
||||
if(lp2 > 0 || flag1 == 0 || strip->ypos != 0)
|
||||
cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
|
||||
else
|
||||
cur_lp[0] = ((*ref_lp >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[0] = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
((unsigned short *)cur_lp)[width_tbl[2]] =
|
||||
((((unsigned short *)ref_lp)[0] >> 1) + correction_lp[lp2 & 0x01][*buf1++]) << 1;
|
||||
((unsigned short *)cur_lp)[width_tbl[2]+1] =
|
||||
((((unsigned short *)ref_lp)[1] >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
res = ((le2me_16(((unsigned short *)ref_lp)[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
|
||||
((unsigned short *)cur_lp)[width_tbl[2]] = le2me_16(res);
|
||||
res = ((le2me_16(((unsigned short *)ref_lp)[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
((unsigned short *)cur_lp)[width_tbl[2]+1] = le2me_16(res);
|
||||
|
||||
if(lp2 > 0 || flag1 == 0 || strip->ypos != 0)
|
||||
cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
|
||||
else
|
||||
cur_lp[0] = cur_lp[width_tbl[1]];
|
||||
buf1++;
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
@@ -589,7 +593,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if(rle_v3 != 0)
|
||||
if(rle_v3 != 0)
|
||||
rle_v3 = 0;
|
||||
else {
|
||||
buf1--;
|
||||
@@ -634,7 +638,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
LV1_CHECK(buf1,rle_v3,lv1,lp2)
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -660,16 +664,23 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
lv1 = ref_lp[0];
|
||||
lv2 = ref_lp[1];
|
||||
if(lp2 == 0 && flag1 != 0) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
lv1 = lv1 & 0xFF00FF00;
|
||||
lv1 = (lv1 >> 8) | lv1;
|
||||
lv2 = lv2 & 0xFF00FF00;
|
||||
lv2 = (lv2 >> 8) | lv2;
|
||||
#else
|
||||
lv1 = lv1 & 0x00FF00FF;
|
||||
lv1 = (lv1 << 8) | lv1;
|
||||
lv2 = lv2 & 0x00FF00FF;
|
||||
lv2 = (lv2 << 8) | lv2;
|
||||
#endif
|
||||
}
|
||||
|
||||
switch(correction_type_sp[lp2 & 0x01][k]) {
|
||||
case 0:
|
||||
cur_lp[width_tbl[1]] = ((lv1 >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[width_tbl[1]+1] = ((lv2 >> 1) + correctionhighorder_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[width_tbl[1]] = le2me_32(((le2me_32(lv1) >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1);
|
||||
cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(lv2) >> 1) + correctionhighorder_lp[lp2 & 0x01][k]) << 1);
|
||||
if(lp2 > 0 || strip->ypos != 0 || flag1 == 0) {
|
||||
cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
|
||||
cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
|
||||
@@ -681,8 +692,8 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cur_lp[width_tbl[1]] = ((lv1 >> 1) + correctionloworder_lp[lp2 & 0x01][*buf1++]) << 1;
|
||||
cur_lp[width_tbl[1]+1] = ((lv2 >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[width_tbl[1]] = le2me_32(((le2me_32(lv1) >> 1) + correctionloworder_lp[lp2 & 0x01][*buf1]) << 1);
|
||||
cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(lv2) >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1);
|
||||
if(lp2 > 0 || strip->ypos != 0 || flag1 == 0) {
|
||||
cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
|
||||
cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
|
||||
@@ -690,6 +701,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
cur_lp[0] = cur_lp[width_tbl[1]];
|
||||
cur_lp[1] = cur_lp[width_tbl[1]+1];
|
||||
}
|
||||
buf1++;
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
@@ -780,7 +792,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
case 7:
|
||||
if(lp2 == 0) {
|
||||
if(rle_v3 != 0)
|
||||
if(rle_v3 != 0)
|
||||
rle_v3 = 0;
|
||||
else {
|
||||
buf1--;
|
||||
@@ -801,7 +813,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
LV1_CHECK(buf1,rle_v3,lv1,lp2)
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -824,20 +836,20 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
case 0:
|
||||
lv1 = correctionloworder_lp[lp2 & 0x01][k];
|
||||
lv2 = correctionhighorder_lp[lp2 & 0x01][k];
|
||||
cur_lp[0] = ((ref_lp[0] >> 1) + lv1) << 1;
|
||||
cur_lp[1] = ((ref_lp[1] >> 1) + lv2) << 1;
|
||||
cur_lp[width_tbl[1]] = ((ref_lp[width_tbl[1]] >> 1) + lv1) << 1;
|
||||
cur_lp[width_tbl[1]+1] = ((ref_lp[width_tbl[1]+1] >> 1) + lv2) << 1;
|
||||
cur_lp[0] = le2me_32(((le2me_32(ref_lp[0]) >> 1) + lv1) << 1);
|
||||
cur_lp[1] = le2me_32(((le2me_32(ref_lp[1]) >> 1) + lv2) << 1);
|
||||
cur_lp[width_tbl[1]] = le2me_32(((le2me_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
|
||||
cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lv1 = correctionloworder_lp[lp2 & 0x01][*buf1++];
|
||||
lv2 = correctionloworder_lp[lp2 & 0x01][k];
|
||||
cur_lp[0] = ((ref_lp[0] >> 1) + lv1) << 1;
|
||||
cur_lp[1] = ((ref_lp[1] >> 1) + lv2) << 1;
|
||||
cur_lp[width_tbl[1]] = ((ref_lp[width_tbl[1]] >> 1) + lv1) << 1;
|
||||
cur_lp[width_tbl[1]+1] = ((ref_lp[width_tbl[1]+1] >> 1) + lv2) << 1;
|
||||
cur_lp[0] = le2me_32(((le2me_32(ref_lp[0]) >> 1) + lv1) << 1);
|
||||
cur_lp[1] = le2me_32(((le2me_32(ref_lp[1]) >> 1) + lv2) << 1);
|
||||
cur_lp[width_tbl[1]] = le2me_32(((le2me_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
|
||||
cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
@@ -897,7 +909,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
LV1_CHECK(buf1,rle_v3,lv1,lp2)
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -913,7 +925,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
break;
|
||||
|
||||
case 11: /********** CASE 11 **********/
|
||||
if(ref_vectors == NULL)
|
||||
if(ref_vectors == NULL)
|
||||
return;
|
||||
|
||||
for( ; blks_height > 0; blks_height -= 8) {
|
||||
@@ -925,18 +937,22 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
|
||||
switch(correction_type_sp[lp2 & 0x01][k]) {
|
||||
case 0:
|
||||
cur_lp[0] = ((*ref_lp >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[width_tbl[1]] = ((ref_lp[width_tbl[1]] >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
|
||||
cur_lp[0] = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
|
||||
cur_lp[width_tbl[1]] = le2me_32(((le2me_32(ref_lp[width_tbl[1]]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lv1 = (unsigned short)(correction_lp[lp2 & 0x01][*buf1++]);
|
||||
lv2 = (unsigned short)(correction_lp[lp2 & 0x01][k]);
|
||||
((unsigned short *)cur_lp)[0] = ((((unsigned short *)ref_lp)[0] >> 1) + lv1) << 1;
|
||||
((unsigned short *)cur_lp)[1] = ((((unsigned short *)ref_lp)[1] >> 1) + lv2) << 1;
|
||||
((unsigned short *)cur_lp)[width_tbl[2]] = ((((unsigned short *)ref_lp)[width_tbl[2]] >> 1) + lv1) << 1;
|
||||
((unsigned short *)cur_lp)[width_tbl[2]+1] = ((((unsigned short *)ref_lp)[width_tbl[2]+1] >> 1) + lv2) << 1;
|
||||
res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[0]) >> 1) + lv1) << 1);
|
||||
((unsigned short *)cur_lp)[0] = le2me_16(res);
|
||||
res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[1]) >> 1) + lv2) << 1);
|
||||
((unsigned short *)cur_lp)[1] = le2me_16(res);
|
||||
res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[width_tbl[2]]) >> 1) + lv1) << 1);
|
||||
((unsigned short *)cur_lp)[width_tbl[2]] = le2me_16(res);
|
||||
res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[width_tbl[2]+1]) >> 1) + lv2) << 1);
|
||||
((unsigned short *)cur_lp)[width_tbl[2]+1] = le2me_16(res);
|
||||
lp2++;
|
||||
break;
|
||||
|
||||
@@ -990,7 +1006,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
LV1_CHECK(buf1,rle_v3,lv1,lp2)
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1004,12 +1020,12 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(strip < strip_tbl)
|
||||
if(strip < strip_tbl)
|
||||
return;
|
||||
|
||||
for( ; strip >= strip_tbl; strip--) {
|
||||
@@ -1032,7 +1048,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
|
||||
}
|
||||
}
|
||||
|
||||
static int indeo3_decode_init(AVCodecContext *avctx)
|
||||
static av_cold int indeo3_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
Indeo3DecodeContext *s = avctx->priv_data;
|
||||
|
||||
@@ -1040,7 +1056,6 @@ static int indeo3_decode_init(AVCodecContext *avctx)
|
||||
s->width = avctx->width;
|
||||
s->height = avctx->height;
|
||||
avctx->pix_fmt = PIX_FMT_YUV410P;
|
||||
avctx->has_b_frames = 0;
|
||||
|
||||
build_modpred(s);
|
||||
iv_alloc_frames(s);
|
||||
@@ -1050,7 +1065,7 @@ static int indeo3_decode_init(AVCodecContext *avctx)
|
||||
|
||||
static int indeo3_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
unsigned char *buf, int buf_size)
|
||||
const unsigned char *buf, int buf_size)
|
||||
{
|
||||
Indeo3DecodeContext *s=avctx->priv_data;
|
||||
unsigned char *src, *dest;
|
||||
@@ -1075,6 +1090,8 @@ static int indeo3_decode_frame(AVCodecContext *avctx,
|
||||
dest += s->frame.linesize[0];
|
||||
}
|
||||
|
||||
if (!(s->avctx->flags & CODEC_FLAG_GRAY))
|
||||
{
|
||||
src = s->cur_frame->Ubuf;
|
||||
dest = s->frame.data[1];
|
||||
for (y = 0; y < s->height / 4; y++) {
|
||||
@@ -1090,6 +1107,7 @@ static int indeo3_decode_frame(AVCodecContext *avctx,
|
||||
src += s->cur_frame->uv_w;
|
||||
dest += s->frame.linesize[2];
|
||||
}
|
||||
}
|
||||
|
||||
*data_size=sizeof(AVFrame);
|
||||
*(AVFrame*)data= s->frame;
|
||||
@@ -1097,7 +1115,7 @@ static int indeo3_decode_frame(AVCodecContext *avctx,
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int indeo3_decode_end(AVCodecContext *avctx)
|
||||
static av_cold int indeo3_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
Indeo3DecodeContext *s = avctx->priv_data;
|
||||
|
||||
@@ -1116,5 +1134,6 @@ AVCodec indeo3_decoder = {
|
||||
indeo3_decode_end,
|
||||
indeo3_decode_frame,
|
||||
0,
|
||||
NULL
|
||||
NULL,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"),
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,20 +2,21 @@
|
||||
* Interplay MVE Video Decoder
|
||||
* Copyright (C) 2003 the ffmpeg project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -38,8 +39,8 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
#define PALETTE_COUNT 256
|
||||
@@ -47,7 +48,7 @@
|
||||
/* debugging support */
|
||||
#define DEBUG_INTERPLAY 0
|
||||
#if DEBUG_INTERPLAY
|
||||
#define debug_interplay printf
|
||||
#define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__)
|
||||
#else
|
||||
static inline void debug_interplay(const char *format, ...) { }
|
||||
#endif
|
||||
@@ -59,14 +60,14 @@ typedef struct IpvideoContext {
|
||||
AVFrame second_last_frame;
|
||||
AVFrame last_frame;
|
||||
AVFrame current_frame;
|
||||
unsigned char *decoding_map;
|
||||
const unsigned char *decoding_map;
|
||||
int decoding_map_size;
|
||||
|
||||
unsigned char *buf;
|
||||
const unsigned char *buf;
|
||||
int size;
|
||||
|
||||
unsigned char *stream_ptr;
|
||||
unsigned char *stream_end;
|
||||
const unsigned char *stream_ptr;
|
||||
const unsigned char *stream_end;
|
||||
unsigned char *pixel_ptr;
|
||||
int line_inc;
|
||||
int stride;
|
||||
@@ -296,10 +297,8 @@ static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
|
||||
|
||||
/* need 2 more bytes from the stream */
|
||||
CHECK_STREAM_PTR(2);
|
||||
B[0] = *s->stream_ptr++;
|
||||
B[1] = *s->stream_ptr++;
|
||||
|
||||
flags = (B[1] << 8) | B[0];
|
||||
flags = bytestream_get_le16(&s->stream_ptr);
|
||||
bitmask = 0x0001;
|
||||
for (y = 0; y < 8; y += 2) {
|
||||
for (x = 0; x < 8; x += 2, bitmask <<= 1) {
|
||||
@@ -477,7 +476,6 @@ static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
|
||||
{
|
||||
int x, y;
|
||||
unsigned char P[4];
|
||||
unsigned char B[4];
|
||||
unsigned int flags = 0;
|
||||
int shifter = 0;
|
||||
unsigned char pix;
|
||||
@@ -495,8 +493,7 @@ static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
|
||||
|
||||
for (y = 0; y < 8; y++) {
|
||||
/* get the next set of 8 2-bit flags */
|
||||
flags = (s->stream_ptr[1] << 8) | s->stream_ptr[0];
|
||||
s->stream_ptr += 2;
|
||||
flags = bytestream_get_le16(&s->stream_ptr);
|
||||
for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
|
||||
*s->pixel_ptr++ = P[(flags >> shifter) & 0x03];
|
||||
}
|
||||
@@ -508,11 +505,7 @@ static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
|
||||
/* 1 of 4 colors for each 2x2 block, need 4 more bytes */
|
||||
CHECK_STREAM_PTR(4);
|
||||
|
||||
B[0] = *s->stream_ptr++;
|
||||
B[1] = *s->stream_ptr++;
|
||||
B[2] = *s->stream_ptr++;
|
||||
B[3] = *s->stream_ptr++;
|
||||
flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
|
||||
flags = bytestream_get_le32(&s->stream_ptr);
|
||||
shifter = 0;
|
||||
|
||||
for (y = 0; y < 8; y += 2) {
|
||||
@@ -534,11 +527,7 @@ static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
|
||||
for (y = 0; y < 8; y++) {
|
||||
/* time to reload flags? */
|
||||
if ((y == 0) || (y == 4)) {
|
||||
B[0] = *s->stream_ptr++;
|
||||
B[1] = *s->stream_ptr++;
|
||||
B[2] = *s->stream_ptr++;
|
||||
B[3] = *s->stream_ptr++;
|
||||
flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
|
||||
flags = bytestream_get_le32(&s->stream_ptr);
|
||||
shifter = 0;
|
||||
}
|
||||
for (x = 0; x < 8; x += 2, shifter += 2) {
|
||||
@@ -557,11 +546,7 @@ static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
|
||||
for (y = 0; y < 8; y += 2) {
|
||||
/* time to reload flags? */
|
||||
if ((y == 0) || (y == 4)) {
|
||||
B[0] = *s->stream_ptr++;
|
||||
B[1] = *s->stream_ptr++;
|
||||
B[2] = *s->stream_ptr++;
|
||||
B[3] = *s->stream_ptr++;
|
||||
flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
|
||||
flags = bytestream_get_le32(&s->stream_ptr);
|
||||
shifter = 0;
|
||||
}
|
||||
for (x = 0; x < 8; x++, shifter += 2) {
|
||||
@@ -819,7 +804,6 @@ static void ipvideo_decode_opcodes(IpvideoContext *s)
|
||||
s->line_inc = s->stride - 8;
|
||||
s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride
|
||||
+ s->avctx->width - 8;
|
||||
s->dsp = s->dsp;
|
||||
|
||||
for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) {
|
||||
for (x = y; x < y + s->avctx->width; x += 8) {
|
||||
@@ -846,12 +830,12 @@ static void ipvideo_decode_opcodes(IpvideoContext *s)
|
||||
}
|
||||
if ((s->stream_ptr != s->stream_end) &&
|
||||
(s->stream_ptr + 1 != s->stream_end)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %d bytes left over\n",
|
||||
av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
|
||||
s->stream_end - s->stream_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static int ipvideo_decode_init(AVCodecContext *avctx)
|
||||
static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
IpvideoContext *s = avctx->priv_data;
|
||||
|
||||
@@ -863,7 +847,6 @@ static int ipvideo_decode_init(AVCodecContext *avctx)
|
||||
}
|
||||
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
avctx->has_b_frames = 0;
|
||||
dsputil_init(&s->dsp, avctx);
|
||||
|
||||
/* decoding map contains 4 bits of information per 8x8 block */
|
||||
@@ -895,7 +878,7 @@ static int ipvideo_decode_init(AVCodecContext *avctx)
|
||||
|
||||
static int ipvideo_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
uint8_t *buf, int buf_size)
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
IpvideoContext *s = avctx->priv_data;
|
||||
AVPaletteControl *palette_control = avctx->palctrl;
|
||||
@@ -936,7 +919,7 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int ipvideo_decode_end(AVCodecContext *avctx)
|
||||
static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
IpvideoContext *s = avctx->priv_data;
|
||||
|
||||
@@ -959,4 +942,5 @@ AVCodec interplay_video_decoder = {
|
||||
ipvideo_decode_end,
|
||||
ipvideo_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Interplay MVE Video"),
|
||||
};
|
||||
|
||||
@@ -0,0 +1,764 @@
|
||||
/*
|
||||
* 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 intrax8.c
|
||||
* @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
#include "mpegvideo.h"
|
||||
#include "msmpeg4data.h"
|
||||
#include "intrax8huf.h"
|
||||
#include "intrax8.h"
|
||||
|
||||
#define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits)
|
||||
|
||||
#define DC_VLC_BITS 9
|
||||
#define AC_VLC_BITS 9
|
||||
#define OR_VLC_BITS 7
|
||||
|
||||
#define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS)
|
||||
#define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS)
|
||||
#define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS)
|
||||
|
||||
static VLC j_ac_vlc[2][2][8]; //[quant<13],[intra/inter],[select]
|
||||
static VLC j_dc_vlc[2][8]; //[quant], [select]
|
||||
static VLC j_orient_vlc[2][4]; //[quant], [select]
|
||||
|
||||
static void x8_vlc_init(){
|
||||
int i;
|
||||
|
||||
#define init_ac_vlc(dst,src) \
|
||||
init_vlc(&dst, \
|
||||
AC_VLC_BITS,77, \
|
||||
&src[1],4,2, \
|
||||
&src[0],4,2, \
|
||||
1)
|
||||
//set ac tables
|
||||
for(i=0;i<8;i++){
|
||||
init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] );
|
||||
init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] );
|
||||
init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] );
|
||||
init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] );
|
||||
}
|
||||
#undef init_ac_vlc
|
||||
|
||||
//set dc tables
|
||||
#define init_dc_vlc(dst,src) \
|
||||
init_vlc(&dst, \
|
||||
DC_VLC_BITS,34, \
|
||||
&src[1],4,2, \
|
||||
&src[0],4,2, \
|
||||
1);
|
||||
for(i=0;i<8;i++){
|
||||
init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]);
|
||||
init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]);
|
||||
}
|
||||
#undef init_dc_vlc
|
||||
|
||||
//set orient tables
|
||||
#define init_or_vlc(dst,src) \
|
||||
init_vlc(&dst, \
|
||||
OR_VLC_BITS,12, \
|
||||
&src[1],4,2, \
|
||||
&src[0],4,2, \
|
||||
1);
|
||||
for(i=0;i<2;i++){
|
||||
init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]);
|
||||
}
|
||||
for(i=0;i<4;i++){
|
||||
init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0])
|
||||
}
|
||||
}
|
||||
#undef init_or_vlc
|
||||
|
||||
static void x8_reset_vlc_tables(IntraX8Context * w){
|
||||
memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc));
|
||||
memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc));
|
||||
w->j_orient_vlc=NULL;
|
||||
}
|
||||
|
||||
static inline void x8_select_ac_table(IntraX8Context * const w , int mode){
|
||||
MpegEncContext * const s= w->s;
|
||||
int table_index;
|
||||
|
||||
assert(mode<4);
|
||||
|
||||
if( w->j_ac_vlc[mode] ) return;
|
||||
|
||||
table_index = get_bits(&s->gb, 3);
|
||||
w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables
|
||||
assert(w->j_ac_vlc[mode]);
|
||||
}
|
||||
|
||||
static inline int x8_get_orient_vlc(IntraX8Context * w){
|
||||
MpegEncContext * const s= w->s;
|
||||
int table_index;
|
||||
|
||||
if(!w->j_orient_vlc ){
|
||||
table_index = get_bits(&s->gb, 1+(w->quant<13) );
|
||||
w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index];
|
||||
}
|
||||
assert(w->j_orient_vlc);
|
||||
assert(w->j_orient_vlc->table);
|
||||
|
||||
return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD);
|
||||
}
|
||||
|
||||
#define extra_bits(eb) (eb)
|
||||
#define extra_run (0xFF<<8)
|
||||
#define extra_level (0x00<<8)
|
||||
#define run_offset(r) ((r)<<16)
|
||||
#define level_offset(l) ((l)<<24)
|
||||
static const uint32_t ac_decode_table[]={
|
||||
/*46*/ extra_bits(3) | extra_run | run_offset(16) | level_offset( 0),
|
||||
/*47*/ extra_bits(3) | extra_run | run_offset(24) | level_offset( 0),
|
||||
/*48*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1),
|
||||
/*49*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1),
|
||||
|
||||
/*50*/ extra_bits(5) | extra_run | run_offset(32) | level_offset( 0),
|
||||
/*51*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1),
|
||||
|
||||
/*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4),
|
||||
/*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8),
|
||||
/*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12),
|
||||
/*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16),
|
||||
/*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24),
|
||||
|
||||
/*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3),
|
||||
/*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7),
|
||||
|
||||
/*59*/ extra_bits(2) | extra_run | run_offset(16) | level_offset( 0),
|
||||
/*60*/ extra_bits(2) | extra_run | run_offset(20) | level_offset( 0),
|
||||
/*61*/ extra_bits(2) | extra_run | run_offset(24) | level_offset( 0),
|
||||
/*62*/ extra_bits(2) | extra_run | run_offset(28) | level_offset( 0),
|
||||
/*63*/ extra_bits(4) | extra_run | run_offset(32) | level_offset( 0),
|
||||
/*64*/ extra_bits(4) | extra_run | run_offset(48) | level_offset( 0),
|
||||
|
||||
/*65*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1),
|
||||
/*66*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1),
|
||||
/*67*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1),
|
||||
|
||||
/*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4),
|
||||
/*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8),
|
||||
/*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16),
|
||||
|
||||
/*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3),
|
||||
/*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7),
|
||||
};
|
||||
//extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits;
|
||||
#undef extra_bits
|
||||
#undef extra_run
|
||||
#undef extra_level
|
||||
#undef run_offset
|
||||
#undef level_offset
|
||||
|
||||
static void x8_get_ac_rlf(IntraX8Context * const w, const int mode,
|
||||
int * const run, int * const level, int * const final){
|
||||
MpegEncContext * const s= w->s;
|
||||
int i,e;
|
||||
|
||||
// x8_select_ac_table(w,mode);
|
||||
i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD);
|
||||
|
||||
if(i<46){ //[0-45]
|
||||
int t,l;
|
||||
if(i<0){
|
||||
(*level)=(*final)=//prevent 'may be used unilitialized'
|
||||
(*run)=64;//this would cause error exit in the ac loop
|
||||
return;
|
||||
}
|
||||
|
||||
(*final) = t = (i>22);
|
||||
i-=23*t;
|
||||
/*
|
||||
i== 0-15 r=0-15 l=0 ;r=i& %01111
|
||||
i==16-19 r=0-3 l=1 ;r=i& %00011
|
||||
i==20-21 r=0-1 l=2 ;r=i& %00001
|
||||
i==22 r=0 l=3 ;r=i& %00000
|
||||
l=lut_l[i/2]={0,0,0,0,0,0,0,0,1,1,2,3}[i>>1];// 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000
|
||||
t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */
|
||||
l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/
|
||||
t=(0x01030F>>(l<<3));
|
||||
|
||||
(*run) = i&t;
|
||||
(*level) = l;
|
||||
}else if(i<73){//[46-72]
|
||||
uint32_t sm;
|
||||
uint32_t mask;
|
||||
|
||||
i-=46;
|
||||
sm=ac_decode_table[i];
|
||||
|
||||
e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits
|
||||
mask=sm&0xff;sm>>=8; //1bit
|
||||
|
||||
(*run) =(sm&0xff) + (e&( mask));//6bits
|
||||
(*level)=(sm>>8) + (e&(~mask));//5bits
|
||||
(*final)=i>(58-46);
|
||||
}else if(i<75){//[73-74]
|
||||
static const uint8_t crazy_mix_runlevel[32]={
|
||||
0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63,
|
||||
0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83,
|
||||
0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64,
|
||||
0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84};
|
||||
|
||||
(*final)=!(i&1);
|
||||
e=get_bits(&s->gb,5);//get the extra bits
|
||||
(*run) =crazy_mix_runlevel[e]>>4;
|
||||
(*level)=crazy_mix_runlevel[e]&0x0F;
|
||||
}else{
|
||||
(*level)=get_bits( &s->gb, 7-3*(i&1));
|
||||
(*run) =get_bits( &s->gb, 6);
|
||||
(*final)=get_bits1(&s->gb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//static const uint8_t dc_extra_sbits[] ={0, 1,1, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7 };
|
||||
static const uint8_t dc_index_offset[] ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193};
|
||||
|
||||
static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){
|
||||
MpegEncContext * const s= w->s;
|
||||
int i,e,c;
|
||||
|
||||
assert(mode<3);
|
||||
if( !w->j_dc_vlc[mode] ) {
|
||||
int table_index;
|
||||
table_index = get_bits(&s->gb, 3);
|
||||
//4 modes, same table
|
||||
w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index];
|
||||
}
|
||||
assert(w->j_dc_vlc);
|
||||
assert(w->j_dc_vlc[mode]->table);
|
||||
|
||||
i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD);
|
||||
|
||||
/*(i>=17) {i-=17;final=1;}*/
|
||||
c= i>16;
|
||||
(*final)=c;
|
||||
i-=17*c;
|
||||
|
||||
if(i<=0){
|
||||
(*level)=0;
|
||||
return -i;
|
||||
}
|
||||
c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[]
|
||||
c-=c>1;
|
||||
|
||||
e=get_bits(&s->gb,c);//get the extra bits
|
||||
i=dc_index_offset[i]+(e>>1);
|
||||
|
||||
e= -(e & 1);//0,0xffffff
|
||||
(*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1)
|
||||
return 0;
|
||||
}
|
||||
//end of huffman
|
||||
|
||||
static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){
|
||||
MpegEncContext * const s= w->s;
|
||||
int range;
|
||||
int sum;
|
||||
int quant;
|
||||
|
||||
s->dsp.x8_setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer,
|
||||
s->current_picture.linesize[chroma>0],
|
||||
&range, &sum, w->edges);
|
||||
if(chroma){
|
||||
w->orient=w->chroma_orient;
|
||||
quant=w->quant_dc_chroma;
|
||||
}else{
|
||||
quant=w->quant;
|
||||
}
|
||||
|
||||
w->flat_dc=0;
|
||||
if(range < quant || range < 3){
|
||||
w->orient=0;
|
||||
if(range < 3){//yep you read right, a +-1 idct error may break decoding!
|
||||
w->flat_dc=1;
|
||||
sum+=9;
|
||||
w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899
|
||||
}
|
||||
}
|
||||
if(chroma)
|
||||
return 0;
|
||||
|
||||
assert(w->orient < 3);
|
||||
if(range < 2*w->quant){
|
||||
if( (w->edges&3) == 0){
|
||||
if(w->orient==1) w->orient=11;
|
||||
if(w->orient==2) w->orient=10;
|
||||
}else{
|
||||
w->orient=0;
|
||||
}
|
||||
w->raw_orient=0;
|
||||
}else{
|
||||
static const uint8_t prediction_table[3][12]={
|
||||
{0,8,4, 10,11, 2,6,9,1,3,5,7},
|
||||
{4,0,8, 11,10, 3,5,2,6,9,1,7},
|
||||
{8,0,4, 10,11, 1,7,2,6,9,3,5}
|
||||
};
|
||||
w->raw_orient=x8_get_orient_vlc(w);
|
||||
if(w->raw_orient<0) return -1;
|
||||
assert(w->raw_orient < 12 );
|
||||
assert(w->orient<3);
|
||||
w->orient=prediction_table[w->orient][w->raw_orient];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){
|
||||
MpegEncContext * const s= w->s;
|
||||
|
||||
w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8);
|
||||
/*
|
||||
y=2n+0 ->//0 2 4
|
||||
y=2n+1 ->//1 3 5
|
||||
*/
|
||||
}
|
||||
static void x8_get_prediction_chroma(IntraX8Context * const w){
|
||||
MpegEncContext * const s= w->s;
|
||||
|
||||
w->edges = 1*( !(s->mb_x>>1) );
|
||||
w->edges|= 2*( !(s->mb_y>>1) );
|
||||
w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd
|
||||
|
||||
w->raw_orient=0;
|
||||
if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC
|
||||
w->chroma_orient=4<<((0xCC>>w->edges)&1);
|
||||
return;
|
||||
}
|
||||
w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)]
|
||||
}
|
||||
|
||||
static void x8_get_prediction(IntraX8Context * const w){
|
||||
MpegEncContext * const s= w->s;
|
||||
int a,b,c,i;
|
||||
|
||||
w->edges = 1*( !s->mb_x );
|
||||
w->edges|= 2*( !s->mb_y );
|
||||
w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );
|
||||
|
||||
switch(w->edges&3){
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
//take the one from the above block[0][y-1]
|
||||
w->est_run = w->prediction_table[!(s->mb_y&1)]>>2;
|
||||
w->orient = 1;
|
||||
return;
|
||||
case 2:
|
||||
//take the one from the previous block[x-1][0]
|
||||
w->est_run = w->prediction_table[2*s->mb_x-2]>>2;
|
||||
w->orient = 2;
|
||||
return;
|
||||
case 3:
|
||||
w->est_run = 16;
|
||||
w->orient = 0;
|
||||
return;
|
||||
}
|
||||
//no edge cases
|
||||
b= w->prediction_table[2*s->mb_x + !(s->mb_y&1) ];//block[x ][y-1]
|
||||
a= w->prediction_table[2*s->mb_x-2 + (s->mb_y&1) ];//block[x-1][y ]
|
||||
c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1]
|
||||
|
||||
w->est_run = FFMIN(b,a);
|
||||
/* This condition has nothing to do with w->edges, even if it looks
|
||||
similar it would trigger if e.g. x=3;y=2;
|
||||
I guess somebody wrote something wrong and it became standard. */
|
||||
if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run);
|
||||
w->est_run>>=2;
|
||||
|
||||
a&=3;
|
||||
b&=3;
|
||||
c&=3;
|
||||
|
||||
i=( 0xFFEAF4C4>>(2*b+8*a) )&3;
|
||||
if(i!=3) w->orient=i;
|
||||
else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3;
|
||||
/*
|
||||
lut1[b][a]={
|
||||
->{0, 1, 0, pad},
|
||||
{0, 1, X, pad},
|
||||
{2, 2, 2, pad}}
|
||||
pad 2 2 2; pad X 1 0; pad 0 1 0 <-
|
||||
-> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4
|
||||
|
||||
lut2[q>12][c]={
|
||||
->{0,2,1,pad},
|
||||
{2,2,2,pad}}
|
||||
pad 2 2 2; pad 1 2 0 <-
|
||||
-> 11 10'10 10 '11 01'10 00=>0xEAD8
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){
|
||||
MpegEncContext * const s= w->s;
|
||||
int t;
|
||||
#define B(x,y) s->block[0][s->dsp.idct_permutation[(x)+(y)*8]]
|
||||
#define T(x) ((x) * dc_level + 0x8000) >> 16;
|
||||
switch(direction){
|
||||
case 0:
|
||||
t = T(3811);//h
|
||||
B(1,0) -= t;
|
||||
B(0,1) -= t;
|
||||
|
||||
t = T(487);//e
|
||||
B(2,0) -= t;
|
||||
B(0,2) -= t;
|
||||
|
||||
t = T(506);//f
|
||||
B(3,0) -= t;
|
||||
B(0,3) -= t;
|
||||
|
||||
t = T(135);//c
|
||||
B(4,0) -= t;
|
||||
B(0,4) -= t;
|
||||
B(2,1) += t;
|
||||
B(1,2) += t;
|
||||
B(3,1) += t;
|
||||
B(1,3) += t;
|
||||
|
||||
t = T(173);//d
|
||||
B(5,0) -= t;
|
||||
B(0,5) -= t;
|
||||
|
||||
t = T(61);//b
|
||||
B(6,0) -= t;
|
||||
B(0,6) -= t;
|
||||
B(5,1) += t;
|
||||
B(1,5) += t;
|
||||
|
||||
t = T(42); //a
|
||||
B(7,0) -= t;
|
||||
B(0,7) -= t;
|
||||
B(4,1) += t;
|
||||
B(1,4) += t;
|
||||
B(4,4) += t;
|
||||
|
||||
t = T(1084);//g
|
||||
B(1,1) += t;
|
||||
|
||||
s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8);
|
||||
break;
|
||||
case 1:
|
||||
B(0,1) -= T(6269);
|
||||
B(0,3) -= T( 708);
|
||||
B(0,5) -= T( 172);
|
||||
B(0,7) -= T( 73);
|
||||
|
||||
s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8);
|
||||
break;
|
||||
case 2:
|
||||
B(1,0) -= T(6269);
|
||||
B(3,0) -= T( 708);
|
||||
B(5,0) -= T( 172);
|
||||
B(7,0) -= T( 73);
|
||||
|
||||
s->block_last_index[0] = FFMAX(s->block_last_index[0], 7);
|
||||
break;
|
||||
}
|
||||
#undef B
|
||||
#undef T
|
||||
}
|
||||
|
||||
static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){
|
||||
int k;
|
||||
for(k=0;k<8;k++){
|
||||
memset(dst,pix,8);
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
|
||||
static const int16_t quant_table[64] = {
|
||||
256, 256, 256, 256, 256, 256, 259, 262,
|
||||
265, 269, 272, 275, 278, 282, 285, 288,
|
||||
292, 295, 299, 303, 306, 310, 314, 317,
|
||||
321, 325, 329, 333, 337, 341, 345, 349,
|
||||
353, 358, 362, 366, 371, 375, 379, 384,
|
||||
389, 393, 398, 403, 408, 413, 417, 422,
|
||||
428, 433, 438, 443, 448, 454, 459, 465,
|
||||
470, 476, 482, 488, 493, 499, 505, 511
|
||||
};
|
||||
|
||||
static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){
|
||||
MpegEncContext * const s= w->s;
|
||||
|
||||
uint8_t * scantable;
|
||||
int final,run,level;
|
||||
int ac_mode,dc_mode,est_run,dc_level;
|
||||
int pos,n;
|
||||
int zeros_only;
|
||||
int use_quant_matrix;
|
||||
int sign;
|
||||
|
||||
assert(w->orient<12);
|
||||
memset(s->block[0],0x00,64*sizeof(DCTELEM));
|
||||
|
||||
if(chroma){
|
||||
dc_mode=2;
|
||||
}else{
|
||||
dc_mode=!!w->est_run;//0,1
|
||||
}
|
||||
|
||||
if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1;
|
||||
n=0;
|
||||
zeros_only=0;
|
||||
if(!final){//decode ac
|
||||
use_quant_matrix=w->use_quant_matrix;
|
||||
if(chroma){
|
||||
ac_mode = 1;
|
||||
est_run = 64;//not used
|
||||
}else{
|
||||
if (w->raw_orient < 3){
|
||||
use_quant_matrix = 0;
|
||||
}
|
||||
if(w->raw_orient > 4){
|
||||
ac_mode = 0;
|
||||
est_run = 64;
|
||||
}else{
|
||||
if(w->est_run > 1){
|
||||
ac_mode = 2;
|
||||
est_run=w->est_run;
|
||||
}else{
|
||||
ac_mode = 3;
|
||||
est_run = 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
x8_select_ac_table(w,ac_mode);
|
||||
/*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<-
|
||||
-> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */
|
||||
scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated;
|
||||
pos=0;
|
||||
do {
|
||||
n++;
|
||||
if( n >= est_run ){
|
||||
ac_mode=3;
|
||||
x8_select_ac_table(w,3);
|
||||
}
|
||||
|
||||
x8_get_ac_rlf(w,ac_mode,&run,&level,&final);
|
||||
|
||||
pos+=run+1;
|
||||
if(pos>63){
|
||||
//this also handles vlc error in x8_get_ac_rlf
|
||||
return -1;
|
||||
}
|
||||
level= (level+1) * w->dquant;
|
||||
level+= w->qsum;
|
||||
|
||||
sign = - get_bits1(&s->gb);
|
||||
level = (level ^ sign) - sign;
|
||||
|
||||
if(use_quant_matrix){
|
||||
level = (level*quant_table[pos])>>8;
|
||||
}
|
||||
s->block[0][ scantable[pos] ]=level;
|
||||
}while(!final);
|
||||
|
||||
s->block_last_index[0]=pos;
|
||||
}else{//DC only
|
||||
s->block_last_index[0]=0;
|
||||
if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1]
|
||||
int32_t divide_quant= !chroma ? w->divide_quant_dc_luma:
|
||||
w->divide_quant_dc_chroma;
|
||||
int32_t dc_quant = !chroma ? w->quant:
|
||||
w->quant_dc_chroma;
|
||||
|
||||
//original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding
|
||||
dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13;
|
||||
|
||||
dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3),
|
||||
s->dest[chroma], s->current_picture.linesize[!!chroma]);
|
||||
|
||||
goto block_placed;
|
||||
}
|
||||
zeros_only = (dc_level == 0);
|
||||
}
|
||||
if(!chroma){
|
||||
s->block[0][0] = dc_level*w->quant;
|
||||
}else{
|
||||
s->block[0][0] = dc_level*w->quant_dc_chroma;
|
||||
}
|
||||
|
||||
//there is !zero_only check in the original, but dc_level check is enough
|
||||
if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){
|
||||
int direction;
|
||||
/*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<-
|
||||
-> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */
|
||||
direction= (0x6A017C>>(w->orient*2))&3;
|
||||
if (direction != 3){
|
||||
x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[]
|
||||
}
|
||||
}
|
||||
|
||||
if(w->flat_dc){
|
||||
dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.linesize[!!chroma]);
|
||||
}else{
|
||||
s->dsp.x8_spatial_compensation[w->orient]( s->edge_emu_buffer,
|
||||
s->dest[chroma],
|
||||
s->current_picture.linesize[!!chroma] );
|
||||
}
|
||||
if(!zeros_only)
|
||||
s->dsp.idct_add ( s->dest[chroma],
|
||||
s->current_picture.linesize[!!chroma],
|
||||
s->block[0] );
|
||||
|
||||
block_placed:
|
||||
|
||||
if(!chroma){
|
||||
x8_update_predictions(w,w->orient,n);
|
||||
}
|
||||
|
||||
if(s->loop_filter){
|
||||
uint8_t* ptr = s->dest[chroma];
|
||||
int linesize = s->current_picture.linesize[!!chroma];
|
||||
|
||||
if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){
|
||||
s->dsp.x8_h_loop_filter(ptr, linesize, w->quant);
|
||||
}
|
||||
if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){
|
||||
s->dsp.x8_v_loop_filter(ptr, linesize, w->quant);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_*
|
||||
//not s->linesize as this would be wrong for field pics
|
||||
//not that IntraX8 has interlacing support ;)
|
||||
const int linesize = s->current_picture.linesize[0];
|
||||
const int uvlinesize= s->current_picture.linesize[1];
|
||||
|
||||
s->dest[0] = s->current_picture.data[0];
|
||||
s->dest[1] = s->current_picture.data[1];
|
||||
s->dest[2] = s->current_picture.data[2];
|
||||
|
||||
s->dest[0] += s->mb_y * linesize << 3;
|
||||
s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows
|
||||
s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize IntraX8 frame decoder.
|
||||
* Requires valid MpegEncContext with valid s->mb_width before calling.
|
||||
* @param w pointer to IntraX8Context
|
||||
* @param s pointer to MpegEncContext of the parent codec
|
||||
*/
|
||||
void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){
|
||||
|
||||
w->s=s;
|
||||
x8_vlc_init();
|
||||
assert(s->mb_width>0);
|
||||
w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb
|
||||
|
||||
ff_init_scantable(s->dsp.idct_permutation, &w->scantable[0], wmv1_scantable[0]);
|
||||
ff_init_scantable(s->dsp.idct_permutation, &w->scantable[1], wmv1_scantable[2]);
|
||||
ff_init_scantable(s->dsp.idct_permutation, &w->scantable[2], wmv1_scantable[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy IntraX8 frame structure.
|
||||
* @param w pointer to IntraX8Context
|
||||
*/
|
||||
void ff_intrax8_common_end(IntraX8Context * w)
|
||||
{
|
||||
av_freep(&w->prediction_table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode single IntraX8 frame.
|
||||
* The parent codec must fill s->loopfilter and s->gb (bitstream).
|
||||
* The parent codec must call MPV_frame_start(), ff_er_frame_start() before calling this function.
|
||||
* The parent codec must call ff_er_frame_end(), MPV_frame_end() after calling this function.
|
||||
* This function does not use MPV_decode_mb().
|
||||
* lowres decoding is theoretically impossible.
|
||||
* @param w pointer to IntraX8Context
|
||||
* @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1.
|
||||
* @param quant_offset offset away from zero
|
||||
*/
|
||||
//FIXME extern uint8_t wmv3_dc_scale_table[32];
|
||||
int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){
|
||||
MpegEncContext * const s= w->s;
|
||||
int mb_xy;
|
||||
assert(s);
|
||||
w->use_quant_matrix = get_bits1(&s->gb);
|
||||
|
||||
w->dquant = dquant;
|
||||
w->quant = dquant >> 1;
|
||||
w->qsum = quant_offset;
|
||||
|
||||
w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant;
|
||||
if(w->quant < 5){
|
||||
w->quant_dc_chroma = w->quant;
|
||||
w->divide_quant_dc_chroma = w->divide_quant_dc_luma;
|
||||
}else{
|
||||
w->quant_dc_chroma = w->quant+((w->quant+3)>>3);
|
||||
w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma;
|
||||
}
|
||||
x8_reset_vlc_tables(w);
|
||||
|
||||
s->resync_mb_x=0;
|
||||
s->resync_mb_y=0;
|
||||
|
||||
for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){
|
||||
x8_init_block_index(s);
|
||||
mb_xy=(s->mb_y>>1)*s->mb_stride;
|
||||
|
||||
for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){
|
||||
x8_get_prediction(w);
|
||||
if(x8_setup_spatial_predictor(w,0)) goto error;
|
||||
if(x8_decode_intra_mb(w,0)) goto error;
|
||||
|
||||
if( s->mb_x & s->mb_y & 1 ){
|
||||
x8_get_prediction_chroma(w);
|
||||
|
||||
/*when setting up chroma, no vlc is read,
|
||||
so no error condition can be reached*/
|
||||
x8_setup_spatial_predictor(w,1);
|
||||
if(x8_decode_intra_mb(w,1)) goto error;
|
||||
|
||||
x8_setup_spatial_predictor(w,2);
|
||||
if(x8_decode_intra_mb(w,2)) goto error;
|
||||
|
||||
s->dest[1]+= 8;
|
||||
s->dest[2]+= 8;
|
||||
|
||||
/*emulate MB info in the relevant tables*/
|
||||
s->mbskip_table [mb_xy]=0;
|
||||
s->mbintra_table[mb_xy]=1;
|
||||
s->current_picture.qscale_table[mb_xy]=w->quant;
|
||||
mb_xy++;
|
||||
}
|
||||
s->dest[0]+= 8;
|
||||
}
|
||||
if(s->mb_y&1){
|
||||
ff_draw_horiz_band(s, (s->mb_y-1)*8, 16);
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y,
|
||||
(s->mb_x>>1)-1, (s->mb_y>>1)-1,
|
||||
(AC_END|DC_END|MV_END) );
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_INTRAX8_H
|
||||
#define FFMPEG_INTRAX8_H
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "mpegvideo.h"
|
||||
|
||||
typedef struct{
|
||||
VLC * j_ac_vlc[4];//they point to the static j_mb_vlc
|
||||
VLC * j_orient_vlc;
|
||||
VLC * j_dc_vlc[3];
|
||||
|
||||
int use_quant_matrix;
|
||||
//set by ff_intrax8_common_init
|
||||
uint8_t * prediction_table;//2*(mb_w*2)
|
||||
ScanTable scantable[3];
|
||||
//set by the caller codec
|
||||
MpegEncContext * s;
|
||||
int quant;
|
||||
int dquant;
|
||||
int qsum;
|
||||
//calculated per frame
|
||||
int quant_dc_chroma;
|
||||
int divide_quant_dc_luma;
|
||||
int divide_quant_dc_chroma;
|
||||
//changed per block
|
||||
int edges;
|
||||
int flat_dc;
|
||||
int predicted_dc;
|
||||
int raw_orient;
|
||||
int chroma_orient;
|
||||
int orient;
|
||||
int est_run;
|
||||
} IntraX8Context;
|
||||
|
||||
void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s);
|
||||
void ff_intrax8_common_end(IntraX8Context * w);
|
||||
int ff_intrax8_decode_picture(IntraX8Context * w, int quant, int halfpq);
|
||||
|
||||
#endif /* FFMPEG_INTRAX8_H */
|
||||
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* 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 intrax8dsp.c
|
||||
*@brief IntraX8 frame subdecoder image manipulation routines
|
||||
*/
|
||||
|
||||
#include "dsputil.h"
|
||||
|
||||
/*
|
||||
area positions, #3 is 1 pixel only, other are 8 pixels
|
||||
|66666666|
|
||||
3|44444444|55555555|
|
||||
- -+--------+--------+
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
1 2|XXXXXXXX|
|
||||
^-start
|
||||
*/
|
||||
|
||||
#define area1 (0)
|
||||
#define area2 (8)
|
||||
#define area3 (8+8)
|
||||
#define area4 (8+8+1)
|
||||
#define area5 (8+8+1+8)
|
||||
#define area6 (8+8+1+16)
|
||||
|
||||
/**
|
||||
Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
|
||||
|
||||
* @param src pointer to the beginning of the processed block
|
||||
* @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do.
|
||||
* @param linesize byte offset between 2 vertical pixels in the source image
|
||||
* @param range pointer to the variable where the edge pixel range is to be stored (max-min values)
|
||||
* @param psum pointer to the variable where the edge pixel sum is to be stored
|
||||
* @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels.
|
||||
and some of the edge pixels should be interpolated, the flag has the following meaning:
|
||||
1 - mb_x==0 - first block in the row, interpolate area #1,#2,#3;
|
||||
2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6;
|
||||
note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas;
|
||||
4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5;
|
||||
*/
|
||||
static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
|
||||
int * range, int * psum, int edges){
|
||||
uint8_t * ptr;
|
||||
int sum;
|
||||
int i;
|
||||
int min_pix,max_pix;
|
||||
uint8_t c;
|
||||
|
||||
if((edges&3)==3){
|
||||
*psum=0x80*(8+1+8+2);
|
||||
*range=0;
|
||||
memset(dst,0x80,16+1+16+8);
|
||||
//this triggers flat_dc for sure.
|
||||
//flat_dc avoids all (other) prediction modes, but requires dc_level decoding.
|
||||
return;
|
||||
}
|
||||
|
||||
min_pix=256;
|
||||
max_pix=-1;
|
||||
|
||||
sum=0;
|
||||
|
||||
if(!(edges&1)){//(mb_x!=0)//there is previous block on this row
|
||||
ptr=src-1;//left column, area 2
|
||||
for(i=7;i>=0;i--){
|
||||
c=*(ptr-1);//area1, same mb as area2, no need to check
|
||||
dst[area1+i]=c;
|
||||
c=*(ptr);
|
||||
|
||||
sum+=c;
|
||||
min_pix=FFMIN(min_pix,c);
|
||||
max_pix=FFMAX(max_pix,c);
|
||||
dst[area2+i]=c;
|
||||
|
||||
ptr+=linesize;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(edges&2)){ //(mb_y!=0)//there is row above
|
||||
ptr=src-linesize;//top line
|
||||
for(i=0;i<8;i++){
|
||||
c=*(ptr+i);
|
||||
sum+=c;
|
||||
min_pix=FFMIN(min_pix, c);
|
||||
max_pix=FFMAX(max_pix, c);
|
||||
}
|
||||
if(edges&4){//last block on the row?
|
||||
memset(dst+area5,c,8);//set with last pixel fr
|
||||
memcpy(dst+area4, ptr, 8);
|
||||
}else{
|
||||
memcpy(dst+area4, ptr, 16);//both area4 and 5
|
||||
}
|
||||
memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block
|
||||
}
|
||||
//now calculate the stuff we need
|
||||
if(edges&3){//mb_x==0 || mb_y==0){
|
||||
int avg=(sum+4)>>3;
|
||||
if(edges&1){ //(mb_x==0) {//implies mb_y!=0
|
||||
memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
|
||||
}else{//implies y==0 x!=0
|
||||
memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
|
||||
}
|
||||
sum+=avg*9;
|
||||
}else{
|
||||
uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column
|
||||
dst[area3]=c;
|
||||
sum+=c;
|
||||
//edge pixel is not part of min/max
|
||||
}
|
||||
(*range) = max_pix - min_pix;
|
||||
sum += *(dst+area5) + *(dst+area5+1);
|
||||
*psum = sum;
|
||||
}
|
||||
|
||||
|
||||
static const uint16_t zero_prediction_weights[64*2] = {
|
||||
640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72,
|
||||
480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97,
|
||||
354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132,
|
||||
257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180,
|
||||
198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231,
|
||||
161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288,
|
||||
122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390,
|
||||
110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499
|
||||
};
|
||||
|
||||
static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int i,j;
|
||||
int x,y;
|
||||
unsigned int p;//power divided by 2
|
||||
int a;
|
||||
uint16_t left_sum[2][8];
|
||||
uint16_t top_sum[2][8];
|
||||
memset(left_sum,0,2*8*sizeof(uint16_t));
|
||||
memset( top_sum,0,2*8*sizeof(uint16_t));
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
a=src[area2+7-i]<<4;
|
||||
for(j=0;j<8;j++){
|
||||
p=abs(i-j);
|
||||
left_sum[p&1][j]+= a>>(p>>1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
a=src[area4+i]<<4;
|
||||
for(j=0;j<8;j++){
|
||||
p=abs(i-j);
|
||||
top_sum[p&1][j]+= a>>(p>>1);
|
||||
}
|
||||
}
|
||||
for(;i<10;i++){
|
||||
a=src[area4+i]<<4;
|
||||
for(j=5;j<8;j++){
|
||||
p=abs(i-j);
|
||||
top_sum[p&1][j]+= a>>(p>>1);
|
||||
}
|
||||
}
|
||||
for(;i<12;i++){
|
||||
a=src[area4+i]<<4;
|
||||
for(j=7;j<8;j++){
|
||||
p=abs(i-j);
|
||||
top_sum[p&1][j]+= a>>(p>>1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
|
||||
left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
|
||||
}
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x] = (
|
||||
(uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
|
||||
(uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
|
||||
0x8000
|
||||
)>>16;
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=src[area4 +1+y+x];
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=src[area4 +((y+1)>>1)+x];
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
if(2*x-y<0){
|
||||
dst[x]=src[area2+9+2*x-y];
|
||||
}else{
|
||||
dst[x]=src[area4 +x-((y+1)>>1)];
|
||||
}
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=src[area3+x-y];
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
if(x-2*y>0){
|
||||
dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
|
||||
}else{
|
||||
dst[x]=src[area2+8-y +(x>>1)];
|
||||
}
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=src[area2+6-FFMIN(x+y,6)];
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
|
||||
int x,y;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
|
||||
}
|
||||
dst+=linesize;
|
||||
}
|
||||
}
|
||||
|
||||
static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
|
||||
int i,t;
|
||||
int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
|
||||
int ql=(quant+10)>>3;
|
||||
|
||||
for(i=0; i<8; i++,ptr+=b_stride){
|
||||
p0=ptr[-5*a_stride];
|
||||
p1=ptr[-4*a_stride];
|
||||
p2=ptr[-3*a_stride];
|
||||
p3=ptr[-2*a_stride];
|
||||
p4=ptr[-1*a_stride];
|
||||
p5=ptr[ 0 ];
|
||||
p6=ptr[ 1*a_stride];
|
||||
p7=ptr[ 2*a_stride];
|
||||
p8=ptr[ 3*a_stride];
|
||||
p9=ptr[ 4*a_stride];
|
||||
|
||||
t=
|
||||
(FFABS(p1-p2) <= ql) +
|
||||
(FFABS(p2-p3) <= ql) +
|
||||
(FFABS(p3-p4) <= ql) +
|
||||
(FFABS(p4-p5) <= ql);
|
||||
if(t>0){//You need at least 1 to be able to reach a total score of 6.
|
||||
t+=
|
||||
(FFABS(p5-p6) <= ql) +
|
||||
(FFABS(p6-p7) <= ql) +
|
||||
(FFABS(p7-p8) <= ql) +
|
||||
(FFABS(p8-p9) <= ql) +
|
||||
(FFABS(p0-p1) <= ql);
|
||||
if(t>=6){
|
||||
int min,max;
|
||||
|
||||
min=max=p1;
|
||||
min=FFMIN(min,p3); max=FFMAX(max,p3);
|
||||
min=FFMIN(min,p5); max=FFMAX(max,p5);
|
||||
min=FFMIN(min,p8); max=FFMAX(max,p8);
|
||||
if(max-min<2*quant){//early stop
|
||||
min=FFMIN(min,p2); max=FFMAX(max,p2);
|
||||
min=FFMIN(min,p4); max=FFMAX(max,p4);
|
||||
min=FFMIN(min,p6); max=FFMAX(max,p6);
|
||||
min=FFMIN(min,p7); max=FFMAX(max,p7);
|
||||
if(max-min<2*quant){
|
||||
ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
|
||||
ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
|
||||
ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
|
||||
ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
|
||||
continue;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
int x,x0,x1,x2;
|
||||
int m;
|
||||
|
||||
x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
|
||||
if(FFABS(x0) < quant){
|
||||
x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
|
||||
x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
|
||||
|
||||
x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
|
||||
m=p4-p5;
|
||||
|
||||
if( x > 0 && (m^x0) <0){
|
||||
int32_t sign;
|
||||
|
||||
sign=m>>31;
|
||||
m=(m^sign)-sign;//abs(m)
|
||||
m>>=1;
|
||||
|
||||
x=(5*x)>>3;
|
||||
|
||||
if(x>m) x=m;
|
||||
|
||||
x=(x^sign)-sign;
|
||||
|
||||
ptr[-1*a_stride] -= x;
|
||||
ptr[ 0] += x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
|
||||
x8_loop_filter(src, stride, 1, qscale);
|
||||
}
|
||||
|
||||
static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
|
||||
x8_loop_filter(src, 1, stride, qscale);
|
||||
}
|
||||
|
||||
void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
|
||||
dsp->x8_h_loop_filter=x8_h_loop_filter;
|
||||
dsp->x8_v_loop_filter=x8_v_loop_filter;
|
||||
dsp->x8_setup_spatial_compensation=x8_setup_spatial_compensation;
|
||||
dsp->x8_spatial_compensation[0]=spatial_compensation_0;
|
||||
dsp->x8_spatial_compensation[1]=spatial_compensation_1;
|
||||
dsp->x8_spatial_compensation[2]=spatial_compensation_2;
|
||||
dsp->x8_spatial_compensation[3]=spatial_compensation_3;
|
||||
dsp->x8_spatial_compensation[4]=spatial_compensation_4;
|
||||
dsp->x8_spatial_compensation[5]=spatial_compensation_5;
|
||||
dsp->x8_spatial_compensation[6]=spatial_compensation_6;
|
||||
dsp->x8_spatial_compensation[7]=spatial_compensation_7;
|
||||
dsp->x8_spatial_compensation[8]=spatial_compensation_8;
|
||||
dsp->x8_spatial_compensation[9]=spatial_compensation_9;
|
||||
dsp->x8_spatial_compensation[10]=spatial_compensation_10;
|
||||
dsp->x8_spatial_compensation[11]=spatial_compensation_11;
|
||||
}
|
||||
@@ -0,0 +1,918 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_INTRAX8HUF_H
|
||||
#define FFMPEG_INTRAX8HUF_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
static const uint16_t x8_orient_lowquant_table[4][12][2]={
|
||||
{//0
|
||||
{0x0000, 1}, {0x0004, 3}, {0x0005, 3}, {0x000C, 4},
|
||||
{0x000D, 4}, {0x0038, 6}, {0x001D, 5}, {0x0039, 6},
|
||||
{0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6},
|
||||
},{//1
|
||||
{0x0000, 5}, {0x0001, 5}, {0x0002, 5}, {0x0001, 2},
|
||||
{0x0002, 2}, {0x0002, 4}, {0x0003, 5}, {0x0006, 3},
|
||||
{0x0003, 4}, {0x000E, 4}, {0x001E, 5}, {0x001F, 5},
|
||||
},{//2
|
||||
{0x0000, 2}, {0x0001, 2}, {0x0004, 3}, {0x0005, 3},
|
||||
{0x0006, 3}, {0x0038, 6}, {0x0039, 6}, {0x001D, 5},
|
||||
{0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6},
|
||||
},{//3
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0001, 2},
|
||||
{0x0002, 2}, {0x0018, 5}, {0x0019, 5}, {0x000D, 4},
|
||||
{0x001C, 5}, {0x001D, 5}, {0x001E, 5}, {0x001F, 5},
|
||||
}
|
||||
};
|
||||
|
||||
static const uint16_t x8_orient_highquant_table[2][12][2]={
|
||||
{//0
|
||||
{0x0000, 2}, {0x0001, 2}, {0x0004, 3}, {0x0005, 3},
|
||||
{0x0006, 3}, {0x0038, 6}, {0x001D, 5}, {0x0039, 6},
|
||||
{0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6},
|
||||
},{//1
|
||||
{0x0000, 1}, {0x0002, 2}, {0x0006, 3}, {0x001C, 5},
|
||||
{0x001D, 5}, {0x0078, 7}, {0x003D, 6}, {0x0079, 7},
|
||||
{0x007C, 7}, {0x007D, 7}, {0x007E, 7}, {0x007F, 7},
|
||||
}
|
||||
};
|
||||
#define MAX_OR_VLC_BITS 7
|
||||
|
||||
|
||||
static const uint16_t x8_dc_lowquant_table[8][34][2]={
|
||||
{//0
|
||||
{0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0004, 5},
|
||||
{0x0005, 5}, {0x0006, 5}, {0x000E, 6}, {0x000F, 6},
|
||||
{0x0040, 8}, {0x0041, 8}, {0x0840, 13}, {0x0841, 13},
|
||||
{0x0842, 13}, {0x0843, 13}, {0x0844, 13}, {0x0845, 13},
|
||||
{0x0846, 13}, {0x0002, 2}, {0x0003, 2}, {0x0003, 3},
|
||||
{0x0005, 4}, {0x0009, 5}, {0x0011, 6}, {0x0043, 8},
|
||||
{0x0085, 9}, {0x0847, 13}, {0x0848, 13}, {0x0849, 13},
|
||||
{0x084A, 13}, {0x084B, 13}, {0x084C, 13}, {0x084D, 13},
|
||||
{0x084E, 13}, {0x084F, 13},
|
||||
},{//1
|
||||
{0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4},
|
||||
{0x0006, 4}, {0x0004, 3}, {0x0007, 4}, {0x0005, 3},
|
||||
{0x000C, 4}, {0x000D, 4}, {0x001C, 5}, {0x003A, 6},
|
||||
{0x01D8, 9}, {0x01D9, 9}, {0x1DA0, 13}, {0x1DA1, 13},
|
||||
{0x1DA2, 13}, {0x003C, 6}, {0x003D, 6}, {0x003E, 6},
|
||||
{0x0077, 7}, {0x01DB, 9}, {0x007E, 7}, {0x00FE, 8},
|
||||
{0x01FE, 9}, {0x1DA3, 13}, {0x1DA4, 13}, {0x1DA5, 13},
|
||||
{0x0ED3, 12}, {0x0ED4, 12}, {0x01FF, 9}, {0x0ED5, 12},
|
||||
{0x0ED6, 12}, {0x0ED7, 12},
|
||||
},{//2
|
||||
{0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4},
|
||||
{0x0006, 4}, {0x0007, 4}, {0x0008, 4}, {0x0009, 4},
|
||||
{0x0028, 6}, {0x0029, 6}, {0x0054, 7}, {0x0055, 7},
|
||||
{0x0AC0, 12}, {0x0AC1, 12}, {0x0AC2, 12}, {0x0AC3, 12},
|
||||
{0x0AC4, 12}, {0x000B, 4}, {0x0006, 3}, {0x000E, 4},
|
||||
{0x001E, 5}, {0x003E, 6}, {0x003F, 6}, {0x0057, 7},
|
||||
{0x00AD, 8}, {0x0AC5, 12}, {0x0AC6, 12}, {0x0AC7, 12},
|
||||
{0x0AC8, 12}, {0x0AC9, 12}, {0x0ACA, 12}, {0x0ACB, 12},
|
||||
{0x0566, 11}, {0x0567, 11},
|
||||
},{//3
|
||||
{0x0000, 4}, {0x0001, 2}, {0x0001, 3}, {0x0004, 3},
|
||||
{0x0005, 3}, {0x0006, 3}, {0x0001, 4}, {0x000E, 4},
|
||||
{0x003C, 6}, {0x003D, 6}, {0x007C, 7}, {0x00FA, 8},
|
||||
{0x3EC0, 14}, {0x3EC1, 14}, {0x3EC2, 14}, {0x3EC3, 14},
|
||||
{0x1F62, 13}, {0x01F7, 9}, {0x007E, 7}, {0x00FE, 8},
|
||||
{0x00FF, 8}, {0x1F63, 13}, {0x1F64, 13}, {0x1F65, 13},
|
||||
{0x1F66, 13}, {0x1F67, 13}, {0x1F68, 13}, {0x1F69, 13},
|
||||
{0x1F6A, 13}, {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13},
|
||||
{0x1F6E, 13}, {0x1F6F, 13},
|
||||
},{//4
|
||||
{0x0000, 7}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7},
|
||||
{0x0004, 7}, {0x0005, 7}, {0x0006, 7}, {0x0007, 7},
|
||||
{0x0008, 7}, {0x0009, 7}, {0x000A, 7}, {0x000B, 7},
|
||||
{0x000C, 7}, {0x000D, 7}, {0x000E, 7}, {0x000F, 7},
|
||||
{0x0010, 7}, {0x0001, 1}, {0x0001, 2}, {0x0011, 7},
|
||||
{0x0012, 7}, {0x0013, 7}, {0x0014, 7}, {0x0015, 7},
|
||||
{0x0016, 7}, {0x0017, 7}, {0x0018, 7}, {0x0019, 7},
|
||||
{0x001A, 7}, {0x001B, 7}, {0x001C, 7}, {0x001D, 7},
|
||||
{0x001E, 7}, {0x001F, 7},
|
||||
},{//5
|
||||
{0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0008, 6},
|
||||
{0x0009, 6}, {0x000A, 6}, {0x0016, 7}, {0x000C, 6},
|
||||
{0x0017, 7}, {0x000D, 6}, {0x0038, 8}, {0x001D, 7},
|
||||
{0x0039, 8}, {0x0780, 13}, {0x0781, 13}, {0x0782, 13},
|
||||
{0x0783, 13}, {0x0002, 3}, {0x0001, 1}, {0x0003, 3},
|
||||
{0x001F, 7}, {0x003D, 8}, {0x0079, 9}, {0x0784, 13},
|
||||
{0x0785, 13}, {0x0786, 13}, {0x0787, 13}, {0x0788, 13},
|
||||
{0x0789, 13}, {0x078A, 13}, {0x078B, 13}, {0x078C, 13},
|
||||
{0x078D, 13}, {0x03C7, 12},
|
||||
},{//6
|
||||
{0x0000, 4}, {0x0001, 2}, {0x0001, 3}, {0x0004, 3},
|
||||
{0x0001, 4}, {0x000A, 4}, {0x0016, 5}, {0x002E, 6},
|
||||
{0x005E, 7}, {0x005F, 7}, {0x00C0, 8}, {0x3040, 14},
|
||||
{0x3041, 14}, {0x0305, 10}, {0x0183, 9}, {0x3042, 14},
|
||||
{0x3043, 14}, {0x000D, 4}, {0x0007, 3}, {0x0019, 5},
|
||||
{0x0031, 6}, {0x00C2, 8}, {0x00C3, 8}, {0x3044, 14},
|
||||
{0x3045, 14}, {0x3046, 14}, {0x3047, 14}, {0x3048, 14},
|
||||
{0x3049, 14}, {0x304A, 14}, {0x304B, 14}, {0x304C, 14},
|
||||
{0x304D, 14}, {0x1827, 13},
|
||||
},{//7
|
||||
{0x0000, 6}, {0x0001, 6}, {0x0002, 6}, {0x0006, 7},
|
||||
{0x0007, 7}, {0x0004, 6}, {0x0005, 6}, {0x0006, 6},
|
||||
{0x000E, 7}, {0x001E, 8}, {0x001F, 8}, {0x0040, 9},
|
||||
{0x0082, 10}, {0x0830, 14}, {0x0831, 14}, {0x0832, 14},
|
||||
{0x0833, 14}, {0x0001, 1}, {0x0001, 2}, {0x0003, 4},
|
||||
{0x0005, 5}, {0x0009, 6}, {0x0011, 7}, {0x0021, 8},
|
||||
{0x0834, 14}, {0x0835, 14}, {0x0836, 14}, {0x0837, 14},
|
||||
{0x0838, 14}, {0x0839, 14}, {0x083A, 14}, {0x083B, 14},
|
||||
{0x041E, 13}, {0x041F, 13},
|
||||
}
|
||||
};
|
||||
|
||||
static const uint16_t x8_dc_highquant_table[8][34][2]={
|
||||
{//0
|
||||
{0x0000, 5}, {0x0001, 4}, {0x0002, 4}, {0x0001, 5},
|
||||
{0x0006, 5}, {0x0004, 4}, {0x0007, 5}, {0x000A, 5},
|
||||
{0x002C, 7}, {0x002D, 7}, {0x05C0, 12}, {0x05C1, 12},
|
||||
{0x05C2, 12}, {0x05C3, 12}, {0x05C4, 12}, {0x05C5, 12},
|
||||
{0x05C6, 12}, {0x0003, 3}, {0x0002, 2}, {0x0006, 3},
|
||||
{0x000E, 4}, {0x001E, 5}, {0x001F, 5}, {0x002F, 7},
|
||||
{0x005D, 8}, {0x05C7, 12}, {0x05C8, 12}, {0x05C9, 12},
|
||||
{0x05CA, 12}, {0x05CB, 12}, {0x05CC, 12}, {0x05CD, 12},
|
||||
{0x05CE, 12}, {0x05CF, 12},
|
||||
},{//1
|
||||
{0x0000, 3}, {0x0001, 3}, {0x0002, 3}, {0x0006, 4},
|
||||
{0x0007, 4}, {0x0004, 3}, {0x000A, 4}, {0x000B, 4},
|
||||
{0x0030, 6}, {0x0062, 7}, {0x0063, 7}, {0x0640, 11},
|
||||
{0x0641, 11}, {0x0642, 11}, {0x0643, 11}, {0x0644, 11},
|
||||
{0x0645, 11}, {0x0033, 6}, {0x000D, 4}, {0x001C, 5},
|
||||
{0x001D, 5}, {0x003C, 6}, {0x001F, 5}, {0x0065, 7},
|
||||
{0x007A, 7}, {0x0646, 11}, {0x007B, 7}, {0x0647, 11},
|
||||
{0x0648, 11}, {0x0649, 11}, {0x064A, 11}, {0x064B, 11},
|
||||
{0x0326, 10}, {0x0327, 10},
|
||||
},{//2
|
||||
{0x0000, 7}, {0x0001, 7}, {0x0001, 6}, {0x0004, 7},
|
||||
{0x0003, 6}, {0x0005, 7}, {0x0010, 8}, {0x0011, 8},
|
||||
{0x0240, 13}, {0x0241, 13}, {0x0242, 13}, {0x0243, 13},
|
||||
{0x0244, 13}, {0x0245, 13}, {0x0246, 13}, {0x0247, 13},
|
||||
{0x0124, 12}, {0x0001, 1}, {0x0001, 2}, {0x0001, 3},
|
||||
{0x0003, 5}, {0x0005, 6}, {0x0013, 8}, {0x0125, 12},
|
||||
{0x0126, 12}, {0x0127, 12}, {0x0128, 12}, {0x0129, 12},
|
||||
{0x012A, 12}, {0x012B, 12}, {0x012C, 12}, {0x012D, 12},
|
||||
{0x012E, 12}, {0x012F, 12},
|
||||
},{//3
|
||||
{0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4},
|
||||
{0x0006, 4}, {0x0004, 3}, {0x0005, 3}, {0x0006, 3},
|
||||
{0x000E, 5}, {0x000F, 5}, {0x0070, 7}, {0x0710, 11},
|
||||
{0x0711, 11}, {0x0712, 11}, {0x0713, 11}, {0x0714, 11},
|
||||
{0x0715, 11}, {0x001D, 5}, {0x0072, 7}, {0x003C, 6},
|
||||
{0x003D, 6}, {0x0073, 7}, {0x007C, 7}, {0x007D, 7},
|
||||
{0x007E, 7}, {0x0716, 11}, {0x0717, 11}, {0x0718, 11},
|
||||
{0x007F, 7}, {0x0719, 11}, {0x071A, 11}, {0x071B, 11},
|
||||
{0x038E, 10}, {0x038F, 10},
|
||||
},{//4
|
||||
{0x0000, 8}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7},
|
||||
{0x0002, 9}, {0x0008, 8}, {0x0003, 9}, {0x0240, 14},
|
||||
{0x0241, 14}, {0x0242, 14}, {0x0243, 14}, {0x0244, 14},
|
||||
{0x0245, 14}, {0x0246, 14}, {0x0247, 14}, {0x0124, 13},
|
||||
{0x0125, 13}, {0x0001, 2}, {0x0001, 1}, {0x0001, 3},
|
||||
{0x0001, 4}, {0x0003, 6}, {0x0005, 7}, {0x0013, 9},
|
||||
{0x0126, 13}, {0x0127, 13}, {0x0128, 13}, {0x0129, 13},
|
||||
{0x012A, 13}, {0x012B, 13}, {0x012C, 13}, {0x012D, 13},
|
||||
{0x012E, 13}, {0x012F, 13},
|
||||
},{//5
|
||||
{0x0000, 7}, {0x0001, 7}, {0x0001, 6}, {0x0002, 6},
|
||||
{0x0003, 6}, {0x0004, 6}, {0x0005, 6}, {0x0006, 6},
|
||||
{0x0007, 6}, {0x0008, 6}, {0x0009, 6}, {0x000A, 6},
|
||||
{0x000B, 6}, {0x000C, 6}, {0x000D, 6}, {0x000E, 6},
|
||||
{0x000F, 6}, {0x0010, 6}, {0x0011, 6}, {0x0012, 6},
|
||||
{0x0013, 6}, {0x0014, 6}, {0x0015, 6}, {0x0016, 6},
|
||||
{0x0017, 6}, {0x0018, 6}, {0x0019, 6}, {0x0001, 1},
|
||||
{0x001A, 6}, {0x001B, 6}, {0x001C, 6}, {0x001D, 6},
|
||||
{0x001E, 6}, {0x001F, 6},
|
||||
},{//6
|
||||
{0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0004, 5},
|
||||
{0x000A, 6}, {0x0006, 5}, {0x000B, 6}, {0x000E, 6},
|
||||
{0x003C, 8}, {0x003D, 8}, {0x07C0, 13}, {0x07C1, 13},
|
||||
{0x07C2, 13}, {0x07C3, 13}, {0x07C4, 13}, {0x07C5, 13},
|
||||
{0x07C6, 13}, {0x0001, 2}, {0x0002, 2}, {0x0006, 3},
|
||||
{0x000E, 4}, {0x001E, 5}, {0x001F, 5}, {0x003F, 8},
|
||||
{0x007D, 9}, {0x07C7, 13}, {0x07C8, 13}, {0x07C9, 13},
|
||||
{0x07CA, 13}, {0x07CB, 13}, {0x07CC, 13}, {0x07CD, 13},
|
||||
{0x07CE, 13}, {0x07CF, 13},
|
||||
},{//7
|
||||
{0x0000, 7}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7},
|
||||
{0x0004, 7}, {0x0005, 7}, {0x0006, 7}, {0x0007, 7},
|
||||
{0x0008, 7}, {0x0009, 7}, {0x000A, 7}, {0x000B, 7},
|
||||
{0x000C, 7}, {0x000D, 7}, {0x000E, 7}, {0x000F, 7},
|
||||
{0x0010, 7}, {0x0001, 1}, {0x0001, 2}, {0x0011, 7},
|
||||
{0x0012, 7}, {0x0013, 7}, {0x0014, 7}, {0x0015, 7},
|
||||
{0x0016, 7}, {0x0017, 7}, {0x0018, 7}, {0x0019, 7},
|
||||
{0x001A, 7}, {0x001B, 7}, {0x001C, 7}, {0x001D, 7},
|
||||
{0x001E, 7}, {0x001F, 7},
|
||||
}
|
||||
};
|
||||
#define MAX_DC_VLC_BITS 14
|
||||
|
||||
|
||||
static const uint16_t x8_ac0_lowquant_table[8][77][2]={
|
||||
{//0
|
||||
{0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5},
|
||||
{0x001E, 6}, {0x003E, 7}, {0x003F, 7}, {0x0040, 7},
|
||||
{0x0104, 9}, {0x0083, 8}, {0x0084, 8}, {0x0085, 8},
|
||||
{0x020A, 10}, {0x020B, 10}, {0x0218, 10}, {0x0219, 10},
|
||||
{0x0009, 4}, {0x0044, 7}, {0x010D, 9}, {0x021C, 10},
|
||||
{0x0023, 6}, {0x0045, 7}, {0x0050, 7}, {0x000B, 4},
|
||||
{0x000C, 4}, {0x0015, 5}, {0x001A, 5}, {0x001B, 5},
|
||||
{0x0029, 6}, {0x0038, 6}, {0x0039, 6}, {0x003A, 6},
|
||||
{0x0051, 7}, {0x0076, 7}, {0x0077, 7}, {0x0078, 7},
|
||||
{0x0079, 7}, {0x007A, 7}, {0x007B, 7}, {0x00F8, 8},
|
||||
{0x010F, 9}, {0x021D, 10}, {0x3E40, 14}, {0x3E41, 14},
|
||||
{0x3E42, 14}, {0x3E43, 14}, {0x03E5, 10}, {0x3E44, 14},
|
||||
{0x01F3, 9}, {0x3E45, 14}, {0x3E46, 14}, {0x3E47, 14},
|
||||
{0x00FA, 8}, {0x3E48, 14}, {0x3E49, 14}, {0x3E4A, 14},
|
||||
{0x3E4B, 14}, {0x03EC, 10}, {0x3E4C, 14}, {0x007E, 7},
|
||||
{0x00FE, 8}, {0x00FF, 8}, {0x01F7, 9}, {0x3E4D, 14},
|
||||
{0x3E4E, 14}, {0x3E4F, 14}, {0x3ED0, 14}, {0x3ED1, 14},
|
||||
{0x3ED2, 14}, {0x3ED3, 14}, {0x3ED4, 14}, {0x3ED5, 14},
|
||||
{0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13}, {0x1F6E, 13},
|
||||
{0x1F6F, 13},
|
||||
},{//1
|
||||
{0x0000, 3}, {0x0004, 5}, {0x0014, 7}, {0x000B, 6},
|
||||
{0x000C, 6}, {0x002A, 8}, {0x002B, 8}, {0x0034, 8},
|
||||
{0x0D40, 14}, {0x0D41, 14}, {0x001B, 7}, {0x0D42, 14},
|
||||
{0x0D43, 14}, {0x0D44, 14}, {0x0D45, 14}, {0x0D46, 14},
|
||||
{0x000E, 6}, {0x003C, 8}, {0x0D47, 14}, {0x003D, 8},
|
||||
{0x0D48, 14}, {0x0D49, 14}, {0x0D4A, 14}, {0x0001, 2},
|
||||
{0x0004, 3}, {0x0014, 5}, {0x000B, 4}, {0x000C, 4},
|
||||
{0x000D, 4}, {0x002A, 6}, {0x001F, 7}, {0x0056, 7},
|
||||
{0x0057, 7}, {0x0070, 7}, {0x00E2, 8}, {0x0072, 7},
|
||||
{0x003A, 6}, {0x003B, 6}, {0x003C, 6}, {0x003D, 6},
|
||||
{0x00E3, 8}, {0x0D4B, 14}, {0x00E6, 8}, {0x00E7, 8},
|
||||
{0x00F8, 8}, {0x0D4C, 14}, {0x0D4D, 14}, {0x0D4E, 14},
|
||||
{0x00F9, 8}, {0x0D4F, 14}, {0x0D50, 14}, {0x0D51, 14},
|
||||
{0x06A9, 13}, {0x06AA, 13}, {0x06AB, 13}, {0x06AC, 13},
|
||||
{0x06AD, 13}, {0x06AE, 13}, {0x06AF, 13}, {0x003F, 6},
|
||||
{0x06B0, 13}, {0x06B1, 13}, {0x06B2, 13}, {0x06B3, 13},
|
||||
{0x06B4, 13}, {0x007D, 7}, {0x06B5, 13}, {0x06B6, 13},
|
||||
{0x06B7, 13}, {0x06B8, 13}, {0x06B9, 13}, {0x06BA, 13},
|
||||
{0x06BB, 13}, {0x06BC, 13}, {0x06BD, 13}, {0x06BE, 13},
|
||||
{0x06BF, 13},
|
||||
},{//2
|
||||
{0x0000, 2}, {0x0002, 3}, {0x0003, 3}, {0x0008, 4},
|
||||
{0x0012, 5}, {0x0013, 5}, {0x0028, 6}, {0x0029, 6},
|
||||
{0x0054, 7}, {0x0055, 7}, {0x0056, 7}, {0x00AE, 8},
|
||||
{0x00AF, 8}, {0x00B0, 8}, {0x0162, 9}, {0x02C6, 10},
|
||||
{0x000C, 4}, {0x002D, 6}, {0x00B2, 8}, {0x0166, 9},
|
||||
{0x002E, 6}, {0x0167, 9}, {0x00BC, 8}, {0x001A, 5},
|
||||
{0x0036, 6}, {0x0037, 6}, {0x0038, 6}, {0x005F, 7},
|
||||
{0x0072, 7}, {0x0073, 7}, {0x0074, 7}, {0x0075, 7},
|
||||
{0x0076, 7}, {0x0077, 7}, {0x0078, 7}, {0x0079, 7},
|
||||
{0x007A, 7}, {0x007B, 7}, {0x00BD, 8}, {0xB1C0, 16},
|
||||
{0xB1C1, 16}, {0x58E1, 15}, {0x0B1D, 12}, {0x58E2, 15},
|
||||
{0x58E3, 15}, {0x58E4, 15}, {0x00F8, 8}, {0x03E4, 10},
|
||||
{0x01F3, 9}, {0x0B1E, 12}, {0x58E5, 15}, {0x58E6, 15},
|
||||
{0x00FA, 8}, {0x58E7, 15}, {0x58F8, 15}, {0x58F9, 15},
|
||||
{0x58FA, 15}, {0x01F6, 9}, {0x58FB, 15}, {0x007E, 7},
|
||||
{0x00FE, 8}, {0x00FF, 8}, {0x07CA, 11}, {0x0F96, 12},
|
||||
{0x58FC, 15}, {0x58FD, 15}, {0x58FE, 15}, {0x58FF, 15},
|
||||
{0x7CB8, 15}, {0x7CB9, 15}, {0x7CBA, 15}, {0x7CBB, 15},
|
||||
{0x7CBC, 15}, {0x01F7, 9}, {0x7CBD, 15}, {0x7CBE, 15},
|
||||
{0x7CBF, 15},
|
||||
},{//3
|
||||
{0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5},
|
||||
{0x000F, 5}, {0x0020, 6}, {0x0021, 6}, {0x0044, 7},
|
||||
{0x0045, 7}, {0x008C, 8}, {0x008D, 8}, {0x011C, 9},
|
||||
{0x011D, 9}, {0x011E, 9}, {0x023E, 10}, {0x023F, 10},
|
||||
{0x0005, 3}, {0x0012, 5}, {0x004C, 7}, {0x004D, 7},
|
||||
{0x000C, 4}, {0x004E, 7}, {0x001A, 5}, {0x0036, 6},
|
||||
{0x004F, 7}, {0x006E, 7}, {0x006F, 7}, {0x00E0, 8},
|
||||
{0x00E1, 8}, {0x00E2, 8}, {0x00E3, 8}, {0x00E4, 8},
|
||||
{0x00E5, 8}, {0x01CC, 9}, {0x00E7, 8}, {0x00E8, 8},
|
||||
{0x00E9, 8}, {0x01CD, 9}, {0x0750, 11}, {0x03A9, 10},
|
||||
{0x0751, 11}, {0x7540, 15}, {0x03AB, 10}, {0x7541, 15},
|
||||
{0x7542, 15}, {0x7543, 15}, {0x01D6, 9}, {0x0755, 11},
|
||||
{0x0076, 7}, {0x0EA9, 12}, {0x7544, 15}, {0x7545, 15},
|
||||
{0x001E, 5}, {0x0077, 7}, {0x00F8, 8}, {0x03AE, 10},
|
||||
{0x075E, 11}, {0x007D, 7}, {0x03E4, 10}, {0x00FC, 8},
|
||||
{0x00FD, 8}, {0x03E5, 10}, {0x03E6, 10}, {0x0EBE, 12},
|
||||
{0x7546, 15}, {0x07CE, 11}, {0x7547, 15}, {0x75F8, 15},
|
||||
{0x75F9, 15}, {0x75FA, 15}, {0x75FB, 15}, {0x75FC, 15},
|
||||
{0x75FD, 15}, {0x007F, 7}, {0x3AFF, 14}, {0x0F9E, 12},
|
||||
{0x0F9F, 12},
|
||||
},{//4
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0012, 6}, {0x0013, 6}, {0x0014, 6}, {0x002A, 7},
|
||||
{0x0016, 6}, {0x002B, 7}, {0x005C, 8}, {0x005D, 8},
|
||||
{0x005E, 8}, {0x00BE, 9}, {0x00BF, 9}, {0x0060, 8},
|
||||
{0x0007, 4}, {0x000D, 5}, {0x0019, 6}, {0x0020, 6},
|
||||
{0x0009, 4}, {0x0021, 6}, {0x0011, 5}, {0x0014, 5},
|
||||
{0x002A, 6}, {0x002B, 6}, {0x002C, 6}, {0x002D, 6},
|
||||
{0x002E, 6}, {0x002F, 6}, {0x0030, 6}, {0x0031, 7},
|
||||
{0x0062, 7}, {0x0063, 7}, {0x0064, 7}, {0x0065, 7},
|
||||
{0x0066, 7}, {0x0061, 8}, {0x0670, 11}, {0x0068, 7},
|
||||
{0x0069, 7}, {0x00CF, 8}, {0x019D, 9}, {0x01A8, 9},
|
||||
{0x01A9, 9}, {0x0339, 10}, {0x01AA, 9}, {0x0356, 10},
|
||||
{0x0036, 6}, {0x00D6, 8}, {0x6710, 15}, {0x6711, 15},
|
||||
{0x000E, 4}, {0x006E, 7}, {0x01AE, 9}, {0x6712, 15},
|
||||
{0x6713, 15}, {0x003C, 6}, {0x0357, 10}, {0x006F, 7},
|
||||
{0x00F4, 8}, {0x00F5, 8}, {0x035E, 10}, {0x01EC, 9},
|
||||
{0x6714, 15}, {0x01ED, 9}, {0x035F, 10}, {0x03DC, 10},
|
||||
{0x03DD, 10}, {0x6715, 15}, {0x338B, 14}, {0x338C, 14},
|
||||
{0x338D, 14}, {0x001F, 5}, {0x01EF, 9}, {0x338E, 14},
|
||||
{0x338F, 14},
|
||||
},{//5
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5},
|
||||
{0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x006A, 8},
|
||||
{0x006B, 8}, {0x006C, 8}, {0x00DA, 9}, {0x036C, 11},
|
||||
{0x006E, 8}, {0x01B7, 10}, {0x036D, 11}, {0x3780, 15},
|
||||
{0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x003E, 7},
|
||||
{0x000A, 4}, {0x002C, 6}, {0x0017, 5}, {0x002D, 6},
|
||||
{0x003F, 7}, {0x00C0, 8}, {0x0061, 7}, {0x00C1, 8},
|
||||
{0x0062, 7}, {0x00C6, 8}, {0x0064, 7}, {0x00C7, 8},
|
||||
{0x00CA, 8}, {0x00DF, 9}, {0x0196, 9}, {0x0197, 9},
|
||||
{0x0198, 9}, {0x0199, 9}, {0x0379, 11}, {0x019A, 9},
|
||||
{0x01BD, 10}, {0x066C, 11}, {0x3781, 15}, {0x0337, 10},
|
||||
{0x066D, 11}, {0x0670, 11}, {0x0339, 10}, {0x0671, 11},
|
||||
{0x0034, 6}, {0x00CF, 8}, {0x3782, 15}, {0x3783, 15},
|
||||
{0x000E, 4}, {0x001B, 5}, {0x006A, 7}, {0x006B, 7},
|
||||
{0x019D, 9}, {0x003C, 6}, {0x00F4, 8}, {0x00F5, 8},
|
||||
{0x03D8, 10}, {0x07B2, 11}, {0x3784, 15}, {0x03DA, 10},
|
||||
{0x3785, 15}, {0x03DB, 10}, {0x03DC, 10}, {0x3786, 15},
|
||||
{0x3787, 15}, {0x1BC4, 14}, {0x1BC5, 14}, {0x1BC6, 14},
|
||||
{0x1BC7, 14}, {0x001F, 5}, {0x03DD, 10}, {0x07B3, 11},
|
||||
{0x01EF, 9},
|
||||
},{//6
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6},
|
||||
{0x0017, 6}, {0x0060, 8}, {0x00C2, 9}, {0x0186, 10},
|
||||
{0x0187, 10}, {0x00C4, 9}, {0x3140, 15}, {0x3141, 15},
|
||||
{0x018B, 10}, {0x3142, 15}, {0x018C, 10}, {0x3143, 15},
|
||||
{0x0007, 4}, {0x000D, 5}, {0x0064, 8}, {0x0065, 8},
|
||||
{0x0010, 5}, {0x00C7, 9}, {0x0066, 8}, {0x0005, 3},
|
||||
{0x0006, 3}, {0x0009, 4}, {0x0011, 5}, {0x0038, 6},
|
||||
{0x0039, 6}, {0x0074, 7}, {0x0075, 7}, {0x0076, 7},
|
||||
{0x0067, 8}, {0x00EE, 8}, {0x01DE, 9}, {0x00F0, 8},
|
||||
{0x018D, 10}, {0x3144, 15}, {0x01DF, 9}, {0x003D, 6},
|
||||
{0x003E, 6}, {0x01E2, 9}, {0x03C6, 10}, {0x00F2, 8},
|
||||
{0x00F3, 8}, {0x03C7, 10}, {0x3145, 15}, {0x3146, 15},
|
||||
{0x01F8, 9}, {0x3147, 15}, {0x3148, 15}, {0x3149, 15},
|
||||
{0x00FD, 8}, {0x314A, 15}, {0x314B, 15}, {0x314C, 15},
|
||||
{0x314D, 15}, {0x01F9, 9}, {0x314E, 15}, {0x01FC, 9},
|
||||
{0x314F, 15}, {0x3150, 15}, {0x3151, 15}, {0x3152, 15},
|
||||
{0x3153, 15}, {0x03FA, 10}, {0x03FB, 10}, {0x3154, 15},
|
||||
{0x3155, 15}, {0x3156, 15}, {0x3157, 15}, {0x3158, 15},
|
||||
{0x3159, 15}, {0x00FF, 8}, {0x18AD, 14}, {0x18AE, 14},
|
||||
{0x18AF, 14},
|
||||
},{//7
|
||||
{0x0000, 4}, {0x0080, 11}, {0x0081, 11}, {0x0082, 11},
|
||||
{0x0083, 11}, {0x0084, 11}, {0x0085, 11}, {0x0086, 11},
|
||||
{0x0087, 11}, {0x0088, 11}, {0x0089, 11}, {0x008A, 11},
|
||||
{0x008B, 11}, {0x008C, 11}, {0x008D, 11}, {0x008E, 11},
|
||||
{0x008F, 11}, {0x0048, 10}, {0x0049, 10}, {0x004A, 10},
|
||||
{0x004B, 10}, {0x004C, 10}, {0x004D, 10}, {0x0001, 1},
|
||||
{0x0001, 2}, {0x004E, 10}, {0x0002, 4}, {0x0003, 4},
|
||||
{0x004F, 10}, {0x0050, 10}, {0x0051, 10}, {0x0052, 10},
|
||||
{0x0053, 10}, {0x0054, 10}, {0x0055, 10}, {0x0056, 10},
|
||||
{0x0057, 10}, {0x0058, 10}, {0x0059, 10}, {0x005A, 10},
|
||||
{0x005B, 10}, {0x005C, 10}, {0x005D, 10}, {0x005E, 10},
|
||||
{0x005F, 10}, {0x0060, 10}, {0x0061, 10}, {0x0062, 10},
|
||||
{0x0063, 10}, {0x0064, 10}, {0x0065, 10}, {0x0066, 10},
|
||||
{0x0067, 10}, {0x0068, 10}, {0x0069, 10}, {0x006A, 10},
|
||||
{0x006B, 10}, {0x006C, 10}, {0x006D, 10}, {0x006E, 10},
|
||||
{0x006F, 10}, {0x0070, 10}, {0x0071, 10}, {0x0072, 10},
|
||||
{0x0073, 10}, {0x0074, 10}, {0x0075, 10}, {0x0076, 10},
|
||||
{0x0077, 10}, {0x0078, 10}, {0x0079, 10}, {0x007A, 10},
|
||||
{0x007B, 10}, {0x007C, 10}, {0x007D, 10}, {0x007E, 10},
|
||||
{0x007F, 10},
|
||||
}
|
||||
};
|
||||
|
||||
static const uint16_t x8_ac0_highquant_table[8][77][2]={
|
||||
{//0
|
||||
{0x0000, 3}, {0x0002, 4}, {0x000C, 6}, {0x000D, 6},
|
||||
{0x001C, 7}, {0x000F, 6}, {0x1D00, 15}, {0x003B, 8},
|
||||
{0x1D01, 15}, {0x0075, 9}, {0x1D02, 15}, {0x0080, 9},
|
||||
{0x1D03, 15}, {0x1D04, 15}, {0x1D05, 15}, {0x0E83, 14},
|
||||
{0x0009, 5}, {0x0011, 6}, {0x0081, 9}, {0x0082, 9},
|
||||
{0x0021, 7}, {0x0028, 7}, {0x0083, 9}, {0x0002, 2},
|
||||
{0x0003, 3}, {0x000C, 4}, {0x000D, 4}, {0x000B, 5},
|
||||
{0x0015, 6}, {0x0052, 8}, {0x0070, 7}, {0x0039, 6},
|
||||
{0x0071, 7}, {0x0053, 8}, {0x0E84, 14}, {0x0074, 7},
|
||||
{0x0075, 7}, {0x0076, 7}, {0x01DC, 9}, {0x001E, 5},
|
||||
{0x003E, 6}, {0x01DD, 9}, {0x00EF, 8}, {0x01F8, 9},
|
||||
{0x01F9, 9}, {0x0E85, 14}, {0x0E86, 14}, {0x0E87, 14},
|
||||
{0x00FD, 8}, {0x0E88, 14}, {0x0E89, 14}, {0x0E8A, 14},
|
||||
{0x0E8B, 14}, {0x0E8C, 14}, {0x0E8D, 14}, {0x0E8E, 14},
|
||||
{0x0E8F, 14}, {0x0E90, 14}, {0x0E91, 14}, {0x01FC, 9},
|
||||
{0x0E92, 14}, {0x0E93, 14}, {0x0E94, 14}, {0x0E95, 14},
|
||||
{0x0E96, 14}, {0x0E97, 14}, {0x01FD, 9}, {0x0E98, 14},
|
||||
{0x01FE, 9}, {0x0E99, 14}, {0x0E9A, 14}, {0x0E9B, 14},
|
||||
{0x0E9C, 14}, {0x01FF, 9}, {0x0E9D, 14}, {0x0E9E, 14},
|
||||
{0x0E9F, 14},
|
||||
},{//1
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0012, 6}, {0x0013, 6}, {0x0014, 6}, {0x0015, 6},
|
||||
{0x002C, 7}, {0x005A, 8}, {0x005B, 8}, {0x005C, 8},
|
||||
{0x005D, 8}, {0x1780, 14}, {0x0179, 10}, {0x017A, 10},
|
||||
{0x0006, 4}, {0x000E, 5}, {0x001E, 6}, {0x003E, 7},
|
||||
{0x0010, 5}, {0x0022, 6}, {0x0012, 5}, {0x000A, 4},
|
||||
{0x0013, 5}, {0x0016, 5}, {0x0023, 6}, {0x002E, 6},
|
||||
{0x002F, 6}, {0x0030, 6}, {0x0031, 6}, {0x003F, 7},
|
||||
{0x005F, 8}, {0x00C8, 8}, {0x0065, 7}, {0x0066, 7},
|
||||
{0x0067, 7}, {0x0068, 7}, {0x00C9, 8}, {0x0069, 7},
|
||||
{0x006A, 7}, {0x00D6, 8}, {0x00D7, 8}, {0x00D8, 8},
|
||||
{0x1781, 14}, {0x017B, 10}, {0x01B2, 9}, {0x1782, 14},
|
||||
{0x001C, 5}, {0x01B3, 9}, {0x1783, 14}, {0x1784, 14},
|
||||
{0x001D, 5}, {0x00DA, 8}, {0x1785, 14}, {0x1786, 14},
|
||||
{0x1787, 14}, {0x0037, 6}, {0x00DB, 8}, {0x0078, 7},
|
||||
{0x00F2, 8}, {0x01E6, 9}, {0x00F4, 8}, {0x1788, 14},
|
||||
{0x1789, 14}, {0x00F5, 8}, {0x01E7, 9}, {0x178A, 14},
|
||||
{0x178B, 14}, {0x178C, 14}, {0x178D, 14}, {0x01EC, 9},
|
||||
{0x178E, 14}, {0x001F, 5}, {0x00F7, 8}, {0x01ED, 9},
|
||||
{0x178F, 14},
|
||||
},{//2
|
||||
{0x0000, 4}, {0x0002, 5}, {0x0180, 12}, {0x0181, 12},
|
||||
{0x0182, 12}, {0x0183, 12}, {0x0184, 12}, {0x0185, 12},
|
||||
{0x0186, 12}, {0x0187, 12}, {0x0188, 12}, {0x0189, 12},
|
||||
{0x00C5, 11}, {0x00C6, 11}, {0x00C7, 11}, {0x00C8, 11},
|
||||
{0x00C9, 11}, {0x00CA, 11}, {0x00CB, 11}, {0x00CC, 11},
|
||||
{0x00CD, 11}, {0x00CE, 11}, {0x00CF, 11}, {0x0001, 1},
|
||||
{0x0001, 2}, {0x0004, 5}, {0x0005, 5}, {0x0006, 5},
|
||||
{0x00D0, 11}, {0x00D1, 11}, {0x00D2, 11}, {0x00D3, 11},
|
||||
{0x00D4, 11}, {0x00D5, 11}, {0x00D6, 11}, {0x00D7, 11},
|
||||
{0x00D8, 11}, {0x00D9, 11}, {0x00DA, 11}, {0x0007, 5},
|
||||
{0x00DB, 11}, {0x00DC, 11}, {0x00DD, 11}, {0x00DE, 11},
|
||||
{0x00DF, 11}, {0x00E0, 11}, {0x00E1, 11}, {0x00E2, 11},
|
||||
{0x00E3, 11}, {0x00E4, 11}, {0x00E5, 11}, {0x00E6, 11},
|
||||
{0x00E7, 11}, {0x00E8, 11}, {0x00E9, 11}, {0x00EA, 11},
|
||||
{0x00EB, 11}, {0x00EC, 11}, {0x00ED, 11}, {0x00EE, 11},
|
||||
{0x00EF, 11}, {0x00F0, 11}, {0x00F1, 11}, {0x00F2, 11},
|
||||
{0x00F3, 11}, {0x00F4, 11}, {0x00F5, 11}, {0x00F6, 11},
|
||||
{0x00F7, 11}, {0x00F8, 11}, {0x00F9, 11}, {0x00FA, 11},
|
||||
{0x00FB, 11}, {0x00FC, 11}, {0x00FD, 11}, {0x00FE, 11},
|
||||
{0x00FF, 11},
|
||||
},{//3
|
||||
{0x0000, 8}, {0x0001, 8}, {0x0002, 8}, {0x0003, 8},
|
||||
{0x0004, 8}, {0x0005, 8}, {0x0006, 8}, {0x0007, 8},
|
||||
{0x0008, 8}, {0x0009, 8}, {0x000A, 8}, {0x000B, 8},
|
||||
{0x000C, 8}, {0x000D, 8}, {0x000E, 8}, {0x000F, 8},
|
||||
{0x0010, 8}, {0x0011, 8}, {0x0012, 8}, {0x0013, 8},
|
||||
{0x0014, 8}, {0x0015, 8}, {0x0016, 8}, {0x0001, 1},
|
||||
{0x0017, 8}, {0x000C, 7}, {0x000D, 7}, {0x000E, 7},
|
||||
{0x000F, 7}, {0x0010, 7}, {0x0011, 7}, {0x0012, 7},
|
||||
{0x0013, 7}, {0x0014, 7}, {0x0015, 7}, {0x0016, 7},
|
||||
{0x0017, 7}, {0x0018, 7}, {0x0019, 7}, {0x001A, 7},
|
||||
{0x001B, 7}, {0x001C, 7}, {0x001D, 7}, {0x001E, 7},
|
||||
{0x001F, 7}, {0x0020, 7}, {0x0021, 7}, {0x0022, 7},
|
||||
{0x0023, 7}, {0x0024, 7}, {0x0025, 7}, {0x0026, 7},
|
||||
{0x0027, 7}, {0x0028, 7}, {0x0029, 7}, {0x002A, 7},
|
||||
{0x002B, 7}, {0x002C, 7}, {0x002D, 7}, {0x002E, 7},
|
||||
{0x002F, 7}, {0x0030, 7}, {0x0031, 7}, {0x0032, 7},
|
||||
{0x0033, 7}, {0x0034, 7}, {0x0035, 7}, {0x0036, 7},
|
||||
{0x0037, 7}, {0x0038, 7}, {0x0039, 7}, {0x003A, 7},
|
||||
{0x003B, 7}, {0x003C, 7}, {0x003D, 7}, {0x003E, 7},
|
||||
{0x003F, 7},
|
||||
},{//4
|
||||
{0x0000, 9}, {0x0001, 9}, {0x0002, 9}, {0x0003, 9},
|
||||
{0x0004, 9}, {0x0005, 9}, {0x0006, 9}, {0x0007, 9},
|
||||
{0x0008, 9}, {0x0009, 9}, {0x000A, 9}, {0x000B, 9},
|
||||
{0x000C, 9}, {0x000D, 9}, {0x000E, 9}, {0x000F, 9},
|
||||
{0x0010, 9}, {0x0011, 9}, {0x0012, 9}, {0x0013, 9},
|
||||
{0x0014, 9}, {0x0015, 9}, {0x000B, 8}, {0x0001, 2},
|
||||
{0x0001, 1}, {0x000C, 8}, {0x000D, 8}, {0x000E, 8},
|
||||
{0x000F, 8}, {0x0010, 8}, {0x0011, 8}, {0x0012, 8},
|
||||
{0x0013, 8}, {0x0014, 8}, {0x0015, 8}, {0x0016, 8},
|
||||
{0x0017, 8}, {0x0018, 8}, {0x0019, 8}, {0x001A, 8},
|
||||
{0x001B, 8}, {0x001C, 8}, {0x001D, 8}, {0x001E, 8},
|
||||
{0x001F, 8}, {0x0020, 8}, {0x0021, 8}, {0x0022, 8},
|
||||
{0x0023, 8}, {0x0024, 8}, {0x0025, 8}, {0x0026, 8},
|
||||
{0x0027, 8}, {0x0028, 8}, {0x0029, 8}, {0x002A, 8},
|
||||
{0x002B, 8}, {0x002C, 8}, {0x002D, 8}, {0x002E, 8},
|
||||
{0x002F, 8}, {0x0030, 8}, {0x0031, 8}, {0x0032, 8},
|
||||
{0x0033, 8}, {0x0034, 8}, {0x0035, 8}, {0x0036, 8},
|
||||
{0x0037, 8}, {0x0038, 8}, {0x0039, 8}, {0x003A, 8},
|
||||
{0x003B, 8}, {0x003C, 8}, {0x003D, 8}, {0x003E, 8},
|
||||
{0x003F, 8},
|
||||
},{//5
|
||||
{0x0000, 10}, {0x0001, 10}, {0x0002, 10}, {0x0003, 10},
|
||||
{0x0004, 10}, {0x0005, 10}, {0x0006, 10}, {0x0007, 10},
|
||||
{0x0008, 10}, {0x0009, 10}, {0x000A, 10}, {0x000B, 10},
|
||||
{0x000C, 10}, {0x000D, 10}, {0x000E, 10}, {0x000F, 10},
|
||||
{0x0010, 10}, {0x0011, 10}, {0x0012, 10}, {0x0013, 10},
|
||||
{0x000A, 9}, {0x000B, 9}, {0x000C, 9}, {0x0001, 1},
|
||||
{0x0001, 3}, {0x000D, 9}, {0x000E, 9}, {0x0001, 2},
|
||||
{0x000F, 9}, {0x0010, 9}, {0x0011, 9}, {0x0012, 9},
|
||||
{0x0013, 9}, {0x0014, 9}, {0x0015, 9}, {0x0016, 9},
|
||||
{0x0017, 9}, {0x0018, 9}, {0x0019, 9}, {0x001A, 9},
|
||||
{0x001B, 9}, {0x001C, 9}, {0x001D, 9}, {0x001E, 9},
|
||||
{0x001F, 9}, {0x0020, 9}, {0x0021, 9}, {0x0022, 9},
|
||||
{0x0023, 9}, {0x0024, 9}, {0x0025, 9}, {0x0026, 9},
|
||||
{0x0027, 9}, {0x0028, 9}, {0x0029, 9}, {0x002A, 9},
|
||||
{0x002B, 9}, {0x002C, 9}, {0x002D, 9}, {0x002E, 9},
|
||||
{0x002F, 9}, {0x0030, 9}, {0x0031, 9}, {0x0032, 9},
|
||||
{0x0033, 9}, {0x0034, 9}, {0x0035, 9}, {0x0036, 9},
|
||||
{0x0037, 9}, {0x0038, 9}, {0x0039, 9}, {0x003A, 9},
|
||||
{0x003B, 9}, {0x003C, 9}, {0x003D, 9}, {0x003E, 9},
|
||||
{0x003F, 9},
|
||||
},{//6
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5},
|
||||
{0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x006A, 8},
|
||||
{0x006B, 8}, {0x006C, 8}, {0x00DA, 9}, {0x00DB, 9},
|
||||
{0x01B8, 10}, {0x00DD, 9}, {0x01B9, 10}, {0x3780, 15},
|
||||
{0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x001F, 6},
|
||||
{0x000A, 4}, {0x0058, 7}, {0x0017, 5}, {0x0018, 5},
|
||||
{0x0059, 7}, {0x005A, 7}, {0x005B, 7}, {0x00C8, 8},
|
||||
{0x0065, 7}, {0x0066, 7}, {0x00C9, 8}, {0x00CE, 8},
|
||||
{0x00CF, 8}, {0x00D0, 8}, {0x00D1, 8}, {0x00D2, 8},
|
||||
{0x00D3, 8}, {0x00DF, 9}, {0x00D4, 8}, {0x00D5, 8},
|
||||
{0x00D6, 8}, {0x01AE, 9}, {0x3781, 15}, {0x01BD, 10},
|
||||
{0x035E, 10}, {0x035F, 10}, {0x3782, 15}, {0x0360, 10},
|
||||
{0x0037, 6}, {0x01B1, 9}, {0x3783, 15}, {0x3784, 15},
|
||||
{0x000E, 4}, {0x003C, 6}, {0x0361, 10}, {0x3785, 15},
|
||||
{0x1BC3, 14}, {0x003D, 6}, {0x00D9, 8}, {0x1BC4, 14},
|
||||
{0x0368, 10}, {0x1BC5, 14}, {0x1BC6, 14}, {0x1BC7, 14},
|
||||
{0x1BC8, 14}, {0x00DB, 8}, {0x0369, 10}, {0x036A, 10},
|
||||
{0x1BC9, 14}, {0x1BCA, 14}, {0x1BCB, 14}, {0x1BCC, 14},
|
||||
{0x1BCD, 14}, {0x001F, 5}, {0x036B, 10}, {0x1BCE, 14},
|
||||
{0x1BCF, 14},
|
||||
},{//7
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5},
|
||||
{0x0010, 6}, {0x0044, 8}, {0x0023, 7}, {0x0012, 6},
|
||||
{0x0026, 7}, {0x08A0, 13}, {0x004E, 8}, {0x004F, 8},
|
||||
{0x08A1, 13}, {0x08A2, 13}, {0x08A3, 13}, {0x0050, 8},
|
||||
{0x0006, 4}, {0x000B, 5}, {0x0029, 7}, {0x0015, 6},
|
||||
{0x001C, 6}, {0x003A, 7}, {0x001E, 6}, {0x0004, 3},
|
||||
{0x0014, 5}, {0x0015, 5}, {0x000B, 4}, {0x001F, 6},
|
||||
{0x0030, 6}, {0x0031, 6}, {0x0019, 5}, {0x0051, 8},
|
||||
{0x0034, 6}, {0x0035, 6}, {0x0036, 6}, {0x0037, 6},
|
||||
{0x0076, 8}, {0x0077, 8}, {0x0070, 7}, {0x001D, 5},
|
||||
{0x0071, 7}, {0x0072, 7}, {0x08A4, 13}, {0x0073, 7},
|
||||
{0x00F0, 8}, {0x08A5, 13}, {0x08A6, 13}, {0x08A7, 13},
|
||||
{0x0079, 7}, {0x007A, 7}, {0x08A8, 13}, {0x08A9, 13},
|
||||
{0x00F1, 8}, {0x08AA, 13}, {0x08AB, 13}, {0x08AC, 13},
|
||||
{0x08AD, 13}, {0x00F6, 8}, {0x08AE, 13}, {0x007C, 7},
|
||||
{0x00F7, 8}, {0x08AF, 13}, {0x08B0, 13}, {0x08B1, 13},
|
||||
{0x08B2, 13}, {0x00FA, 8}, {0x08B3, 13}, {0x08B4, 13},
|
||||
{0x08B5, 13}, {0x08B6, 13}, {0x08B7, 13}, {0x00FB, 8},
|
||||
{0x045C, 12}, {0x003F, 6}, {0x045D, 12}, {0x045E, 12},
|
||||
{0x045F, 12},
|
||||
}
|
||||
};
|
||||
|
||||
static const uint16_t x8_ac1_lowquant_table[8][77][2]={
|
||||
{//0
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0012, 6}, {0x0026, 7}, {0x0014, 6}, {0x004E, 8},
|
||||
{0x004F, 8}, {0x00A8, 9}, {0x0152, 10}, {0x00AA, 9},
|
||||
{0x00AB, 9}, {0x00AC, 9}, {0x2A60, 15}, {0x02A7, 11},
|
||||
{0x0006, 4}, {0x000B, 5}, {0x001C, 6}, {0x003A, 7},
|
||||
{0x000F, 5}, {0x003B, 7}, {0x0010, 5}, {0x0005, 3},
|
||||
{0x0009, 4}, {0x0011, 5}, {0x0018, 5}, {0x0019, 5},
|
||||
{0x001A, 5}, {0x0036, 6}, {0x0037, 6}, {0x0070, 7},
|
||||
{0x0057, 8}, {0x00E2, 8}, {0x00E3, 8}, {0x00E4, 8},
|
||||
{0x00E5, 8}, {0x00AD, 9}, {0x0398, 10}, {0x003A, 6},
|
||||
{0x0076, 7}, {0x00E7, 8}, {0x00EE, 8}, {0x00EF, 8},
|
||||
{0x0732, 11}, {0x039A, 10}, {0x0733, 11}, {0x2A61, 15},
|
||||
{0x0078, 7}, {0x1531, 14}, {0x1532, 14}, {0x1533, 14},
|
||||
{0x003D, 6}, {0x039B, 10}, {0x1534, 14}, {0x1535, 14},
|
||||
{0x1536, 14}, {0x0079, 7}, {0x1537, 14}, {0x00F8, 8},
|
||||
{0x01F2, 9}, {0x07CC, 11}, {0x03E7, 10}, {0x07CD, 11},
|
||||
{0x3E80, 14}, {0x00FB, 8}, {0x03E9, 10}, {0x3E81, 14},
|
||||
{0x3E82, 14}, {0x3E83, 14}, {0x3E84, 14}, {0x3E85, 14},
|
||||
{0x3E86, 14}, {0x003F, 6}, {0x01F5, 9}, {0x07D1, 11},
|
||||
{0x3E87, 14},
|
||||
},{//1
|
||||
{0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5},
|
||||
{0x001E, 6}, {0x001F, 6}, {0x0040, 7}, {0x0082, 8},
|
||||
{0x0083, 8}, {0x0084, 8}, {0x010A, 9}, {0x010B, 9},
|
||||
{0x0430, 11}, {0x0431, 11}, {0x0432, 11}, {0x0433, 11},
|
||||
{0x0005, 3}, {0x0011, 5}, {0x0024, 6}, {0x004A, 7},
|
||||
{0x000C, 4}, {0x0026, 6}, {0x000D, 4}, {0x0087, 8},
|
||||
{0x010D, 9}, {0x0258, 10}, {0x012D, 9}, {0x0259, 10},
|
||||
{0x025C, 10}, {0x0974, 12}, {0x025E, 10}, {0x025F, 10},
|
||||
{0x0270, 10}, {0x0271, 10}, {0x04BB, 11}, {0x0975, 12},
|
||||
{0x0272, 10}, {0x09CC, 12}, {0x09CD, 12}, {0x4E70, 15},
|
||||
{0x4E71, 15}, {0x4E72, 15}, {0x4E73, 15}, {0x273A, 14},
|
||||
{0x273B, 14}, {0x273C, 14}, {0x04E8, 11}, {0x04E9, 11},
|
||||
{0x009E, 8}, {0x0275, 10}, {0x09D8, 12}, {0x273D, 14},
|
||||
{0x000E, 4}, {0x003C, 6}, {0x007A, 7}, {0x009F, 8},
|
||||
{0x0277, 10}, {0x003E, 6}, {0x00F6, 8}, {0x04ED, 11},
|
||||
{0x03DC, 10}, {0x273E, 14}, {0x07BA, 11}, {0x09D9, 12},
|
||||
{0x273F, 14}, {0x3DD8, 14}, {0x3DD9, 14}, {0x3DDA, 14},
|
||||
{0x3DDB, 14}, {0x3DDC, 14}, {0x3DDD, 14}, {0x3DDE, 14},
|
||||
{0x3DDF, 14}, {0x003F, 6}, {0x07BC, 11}, {0x07BD, 11},
|
||||
{0x03DF, 10},
|
||||
},{//2
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x000E, 6},
|
||||
{0x001E, 7}, {0x003E, 8}, {0x003F, 8}, {0x0040, 8},
|
||||
{0x0104, 10}, {0x0083, 9}, {0x0105, 10}, {0x0108, 10},
|
||||
{0x4240, 16}, {0x010A, 10}, {0x010B, 10}, {0x4241, 16},
|
||||
{0x0003, 3}, {0x0009, 5}, {0x0011, 6}, {0x0043, 8},
|
||||
{0x0004, 3}, {0x000A, 5}, {0x000A, 4}, {0x002C, 7},
|
||||
{0x00B4, 9}, {0x00B5, 9}, {0x00B6, 9}, {0x00B7, 9},
|
||||
{0x00B8, 9}, {0x0172, 10}, {0x0173, 10}, {0x0174, 10},
|
||||
{0x0175, 10}, {0x0176, 10}, {0x0177, 10}, {0x00BC, 9},
|
||||
{0x017A, 10}, {0x0213, 11}, {0x4242, 16}, {0x017B, 10},
|
||||
{0x02F8, 11}, {0x017D, 10}, {0x02F9, 11}, {0x017E, 10},
|
||||
{0x4243, 16}, {0x02FE, 11}, {0x2122, 15}, {0x2123, 15},
|
||||
{0x0058, 7}, {0x0164, 9}, {0x2124, 15}, {0x2125, 15},
|
||||
{0x0006, 3}, {0x000E, 4}, {0x002D, 6}, {0x002E, 6},
|
||||
{0x00B3, 8}, {0x001E, 5}, {0x005E, 7}, {0x2126, 15},
|
||||
{0x2127, 15}, {0x2128, 15}, {0x2129, 15}, {0x02FF, 11},
|
||||
{0x212A, 15}, {0x0594, 11}, {0x0595, 11}, {0x0596, 11},
|
||||
{0x212B, 15}, {0x212C, 15}, {0x212D, 15}, {0x212E, 15},
|
||||
{0x212F, 15}, {0x001F, 5}, {0x0597, 11}, {0x00BE, 8},
|
||||
{0x00BF, 8},
|
||||
},{//3
|
||||
{0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x0007, 4},
|
||||
{0x0010, 5}, {0x0011, 5}, {0x0024, 6}, {0x0025, 6},
|
||||
{0x0026, 6}, {0x0027, 6}, {0x0050, 7}, {0x0051, 7},
|
||||
{0x00A4, 8}, {0x00A5, 8}, {0x00A6, 8}, {0x014E, 9},
|
||||
{0x000B, 4}, {0x002A, 6}, {0x0056, 7}, {0x014F, 9},
|
||||
{0x0030, 6}, {0x00AE, 8}, {0x0062, 7}, {0x0032, 6},
|
||||
{0x0033, 6}, {0x0034, 6}, {0x0035, 6}, {0x0036, 6},
|
||||
{0x0063, 7}, {0x006E, 7}, {0x006F, 7}, {0x0070, 7},
|
||||
{0x0071, 7}, {0x0072, 7}, {0x0073, 7}, {0x0074, 7},
|
||||
{0x00AF, 8}, {0x00EA, 8}, {0x01D6, 9}, {0x075C, 11},
|
||||
{0x03AF, 10}, {0x75D0, 15}, {0x75D1, 15}, {0x75D2, 15},
|
||||
{0x75D3, 15}, {0x75D4, 15}, {0x0076, 7}, {0x00EE, 8},
|
||||
{0x00EF, 8}, {0x0EBB, 12}, {0x01E0, 9}, {0x75D5, 15},
|
||||
{0x0079, 7}, {0x01E1, 9}, {0x75D6, 15}, {0x75D7, 15},
|
||||
{0x7880, 15}, {0x00F4, 8}, {0x0789, 11}, {0x003E, 6},
|
||||
{0x007B, 7}, {0x00F5, 8}, {0x00FC, 8}, {0x007F, 7},
|
||||
{0x01E3, 9}, {0x078A, 11}, {0x078B, 11}, {0x7881, 15},
|
||||
{0x7882, 15}, {0x7883, 15}, {0x3C42, 14}, {0x3C43, 14},
|
||||
{0x3C44, 14}, {0x00FD, 8}, {0x3C45, 14}, {0x3C46, 14},
|
||||
{0x3C47, 14},
|
||||
},{//4
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6},
|
||||
{0x0017, 6}, {0x0030, 7}, {0x0031, 7}, {0x0064, 8},
|
||||
{0x0065, 8}, {0x0066, 8}, {0x00CE, 9}, {0x00CF, 9},
|
||||
{0x01A0, 10}, {0x01A1, 10}, {0x1A20, 14}, {0x0689, 12},
|
||||
{0x0004, 3}, {0x000E, 5}, {0x001B, 6}, {0x0035, 7},
|
||||
{0x000A, 4}, {0x001E, 6}, {0x0016, 5}, {0x0017, 5},
|
||||
{0x001F, 6}, {0x0030, 6}, {0x0031, 6}, {0x0064, 7},
|
||||
{0x0065, 7}, {0x0069, 8}, {0x0066, 7}, {0x00CE, 8},
|
||||
{0x00CF, 8}, {0x00D0, 8}, {0x00D1, 8}, {0x00D2, 8},
|
||||
{0x01A6, 9}, {0x01A3, 10}, {0x034E, 10}, {0x006A, 7},
|
||||
{0x00D6, 8}, {0x01AE, 9}, {0x01AF, 9}, {0x034F, 10},
|
||||
{0x0345, 11}, {0x01B0, 9}, {0x01B1, 9}, {0x0364, 10},
|
||||
{0x006D, 7}, {0x00DC, 8}, {0x0D94, 12}, {0x0D95, 12},
|
||||
{0x000E, 4}, {0x003C, 6}, {0x00DD, 8}, {0x00DE, 8},
|
||||
{0x01B3, 9}, {0x003D, 6}, {0x00DF, 8}, {0x01F0, 9},
|
||||
{0x03E2, 10}, {0x03E3, 10}, {0x06CB, 11}, {0x03E4, 10},
|
||||
{0x07CA, 11}, {0x01F3, 9}, {0x01F4, 9}, {0x07CB, 11},
|
||||
{0x07D4, 11}, {0x1A21, 14}, {0x1A22, 14}, {0x07D5, 11},
|
||||
{0x1A23, 14}, {0x003F, 6}, {0x01F6, 9}, {0x01F7, 9},
|
||||
{0x03EB, 10},
|
||||
},{//5
|
||||
{0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5},
|
||||
{0x000F, 5}, {0x0020, 6}, {0x0021, 6}, {0x0044, 7},
|
||||
{0x0045, 7}, {0x0046, 7}, {0x008E, 8}, {0x008F, 8},
|
||||
{0x0090, 8}, {0x0122, 9}, {0x0246, 10}, {0x0124, 9},
|
||||
{0x0005, 3}, {0x0013, 5}, {0x004A, 7}, {0x0093, 8},
|
||||
{0x0018, 5}, {0x004B, 7}, {0x0032, 6}, {0x001A, 5},
|
||||
{0x0033, 6}, {0x006C, 7}, {0x006D, 7}, {0x006E, 7},
|
||||
{0x00DE, 8}, {0x00DF, 8}, {0x0070, 7}, {0x00E2, 8},
|
||||
{0x00E3, 8}, {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8},
|
||||
{0x00E7, 8}, {0x0125, 9}, {0x01D0, 9}, {0x048E, 11},
|
||||
{0x091E, 12}, {0x091F, 12}, {0x7440, 15}, {0x1D11, 13},
|
||||
{0x7441, 15}, {0x7442, 15}, {0x00E9, 8}, {0x01D4, 9},
|
||||
{0x00EB, 8}, {0x03A3, 10}, {0x01D5, 9}, {0x1D12, 13},
|
||||
{0x001E, 5}, {0x0076, 7}, {0x01DC, 9}, {0x01DD, 9},
|
||||
{0x7443, 15}, {0x007C, 7}, {0x0745, 11}, {0x00EF, 8},
|
||||
{0x00FA, 8}, {0x00FB, 8}, {0x01F8, 9}, {0x00FD, 8},
|
||||
{0x07E4, 11}, {0x0FCA, 12}, {0x1D13, 13}, {0x7E58, 15},
|
||||
{0x7E59, 15}, {0x7E5A, 15}, {0x7E5B, 15}, {0x7E5C, 15},
|
||||
{0x7E5D, 15}, {0x007F, 7}, {0x3F2F, 14}, {0x07E6, 11},
|
||||
{0x07E7, 11},
|
||||
},{//6
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0009, 5}, {0x0014, 6}, {0x0015, 6}, {0x002C, 7},
|
||||
{0x005A, 8}, {0x005B, 8}, {0x005C, 8}, {0x00BA, 9},
|
||||
{0x00BB, 9}, {0x00BC, 9}, {0x02F4, 11}, {0x05EA, 12},
|
||||
{0x0003, 3}, {0x0010, 5}, {0x0022, 6}, {0x0046, 7},
|
||||
{0x0009, 4}, {0x0028, 6}, {0x0015, 5}, {0x000B, 4},
|
||||
{0x0018, 5}, {0x0029, 6}, {0x0032, 6}, {0x0047, 7},
|
||||
{0x0066, 7}, {0x0067, 7}, {0x0068, 7}, {0x0069, 7},
|
||||
{0x006A, 7}, {0x005F, 8}, {0x00D6, 8}, {0x00D7, 8},
|
||||
{0x01B0, 9}, {0x00D9, 8}, {0x017B, 10}, {0x006D, 7},
|
||||
{0x00DC, 8}, {0x01B1, 9}, {0x06E8, 11}, {0x01BB, 9},
|
||||
{0x0375, 10}, {0x05EB, 12}, {0x01BC, 9}, {0x6E90, 15},
|
||||
{0x0038, 6}, {0x0072, 7}, {0x6E91, 15}, {0x6E92, 15},
|
||||
{0x001D, 5}, {0x0073, 7}, {0x01BD, 9}, {0x06F8, 11},
|
||||
{0x6E93, 15}, {0x003C, 6}, {0x01BF, 9}, {0x00F4, 8},
|
||||
{0x01EA, 9}, {0x037D, 10}, {0x03D6, 10}, {0x06F9, 11},
|
||||
{0x6E94, 15}, {0x00F6, 8}, {0x01EE, 9}, {0x6E95, 15},
|
||||
{0x6E96, 15}, {0x6E97, 15}, {0x374C, 14}, {0x374D, 14},
|
||||
{0x374E, 14}, {0x001F, 5}, {0x03D7, 10}, {0x01EF, 9},
|
||||
{0x374F, 14},
|
||||
},{//7
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6},
|
||||
{0x002E, 7}, {0x002F, 7}, {0x0060, 8}, {0x0061, 8},
|
||||
{0x00C4, 9}, {0x00C5, 9}, {0x00C6, 9}, {0x018E, 10},
|
||||
{0x31E0, 15}, {0x31E1, 15}, {0x31E2, 15}, {0x31E3, 15},
|
||||
{0x0004, 3}, {0x000D, 5}, {0x0019, 6}, {0x0038, 7},
|
||||
{0x000A, 4}, {0x001D, 6}, {0x000B, 4}, {0x0072, 8},
|
||||
{0x0073, 8}, {0x00F0, 9}, {0x01E2, 10}, {0x00F2, 9},
|
||||
{0x01E3, 10}, {0x00F3, 9}, {0x01E8, 10}, {0x01E9, 10},
|
||||
{0x31E4, 15}, {0x01EA, 10}, {0x031F, 11}, {0x03D6, 11},
|
||||
{0x31E5, 15}, {0x01EC, 10}, {0x31E6, 15}, {0x00F7, 9},
|
||||
{0x03D7, 11}, {0x31E7, 15}, {0x31E8, 15}, {0x03DA, 11},
|
||||
{0x03DB, 11}, {0x31E9, 15}, {0x03E0, 11}, {0x31EA, 15},
|
||||
{0x003F, 7}, {0x01F1, 10}, {0x31EB, 15}, {0x31EC, 15},
|
||||
{0x0006, 3}, {0x001C, 5}, {0x0074, 7}, {0x0075, 7},
|
||||
{0x00F9, 9}, {0x001E, 5}, {0x0076, 7}, {0x00FA, 9},
|
||||
{0x03E1, 11}, {0x31ED, 15}, {0x18F7, 14}, {0x1F60, 14},
|
||||
{0x1F61, 14}, {0x01DC, 9}, {0x01DD, 9}, {0x1F62, 14},
|
||||
{0x1F63, 14}, {0x1F64, 14}, {0x1F65, 14}, {0x1F66, 14},
|
||||
{0x1F67, 14}, {0x001F, 5}, {0x03ED, 11}, {0x00EF, 8},
|
||||
{0x01F7, 10},
|
||||
}
|
||||
};
|
||||
|
||||
static const uint16_t x8_ac1_highquant_table[8][77][2]={
|
||||
{//0
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5},
|
||||
{0x0008, 5}, {0x0009, 5}, {0x0014, 6}, {0x002A, 7},
|
||||
{0x0016, 6}, {0x002B, 7}, {0x005C, 8}, {0x002F, 7},
|
||||
{0x0030, 7}, {0x005D, 8}, {0x0062, 8}, {0x00C6, 9},
|
||||
{0x0007, 4}, {0x0019, 6}, {0x001A, 6}, {0x0036, 7},
|
||||
{0x0010, 5}, {0x006E, 8}, {0x0022, 6}, {0x0009, 4},
|
||||
{0x000A, 4}, {0x0016, 5}, {0x0023, 6}, {0x002E, 6},
|
||||
{0x002F, 6}, {0x0030, 6}, {0x0062, 7}, {0x0063, 7},
|
||||
{0x0064, 7}, {0x0065, 7}, {0x0066, 7}, {0x0067, 7},
|
||||
{0x0068, 7}, {0x0069, 7}, {0x006A, 7}, {0x006B, 7},
|
||||
{0x006C, 7}, {0x00C7, 9}, {0x00DE, 9}, {0x00DF, 9},
|
||||
{0x06D0, 11}, {0x01B5, 9}, {0x0037, 6}, {0x00DB, 8},
|
||||
{0x001C, 5}, {0x0074, 7}, {0x01D4, 9}, {0x01D5, 9},
|
||||
{0x0076, 7}, {0x0369, 10}, {0x3688, 14}, {0x3689, 14},
|
||||
{0x368A, 14}, {0x0077, 7}, {0x03AC, 10}, {0x0078, 7},
|
||||
{0x00F2, 8}, {0x01D7, 9}, {0x00F3, 8}, {0x007A, 7},
|
||||
{0x368B, 14}, {0x007B, 7}, {0x007C, 7}, {0x03AD, 10},
|
||||
{0x03E8, 10}, {0x368C, 14}, {0x368D, 14}, {0x03E9, 10},
|
||||
{0x368E, 14}, {0x003F, 6}, {0x01F5, 9}, {0x00FB, 8},
|
||||
{0x368F, 14},
|
||||
},{//1
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5},
|
||||
{0x0018, 6}, {0x0032, 7}, {0x0033, 7}, {0x0034, 7},
|
||||
{0x006A, 8}, {0x00D6, 9}, {0x00D7, 9}, {0x00D8, 9},
|
||||
{0x00D9, 9}, {0x3680, 15}, {0x01B5, 10}, {0x0369, 11},
|
||||
{0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x0037, 7},
|
||||
{0x000A, 4}, {0x0016, 5}, {0x000C, 4}, {0x001F, 6},
|
||||
{0x005C, 7}, {0x005D, 7}, {0x00BC, 8}, {0x00BD, 8},
|
||||
{0x005F, 7}, {0x00D0, 8}, {0x00DB, 9}, {0x00D1, 8},
|
||||
{0x01A4, 9}, {0x01A5, 9}, {0x01A6, 9}, {0x01A7, 9},
|
||||
{0x0350, 10}, {0x06A2, 11}, {0x06A3, 11}, {0x01A9, 9},
|
||||
{0x01AA, 9}, {0x06AC, 11}, {0x3681, 15}, {0x0357, 10},
|
||||
{0x3682, 15}, {0x3683, 15}, {0x3684, 15}, {0x3685, 15},
|
||||
{0x0036, 6}, {0x00D6, 8}, {0x3686, 15}, {0x3687, 15},
|
||||
{0x000E, 4}, {0x006E, 7}, {0x00D7, 8}, {0x06AD, 11},
|
||||
{0x3688, 15}, {0x001E, 5}, {0x00DE, 8}, {0x06F8, 11},
|
||||
{0x037D, 10}, {0x3689, 15}, {0x368A, 15}, {0x368B, 15},
|
||||
{0x368C, 15}, {0x01BF, 9}, {0x368D, 15}, {0x1B47, 14},
|
||||
{0x37C8, 14}, {0x37C9, 14}, {0x37CA, 14}, {0x37CB, 14},
|
||||
{0x37CC, 14}, {0x001F, 5}, {0x37CD, 14}, {0x37CE, 14},
|
||||
{0x37CF, 14},
|
||||
},{//2
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0012, 6}, {0x0026, 7}, {0x0014, 6}, {0x0027, 7},
|
||||
{0x00A8, 9}, {0x00A9, 9}, {0x0055, 8}, {0x2B00, 15},
|
||||
{0x00AD, 9}, {0x2B01, 15}, {0x2B02, 15}, {0x2B03, 15},
|
||||
{0x0003, 3}, {0x000B, 5}, {0x0040, 7}, {0x0041, 7},
|
||||
{0x0009, 4}, {0x0021, 6}, {0x0011, 5}, {0x000A, 4},
|
||||
{0x000B, 4}, {0x0018, 5}, {0x0032, 6}, {0x0033, 6},
|
||||
{0x0034, 6}, {0x0035, 6}, {0x006C, 7}, {0x0057, 8},
|
||||
{0x006D, 7}, {0x00DC, 8}, {0x0159, 10}, {0x00DD, 8},
|
||||
{0x01BC, 9}, {0x037A, 10}, {0x037B, 10}, {0x0038, 6},
|
||||
{0x0072, 7}, {0x01BE, 9}, {0x01BF, 9}, {0x00E6, 8},
|
||||
{0x039C, 10}, {0x01CF, 9}, {0x2B04, 15}, {0x2B05, 15},
|
||||
{0x0074, 7}, {0x01D4, 9}, {0x2B06, 15}, {0x2B07, 15},
|
||||
{0x001E, 5}, {0x00EB, 8}, {0x1584, 14}, {0x1585, 14},
|
||||
{0x1586, 14}, {0x003B, 6}, {0x01D5, 9}, {0x01F0, 9},
|
||||
{0x039D, 10}, {0x03E2, 10}, {0x1587, 14}, {0x1588, 14},
|
||||
{0x1589, 14}, {0x00F9, 8}, {0x158A, 14}, {0x158B, 14},
|
||||
{0x03E3, 10}, {0x158C, 14}, {0x158D, 14}, {0x01F4, 9},
|
||||
{0x158E, 14}, {0x003F, 6}, {0x00FB, 8}, {0x01F5, 9},
|
||||
{0x158F, 14},
|
||||
},{//3
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5},
|
||||
{0x0010, 6}, {0x0011, 6}, {0x0024, 7}, {0x0025, 7},
|
||||
{0x0013, 6}, {0x0014, 6}, {0x002A, 7}, {0x002B, 7},
|
||||
{0x00B0, 9}, {0x00B1, 9}, {0x002D, 7}, {0x0059, 8},
|
||||
{0x000C, 5}, {0x0017, 6}, {0x00D0, 9}, {0x0035, 7},
|
||||
{0x001B, 6}, {0x0038, 7}, {0x0039, 7}, {0x0004, 3},
|
||||
{0x0005, 3}, {0x000F, 5}, {0x0018, 5}, {0x001D, 6},
|
||||
{0x0032, 6}, {0x0033, 6}, {0x0068, 7}, {0x0069, 7},
|
||||
{0x0069, 8}, {0x00D4, 8}, {0x00D5, 8}, {0x00D6, 8},
|
||||
{0x006C, 7}, {0x0037, 6}, {0x006D, 7}, {0x0070, 7},
|
||||
{0x0039, 6}, {0x00D7, 8}, {0x00D1, 9}, {0x3880, 14},
|
||||
{0x3881, 14}, {0x3882, 14}, {0x0074, 7}, {0x01C5, 9},
|
||||
{0x0075, 7}, {0x00E3, 8}, {0x3883, 14}, {0x3884, 14},
|
||||
{0x00EC, 8}, {0x3885, 14}, {0x1C43, 13}, {0x1C44, 13},
|
||||
{0x1C45, 13}, {0x00ED, 8}, {0x1C46, 13}, {0x003C, 6},
|
||||
{0x0077, 7}, {0x01E8, 9}, {0x003E, 6}, {0x007B, 7},
|
||||
{0x1C47, 13}, {0x007E, 7}, {0x007F, 7}, {0x1C48, 13},
|
||||
{0x1C49, 13}, {0x1C4A, 13}, {0x1C4B, 13}, {0x1C4C, 13},
|
||||
{0x1C4D, 13}, {0x00F5, 8}, {0x1C4E, 13}, {0x01E9, 9},
|
||||
{0x1C4F, 13},
|
||||
},{//4
|
||||
{0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5},
|
||||
{0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x0035, 7},
|
||||
{0x0036, 7}, {0x006E, 8}, {0x00DE, 9}, {0x00DF, 9},
|
||||
{0x01C0, 10}, {0x01C1, 10}, {0x01C2, 10}, {0x3860, 15},
|
||||
{0x0004, 3}, {0x000F, 5}, {0x001D, 6}, {0x0039, 7},
|
||||
{0x000A, 4}, {0x002C, 6}, {0x002D, 6}, {0x000C, 4},
|
||||
{0x0017, 5}, {0x0034, 6}, {0x0035, 6}, {0x0036, 6},
|
||||
{0x006E, 7}, {0x006F, 7}, {0x0070, 7}, {0x0071, 7},
|
||||
{0x0071, 8}, {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8},
|
||||
{0x00E7, 8}, {0x00E8, 8}, {0x03A4, 10}, {0x0075, 7},
|
||||
{0x00EC, 8}, {0x01D3, 9}, {0x01DA, 9}, {0x03A5, 10},
|
||||
{0x03B6, 10}, {0x070D, 12}, {0x03B7, 10}, {0x070E, 12},
|
||||
{0x003C, 6}, {0x00EE, 8}, {0x3861, 15}, {0x3862, 15},
|
||||
{0x003D, 6}, {0x01DE, 9}, {0x3863, 15}, {0x3864, 15},
|
||||
{0x3865, 15}, {0x007C, 7}, {0x070F, 12}, {0x03BE, 10},
|
||||
{0x03BF, 10}, {0x3866, 15}, {0x0FA0, 12}, {0x07D1, 11},
|
||||
{0x3867, 15}, {0x00FB, 8}, {0x01F5, 9}, {0x7D08, 15},
|
||||
{0x0FA4, 12}, {0x7D09, 15}, {0x7D0A, 15}, {0x7D0B, 15},
|
||||
{0x3E86, 14}, {0x003F, 6}, {0x0FA5, 12}, {0x07D3, 11},
|
||||
{0x3E87, 14},
|
||||
},{//5
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0009, 5}, {0x0014, 6}, {0x002A, 7}, {0x0056, 8},
|
||||
{0x02B8, 11}, {0x00AF, 9}, {0x02B9, 11}, {0x015D, 10},
|
||||
{0x02C0, 11}, {0x2C10, 15}, {0x2C11, 15}, {0x2C12, 15},
|
||||
{0x0006, 4}, {0x000E, 5}, {0x0017, 6}, {0x002D, 7},
|
||||
{0x000F, 5}, {0x0040, 7}, {0x0021, 6}, {0x0005, 3},
|
||||
{0x0009, 4}, {0x0011, 5}, {0x0018, 5}, {0x0019, 5},
|
||||
{0x001A, 5}, {0x0036, 6}, {0x0037, 6}, {0x0041, 7},
|
||||
{0x0059, 8}, {0x00E0, 8}, {0x00E1, 8}, {0x0071, 7},
|
||||
{0x00E4, 8}, {0x00B1, 9}, {0x02C2, 11}, {0x001D, 5},
|
||||
{0x0073, 7}, {0x00E5, 8}, {0x00F0, 8}, {0x0079, 7},
|
||||
{0x03C4, 10}, {0x01E3, 9}, {0x01E8, 9}, {0x2C13, 15},
|
||||
{0x007B, 7}, {0x2C14, 15}, {0x2C15, 15}, {0x2C16, 15},
|
||||
{0x007C, 7}, {0x02C3, 11}, {0x2C17, 15}, {0x160C, 14},
|
||||
{0x160D, 14}, {0x007D, 7}, {0x160E, 14}, {0x01E9, 9},
|
||||
{0x03C5, 10}, {0x03D4, 10}, {0x01EB, 9}, {0x160F, 14},
|
||||
{0x3D50, 14}, {0x00FC, 8}, {0x07AB, 11}, {0x3D51, 14},
|
||||
{0x3D52, 14}, {0x3D53, 14}, {0x3D54, 14}, {0x01FA, 9},
|
||||
{0x3D55, 14}, {0x007F, 7}, {0x01FB, 9}, {0x3D56, 14},
|
||||
{0x3D57, 14},
|
||||
},{//6
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5},
|
||||
{0x0009, 5}, {0x000A, 5}, {0x000B, 5}, {0x0018, 6},
|
||||
{0x0032, 7}, {0x000D, 5}, {0x0033, 7}, {0x0E00, 13},
|
||||
{0x0039, 7}, {0x0E01, 13}, {0x003A, 7}, {0x0E02, 13},
|
||||
{0x0008, 4}, {0x001E, 6}, {0x003B, 7}, {0x003E, 7},
|
||||
{0x0012, 5}, {0x003F, 7}, {0x0013, 5}, {0x0028, 6},
|
||||
{0x0029, 6}, {0x0054, 7}, {0x002B, 6}, {0x0055, 7},
|
||||
{0x0058, 7}, {0x0E03, 13}, {0x0059, 7}, {0x005A, 7},
|
||||
{0x0E04, 13}, {0x0E05, 13}, {0x0703, 12}, {0x005B, 7},
|
||||
{0x005C, 7}, {0x0704, 12}, {0x0705, 12}, {0x005D, 7},
|
||||
{0x0706, 12}, {0x0707, 12}, {0x0708, 12}, {0x0709, 12},
|
||||
{0x070A, 12}, {0x070B, 12}, {0x0018, 5}, {0x002F, 6},
|
||||
{0x000D, 4}, {0x0019, 5}, {0x070C, 12}, {0x0070, 7},
|
||||
{0x001D, 5}, {0x070D, 12}, {0x070E, 12}, {0x070F, 12},
|
||||
{0x0710, 12}, {0x0039, 6}, {0x0711, 12}, {0x003C, 6},
|
||||
{0x0712, 12}, {0x0713, 12}, {0x0714, 12}, {0x0715, 12},
|
||||
{0x0716, 12}, {0x003D, 6}, {0x0717, 12}, {0x0718, 12},
|
||||
{0x0719, 12}, {0x071A, 12}, {0x071B, 12}, {0x071C, 12},
|
||||
{0x071D, 12}, {0x001F, 5}, {0x071E, 12}, {0x0071, 7},
|
||||
{0x071F, 12},
|
||||
},{//7
|
||||
{0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x000E, 6},
|
||||
{0x000F, 6}, {0x0040, 8}, {0x0041, 8}, {0x0042, 8},
|
||||
{0x0218, 11}, {0x2190, 15}, {0x2191, 15}, {0x2192, 15},
|
||||
{0x2193, 15}, {0x2194, 15}, {0x2195, 15}, {0x2196, 15},
|
||||
{0x0005, 4}, {0x0011, 6}, {0x0024, 7}, {0x0087, 9},
|
||||
{0x000C, 5}, {0x004A, 8}, {0x004B, 8}, {0x0002, 2},
|
||||
{0x0006, 3}, {0x000D, 5}, {0x000E, 5}, {0x000F, 5},
|
||||
{0x0013, 6}, {0x0038, 6}, {0x00E4, 8}, {0x00E5, 8},
|
||||
{0x01CC, 9}, {0x00E7, 8}, {0x0074, 7}, {0x00EA, 8},
|
||||
{0x01CD, 9}, {0x021A, 11}, {0x2197, 15}, {0x001E, 5},
|
||||
{0x0076, 7}, {0x00EB, 8}, {0x01DC, 9}, {0x00EF, 8},
|
||||
{0x01DD, 9}, {0x01F0, 9}, {0x2198, 15}, {0x2199, 15},
|
||||
{0x00F9, 8}, {0x03E2, 10}, {0x219A, 15}, {0x219B, 15},
|
||||
{0x00FA, 8}, {0x219C, 15}, {0x219D, 15}, {0x219E, 15},
|
||||
{0x219F, 15}, {0x01F6, 9}, {0x21B0, 15}, {0x00FC, 8},
|
||||
{0x01F7, 9}, {0x21B1, 15}, {0x21B2, 15}, {0x21B3, 15},
|
||||
{0x21B4, 15}, {0x01FA, 9}, {0x21B5, 15}, {0x21B6, 15},
|
||||
{0x21B7, 15}, {0x21B8, 15}, {0x21B9, 15}, {0x03E3, 10},
|
||||
{0x10DD, 14}, {0x007F, 7}, {0x01FB, 9}, {0x10DE, 14},
|
||||
{0x10DF, 14},
|
||||
}
|
||||
};
|
||||
#define MAX_AC_VLC_BITS 16
|
||||
|
||||
#endif /* FFMPEG_INTRAX8HUF_H */
|
||||
Reference in New Issue
Block a user