summaryrefslogtreecommitdiffstats
path: root/libavformat/img2dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/img2dec.c')
-rw-r--r--libavformat/img2dec.c181
1 files changed, 161 insertions, 20 deletions
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index 14f7785..79f10b9 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,19 @@ 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;
+ enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type;
+ 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 +89,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 +137,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 +177,10 @@ 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 if(av_match_ext(p->filename, "raw"))
+ return 5;
else
return AVPROBE_SCORE_MAX/2;
}
@@ -183,9 +236,67 @@ 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);
+ if (s->pattern_type == PT_GLOB_SEQUENCE) {
+ s->use_glob = is_glob(s->path);
+ if (s->use_glob) {
+ char *p = s->path, *q, *dup;
+ int gerr;
+
+ av_log(s1, AV_LOG_WARNING, "Pattern type 'glob_sequence' is deprecated: "
+ "use pattern_type 'glob' instead\n");
+#if HAVE_GLOB
+ 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
+ }
+ }
+ if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) {
+ 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);
+ }
+ } else if (s->pattern_type == PT_GLOB) {
+#if HAVE_GLOB
+ int gerr;
+ 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;
+ s->use_glob = 1;
+#else
+ av_log(s1, AV_LOG_ERROR,
+ "Pattern type 'glob' was selected but globbing "
+ "is not supported by this libavformat build\n");
+ return AVERROR(ENOSYS);
+#endif
+ } else if (s->pattern_type != PT_GLOB_SEQUENCE) {
+ av_log(s1, AV_LOG_ERROR,
+ "Unknown value '%d' for pattern_type option\n", s->pattern_type);
+ return AVERROR(EINVAL);
+ }
s->img_first = first_index;
s->img_last = last_index;
s->img_number = first_index;
@@ -201,8 +312,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 != AV_PIX_FMT_NONE)
st->codec->pix_fmt = pix_fmt;
@@ -213,7 +328,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] = {NULL};
@@ -226,9 +342,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 +361,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 +370,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 +400,32 @@ 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, {.i64 = 0}, 0, 1, DEC },
- { "start_number", "first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64 = 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, {.i64 = 0}, 0, 1, DEC },
+
+ { "pattern_type", "set pattern type", OFFSET(pattern_type), AV_OPT_TYPE_INT, {.i64=PT_GLOB_SEQUENCE}, 0, INT_MAX, DEC, "pattern_type"},
+ { "glob_sequence","glob/sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
+ { "glob", "glob pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB}, INT_MIN, INT_MAX, DEC, "pattern_type" },
+ { "sequence", "glob pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
+
+ { "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, {.i64 = 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, {.i64 = 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 +443,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,
};
OpenPOWER on IntegriCloud