support single images, remove copy/paste junk
[ffmpeg.git] / libavformat / img2.c
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
22 typedef 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
31 typedef struct {
32     enum CodecID id;
33     const char *str;
34 } IdStrMap;
35
36 static 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
47 static 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
64 static 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 */
75 static 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             *pfirst_index = 
85             *plast_index = 1;
86             return 0;
87         }
88         if (url_exist(buf))
89             break;
90     }
91     if (first_index == 5)
92         goto fail;
93     
94     /* find the last image */
95     last_index = first_index;
96     for(;;) {
97         range = 0;
98         for(;;) {
99             if (!range)
100                 range1 = 1;
101             else
102                 range1 = 2 * range;
103             if (get_frame_filename(buf, sizeof(buf), path, 
104                                    last_index + range1) < 0)
105                 goto fail;
106             if (!url_exist(buf))
107                 break;
108             range = range1;
109             /* just in case... */
110             if (range >= (1 << 30))
111                 goto fail;
112         }
113         /* we are sure than image last_index + range exists */
114         if (!range)
115             break;
116         last_index += range;
117     }
118     *pfirst_index = first_index;
119     *plast_index = last_index;
120     return 0;
121  fail:
122     return -1;
123 }
124
125
126 static int image_probe(AVProbeData *p)
127 {
128     if (filename_number_test(p->filename) >= 0 && av_str2id(img_tags, p->filename))
129         return AVPROBE_SCORE_MAX;
130     else
131         return 0;
132 }
133
134 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
135 {
136     VideoData *s = s1->priv_data;
137     int first_index, last_index;
138     AVStream *st;
139
140     s1->ctx_flags |= AVFMTCTX_NOHEADER;
141
142     st = av_new_stream(s1, 0);
143     if (!st) {
144         av_free(s);
145         return -ENOMEM;
146     }
147
148     strcpy(s->path, s1->filename);
149     s->img_number = 0;
150     s->img_count = 0;
151     
152     /* find format */
153     if (s1->iformat->flags & AVFMT_NOFILE)
154         s->is_pipe = 0;
155     else
156         s->is_pipe = 1;
157         
158     if (!ap || !ap->frame_rate) {
159         st->codec.frame_rate      = 25;
160         st->codec.frame_rate_base = 1;
161     } else {
162         st->codec.frame_rate      = ap->frame_rate;
163         st->codec.frame_rate_base = ap->frame_rate_base;
164     }
165     
166     if (!s->is_pipe) {
167         if (find_image_range(&first_index, &last_index, s->path) < 0)
168             goto fail;
169         s->img_first = first_index;
170         s->img_last = last_index;
171         s->img_number = first_index;
172         /* compute duration */
173         st->start_time = 0;
174         st->duration = ((int64_t)AV_TIME_BASE * 
175                         (last_index - first_index + 1) * 
176                         st->codec.frame_rate_base) / st->codec.frame_rate;
177     }
178     
179     st->codec.codec_type = CODEC_TYPE_VIDEO;
180     st->codec.codec_id = av_str2id(img_tags, s->path);
181
182     return 0;
183  
184  fail:
185     av_free(s);
186     return AVERROR_IO;
187 }
188
189 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
190 {
191     VideoData *s = s1->priv_data;
192     char filename[1024];
193     int ret;
194     ByteIOContext f1, *f;
195
196     if (!s->is_pipe) {
197         /* loop over input */
198 /*        if (loop_input && s->img_number > s->img_last) {
199             s->img_number = s->img_first;
200         }*/
201         if (get_frame_filename(filename, sizeof(filename),
202                                s->path, s->img_number)<0 && s->img_number > 1)
203             return AVERROR_IO;
204         f = &f1;
205         if (url_fopen(f, filename, URL_RDONLY) < 0)
206             return AVERROR_IO;
207     } else {
208         f = &s1->pb;
209         if (url_feof(f))
210             return AVERROR_IO;
211     }
212
213     if (s->is_pipe) {
214         av_new_packet(pkt, 4096);
215     }else{
216         av_new_packet(pkt, url_filesize(url_fileno(f)));
217     }
218     pkt->stream_index = 0;
219     pkt->flags |= PKT_FLAG_KEY;
220
221     ret = get_buffer(f, pkt->data, pkt->size);
222     if (!s->is_pipe) {
223         url_fclose(f);
224     }
225
226     if (ret <= 0) {
227         av_free_packet(pkt);
228         return AVERROR_IO; /* signal EOF */
229     } else {
230         s->img_count++;
231         s->img_number++;
232         return 0;
233     }
234 }
235
236 static int img_read_close(AVFormatContext *s1)
237 {
238     return 0;
239 }
240
241 /******************************************************/
242 /* image output */
243
244 static int img_write_header(AVFormatContext *s)
245 {
246     VideoData *img = s->priv_data;
247
248     img->img_number = 1;
249     strcpy(img->path, s->filename);
250
251     /* find format */
252     if (s->oformat->flags & AVFMT_NOFILE)
253         img->is_pipe = 0;
254     else
255         img->is_pipe = 1;
256         
257     return 0;
258 }
259
260 static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
261 {
262     VideoData *img = s->priv_data;
263     ByteIOContext pb1, *pb;
264     char filename[1024];
265
266     if (!img->is_pipe) {
267         if (get_frame_filename(filename, sizeof(filename), 
268                                img->path, img->img_number) < 0 && img->img_number>1)
269             return AVERROR_IO;
270         pb = &pb1;
271         if (url_fopen(pb, filename, URL_WRONLY) < 0)
272             return AVERROR_IO;
273     } else {
274         pb = &s->pb;
275     }
276
277     put_buffer(pb, pkt->data, pkt->size);
278     put_flush_packet(pb);
279     if (!img->is_pipe) {
280         url_fclose(pb);
281     }
282
283     img->img_number++;
284     return 0;
285 }
286
287 static int img_write_trailer(AVFormatContext *s)
288 {
289     return 0;
290 }
291
292 /* input */
293
294 static AVInputFormat image2_iformat = {
295     "image2",
296     "image2 sequence",
297     sizeof(VideoData),
298     image_probe,
299     img_read_header,
300     img_read_packet,
301     img_read_close,
302     NULL,
303     NULL,
304     AVFMT_NOFILE,
305 };
306
307 static AVInputFormat image2pipe_iformat = {
308     "image2pipe",
309     "piped image2 sequence",
310     sizeof(VideoData),
311     NULL, /* no probe */
312     img_read_header,
313     img_read_packet,
314     img_read_close,
315     NULL,
316 };
317
318
319 /* output */
320
321 static AVOutputFormat image2_oformat = {
322     "image2",
323     "image2 sequence",
324     "",
325     "",
326     sizeof(VideoData),
327     CODEC_ID_NONE,
328     CODEC_ID_MJPEG,
329     img_write_header,
330     img_write_packet,
331     img_write_trailer,
332     AVFMT_NOFILE,
333 };
334
335 static AVOutputFormat image2pipe_oformat = {
336     "image2pipe",
337     "piped image2 sequence",
338     "",
339     "",
340     sizeof(VideoData),
341     CODEC_ID_NONE,
342     CODEC_ID_MJPEG,
343     img_write_header,
344     img_write_packet,
345     img_write_trailer,
346 };
347
348 int img2_init(void)
349 {
350     av_register_input_format(&image2_iformat);
351     av_register_output_format(&image2_oformat);
352
353     av_register_input_format(&image2pipe_iformat);
354     av_register_output_format(&image2pipe_oformat);
355     
356     return 0;
357 }