img2: glob matching for image series
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
d61ef05bc5
commit
0be130e37b
2
configure
vendored
2
configure
vendored
@ -1183,6 +1183,7 @@ HAVE_LIST="
|
||||
GetProcessMemoryInfo
|
||||
GetProcessTimes
|
||||
getrusage
|
||||
glob
|
||||
gnu_as
|
||||
ibm_asm
|
||||
inet_aton
|
||||
@ -3075,6 +3076,7 @@ check_func_headers windows.h GetProcessAffinityMask
|
||||
check_func_headers windows.h GetProcessTimes
|
||||
check_func_headers windows.h MapViewOfFile
|
||||
check_func_headers windows.h VirtualAlloc
|
||||
check_func_headers glob.h glob
|
||||
|
||||
check_header dlfcn.h
|
||||
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
|
||||
The syntax @code{foo-%03d.jpeg} specifies to use a decimal number
|
||||
composed of three digits padded with zeroes to express the sequence
|
||||
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
|
||||
You can put many streams of the same type in the output:
|
||||
|
@ -27,6 +27,25 @@
|
||||
#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_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 {
|
||||
const AVClass *class; /**< Class for private options. */
|
||||
@ -41,6 +60,10 @@ typedef struct {
|
||||
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
|
||||
} VideoDemuxData;
|
||||
|
||||
static const int sizes[][2] = {
|
||||
@ -69,6 +92,17 @@ static int infer_size(int *width_ptr, int *height_ptr, int size)
|
||||
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 */
|
||||
static int find_image_range(int *pfirst_index, int *plast_index,
|
||||
const char *path)
|
||||
@ -128,6 +162,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,8 +219,21 @@ static int read_header(AVFormatContext *s1)
|
||||
}
|
||||
|
||||
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)
|
||||
return AVERROR(ENOENT);
|
||||
}
|
||||
s->img_first = first_index;
|
||||
s->img_last = last_index;
|
||||
s->img_number = first_index;
|
||||
@ -216,7 +265,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];
|
||||
@ -229,9 +279,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) {
|
||||
@ -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 DEC AV_OPT_FLAG_DECODING_PARAM
|
||||
static const AVOption options[] = {
|
||||
@ -305,6 +372,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,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user