ffmpeg / libavfilter / libmpcodecs / vf_tile.c @ e4852fb3
History | View | Annotate | Download (8.87 KB)
1 |
/*
|
---|---|
2 |
* 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 |
* copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it )
|
32 |
*
|
33 |
* This file is part of MPlayer.
|
34 |
*
|
35 |
* MPlayer is free software; you can redistribute it and/or modify
|
36 |
* it under the terms of the GNU General Public License as published by
|
37 |
* the Free Software Foundation; either version 2 of the License, or
|
38 |
* (at your option) any later version.
|
39 |
*
|
40 |
* MPlayer is distributed in the hope that it will be useful,
|
41 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
42 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
43 |
* GNU General Public License for more details.
|
44 |
*
|
45 |
* You should have received a copy of the GNU General Public License along
|
46 |
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
47 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
48 |
*/
|
49 |
|
50 |
// strtoi memcpy_pic
|
51 |
|
52 |
#include <stdio.h> |
53 |
#include <stdlib.h> |
54 |
#include <string.h> |
55 |
|
56 |
#include "config.h" |
57 |
#include "mp_msg.h" |
58 |
#include "help_mp.h" |
59 |
#include "cpudetect.h" |
60 |
|
61 |
#include "img_format.h" |
62 |
#include "mp_image.h" |
63 |
#include "vf.h" |
64 |
|
65 |
#include "libvo/fastmemcpy.h" |
66 |
|
67 |
/* private data */
|
68 |
struct vf_priv_s {
|
69 |
/* configuration data */
|
70 |
/* Number on hor/ver tiles */
|
71 |
int xtile;
|
72 |
int ytile;
|
73 |
/* When write the whole frame (default = xtile * ytile) */
|
74 |
int xytile;
|
75 |
/* pixel at start / end (default = 4) */
|
76 |
int start;
|
77 |
/* pixel between image (default = 2) */
|
78 |
int delta;
|
79 |
// /* Background color, in destination format */
|
80 |
// int bkgSet;
|
81 |
|
82 |
/* Work data */
|
83 |
int frame_cur;
|
84 |
}; |
85 |
|
86 |
|
87 |
static int config(struct vf_instance *vf, |
88 |
int width, int height, int d_width, int d_height, |
89 |
unsigned int flags, unsigned int outfmt){ |
90 |
|
91 |
struct vf_priv_s *priv;
|
92 |
int xw;
|
93 |
int yh;
|
94 |
|
95 |
/* Calculate new destination size */
|
96 |
priv = vf->priv; |
97 |
xw = priv->start * 2 +
|
98 |
priv->xtile * width + |
99 |
(priv->xtile - 1) * priv->delta;
|
100 |
yh = priv->start * 2 +
|
101 |
priv->ytile * height + |
102 |
(priv->ytile - 1) * priv->delta;
|
103 |
|
104 |
mp_msg(MSGT_VFILTER,MSGL_V,"vf_tile:config size set to %d * %d\n", xw, yh);
|
105 |
|
106 |
return vf_next_config(vf, xw, yh, xw, yh, flags, outfmt);
|
107 |
} |
108 |
|
109 |
/* Filter handler */
|
110 |
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) |
111 |
{ |
112 |
mp_image_t *dmpi; |
113 |
struct vf_priv_s *priv;
|
114 |
int t;
|
115 |
int xw;
|
116 |
int yh;
|
117 |
int xi;
|
118 |
int yi;
|
119 |
int by;
|
120 |
int dw;
|
121 |
|
122 |
/* Calculate new size */
|
123 |
priv = vf->priv; |
124 |
xw = priv->start * 2 +
|
125 |
priv->xtile * mpi->w + |
126 |
(priv->xtile - 1) * priv->delta;
|
127 |
yh = priv->start * 2 +
|
128 |
priv->ytile * mpi->h+ |
129 |
(priv->ytile - 1) * priv->delta;
|
130 |
|
131 |
/* Get the big image! */
|
132 |
dmpi=vf_get_image(vf->next, mpi->imgfmt, |
133 |
MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE, |
134 |
xw, yh); |
135 |
|
136 |
/* bytes x pixel & bytes x line */
|
137 |
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
138 |
by = 1;
|
139 |
dw = mpi->w; |
140 |
} |
141 |
else {
|
142 |
by = (mpi->bpp + 7) / 8; |
143 |
dw = mpi->w * by; |
144 |
} |
145 |
/* Index position */
|
146 |
t = priv->frame_cur % priv->xytile; |
147 |
// if ((t == 0) && (bkg != 0)) {
|
148 |
// /* First frame, delete the background */
|
149 |
//
|
150 |
// }
|
151 |
|
152 |
/* Position of image */
|
153 |
xi = priv->start + (mpi->w + priv->delta) * (t % priv->xtile); |
154 |
yi = priv->start + (mpi->h + priv->delta) * (t / priv->xtile); |
155 |
|
156 |
/* Copy first (or only) plane */
|
157 |
memcpy_pic( dmpi->planes[0] + xi * by + yi * dmpi->stride[0], |
158 |
mpi->planes[0],
|
159 |
dw, |
160 |
mpi->h, |
161 |
dmpi->stride[0],
|
162 |
mpi->stride[0]);
|
163 |
|
164 |
if (mpi->flags & MP_IMGFLAG_PLANAR) {
|
165 |
/* Copy the other 2 planes */
|
166 |
memcpy_pic( dmpi->planes[1] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[1], |
167 |
mpi->planes[1],
|
168 |
mpi->chroma_width, |
169 |
mpi->chroma_height, |
170 |
dmpi->stride[1],
|
171 |
mpi->stride[1]);
|
172 |
memcpy_pic( dmpi->planes[2] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[2], |
173 |
mpi->planes[2],
|
174 |
mpi->chroma_width, |
175 |
mpi->chroma_height, |
176 |
dmpi->stride[2],
|
177 |
mpi->stride[2]);
|
178 |
} |
179 |
|
180 |
/* Increment current frame */
|
181 |
++priv->frame_cur; |
182 |
|
183 |
if (t == priv->xytile - 1) { |
184 |
/* Display the composition */
|
185 |
dmpi->width = xw; |
186 |
dmpi->height = yh; |
187 |
return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
188 |
} |
189 |
else {
|
190 |
/* Skip the frame */
|
191 |
return 0; |
192 |
} |
193 |
} |
194 |
|
195 |
static void uninit(struct vf_instance *vf) |
196 |
{ |
197 |
/* free local data */
|
198 |
free(vf->priv); |
199 |
} |
200 |
|
201 |
/* rgb/bgr 12...32 supported & some Yxxx */
|
202 |
static int query_format(struct vf_instance *vf, unsigned int fmt) |
203 |
{ |
204 |
switch (fmt) {
|
205 |
/* rgb 12...32 bit */
|
206 |
case IMGFMT_RGB12:
|
207 |
case IMGFMT_RGB15:
|
208 |
case IMGFMT_RGB16:
|
209 |
case IMGFMT_RGB24:
|
210 |
case IMGFMT_RGB32:
|
211 |
/* bgr 12...32 bit */
|
212 |
case IMGFMT_BGR12:
|
213 |
case IMGFMT_BGR15:
|
214 |
case IMGFMT_BGR16:
|
215 |
case IMGFMT_BGR24:
|
216 |
case IMGFMT_BGR32:
|
217 |
/* Various Yxxx Formats */
|
218 |
case IMGFMT_444P:
|
219 |
case IMGFMT_422P:
|
220 |
case IMGFMT_411P:
|
221 |
case IMGFMT_YUY2:
|
222 |
case IMGFMT_YV12:
|
223 |
case IMGFMT_I420:
|
224 |
case IMGFMT_YVU9:
|
225 |
case IMGFMT_IF09:
|
226 |
case IMGFMT_IYUV:
|
227 |
return vf_next_query_format(vf, fmt);
|
228 |
} |
229 |
return 0; |
230 |
} |
231 |
|
232 |
/* Get an integer from the string pointed by s, adjusting s.
|
233 |
* If the value is less then 0 def_val is used.
|
234 |
* Return 0 for ok
|
235 |
*
|
236 |
* Look below ( in vf_open(...) ) for a use ...
|
237 |
*/
|
238 |
static int parse_int(char **s, int *rt, int def_val) |
239 |
{ |
240 |
|
241 |
int t = 0; |
242 |
|
243 |
if (**s) {
|
244 |
/* Get value (dec, hex or octal) */
|
245 |
t = strtol( *s, s, 0 );
|
246 |
|
247 |
/* Use default */
|
248 |
if (t < 0) { |
249 |
t = def_val; |
250 |
} |
251 |
|
252 |
if (**s == ':') { |
253 |
/* Point to next character (problably a digit) */
|
254 |
++(*s); |
255 |
} |
256 |
else if (**s != '\0') { |
257 |
/* Error, we got some wrong char */
|
258 |
return 1; |
259 |
} |
260 |
} |
261 |
else {
|
262 |
t = def_val; |
263 |
} |
264 |
|
265 |
*rt = t; |
266 |
return 0; |
267 |
|
268 |
} |
269 |
|
270 |
/* Main entry funct for the filter */
|
271 |
static int vf_open(vf_instance_t *vf, char *args) |
272 |
{ |
273 |
struct vf_priv_s *p;
|
274 |
int er;
|
275 |
|
276 |
vf->put_image = put_image; |
277 |
vf->query_format = query_format; |
278 |
vf->config = config; |
279 |
vf->uninit = uninit; |
280 |
vf->default_reqs = VFCAP_ACCEPT_STRIDE; |
281 |
/* Private data */
|
282 |
vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); |
283 |
if (p == NULL) { |
284 |
return 0; |
285 |
} |
286 |
|
287 |
if (args == NULL) { |
288 |
/* Use the default */
|
289 |
args = "";
|
290 |
} |
291 |
/* Parse all the arguments */
|
292 |
er = parse_int( &args, &p->xtile, 5 );
|
293 |
er |= parse_int( &args, &p->ytile, 5 );
|
294 |
er |= parse_int( &args, &p->xytile, 0 );
|
295 |
er |= parse_int( &args, &p->start, 2 );
|
296 |
er |= parse_int( &args, &p->delta, 4 );
|
297 |
// er |= parse_int( &args, &p->bkgSet, 0 );
|
298 |
|
299 |
if (er) {
|
300 |
mp_msg(MSGT_VFILTER, MSGL_ERR, MSGTR_MPCODECS_ErrorParsingArgument); |
301 |
return 0; |
302 |
} |
303 |
/* Load some default */
|
304 |
if ((p->xytile <= 0) || (p->xytile > p->xtile * p->ytile)) { |
305 |
p->xytile = p->xtile * p->ytile; |
306 |
} |
307 |
|
308 |
/* Say what happen: use mp_msg(...)? */
|
309 |
if ( mp_msg_test(MSGT_VFILTER,MSGL_V) ) {
|
310 |
printf("vf_tile: tiling %d * %d, output every %d frames\n",
|
311 |
p->xtile, |
312 |
p->ytile, |
313 |
p->xytile); |
314 |
printf("vf_tile: start pixel %d, delta pixel %d\n",
|
315 |
p->start, |
316 |
p->delta); |
317 |
// printf("vf_tile: background 0x%x\n",
|
318 |
// p->bkgSet);
|
319 |
} |
320 |
return 1; |
321 |
} |
322 |
|
323 |
const vf_info_t vf_info_tile = {
|
324 |
"Make a single image tiling x/y images",
|
325 |
"tile",
|
326 |
"Daniele Forghieri",
|
327 |
"",
|
328 |
vf_open, |
329 |
NULL
|
330 |
}; |