Mercurial > mplayer.hg
comparison libmpcodecs/vf_tile.c @ 10751:81d03cb2cd64
2 new filters: tile & framestep
patch by Daniele Forghieri ( guru@digitalfantasy.it )
(little cleanup by me)
author | arpi |
---|---|
date | Sun, 31 Aug 2003 21:41:24 +0000 |
parents | |
children | 6ff3379a0862 |
comparison
equal
deleted
inserted
replaced
10750:338d91776700 | 10751:81d03cb2cd64 |
---|---|
1 /* | |
2 * vf_tile.c - filter to tile a serie of image in a single, bigger, image | |
3 * | |
4 * The parameters are: | |
5 * | |
6 * xtile: number of tile on the x axis (5) | |
7 * ytile: number of tile on the y axis (5) | |
8 * xytile: when write the image, it can be different then xtile * ytile | |
9 * (for example you can write 8 * 7 tile, writing the file every | |
10 * 50 frame, to have one image every 2 seconds @ 25 fps ). | |
11 * start: pixel at the start (x/y), default 2 | |
12 * delta: pixel between 2 tile, (x/y), default 4 | |
13 * | |
14 * For example a valid command line is: | |
15 * ... -vf tile=10:5:-1:4:8 ... | |
16 * that make images of 10 * 5 tiles, with 4 pixel at the beginning and | |
17 * 8 pixel between tiles. | |
18 * | |
19 * The default command is: | |
20 * ... -vf tile=5:5:25:2:4 | |
21 * | |
22 * If you omit a parameter or put a value less then 0, the default is used. | |
23 * ... -vf tile=10:5::-1:10 | |
24 * | |
25 * You can also stop when you're ok | |
26 * ... -vf tile=10:5 | |
27 * (and this is probably the option you will use more often ...) | |
28 * | |
29 * Probably is good to put the scale filter before the tile :-) | |
30 * | |
31 * Daniele Forghieri ( guru@digitalfantasy.it ) | |
32 */ | |
33 | |
34 // strtoi memcpy_pic | |
35 | |
36 #include <stdio.h> | |
37 #include <stdlib.h> | |
38 #include <string.h> | |
39 | |
40 #include "../config.h" | |
41 #include "../mp_msg.h" | |
42 #include "../cpudetect.h" | |
43 | |
44 #include "img_format.h" | |
45 #include "mp_image.h" | |
46 #include "vf.h" | |
47 | |
48 #include "../libvo/fastmemcpy.h" | |
49 | |
50 /* external */ | |
51 extern int verbose; | |
52 | |
53 /* private data */ | |
54 struct vf_priv_s { | |
55 /* configuration data */ | |
56 /* Number on hor/ver tiles */ | |
57 int xtile; | |
58 int ytile; | |
59 /* When write the whole frame (default = xtile * ytile) */ | |
60 int xytile; | |
61 /* pixel at start / end (default = 4) */ | |
62 int start; | |
63 /* pixel between image (default = 2) */ | |
64 int delta; | |
65 // /* Background color, in destination format */ | |
66 // int bkgSet; | |
67 | |
68 /* Work data */ | |
69 int frame_cur; | |
70 }; | |
71 | |
72 | |
73 static int config(struct vf_instance_s* vf, | |
74 int width, int height, int d_width, int d_height, | |
75 unsigned int flags, unsigned int outfmt){ | |
76 | |
77 struct vf_priv_s *priv; | |
78 int xw; | |
79 int yh; | |
80 | |
81 /* Calculate new destination size */ | |
82 priv = vf->priv; | |
83 xw = priv->start * 2 + | |
84 priv->xtile * width + | |
85 (priv->xtile - 1) * priv->delta; | |
86 yh = priv->start * 2 + | |
87 priv->ytile * height + | |
88 (priv->ytile - 1) * priv->delta; | |
89 | |
90 mp_msg(MSGT_VFILTER,MSGL_V,"vf_tile:config size set to %d * %d\n", xw, yh); | |
91 | |
92 return vf_next_config(vf, xw, yh, xw, yh, flags, outfmt); | |
93 } | |
94 | |
95 /* Filter handler */ | |
96 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
97 { | |
98 mp_image_t *dmpi; | |
99 struct vf_priv_s *priv; | |
100 int t; | |
101 int xw; | |
102 int yh; | |
103 int xi; | |
104 int yi; | |
105 int by; | |
106 int dw; | |
107 | |
108 /* Calculate new size */ | |
109 priv = vf->priv; | |
110 xw = priv->start * 2 + | |
111 priv->xtile * mpi->w + | |
112 (priv->xtile - 1) * priv->delta; | |
113 yh = priv->start * 2 + | |
114 priv->ytile * mpi->h+ | |
115 (priv->ytile - 1) * priv->delta; | |
116 | |
117 /* Get the big image! */ | |
118 dmpi=vf_get_image(vf->next, mpi->imgfmt, | |
119 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE, | |
120 xw, yh); | |
121 | |
122 /* bytes x pixel & bytes x line */ | |
123 if (mpi->flags & MP_IMGFLAG_PLANAR) { | |
124 by = 1; | |
125 dw = mpi->w; | |
126 } | |
127 else { | |
128 by = (mpi->bpp + 7) / 8; | |
129 dw = mpi->w * by; | |
130 } | |
131 /* Index position */ | |
132 t = priv->frame_cur % priv->xytile; | |
133 // if ((t == 0) && (bkg != 0)) { | |
134 // /* First frame, delete the background */ | |
135 // | |
136 // } | |
137 | |
138 /* Position of image */ | |
139 xi = priv->start + (mpi->w + priv->delta) * (t % priv->xtile); | |
140 yi = priv->start + (mpi->h + priv->delta) * (t / priv->xtile); | |
141 | |
142 /* Copy first (or only) plane */ | |
143 memcpy_pic( dmpi->planes[0] + xi * by + yi * dmpi->stride[0], | |
144 mpi->planes[0], | |
145 dw, | |
146 mpi->h, | |
147 dmpi->stride[0], | |
148 mpi->stride[0]); | |
149 | |
150 if (mpi->flags & MP_IMGFLAG_PLANAR) { | |
151 /* Copy the other 2 planes */ | |
152 memcpy_pic( dmpi->planes[1] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[1], | |
153 mpi->planes[1], | |
154 mpi->chroma_width, | |
155 mpi->chroma_height, | |
156 dmpi->stride[1], | |
157 mpi->stride[1]); | |
158 memcpy_pic( dmpi->planes[2] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[2], | |
159 mpi->planes[2], | |
160 mpi->chroma_width, | |
161 mpi->chroma_height, | |
162 dmpi->stride[2], | |
163 mpi->stride[2]); | |
164 } | |
165 | |
166 /* Increment current frame */ | |
167 ++priv->frame_cur; | |
168 | |
169 if (t == priv->xytile - 1) { | |
170 /* Display the composition */ | |
171 dmpi->width = xw; | |
172 dmpi->height = yh; | |
173 return vf_next_put_image(vf, dmpi); | |
174 } | |
175 else { | |
176 /* Skip the frame */ | |
177 return(0); | |
178 } | |
179 } | |
180 | |
181 static void uninit(struct vf_instance_s* vf) | |
182 { | |
183 /* free local data */ | |
184 free(vf->priv); | |
185 } | |
186 | |
187 /* rgb/bgr 15->32 supported & some Yxxx */ | |
188 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
189 { | |
190 switch (fmt) { | |
191 /* rgb 15 -> 32 bit */ | |
192 case IMGFMT_RGB15: | |
193 case IMGFMT_RGB16: | |
194 case IMGFMT_RGB24: | |
195 case IMGFMT_RGB32: | |
196 /* bgr 15 -> 32 bit */ | |
197 case IMGFMT_BGR15: | |
198 case IMGFMT_BGR16: | |
199 case IMGFMT_BGR24: | |
200 case IMGFMT_BGR32: | |
201 /* Various Yxxx Formats */ | |
202 case IMGFMT_444P: | |
203 case IMGFMT_422P: | |
204 case IMGFMT_411P: | |
205 case IMGFMT_YUY2: | |
206 case IMGFMT_YV12: | |
207 case IMGFMT_I420: | |
208 case IMGFMT_YVU9: | |
209 case IMGFMT_IF09: | |
210 case IMGFMT_IYUV: | |
211 return vf_next_query_format(vf, fmt); | |
212 } | |
213 return 0; | |
214 } | |
215 | |
216 /* Get an integer from the string pointed by s, adjusting s. | |
217 * If the value is less then 0 def_val is used. | |
218 * Return 0 for ok | |
219 * | |
220 * Look below ( in open(...) ) for a use ... | |
221 */ | |
222 static int parse_int(char **s, int *rt, int def_val) | |
223 { | |
224 | |
225 int t = 0; | |
226 | |
227 if (**s) { | |
228 /* Get value (dec, hex or octal) */ | |
229 t = strtol( *s, s, 0 ); | |
230 | |
231 /* Use default */ | |
232 if (t < 0) { | |
233 t = def_val; | |
234 } | |
235 | |
236 if (**s == ':') { | |
237 /* Point to next character (problably a digit) */ | |
238 ++(*s); | |
239 } | |
240 else if (**s != '\0') { | |
241 /* Error, we got some wrong char */ | |
242 return(1); | |
243 } | |
244 } | |
245 else { | |
246 t = def_val; | |
247 } | |
248 | |
249 *rt = t; | |
250 return(0); | |
251 | |
252 } | |
253 | |
254 /* Main entry funct for the filter */ | |
255 static int open(vf_instance_t *vf, char* args) | |
256 { | |
257 struct vf_priv_s *p; | |
258 int er; | |
259 | |
260 vf->put_image = put_image; | |
261 vf->query_format = query_format; | |
262 vf->config = config; | |
263 vf->uninit = uninit; | |
264 vf->default_reqs = VFCAP_ACCEPT_STRIDE; | |
265 /* Private data */ | |
266 vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); | |
267 if (p == NULL) { | |
268 return(0); | |
269 } | |
270 | |
271 if (args == NULL) { | |
272 /* Use the default */ | |
273 args = ""; | |
274 } | |
275 /* Parse all the arguments */ | |
276 er = parse_int( &args, &p->xtile, 5 ); | |
277 er |= parse_int( &args, &p->ytile, 5 ); | |
278 er |= parse_int( &args, &p->xytile, 0 ); | |
279 er |= parse_int( &args, &p->start, 2 ); | |
280 er |= parse_int( &args, &p->delta, 4 ); | |
281 // er |= parse_int( &args, &p->bkgSet, 0 ); | |
282 | |
283 if (er) { | |
284 printf("Error parsing argument\n"); | |
285 return(0); | |
286 } | |
287 /* Load some default */ | |
288 if ((p->xytile <= 0) || (p->xytile > p->xtile * p->ytile)) { | |
289 p->xytile = p->xtile * p->ytile; | |
290 } | |
291 | |
292 /* Say what happen: use mp_msg(...)? */ | |
293 if (verbose) { | |
294 printf("vf_tile: tiling %d * %d, output every %d frames\n", | |
295 p->xtile, | |
296 p->ytile, | |
297 p->xytile); | |
298 printf("vf_tile: start pixel %d, delta pixel %d\n", | |
299 p->start, | |
300 p->delta); | |
301 // printf("vf_tile: background 0x%x\n", | |
302 // p->bkgSet); | |
303 } | |
304 return 1; | |
305 } | |
306 | |
307 vf_info_t vf_info_tile = { | |
308 "Make a single image tiling x/y images", | |
309 "tile", | |
310 "Daniele Forghieri", | |
311 "", | |
312 open, | |
313 NULL | |
314 }; |