diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6fe05eec1f..24fa453672 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -324,6 +324,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o +OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V2_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index e91ba2e6c8..1c7a2aab74 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -24,6 +24,7 @@ #include "faanidct.h" #include "idctdsp.h" #include "simple_idct.h" +#include "xvididct.h" av_cold void ff_init_scantable(uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable) @@ -299,6 +300,9 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; c->add_pixels_clamped = add_pixels_clamped_c; + if (CONFIG_MPEG4_DECODER && avctx->idct_algo == FF_IDCT_XVIDMMX) + ff_xvididct_init(c, avctx); + if (ARCH_ALPHA) ff_idctdsp_init_alpha(c, avctx, high_bit_depth); if (ARCH_ARM) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 41a2ff992f..6ff9aaf361 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -31,6 +31,7 @@ #include "mpeg4video.h" #include "h263.h" #include "thread.h" +#include "xvididct.h" /* The defines below define the number of bits that are read at once for * reading vlc values. Changing these may improve speed and data cache needs @@ -2209,7 +2210,8 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) ctx->divx_version, ctx->divx_build, s->divx_packed ? "p" : ""); #if HAVE_MMX - if (s->codec_id == AV_CODEC_ID_MPEG4 && ctx->xvid_build >= 0 && + if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0 && + s->codec_id == AV_CODEC_ID_MPEG4 && avctx->idct_algo == FF_IDCT_AUTO && (av_get_cpu_flags() & AV_CPU_FLAG_MMX)) { avctx->idct_algo = FF_IDCT_XVIDMMX; @@ -2217,6 +2219,7 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) return 1; } #endif + return 0; } diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index 74692939d5..53e643b5d4 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -40,6 +40,7 @@ OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp_init.o OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc_init.o OBJS-$(CONFIG_HEVC_DECODER) += x86/hevcdsp_init.o OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o +OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct_init.o OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp_init.o OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp_init.o OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp_init.o @@ -61,10 +62,10 @@ OBJS-$(CONFIG_WEBP_DECODER) += x86/vp8dsp_init.o MMX-OBJS-$(CONFIG_DIRAC_DECODER) += x86/dirac_dwt.o MMX-OBJS-$(CONFIG_FDCTDSP) += x86/fdct.o MMX-OBJS-$(CONFIG_IDCTDSP) += x86/idctdsp_mmx.o \ - x86/idct_mmx_xvid.o \ - x86/idct_sse2_xvid.o \ x86/simple_idct.o +MMX-OBJS-$(CONFIG_MPEG4_DECODER) += x86/idct_mmx_xvid.o \ + x86/idct_sse2_xvid.o MMX-OBJS-$(CONFIG_SNOW_DECODER) += x86/snowdsp.o MMX-OBJS-$(CONFIG_SNOW_ENCODER) += x86/snowdsp.o MMX-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_mmx.o diff --git a/libavcodec/x86/dct-test.c b/libavcodec/x86/dct-test.c index 85d643aa63..3ade1f3ce4 100644 --- a/libavcodec/x86/dct-test.c +++ b/libavcodec/x86/dct-test.c @@ -59,6 +59,9 @@ static const struct algo fdct_tab_arch[] = { static const struct algo idct_tab_arch[] = { #if HAVE_MMX_INLINE { "SIMPLE-MMX", ff_simple_idct_mmx, FF_IDCT_PERM_SIMPLE, AV_CPU_FLAG_MMX }, +#endif +#if CONFIG_MPEG4_DECODER +#if HAVE_MMX_INLINE { "XVID-MMX", ff_idct_xvid_mmx, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX, 1 }, #endif #if HAVE_MMXEXT_INLINE @@ -70,6 +73,7 @@ static const struct algo idct_tab_arch[] = { { "PR-SSE2", ff_prores_idct_put_10_sse2_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 }, #endif #endif +#endif /* CONFIG_MPEG4_DECODER */ { 0 } }; diff --git a/libavcodec/x86/idctdsp_init.c b/libavcodec/x86/idctdsp_init.c index 5bf5cc6ecc..6f54d80f87 100644 --- a/libavcodec/x86/idctdsp_init.c +++ b/libavcodec/x86/idctdsp_init.c @@ -22,7 +22,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/avcodec.h" #include "libavcodec/idctdsp.h" -#include "idct_xvid.h" #include "idctdsp.h" #include "simple_idct.h" @@ -38,8 +37,6 @@ static const uint8_t simple_mmx_permutation[64] = { 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, }; -static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 }; - av_cold int ff_init_scantable_permutation_x86(uint8_t *idct_permutation, enum idct_permutation_type perm_type) { @@ -50,10 +47,6 @@ av_cold int ff_init_scantable_permutation_x86(uint8_t *idct_permutation, for (i = 0; i < 64; i++) idct_permutation[i] = simple_mmx_permutation[i]; return 1; - case FF_IDCT_PERM_SSE2: - for (i = 0; i < 64; i++) - idct_permutation[i] = (i & 0x38) | idct_sse2_row_perm[i & 7]; - return 1; } return 0; @@ -68,44 +61,20 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, c->put_pixels_clamped = ff_put_pixels_clamped_mmx; c->add_pixels_clamped = ff_add_pixels_clamped_mmx; - if (avctx->lowres == 0 && !high_bit_depth) { - switch (avctx->idct_algo) { - case FF_IDCT_AUTO: - case FF_IDCT_SIMPLEAUTO: - case FF_IDCT_SIMPLEMMX: + if (!high_bit_depth && + avctx->lowres == 0 && + (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEAUTO || + avctx->idct_algo == FF_IDCT_SIMPLEMMX)) { c->idct_put = ff_simple_idct_put_mmx; c->idct_add = ff_simple_idct_add_mmx; c->idct = ff_simple_idct_mmx; c->perm_type = FF_IDCT_PERM_SIMPLE; - break; - case FF_IDCT_XVIDMMX: - c->idct_put = ff_idct_xvid_mmx_put; - c->idct_add = ff_idct_xvid_mmx_add; - c->idct = ff_idct_xvid_mmx; - break; - } } } if (EXTERNAL_MMX(cpu_flags)) { c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx; } - - if (INLINE_MMXEXT(cpu_flags)) { - if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) { - c->idct_put = ff_idct_xvid_mmxext_put; - c->idct_add = ff_idct_xvid_mmxext_add; - c->idct = ff_idct_xvid_mmxext; - } - } - - if (INLINE_SSE2(cpu_flags)) { - if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) { - c->idct_put = ff_idct_xvid_sse2_put; - c->idct_add = ff_idct_xvid_sse2_add; - c->idct = ff_idct_xvid_sse2; - c->perm_type = FF_IDCT_PERM_SSE2; - } - } if (EXTERNAL_SSE2(cpu_flags)) { c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_sse2; } diff --git a/libavcodec/x86/xvididct_init.c b/libavcodec/x86/xvididct_init.c new file mode 100644 index 0000000000..2ea48100bc --- /dev/null +++ b/libavcodec/x86/xvididct_init.c @@ -0,0 +1,63 @@ +/* + * 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 "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/idctdsp.h" +#include "libavcodec/xvididct.h" +#include "idct_xvid.h" +#include "idctdsp.h" + +static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 }; + +static av_cold void init_scantable_permutation_sse2(uint8_t *idct_permutation, + enum idct_permutation_type perm_type) +{ + int i; + + for (i = 0; i < 64; i++) + idct_permutation[i] = (i & 0x38) | idct_sse2_row_perm[i & 7]; +} + +av_cold void ff_xvididct_init_x86(IDCTDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (INLINE_MMX(cpu_flags)) { + c->idct_put = ff_idct_xvid_mmx_put; + c->idct_add = ff_idct_xvid_mmx_add; + c->idct = ff_idct_xvid_mmx; + } + + if (INLINE_MMXEXT(cpu_flags)) { + c->idct_put = ff_idct_xvid_mmxext_put; + c->idct_add = ff_idct_xvid_mmxext_add; + c->idct = ff_idct_xvid_mmxext; + } + + if (INLINE_SSE2(cpu_flags)) { + c->idct_put = ff_idct_xvid_sse2_put; + c->idct_add = ff_idct_xvid_sse2_add; + c->idct = ff_idct_xvid_sse2; + c->perm_type = FF_IDCT_PERM_SSE2; + + init_scantable_permutation_sse2(c->idct_permutation, c->perm_type); + } +} diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c new file mode 100644 index 0000000000..36f65a6aaf --- /dev/null +++ b/libavcodec/xvididct.c @@ -0,0 +1,36 @@ +/* + * 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 "config.h" +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "idctdsp.h" +#include "xvididct.h" + +av_cold void ff_xvididct_init(IDCTDSPContext *c, AVCodecContext *avctx) +{ + const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (high_bit_depth || avctx->lowres || + !(avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_XVIDMMX)) + return; + + if (ARCH_X86) + ff_xvididct_init_x86(c); +} diff --git a/libavcodec/xvididct.h b/libavcodec/xvididct.h new file mode 100644 index 0000000000..6678329201 --- /dev/null +++ b/libavcodec/xvididct.h @@ -0,0 +1,29 @@ +/* + * 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 AVCODEC_XVIDIDCT_H +#define AVCODEC_XVIDIDCT_H + +#include "avcodec.h" +#include "idctdsp.h" + +void ff_xvididct_init(IDCTDSPContext *c, AVCodecContext *avctx); + +void ff_xvididct_init_x86(IDCTDSPContext *c); + +#endif /* AVCODEC_XVIDIDCT_H */