Browse code

img2: glob matching for image series

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Brian Olson authored on 2012/02/27 18:27:17
Showing 3 changed files
... ...
@@ -1183,6 +1183,7 @@ HAVE_LIST="
1183 1183
     GetProcessMemoryInfo
1184 1184
     GetProcessTimes
1185 1185
     getrusage
1186
+    glob
1186 1187
     gnu_as
1187 1188
     ibm_asm
1188 1189
     inet_aton
... ...
@@ -3075,6 +3076,7 @@ check_func_headers windows.h GetProcessAffinityMask
3075 3075
 check_func_headers windows.h GetProcessTimes
3076 3076
 check_func_headers windows.h MapViewOfFile
3077 3077
 check_func_headers windows.h VirtualAlloc
3078
+check_func_headers glob.h glob
3078 3079
 
3079 3080
 check_header dlfcn.h
3080 3081
 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 1077
 The syntax @code{foo-%03d.jpeg} specifies to use a decimal number
1078 1078
 composed of three digits padded with zeroes to express the sequence
1079 1079
 number. It is the same syntax supported by the C printf function, but
1080
-only formats accepting a normal integer are suitable.
1080
+only formats accepting a normal integer are suitable. When importing
1081
+an image sequence, -i also accepts shell-like wildcard patterns such as
1082
+@code{foo-*.jpeg}, @code{foo-???.jpeg} or @code{foo-00[234]*.jpeg}.
1083
+It will probably be necessary to escape these patterns so they do not
1084
+get interpreted by your shell.
1081 1085
 
1082 1086
 @item
1083 1087
 You can put many streams of the same type in the output:
... ...
@@ -27,6 +27,25 @@
27 27
 #include "libavutil/parseutils.h"
28 28
 #include "avformat.h"
29 29
 #include "internal.h"
30
+#if HAVE_GLOB
31
+#include <glob.h>
32
+
33
+/* Locally define as 0 (bitwise-OR no-op) any missing glob options that
34
+   are non-posix glibc/bsd extensions. */
35
+#ifndef GLOB_NOMAGIC
36
+#define GLOB_NOMAGIC 0
37
+#endif
38
+#ifndef GLOB_TILDE
39
+#define GLOB_TILDE 0
40
+#endif
41
+#ifndef GLOB_TILDE_CHECK
42
+#define GLOB_TILDE_CHECK GLOB_TILDE
43
+#endif
44
+#ifndef GLOB_BRACE
45
+#define GLOB_BRACE 0
46
+#endif
47
+
48
+#endif /* HAVE_GLOB */
30 49
 
31 50
 typedef struct {
32 51
     const AVClass *class;  /**< Class for private options. */
... ...
@@ -41,6 +60,10 @@ typedef struct {
41 41
     char *video_size;       /**< Set by a private option. */
42 42
     char *framerate;        /**< Set by a private option. */
43 43
     int loop;
44
+    int use_glob;
45
+#if HAVE_GLOB
46
+    glob_t globstate;
47
+#endif
44 48
 } VideoDemuxData;
45 49
 
46 50
 static const int sizes[][2] = {
... ...
@@ -69,6 +92,17 @@ static int infer_size(int *width_ptr, int *height_ptr, int size)
69 69
     return -1;
70 70
 }
71 71
 
72
+static int is_glob(const char *path)
73
+{
74
+#if HAVE_GLOB
75
+    size_t span = strcspn(path, "*?[]{}\\");
76
+    /* Did we hit a glob char or get to the end? */
77
+    return path[span] != '\0';
78
+#else
79
+    return 0;
80
+#endif
81
+}
82
+
72 83
 /* return -1 if no image found */
73 84
 static int find_image_range(int *pfirst_index, int *plast_index,
74 85
                             const char *path)
... ...
@@ -128,6 +162,8 @@ static int read_probe(AVProbeData *p)
128 128
     if (p->filename && ff_guess_image2_codec(p->filename)) {
129 129
         if (av_filename_number_test(p->filename))
130 130
             return AVPROBE_SCORE_MAX;
131
+        else if (is_glob(p->filename))
132
+            return AVPROBE_SCORE_MAX;
131 133
         else
132 134
             return AVPROBE_SCORE_MAX/2;
133 135
     }
... ...
@@ -183,8 +219,21 @@ static int read_header(AVFormatContext *s1)
183 183
     }
184 184
 
185 185
     if (!s->is_pipe) {
186
+        s->use_glob = is_glob(s->path);
187
+        if (s->use_glob) {
188
+#if HAVE_GLOB
189
+            int gerr;
190
+            gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC|GLOB_TILDE_CHECK, NULL, &s->globstate);
191
+            if (gerr != 0) {
192
+                return AVERROR(ENOENT);
193
+            }
194
+            first_index = 0;
195
+            last_index = s->globstate.gl_pathc - 1;
196
+#endif
197
+        } else {
186 198
         if (find_image_range(&first_index, &last_index, s->path) < 0)
187 199
             return AVERROR(ENOENT);
200
+        }
188 201
         s->img_first = first_index;
189 202
         s->img_last = last_index;
190 203
         s->img_number = first_index;
... ...
@@ -216,7 +265,8 @@ static int read_header(AVFormatContext *s1)
216 216
 static int read_packet(AVFormatContext *s1, AVPacket *pkt)
217 217
 {
218 218
     VideoDemuxData *s = s1->priv_data;
219
-    char filename[1024];
219
+    char filename_bytes[1024];
220
+    char *filename = filename_bytes;
220 221
     int i;
221 222
     int size[3]={0}, ret[3]={0};
222 223
     AVIOContext *f[3];
... ...
@@ -229,9 +279,15 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt)
229 229
         }
230 230
         if (s->img_number > s->img_last)
231 231
             return AVERROR_EOF;
232
-        if (av_get_frame_filename(filename, sizeof(filename),
232
+        if (s->use_glob) {
233
+#if HAVE_GLOB
234
+            filename = s->globstate.gl_pathv[s->img_number];
235
+#endif
236
+        } else {
237
+        if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
233 238
                                   s->path, s->img_number)<0 && s->img_number > 1)
234 239
             return AVERROR(EIO);
240
+        }
235 241
         for(i=0; i<3; i++){
236 242
             if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
237 243
                            &s1->interrupt_callback, NULL) < 0) {
... ...
@@ -281,6 +337,17 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt)
281 281
     }
282 282
 }
283 283
 
284
+static int read_close(struct AVFormatContext* s1)
285
+{
286
+    VideoDemuxData *s = s1->priv_data;
287
+#if HAVE_GLOB
288
+    if (s->use_glob) {
289
+        globfree(&s->globstate);
290
+    }
291
+#endif
292
+    return 0;
293
+}
294
+
284 295
 #define OFFSET(x) offsetof(VideoDemuxData, x)
285 296
 #define DEC AV_OPT_FLAG_DECODING_PARAM
286 297
 static const AVOption options[] = {
... ...
@@ -305,6 +372,7 @@ AVInputFormat ff_image2_demuxer = {
305 305
     .read_probe     = read_probe,
306 306
     .read_header    = read_header,
307 307
     .read_packet    = read_packet,
308
+    .read_close     = read_close,
308 309
     .flags          = AVFMT_NOFILE,
309 310
     .priv_class     = &img2_class,
310 311
 };