Mercurial > mplayer.hg
annotate libmpcodecs/vf_smartblur.c @ 32282:606e4157cd4c
Split alloc and init of context so that parameters can be set in the context
instead of requireing being passed through function parameters. This also
makes sws work with AVOptions.
author | michael |
---|---|
date | Sun, 26 Sep 2010 19:33:57 +0000 |
parents | effad4f941ff |
children | 7af3e6f901fd |
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 "mp_msg.h" |
26069
1318e956c092
FFmpeg now uses different (unified) #include paths.
diego
parents:
25221
diff
changeset
|
28 #include "libavutil/avutil.h" |
8106 | 29 #include "img_format.h" |
30 #include "mp_image.h" | |
31 #include "vf.h" | |
18861 | 32 #include "libswscale/swscale.h" |
10233
35f52ad860a0
vf_scale.h & related cleanup & some small warning fix by dominik
michael
parents:
9975
diff
changeset
|
33 #include "vf_scale.h" |
8106 | 34 |
35 //===========================================================================// | |
36 | |
37 typedef struct FilterParam{ | |
38 float radius; | |
39 float strength; | |
40 int threshold; | |
41 float quality; | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
42 struct SwsContext *filterContext; |
8106 | 43 }FilterParam; |
44 | |
45 struct vf_priv_s { | |
46 FilterParam luma; | |
47 FilterParam chroma; | |
48 }; | |
49 | |
50 | |
51 /***************************************************************************/ | |
52 | |
53 //FIXME stupid code duplication | |
54 static void getSubSampleFactors(int *h, int *v, int format){ | |
55 switch(format){ | |
56 case IMGFMT_YV12: | |
57 case IMGFMT_I420: | |
58 *h=1; | |
59 *v=1; | |
60 break; | |
61 case IMGFMT_YVU9: | |
62 *h=2; | |
63 *v=2; | |
64 break; | |
65 case IMGFMT_444P: | |
66 *h=0; | |
67 *v=0; | |
68 break; | |
69 case IMGFMT_422P: | |
70 *h=1; | |
71 *v=0; | |
72 break; | |
73 case IMGFMT_411P: | |
74 *h=2; | |
75 *v=0; | |
76 break; | |
77 } | |
78 } | |
79 | |
80 static int allocStuff(FilterParam *f, int width, int height){ | |
81 SwsVector *vec; | |
82 SwsFilter swsF; | |
83 | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
84 vec = sws_getGaussianVec(f->radius, f->quality); |
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
85 sws_scaleVec(vec, f->strength); |
8106 | 86 vec->coeff[vec->length/2]+= 1.0 - f->strength; |
87 swsF.lumH= swsF.lumV= vec; | |
88 swsF.chrH= swsF.chrV= NULL; | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
89 f->filterContext= sws_getContext( |
27804
bacaca1ac820
Fix smartblur filter crash due to missing default scaler choice;
diego
parents:
26727
diff
changeset
|
90 width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, SWS_BICUBIC | get_sws_cpuflags(), &swsF, NULL, NULL); |
8106 | 91 |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
92 sws_freeVec(vec); |
8106 | 93 |
94 return 0; | |
95 } | |
96 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
97 static int config(struct vf_instance *vf, |
8106 | 98 int width, int height, int d_width, int d_height, |
99 unsigned int flags, unsigned int outfmt){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
100 |
8106 | 101 int sw, sh; |
102 | |
103 allocStuff(&vf->priv->luma, width, height); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
104 |
8106 | 105 getSubSampleFactors(&sw, &sh, outfmt); |
106 allocStuff(&vf->priv->chroma, width>>sw, height>>sh); | |
107 | |
108 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
109 } | |
110 | |
111 static void freeBuffers(FilterParam *f){ | |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
112 if(f->filterContext) sws_freeContext(f->filterContext); |
8106 | 113 f->filterContext=NULL; |
114 } | |
115 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
116 static void uninit(struct vf_instance *vf){ |
8106 | 117 if(!vf->priv) return; |
118 | |
119 freeBuffers(&vf->priv->luma); | |
120 freeBuffers(&vf->priv->chroma); | |
121 | |
122 free(vf->priv); | |
123 vf->priv=NULL; | |
124 } | |
125 | |
126 static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){ | |
127 int x, y; | |
128 FilterParam f= *fp; | |
32136
effad4f941ff
Mark srcArray as const pointer to const data, fixes the warnings:
diego
parents:
30642
diff
changeset
|
129 const uint8_t* const srcArray[MP_MAX_PLANES] = {src}; |
29064
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
130 uint8_t *dstArray[MP_MAX_PLANES]= {dst}; |
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
131 int srcStrideArray[MP_MAX_PLANES]= {srcStride}; |
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
132 int dstStrideArray[MP_MAX_PLANES]= {dstStride}; |
8106 | 133 |
9494
543ab3909b78
sws_ prefix, more seperation between internal & external swscaler API
michael
parents:
8263
diff
changeset
|
134 sws_scale(f.filterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
135 |
8106 | 136 if(f.threshold > 0){ |
137 for(y=0; y<h; y++){ | |
138 for(x=0; x<w; x++){ | |
139 const int orig= src[x + y*srcStride]; | |
140 const int filtered= dst[x + y*dstStride]; | |
141 const int diff= orig - filtered; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
142 |
8106 | 143 if(diff > 0){ |
144 if(diff > 2*f.threshold){ | |
145 dst[x + y*dstStride]= orig; | |
146 }else if(diff > f.threshold){ | |
147 dst[x + y*dstStride]= filtered + diff - f.threshold; | |
148 } | |
149 }else{ | |
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 } | |
156 } | |
157 } | |
158 }else if(f.threshold < 0){ | |
159 for(y=0; y<h; y++){ | |
160 for(x=0; x<w; x++){ | |
161 const int orig= src[x + y*srcStride]; | |
162 const int filtered= dst[x + y*dstStride]; | |
163 const int diff= orig - filtered; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
164 |
8106 | 165 if(diff > 0){ |
166 if(diff > -2*f.threshold){ | |
167 }else if(diff > -f.threshold){ | |
168 dst[x + y*dstStride]= orig - diff - f.threshold; | |
169 }else | |
170 dst[x + y*dstStride]= orig; | |
171 }else{ | |
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 } | |
178 } | |
179 } | |
180 } | |
181 } | |
182 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
183 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ |
8106 | 184 int cw= mpi->w >> mpi->chroma_x_shift; |
185 int ch= mpi->h >> mpi->chroma_y_shift; | |
16154
abe49bc12544
when threshold != 0 the dest image must be readable
reimar
parents:
14542
diff
changeset
|
186 FilterParam *f= &vf->priv; |
8106 | 187 |
188 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
|
189 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE| |
abe49bc12544
when threshold != 0 the dest image must be readable
reimar
parents:
14542
diff
changeset
|
190 (f->threshold) ? MP_IMGFLAG_READABLE : 0, |
8106 | 191 mpi->w,mpi->h); |
192 | |
193 assert(mpi->flags&MP_IMGFLAG_PLANAR); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
194 |
8106 | 195 blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma); |
196 blur(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma); | |
197 blur(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
198 |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17367
diff
changeset
|
199 return vf_next_put_image(vf,dmpi, pts); |
8106 | 200 } |
201 | |
202 //===========================================================================// | |
203 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
204 static int query_format(struct vf_instance *vf, unsigned int fmt){ |
8106 | 205 switch(fmt) |
206 { | |
207 case IMGFMT_YV12: | |
208 case IMGFMT_I420: | |
209 case IMGFMT_IYUV: | |
210 case IMGFMT_YVU9: | |
211 case IMGFMT_444P: | |
212 case IMGFMT_422P: | |
213 case IMGFMT_411P: | |
214 return vf_next_query_format(vf, fmt); | |
215 } | |
216 return 0; | |
217 } | |
218 | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
29263
diff
changeset
|
219 static int vf_open(vf_instance_t *vf, char *args){ |
8106 | 220 int e; |
221 | |
222 vf->config=config; | |
223 vf->put_image=put_image; | |
224 // vf->get_image=get_image; | |
225 vf->query_format=query_format; | |
226 vf->uninit=uninit; | |
227 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
228 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
229 | |
230 if(args==NULL) return 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
231 |
8106 | 232 e=sscanf(args, "%f:%f:%d:%f:%f:%d", |
233 &vf->priv->luma.radius, | |
234 &vf->priv->luma.strength, | |
235 &vf->priv->luma.threshold, | |
236 &vf->priv->chroma.radius, | |
237 &vf->priv->chroma.strength, | |
238 &vf->priv->chroma.threshold | |
239 ); | |
240 | |
241 vf->priv->luma.quality = vf->priv->chroma.quality= 3.0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
242 |
8106 | 243 if(e==3){ |
244 vf->priv->chroma.radius= vf->priv->luma.radius; | |
245 vf->priv->chroma.strength= vf->priv->luma.strength; | |
246 vf->priv->chroma.threshold = vf->priv->luma.threshold; | |
247 }else if(e!=6) | |
248 return 0; | |
249 | |
250 return 1; | |
251 } | |
252 | |
25221 | 253 const vf_info_t vf_info_smartblur = { |
8106 | 254 "smart blur", |
255 "smartblur", | |
256 "Michael Niedermayer", | |
257 "", | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
29263
diff
changeset
|
258 vf_open, |
9593
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
9494
diff
changeset
|
259 NULL |
8106 | 260 }; |
261 | |
262 //===========================================================================// |