]> git.sesse.net Git - ffmpeg/blob - libavformat/img2.c
add loop_input to AVFormatContext, getting rid of old hack
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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_PPM       , "ppm"},
42     { CODEC_ID_PGM       , "pgm"},
43     { CODEC_ID_PGMYUV    , "pgmyuv"},
44     { CODEC_ID_PBM       , "pbm"},
45     { CODEC_ID_PAM       , "pam"},
46     { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
47     { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
48     { CODEC_ID_MPEG4     , "mpg4-img"},
49     { CODEC_ID_FFV1      , "ffv1-img"},
50     { CODEC_ID_RAWVIDEO  , "y"},
51     { CODEC_ID_BMP       , "bmp"},
52     {0, NULL}
53 };
54
55 static int sizes[][2] = {
56     { 640, 480 },
57     { 720, 480 },
58     { 720, 576 },
59     { 352, 288 },
60     { 352, 240 },
61     { 160, 128 },
62     { 512, 384 },
63     { 640, 352 },
64     { 640, 240 },
65 };
66
67 static int infer_size(int *width_ptr, int *height_ptr, int size)
68 {
69     int i;
70
71     for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
72         if ((sizes[i][0] * sizes[i][1]) == size) {
73             *width_ptr = sizes[i][0];
74             *height_ptr = sizes[i][1];
75             return 0;
76         }
77     }
78     return -1;
79 }
80 static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
81 {
82     str= strrchr(str, '.');
83     if(!str) return CODEC_ID_NONE;
84     str++;
85
86     while (tags->id) {
87         int i;
88         for(i=0; toupper(tags->str[i]) == toupper(str[i]); i++){
89             if(tags->str[i]==0 && str[i]==0)
90                 return tags->id;
91         }
92
93         tags++;
94     }
95     return CODEC_ID_NONE;
96 }
97
98 /* return -1 if no image found */
99 static int find_image_range(int *pfirst_index, int *plast_index,
100                             const char *path)
101 {
102     char buf[1024];
103     int range, last_index, range1, first_index;
104
105     /* find the first image */
106     for(first_index = 0; first_index < 5; first_index++) {
107         if (get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
108             *pfirst_index =
109             *plast_index = 1;
110             return 0;
111         }
112         if (url_exist(buf))
113             break;
114     }
115     if (first_index == 5)
116         goto fail;
117
118     /* find the last image */
119     last_index = first_index;
120     for(;;) {
121         range = 0;
122         for(;;) {
123             if (!range)
124                 range1 = 1;
125             else
126                 range1 = 2 * range;
127             if (get_frame_filename(buf, sizeof(buf), path,
128                                    last_index + range1) < 0)
129                 goto fail;
130             if (!url_exist(buf))
131                 break;
132             range = range1;
133             /* just in case... */
134             if (range >= (1 << 30))
135                 goto fail;
136         }
137         /* we are sure than image last_index + range exists */
138         if (!range)
139             break;
140         last_index += range;
141     }
142     *pfirst_index = first_index;
143     *plast_index = last_index;
144     return 0;
145  fail:
146     return -1;
147 }
148
149
150 static int image_probe(AVProbeData *p)
151 {
152     if (filename_number_test(p->filename) >= 0 && av_str2id(img_tags, p->filename))
153         return AVPROBE_SCORE_MAX;
154     else
155         return 0;
156 }
157
158 enum CodecID av_guess_image2_codec(const char *filename){
159     return av_str2id(img_tags, filename);
160 }
161
162 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
163 {
164     VideoData *s = s1->priv_data;
165     int first_index, last_index;
166     AVStream *st;
167
168     s1->ctx_flags |= AVFMTCTX_NOHEADER;
169
170     st = av_new_stream(s1, 0);
171     if (!st) {
172         return -ENOMEM;
173     }
174
175     pstrcpy(s->path, sizeof(s->path), s1->filename);
176     s->img_number = 0;
177     s->img_count = 0;
178
179     /* find format */
180     if (s1->iformat->flags & AVFMT_NOFILE)
181         s->is_pipe = 0;
182     else{
183         s->is_pipe = 1;
184         st->need_parsing= 1;
185     }
186
187     if (!ap->time_base.num) {
188         av_set_pts_info(st, 60, 1, 25);
189     } else {
190         av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den);
191     }
192
193     if(ap->width && ap->height){
194         st->codec->width = ap->width;
195         st->codec->height= ap->height;
196     }
197
198     if (!s->is_pipe) {
199         if (find_image_range(&first_index, &last_index, s->path) < 0)
200             return AVERROR_IO;
201         s->img_first = first_index;
202         s->img_last = last_index;
203         s->img_number = first_index;
204         /* compute duration */
205         st->start_time = 0;
206         st->duration = last_index - first_index + 1;
207     }
208
209     if(ap->video_codec_id){
210         st->codec->codec_type = CODEC_TYPE_VIDEO;
211         st->codec->codec_id = ap->video_codec_id;
212     }else if(ap->audio_codec_id){
213         st->codec->codec_type = CODEC_TYPE_AUDIO;
214         st->codec->codec_id = ap->audio_codec_id;
215     }else{
216         st->codec->codec_type = CODEC_TYPE_VIDEO;
217         st->codec->codec_id = av_str2id(img_tags, s->path);
218     }
219     if(st->codec->codec_type == CODEC_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE)
220         st->codec->pix_fmt = ap->pix_fmt;
221
222     return 0;
223 }
224
225 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
226 {
227     VideoData *s = s1->priv_data;
228     char filename[1024];
229     int i;
230     int size[3]={0}, ret[3]={0};
231     ByteIOContext f1[3], *f[3]= {&f1[0], &f1[1], &f1[2]};
232     AVCodecContext *codec= s1->streams[0]->codec;
233
234     if (!s->is_pipe) {
235         /* loop over input */
236         if (s1->loop_input && s->img_number > s->img_last) {
237             s->img_number = s->img_first;
238         }
239         if (get_frame_filename(filename, sizeof(filename),
240                                s->path, s->img_number)<0 && s->img_number > 1)
241             return AVERROR_IO;
242         for(i=0; i<3; i++){
243             if (url_fopen(f[i], filename, URL_RDONLY) < 0)
244                 return AVERROR_IO;
245             size[i]= url_fsize(f[i]);
246
247             if(codec->codec_id != CODEC_ID_RAWVIDEO)
248                 break;
249             filename[ strlen(filename) - 1 ]= 'U' + i;
250         }
251
252         if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
253             infer_size(&codec->width, &codec->height, size[0]);
254     } else {
255         f[0] = &s1->pb;
256         if (url_feof(f[0]))
257             return AVERROR_IO;
258         size[0]= 4096;
259     }
260
261     av_new_packet(pkt, size[0] + size[1] + size[2]);
262     pkt->stream_index = 0;
263     pkt->flags |= PKT_FLAG_KEY;
264
265     pkt->size= 0;
266     for(i=0; i<3; i++){
267         if(size[i]){
268             ret[i]= get_buffer(f[i], pkt->data + pkt->size, size[i]);
269             if (!s->is_pipe)
270                 url_fclose(f[i]);
271             if(ret[i]>0)
272                 pkt->size += ret[i];
273         }
274     }
275
276     if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
277         av_free_packet(pkt);
278         return AVERROR_IO; /* signal EOF */
279     } else {
280         s->img_count++;
281         s->img_number++;
282         return 0;
283     }
284 }
285
286 static int img_read_close(AVFormatContext *s1)
287 {
288     return 0;
289 }
290
291 #ifdef CONFIG_MUXERS
292 /******************************************************/
293 /* image output */
294
295 static int img_write_header(AVFormatContext *s)
296 {
297     VideoData *img = s->priv_data;
298
299     img->img_number = 1;
300     pstrcpy(img->path, sizeof(img->path), s->filename);
301
302     /* find format */
303     if (s->oformat->flags & AVFMT_NOFILE)
304         img->is_pipe = 0;
305     else
306         img->is_pipe = 1;
307
308     return 0;
309 }
310
311 static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
312 {
313     VideoData *img = s->priv_data;
314     ByteIOContext pb1[3], *pb[3]= {&pb1[0], &pb1[1], &pb1[2]};
315     char filename[1024];
316     AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
317     int i;
318
319     if (!img->is_pipe) {
320         if (get_frame_filename(filename, sizeof(filename),
321                                img->path, img->img_number) < 0 && img->img_number>1)
322             return AVERROR_IO;
323         for(i=0; i<3; i++){
324             if (url_fopen(pb[i], filename, URL_WRONLY) < 0)
325                 return AVERROR_IO;
326
327             if(codec->codec_id != CODEC_ID_RAWVIDEO)
328                 break;
329             filename[ strlen(filename) - 1 ]= 'U' + i;
330         }
331     } else {
332         pb[0] = &s->pb;
333     }
334
335     if(codec->codec_id == CODEC_ID_RAWVIDEO){
336         int ysize = codec->width * codec->height;
337         put_buffer(pb[0], pkt->data        , ysize);
338         put_buffer(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
339         put_buffer(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
340         put_flush_packet(pb[1]);
341         put_flush_packet(pb[2]);
342         url_fclose(pb[1]);
343         url_fclose(pb[2]);
344     }else{
345         put_buffer(pb[0], pkt->data, pkt->size);
346     }
347     put_flush_packet(pb[0]);
348     if (!img->is_pipe) {
349         url_fclose(pb[0]);
350     }
351
352     img->img_number++;
353     return 0;
354 }
355
356 static int img_write_trailer(AVFormatContext *s)
357 {
358     return 0;
359 }
360
361 #endif /* CONFIG_MUXERS */
362
363 /* input */
364 #ifdef CONFIG_IMAGE2_DEMUXER
365 AVInputFormat image2_demuxer = {
366     "image2",
367     "image2 sequence",
368     sizeof(VideoData),
369     image_probe,
370     img_read_header,
371     img_read_packet,
372     img_read_close,
373     NULL,
374     NULL,
375     AVFMT_NOFILE,
376 };
377 #endif
378 #ifdef CONFIG_IMAGE2PIPE_DEMUXER
379 AVInputFormat image2pipe_demuxer = {
380     "image2pipe",
381     "piped image2 sequence",
382     sizeof(VideoData),
383     NULL, /* no probe */
384     img_read_header,
385     img_read_packet,
386     img_read_close,
387     NULL,
388 };
389 #endif
390
391 /* output */
392 #ifdef CONFIG_IMAGE2_MUXER
393 AVOutputFormat image2_muxer = {
394     "image2",
395     "image2 sequence",
396     "",
397     "",
398     sizeof(VideoData),
399     CODEC_ID_NONE,
400     CODEC_ID_MJPEG,
401     img_write_header,
402     img_write_packet,
403     img_write_trailer,
404     AVFMT_NOFILE,
405 };
406 #endif
407 #ifdef CONFIG_IMAGE2PIPE_MUXER
408 AVOutputFormat image2pipe_muxer = {
409     "image2pipe",
410     "piped image2 sequence",
411     "",
412     "",
413     sizeof(VideoData),
414     CODEC_ID_NONE,
415     CODEC_ID_MJPEG,
416     img_write_header,
417     img_write_packet,
418     img_write_trailer,
419 };
420 #endif