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 + -
显示快捷键?