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