From 0c6fa1fca2cefd7a42fefb4c36c31780dabc1944 Mon Sep 17 00:00:00 2001 From: James Stembridge Date: Fri, 14 Mar 2003 12:14:10 +0000 Subject: Import post processing code from ffmpeg CVS patchset: 4405 CVS date: 2003/03/14 12:14:10 --- src/libffmpeg/libavcodec/libpostproc/Makefile.am | 29 + src/libffmpeg/libavcodec/libpostproc/mangle.h | 19 + src/libffmpeg/libavcodec/libpostproc/postprocess.c | 851 ++++++ src/libffmpeg/libavcodec/libpostproc/postprocess.h | 73 + .../libavcodec/libpostproc/postprocess_internal.h | 128 + .../libavcodec/libpostproc/postprocess_template.c | 3127 ++++++++++++++++++++ 6 files changed, 4227 insertions(+) create mode 100644 src/libffmpeg/libavcodec/libpostproc/Makefile.am create mode 100644 src/libffmpeg/libavcodec/libpostproc/mangle.h create mode 100644 src/libffmpeg/libavcodec/libpostproc/postprocess.c create mode 100644 src/libffmpeg/libavcodec/libpostproc/postprocess.h create mode 100644 src/libffmpeg/libavcodec/libpostproc/postprocess_internal.h create mode 100644 src/libffmpeg/libavcodec/libpostproc/postprocess_template.c diff --git a/src/libffmpeg/libavcodec/libpostproc/Makefile.am b/src/libffmpeg/libavcodec/libpostproc/Makefile.am new file mode 100644 index 000000000..10328eeff --- /dev/null +++ b/src/libffmpeg/libavcodec/libpostproc/Makefile.am @@ -0,0 +1,29 @@ +AM_CFLAGS = $(LIBFFMPEG_CFLAGS) +ASFLAGS = + +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic + +noinst_LTLIBRARIES = libpostprocess.la + +EXTRA_DIST = postprocess_template.c + +libpostprocess_la_SOURCES = postprocess.c + +noinst_HEADERS = mangle.h postprocess.h postprocess_internal.h + +.s.lo: + $(ASCOMPILE) -o $@ `test -f $< || echo '$(srcdir)/'`$< + +debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(LIBFFMPEG_CFLAGS)" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/libffmpeg/libavcodec/libpostproc/mangle.h b/src/libffmpeg/libavcodec/libpostproc/mangle.h new file mode 100644 index 000000000..5f5dc4849 --- /dev/null +++ b/src/libffmpeg/libavcodec/libpostproc/mangle.h @@ -0,0 +1,19 @@ +/* mangle.h - This file has some CPP macros to deal with different symbol + * mangling across binary formats. + * (c)2002 by Felix Buenemann + * File licensed under the GPL, see http://www.fsf.org/ for more info. + */ + +#ifndef __MANGLE_H +#define __MANGLE_H + +/* Feel free to add more to the list, eg. a.out IMO */ +#if defined(__CYGWIN__) || defined(__OS2__) || \ + (defined(__OpenBSD__) && !defined(__ELF__)) +#define MANGLE(a) "_" #a +#else +#define MANGLE(a) #a +#endif + +#endif /* !__MANGLE_H */ + diff --git a/src/libffmpeg/libavcodec/libpostproc/postprocess.c b/src/libffmpeg/libavcodec/libpostproc/postprocess.c new file mode 100644 index 000000000..130bb36c6 --- /dev/null +++ b/src/libffmpeg/libavcodec/libpostproc/postprocess.c @@ -0,0 +1,851 @@ +/* + Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at) + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + C MMX MMX2 3DNow +isVertDC Ec Ec +isVertMinMaxOk Ec Ec +doVertLowPass E e e +doVertDefFilter Ec Ec e e +isHorizDC Ec Ec +isHorizMinMaxOk a E +doHorizLowPass E e e +doHorizDefFilter Ec Ec e e +deRing E e e* +Vertical RKAlgo1 E a a +Horizontal RKAlgo1 a a +Vertical X1# a E E +Horizontal X1# a E E +LinIpolDeinterlace e E E* +CubicIpolDeinterlace a e e* +LinBlendDeinterlace e E E* +MedianDeinterlace# E Ec Ec +TempDeNoiser# E e e + +* i dont have a 3dnow CPU -> its untested, but noone said it doesnt work so it seems to work +# more or less selfinvented filters so the exactness isnt too meaningfull +E = Exact implementation +e = allmost exact implementation (slightly different rounding,...) +a = alternative / approximate impl +c = checked against the other implementations (-vo md5) +*/ + +/* +TODO: +reduce the time wasted on the mem transfer +unroll stuff if instructions depend too much on the prior one +move YScale thing to the end instead of fixing QP +write a faster and higher quality deblocking filter :) +make the mainloop more flexible (variable number of blocks at once + (the if/else stuff per block is slowing things down) +compare the quality & speed of all filters +split this huge file +optimize c versions +try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks +... +*/ + +//Changelog: use the CVS log + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "xineutils.h" + +#ifdef HAVE_MALLOC_H +#include +#endif +//#undef HAVE_MMX2 +//#define HAVE_3DNOW +//#undef HAVE_MMX +//#undef ARCH_X86 +//#define DEBUG_BRIGHTNESS + +#define memcpy(a,b,c) xine_fast_memcpy(a,b,c) + +#include "postprocess.h" +#include "postprocess_internal.h" + +#include "mangle.h" //FIXME should be supressed + +#ifndef HAVE_MEMALIGN +#define memalign(a,b) malloc(b) +#endif + +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) < (b) ? (b) : (a)) +#define ABS(a) ((a) > 0 ? (a) : (-(a))) +#define SIGN(a) ((a) > 0 ? 1 : -1) + +#define GET_MODE_BUFFER_SIZE 500 +#define OPTIONS_ARRAY_SIZE 10 +#define BLOCK_SIZE 8 +#define TEMP_STRIDE 8 +//#define NUM_BLOCKS_AT_ONCE 16 //not used yet + +#ifdef ARCH_X86 +static uint64_t __attribute__((aligned(8))) w05= 0x0005000500050005LL; +static uint64_t __attribute__((aligned(8))) w20= 0x0020002000200020LL; +static uint64_t __attribute__((aligned(8))) b00= 0x0000000000000000LL; +static uint64_t __attribute__((aligned(8))) b01= 0x0101010101010101LL; +static uint64_t __attribute__((aligned(8))) b02= 0x0202020202020202LL; +static uint64_t __attribute__((aligned(8))) b08= 0x0808080808080808LL; +static uint64_t __attribute__((aligned(8))) b80= 0x8080808080808080LL; +#endif + +static int verbose= 0; + +static const int deringThreshold= 20; + + +static struct PPFilter filters[]= +{ + {"hb", "hdeblock", 1, 1, 3, H_DEBLOCK}, + {"vb", "vdeblock", 1, 2, 4, V_DEBLOCK}, +/* {"hr", "rkhdeblock", 1, 1, 3, H_RK1_FILTER}, + {"vr", "rkvdeblock", 1, 2, 4, V_RK1_FILTER},*/ + {"h1", "x1hdeblock", 1, 1, 3, H_X1_FILTER}, + {"v1", "x1vdeblock", 1, 2, 4, V_X1_FILTER}, + {"dr", "dering", 1, 5, 6, DERING}, + {"al", "autolevels", 0, 1, 2, LEVEL_FIX}, + {"lb", "linblenddeint", 1, 1, 4, LINEAR_BLEND_DEINT_FILTER}, + {"li", "linipoldeint", 1, 1, 4, LINEAR_IPOL_DEINT_FILTER}, + {"ci", "cubicipoldeint", 1, 1, 4, CUBIC_IPOL_DEINT_FILTER}, + {"md", "mediandeint", 1, 1, 4, MEDIAN_DEINT_FILTER}, + {"fd", "ffmpegdeint", 1, 1, 4, FFMPEG_DEINT_FILTER}, + {"tn", "tmpnoise", 1, 7, 8, TEMP_NOISE_FILTER}, + {"fq", "forcequant", 1, 0, 0, FORCE_QUANT}, + {NULL, NULL,0,0,0,0} //End Marker +}; + +static char *replaceTable[]= +{ + "default", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", + "de", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", + "fast", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", + "fa", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", + NULL //End Marker +}; + +#ifdef ARCH_X86 +static inline void unusedVariableWarningFixer() +{ + if(w05 + w20 + b00 + b01 + b02 + b08 + b80 == 0) b00=0; +} +#endif + + +// The horizontal Functions exist only in C cuz the MMX code is faster with vertical filters and transposing + +/** + * Check if the given 8x8 Block is mostly "flat" + */ +static inline int isHorizDC(uint8_t src[], int stride, PPContext *c) +{ + int numEq= 0; + int y; + const int dcOffset= ((c->QP*c->ppMode.baseDcDiff)>>8) + 1; + const int dcThreshold= dcOffset*2 + 1; + for(y=0; y c->ppMode.flatnessThreshold; +} + +/** + * Check if the middle 8x8 Block in the given 8x16 block is flat + */ +static inline int isVertDC_C(uint8_t src[], int stride, PPContext *c){ + int numEq= 0; + int y; + const int dcOffset= ((c->QP*c->ppMode.baseDcDiff)>>8) + 1; + const int dcThreshold= dcOffset*2 + 1; + src+= stride*4; // src points to begin of the 8x8 Block + for(y=0; y c->ppMode.flatnessThreshold; +} + +static inline int isHorizMinMaxOk(uint8_t src[], int stride, int QP) +{ + if(abs(src[0] - src[7]) > 2*QP) return 0; + + return 1; +} + +static inline void doHorizDefFilter(uint8_t dst[], int stride, int QP) +{ + int y; + for(y=0; y> 6; + d*= SIGN(-middleEnergy); + + if(q>0) + { + d= d<0 ? 0 : d; + d= d>q ? q : d; + } + else + { + d= d>0 ? 0 : d; + d= d>4; + dst[1]= ((dst[1]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4; + dst[2]= ((dst[2]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4; + dst[3]= ((dst[3]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4; + dst[4]= ((dst[4]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4; + dst[5]= ((dst[5]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4; + dst[6]= (((last + dst[6])<<2) + ((dst[7] + sums[5])<<1) + sums[3] + 8)>>4; + dst[7]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4; + + dst+= stride; + } +} + +/** + * Experimental Filter 1 (Horizontal) + * will not damage linear gradients + * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter + * can only smooth blocks at the expected locations (it cant smooth them if they did move) + * MMX2 version does correct clipping C version doesnt + * not identical with the vertical one + */ +static inline void horizX1Filter(uint8_t *src, int stride, int QP) +{ + int y; + static uint64_t *lut= NULL; + if(lut==NULL) + { + int i; + lut= (uint64_t*)memalign(8, 256*8); + for(i=0; i<256; i++) + { + int v= i < 128 ? 2*i : 2*(i-256); +/* +//Simulate 112242211 9-Tap filter + uint64_t a= (v/16) & 0xFF; + uint64_t b= (v/8) & 0xFF; + uint64_t c= (v/4) & 0xFF; + uint64_t d= (3*v/8) & 0xFF; +*/ +//Simulate piecewise linear interpolation + uint64_t a= (v/16) & 0xFF; + uint64_t b= (v*3/16) & 0xFF; + uint64_t c= (v*5/16) & 0xFF; + uint64_t d= (7*v/16) & 0xFF; + uint64_t A= (0x100 - a)&0xFF; + uint64_t B= (0x100 - b)&0xFF; + uint64_t C= (0x100 - c)&0xFF; + uint64_t D= (0x100 - c)&0xFF; + + lut[i] = (a<<56) | (b<<48) | (c<<40) | (d<<32) | + (D<<24) | (C<<16) | (B<<8) | (A); + //lut[i] = (v<<32) | (v<<24); + } + } + + for(y=0; yppMode= *ppMode; //FIXME + + // useing ifs here as they are faster than function pointers allthough the + // difference wouldnt be messureable here but its much better because + // someone might exchange the cpu whithout restarting mplayer ;) +#ifdef RUNTIME_CPUDETECT +#ifdef ARCH_X86 + // ordered per speed fasterst first + if(c->cpuCaps & PP_CPU_CAPS_MMX2) + postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); + else if(c->cpuCaps & PP_CPU_CAPS_3DNOW) + postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); + else if(c->cpuCaps & PP_CPU_CAPS_MMX) + postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); + else + postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); +#else + postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); +#endif +#else //RUNTIME_CPUDETECT +#ifdef HAVE_MMX2 + postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); +#elif defined (HAVE_3DNOW) + postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); +#elif defined (HAVE_MMX) + postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); +#else + postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); +#endif +#endif //!RUNTIME_CPUDETECT +} + +//static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, +// QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode); + +/* -pp Command line Help +*/ +char *pp_help= +"[: