libavfilter/libmpcodecs/vf_hue.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of MPlayer.
00003  *
00004  * MPlayer is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * MPlayer is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License along
00015  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <inttypes.h>
00023 #include <math.h>
00024 
00025 #include "config.h"
00026 #include "mp_msg.h"
00027 #include "cpudetect.h"
00028 
00029 #include "img_format.h"
00030 #include "mp_image.h"
00031 #include "vf.h"
00032 
00033 #include "libvo/video_out.h"
00034 
00035 struct vf_priv_s {
00036         uint8_t *buf[2];
00037         float hue;
00038         float saturation;
00039 };
00040 
00041 static void process_C(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsrc, int dststride, int srcstride,
00042                     int w, int h, float hue, float sat)
00043 {
00044         int i;
00045         const int s= rint(sin(hue) * (1<<16) * sat);
00046         const int c= rint(cos(hue) * (1<<16) * sat);
00047 
00048         while (h--) {
00049                 for (i = 0; i<w; i++)
00050                 {
00051                         const int u= usrc[i] - 128;
00052                         const int v= vsrc[i] - 128;
00053                         int new_u= (c*u - s*v + (1<<15) + (128<<16))>>16;
00054                         int new_v= (s*u + c*v + (1<<15) + (128<<16))>>16;
00055                         if(new_u & 768) new_u= (-new_u)>>31;
00056                         if(new_v & 768) new_v= (-new_v)>>31;
00057                         udst[i]= new_u;
00058                         vdst[i]= new_v;
00059                 }
00060                 usrc += srcstride;
00061                 vsrc += srcstride;
00062                 udst += dststride;
00063                 vdst += dststride;
00064         }
00065 }
00066 
00067 static void (*process)(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsrc, int dststride, int srcstride,
00068                     int w, int h, float hue, float sat);
00069 
00070 /* FIXME: add packed yuv version of process */
00071 
00072 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
00073 {
00074         mp_image_t *dmpi;
00075 
00076         dmpi=vf_get_image(vf->next, mpi->imgfmt,
00077                           MP_IMGTYPE_EXPORT, 0,
00078                           mpi->w, mpi->h);
00079 
00080         dmpi->planes[0] = mpi->planes[0];
00081         dmpi->stride[0] = mpi->stride[0];
00082         dmpi->stride[1] = mpi->stride[1];
00083         dmpi->stride[2] = mpi->stride[2];
00084 
00085         if (!vf->priv->buf[0]){
00086                 vf->priv->buf[0] = malloc(mpi->stride[1]*mpi->h >> mpi->chroma_y_shift);
00087                 vf->priv->buf[1] = malloc(mpi->stride[2]*mpi->h >> mpi->chroma_y_shift);
00088         }
00089 
00090         if (vf->priv->hue == 0 && vf->priv->saturation == 1){
00091                 dmpi->planes[1] = mpi->planes[1];
00092                 dmpi->planes[2] = mpi->planes[2];
00093         }else {
00094                 dmpi->planes[1] = vf->priv->buf[0];
00095                 dmpi->planes[2] = vf->priv->buf[1];
00096                 process(dmpi->planes[1], dmpi->planes[2],
00097                         mpi->planes[1], mpi->planes[2],
00098                         dmpi->stride[1],mpi->stride[1],
00099                         mpi->w>> mpi->chroma_x_shift, mpi->h>> mpi->chroma_y_shift,
00100                         vf->priv->hue, vf->priv->saturation);
00101         }
00102 
00103         return vf_next_put_image(vf,dmpi, pts);
00104 }
00105 
00106 static int control(struct vf_instance *vf, int request, void* data)
00107 {
00108         vf_equalizer_t *eq;
00109 
00110         switch (request) {
00111         case VFCTRL_SET_EQUALIZER:
00112                 eq = data;
00113                 if (!strcmp(eq->item,"hue")) {
00114                         vf->priv->hue = eq->value * M_PI / 100;
00115                         return CONTROL_TRUE;
00116                 } else if (!strcmp(eq->item,"saturation")) {
00117                         vf->priv->saturation = (eq->value + 100)/100.0;
00118                         return CONTROL_TRUE;
00119                 }
00120                 break;
00121         case VFCTRL_GET_EQUALIZER:
00122                 eq = data;
00123                 if (!strcmp(eq->item,"hue")) {
00124                         eq->value = rint(vf->priv->hue *100 / M_PI);
00125                         return CONTROL_TRUE;
00126                 }else if (!strcmp(eq->item,"saturation")) {
00127                         eq->value = rint(vf->priv->saturation*100 - 100);
00128                         return CONTROL_TRUE;
00129                 }
00130                 break;
00131         }
00132         return vf_next_control(vf, request, data);
00133 }
00134 
00135 static int query_format(struct vf_instance *vf, unsigned int fmt)
00136 {
00137         switch (fmt) {
00138         case IMGFMT_YVU9:
00139         case IMGFMT_IF09:
00140         case IMGFMT_YV12:
00141         case IMGFMT_I420:
00142         case IMGFMT_IYUV:
00143         case IMGFMT_CLPL:
00144         case IMGFMT_444P:
00145         case IMGFMT_422P:
00146         case IMGFMT_411P:
00147                 return vf_next_query_format(vf, fmt);
00148         }
00149         return 0;
00150 }
00151 
00152 static void uninit(struct vf_instance *vf)
00153 {
00154         free(vf->priv->buf[0]);
00155         free(vf->priv->buf[1]);
00156         free(vf->priv);
00157 }
00158 
00159 static int vf_open(vf_instance_t *vf, char *args)
00160 {
00161         vf->control=control;
00162         vf->query_format=query_format;
00163         vf->put_image=put_image;
00164         vf->uninit=uninit;
00165 
00166     vf->priv = malloc(sizeof(struct vf_priv_s));
00167     memset(vf->priv, 0, sizeof(struct vf_priv_s));
00168     sscanf(args, "%f:%f", &vf->priv->hue, &vf->priv->saturation);
00169         vf->priv->hue *= M_PI / 180.0;
00170 
00171         process = process_C;
00172         return 1;
00173 }
00174 
00175 const vf_info_t vf_info_hue = {
00176         "hue changer",
00177         "hue",
00178         "Michael Niedermayer",
00179         "",
00180         vf_open,
00181 };