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