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 <inttypes.h>
00025 #include <assert.h>
00026
00027 #include "mp_msg.h"
00028 #include "img_format.h"
00029 #include "mp_image.h"
00030 #include "vf.h"
00031
00032
00033
00034
00035 typedef struct FilterParam{
00036 int radius;
00037 int power;
00038 }FilterParam;
00039
00040 struct vf_priv_s {
00041 FilterParam lumaParam;
00042 FilterParam chromaParam;
00043 };
00044
00045
00046
00047
00048
00049 static int config(struct vf_instance *vf,
00050 int width, int height, int d_width, int d_height,
00051 unsigned int flags, unsigned int outfmt){
00052
00053 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00054 }
00055
00056 static inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstStep, int srcStep){
00057 int x;
00058 const int length= radius*2 + 1;
00059 const int inv= ((1<<16) + length/2)/length;
00060
00061 int sum= 0;
00062
00063 for(x=0; x<radius; x++){
00064 sum+= src[x*srcStep]<<1;
00065 }
00066 sum+= src[radius*srcStep];
00067
00068 for(x=0; x<=radius; x++){
00069 sum+= src[(radius+x)*srcStep] - src[(radius-x)*srcStep];
00070 dst[x*dstStep]= (sum*inv + (1<<15))>>16;
00071 }
00072
00073 for(; x<w-radius; x++){
00074 sum+= src[(radius+x)*srcStep] - src[(x-radius-1)*srcStep];
00075 dst[x*dstStep]= (sum*inv + (1<<15))>>16;
00076 }
00077
00078 for(; x<w; x++){
00079 sum+= src[(2*w-radius-x-1)*srcStep] - src[(x-radius-1)*srcStep];
00080 dst[x*dstStep]= (sum*inv + (1<<15))>>16;
00081 }
00082 }
00083
00084 static inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep){
00085 uint8_t temp[2][4096];
00086 uint8_t *a= temp[0], *b=temp[1];
00087
00088 if(radius){
00089 blur(a, src, w, radius, 1, srcStep);
00090 for(; power>2; power--){
00091 uint8_t *c;
00092 blur(b, a, w, radius, 1, 1);
00093 c=a; a=b; b=c;
00094 }
00095 if(power>1)
00096 blur(dst, a, w, radius, dstStep, 1);
00097 else{
00098 int i;
00099 for(i=0; i<w; i++)
00100 dst[i*dstStep]= a[i];
00101 }
00102 }else{
00103 int i;
00104 for(i=0; i<w; i++)
00105 dst[i*dstStep]= src[i*srcStep];
00106 }
00107 }
00108
00109 static void hBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){
00110 int y;
00111
00112 if(radius==0 && dst==src) return;
00113
00114 for(y=0; y<h; y++){
00115 blur2(dst + y*dstStride, src + y*srcStride, w, radius, power, 1, 1);
00116 }
00117 }
00118
00119
00120 static void vBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){
00121 int x;
00122
00123 if(radius==0 && dst==src) return;
00124
00125 for(x=0; x<w; x++){
00126 blur2(dst + x, src + x, h, radius, power, dstStride, srcStride);
00127 }
00128 }
00129
00130 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00131 int cw= mpi->w >> mpi->chroma_x_shift;
00132 int ch= mpi->h >> mpi->chroma_y_shift;
00133
00134 mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
00135 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_READABLE,
00136 mpi->w,mpi->h);
00137
00138 assert(mpi->flags&MP_IMGFLAG_PLANAR);
00139
00140 hBlur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h,
00141 dmpi->stride[0], mpi->stride[0], vf->priv->lumaParam.radius, vf->priv->lumaParam.power);
00142 hBlur(dmpi->planes[1], mpi->planes[1], cw,ch,
00143 dmpi->stride[1], mpi->stride[1], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
00144 hBlur(dmpi->planes[2], mpi->planes[2], cw,ch,
00145 dmpi->stride[2], mpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
00146
00147 vBlur(dmpi->planes[0], dmpi->planes[0], mpi->w,mpi->h,
00148 dmpi->stride[0], dmpi->stride[0], vf->priv->lumaParam.radius, vf->priv->lumaParam.power);
00149 vBlur(dmpi->planes[1], dmpi->planes[1], cw,ch,
00150 dmpi->stride[1], dmpi->stride[1], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
00151 vBlur(dmpi->planes[2], dmpi->planes[2], cw,ch,
00152 dmpi->stride[2], dmpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
00153
00154 return vf_next_put_image(vf,dmpi, pts);
00155 }
00156
00157
00158
00159 static int query_format(struct vf_instance *vf, unsigned int fmt){
00160 switch(fmt)
00161 {
00162 case IMGFMT_YV12:
00163 case IMGFMT_I420:
00164 case IMGFMT_IYUV:
00165 case IMGFMT_YVU9:
00166 case IMGFMT_444P:
00167 case IMGFMT_422P:
00168 case IMGFMT_411P:
00169 return vf_next_query_format(vf, fmt);
00170 }
00171 return 0;
00172 }
00173
00174 static int vf_open(vf_instance_t *vf, char *args){
00175 int e;
00176
00177 vf->config=config;
00178 vf->put_image=put_image;
00179
00180 vf->query_format=query_format;
00181 vf->priv=malloc(sizeof(struct vf_priv_s));
00182 memset(vf->priv, 0, sizeof(struct vf_priv_s));
00183
00184 if(args==NULL) return 0;
00185
00186 e=sscanf(args, "%d:%d:%d:%d",
00187 &vf->priv->lumaParam.radius,
00188 &vf->priv->lumaParam.power,
00189 &vf->priv->chromaParam.radius,
00190 &vf->priv->chromaParam.power
00191 );
00192
00193 if(e==2){
00194 vf->priv->chromaParam.radius= vf->priv->lumaParam.radius;
00195 vf->priv->chromaParam.power = vf->priv->lumaParam.power;
00196 }else if(e!=4)
00197 return 0;
00198
00199 if(vf->priv->lumaParam.radius < 0) return 0;
00200 if(vf->priv->chromaParam.radius < 0) return 0;
00201
00202 return 1;
00203 }
00204
00205 const vf_info_t vf_info_boxblur = {
00206 "box blur",
00207 "boxblur",
00208 "Michael Niedermayer",
00209 "",
00210 vf_open,
00211 NULL
00212 };
00213
00214