diff options
Diffstat (limited to 'demux/demux_mf.c')
-rw-r--r-- | demux/demux_mf.c | 94 |
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); |