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