diff options
Diffstat (limited to 'libavformat/img2dec.c')
-rw-r--r-- | libavformat/img2dec.c | 147 |
1 files changed, 127 insertions, 20 deletions
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index 18fa5d5..b87b5d5 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -3,20 +3,20 @@ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * Copyright (c) 2004 Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,6 +27,19 @@ #include "libavutil/parseutils.h" #include "avformat.h" #include "internal.h" +#if HAVE_GLOB +#include <glob.h> + +/* Locally define as 0 (bitwise-OR no-op) any missing glob options that + are non-posix glibc/bsd extensions. */ +#ifndef GLOB_NOMAGIC +#define GLOB_NOMAGIC 0 +#endif +#ifndef GLOB_BRACE +#define GLOB_BRACE 0 +#endif + +#endif /* HAVE_GLOB */ typedef struct { const AVClass *class; /**< Class for private options. */ @@ -35,12 +48,18 @@ typedef struct { int img_number; int img_count; int is_pipe; + int split_planes; /**< use independent file for each Y, U, V plane */ char path[1024]; char *pixel_format; /**< Set by a private option. */ char *video_size; /**< Set by a private option. */ char *framerate; /**< Set by a private option. */ int loop; + int use_glob; +#if HAVE_GLOB + glob_t globstate; +#endif int start_number; + int start_number_range; } VideoDemuxData; static const int sizes[][2] = { @@ -69,15 +88,44 @@ static int infer_size(int *width_ptr, int *height_ptr, int size) return -1; } -/* return -1 if no image found */ +static int is_glob(const char *path) +{ +#if HAVE_GLOB + size_t span = 0; + const char *p = path; + + while (p = strchr(p, '%')) { + if (*(++p) == '%') { + ++p; + continue; + } + if (span = strspn(p, "*?[]{}")) + break; + } + /* Did we hit a glob char or get to the end? */ + return span != 0; +#else + return 0; +#endif +} + +/** + * Get index range of image files matched by path. + * + * @param pfirst_index pointer to index updated with the first number in the range + * @param plast_index pointer to index updated with the last number in the range + * @param path path which has to be matched by the image files in the range + * @param start_index minimum accepted value for the first index in the range + * @return -1 if no image file could be found + */ static int find_image_range(int *pfirst_index, int *plast_index, - const char *path, int max_start) + const char *path, int start_index, int start_index_range) { char buf[1024]; int range, last_index, range1, first_index; /* find the first image */ - for (first_index = 0; first_index < max_start; first_index++) { + for (first_index = start_index; first_index < start_index + start_index_range; first_index++) { if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){ *pfirst_index = *plast_index = 1; @@ -88,7 +136,7 @@ static int find_image_range(int *pfirst_index, int *plast_index, if (avio_check(buf, AVIO_FLAG_READ) > 0) break; } - if (first_index == 5) + if (first_index == start_index + start_index_range) goto fail; /* find the last image */ @@ -128,6 +176,8 @@ static int read_probe(AVProbeData *p) if (p->filename && ff_guess_image2_codec(p->filename)) { if (av_filename_number_test(p->filename)) return AVPROBE_SCORE_MAX; + else if (is_glob(p->filename)) + return AVPROBE_SCORE_MAX; else return AVPROBE_SCORE_MAX/2; } @@ -183,9 +233,42 @@ static int read_header(AVFormatContext *s1) } if (!s->is_pipe) { - if (find_image_range(&first_index, &last_index, s->path, - FFMAX(s->start_number, 5)) < 0) - return AVERROR(ENOENT); + s->use_glob = is_glob(s->path); + if (s->use_glob) { +#if HAVE_GLOB + char *p = s->path, *q, *dup; + int gerr; + + dup = q = av_strdup(p); + while (*q) { + /* Do we have room for the next char and a \ insertion? */ + if ((p - s->path) >= (sizeof(s->path) - 2)) + break; + if (*q == '%' && strspn(q + 1, "%*?[]{}")) + ++q; + else if (strspn(q, "\\*?[]{}")) + *p++ = '\\'; + *p++ = *q++; + } + *p = 0; + av_free(dup); + + gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate); + if (gerr != 0) { + return AVERROR(ENOENT); + } + first_index = 0; + last_index = s->globstate.gl_pathc - 1; +#endif + } else { + if (find_image_range(&first_index, &last_index, s->path, + s->start_number, s->start_number_range) < 0) { + av_log(s1, AV_LOG_ERROR, + "Could find no file with with path '%s' and index in the range %d-%d\n", + s->path, s->start_number, s->start_number + s->start_number_range - 1); + return AVERROR(ENOENT); + } + } s->img_first = first_index; s->img_last = last_index; s->img_number = first_index; @@ -201,8 +284,12 @@ static int read_header(AVFormatContext *s1) st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = s1->audio_codec_id; }else{ + const char *str= strrchr(s->path, '.'); + s->split_planes = str && !av_strcasecmp(str + 1, "y"); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = ff_guess_image2_codec(s->path); + if (st->codec->codec_id == AV_CODEC_ID_LJPEG) + st->codec->codec_id = AV_CODEC_ID_MJPEG; } if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE) st->codec->pix_fmt = pix_fmt; @@ -213,7 +300,8 @@ static int read_header(AVFormatContext *s1) static int read_packet(AVFormatContext *s1, AVPacket *pkt) { VideoDemuxData *s = s1->priv_data; - char filename[1024]; + char filename_bytes[1024]; + char *filename = filename_bytes; int i; int size[3]={0}, ret[3]={0}; AVIOContext *f[3]; @@ -226,9 +314,15 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) } if (s->img_number > s->img_last) return AVERROR_EOF; - if (av_get_frame_filename(filename, sizeof(filename), + if (s->use_glob) { +#if HAVE_GLOB + filename = s->globstate.gl_pathv[s->img_number]; +#endif + } else { + if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes), s->path, s->img_number)<0 && s->img_number > 1) return AVERROR(EIO); + } for(i=0; i<3; i++){ if (avio_open2(&f[i], filename, AVIO_FLAG_READ, &s1->interrupt_callback, NULL) < 0) { @@ -239,7 +333,7 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) } size[i]= avio_size(f[i]); - if(codec->codec_id != AV_CODEC_ID_RAWVIDEO) + if(!s->split_planes) break; filename[ strlen(filename) - 1 ]= 'U' + i; } @@ -248,7 +342,7 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) infer_size(&codec->width, &codec->height, size[0]); } else { f[0] = s1->pb; - if (f[0]->eof_reached) + if (url_feof(f[0])) return AVERROR(EIO); size[0]= 4096; } @@ -278,14 +372,26 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) } } +static int read_close(struct AVFormatContext* s1) +{ + VideoDemuxData *s = s1->priv_data; +#if HAVE_GLOB + if (s->use_glob) { + globfree(&s->globstate); + } +#endif + return 0; +} + #define OFFSET(x) offsetof(VideoDemuxData, x) #define DEC AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { - { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, - { "video_size", "", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, - { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC }, - { "loop", "", OFFSET(loop), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, DEC }, - { "start_number", "first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.dbl = 1}, 1, INT_MAX, DEC }, + { "framerate", "set the video framerate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC }, + { "loop", "force loop over input file sequence", OFFSET(loop), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, DEC }, + { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "start_number", "set first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC }, + { "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 }, + { "video_size", "set video size", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { NULL }, }; @@ -303,6 +409,7 @@ AVInputFormat ff_image2_demuxer = { .read_probe = read_probe, .read_header = read_header, .read_packet = read_packet, + .read_close = read_close, .flags = AVFMT_NOFILE, .priv_class = &img2_class, }; |