image2 / image API cleanup phase-1
[libav.git] / libavformat / img2.c
CommitLineData
03cfe134
MN
1/*
2 * Image format
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
4 * Copyright (c) 2004 Michael Niedermayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include "avformat.h"
21
22typedef struct {
23 int img_first;
24 int img_last;
25 int img_number;
26 int img_count;
27 int is_pipe;
28 char path[1024];
29} VideoData;
30
31typedef struct {
32 enum CodecID id;
33 const char *str;
34} IdStrMap;
35
36static const IdStrMap img_tags[] = {
37 { CODEC_ID_MJPEG , "jpeg"},
38 { CODEC_ID_MJPEG , "jpg"},
39 { CODEC_ID_LJPEG , "ljpg"},
40 { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
41 { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
42 { CODEC_ID_MPEG4 , "mpg4-img"},
43 { CODEC_ID_FFV1 , "ffv1-img"},
44 {0, NULL}
45};
46
47static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
48{
49 while(*str && *str!='.') str++;
50 if(*str) str++;
51
52 while (tags->id) {
53 int i;
54 for(i=0; toupper(tags->str[i]) == toupper(str[i]); i++){
55 if(tags->str[i]==0 && str[i]==0)
56 return tags->id;
57 }
58
59 tags++;
60 }
61 return CODEC_ID_NONE;
62}
63
64static const char *av_id2str(const IdStrMap *tags, enum CodecID id)
65{
66 while (tags->id) {
67 if(tags->id == id)
68 return tags->str;
69 tags++;
70 }
71 return NULL;
72}
73
74/* return -1 if no image found */
75static int find_image_range(int *pfirst_index, int *plast_index,
76 const char *path)
77{
78 char buf[1024];
79 int range, last_index, range1, first_index;
80
81 /* find the first image */
82 for(first_index = 0; first_index < 5; first_index++) {
83 if (get_frame_filename(buf, sizeof(buf), path, first_index) < 0)
84 goto fail;
85 if (url_exist(buf))
86 break;
87 }
88 if (first_index == 5)
89 goto fail;
90
91 /* find the last image */
92 last_index = first_index;
93 for(;;) {
94 range = 0;
95 for(;;) {
96 if (!range)
97 range1 = 1;
98 else
99 range1 = 2 * range;
100 if (get_frame_filename(buf, sizeof(buf), path,
101 last_index + range1) < 0)
102 goto fail;
103 if (!url_exist(buf))
104 break;
105 range = range1;
106 /* just in case... */
107 if (range >= (1 << 30))
108 goto fail;
109 }
110 /* we are sure than image last_index + range exists */
111 if (!range)
112 break;
113 last_index += range;
114 }
115 *pfirst_index = first_index;
116 *plast_index = last_index;
117 return 0;
118 fail:
119 return -1;
120}
121
122
123static int image_probe(AVProbeData *p)
124{
125 if (filename_number_test(p->filename) >= 0 && av_str2id(img_tags, p->filename))
126 return AVPROBE_SCORE_MAX;
127 else
128 return 0;
129}
130
131static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
132{
133 VideoData *s = s1->priv_data;
134 int first_index, last_index;
135 char buf[1024];
136 ByteIOContext pb1, *f = &pb1;
137 AVStream *st;
138
139 s1->ctx_flags |= AVFMTCTX_NOHEADER;
140
141 st = av_new_stream(s1, 0);
142 if (!st) {
143 av_free(s);
144 return -ENOMEM;
145 }
146
147 strcpy(s->path, s1->filename);
148 s->img_number = 0;
149 s->img_count = 0;
150
151 /* find format */
152 if (s1->iformat->flags & AVFMT_NOFILE)
153 s->is_pipe = 0;
154 else
155 s->is_pipe = 1;
156
157 if (!ap || !ap->frame_rate) {
158 st->codec.frame_rate = 25;
159 st->codec.frame_rate_base = 1;
160 } else {
161 st->codec.frame_rate = ap->frame_rate;
162 st->codec.frame_rate_base = ap->frame_rate_base;
163 }
164
165 if (!s->is_pipe) {
166 if (find_image_range(&first_index, &last_index, s->path) < 0)
167 goto fail;
168 s->img_first = first_index;
169 s->img_last = last_index;
170 s->img_number = first_index;
171 /* compute duration */
172 st->start_time = 0;
173 st->duration = ((int64_t)AV_TIME_BASE *
174 (last_index - first_index + 1) *
175 st->codec.frame_rate_base) / st->codec.frame_rate;
176 if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
177 goto fail;
178 if (url_fopen(f, buf, URL_RDONLY) < 0)
179 goto fail;
180 } else {
181 f = &s1->pb;
182 }
183
184 if (!s->is_pipe) {
185 url_fclose(f);
186 } else {
187 url_fseek(f, 0, SEEK_SET);
188 }
189
190 st->codec.codec_type = CODEC_TYPE_VIDEO;
191 st->codec.codec_id = av_str2id(img_tags, s->path);
192
193 return 0;
194
195 if (!s->is_pipe)
196 url_fclose(f);
197 fail:
198 av_free(s);
199 return AVERROR_IO;
200}
201
202static 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) {
210 /* loop over input */
211/* if (loop_input && s->img_number > s->img_last) {
212 s->img_number = s->img_first;
213 }*/
214 if (get_frame_filename(filename, sizeof(filename),
215 s->path, s->img_number) < 0)
216 return AVERROR_IO;
217 f = &f1;
218 if (url_fopen(f, filename, URL_RDONLY) < 0)
219 return AVERROR_IO;
220 } else {
221 f = &s1->pb;
222 if (url_feof(f))
223 return AVERROR_IO;
224 }
225
226 if (s->is_pipe) {
227 av_new_packet(pkt, 4096);
228 }else{
229 av_new_packet(pkt, url_filesize(url_fileno(f)));
230 }
231 pkt->stream_index = 0;
232 pkt->flags |= PKT_FLAG_KEY;
233
234 ret = get_buffer(f, pkt->data, pkt->size);
235 if (!s->is_pipe) {
236 url_fclose(f);
237 }
238
239 if (ret <= 0) {
240 av_free_packet(pkt);
241 return AVERROR_IO; /* signal EOF */
242 } else {
243 s->img_count++;
244 s->img_number++;
245 return 0;
246 }
247}
248
249static int img_read_close(AVFormatContext *s1)
250{
251 return 0;
252}
253
254/******************************************************/
255/* image output */
256
257static int img_write_header(AVFormatContext *s)
258{
259 VideoData *img = s->priv_data;
260
261 img->img_number = 1;
262 strcpy(img->path, s->filename);
263
264 /* find format */
265 if (s->oformat->flags & AVFMT_NOFILE)
266 img->is_pipe = 0;
267 else
268 img->is_pipe = 1;
269
270 return 0;
271}
272
273static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
274{
275 VideoData *img = s->priv_data;
276 ByteIOContext pb1, *pb;
277 char filename[1024];
278
279 if (!img->is_pipe) {
280 if (get_frame_filename(filename, sizeof(filename),
281 img->path, img->img_number) < 0)
282 return AVERROR_IO;
283 pb = &pb1;
284 if (url_fopen(pb, filename, URL_WRONLY) < 0)
285 return AVERROR_IO;
286 } else {
287 pb = &s->pb;
288 }
289
290 put_buffer(pb, pkt->data, pkt->size);
291 put_flush_packet(pb);
292 if (!img->is_pipe) {
293 url_fclose(pb);
294 }
295
296 img->img_number++;
297 return 0;
298}
299
300static int img_write_trailer(AVFormatContext *s)
301{
302 return 0;
303}
304
305/* input */
306
307static AVInputFormat image2_iformat = {
308 "image2",
309 "image2 sequence",
310 sizeof(VideoData),
311 image_probe,
312 img_read_header,
313 img_read_packet,
314 img_read_close,
315 NULL,
316 NULL,
317 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
318};
319
320static AVInputFormat image2pipe_iformat = {
321 "image2pipe",
322 "piped image2 sequence",
323 sizeof(VideoData),
324 NULL, /* no probe */
325 img_read_header,
326 img_read_packet,
327 img_read_close,
328 NULL,
329};
330
331
332/* output */
333
334static AVOutputFormat image2_oformat = {
335 "image2",
336 "image2 sequence",
337 "",
338 "",
339 sizeof(VideoData),
340 CODEC_ID_NONE,
341 CODEC_ID_MJPEG,
342 img_write_header,
343 img_write_packet,
344 img_write_trailer,
345 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
346};
347
348static AVOutputFormat image2pipe_oformat = {
349 "image2pipe",
350 "piped image2 sequence",
351 "",
352 "",
353 sizeof(VideoData),
354 CODEC_ID_NONE,
355 CODEC_ID_MJPEG,
356 img_write_header,
357 img_write_packet,
358 img_write_trailer,
359};
360
361int img2_init(void)
362{
363 av_register_input_format(&image2_iformat);
364 av_register_output_format(&image2_oformat);
365
366 av_register_input_format(&image2pipe_iformat);
367 av_register_output_format(&image2pipe_oformat);
368
369 return 0;
370}