]> git.sesse.net Git - ffmpeg/blob - libavformat/img2dec.c
nut: fix int32 overflow
[ffmpeg] / libavformat / img2dec.c
1 /*
2  * Image format
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4  * Copyright (c) 2004 Michael Niedermayer
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "libavutil/avstring.h"
24 #include "libavutil/log.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/pixdesc.h"
27 #include "libavutil/parseutils.h"
28 #include "avformat.h"
29 #include "internal.h"
30 #if HAVE_GLOB
31 #include <glob.h>
32
33 /* Locally define as 0 (bitwise-OR no-op) any missing glob options that
34    are non-posix glibc/bsd extensions. */
35 #ifndef GLOB_NOMAGIC
36 #define GLOB_NOMAGIC 0
37 #endif
38 #ifndef GLOB_BRACE
39 #define GLOB_BRACE 0
40 #endif
41
42 #endif /* HAVE_GLOB */
43
44 typedef struct {
45     const AVClass *class;  /**< Class for private options. */
46     int img_first;
47     int img_last;
48     int img_number;
49     int img_count;
50     int is_pipe;
51     int split_planes;       /**< use independent file for each Y, U, V plane */
52     char path[1024];
53     char *pixel_format;     /**< Set by a private option. */
54     char *video_size;       /**< Set by a private option. */
55     char *framerate;        /**< Set by a private option. */
56     int loop;
57     enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type;
58     int use_glob;
59 #if HAVE_GLOB
60     glob_t globstate;
61 #endif
62     int start_number;
63     int start_number_range;
64 } VideoDemuxData;
65
66 static const int sizes[][2] = {
67     { 640, 480 },
68     { 720, 480 },
69     { 720, 576 },
70     { 352, 288 },
71     { 352, 240 },
72     { 160, 128 },
73     { 512, 384 },
74     { 640, 352 },
75     { 640, 240 },
76 };
77
78 static int infer_size(int *width_ptr, int *height_ptr, int size)
79 {
80     int i;
81
82     for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
83         if ((sizes[i][0] * sizes[i][1]) == size) {
84             *width_ptr = sizes[i][0];
85             *height_ptr = sizes[i][1];
86             return 0;
87         }
88     }
89     return -1;
90 }
91
92 static int is_glob(const char *path)
93 {
94 #if HAVE_GLOB
95     size_t span = 0;
96     const char *p = path;
97
98     while (p = strchr(p, '%')) {
99         if (*(++p) == '%') {
100             ++p;
101             continue;
102         }
103         if (span = strspn(p, "*?[]{}"))
104             break;
105     }
106     /* Did we hit a glob char or get to the end? */
107     return span != 0;
108 #else
109     return 0;
110 #endif
111 }
112
113 /**
114  * Get index range of image files matched by path.
115  *
116  * @param pfirst_index pointer to index updated with the first number in the range
117  * @param plast_index  pointer to index updated with the last number in the range
118  * @param path         path which has to be matched by the image files in the range
119  * @param start_index  minimum accepted value for the first index in the range
120  * @return -1 if no image file could be found
121  */
122 static int find_image_range(int *pfirst_index, int *plast_index,
123                             const char *path, int start_index, int start_index_range)
124 {
125     char buf[1024];
126     int range, last_index, range1, first_index;
127
128     /* find the first image */
129     for (first_index = start_index; first_index < start_index + start_index_range; first_index++) {
130         if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
131             *pfirst_index =
132             *plast_index = 1;
133             if (avio_check(buf, AVIO_FLAG_READ) > 0)
134                 return 0;
135             return -1;
136         }
137         if (avio_check(buf, AVIO_FLAG_READ) > 0)
138             break;
139     }
140     if (first_index == start_index + start_index_range)
141         goto fail;
142
143     /* find the last image */
144     last_index = first_index;
145     for(;;) {
146         range = 0;
147         for(;;) {
148             if (!range)
149                 range1 = 1;
150             else
151                 range1 = 2 * range;
152             if (av_get_frame_filename(buf, sizeof(buf), path,
153                                       last_index + range1) < 0)
154                 goto fail;
155             if (avio_check(buf, AVIO_FLAG_READ) <= 0)
156                 break;
157             range = range1;
158             /* just in case... */
159             if (range >= (1 << 30))
160                 goto fail;
161         }
162         /* we are sure than image last_index + range exists */
163         if (!range)
164             break;
165         last_index += range;
166     }
167     *pfirst_index = first_index;
168     *plast_index = last_index;
169     return 0;
170  fail:
171     return -1;
172 }
173
174
175 static int read_probe(AVProbeData *p)
176 {
177     if (p->filename && ff_guess_image2_codec(p->filename)) {
178         if (av_filename_number_test(p->filename))
179             return AVPROBE_SCORE_MAX;
180         else if (is_glob(p->filename))
181             return AVPROBE_SCORE_MAX;
182         else if(av_match_ext(p->filename, "raw"))
183             return 5;
184         else
185             return AVPROBE_SCORE_MAX/2;
186     }
187     return 0;
188 }
189
190 static int read_header(AVFormatContext *s1)
191 {
192     VideoDemuxData *s = s1->priv_data;
193     int first_index, last_index, ret = 0;
194     int width = 0, height = 0;
195     AVStream *st;
196     enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
197     AVRational framerate;
198
199     s1->ctx_flags |= AVFMTCTX_NOHEADER;
200
201     st = avformat_new_stream(s1, NULL);
202     if (!st) {
203         return AVERROR(ENOMEM);
204     }
205
206     if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) {
207         av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format);
208         return AVERROR(EINVAL);
209     }
210     if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
211         av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size);
212         return ret;
213     }
214     if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
215         av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate);
216         return ret;
217     }
218
219     av_strlcpy(s->path, s1->filename, sizeof(s->path));
220     s->img_number = 0;
221     s->img_count = 0;
222
223     /* find format */
224     if (s1->iformat->flags & AVFMT_NOFILE)
225         s->is_pipe = 0;
226     else{
227         s->is_pipe = 1;
228         st->need_parsing = AVSTREAM_PARSE_FULL;
229     }
230
231     avpriv_set_pts_info(st, 60, framerate.den, framerate.num);
232
233     if (width && height) {
234         st->codec->width  = width;
235         st->codec->height = height;
236     }
237
238     if (!s->is_pipe) {
239         if (s->pattern_type == PT_GLOB_SEQUENCE) {
240         s->use_glob = is_glob(s->path);
241         if (s->use_glob) {
242             char *p = s->path, *q, *dup;
243             int gerr;
244
245             av_log(s1, AV_LOG_WARNING, "Pattern type 'glob_sequence' is deprecated: "
246                    "use pattern_type 'glob' instead\n");
247 #if HAVE_GLOB
248             dup = q = av_strdup(p);
249             while (*q) {
250                 /* Do we have room for the next char and a \ insertion? */
251                 if ((p - s->path) >= (sizeof(s->path) - 2))
252                   break;
253                 if (*q == '%' && strspn(q + 1, "%*?[]{}"))
254                     ++q;
255                 else if (strspn(q, "\\*?[]{}"))
256                     *p++ = '\\';
257                 *p++ = *q++;
258             }
259             *p = 0;
260             av_free(dup);
261
262             gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
263             if (gerr != 0) {
264                 return AVERROR(ENOENT);
265             }
266             first_index = 0;
267             last_index = s->globstate.gl_pathc - 1;
268 #endif
269         }
270         }
271         if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) {
272             if (find_image_range(&first_index, &last_index, s->path,
273                                  s->start_number, s->start_number_range) < 0) {
274                 av_log(s1, AV_LOG_ERROR,
275                        "Could find no file with with path '%s' and index in the range %d-%d\n",
276                        s->path, s->start_number, s->start_number + s->start_number_range - 1);
277                 return AVERROR(ENOENT);
278             }
279         } else if (s->pattern_type == PT_GLOB) {
280 #if HAVE_GLOB
281             int gerr;
282             gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
283             if (gerr != 0) {
284                 return AVERROR(ENOENT);
285             }
286             first_index = 0;
287             last_index = s->globstate.gl_pathc - 1;
288             s->use_glob = 1;
289 #else
290             av_log(s1, AV_LOG_ERROR,
291                    "Pattern type 'glob' was selected but globbing "
292                    "is not supported by this libavformat build\n");
293             return AVERROR(ENOSYS);
294 #endif
295         } else if (s->pattern_type != PT_GLOB_SEQUENCE) {
296             av_log(s1, AV_LOG_ERROR,
297                    "Unknown value '%d' for pattern_type option\n", s->pattern_type);
298             return AVERROR(EINVAL);
299         }
300         s->img_first = first_index;
301         s->img_last = last_index;
302         s->img_number = first_index;
303         /* compute duration */
304         st->start_time = 0;
305         st->duration = last_index - first_index + 1;
306     }
307
308     if(s1->video_codec_id){
309         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
310         st->codec->codec_id = s1->video_codec_id;
311     }else if(s1->audio_codec_id){
312         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
313         st->codec->codec_id = s1->audio_codec_id;
314     }else{
315         const char *str= strrchr(s->path, '.');
316         s->split_planes = str && !av_strcasecmp(str + 1, "y");
317         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
318         st->codec->codec_id = ff_guess_image2_codec(s->path);
319         if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
320             st->codec->codec_id = AV_CODEC_ID_MJPEG;
321     }
322     if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != AV_PIX_FMT_NONE)
323         st->codec->pix_fmt = pix_fmt;
324
325     return 0;
326 }
327
328 static int read_packet(AVFormatContext *s1, AVPacket *pkt)
329 {
330     VideoDemuxData *s = s1->priv_data;
331     char filename_bytes[1024];
332     char *filename = filename_bytes;
333     int i;
334     int size[3]={0}, ret[3]={0};
335     AVIOContext *f[3] = {NULL};
336     AVCodecContext *codec= s1->streams[0]->codec;
337
338     if (!s->is_pipe) {
339         /* loop over input */
340         if (s->loop && s->img_number > s->img_last) {
341             s->img_number = s->img_first;
342         }
343         if (s->img_number > s->img_last)
344             return AVERROR_EOF;
345         if (s->use_glob) {
346 #if HAVE_GLOB
347             filename = s->globstate.gl_pathv[s->img_number];
348 #endif
349         } else {
350         if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
351                                   s->path, s->img_number)<0 && s->img_number > 1)
352             return AVERROR(EIO);
353         }
354         for(i=0; i<3; i++){
355             if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
356                            &s1->interrupt_callback, NULL) < 0) {
357                 if(i>=1)
358                     break;
359                 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
360                 return AVERROR(EIO);
361             }
362             size[i]= avio_size(f[i]);
363
364             if(!s->split_planes)
365                 break;
366             filename[ strlen(filename) - 1 ]= 'U' + i;
367         }
368
369         if(codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
370             infer_size(&codec->width, &codec->height, size[0]);
371     } else {
372         f[0] = s1->pb;
373         if (url_feof(f[0]))
374             return AVERROR(EIO);
375         size[0]= 4096;
376     }
377
378     if (av_new_packet(pkt, size[0] + size[1] + size[2]) < 0)
379         return AVERROR(ENOMEM);
380     pkt->stream_index = 0;
381     pkt->flags |= AV_PKT_FLAG_KEY;
382
383     pkt->size= 0;
384     for(i=0; i<3; i++){
385         if(f[i]){
386             ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]);
387             if (!s->is_pipe)
388                 avio_close(f[i]);
389             if(ret[i]>0)
390                 pkt->size += ret[i];
391         }
392     }
393
394     if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
395         av_free_packet(pkt);
396         return AVERROR(EIO); /* signal EOF */
397     } else {
398         s->img_count++;
399         s->img_number++;
400         return 0;
401     }
402 }
403
404 static int read_close(struct AVFormatContext* s1)
405 {
406     VideoDemuxData *s = s1->priv_data;
407 #if HAVE_GLOB
408     if (s->use_glob) {
409         globfree(&s->globstate);
410     }
411 #endif
412     return 0;
413 }
414
415 #define OFFSET(x) offsetof(VideoDemuxData, x)
416 #define DEC AV_OPT_FLAG_DECODING_PARAM
417 static const AVOption options[] = {
418     { "framerate",    "set the video framerate",             OFFSET(framerate),    AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC },
419     { "loop",         "force loop over input file sequence", OFFSET(loop),         AV_OPT_TYPE_INT,    {.i64 = 0},    0, 1, DEC },
420
421     { "pattern_type", "set pattern type",                    OFFSET(pattern_type), AV_OPT_TYPE_INT, {.i64=PT_GLOB_SEQUENCE}, 0, INT_MAX, DEC, "pattern_type"},
422     { "glob_sequence","glob/sequence pattern type",          0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
423     { "glob",         "glob pattern type",                   0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB},          INT_MIN, INT_MAX, DEC, "pattern_type" },
424     { "sequence",     "glob pattern type",                   0, AV_OPT_TYPE_CONST, {.i64=PT_SEQUENCE},      INT_MIN, INT_MAX, DEC, "pattern_type" },
425
426     { "pixel_format", "set video pixel format",              OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
427     { "start_number", "set first number in the sequence",    OFFSET(start_number), AV_OPT_TYPE_INT,    {.i64 = 0},    0, INT_MAX, DEC },
428     { "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC },
429     { "video_size",   "set video size",                      OFFSET(video_size),   AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
430     { NULL },
431 };
432
433 #if CONFIG_IMAGE2_DEMUXER
434 static const AVClass img2_class = {
435     .class_name = "image2 demuxer",
436     .item_name  = av_default_item_name,
437     .option     = options,
438     .version    = LIBAVUTIL_VERSION_INT,
439 };
440 AVInputFormat ff_image2_demuxer = {
441     .name           = "image2",
442     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
443     .priv_data_size = sizeof(VideoDemuxData),
444     .read_probe     = read_probe,
445     .read_header    = read_header,
446     .read_packet    = read_packet,
447     .read_close     = read_close,
448     .flags          = AVFMT_NOFILE,
449     .priv_class     = &img2_class,
450 };
451 #endif
452 #if CONFIG_IMAGE2PIPE_DEMUXER
453 static const AVClass img2pipe_class = {
454     .class_name = "image2pipe demuxer",
455     .item_name  = av_default_item_name,
456     .option     = options,
457     .version    = LIBAVUTIL_VERSION_INT,
458 };
459 AVInputFormat ff_image2pipe_demuxer = {
460     .name           = "image2pipe",
461     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
462     .priv_data_size = sizeof(VideoDemuxData),
463     .read_header    = read_header,
464     .read_packet    = read_packet,
465     .priv_class     = &img2pipe_class,
466 };
467 #endif