Mercurial > mplayer.hg
annotate libmpcodecs/vf_smartblur.c @ 27985:1c77b86d355d
Remove a ColorFill that is not necessary since the surface it is used
on has exactly the same size as the video image and the video will
be copied into it before it is used the first time.
author | reimar |
---|---|
date | Mon, 24 Nov 2008 09:46:23 +0000 |
parents | bacaca1ac820 |
children | df67d03dde3b |
rev | line source |
---|---|
8106 | 1 /* |
26727 | 2 * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at> |
3 * | |
4 * This file is part of MPlayer. | |
5 * | |
6 * MPlayer is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * MPlayer is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 */ | |
8106 | 20 |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <inttypes.h> | |
25 #include <assert.h> | |
26 | |
17012 | 27 #include "config.h" |
28 #include "mp_msg.h" | |
8106 | 29 |
30 #ifdef HAVE_MALLOC_H | |
31 #include <malloc.h> | |
32 #endif | |
33 | |
26069
1318e956c092
FFmpeg now uses different (unified) #include paths.
diego
parents:
25221
diff
changeset
|
34 #include "libavutil/avutil.h" |
8106 | 35 #include "img_format.h" |
36 #include "mp_image.h" | |
37 #include "vf.h" | |
18861 | 38 #include "libswscale/swscale.h" |
10233
35f52ad860a0
vf_scale.h & related cleanup & some small warning fix by dominik
michael
parents:
9975
diff
changeset
|
39 #include "vf_scale.h" |
8106 | 40 |
41 //===========================================================================// | |
42 | |
43 typedef struct FilterParam{ | |
44 float radius; | |
45 float strength; | |
46 int threshold; | |
47 float quality; | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
48 struct SwsContext *filterContext; |
8106 | 49 }FilterParam; |
50 | |
51 struct vf_priv_s { | |
52 FilterParam luma; | |
53 FilterParam chroma; | |
54 }; | |
55 | |
56 | |
57 /***************************************************************************/ | |
58 | |
59 //FIXME stupid code duplication | |
60 static void getSubSampleFactors(int *h, int *v, int format){ | |
61 switch(format){ | |
62 case IMGFMT_YV12: | |
63 case IMGFMT_I420: | |
64 *h=1; | |
65 *v=1; | |
66 break; | |
67 case IMGFMT_YVU9: | |
68 *h=2; | |
69 *v=2; | |
70 break; | |
71 case IMGFMT_444P: | |
72 *h=0; | |
73 *v=0; | |
74 break; | |
75 case IMGFMT_422P: | |
76 *h=1; | |
77 *v=0; | |
78 break; | |
79 case IMGFMT_411P: | |
80 *h=2; | |
81 *v=0; | |
82 break; | |
83 } | |
84 } | |
85 | |
86 static int allocStuff(FilterParam *f, int width, int height){ | |
87 SwsVector *vec; | |
88 SwsFilter swsF; | |
89 | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
90 vec = sws_getGaussianVec(f->radius, f->quality); |
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
91 sws_scaleVec(vec, f->strength); |
8106 | 92 vec->coeff[vec->length/2]+= 1.0 - f->strength; |
93 swsF.lumH= swsF.lumV= vec; | |
94 swsF.chrH= swsF.chrV= NULL; | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
95 f->filterContext= sws_getContext( |
27804
bacaca1ac820
Fix smartblur filter crash due to missing default scaler choice;
diego
parents:
26727
diff
changeset
|
96 width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, SWS_BICUBIC | get_sws_cpuflags(), &swsF, NULL, NULL); |
8106 | 97 |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
98 sws_freeVec(vec); |
8106 | 99 |
100 return 0; | |
101 } | |
102 | |
103 static int config(struct vf_instance_s* vf, | |
104 int width, int height, int d_width, int d_height, | |
105 unsigned int flags, unsigned int outfmt){ | |
106 | |
107 int sw, sh; | |
108 | |
109 allocStuff(&vf->priv->luma, width, height); | |
110 | |
111 getSubSampleFactors(&sw, &sh, outfmt); | |
112 allocStuff(&vf->priv->chroma, width>>sw, height>>sh); | |
113 | |
114 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
115 } | |
116 | |
117 static void freeBuffers(FilterParam *f){ | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
118 if(f->filterContext) sws_freeContext(f->filterContext); |
8106 | 119 f->filterContext=NULL; |
120 } | |
121 | |
122 static void uninit(struct vf_instance_s* vf){ | |
123 if(!vf->priv) return; | |
124 | |
125 freeBuffers(&vf->priv->luma); | |
126 freeBuffers(&vf->priv->chroma); | |
127 | |
128 free(vf->priv); | |
129 vf->priv=NULL; | |
130 } | |
131 | |
132 static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){ | |
133 int x, y; | |
134 FilterParam f= *fp; | |
135 uint8_t *srcArray[3]= {src, NULL, NULL}; | |
136 uint8_t *dstArray[3]= {dst, NULL, NULL}; | |
137 int srcStrideArray[3]= {srcStride, 0, 0}; | |
138 int dstStrideArray[3]= {dstStride, 0, 0}; | |
139 | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
140 sws_scale(f.filterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray); |
8106 | 141 |
142 if(f.threshold > 0){ | |
143 for(y=0; y<h; y++){ | |
144 for(x=0; x<w; x++){ | |
145 const int orig= src[x + y*srcStride]; | |
146 const int filtered= dst[x + y*dstStride]; | |
147 const int diff= orig - filtered; | |
148 | |
149 if(diff > 0){ | |
150 if(diff > 2*f.threshold){ | |
151 dst[x + y*dstStride]= orig; | |
152 }else if(diff > f.threshold){ | |
153 dst[x + y*dstStride]= filtered + diff - f.threshold; | |
154 } | |
155 }else{ | |
156 if(-diff > 2*f.threshold){ | |
157 dst[x + y*dstStride]= orig; | |
158 }else if(-diff > f.threshold){ | |
159 dst[x + y*dstStride]= filtered + diff + f.threshold; | |
160 } | |
161 } | |
162 } | |
163 } | |
164 }else if(f.threshold < 0){ | |
165 for(y=0; y<h; y++){ | |
166 for(x=0; x<w; x++){ | |
167 const int orig= src[x + y*srcStride]; | |
168 const int filtered= dst[x + y*dstStride]; | |
169 const int diff= orig - filtered; | |
170 | |
171 if(diff > 0){ | |
172 if(diff > -2*f.threshold){ | |
173 }else if(diff > -f.threshold){ | |
174 dst[x + y*dstStride]= orig - diff - f.threshold; | |
175 }else | |
176 dst[x + y*dstStride]= orig; | |
177 }else{ | |
178 if(diff < 2*f.threshold){ | |
179 }else if(diff < f.threshold){ | |
180 dst[x + y*dstStride]= orig - diff + f.threshold; | |
181 }else | |
182 dst[x + y*dstStride]= orig; | |
183 } | |
184 } | |
185 } | |
186 } | |
187 } | |
188 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17367
diff
changeset
|
189 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){ |
8106 | 190 int cw= mpi->w >> mpi->chroma_x_shift; |
191 int ch= mpi->h >> mpi->chroma_y_shift; | |
16154
abe49bc12544
when threshold != 0 the dest image must be readable
reimar
parents:
14542
diff
changeset
|
192 FilterParam *f= &vf->priv; |
8106 | 193 |
194 mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
16154
abe49bc12544
when threshold != 0 the dest image must be readable
reimar
parents:
14542
diff
changeset
|
195 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE| |
abe49bc12544
when threshold != 0 the dest image must be readable
reimar
parents:
14542
diff
changeset
|
196 (f->threshold) ? MP_IMGFLAG_READABLE : 0, |
8106 | 197 mpi->w,mpi->h); |
198 | |
199 assert(mpi->flags&MP_IMGFLAG_PLANAR); | |
200 | |
201 blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma); | |
202 blur(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma); | |
203 blur(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma); | |
204 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17367
diff
changeset
|
205 return vf_next_put_image(vf,dmpi, pts); |
8106 | 206 } |
207 | |
208 //===========================================================================// | |
209 | |
210 static int query_format(struct vf_instance_s* vf, unsigned int fmt){ | |
211 switch(fmt) | |
212 { | |
213 case IMGFMT_YV12: | |
214 case IMGFMT_I420: | |
215 case IMGFMT_IYUV: | |
216 case IMGFMT_YVU9: | |
217 case IMGFMT_444P: | |
218 case IMGFMT_422P: | |
219 case IMGFMT_411P: | |
220 return vf_next_query_format(vf, fmt); | |
221 } | |
222 return 0; | |
223 } | |
224 | |
225 static int open(vf_instance_t *vf, char* args){ | |
226 int e; | |
227 | |
228 vf->config=config; | |
229 vf->put_image=put_image; | |
230 // vf->get_image=get_image; | |
231 vf->query_format=query_format; | |
232 vf->uninit=uninit; | |
233 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
234 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
235 | |
236 if(args==NULL) return 0; | |
237 | |
238 e=sscanf(args, "%f:%f:%d:%f:%f:%d", | |
239 &vf->priv->luma.radius, | |
240 &vf->priv->luma.strength, | |
241 &vf->priv->luma.threshold, | |
242 &vf->priv->chroma.radius, | |
243 &vf->priv->chroma.strength, | |
244 &vf->priv->chroma.threshold | |
245 ); | |
246 | |
247 vf->priv->luma.quality = vf->priv->chroma.quality= 3.0; | |
248 | |
249 if(e==3){ | |
250 vf->priv->chroma.radius= vf->priv->luma.radius; | |
251 vf->priv->chroma.strength= vf->priv->luma.strength; | |
252 vf->priv->chroma.threshold = vf->priv->luma.threshold; | |
253 }else if(e!=6) | |
254 return 0; | |
255 | |
256 return 1; | |
257 } | |
258 | |
25221 | 259 const vf_info_t vf_info_smartblur = { |
8106 | 260 "smart blur", |
261 "smartblur", | |
262 "Michael Niedermayer", | |
263 "", | |
9593
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
9494
diff
changeset
|
264 open, |
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
9494
diff
changeset
|
265 NULL |
8106 | 266 }; |
267 | |
268 //===========================================================================// |