]> git.sesse.net Git - ffmpeg/blob - libavformat/img.c
Fix typo in comment
[ffmpeg] / libavformat / img.c
1 /*
2  * Image format
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 #include "avformat.h"
20
21 typedef struct {
22     int width;
23     int height;
24     int img_first;
25     int img_last;
26     int img_number;
27     int img_count;
28     int img_size;
29     AVImageFormat *img_fmt;
30     int pix_fmt;
31     int is_pipe;
32     char path[1024];
33     /* temporary usage */
34     void *ptr;
35 } VideoData;
36
37
38 /* return -1 if no image found */
39 static int find_image_range(int *pfirst_index, int *plast_index,
40                             const char *path)
41 {
42     char buf[1024];
43     int range, last_index, range1, first_index;
44
45     /* find the first image */
46     for(first_index = 0; first_index < 5; first_index++) {
47         if (get_frame_filename(buf, sizeof(buf), path, first_index) < 0)
48             goto fail;
49         if (url_exist(buf))
50             break;
51     }
52     if (first_index == 5)
53         goto fail;
54
55     /* find the last image */
56     last_index = first_index;
57     for(;;) {
58         range = 0;
59         for(;;) {
60             if (!range)
61                 range1 = 1;
62             else
63                 range1 = 2 * range;
64             if (get_frame_filename(buf, sizeof(buf), path,
65                                    last_index + range1) < 0)
66                 goto fail;
67             if (!url_exist(buf))
68                 break;
69             range = range1;
70             /* just in case... */
71             if (range >= (1 << 30))
72                 goto fail;
73         }
74         /* we are sure than image last_index + range exists */
75         if (!range)
76             break;
77         last_index += range;
78     }
79     *pfirst_index = first_index;
80     *plast_index = last_index;
81     return 0;
82  fail:
83     return -1;
84 }
85
86
87 static int image_probe(AVProbeData *p)
88 {
89     if (filename_number_test(p->filename) >= 0 && guess_image_format(p->filename))
90         return AVPROBE_SCORE_MAX-1;
91     else
92         return 0;
93 }
94
95 static int read_header_alloc_cb(void *opaque, AVImageInfo *info)
96 {
97     VideoData *s = opaque;
98
99     s->width = info->width;
100     s->height = info->height;
101     s->pix_fmt = info->pix_fmt;
102     /* stop image reading but no error */
103     return 1;
104 }
105
106 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
107 {
108     VideoData *s = s1->priv_data;
109     int ret, first_index, last_index;
110     char buf[1024];
111     ByteIOContext pb1, *f = &pb1;
112     AVStream *st;
113
114     st = av_new_stream(s1, 0);
115     if (!st) {
116         return -ENOMEM;
117     }
118
119     if (ap->image_format)
120         s->img_fmt = ap->image_format;
121
122     pstrcpy(s->path, sizeof(s->path), s1->filename);
123     s->img_number = 0;
124     s->img_count = 0;
125
126     /* find format */
127     if (s1->iformat->flags & AVFMT_NOFILE)
128         s->is_pipe = 0;
129     else
130         s->is_pipe = 1;
131
132     if (!ap->time_base.num) {
133         st->codec->time_base= (AVRational){1,25};
134     } else {
135         st->codec->time_base= ap->time_base;
136     }
137
138     if (!s->is_pipe) {
139         if (find_image_range(&first_index, &last_index, s->path) < 0)
140             goto fail;
141         s->img_first = first_index;
142         s->img_last = last_index;
143         s->img_number = first_index;
144         /* compute duration */
145         st->start_time = 0;
146         st->duration = last_index - first_index + 1;
147         if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
148             goto fail;
149         if (url_fopen(f, buf, URL_RDONLY) < 0)
150             goto fail;
151     } else {
152         f = &s1->pb;
153     }
154
155     ret = av_read_image(f, s1->filename, s->img_fmt, read_header_alloc_cb, s);
156     if (ret < 0)
157         goto fail1;
158
159     if (!s->is_pipe) {
160         url_fclose(f);
161     } else {
162         url_fseek(f, 0, SEEK_SET);
163     }
164
165     st->codec->codec_type = CODEC_TYPE_VIDEO;
166     st->codec->codec_id = CODEC_ID_RAWVIDEO;
167     st->codec->width = s->width;
168     st->codec->height = s->height;
169     st->codec->pix_fmt = s->pix_fmt;
170     s->img_size = avpicture_get_size(s->pix_fmt, (s->width+15)&(~15), (s->height+15)&(~15));
171
172     return 0;
173  fail1:
174     if (!s->is_pipe)
175         url_fclose(f);
176  fail:
177     return AVERROR_IO;
178 }
179
180 static int read_packet_alloc_cb(void *opaque, AVImageInfo *info)
181 {
182     VideoData *s = opaque;
183
184     if (info->width != s->width ||
185         info->height != s->height)
186         return -1;
187     avpicture_fill(&info->pict, s->ptr, info->pix_fmt, (info->width+15)&(~15), (info->height+15)&(~15));
188     return 0;
189 }
190
191 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
192 {
193     VideoData *s = s1->priv_data;
194     char filename[1024];
195     int ret;
196     ByteIOContext f1, *f;
197
198     if (!s->is_pipe) {
199         /* loop over input */
200         if (s1->loop_input && s->img_number > s->img_last) {
201             s->img_number = s->img_first;
202         }
203         if (get_frame_filename(filename, sizeof(filename),
204                                s->path, s->img_number) < 0)
205             return AVERROR_IO;
206         f = &f1;
207         if (url_fopen(f, filename, URL_RDONLY) < 0)
208             return AVERROR_IO;
209     } else {
210         f = &s1->pb;
211         if (url_feof(f))
212             return AVERROR_IO;
213     }
214
215     av_new_packet(pkt, s->img_size);
216     pkt->stream_index = 0;
217
218     s->ptr = pkt->data;
219     ret = av_read_image(f, filename, s->img_fmt, read_packet_alloc_cb, s);
220     if (!s->is_pipe) {
221         url_fclose(f);
222     }
223
224     if (ret < 0) {
225         av_free_packet(pkt);
226         return AVERROR_IO; /* signal EOF */
227     } else {
228         /* XXX: computing this pts is not necessary as it is done in
229            the generic code too */
230         pkt->pts = av_rescale((int64_t)s->img_count * s1->streams[0]->codec->time_base.num, s1->streams[0]->time_base.den, s1->streams[0]->codec->time_base.den) / s1->streams[0]->time_base.num;
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_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
246 {
247     VideoData *img = s->priv_data;
248     AVStream *st;
249     AVImageFormat *img_fmt;
250     int i;
251
252     /* find output image format */
253     if (ap->image_format) {
254         img_fmt = ap->image_format;
255     } else {
256         img_fmt = guess_image_format(s->filename);
257     }
258     if (!img_fmt)
259         return -1;
260
261     if (s->nb_streams != 1)
262         return -1;
263
264     st = s->streams[0];
265     /* we select the first matching format */
266     for(i=0;i<PIX_FMT_NB;i++) {
267         if (img_fmt->supported_pixel_formats & (1 << i))
268             break;
269     }
270     if (i >= PIX_FMT_NB)
271         return -1;
272     img->img_fmt = img_fmt;
273     img->pix_fmt = i;
274     st->codec->pix_fmt = img->pix_fmt;
275     return 0;
276 }
277
278 static int img_write_header(AVFormatContext *s)
279 {
280     VideoData *img = s->priv_data;
281
282     img->img_number = 1;
283     pstrcpy(img->path, sizeof(img->path), s->filename);
284
285     /* find format */
286     if (s->oformat->flags & AVFMT_NOFILE)
287         img->is_pipe = 0;
288     else
289         img->is_pipe = 1;
290
291     return 0;
292 }
293
294 static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
295 {
296     VideoData *img = s->priv_data;
297     AVStream *st = s->streams[pkt->stream_index];
298     ByteIOContext pb1, *pb;
299     AVPicture *picture;
300     int width, height, ret;
301     char filename[1024];
302     AVImageInfo info;
303
304     width = st->codec->width;
305     height = st->codec->height;
306
307     picture = (AVPicture *)pkt->data;
308
309     if (!img->is_pipe) {
310         if (get_frame_filename(filename, sizeof(filename),
311                                img->path, img->img_number) < 0)
312             return AVERROR_IO;
313         pb = &pb1;
314         if (url_fopen(pb, filename, URL_WRONLY) < 0)
315             return AVERROR_IO;
316     } else {
317         pb = &s->pb;
318     }
319     info.width = width;
320     info.height = height;
321     info.pix_fmt = st->codec->pix_fmt;
322     info.interleaved = 0;    /* FIXME: there should be a way to set it right */
323     info.pict = *picture;
324     ret = av_write_image(pb, img->img_fmt, &info);
325     if (!img->is_pipe) {
326         url_fclose(pb);
327     }
328
329     img->img_number++;
330     return 0;
331 }
332
333 static int img_write_trailer(AVFormatContext *s)
334 {
335     return 0;
336 }
337
338 /* input */
339 #ifdef CONFIG_IMAGE_DEMUXER
340 AVInputFormat image_demuxer = {
341     "image",
342     "image sequence",
343     sizeof(VideoData),
344     image_probe,
345     img_read_header,
346     img_read_packet,
347     img_read_close,
348     NULL,
349     NULL,
350     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
351 };
352 #endif
353 #ifdef CONFIG_IMAGEPIPE_DEMUXER
354 AVInputFormat imagepipe_demuxer = {
355     "imagepipe",
356     "piped image sequence",
357     sizeof(VideoData),
358     NULL, /* no probe */
359     img_read_header,
360     img_read_packet,
361     img_read_close,
362     NULL,
363 };
364 #endif
365
366 /* output */
367 #ifdef CONFIG_IMAGE_MUXER
368 AVOutputFormat image_muxer = {
369     "image",
370     "image sequence",
371     "",
372     "",
373     sizeof(VideoData),
374     CODEC_ID_NONE,
375     CODEC_ID_RAWVIDEO,
376     img_write_header,
377     img_write_packet,
378     img_write_trailer,
379     AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RAWPICTURE,
380     img_set_parameters,
381 };
382 #endif
383 #ifdef CONFIG_IMAGEPIPE_MUXER
384 AVOutputFormat imagepipe_muxer = {
385     "imagepipe",
386     "piped image sequence",
387     "",
388     "",
389     sizeof(VideoData),
390     CODEC_ID_NONE,
391     CODEC_ID_RAWVIDEO,
392     img_write_header,
393     img_write_packet,
394     img_write_trailer,
395     AVFMT_RAWPICTURE,
396     img_set_parameters,
397 };
398 #endif