2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "cpudetect.h"
27 #include "img_format.h"
31 #include "libvo/fastmemcpy.h"
40 #if HAVE_MMX && HAVE_EBX_AVAILABLE
41 static int diff_MMX(unsigned char *old
, unsigned char *new, int os
, int ns
)
43 volatile short out
[4];
46 "pxor %%mm4, %%mm4 \n\t"
47 "pxor %%mm7, %%mm7 \n\t"
52 "movq (%%"REG_S
"), %%mm0 \n\t"
53 "movq (%%"REG_S
"), %%mm2 \n\t"
54 "add %%"REG_a
", %%"REG_S
" \n\t"
55 "movq (%%"REG_D
"), %%mm1 \n\t"
56 "add %%"REG_b
", %%"REG_D
" \n\t"
57 "psubusb %%mm1, %%mm2 \n\t"
58 "psubusb %%mm0, %%mm1 \n\t"
59 "movq %%mm2, %%mm0 \n\t"
60 "movq %%mm1, %%mm3 \n\t"
61 "punpcklbw %%mm7, %%mm0 \n\t"
62 "punpcklbw %%mm7, %%mm1 \n\t"
63 "punpckhbw %%mm7, %%mm2 \n\t"
64 "punpckhbw %%mm7, %%mm3 \n\t"
65 "paddw %%mm0, %%mm4 \n\t"
66 "paddw %%mm1, %%mm4 \n\t"
67 "paddw %%mm2, %%mm4 \n\t"
68 "paddw %%mm3, %%mm4 \n\t"
72 "movq %%mm4, (%%"REG_d
") \n\t"
75 : "S" (old
), "D" (new), "a" ((long)os
), "b" ((long)ns
), "d" (out
)
78 return out
[0]+out
[1]+out
[2]+out
[3];
82 static int diff_C(unsigned char *old
, unsigned char *new, int os
, int ns
)
87 d
+= abs(new[x
] - old
[x
]);
95 static int (*diff
)(unsigned char *, unsigned char *, int, int);
97 static int diff_to_drop_plane(int hi
, int lo
, float frac
, unsigned char *old
, unsigned char *new, int w
, int h
, int os
, int ns
)
101 int t
= (w
/16)*(h
/16)*frac
;
102 for (y
= 0; y
< h
-7; y
+= 4) {
103 for (x
= 8; x
< w
-7; x
+= 4) {
104 d
= diff(old
+x
+y
*os
, new+x
+y
*ns
, os
, ns
);
105 if (d
> hi
) return 0;
115 static int diff_to_drop(int hi
, int lo
, float frac
, mp_image_t
*old
, mp_image_t
*new)
117 if (new->flags
& MP_IMGFLAG_PLANAR
) {
118 return diff_to_drop_plane(hi
,lo
,frac
, old
->planes
[0], new->planes
[0],
119 new->w
, new->h
, old
->stride
[0], new->stride
[0])
120 && diff_to_drop_plane(hi
,lo
,frac
, old
->planes
[1], new->planes
[1],
121 new->chroma_width
, new->chroma_height
,
122 old
->stride
[1], new->stride
[1])
123 && diff_to_drop_plane(hi
,lo
,frac
, old
->planes
[2], new->planes
[2],
124 new->chroma_width
, new->chroma_height
,
125 old
->stride
[2], new->stride
[2]);
127 return diff_to_drop_plane(hi
,lo
,frac
, old
->planes
[0], new->planes
[0],
128 new->w
*(new->bpp
/8), new->h
, old
->stride
[0], new->stride
[0]);
131 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
)
135 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
136 MP_IMGTYPE_STATIC
, MP_IMGFLAG_ACCEPT_STRIDE
|
137 MP_IMGFLAG_PRESERVE
| MP_IMGFLAG_READABLE
,
138 mpi
->width
, mpi
->height
);
139 dmpi
->qscale
= mpi
->qscale
;
140 dmpi
->qstride
= mpi
->qstride
;
141 dmpi
->qscale_type
= mpi
->qscale_type
;
143 if (diff_to_drop(vf
->priv
->hi
, vf
->priv
->lo
, vf
->priv
->frac
, dmpi
, mpi
)) {
144 if (vf
->priv
->max
== 0)
146 else if ((vf
->priv
->max
> 0) && (vf
->priv
->cnt
++ < vf
->priv
->max
))
148 else if ((vf
->priv
->max
< 0) && (vf
->priv
->last
+1 >= -vf
->priv
->max
))
149 return vf
->priv
->last
=0;
154 memcpy_pic(dmpi
->planes
[0], mpi
->planes
[0], mpi
->w
, mpi
->h
,
155 dmpi
->stride
[0], mpi
->stride
[0]);
156 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
157 memcpy_pic(dmpi
->planes
[1], mpi
->planes
[1],
158 mpi
->chroma_width
, mpi
->chroma_height
,
159 dmpi
->stride
[1], mpi
->stride
[1]);
160 memcpy_pic(dmpi
->planes
[2], mpi
->planes
[2],
161 mpi
->chroma_width
, mpi
->chroma_height
,
162 dmpi
->stride
[2], mpi
->stride
[2]);
164 return vf_next_put_image(vf
, dmpi
, pts
);
167 static void uninit(struct vf_instance
*vf
)
172 static int vf_open(vf_instance_t
*vf
, char *args
)
175 vf
->put_image
= put_image
;
177 vf
->default_reqs
= VFCAP_ACCEPT_STRIDE
;
178 vf
->priv
= p
= calloc(1, sizeof(struct vf_priv_s
));
183 if (args
) sscanf(args
, "%d:%d:%d:%f", &p
->max
, &p
->hi
, &p
->lo
, &p
->frac
);
185 #if HAVE_MMX && HAVE_EBX_AVAILABLE
186 if(gCpuCaps
.hasMMX
) diff
= diff_MMX
;
191 const vf_info_t vf_info_decimate
= {
192 "near-duplicate frame remover",