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