]> git.sesse.net Git - ffmpeg/blob - libavformat/img2dec.c
Merge remote-tracking branch 'qatar/master'
[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
183             return AVPROBE_SCORE_MAX/2;
184     }
185     return 0;
186 }
187
188 static int read_header(AVFormatContext *s1)
189 {
190     VideoDemuxData *s = s1->priv_data;
191     int first_index, last_index, ret = 0;
192     int width = 0, height = 0;
193     AVStream *st;
194     enum PixelFormat pix_fmt = PIX_FMT_NONE;
195     AVRational framerate;
196
197     s1->ctx_flags |= AVFMTCTX_NOHEADER;
198
199     st = avformat_new_stream(s1, NULL);
200     if (!st) {
201         return AVERROR(ENOMEM);
202     }
203
204     if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) {
205         av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format);
206         return AVERROR(EINVAL);
207     }
208     if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
209         av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size);
210         return ret;
211     }
212     if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
213         av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate);
214         return ret;
215     }
216
217     av_strlcpy(s->path, s1->filename, sizeof(s->path));
218     s->img_number = 0;
219     s->img_count = 0;
220
221     /* find format */
222     if (s1->iformat->flags & AVFMT_NOFILE)
223         s->is_pipe = 0;
224     else{
225         s->is_pipe = 1;
226         st->need_parsing = AVSTREAM_PARSE_FULL;
227     }
228
229     avpriv_set_pts_info(st, 60, framerate.den, framerate.num);
230
231     if (width && height) {
232         st->codec->width  = width;
233         st->codec->height = height;
234     }
235
236     if (!s->is_pipe) {
237         if (s->pattern_type == PT_GLOB_SEQUENCE) {
238         s->use_glob = is_glob(s->path);
239         if (s->use_glob) {
240             char *p = s->path, *q, *dup;
241             int gerr;
242
243             av_log(s1, AV_LOG_WARNING, "Pattern type 'glob_sequence' is deprecated: "
244                    "use pattern_type 'glob' instead\n");
245 #if HAVE_GLOB
246             dup = q = av_strdup(p);
247             while (*q) {
248                 /* Do we have room for the next char and a \ insertion? */
249                 if ((p - s->path) >= (sizeof(s->path) - 2))
250                   break;
251                 if (*q == '%' && strspn(q + 1, "%*?[]{}"))
252                     ++q;
253                 else if (strspn(q, "\\*?[]{}"))
254                     *p++ = '\\';
255                 *p++ = *q++;
256             }
257             *p = 0;
258             av_free(dup);
259
260             gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
261             if (gerr != 0) {
262                 return AVERROR(ENOENT);
263             }
264             first_index = 0;
265             last_index = s->globstate.gl_pathc - 1;
266 #endif
267         }
268         }
269         if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) {
270             if (find_image_range(&first_index, &last_index, s->path,
271                                  s->start_number, s->start_number_range) < 0) {
272                 av_log(s1, AV_LOG_ERROR,
273                        "Could find no file with with path '%s' and index in the range %d-%d\n",
274                        s->path, s->start_number, s->start_number + s->start_number_range - 1);
275                 return AVERROR(ENOENT);
276             }
277         } else if (s->pattern_type == PT_GLOB) {
278 #if HAVE_GLOB
279             int gerr;
280             gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
281             if (gerr != 0) {
282                 return AVERROR(ENOENT);
283             }
284             first_index = 0;
285             last_index = s->globstate.gl_pathc - 1;
286             s->use_glob = 1;
287 #else
288             av_log(s1, AV_LOG_ERROR,
289                    "Pattern type 'glob' was selected but globbing "
290                    "is not supported by this libavformat build\n");
291             return AVERROR(ENOSYS);
292 #endif
293         } else if (s->pattern_type != PT_GLOB_SEQUENCE) {
294             av_log(s1, AV_LOG_ERROR,
295                    "Unknown value '%d' for pattern_type option\n", s->pattern_type);
296             return AVERROR(EINVAL);
297         }
298         s->img_first = first_index;
299         s->img_last = last_index;
300         s->img_number = first_index;
301         /* compute duration */
302         st->start_time = 0;
303         st->duration = last_index - first_index + 1;
304     }
305
306     if(s1->video_codec_id){
307         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
308         st->codec->codec_id = s1->video_codec_id;
309     }else if(s1->audio_codec_id){
310         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
311         st->codec->codec_id = s1->audio_codec_id;
312     }else{
313         const char *str= strrchr(s->path, '.');
314         s->split_planes = str && !av_strcasecmp(str + 1, "y");
315         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
316         st->codec->codec_id = ff_guess_image2_codec(s->path);
317         if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
318             st->codec->codec_id = AV_CODEC_ID_MJPEG;
319     }
320     if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE)
321         st->codec->pix_fmt = pix_fmt;
322
323     return 0;
324 }
325
326 static int read_packet(AVFormatContext *s1, AVPacket *pkt)
327 {
328     VideoDemuxData *s = s1->priv_data;
329     char filename_bytes[1024];
330     char *filename = filename_bytes;
331     int i;
332     int size[3]={0}, ret[3]={0};
333     AVIOContext *f[3];
334     AVCodecContext *codec= s1->streams[0]->codec;
335
336     if (!s->is_pipe) {
337         /* loop over input */
338         if (s->loop && s->img_number > s->img_last) {
339             s->img_number = s->img_first;
340         }
341         if (s->img_number > s->img_last)
342             return AVERROR_EOF;
343         if (s->use_glob) {
344 #if HAVE_GLOB
345             filename = s->globstate.gl_pathv[s->img_number];
346 #endif
347         } else {
348         if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
349                                   s->path, s->img_number)<0 && s->img_number > 1)
350             return AVERROR(EIO);
351         }
352         for(i=0; i<3; i++){
353             if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
354                            &s1->interrupt_callback, NULL) < 0) {
355                 if(i==1)
356                     break;
357                 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
358                 return AVERROR(EIO);
359             }
360             size[i]= avio_size(f[i]);
361
362             if(!s->split_planes)
363                 break;
364             filename[ strlen(filename) - 1 ]= 'U' + i;
365         }
366
367         if(codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
368             infer_size(&codec->width, &codec->height, size[0]);
369     } else {
370         f[0] = s1->pb;
371         if (url_feof(f[0]))
372             return AVERROR(EIO);
373         size[0]= 4096;
374     }
375
376     av_new_packet(pkt, size[0] + size[1] + size[2]);
377     pkt->stream_index = 0;
378     pkt->flags |= AV_PKT_FLAG_KEY;
379
380     pkt->size= 0;
381     for(i=0; i<3; i++){
382         if(size[i]){
383             ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]);
384             if (!s->is_pipe)
385                 avio_close(f[i]);
386             if(ret[i]>0)
387                 pkt->size += ret[i];
388         }
389     }
390
391     if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
392         av_free_packet(pkt);
393         return AVERROR(EIO); /* signal EOF */
394     } else {
395         s->img_count++;
396         s->img_number++;
397         return 0;
398     }
399 }
400
401 static int read_close(struct AVFormatContext* s1)
402 {
403     VideoDemuxData *s = s1->priv_data;
404 #if HAVE_GLOB
405     if (s->use_glob) {
406         globfree(&s->globstate);
407     }
408 #endif
409     return 0;
410 }
411
412 #define OFFSET(x) offsetof(VideoDemuxData, x)
413 #define DEC AV_OPT_FLAG_DECODING_PARAM
414 static const AVOption options[] = {
415     { "framerate",    "set the video framerate",             OFFSET(framerate),    AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC },
416     { "loop",         "force loop over input file sequence", OFFSET(loop),         AV_OPT_TYPE_INT,    {.dbl = 0},    0, 1, DEC },
417
418     { "pattern_type", "set pattern type",                    OFFSET(pattern_type), AV_OPT_TYPE_INT, {.dbl=PT_GLOB_SEQUENCE}, 0, INT_MAX, DEC, "pattern_type"},
419     { "glob_sequence","glob/sequence pattern type",          0, AV_OPT_TYPE_CONST, {.dbl=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
420     { "glob",         "glob pattern type",                   0, AV_OPT_TYPE_CONST, {.dbl=PT_GLOB},          INT_MIN, INT_MAX, DEC, "pattern_type" },
421     { "sequence",     "glob pattern type",                   0, AV_OPT_TYPE_CONST, {.dbl=PT_SEQUENCE},      INT_MIN, INT_MAX, DEC, "pattern_type" },
422
423     { "pixel_format", "set video pixel format",              OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
424     { "start_number", "set first number in the sequence",    OFFSET(start_number), AV_OPT_TYPE_INT,    {.dbl = 0},    0, INT_MAX, DEC },
425     { "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.dbl = 5}, 1, INT_MAX, DEC },
426     { "video_size",   "set video size",                      OFFSET(video_size),   AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
427     { NULL },
428 };
429
430 #if CONFIG_IMAGE2_DEMUXER
431 static const AVClass img2_class = {
432     .class_name = "image2 demuxer",
433     .item_name  = av_default_item_name,
434     .option     = options,
435     .version    = LIBAVUTIL_VERSION_INT,
436 };
437 AVInputFormat ff_image2_demuxer = {
438     .name           = "image2",
439     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
440     .priv_data_size = sizeof(VideoDemuxData),
441     .read_probe     = read_probe,
442     .read_header    = read_header,
443     .read_packet    = read_packet,
444     .read_close     = read_close,
445     .flags          = AVFMT_NOFILE,
446     .priv_class     = &img2_class,
447 };
448 #endif
449 #if CONFIG_IMAGE2PIPE_DEMUXER
450 static const AVClass img2pipe_class = {
451     .class_name = "image2pipe demuxer",
452     .item_name  = av_default_item_name,
453     .option     = options,
454     .version    = LIBAVUTIL_VERSION_INT,
455 };
456 AVInputFormat ff_image2pipe_demuxer = {
457     .name           = "image2pipe",
458     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
459     .priv_data_size = sizeof(VideoDemuxData),
460     .read_header    = read_header,
461     .read_packet    = read_packet,
462     .priv_class     = &img2pipe_class,
463 };
464 #endif