vf_filmdint.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,447 行 · 第 1/3 页

C
1,447
字号
#include <uclib.h>#include <uclib.h>#include <uclib.h>#include <signal.h>#include <sys/time.h>#include "config.h"#include "mp_msg.h"#include "cpudetect.h"#include "img_format.h"#include "mp_image.h"#include "vf.h"#include "cmmx.h"#include "libvo/fastmemcpy.h"#define NUM_STORED 4enum pu_field_type_t {    PU_1ST_OF_3,    PU_2ND_OF_3,    PU_3RD_OF_3,    PU_1ST_OF_2,    PU_2ND_OF_2,    PU_INTERLACED};struct metrics {    /* This struct maps to a packed word 64-bit MMX register */    unsigned short int even;    unsigned short int odd;    unsigned short int noise;    unsigned short int temp;} __attribute__ ((aligned (8)));struct frame_stats {    struct metrics tiny, low, high, bigger, twox, max;    struct { unsigned int even, odd, noise, temp; } sad;    unsigned short interlaced_high;    unsigned short interlaced_low;    unsigned short num_blocks;};struct vf_priv_s {    unsigned long inframes;    unsigned long outframes;    enum pu_field_type_t prev_type;    unsigned swapped, chroma_swapped;    unsigned luma_only;    unsigned verbose;    unsigned fast;    unsigned long w, h, cw, ch, stride, chroma_stride, nplanes;    unsigned long sad_thres;    unsigned long dint_thres;    unsigned char *memory_allocated;    unsigned char *planes[2*NUM_STORED][4];    unsigned char **old_planes;    unsigned long static_idx;    unsigned long temp_idx;    unsigned long crop_x, crop_y, crop_cx, crop_cy;    unsigned long export_count, merge_count;    unsigned long num_breaks;    unsigned long num_copies;    long in_inc, out_dec, iosync;    long num_fields;    long prev_fields;    long notout;    long mmx2;    unsigned small_bytes[2];    unsigned mmx_temp[2];    struct frame_stats stats[2];    struct metrics thres;    char chflag;    double diff_time, merge_time, decode_time, vo_time, filter_time;};#define PPZ { 2000, 2000, 0, 2000 }#define PPR { 2000, 2000, 0, 2000 }static const struct frame_stats ppzs = {PPZ,PPZ,PPZ,PPZ,PPZ,PPZ,PPZ,0,0,9999};static const struct frame_stats pprs = {PPR,PPR,PPR,PPR,PPR,PPR,PPR,0,0,9999};extern int opt_screen_size_x;extern int opt_screen_size_y;#ifndef MIN#define        MIN(a,b) (((a)<(b))?(a):(b))#endif#ifndef MAX#define        MAX(a,b) (((a)>(b))?(a):(b))#endif#define PDIFFUB(X,Y,T) "movq "    #X "," #T "\n\t" \		       "psubusb " #Y "," #T "\n\t" \		       "psubusb " #X "," #Y "\n\t" \		       "paddusb " #Y "," #T "\n\t"#define PDIFFUBT(X,Y,T) "movq "    #X "," #T "\n\t" \			"psubusb " #Y "," #T "\n\t" \			"psubusb " #X "," #Y "\n\t" \			"paddusb " #T "," #Y "\n\t"#define PSUMBW(X,T,Z)	"movq " #X "," #T "\n\t" \			"punpcklbw " #Z "," #X "\n\t" \			"punpckhbw " #Z "," #T "\n\t" \			"paddw " #T "," #X "\n\t" \			"movq " #X "," #T "\n\t" \			"psllq $32, " #T "\n\t" \			"paddw " #T "," #X "\n\t" \			"movq " #X "," #T "\n\t" \			"psllq $16, " #T "\n\t" \			"paddw " #T "," #X "\n\t" \			"psrlq $48, " #X "\n\t"#define PSADBW(X,Y,T,Z)	PDIFFUBT(X,Y,T) PSUMBW(Y,T,Z)#define PMAXUB(X,Y) "psubusb " #X "," #Y "\n\tpaddusb " #X "," #Y "\n\t"#define PMAXUW(X,Y) "psubusw " #X "," #Y "\n\tpaddusw " #X "," #Y "\n\t"#define PMINUBT(X,Y,T)	"movq " #Y "," #T "\n\t" \			"psubusb " #X "," #T "\n\t" \			"psubusb " #T "," #Y "\n\t"#define PAVGB(X,Y)	"pavgusb " #X "," #Y "\n\t"static inline voidget_metrics_c(unsigned char *a, unsigned char *b, int as, int bs, int lines,	      struct metrics *m){    a -= as;    b -= bs;    do {	cmmx_t old_po = *(cmmx_t*)(a      );	cmmx_t     po = *(cmmx_t*)(b      );	cmmx_t      e = *(cmmx_t*)(b +   bs);	cmmx_t  old_o = *(cmmx_t*)(a + 2*as);	cmmx_t      o = *(cmmx_t*)(b + 2*bs);	cmmx_t     ne = *(cmmx_t*)(b + 3*bs);	cmmx_t old_no = *(cmmx_t*)(a + 4*as);	cmmx_t     no = *(cmmx_t*)(b + 4*bs);	cmmx_t   qup_old_odd = p31avgb(old_o, old_po);	cmmx_t       qup_odd = p31avgb(    o,     po);	cmmx_t qdown_old_odd = p31avgb(old_o, old_no);	cmmx_t     qdown_odd = p31avgb(    o,     no);	cmmx_t   qup_even = p31avgb(ne, e);	cmmx_t qdown_even = p31avgb(e, ne);	cmmx_t    temp_up_diff = pdiffub(qdown_even, qup_old_odd);	cmmx_t   noise_up_diff = pdiffub(qdown_even, qup_odd);	cmmx_t  temp_down_diff = pdiffub(qup_even, qdown_old_odd);	cmmx_t noise_down_diff = pdiffub(qup_even, qdown_odd);	cmmx_t odd_diff = pdiffub(o, old_o);	m->odd  += psumbw(odd_diff);	m->even += psadbw(e, *(cmmx_t*)(a+as));	temp_up_diff  = pminub(temp_up_diff, temp_down_diff);	temp_up_diff  = pminub(temp_up_diff, odd_diff);	m->temp  += psumbw(temp_up_diff);	noise_up_diff = pminub(noise_up_diff, odd_diff);	noise_up_diff = pminub(noise_up_diff, noise_down_diff);	m->noise += psumbw(noise_up_diff);	a += 2*as;	b += 2*bs;    } while (--lines);}static inline voidget_metrics_fast_c(unsigned char *a, unsigned char *b, int as, int bs,		   int lines, struct metrics *m){    a -= as;    b -= bs;    do {	cmmx_t old_po = (*(cmmx_t*)(a       ) >> 1) & ~SIGN_BITS;	cmmx_t     po = (*(cmmx_t*)(b       ) >> 1) & ~SIGN_BITS;	cmmx_t  old_e = (*(cmmx_t*)(a +   as) >> 1) & ~SIGN_BITS;	cmmx_t      e = (*(cmmx_t*)(b +   bs) >> 1) & ~SIGN_BITS;	cmmx_t  old_o = (*(cmmx_t*)(a + 2*as) >> 1) & ~SIGN_BITS;	cmmx_t      o = (*(cmmx_t*)(b + 2*bs) >> 1) & ~SIGN_BITS;	cmmx_t     ne = (*(cmmx_t*)(b + 3*bs) >> 1) & ~SIGN_BITS;	cmmx_t old_no = (*(cmmx_t*)(a + 4*as) >> 1) & ~SIGN_BITS;	cmmx_t     no = (*(cmmx_t*)(b + 4*bs) >> 1) & ~SIGN_BITS;	cmmx_t   qup_old_odd = p31avgb_s(old_o, old_po);	cmmx_t       qup_odd = p31avgb_s(    o,     po);	cmmx_t qdown_old_odd = p31avgb_s(old_o, old_no);	cmmx_t     qdown_odd = p31avgb_s(    o,     no);	cmmx_t   qup_even = p31avgb_s(ne, e);	cmmx_t qdown_even = p31avgb_s(e, ne);	cmmx_t    temp_up_diff = pdiffub_s(qdown_even, qup_old_odd);	cmmx_t   noise_up_diff = pdiffub_s(qdown_even, qup_odd);	cmmx_t  temp_down_diff = pdiffub_s(qup_even, qdown_old_odd);	cmmx_t noise_down_diff = pdiffub_s(qup_even, qdown_odd);	cmmx_t odd_diff = pdiffub_s(o, old_o);	m->odd  += psumbw_s(odd_diff) << 1;	m->even += psadbw_s(e, old_e) << 1;	temp_up_diff  = pminub_s(temp_up_diff, temp_down_diff);	temp_up_diff  = pminub_s(temp_up_diff, odd_diff);	m->temp      += psumbw_s(temp_up_diff) << 1;	noise_up_diff = pminub_s(noise_up_diff, odd_diff);	noise_up_diff = pminub_s(noise_up_diff, noise_down_diff);	m->noise += psumbw_s(noise_up_diff) << 1;	a += 2*as;	b += 2*bs;    } while (--lines);}static inline voidget_metrics_faster_c(unsigned char *a, unsigned char *b, int as, int bs,		   int lines, struct metrics *m){    a -= as;    b -= bs;    do {	cmmx_t old_po = (*(cmmx_t*)(a       )>>1) & ~SIGN_BITS;	cmmx_t     po = (*(cmmx_t*)(b       )>>1) & ~SIGN_BITS;	cmmx_t  old_e = (*(cmmx_t*)(a +   as)>>1) & ~SIGN_BITS;	cmmx_t      e = (*(cmmx_t*)(b +   bs)>>1) & ~SIGN_BITS;	cmmx_t  old_o = (*(cmmx_t*)(a + 2*as)>>1) & ~SIGN_BITS;	cmmx_t      o = (*(cmmx_t*)(b + 2*bs)>>1) & ~SIGN_BITS;	cmmx_t     ne = (*(cmmx_t*)(b + 3*bs)>>1) & ~SIGN_BITS;	cmmx_t  down_even = p31avgb_s(e, ne);	cmmx_t     up_odd = p31avgb_s(o, po);	cmmx_t up_old_odd = p31avgb_s(old_o, old_po);	cmmx_t   odd_diff = pdiffub_s(o, old_o);	cmmx_t  temp_diff = pdiffub_s(down_even, up_old_odd);	cmmx_t noise_diff = pdiffub_s(down_even, up_odd);	m->even += psadbw_s(e, old_e) << 1;	m->odd  += psumbw_s(odd_diff) << 1;	temp_diff  = pminub_s(temp_diff, odd_diff);	noise_diff = pminub_s(noise_diff, odd_diff);	m->noise += psumbw_s(noise_diff) << 1;	m->temp  += psumbw_s(temp_diff) << 1;	a += 2*as;	b += 2*bs;    } while (--lines);    }static inline voidget_block_stats(struct metrics *m, struct vf_priv_s *p, struct frame_stats *s){    unsigned two_e = m->even  + MAX(m->even , p->thres.even );    unsigned two_o = m->odd   + MAX(m->odd  , p->thres.odd  );    unsigned two_n = m->noise + MAX(m->noise, p->thres.noise);    unsigned two_t = m->temp  + MAX(m->temp , p->thres.temp );    unsigned e_big   = m->even  >= (m->odd   + two_o + 1)/2;    unsigned o_big   = m->odd   >= (m->even  + two_e + 1)/2;    unsigned n_big   = m->noise >= (m->temp  + two_t + 1)/2;    unsigned t_big   = m->temp  >= (m->noise + two_n + 1)/2;    unsigned e2x     = m->even  >= two_o;    unsigned o2x     = m->odd   >= two_e;    unsigned n2x     = m->noise >= two_t;    unsigned t2x     = m->temp  >= two_n;    unsigned ntiny_e = m->even  > p->thres.even ;    unsigned ntiny_o = m->odd   > p->thres.odd  ;    unsigned ntiny_n = m->noise > p->thres.noise;    unsigned ntiny_t = m->temp  > p->thres.temp ;    unsigned nlow_e  = m->even  > 2*p->thres.even ;    unsigned nlow_o  = m->odd   > 2*p->thres.odd  ;    unsigned nlow_n  = m->noise > 2*p->thres.noise;    unsigned nlow_t  = m->temp  > 2*p->thres.temp ;    unsigned high_e  = m->even  > 4*p->thres.even ;    unsigned high_o  = m->odd   > 4*p->thres.odd  ;    unsigned high_n  = m->noise > 4*p->thres.noise;    unsigned high_t  = m->temp  > 4*p->thres.temp ;    unsigned low_il  = !n_big && !t_big && ntiny_n && ntiny_t;    unsigned high_il = !n_big && !t_big && nlow_n  && nlow_t;    if (low_il | high_il) {	s->interlaced_low  += low_il;	s->interlaced_high += high_il;    } else {	s->tiny.even  += ntiny_e;	s->tiny.odd   += ntiny_o;	s->tiny.noise += ntiny_n;	s->tiny.temp  += ntiny_t;	s->low .even  += nlow_e ;	s->low .odd   += nlow_o ;	s->low .noise += nlow_n ;	s->low .temp  += nlow_t ;	s->high.even  += high_e ;	s->high.odd   += high_o ;	s->high.noise += high_n ;	s->high.temp  += high_t ;	if (m->even  >=	p->sad_thres) s->sad.even  += m->even ;	if (m->odd   >=	p->sad_thres) s->sad.odd   += m->odd  ;	if (m->noise >=	p->sad_thres) s->sad.noise += m->noise;	if (m->temp  >=	p->sad_thres) s->sad.temp  += m->temp ;    }    s->num_blocks++;    s->max.even  = MAX(s->max.even , m->even );    s->max.odd   = MAX(s->max.odd  , m->odd  );    s->max.noise = MAX(s->max.noise, m->noise);    s->max.temp  = MAX(s->max.temp , m->temp );    s->bigger.even  += e_big  ;    s->bigger.odd   += o_big  ;    s->bigger.noise += n_big  ;    s->bigger.temp  += t_big  ;    s->twox.even  += e2x    ;    s->twox.odd   += o2x    ;    s->twox.noise += n2x    ;    s->twox.temp  += t2x    ;}static inline struct metricsblock_metrics_c(unsigned char *a, unsigned char *b, int as, int bs,		int lines, struct vf_priv_s *p, struct frame_stats *s){    struct metrics tm;    tm.even = tm.odd = tm.noise = tm.temp = 0;    get_metrics_c(a, b, as, bs, lines, &tm);    if (sizeof(cmmx_t) < 8)	get_metrics_c(a+4, b+4, as, bs, lines, &tm);    get_block_stats(&tm, p, s);    return tm;}static inline struct metricsblock_metrics_fast_c(unsigned char *a, unsigned char *b, int as, int bs,		int lines, struct vf_priv_s *p, struct frame_stats *s){    struct metrics tm;    tm.even = tm.odd = tm.noise = tm.temp = 0;    get_metrics_fast_c(a, b, as, bs, lines, &tm);    if (sizeof(cmmx_t) < 8)	get_metrics_fast_c(a+4, b+4, as, bs, lines, &tm);    get_block_stats(&tm, p, s);    return tm;}static inline struct metricsblock_metrics_faster_c(unsigned char *a, unsigned char *b, int as, int bs,		int lines, struct vf_priv_s *p, struct frame_stats *s){    struct metrics tm;    tm.even = tm.odd = tm.noise = tm.temp = 0;    get_metrics_faster_c(a, b, as, bs, lines, &tm);    if (sizeof(cmmx_t) < 8)	get_metrics_faster_c(a+4, b+4, as, bs, lines, &tm);    get_block_stats(&tm, p, s);    return tm;}#define MEQ(X,Y) ((X).even == (Y).even && (X).odd == (Y).odd && (X).temp == (Y).temp && (X).noise == (Y).noise)#define BLOCK_METRICS_TEMPLATE() \    asm volatile("pxor %mm7, %mm7\n\t"   /* The result is colleted in mm7 */ \		 "pxor %mm6, %mm6\n\t"   /* Temp to stay at 0 */	     \	);								     \    a -= as;								     \    b -= bs;								     \    do {								     \	asm volatile(							     \	    "movq (%0,%2), %%mm0\n\t"					     \	    "movq (%1,%3), %%mm1\n\t"   /* mm1 = even */		     \	    PSADBW(%%mm1, %%mm0, %%mm4, %%mm6)				     \	    "paddusw %%mm0, %%mm7\n\t"  /* even diff */			     \	    "movq (%0,%2,2), %%mm0\n\t" /* mm0 = old odd */		     \	    "movq (%1,%3,2), %%mm2\n\t" /* mm2 = odd */			     \	    "movq (%0), %%mm3\n\t"					     \	    "psubusb %4, %%mm3\n\t"					     \	    PAVGB(%%mm0, %%mm3)						     \	    PAVGB(%%mm0, %%mm3)    /* mm3 = qup old odd */		     \	    "movq %%mm0, %%mm5\n\t"					     \	    PSADBW(%%mm2, %%mm0, %%mm4, %%mm6)				     \	    "psllq $16, %%mm0\n\t"					     \	    "paddusw %%mm0, %%mm7\n\t"					     \	    "movq (%1), %%mm4\n\t"					     \	    "lea (%0,%2,2), %0\n\t"					     \	    "lea (%1,%3,2), %1\n\t"					     \	    "psubusb %4, %%mm4\n\t"					     \	    PAVGB(%%mm2, %%mm4)						     \	    PAVGB(%%mm2, %%mm4)    /* mm4 = qup odd */			     \	    PDIFFUBT(%%mm5, %%mm2, %%mm0) /* mm2 =abs(oldodd-odd) */	     \	    "movq (%1,%3), %%mm5\n\t"					     \	    "psubusb %4, %%mm5\n\t"					     \	    PAVGB(%%mm1, %%mm5)						     \	    PAVGB(%%mm5, %%mm1)    /* mm1 = qdown even */		     \	    PAVGB((%1,%3), %%mm5)  /* mm5 = qup next even */		     \	    PDIFFUBT(%%mm1, %%mm3, %%mm0) /* mm3 = abs(qupoldo-qde) */	     \	    PDIFFUBT(%%mm1, %%mm4, %%mm0) /* mm4 = abs(qupodd-qde) */	     \	    PMINUBT(%%mm2, %%mm3, %%mm0)  /* limit temp to odd diff */	     \	    PMINUBT(%%mm2, %%mm4, %%mm0)  /* limit noise to odd diff */	     \	    "movq (%1,%3,2), %%mm2\n\t"					     \	    "psubusb %4, %%mm2\n\t"					     \	    PAVGB((%1), %%mm2)						     \	    PAVGB((%1), %%mm2)    /* mm2 = qdown odd */			     \	    "movq (%0,%2,2), %%mm1\n\t"					     \	    "psubusb %4, %%mm1\n\t"					     \	    PAVGB((%0), %%mm1)						     \	    PAVGB((%0), %%mm1)  /* mm1 = qdown old odd */		     \	    PDIFFUBT(%%mm5, %%mm2, %%mm0) /* mm2 = abs(qdo-qune) */	     \	    PDIFFUBT(%%mm5, %%mm1, %%mm0) /* mm1 = abs(qdoo-qune) */	     \	    PMINUBT(%%mm4, %%mm2, %%mm0)  /* current */			     \	    PMINUBT(%%mm3, %%mm1, %%mm0)  /* old */			     \	    PSUMBW(%%mm2, %%mm0, %%mm6)					     \	    PSUMBW(%%mm1, %%mm0, %%mm6)					     \	    "psllq $32, %%mm2\n\t"					     \	    "psllq $48, %%mm1\n\t"					     \	    "paddusw %%mm2, %%mm7\n\t"					     \	    "paddusw %%mm1, %%mm7\n\t"					     \	    : "=r" (a), "=r" (b)					     \	    : "r"((long)as), "r"((long)bs), "m" (ones), "0"(a), "1"(b), "X"(*a), "X"(*b) \	    );								     \    } while (--lines);static inline struct metricsblock_metrics_3dnow(unsigned char *a, unsigned char *b, int as, int bs,		    int lines, struct vf_priv_s *p, struct frame_stats *s){    struct metrics tm;#ifndef HAVE_3DNOW    mp_msg(MSGT_VFILTER, MSGL_FATAL, "block_metrics_3dnow: internal error\n");#else    static const unsigned long long ones = 0x0101010101010101ull;    BLOCK_METRICS_TEMPLATE();    asm volatile("movq %%mm7, %0\n\temms" : "=m" (tm));    get_block_stats(&tm, p, s);#endif    return tm;}#undef PSUMBW#undef PSADBW#undef PMAXUB#undef PMINUBT#undef PAVGB#define PSUMBW(X,T,Z)	"psadbw " #Z "," #X "\n\t"#define PSADBW(X,Y,T,Z) "psadbw " #X "," #Y "\n\t"#define PMAXUB(X,Y)	"pmaxub " #X "," #Y "\n\t"#define PMINUBT(X,Y,T)	"pminub " #X "," #Y "\n\t"#define PAVGB(X,Y)	"pavgb "  #X "," #Y "\n\t"static inline struct metricsblock_metrics_mmx2(unsigned char *a, unsigned char *b, int as, int bs,		   int lines, struct vf_priv_s *p, struct frame_stats *s){    struct metrics tm;#ifndef HAVE_MMX    mp_msg(MSGT_VFILTER, MSGL_FATAL, "block_metrics_mmx2: internal error\n");#else    static const unsigned long long ones = 0x0101010101010101ull;    unsigned long interlaced;    unsigned long prefetch_line = (((long)a>>3) & 7) + 10;#ifdef DEBUG    struct frame_stats ts = *s;#endif    asm volatile("prefetcht0 (%0,%2)\n\t"		 "prefetcht0 (%1,%3)\n\t" :		 : "r" (a), "r" (b),		 "r" (prefetch_line * as), "r" (prefetch_line * bs));    BLOCK_METRICS_TEMPLATE();    s->num_blocks++;    asm volatile(

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?