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