Commit 0be130e3 authored by Brian Olson's avatar Brian Olson Committed by Michael Niedermayer

img2: glob matching for image series

Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent d61ef05b
...@@ -1183,6 +1183,7 @@ HAVE_LIST=" ...@@ -1183,6 +1183,7 @@ HAVE_LIST="
GetProcessMemoryInfo GetProcessMemoryInfo
GetProcessTimes GetProcessTimes
getrusage getrusage
glob
gnu_as gnu_as
ibm_asm ibm_asm
inet_aton inet_aton
...@@ -3075,6 +3076,7 @@ check_func_headers windows.h GetProcessAffinityMask ...@@ -3075,6 +3076,7 @@ check_func_headers windows.h GetProcessAffinityMask
check_func_headers windows.h GetProcessTimes check_func_headers windows.h GetProcessTimes
check_func_headers windows.h MapViewOfFile check_func_headers windows.h MapViewOfFile
check_func_headers windows.h VirtualAlloc check_func_headers windows.h VirtualAlloc
check_func_headers glob.h glob
check_header dlfcn.h check_header dlfcn.h
check_header dxva2api.h -D_WIN32_WINNT=0x0600 check_header dxva2api.h -D_WIN32_WINNT=0x0600
......
...@@ -1077,7 +1077,11 @@ ffmpeg -f image2 -i foo-%03d.jpeg -r 12 -s WxH foo.avi ...@@ -1077,7 +1077,11 @@ ffmpeg -f image2 -i foo-%03d.jpeg -r 12 -s WxH foo.avi
The syntax @code{foo-%03d.jpeg} specifies to use a decimal number The syntax @code{foo-%03d.jpeg} specifies to use a decimal number
composed of three digits padded with zeroes to express the sequence composed of three digits padded with zeroes to express the sequence
number. It is the same syntax supported by the C printf function, but number. It is the same syntax supported by the C printf function, but
only formats accepting a normal integer are suitable. only formats accepting a normal integer are suitable. When importing
an image sequence, -i also accepts shell-like wildcard patterns such as
@code{foo-*.jpeg}, @code{foo-???.jpeg} or @code{foo-00[234]*.jpeg}.
It will probably be necessary to escape these patterns so they do not
get interpreted by your shell.
@item @item
You can put many streams of the same type in the output: You can put many streams of the same type in the output:
......
...@@ -27,6 +27,25 @@ ...@@ -27,6 +27,25 @@
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
#include "avformat.h" #include "avformat.h"
#include "internal.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_TILDE
#define GLOB_TILDE 0
#endif
#ifndef GLOB_TILDE_CHECK
#define GLOB_TILDE_CHECK GLOB_TILDE
#endif
#ifndef GLOB_BRACE
#define GLOB_BRACE 0
#endif
#endif /* HAVE_GLOB */
typedef struct { typedef struct {
const AVClass *class; /**< Class for private options. */ const AVClass *class; /**< Class for private options. */
...@@ -41,6 +60,10 @@ typedef struct { ...@@ -41,6 +60,10 @@ typedef struct {
char *video_size; /**< Set by a private option. */ char *video_size; /**< Set by a private option. */
char *framerate; /**< Set by a private option. */ char *framerate; /**< Set by a private option. */
int loop; int loop;
int use_glob;
#if HAVE_GLOB
glob_t globstate;
#endif
} VideoDemuxData; } VideoDemuxData;
static const int sizes[][2] = { static const int sizes[][2] = {
...@@ -69,6 +92,17 @@ static int infer_size(int *width_ptr, int *height_ptr, int size) ...@@ -69,6 +92,17 @@ static int infer_size(int *width_ptr, int *height_ptr, int size)
return -1; return -1;
} }
static int is_glob(const char *path)
{
#if HAVE_GLOB
size_t span = strcspn(path, "*?[]{}\\");
/* Did we hit a glob char or get to the end? */
return path[span] != '\0';
#else
return 0;
#endif
}
/* return -1 if no image found */ /* return -1 if no image found */
static int find_image_range(int *pfirst_index, int *plast_index, static int find_image_range(int *pfirst_index, int *plast_index,
const char *path) const char *path)
...@@ -128,6 +162,8 @@ static int read_probe(AVProbeData *p) ...@@ -128,6 +162,8 @@ static int read_probe(AVProbeData *p)
if (p->filename && ff_guess_image2_codec(p->filename)) { if (p->filename && ff_guess_image2_codec(p->filename)) {
if (av_filename_number_test(p->filename)) if (av_filename_number_test(p->filename))
return AVPROBE_SCORE_MAX; return AVPROBE_SCORE_MAX;
else if (is_glob(p->filename))
return AVPROBE_SCORE_MAX;
else else
return AVPROBE_SCORE_MAX/2; return AVPROBE_SCORE_MAX/2;
} }
...@@ -183,8 +219,21 @@ static int read_header(AVFormatContext *s1) ...@@ -183,8 +219,21 @@ static int read_header(AVFormatContext *s1)
} }
if (!s->is_pipe) { if (!s->is_pipe) {
s->use_glob = is_glob(s->path);
if (s->use_glob) {
#if HAVE_GLOB
int gerr;
gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC|GLOB_TILDE_CHECK, 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) < 0) if (find_image_range(&first_index, &last_index, s->path) < 0)
return AVERROR(ENOENT); return AVERROR(ENOENT);
}
s->img_first = first_index; s->img_first = first_index;
s->img_last = last_index; s->img_last = last_index;
s->img_number = first_index; s->img_number = first_index;
...@@ -216,7 +265,8 @@ static int read_header(AVFormatContext *s1) ...@@ -216,7 +265,8 @@ static int read_header(AVFormatContext *s1)
static int read_packet(AVFormatContext *s1, AVPacket *pkt) static int read_packet(AVFormatContext *s1, AVPacket *pkt)
{ {
VideoDemuxData *s = s1->priv_data; VideoDemuxData *s = s1->priv_data;
char filename[1024]; char filename_bytes[1024];
char *filename = filename_bytes;
int i; int i;
int size[3]={0}, ret[3]={0}; int size[3]={0}, ret[3]={0};
AVIOContext *f[3]; AVIOContext *f[3];
...@@ -229,9 +279,15 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) ...@@ -229,9 +279,15 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt)
} }
if (s->img_number > s->img_last) if (s->img_number > s->img_last)
return AVERROR_EOF; 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) s->path, s->img_number)<0 && s->img_number > 1)
return AVERROR(EIO); return AVERROR(EIO);
}
for(i=0; i<3; i++){ for(i=0; i<3; i++){
if (avio_open2(&f[i], filename, AVIO_FLAG_READ, if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
&s1->interrupt_callback, NULL) < 0) { &s1->interrupt_callback, NULL) < 0) {
...@@ -281,6 +337,17 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) ...@@ -281,6 +337,17 @@ 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 OFFSET(x) offsetof(VideoDemuxData, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM #define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = { static const AVOption options[] = {
...@@ -305,6 +372,7 @@ AVInputFormat ff_image2_demuxer = { ...@@ -305,6 +372,7 @@ AVInputFormat ff_image2_demuxer = {
.read_probe = read_probe, .read_probe = read_probe,
.read_header = read_header, .read_header = read_header,
.read_packet = read_packet, .read_packet = read_packet,
.read_close = read_close,
.flags = AVFMT_NOFILE, .flags = AVFMT_NOFILE,
.priv_class = &img2_class, .priv_class = &img2_class,
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment