00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <inttypes.h>
00023
00024 #include "config.h"
00025 #include "mp_msg.h"
00026 #include "cpudetect.h"
00027
00028 #include "img_format.h"
00029 #include "mp_image.h"
00030 #include "vf.h"
00031
00032 #include "libvo/video_out.h"
00033
00034 static struct vf_priv_s {
00035 unsigned char *buf;
00036 int brightness;
00037 int contrast;
00038 };
00039
00040 #if HAVE_MMX
00041 static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride,
00042 int w, int h, int brightness, int contrast)
00043 {
00044 int i;
00045 int pel;
00046 int dstep = dstride-w;
00047 int sstep = sstride-w;
00048 short brvec[4];
00049 short contvec[4];
00050
00051 contrast = ((contrast+100)*256*16)/100;
00052 brightness = ((brightness+100)*511)/200-128 - contrast/32;
00053
00054 brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;
00055 contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;
00056
00057 while (h--) {
00058 __asm__ volatile (
00059 "movq (%5), %%mm3 \n\t"
00060 "movq (%6), %%mm4 \n\t"
00061 "pxor %%mm0, %%mm0 \n\t"
00062 "movl %4, %%eax\n\t"
00063 ASMALIGN(4)
00064 "1: \n\t"
00065 "movq (%0), %%mm1 \n\t"
00066 "movq (%0), %%mm2 \n\t"
00067 "punpcklbw %%mm0, %%mm1 \n\t"
00068 "punpckhbw %%mm0, %%mm2 \n\t"
00069 "psllw $4, %%mm1 \n\t"
00070 "psllw $4, %%mm2 \n\t"
00071 "pmulhw %%mm4, %%mm1 \n\t"
00072 "pmulhw %%mm4, %%mm2 \n\t"
00073 "paddw %%mm3, %%mm1 \n\t"
00074 "paddw %%mm3, %%mm2 \n\t"
00075 "packuswb %%mm2, %%mm1 \n\t"
00076 "add $8, %0 \n\t"
00077 "movq %%mm1, (%1) \n\t"
00078 "add $8, %1 \n\t"
00079 "decl %%eax \n\t"
00080 "jnz 1b \n\t"
00081 : "=r" (src), "=r" (dest)
00082 : "0" (src), "1" (dest), "r" (w>>3), "r" (brvec), "r" (contvec)
00083 : "%eax"
00084 );
00085
00086 for (i = w&7; i; i--)
00087 {
00088 pel = ((*src++* contrast)>>12) + brightness;
00089 if(pel&768) pel = (-pel)>>31;
00090 *dest++ = pel;
00091 }
00092
00093 src += sstep;
00094 dest += dstep;
00095 }
00096 __asm__ volatile ( "emms \n\t" ::: "memory" );
00097 }
00098 #endif
00099
00100 static void process_C(unsigned char *dest, int dstride, unsigned char *src, int sstride,
00101 int w, int h, int brightness, int contrast)
00102 {
00103 int i;
00104 int pel;
00105 int dstep = dstride-w;
00106 int sstep = sstride-w;
00107
00108 contrast = ((contrast+100)*256*256)/100;
00109 brightness = ((brightness+100)*511)/200-128 - contrast/512;
00110
00111 while (h--) {
00112 for (i = w; i; i--)
00113 {
00114 pel = ((*src++* contrast)>>16) + brightness;
00115 if(pel&768) pel = (-pel)>>31;
00116 *dest++ = pel;
00117 }
00118 src += sstep;
00119 dest += dstep;
00120 }
00121 }
00122
00123 static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int sstride,
00124 int w, int h, int brightness, int contrast);
00125
00126
00127
00128 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
00129 {
00130 mp_image_t *dmpi;
00131
00132 dmpi=vf_get_image(vf->next, mpi->imgfmt,
00133 MP_IMGTYPE_EXPORT, 0,
00134 mpi->w, mpi->h);
00135
00136 dmpi->stride[0] = mpi->stride[0];
00137 dmpi->planes[1] = mpi->planes[1];
00138 dmpi->planes[2] = mpi->planes[2];
00139 dmpi->stride[1] = mpi->stride[1];
00140 dmpi->stride[2] = mpi->stride[2];
00141
00142 if (!vf->priv->buf) vf->priv->buf = malloc(mpi->stride[0]*mpi->h);
00143
00144 if ((vf->priv->brightness == 0) && (vf->priv->contrast == 0))
00145 dmpi->planes[0] = mpi->planes[0];
00146 else {
00147 dmpi->planes[0] = vf->priv->buf;
00148 process(dmpi->planes[0], dmpi->stride[0],
00149 mpi->planes[0], mpi->stride[0],
00150 mpi->w, mpi->h, vf->priv->brightness,
00151 vf->priv->contrast);
00152 }
00153
00154 return vf_next_put_image(vf,dmpi, pts);
00155 }
00156
00157 static int control(struct vf_instance *vf, int request, void* data)
00158 {
00159 vf_equalizer_t *eq;
00160
00161 switch (request) {
00162 case VFCTRL_SET_EQUALIZER:
00163 eq = data;
00164 if (!strcmp(eq->item,"brightness")) {
00165 vf->priv->brightness = eq->value;
00166 return CONTROL_TRUE;
00167 }
00168 else if (!strcmp(eq->item,"contrast")) {
00169 vf->priv->contrast = eq->value;
00170 return CONTROL_TRUE;
00171 }
00172 break;
00173 case VFCTRL_GET_EQUALIZER:
00174 eq = data;
00175 if (!strcmp(eq->item,"brightness")) {
00176 eq->value = vf->priv->brightness;
00177 return CONTROL_TRUE;
00178 }
00179 else if (!strcmp(eq->item,"contrast")) {
00180 eq->value = vf->priv->contrast;
00181 return CONTROL_TRUE;
00182 }
00183 break;
00184 }
00185 return vf_next_control(vf, request, data);
00186 }
00187
00188 static int query_format(struct vf_instance *vf, unsigned int fmt)
00189 {
00190 switch (fmt) {
00191 case IMGFMT_YVU9:
00192 case IMGFMT_IF09:
00193 case IMGFMT_YV12:
00194 case IMGFMT_I420:
00195 case IMGFMT_IYUV:
00196 case IMGFMT_CLPL:
00197 case IMGFMT_Y800:
00198 case IMGFMT_Y8:
00199 case IMGFMT_NV12:
00200 case IMGFMT_NV21:
00201 case IMGFMT_444P:
00202 case IMGFMT_422P:
00203 case IMGFMT_411P:
00204 return vf_next_query_format(vf, fmt);
00205 }
00206 return 0;
00207 }
00208
00209 static void uninit(struct vf_instance *vf)
00210 {
00211 free(vf->priv->buf);
00212 free(vf->priv);
00213 }
00214
00215 static int vf_open(vf_instance_t *vf, char *args)
00216 {
00217 vf->control=control;
00218 vf->query_format=query_format;
00219 vf->put_image=put_image;
00220 vf->uninit=uninit;
00221
00222 vf->priv = malloc(sizeof(struct vf_priv_s));
00223 memset(vf->priv, 0, sizeof(struct vf_priv_s));
00224 if (args) sscanf(args, "%d:%d", &vf->priv->brightness, &vf->priv->contrast);
00225
00226 process = process_C;
00227 #if HAVE_MMX
00228 if(gCpuCaps.hasMMX) process = process_MMX;
00229 #endif
00230
00231 return 1;
00232 }
00233
00234 const vf_info_t vf_info_eq = {
00235 "soft video equalizer",
00236 "eq",
00237 "Richard Felker",
00238 "",
00239 vf_open,
00240 };