Mercurial > libavformat.hg
annotate img.c @ 229:b0771ae979e3 libavformat
removed ctype.h header
author | bellard |
---|---|
date | Mon, 08 Sep 2003 20:04:44 +0000 |
parents | 66a05c4f8350 |
children | 8ca8b6bc24a5 |
rev | line source |
---|---|
0 | 1 /* |
2 * Image format | |
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
8
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
19 #include <unistd.h> |
0 | 20 #include "avformat.h" |
88 | 21 #include "os_support.h" |
11
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
10
diff
changeset
|
22 |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
23 /* XXX: this is a hack */ |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
24 int loop_input = 0; |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
25 |
0 | 26 typedef struct { |
27 int width; | |
28 int height; | |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
29 int img_first; |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
30 int img_last; |
0 | 31 int img_number; |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
32 int img_count; |
0 | 33 int img_size; |
20 | 34 AVImageFormat *img_fmt; |
35 int pix_fmt; | |
0 | 36 int is_pipe; |
37 char path[1024]; | |
20 | 38 /* temporary usage */ |
39 void *ptr; | |
0 | 40 } VideoData; |
41 | |
189 | 42 |
43 /* return -1 if no image found */ | |
44 static int find_image_range(int *pfirst_index, int *plast_index, | |
45 const char *path) | |
46 { | |
47 char buf[1024]; | |
48 int range, last_index, range1, first_index; | |
49 | |
50 /* find the first image */ | |
51 for(first_index = 0; first_index < 5; first_index++) { | |
52 if (get_frame_filename(buf, sizeof(buf), path, first_index) < 0) | |
53 goto fail; | |
54 if (url_exist(buf)) | |
55 break; | |
56 } | |
57 if (first_index == 5) | |
58 goto fail; | |
59 | |
60 /* find the last image */ | |
61 last_index = first_index; | |
62 for(;;) { | |
63 range = 0; | |
64 for(;;) { | |
65 if (!range) | |
66 range1 = 1; | |
67 else | |
68 range1 = 2 * range; | |
69 if (get_frame_filename(buf, sizeof(buf), path, | |
70 last_index + range1) < 0) | |
71 goto fail; | |
72 if (!url_exist(buf)) | |
73 break; | |
74 range = range1; | |
75 /* just in case... */ | |
76 if (range >= (1 << 30)) | |
77 goto fail; | |
78 } | |
79 /* we are sure than image last_index + range exists */ | |
80 if (!range) | |
81 break; | |
82 last_index += range; | |
83 } | |
84 *pfirst_index = first_index; | |
85 *plast_index = last_index; | |
86 return 0; | |
87 fail: | |
88 return -1; | |
89 } | |
90 | |
91 | |
20 | 92 static int image_probe(AVProbeData *p) |
0 | 93 { |
21 | 94 if (filename_number_test(p->filename) >= 0 && guess_image_format(p->filename)) |
20 | 95 return AVPROBE_SCORE_MAX; |
96 else | |
97 return 0; | |
0 | 98 } |
99 | |
20 | 100 static int read_header_alloc_cb(void *opaque, AVImageInfo *info) |
0 | 101 { |
20 | 102 VideoData *s = opaque; |
103 | |
104 s->width = info->width; | |
105 s->height = info->height; | |
106 s->pix_fmt = info->pix_fmt; | |
107 /* stop image reading but no error */ | |
108 return 1; | |
0 | 109 } |
110 | |
20 | 111 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
0 | 112 { |
20 | 113 VideoData *s = s1->priv_data; |
189 | 114 int ret, first_index, last_index; |
20 | 115 char buf[1024]; |
116 ByteIOContext pb1, *f = &pb1; | |
117 AVStream *st; | |
118 | |
119 st = av_new_stream(s1, 0); | |
120 if (!st) { | |
121 av_free(s); | |
122 return -ENOMEM; | |
123 } | |
124 | |
125 if (ap && ap->image_format) | |
126 s->img_fmt = ap->image_format; | |
127 | |
128 strcpy(s->path, s1->filename); | |
129 s->img_number = 0; | |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
130 s->img_count = 0; |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
131 |
20 | 132 /* find format */ |
133 if (s1->iformat->flags & AVFMT_NOFILE) | |
134 s->is_pipe = 0; | |
135 else | |
136 s->is_pipe = 1; | |
137 | |
189 | 138 if (!ap || !ap->frame_rate) { |
139 st->codec.frame_rate = 25; | |
140 st->codec.frame_rate_base = 1; | |
141 } else { | |
142 st->codec.frame_rate = ap->frame_rate; | |
143 st->codec.frame_rate_base = ap->frame_rate_base; | |
144 } | |
145 | |
20 | 146 if (!s->is_pipe) { |
189 | 147 if (find_image_range(&first_index, &last_index, s->path) < 0) |
148 goto fail; | |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
149 s->img_first = first_index; |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
150 s->img_last = last_index; |
189 | 151 s->img_number = first_index; |
152 /* compute duration */ | |
153 st->start_time = 0; | |
154 st->duration = ((int64_t)AV_TIME_BASE * | |
155 (last_index - first_index + 1) * | |
156 st->codec.frame_rate_base) / st->codec.frame_rate; | |
157 if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0) | |
158 goto fail; | |
159 if (url_fopen(f, buf, URL_RDONLY) < 0) | |
20 | 160 goto fail; |
161 } else { | |
162 f = &s1->pb; | |
0 | 163 } |
164 | |
20 | 165 ret = av_read_image(f, s1->filename, s->img_fmt, read_header_alloc_cb, s); |
166 if (ret < 0) | |
167 goto fail1; | |
168 | |
169 if (!s->is_pipe) { | |
170 url_fclose(f); | |
171 } else { | |
172 url_fseek(f, 0, SEEK_SET); | |
173 } | |
0 | 174 |
20 | 175 st->codec.codec_type = CODEC_TYPE_VIDEO; |
176 st->codec.codec_id = CODEC_ID_RAWVIDEO; | |
177 st->codec.width = s->width; | |
178 st->codec.height = s->height; | |
179 st->codec.pix_fmt = s->pix_fmt; | |
180 s->img_size = avpicture_get_size(s->pix_fmt, s->width, s->height); | |
181 | |
0 | 182 return 0; |
20 | 183 fail1: |
184 if (!s->is_pipe) | |
185 url_fclose(f); | |
186 fail: | |
187 av_free(s); | |
188 return -EIO; | |
0 | 189 } |
190 | |
20 | 191 static int read_packet_alloc_cb(void *opaque, AVImageInfo *info) |
0 | 192 { |
20 | 193 VideoData *s = opaque; |
0 | 194 |
20 | 195 if (info->width != s->width || |
196 info->height != s->height) | |
197 return -1; | |
198 avpicture_fill(&info->pict, s->ptr, info->pix_fmt, info->width, info->height); | |
0 | 199 return 0; |
200 } | |
201 | |
202 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) | |
203 { | |
204 VideoData *s = s1->priv_data; | |
205 char filename[1024]; | |
206 int ret; | |
207 ByteIOContext f1, *f; | |
208 | |
209 if (!s->is_pipe) { | |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
210 /* loop over input */ |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
211 if (loop_input && s->img_number > s->img_last) { |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
212 s->img_number = s->img_first; |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
213 } |
20 | 214 if (get_frame_filename(filename, sizeof(filename), |
215 s->path, s->img_number) < 0) | |
216 return -EIO; | |
0 | 217 f = &f1; |
218 if (url_fopen(f, filename, URL_RDONLY) < 0) | |
219 return -EIO; | |
220 } else { | |
221 f = &s1->pb; | |
222 if (url_feof(f)) | |
223 return -EIO; | |
224 } | |
225 | |
226 av_new_packet(pkt, s->img_size); | |
227 pkt->stream_index = 0; | |
228 | |
20 | 229 s->ptr = pkt->data; |
230 ret = av_read_image(f, filename, s->img_fmt, read_packet_alloc_cb, s); | |
0 | 231 if (!s->is_pipe) { |
232 url_fclose(f); | |
233 } | |
234 | |
235 if (ret < 0) { | |
236 av_free_packet(pkt); | |
237 return -EIO; /* signal EOF */ | |
238 } else { | |
199
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
239 /* XXX: computing this pts is not necessary as it is done in |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
240 the generic code too */ |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
241 pkt->pts = av_rescale((int64_t)s->img_count * s1->streams[0]->codec.frame_rate_base, s1->pts_den, s1->streams[0]->codec.frame_rate) / s1->pts_num; |
66a05c4f8350
suppressed frame number modulus hack - added loop_input hack which I find easier to understand
bellard
parents:
189
diff
changeset
|
242 s->img_count++; |
0 | 243 s->img_number++; |
244 return 0; | |
245 } | |
246 } | |
247 | |
248 static int img_read_close(AVFormatContext *s1) | |
249 { | |
250 return 0; | |
251 } | |
252 | |
253 /******************************************************/ | |
254 /* image output */ | |
255 | |
20 | 256 static int img_set_parameters(AVFormatContext *s, AVFormatParameters *ap) |
0 | 257 { |
20 | 258 VideoData *img = s->priv_data; |
259 AVStream *st; | |
260 AVImageFormat *img_fmt; | |
0 | 261 int i; |
262 | |
20 | 263 /* find output image format */ |
264 if (ap && ap->image_format) { | |
265 img_fmt = ap->image_format; | |
266 } else { | |
267 img_fmt = guess_image_format(s->filename); | |
268 } | |
269 if (!img_fmt) | |
270 return -1; | |
0 | 271 |
20 | 272 if (s->nb_streams != 1) |
273 return -1; | |
0 | 274 |
20 | 275 st = s->streams[0]; |
276 /* we select the first matching format */ | |
277 for(i=0;i<PIX_FMT_NB;i++) { | |
278 if (img_fmt->supported_pixel_formats & (1 << i)) | |
279 break; | |
0 | 280 } |
20 | 281 if (i >= PIX_FMT_NB) |
282 return -1; | |
283 img->img_fmt = img_fmt; | |
284 img->pix_fmt = i; | |
285 st->codec.pix_fmt = img->pix_fmt; | |
0 | 286 return 0; |
287 } | |
288 | |
289 static int img_write_header(AVFormatContext *s) | |
290 { | |
291 VideoData *img = s->priv_data; | |
292 | |
293 img->img_number = 1; | |
294 strcpy(img->path, s->filename); | |
295 | |
296 /* find format */ | |
297 if (s->oformat->flags & AVFMT_NOFILE) | |
298 img->is_pipe = 0; | |
299 else | |
300 img->is_pipe = 1; | |
301 | |
302 return 0; | |
303 } | |
304 | |
305 static int img_write_packet(AVFormatContext *s, int stream_index, | |
65 | 306 uint8_t *buf, int size, int force_pts) |
0 | 307 { |
308 VideoData *img = s->priv_data; | |
309 AVStream *st = s->streams[stream_index]; | |
310 ByteIOContext pb1, *pb; | |
20 | 311 AVPicture *picture; |
312 int width, height, ret; | |
0 | 313 char filename[1024]; |
20 | 314 AVImageInfo info; |
0 | 315 |
316 width = st->codec.width; | |
317 height = st->codec.height; | |
318 | |
20 | 319 picture = (AVPicture *)buf; |
0 | 320 |
20 | 321 if (!img->is_pipe) { |
322 if (get_frame_filename(filename, sizeof(filename), | |
323 img->path, img->img_number) < 0) | |
0 | 324 return -EIO; |
325 pb = &pb1; | |
326 if (url_fopen(pb, filename, URL_WRONLY) < 0) | |
327 return -EIO; | |
328 } else { | |
329 pb = &s->pb; | |
330 } | |
20 | 331 info.width = width; |
332 info.height = height; | |
333 info.pix_fmt = st->codec.pix_fmt; | |
334 info.pict = *picture; | |
335 ret = av_write_image(pb, img->img_fmt, &info); | |
0 | 336 if (!img->is_pipe) { |
337 url_fclose(pb); | |
338 } | |
339 | |
340 img->img_number++; | |
341 return 0; | |
342 } | |
343 | |
344 static int img_write_trailer(AVFormatContext *s) | |
345 { | |
346 return 0; | |
347 } | |
348 | |
20 | 349 /* input */ |
0 | 350 |
20 | 351 static AVInputFormat image_iformat = { |
352 "image", | |
353 "image sequence", | |
0 | 354 sizeof(VideoData), |
20 | 355 image_probe, |
0 | 356 img_read_header, |
357 img_read_packet, | |
358 img_read_close, | |
359 NULL, | |
360 AVFMT_NOFILE | AVFMT_NEEDNUMBER, | |
361 }; | |
362 | |
20 | 363 static AVInputFormat imagepipe_iformat = { |
364 "imagepipe", | |
365 "piped image sequence", | |
0 | 366 sizeof(VideoData), |
367 NULL, /* no probe */ | |
368 img_read_header, | |
369 img_read_packet, | |
370 img_read_close, | |
371 NULL, | |
372 }; | |
373 | |
20 | 374 |
375 /* output */ | |
0 | 376 |
20 | 377 static AVOutputFormat image_oformat = { |
378 "image", | |
379 "image sequence", | |
0 | 380 "", |
20 | 381 "", |
0 | 382 sizeof(VideoData), |
383 CODEC_ID_NONE, | |
384 CODEC_ID_RAWVIDEO, | |
385 img_write_header, | |
386 img_write_packet, | |
387 img_write_trailer, | |
20 | 388 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RAWPICTURE, |
389 img_set_parameters, | |
0 | 390 }; |
391 | |
20 | 392 static AVOutputFormat imagepipe_oformat = { |
393 "imagepipe", | |
394 "piped image sequence", | |
0 | 395 "", |
20 | 396 "", |
0 | 397 sizeof(VideoData), |
398 CODEC_ID_NONE, | |
399 CODEC_ID_RAWVIDEO, | |
400 img_write_header, | |
401 img_write_packet, | |
402 img_write_trailer, | |
21 | 403 AVFMT_RAWPICTURE, |
20 | 404 img_set_parameters, |
0 | 405 }; |
406 | |
407 int img_init(void) | |
408 { | |
20 | 409 av_register_input_format(&image_iformat); |
410 av_register_output_format(&image_oformat); | |
0 | 411 |
20 | 412 av_register_input_format(&imagepipe_iformat); |
413 av_register_output_format(&imagepipe_oformat); | |
0 | 414 |
415 return 0; | |
416 } |