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