summaryrefslogtreecommitdiffstats
path: root/demux/demux_mf.c
diff options
context:
space:
mode:
Diffstat (limited to 'demux/demux_mf.c')
-rw-r--r--demux/demux_mf.c94
1 files changed, 73 insertions, 21 deletions
diff --git a/demux/demux_mf.c b/demux/demux_mf.c
index 161e0cb92d..d971f04c96 100644
--- a/demux/demux_mf.c
+++ b/demux/demux_mf.c
@@ -16,6 +16,7 @@
*/
#include <math.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@@ -94,7 +95,6 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
}
free_stream(s);
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
goto exit_mf;
}
mp_info(log, "%s is not indirect filelist\n", filename + 1);
@@ -116,19 +116,18 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
}
talloc_free(fname2);
}
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
goto exit_mf;
}
- char *fname = talloc_size(mf, strlen(filename) + 32);
+ size_t fname_avail = strlen(filename) + 32;
+ char *fname = talloc_size(mf, fname_avail);
#if HAVE_GLOB
if (!strchr(filename, '%')) {
- strcpy(fname, filename);
- if (!strchr(filename, '*'))
- strcat(fname, "*");
-
+ // append * if none present
+ snprintf(fname, fname_avail, "%s%c", filename,
+ strchr(filename, '*') ? 0 : '*');
mp_info(log, "search expr: %s\n", fname);
glob_t gg;
@@ -142,16 +141,64 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
continue;
mf_add(mf, gg.gl_pathv[i]);
}
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
globfree(&gg);
goto exit_mf;
}
#endif
+ // We're using arbitrary user input as printf format with 1 int argument.
+ // Any format which uses exactly 1 int argument would be valid, but for
+ // simplicity we reject all conversion specifiers except %% and simple
+ // integer specifier: %[.][NUM]d where NUM is 1-3 digits (%.d is valid)
+ const char *f = filename;
+ int MAXDIGS = 3, nspec = 0, c;
+ bool bad_spec = false;
+
+ while (nspec < 2 && (c = *f++)) {
+ if (c != '%')
+ continue;
+
+ if (*f == '%') {
+ // '%%', which ends up as an explicit % in the output.
+ // Skipping forwards as it doesn't require further attention.
+ f++;
+ continue;
+ }
+
+ // Now c == '%' and *f != '%', thus we have entered territory of format
+ // specifiers which we are interested in.
+ nspec++;
+
+ if (*f == '.')
+ f++;
+
+ for (int ndig = 0; mp_isdigit(*f) && ndig < MAXDIGS; ndig++, f++)
+ /* no-op */;
+
+ if (*f != 'd') {
+ bad_spec = true; // not int, or beyond our validation capacity
+ break;
+ }
+
+ // *f is 'd'
+ f++;
+ }
+
+ // nspec==0 (zero specifiers) is rejected because fname wouldn't advance.
+ if (bad_spec || nspec != 1) {
+ mp_err(log,
+ "unsupported expr format: '%s' - exactly one format specifier of the form %%[.][NUM]d is expected\n",
+ filename);
+ goto exit_mf;
+ }
+
mp_info(log, "search expr: %s\n", filename);
while (error_count < 5) {
- sprintf(fname, filename, count++);
+ if (snprintf(fname, fname_avail, filename, count++) >= fname_avail) {
+ mp_err(log, "format result too long: '%s'\n", filename);
+ goto exit_mf;
+ }
if (!mp_path_exists(fname)) {
error_count++;
mp_verbose(log, "file not found: '%s'\n", fname);
@@ -160,9 +207,8 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct demuxer *d, char *filename
}
}
- mp_info(log, "number of files: %d\n", mf->nr_of_files);
-
exit_mf:
+ mp_info(log, "number of files: %d\n", mf->nr_of_files);
return mf;
}
@@ -254,6 +300,10 @@ static const struct {
{ "jls", "ljpeg" },
{ "thm", "mjpeg" },
{ "db", "mjpeg" },
+ { "pcd", "photocd" },
+ { "pfm", "pfm" },
+ { "phm", "phm" },
+ { "hdr", "hdr" },
{ "pcx", "pcx" },
{ "png", "png" },
{ "pns", "png" },
@@ -282,8 +332,12 @@ static const struct {
{ "pix", "brender_pix" },
{ "exr", "exr" },
{ "pic", "pictor" },
+ { "qoi", "qoi" },
{ "xface", "xface" },
{ "xwd", "xwd" },
+ { "svg", "svg" },
+ { "webp", "webp" },
+ { "jxl", "jpegxl" },
{0}
};
@@ -328,15 +382,9 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
if (!mf || mf->nr_of_files < 1)
goto error;
- double mf_fps;
- char *mf_type;
- mp_read_option_raw(demuxer->global, "mf-fps", &m_option_type_double, &mf_fps);
- mp_read_option_raw(demuxer->global, "mf-type", &m_option_type_string, &mf_type);
-
const char *codec = mp_map_mimetype_to_video_codec(demuxer->stream->mime_type);
- if (!codec || (mf_type && mf_type[0]))
- codec = probe_format(mf, mf_type, check);
- talloc_free(mf_type);
+ if (!codec || (demuxer->opts->mf_type && demuxer->opts->mf_type[0]))
+ codec = probe_format(mf, demuxer->opts->mf_type, check);
if (!codec)
goto error;
@@ -344,12 +392,16 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
// create a new video stream header
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
- struct mp_codec_params *c = sh->codec;
+ if (mf->nr_of_files == 1) {
+ MP_VERBOSE(demuxer, "Assuming this is an image format.\n");
+ sh->image = true;
+ }
+ struct mp_codec_params *c = sh->codec;
c->codec = codec;
c->disp_w = 0;
c->disp_h = 0;
- c->fps = mf_fps;
+ c->fps = demuxer->opts->mf_fps;
c->reliable_fps = true;
demux_add_sh_stream(demuxer, sh);