00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <math.h>
00025 #include <inttypes.h>
00026
00027 #include "config.h"
00028
00029 #include "mp_msg.h"
00030 #include "cpudetect.h"
00031
00032 #include "img_format.h"
00033 #include "mp_image.h"
00034 #include "vf.h"
00035
00036 #include "libavcodec/avcodec.h"
00037 #include "libavutil/eval.h"
00038
00039 struct vf_priv_s {
00040 AVExpr * e[3];
00041 int framenum;
00042 mp_image_t *mpi;
00043 };
00044
00045 static int config(struct vf_instance *vf,
00046 int width, int height, int d_width, int d_height,
00047 unsigned int flags, unsigned int outfmt){
00048 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00049 }
00050
00051 static inline double getpix(struct vf_instance *vf, double x, double y, int plane){
00052 int xi, yi;
00053 mp_image_t *mpi= vf->priv->mpi;
00054 int stride= mpi->stride[plane];
00055 uint8_t *src= mpi->planes[plane];
00056 xi=x= FFMIN(FFMAX(x, 0), (mpi->w >> (plane ? mpi->chroma_x_shift : 0))-1);
00057 yi=y= FFMIN(FFMAX(y, 0), (mpi->h >> (plane ? mpi->chroma_y_shift : 0))-1);
00058
00059 x-=xi;
00060 y-=yi;
00061
00062 return
00063 (1-y)*((1-x)*src[xi + yi * stride] + x*src[xi + 1 + yi * stride])
00064 + y *((1-x)*src[xi + (yi+1) * stride] + x*src[xi + 1 + (yi+1) * stride]);
00065 }
00066
00067
00068
00069 static double lum(void *vf, double x, double y){
00070 return getpix(vf, x, y, 0);
00071 }
00072
00073 static double cb(void *vf, double x, double y){
00074 return getpix(vf, x, y, 1);
00075 }
00076
00077 static double cr(void *vf, double x, double y){
00078 return getpix(vf, x, y, 2);
00079 }
00080
00081 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00082 mp_image_t *dmpi;
00083 int x,y, plane;
00084
00085 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
00086
00087 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP,
00088 MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
00089 mpi->w,mpi->h);
00090 }
00091
00092 dmpi= vf->dmpi;
00093 vf->priv->mpi= mpi;
00094
00095 vf_clone_mpi_attributes(dmpi, mpi);
00096
00097 for(plane=0; plane<3; plane++){
00098 int w= mpi->w >> (plane ? mpi->chroma_x_shift : 0);
00099 int h= mpi->h >> (plane ? mpi->chroma_y_shift : 0);
00100 uint8_t *dst = dmpi->planes[plane];
00101 int dst_stride= dmpi->stride[plane];
00102 double const_values[]={
00103 M_PI,
00104 M_E,
00105 0,
00106 0,
00107 w,
00108 h,
00109 vf->priv->framenum,
00110 w/(double)mpi->w,
00111 h/(double)mpi->h,
00112 0
00113 };
00114 if (!vf->priv->e[plane]) continue;
00115 for(y=0; y<h; y++){
00116 const_values[3]=y;
00117 for(x=0; x<w; x++){
00118 const_values[2]=x;
00119 dst[x + y * dst_stride] = av_expr_eval(vf->priv->e[plane],
00120 const_values, vf);
00121 }
00122 }
00123 }
00124
00125 vf->priv->framenum++;
00126
00127 return vf_next_put_image(vf,dmpi, pts);
00128 }
00129
00130 static void uninit(struct vf_instance *vf){
00131 av_free(vf->priv);
00132 vf->priv=NULL;
00133 }
00134
00135
00136 static int vf_open(vf_instance_t *vf, char *args){
00137 char eq[3][2000] = { { 0 }, { 0 }, { 0 } };
00138 int plane, res;
00139
00140 vf->config=config;
00141 vf->put_image=put_image;
00142
00143 vf->uninit=uninit;
00144 vf->priv=av_malloc(sizeof(struct vf_priv_s));
00145 memset(vf->priv, 0, sizeof(struct vf_priv_s));
00146
00147 if (args) sscanf(args, "%1999[^:]:%1999[^:]:%1999[^:]", eq[0], eq[1], eq[2]);
00148
00149 if (!eq[1][0]) strncpy(eq[1], eq[0], sizeof(eq[0])-1);
00150 if (!eq[2][0]) strncpy(eq[2], eq[1], sizeof(eq[0])-1);
00151
00152 for(plane=0; plane<3; plane++){
00153 static const char *const_names[]={
00154 "PI",
00155 "E",
00156 "X",
00157 "Y",
00158 "W",
00159 "H",
00160 "N",
00161 "SW",
00162 "SH",
00163 NULL
00164 };
00165 static const char *func2_names[]={
00166 "lum",
00167 "cb",
00168 "cr",
00169 "p",
00170 NULL
00171 };
00172 double (*func2[])(void *, double, double)={
00173 lum,
00174 cb,
00175 cr,
00176 plane==0 ? lum : (plane==1 ? cb : cr),
00177 NULL
00178 };
00179 res = av_expr_parse(&vf->priv->e[plane], eq[plane], const_names, NULL, NULL, func2_names, func2, 0, NULL);
00180
00181 if (res < 0) {
00182 mp_msg(MSGT_VFILTER, MSGL_ERR, "geq: error loading equation `%s'\n", eq[plane]);
00183 return 0;
00184 }
00185 }
00186
00187 return 1;
00188 }
00189
00190 const vf_info_t vf_info_geq = {
00191 "generic equation filter",
00192 "geq",
00193 "Michael Niedermayer",
00194 "",
00195 vf_open,
00196 NULL
00197 };