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