FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vf_eq.c
Go to the documentation of this file.
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;
37  int contrast;
38 };
39 
40 #if HAVE_MMX && HAVE_6REGS
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,
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) {
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;
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;
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;
227 #if HAVE_MMX && HAVE_6REGS
228  if(ff_gCpuCaps.hasMMX) process = process_MMX;
229 #endif
230 
231  return 1;
232 }
233 
235  "soft video equalizer",
236  "eq",
237  "Richard Felker",
238  "",
239  vf_open,
240 };