Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * This file is part of MPlayer. | |
3 | * | |
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. | |
8 | * | |
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. | |
13 | * | |
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. | |
17 | */ | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <inttypes.h> | |
23 | ||
24 | #include "config.h" | |
25 | #include "mp_msg.h" | |
26 | #include "cpudetect.h" | |
27 | ||
28 | #include "img_format.h" | |
29 | #include "mp_image.h" | |
30 | #include "vf.h" | |
31 | ||
32 | #include "libvo/video_out.h" | |
33 | ||
34 | struct vf_priv_s { | |
35 | unsigned char *buf; | |
36 | int brightness; | |
37 | int contrast; | |
38 | }; | |
39 | ||
f6fa7814 | 40 | #if HAVE_MMX_INLINE && HAVE_6REGS |
2ba45a60 DM |
41 | static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride, |
42 | int w, int h, int brightness, int contrast) | |
43 | { | |
44 | int i; | |
45 | int pel; | |
46 | int dstep = dstride-w; | |
47 | int sstep = sstride-w; | |
48 | short brvec[4]; | |
49 | short contvec[4]; | |
50 | ||
51 | contrast = ((contrast+100)*256*16)/100; | |
52 | brightness = ((brightness+100)*511)/200-128 - contrast/32; | |
53 | ||
54 | brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness; | |
55 | contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast; | |
56 | ||
57 | while (h--) { | |
58 | __asm__ volatile ( | |
59 | "movq (%5), %%mm3 \n\t" | |
60 | "movq (%6), %%mm4 \n\t" | |
61 | "pxor %%mm0, %%mm0 \n\t" | |
62 | "movl %4, %%eax\n\t" | |
63 | ASMALIGN(4) | |
64 | "1: \n\t" | |
65 | "movq (%0), %%mm1 \n\t" | |
66 | "movq (%0), %%mm2 \n\t" | |
67 | "punpcklbw %%mm0, %%mm1 \n\t" | |
68 | "punpckhbw %%mm0, %%mm2 \n\t" | |
69 | "psllw $4, %%mm1 \n\t" | |
70 | "psllw $4, %%mm2 \n\t" | |
71 | "pmulhw %%mm4, %%mm1 \n\t" | |
72 | "pmulhw %%mm4, %%mm2 \n\t" | |
73 | "paddw %%mm3, %%mm1 \n\t" | |
74 | "paddw %%mm3, %%mm2 \n\t" | |
75 | "packuswb %%mm2, %%mm1 \n\t" | |
76 | "add $8, %0 \n\t" | |
77 | "movq %%mm1, (%1) \n\t" | |
78 | "add $8, %1 \n\t" | |
79 | "decl %%eax \n\t" | |
80 | "jnz 1b \n\t" | |
81 | : "=r" (src), "=r" (dest) | |
82 | : "0" (src), "1" (dest), "r" (w>>3), "r" (brvec), "r" (contvec) | |
83 | : "%eax" | |
84 | ); | |
85 | ||
86 | for (i = w&7; i; i--) | |
87 | { | |
88 | pel = ((*src++* contrast)>>12) + brightness; | |
89 | if(pel&768) pel = (-pel)>>31; | |
90 | *dest++ = pel; | |
91 | } | |
92 | ||
93 | src += sstep; | |
94 | dest += dstep; | |
95 | } | |
96 | __asm__ volatile ( "emms \n\t" ::: "memory" ); | |
97 | } | |
98 | #endif | |
99 | ||
100 | static void process_C(unsigned char *dest, int dstride, unsigned char *src, int sstride, | |
101 | int w, int h, int brightness, int contrast) | |
102 | { | |
103 | int i; | |
104 | int pel; | |
105 | int dstep = dstride-w; | |
106 | int sstep = sstride-w; | |
107 | ||
108 | contrast = ((contrast+100)*256*256)/100; | |
109 | brightness = ((brightness+100)*511)/200-128 - contrast/512; | |
110 | ||
111 | while (h--) { | |
112 | for (i = w; i; i--) | |
113 | { | |
114 | pel = ((*src++* contrast)>>16) + brightness; | |
115 | if(pel&768) pel = (-pel)>>31; | |
116 | *dest++ = pel; | |
117 | } | |
118 | src += sstep; | |
119 | dest += dstep; | |
120 | } | |
121 | } | |
122 | ||
123 | static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int sstride, | |
124 | int w, int h, int brightness, int contrast); | |
125 | ||
126 | /* FIXME: add packed yuv version of process */ | |
127 | ||
128 | static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) | |
129 | { | |
130 | mp_image_t *dmpi; | |
131 | ||
132 | dmpi=ff_vf_get_image(vf->next, mpi->imgfmt, | |
133 | MP_IMGTYPE_EXPORT, 0, | |
134 | mpi->w, mpi->h); | |
135 | ||
136 | dmpi->stride[0] = mpi->stride[0]; | |
137 | dmpi->planes[1] = mpi->planes[1]; | |
138 | dmpi->planes[2] = mpi->planes[2]; | |
139 | dmpi->stride[1] = mpi->stride[1]; | |
140 | dmpi->stride[2] = mpi->stride[2]; | |
141 | ||
142 | if (!vf->priv->buf) vf->priv->buf = malloc(mpi->stride[0]*mpi->h); | |
143 | ||
144 | if ((vf->priv->brightness == 0) && (vf->priv->contrast == 0)) | |
145 | dmpi->planes[0] = mpi->planes[0]; | |
146 | else { | |
147 | dmpi->planes[0] = vf->priv->buf; | |
148 | process(dmpi->planes[0], dmpi->stride[0], | |
149 | mpi->planes[0], mpi->stride[0], | |
150 | mpi->w, mpi->h, vf->priv->brightness, | |
151 | vf->priv->contrast); | |
152 | } | |
153 | ||
154 | return ff_vf_next_put_image(vf,dmpi, pts); | |
155 | } | |
156 | ||
157 | static int control(struct vf_instance *vf, int request, void* data) | |
158 | { | |
159 | vf_equalizer_t *eq; | |
160 | ||
161 | switch (request) { | |
162 | case VFCTRL_SET_EQUALIZER: | |
163 | eq = data; | |
164 | if (!strcmp(eq->item,"brightness")) { | |
165 | vf->priv->brightness = eq->value; | |
166 | return CONTROL_TRUE; | |
167 | } | |
168 | else if (!strcmp(eq->item,"contrast")) { | |
169 | vf->priv->contrast = eq->value; | |
170 | return CONTROL_TRUE; | |
171 | } | |
172 | break; | |
173 | case VFCTRL_GET_EQUALIZER: | |
174 | eq = data; | |
175 | if (!strcmp(eq->item,"brightness")) { | |
176 | eq->value = vf->priv->brightness; | |
177 | return CONTROL_TRUE; | |
178 | } | |
179 | else if (!strcmp(eq->item,"contrast")) { | |
180 | eq->value = vf->priv->contrast; | |
181 | return CONTROL_TRUE; | |
182 | } | |
183 | break; | |
184 | } | |
185 | return ff_vf_next_control(vf, request, data); | |
186 | } | |
187 | ||
188 | static int query_format(struct vf_instance *vf, unsigned int fmt) | |
189 | { | |
190 | switch (fmt) { | |
191 | case IMGFMT_YVU9: | |
192 | case IMGFMT_IF09: | |
193 | case IMGFMT_YV12: | |
194 | case IMGFMT_I420: | |
195 | case IMGFMT_IYUV: | |
196 | case IMGFMT_CLPL: | |
197 | case IMGFMT_Y800: | |
198 | case IMGFMT_Y8: | |
199 | case IMGFMT_NV12: | |
200 | case IMGFMT_NV21: | |
201 | case IMGFMT_444P: | |
202 | case IMGFMT_422P: | |
203 | case IMGFMT_411P: | |
204 | return ff_vf_next_query_format(vf, fmt); | |
205 | } | |
206 | return 0; | |
207 | } | |
208 | ||
209 | static void uninit(struct vf_instance *vf) | |
210 | { | |
211 | free(vf->priv->buf); | |
212 | free(vf->priv); | |
213 | } | |
214 | ||
215 | static int vf_open(vf_instance_t *vf, char *args) | |
216 | { | |
217 | vf->control=control; | |
218 | vf->query_format=query_format; | |
219 | vf->put_image=put_image; | |
220 | vf->uninit=uninit; | |
221 | ||
222 | vf->priv = malloc(sizeof(struct vf_priv_s)); | |
223 | memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
224 | if (args) sscanf(args, "%d:%d", &vf->priv->brightness, &vf->priv->contrast); | |
225 | ||
226 | process = process_C; | |
f6fa7814 | 227 | #if HAVE_MMX_INLINE && HAVE_6REGS |
2ba45a60 DM |
228 | if(ff_gCpuCaps.hasMMX) process = process_MMX; |
229 | #endif | |
230 | ||
231 | return 1; | |
232 | } | |
233 | ||
234 | const vf_info_t ff_vf_info_eq = { | |
235 | "soft video equalizer", | |
236 | "eq", | |
237 | "Richard Felker", | |
238 | "", | |
239 | vf_open, | |
240 | }; |