Mercurial > libavformat.hg
annotate img.c @ 55:bde449e6b743 libavformat
yes, PNG can be simpler :-)
author | bellard |
---|---|
date | Tue, 04 Feb 2003 23:44:26 +0000 |
parents | 65433f1b2549 |
children | b0e0eb595e29 |
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" |
21 | |
11
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
10
diff
changeset
|
22 #ifdef __MINGW32__ |
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
10
diff
changeset
|
23 # include <windows.h> |
12
d58c983a19a7
redid usleep() fix for BeOS, more consistant with the MINGW32 one. removed a TAB :P
mmu_man
parents:
11
diff
changeset
|
24 # define usleep(t) Sleep((t) / 1000) |
d58c983a19a7
redid usleep() fix for BeOS, more consistant with the MINGW32 one. removed a TAB :P
mmu_man
parents:
11
diff
changeset
|
25 #endif |
d58c983a19a7
redid usleep() fix for BeOS, more consistant with the MINGW32 one. removed a TAB :P
mmu_man
parents:
11
diff
changeset
|
26 #ifdef __BEOS__ |
d58c983a19a7
redid usleep() fix for BeOS, more consistant with the MINGW32 one. removed a TAB :P
mmu_man
parents:
11
diff
changeset
|
27 # ifndef usleep |
d58c983a19a7
redid usleep() fix for BeOS, more consistant with the MINGW32 one. removed a TAB :P
mmu_man
parents:
11
diff
changeset
|
28 # include <OS.h> |
22
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
29 # define usleep(t) snooze((bigtime_t)(t)) |
12
d58c983a19a7
redid usleep() fix for BeOS, more consistant with the MINGW32 one. removed a TAB :P
mmu_man
parents:
11
diff
changeset
|
30 # endif |
11
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
10
diff
changeset
|
31 #endif |
22
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
32 #if defined(CONFIG_OS2) |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
33 # include <stdlib.h> |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
34 # define usleep(t) _sleep2((t) / 1000) |
65433f1b2549
os2 support patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
21
diff
changeset
|
35 #endif |
11
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
10
diff
changeset
|
36 |
0 | 37 typedef struct { |
38 int width; | |
39 int height; | |
40 int img_number; | |
41 int img_size; | |
20 | 42 AVImageFormat *img_fmt; |
43 int pix_fmt; | |
0 | 44 int is_pipe; |
45 char path[1024]; | |
20 | 46 /* temporary usage */ |
47 void *ptr; | |
0 | 48 } VideoData; |
49 | |
8
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
50 int emulate_frame_rate; |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
51 |
20 | 52 static int image_probe(AVProbeData *p) |
0 | 53 { |
21 | 54 if (filename_number_test(p->filename) >= 0 && guess_image_format(p->filename)) |
20 | 55 return AVPROBE_SCORE_MAX; |
56 else | |
57 return 0; | |
0 | 58 } |
59 | |
20 | 60 static int read_header_alloc_cb(void *opaque, AVImageInfo *info) |
0 | 61 { |
20 | 62 VideoData *s = opaque; |
63 | |
64 s->width = info->width; | |
65 s->height = info->height; | |
66 s->pix_fmt = info->pix_fmt; | |
67 /* stop image reading but no error */ | |
68 return 1; | |
0 | 69 } |
70 | |
20 | 71 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
0 | 72 { |
20 | 73 VideoData *s = s1->priv_data; |
74 int i, ret; | |
75 char buf[1024]; | |
76 ByteIOContext pb1, *f = &pb1; | |
77 AVStream *st; | |
78 | |
79 st = av_new_stream(s1, 0); | |
80 if (!st) { | |
81 av_free(s); | |
82 return -ENOMEM; | |
83 } | |
84 | |
85 if (ap && ap->image_format) | |
86 s->img_fmt = ap->image_format; | |
87 | |
88 strcpy(s->path, s1->filename); | |
89 s->img_number = 0; | |
0 | 90 |
20 | 91 /* find format */ |
92 if (s1->iformat->flags & AVFMT_NOFILE) | |
93 s->is_pipe = 0; | |
94 else | |
95 s->is_pipe = 1; | |
96 | |
97 if (!s->is_pipe) { | |
98 /* try to find the first image */ | |
99 for(i=0;i<5;i++) { | |
100 if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0) | |
101 goto fail; | |
102 if (url_fopen(f, buf, URL_RDONLY) >= 0) | |
103 break; | |
104 s->img_number++; | |
105 } | |
106 if (i == 5) | |
107 goto fail; | |
108 } else { | |
109 f = &s1->pb; | |
0 | 110 } |
111 | |
20 | 112 ret = av_read_image(f, s1->filename, s->img_fmt, read_header_alloc_cb, s); |
113 if (ret < 0) | |
114 goto fail1; | |
115 | |
116 if (!s->is_pipe) { | |
117 url_fclose(f); | |
118 } else { | |
119 url_fseek(f, 0, SEEK_SET); | |
120 } | |
0 | 121 |
20 | 122 st->codec.codec_type = CODEC_TYPE_VIDEO; |
123 st->codec.codec_id = CODEC_ID_RAWVIDEO; | |
124 st->codec.width = s->width; | |
125 st->codec.height = s->height; | |
126 st->codec.pix_fmt = s->pix_fmt; | |
127 s->img_size = avpicture_get_size(s->pix_fmt, s->width, s->height); | |
128 | |
129 if (!ap || !ap->frame_rate) | |
130 st->codec.frame_rate = 25 * FRAME_RATE_BASE; | |
131 else | |
132 st->codec.frame_rate = ap->frame_rate; | |
133 | |
0 | 134 return 0; |
20 | 135 fail1: |
136 if (!s->is_pipe) | |
137 url_fclose(f); | |
138 fail: | |
139 av_free(s); | |
140 return -EIO; | |
0 | 141 } |
142 | |
20 | 143 static int read_packet_alloc_cb(void *opaque, AVImageInfo *info) |
0 | 144 { |
20 | 145 VideoData *s = opaque; |
0 | 146 |
20 | 147 if (info->width != s->width || |
148 info->height != s->height) | |
149 return -1; | |
150 avpicture_fill(&info->pict, s->ptr, info->pix_fmt, info->width, info->height); | |
0 | 151 return 0; |
152 } | |
153 | |
154 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) | |
155 { | |
156 VideoData *s = s1->priv_data; | |
157 char filename[1024]; | |
158 int ret; | |
159 ByteIOContext f1, *f; | |
8
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
160 static INT64 first_frame; |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
161 |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
162 if (emulate_frame_rate) { |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
163 if (!first_frame) { |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
164 first_frame = av_gettime(); |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
165 } else { |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
166 INT64 pts; |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
167 INT64 nowus; |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
168 |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
169 nowus = av_gettime() - first_frame; |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
170 |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
171 pts = ((INT64)s->img_number * FRAME_RATE_BASE * 1000000) / (s1->streams[0]->codec.frame_rate); |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
172 |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
173 if (pts > nowus) |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
174 usleep(pts - nowus); |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
175 } |
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
176 } |
0 | 177 |
178 if (!s->is_pipe) { | |
20 | 179 if (get_frame_filename(filename, sizeof(filename), |
180 s->path, s->img_number) < 0) | |
181 return -EIO; | |
0 | 182 f = &f1; |
183 if (url_fopen(f, filename, URL_RDONLY) < 0) | |
184 return -EIO; | |
185 } else { | |
186 f = &s1->pb; | |
187 if (url_feof(f)) | |
188 return -EIO; | |
189 } | |
190 | |
191 av_new_packet(pkt, s->img_size); | |
192 pkt->stream_index = 0; | |
193 | |
20 | 194 s->ptr = pkt->data; |
195 ret = av_read_image(f, filename, s->img_fmt, read_packet_alloc_cb, s); | |
0 | 196 if (!s->is_pipe) { |
197 url_fclose(f); | |
198 } | |
199 | |
200 if (ret < 0) { | |
201 av_free_packet(pkt); | |
202 return -EIO; /* signal EOF */ | |
203 } else { | |
204 pkt->pts = ((INT64)s->img_number * s1->pts_den * FRAME_RATE_BASE) / (s1->streams[0]->codec.frame_rate * s1->pts_num); | |
205 s->img_number++; | |
206 return 0; | |
207 } | |
208 } | |
209 | |
210 static int img_read_close(AVFormatContext *s1) | |
211 { | |
212 return 0; | |
213 } | |
214 | |
215 /******************************************************/ | |
216 /* image output */ | |
217 | |
20 | 218 static int img_set_parameters(AVFormatContext *s, AVFormatParameters *ap) |
0 | 219 { |
20 | 220 VideoData *img = s->priv_data; |
221 AVStream *st; | |
222 AVImageFormat *img_fmt; | |
0 | 223 int i; |
224 | |
20 | 225 /* find output image format */ |
226 if (ap && ap->image_format) { | |
227 img_fmt = ap->image_format; | |
228 } else { | |
229 img_fmt = guess_image_format(s->filename); | |
230 } | |
231 if (!img_fmt) | |
232 return -1; | |
0 | 233 |
20 | 234 if (s->nb_streams != 1) |
235 return -1; | |
0 | 236 |
20 | 237 st = s->streams[0]; |
238 /* we select the first matching format */ | |
239 for(i=0;i<PIX_FMT_NB;i++) { | |
240 if (img_fmt->supported_pixel_formats & (1 << i)) | |
241 break; | |
0 | 242 } |
20 | 243 if (i >= PIX_FMT_NB) |
244 return -1; | |
245 img->img_fmt = img_fmt; | |
246 img->pix_fmt = i; | |
247 st->codec.pix_fmt = img->pix_fmt; | |
0 | 248 return 0; |
249 } | |
250 | |
251 static int img_write_header(AVFormatContext *s) | |
252 { | |
253 VideoData *img = s->priv_data; | |
254 | |
255 img->img_number = 1; | |
256 strcpy(img->path, s->filename); | |
257 | |
258 /* find format */ | |
259 if (s->oformat->flags & AVFMT_NOFILE) | |
260 img->is_pipe = 0; | |
261 else | |
262 img->is_pipe = 1; | |
263 | |
264 return 0; | |
265 } | |
266 | |
267 static int img_write_packet(AVFormatContext *s, int stream_index, | |
268 UINT8 *buf, int size, int force_pts) | |
269 { | |
270 VideoData *img = s->priv_data; | |
271 AVStream *st = s->streams[stream_index]; | |
272 ByteIOContext pb1, *pb; | |
20 | 273 AVPicture *picture; |
274 int width, height, ret; | |
0 | 275 char filename[1024]; |
20 | 276 AVImageInfo info; |
0 | 277 |
278 width = st->codec.width; | |
279 height = st->codec.height; | |
280 | |
20 | 281 picture = (AVPicture *)buf; |
0 | 282 |
20 | 283 if (!img->is_pipe) { |
284 if (get_frame_filename(filename, sizeof(filename), | |
285 img->path, img->img_number) < 0) | |
0 | 286 return -EIO; |
287 pb = &pb1; | |
288 if (url_fopen(pb, filename, URL_WRONLY) < 0) | |
289 return -EIO; | |
290 } else { | |
291 pb = &s->pb; | |
292 } | |
20 | 293 info.width = width; |
294 info.height = height; | |
295 info.pix_fmt = st->codec.pix_fmt; | |
296 info.pict = *picture; | |
297 ret = av_write_image(pb, img->img_fmt, &info); | |
0 | 298 if (!img->is_pipe) { |
299 url_fclose(pb); | |
300 } | |
301 | |
302 img->img_number++; | |
303 return 0; | |
304 } | |
305 | |
306 static int img_write_trailer(AVFormatContext *s) | |
307 { | |
308 return 0; | |
309 } | |
310 | |
20 | 311 /* input */ |
0 | 312 |
20 | 313 static AVInputFormat image_iformat = { |
314 "image", | |
315 "image sequence", | |
0 | 316 sizeof(VideoData), |
20 | 317 image_probe, |
0 | 318 img_read_header, |
319 img_read_packet, | |
320 img_read_close, | |
321 NULL, | |
322 AVFMT_NOFILE | AVFMT_NEEDNUMBER, | |
323 }; | |
324 | |
20 | 325 static AVInputFormat imagepipe_iformat = { |
326 "imagepipe", | |
327 "piped image sequence", | |
0 | 328 sizeof(VideoData), |
329 NULL, /* no probe */ | |
330 img_read_header, | |
331 img_read_packet, | |
332 img_read_close, | |
333 NULL, | |
334 }; | |
335 | |
20 | 336 |
337 /* output */ | |
0 | 338 |
20 | 339 static AVOutputFormat image_oformat = { |
340 "image", | |
341 "image sequence", | |
0 | 342 "", |
20 | 343 "", |
0 | 344 sizeof(VideoData), |
345 CODEC_ID_NONE, | |
346 CODEC_ID_RAWVIDEO, | |
347 img_write_header, | |
348 img_write_packet, | |
349 img_write_trailer, | |
20 | 350 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RAWPICTURE, |
351 img_set_parameters, | |
0 | 352 }; |
353 | |
20 | 354 static AVOutputFormat imagepipe_oformat = { |
355 "imagepipe", | |
356 "piped image sequence", | |
0 | 357 "", |
20 | 358 "", |
0 | 359 sizeof(VideoData), |
360 CODEC_ID_NONE, | |
361 CODEC_ID_RAWVIDEO, | |
362 img_write_header, | |
363 img_write_packet, | |
364 img_write_trailer, | |
21 | 365 AVFMT_RAWPICTURE, |
20 | 366 img_set_parameters, |
0 | 367 }; |
368 | |
369 int img_init(void) | |
370 { | |
20 | 371 av_register_input_format(&image_iformat); |
372 av_register_output_format(&image_oformat); | |
0 | 373 |
20 | 374 av_register_input_format(&imagepipe_iformat); |
375 av_register_output_format(&imagepipe_oformat); | |
0 | 376 |
377 return 0; | |
378 } |