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 34struct vf_priv_s { 35 unsigned char *buf; 36 int brightness; 37 int contrast; 38}; 39 40#if HAVE_MMX && HAVE_6REGS 41static 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 100static 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 123static 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 128static 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 157static 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 188static 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 209static void uninit(struct vf_instance *vf) 210{ 211 free(vf->priv->buf); 212 free(vf->priv); 213} 214 215static 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; 227#if HAVE_MMX && HAVE_6REGS 228 if(ff_gCpuCaps.hasMMX) process = process_MMX; 229#endif 230 231 return 1; 232} 233 234const vf_info_t ff_vf_info_eq = { 235 "soft video equalizer", 236 "eq", 237 "Richard Felker", 238 "", 239 vf_open, 240}; 241