Commit | Line | Data |
---|---|---|
de6d9b64 FB |
1 | /* |
2 | * Image format | |
19720f15 | 3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. |
de6d9b64 | 4 | * |
19720f15 FB |
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. | |
de6d9b64 | 9 | * |
19720f15 | 10 | * This library is distributed in the hope that it will be useful, |
de6d9b64 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19720f15 FB |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. | |
de6d9b64 | 14 | * |
19720f15 FB |
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 | |
de6d9b64 | 18 | */ |
38758ab0 | 19 | #include <unistd.h> |
de6d9b64 | 20 | #include "avformat.h" |
4a899dd6 | 21 | #include "os_support.h" |
9b2e001f | 22 | |
de6d9b64 FB |
23 | typedef struct { |
24 | int width; | |
25 | int height; | |
26 | int img_number; | |
27 | int img_size; | |
87a0a681 FB |
28 | AVImageFormat *img_fmt; |
29 | int pix_fmt; | |
de6d9b64 FB |
30 | int is_pipe; |
31 | char path[1024]; | |
87a0a681 FB |
32 | /* temporary usage */ |
33 | void *ptr; | |
de6d9b64 FB |
34 | } VideoData; |
35 | ||
87a0a681 | 36 | static int image_probe(AVProbeData *p) |
de6d9b64 | 37 | { |
94d883e8 | 38 | if (filename_number_test(p->filename) >= 0 && guess_image_format(p->filename)) |
87a0a681 FB |
39 | return AVPROBE_SCORE_MAX; |
40 | else | |
de6d9b64 | 41 | return 0; |
de6d9b64 FB |
42 | } |
43 | ||
87a0a681 | 44 | static int read_header_alloc_cb(void *opaque, AVImageInfo *info) |
de6d9b64 | 45 | { |
87a0a681 | 46 | VideoData *s = opaque; |
de6d9b64 | 47 | |
87a0a681 FB |
48 | s->width = info->width; |
49 | s->height = info->height; | |
50 | s->pix_fmt = info->pix_fmt; | |
51 | /* stop image reading but no error */ | |
52 | return 1; | |
de6d9b64 FB |
53 | } |
54 | ||
55 | static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |
56 | { | |
c9a65ca8 | 57 | VideoData *s = s1->priv_data; |
87a0a681 | 58 | int i, ret; |
de6d9b64 | 59 | char buf[1024]; |
de6d9b64 FB |
60 | ByteIOContext pb1, *f = &pb1; |
61 | AVStream *st; | |
62 | ||
c9a65ca8 | 63 | st = av_new_stream(s1, 0); |
de6d9b64 | 64 | if (!st) { |
1ea4f593 | 65 | av_free(s); |
de6d9b64 FB |
66 | return -ENOMEM; |
67 | } | |
c9a65ca8 | 68 | |
87a0a681 FB |
69 | if (ap && ap->image_format) |
70 | s->img_fmt = ap->image_format; | |
71 | ||
de6d9b64 FB |
72 | strcpy(s->path, s1->filename); |
73 | s->img_number = 0; | |
74 | ||
75 | /* find format */ | |
c9a65ca8 | 76 | if (s1->iformat->flags & AVFMT_NOFILE) |
de6d9b64 FB |
77 | s->is_pipe = 0; |
78 | else | |
79 | s->is_pipe = 1; | |
80 | ||
de6d9b64 FB |
81 | if (!s->is_pipe) { |
82 | /* try to find the first image */ | |
83 | for(i=0;i<5;i++) { | |
9150f42e FB |
84 | if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0) |
85 | goto fail; | |
de6d9b64 FB |
86 | if (url_fopen(f, buf, URL_RDONLY) >= 0) |
87 | break; | |
88 | s->img_number++; | |
89 | } | |
90 | if (i == 5) | |
91 | goto fail; | |
92 | } else { | |
93 | f = &s1->pb; | |
94 | } | |
95 | ||
87a0a681 FB |
96 | ret = av_read_image(f, s1->filename, s->img_fmt, read_header_alloc_cb, s); |
97 | if (ret < 0) | |
98 | goto fail1; | |
de6d9b64 FB |
99 | |
100 | if (!s->is_pipe) { | |
101 | url_fclose(f); | |
102 | } else { | |
103 | url_fseek(f, 0, SEEK_SET); | |
104 | } | |
105 | ||
de6d9b64 FB |
106 | st->codec.codec_type = CODEC_TYPE_VIDEO; |
107 | st->codec.codec_id = CODEC_ID_RAWVIDEO; | |
108 | st->codec.width = s->width; | |
109 | st->codec.height = s->height; | |
87a0a681 FB |
110 | st->codec.pix_fmt = s->pix_fmt; |
111 | s->img_size = avpicture_get_size(s->pix_fmt, s->width, s->height); | |
112 | ||
14bea432 MN |
113 | if (!ap || !ap->frame_rate){ |
114 | st->codec.frame_rate = 25; | |
115 | st->codec.frame_rate_base = 1; | |
116 | }else{ | |
117 | st->codec.frame_rate = ap->frame_rate; | |
118 | st->codec.frame_rate_base = ap->frame_rate_base; | |
119 | } | |
de6d9b64 FB |
120 | |
121 | return 0; | |
122 | fail1: | |
123 | if (!s->is_pipe) | |
124 | url_fclose(f); | |
125 | fail: | |
1ea4f593 | 126 | av_free(s); |
de6d9b64 FB |
127 | return -EIO; |
128 | } | |
129 | ||
87a0a681 | 130 | static int read_packet_alloc_cb(void *opaque, AVImageInfo *info) |
de6d9b64 | 131 | { |
87a0a681 FB |
132 | VideoData *s = opaque; |
133 | ||
134 | if (info->width != s->width || | |
135 | info->height != s->height) | |
136 | return -1; | |
137 | avpicture_fill(&info->pict, s->ptr, info->pix_fmt, info->width, info->height); | |
de6d9b64 FB |
138 | return 0; |
139 | } | |
140 | ||
87a0a681 | 141 | static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) |
de6d9b64 | 142 | { |
87a0a681 FB |
143 | VideoData *s = s1->priv_data; |
144 | char filename[1024]; | |
145 | int ret; | |
146 | ByteIOContext f1, *f; | |
de6d9b64 | 147 | |
87a0a681 FB |
148 | if (!s->is_pipe) { |
149 | if (get_frame_filename(filename, sizeof(filename), | |
150 | s->path, s->img_number) < 0) | |
151 | return -EIO; | |
152 | f = &f1; | |
153 | if (url_fopen(f, filename, URL_RDONLY) < 0) | |
154 | return -EIO; | |
155 | } else { | |
156 | f = &s1->pb; | |
157 | if (url_feof(f)) | |
158 | return -EIO; | |
159 | } | |
6775c758 | 160 | |
87a0a681 FB |
161 | av_new_packet(pkt, s->img_size); |
162 | pkt->stream_index = 0; | |
163 | ||
164 | s->ptr = pkt->data; | |
165 | ret = av_read_image(f, filename, s->img_fmt, read_packet_alloc_cb, s); | |
166 | if (!s->is_pipe) { | |
167 | url_fclose(f); | |
6775c758 FB |
168 | } |
169 | ||
87a0a681 FB |
170 | if (ret < 0) { |
171 | av_free_packet(pkt); | |
172 | return -EIO; /* signal EOF */ | |
173 | } else { | |
14bea432 | 174 | pkt->pts = av_rescale((int64_t)s->img_number * s1->streams[0]->codec.frame_rate_base, s1->pts_den, s1->streams[0]->codec.frame_rate) / s1->pts_num; |
87a0a681 FB |
175 | s->img_number++; |
176 | return 0; | |
177 | } | |
6775c758 FB |
178 | } |
179 | ||
87a0a681 | 180 | static int img_read_close(AVFormatContext *s1) |
de6d9b64 | 181 | { |
de6d9b64 FB |
182 | return 0; |
183 | } | |
184 | ||
87a0a681 FB |
185 | /******************************************************/ |
186 | /* image output */ | |
187 | ||
188 | static int img_set_parameters(AVFormatContext *s, AVFormatParameters *ap) | |
ad436907 | 189 | { |
87a0a681 FB |
190 | VideoData *img = s->priv_data; |
191 | AVStream *st; | |
192 | AVImageFormat *img_fmt; | |
193 | int i; | |
194 | ||
195 | /* find output image format */ | |
196 | if (ap && ap->image_format) { | |
197 | img_fmt = ap->image_format; | |
ad436907 | 198 | } else { |
87a0a681 | 199 | img_fmt = guess_image_format(s->filename); |
ad436907 | 200 | } |
87a0a681 FB |
201 | if (!img_fmt) |
202 | return -1; | |
ad436907 | 203 | |
87a0a681 FB |
204 | if (s->nb_streams != 1) |
205 | return -1; | |
206 | ||
207 | st = s->streams[0]; | |
208 | /* we select the first matching format */ | |
209 | for(i=0;i<PIX_FMT_NB;i++) { | |
210 | if (img_fmt->supported_pixel_formats & (1 << i)) | |
211 | break; | |
ad436907 | 212 | } |
87a0a681 FB |
213 | if (i >= PIX_FMT_NB) |
214 | return -1; | |
215 | img->img_fmt = img_fmt; | |
216 | img->pix_fmt = i; | |
217 | st->codec.pix_fmt = img->pix_fmt; | |
ad436907 HM |
218 | return 0; |
219 | } | |
220 | ||
de6d9b64 FB |
221 | static int img_write_header(AVFormatContext *s) |
222 | { | |
c9a65ca8 | 223 | VideoData *img = s->priv_data; |
de6d9b64 | 224 | |
de6d9b64 FB |
225 | img->img_number = 1; |
226 | strcpy(img->path, s->filename); | |
227 | ||
228 | /* find format */ | |
c9a65ca8 | 229 | if (s->oformat->flags & AVFMT_NOFILE) |
de6d9b64 FB |
230 | img->is_pipe = 0; |
231 | else | |
232 | img->is_pipe = 1; | |
233 | ||
de6d9b64 | 234 | return 0; |
de6d9b64 FB |
235 | } |
236 | ||
237 | static int img_write_packet(AVFormatContext *s, int stream_index, | |
0c1a9eda | 238 | uint8_t *buf, int size, int force_pts) |
de6d9b64 FB |
239 | { |
240 | VideoData *img = s->priv_data; | |
241 | AVStream *st = s->streams[stream_index]; | |
242 | ByteIOContext pb1, *pb; | |
87a0a681 FB |
243 | AVPicture *picture; |
244 | int width, height, ret; | |
de6d9b64 | 245 | char filename[1024]; |
87a0a681 | 246 | AVImageInfo info; |
de6d9b64 FB |
247 | |
248 | width = st->codec.width; | |
249 | height = st->codec.height; | |
ad436907 | 250 | |
87a0a681 | 251 | picture = (AVPicture *)buf; |
de6d9b64 | 252 | |
de6d9b64 | 253 | if (!img->is_pipe) { |
87a0a681 FB |
254 | if (get_frame_filename(filename, sizeof(filename), |
255 | img->path, img->img_number) < 0) | |
256 | return -EIO; | |
de6d9b64 FB |
257 | pb = &pb1; |
258 | if (url_fopen(pb, filename, URL_WRONLY) < 0) | |
259 | return -EIO; | |
260 | } else { | |
261 | pb = &s->pb; | |
262 | } | |
87a0a681 FB |
263 | info.width = width; |
264 | info.height = height; | |
265 | info.pix_fmt = st->codec.pix_fmt; | |
266 | info.pict = *picture; | |
267 | ret = av_write_image(pb, img->img_fmt, &info); | |
de6d9b64 FB |
268 | if (!img->is_pipe) { |
269 | url_fclose(pb); | |
270 | } | |
271 | ||
272 | img->img_number++; | |
273 | return 0; | |
274 | } | |
275 | ||
276 | static int img_write_trailer(AVFormatContext *s) | |
277 | { | |
de6d9b64 FB |
278 | return 0; |
279 | } | |
280 | ||
87a0a681 | 281 | /* input */ |
de6d9b64 | 282 | |
87a0a681 FB |
283 | static AVInputFormat image_iformat = { |
284 | "image", | |
285 | "image sequence", | |
c9a65ca8 | 286 | sizeof(VideoData), |
87a0a681 | 287 | image_probe, |
de6d9b64 FB |
288 | img_read_header, |
289 | img_read_packet, | |
290 | img_read_close, | |
291 | NULL, | |
9150f42e | 292 | AVFMT_NOFILE | AVFMT_NEEDNUMBER, |
de6d9b64 FB |
293 | }; |
294 | ||
87a0a681 FB |
295 | static AVInputFormat imagepipe_iformat = { |
296 | "imagepipe", | |
297 | "piped image sequence", | |
c9a65ca8 FB |
298 | sizeof(VideoData), |
299 | NULL, /* no probe */ | |
de6d9b64 FB |
300 | img_read_header, |
301 | img_read_packet, | |
302 | img_read_close, | |
303 | NULL, | |
de6d9b64 FB |
304 | }; |
305 | ||
de6d9b64 | 306 | |
87a0a681 | 307 | /* output */ |
6775c758 | 308 | |
87a0a681 FB |
309 | static AVOutputFormat image_oformat = { |
310 | "image", | |
311 | "image sequence", | |
6775c758 | 312 | "", |
6775c758 | 313 | "", |
c9a65ca8 | 314 | sizeof(VideoData), |
6775c758 FB |
315 | CODEC_ID_NONE, |
316 | CODEC_ID_RAWVIDEO, | |
317 | img_write_header, | |
318 | img_write_packet, | |
319 | img_write_trailer, | |
87a0a681 FB |
320 | AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RAWPICTURE, |
321 | img_set_parameters, | |
6775c758 | 322 | }; |
c9a65ca8 | 323 | |
87a0a681 FB |
324 | static AVOutputFormat imagepipe_oformat = { |
325 | "imagepipe", | |
326 | "piped image sequence", | |
327 | "", | |
ad436907 | 328 | "", |
ad436907 HM |
329 | sizeof(VideoData), |
330 | CODEC_ID_NONE, | |
331 | CODEC_ID_RAWVIDEO, | |
332 | img_write_header, | |
333 | img_write_packet, | |
334 | img_write_trailer, | |
94d883e8 | 335 | AVFMT_RAWPICTURE, |
87a0a681 | 336 | img_set_parameters, |
ad436907 HM |
337 | }; |
338 | ||
c9a65ca8 FB |
339 | int img_init(void) |
340 | { | |
87a0a681 FB |
341 | av_register_input_format(&image_iformat); |
342 | av_register_output_format(&image_oformat); | |
c9a65ca8 | 343 | |
87a0a681 FB |
344 | av_register_input_format(&imagepipe_iformat); |
345 | av_register_output_format(&imagepipe_oformat); | |
ad436907 | 346 | |
c9a65ca8 FB |
347 | return 0; |
348 | } |