Add -json_cmd_print option that parses a JSON command file and prints
the equivalent shell command line to stdout.
Arguments containing shell metacharacters are POSIX single-quoted.
Single quotes within arguments are escaped as '\'' (end quote,
literal escaped quote, restart quote).
This is useful for reviewing JSON command files or converting them
to traditional shell scripts.
Signed-off-by: Tom Vaughan
---
fftools/ffmpeg.c | 10 ++++++++
fftools/ffmpeg_json.c | 57 +++++++++++++++++++++++++++++++++++++++++++
fftools/ffmpeg_json.h | 13 ++++++++++
fftools/ffmpeg_opt.c | 11 +++++++++
4 files changed, 91 insertions(+)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 5dcd641700..3090864c09 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1011,6 +1011,16 @@ int main(int argc, char **argv)
argv = json_argv;
}
+ /* Handle -json_cmd_print <file>: parse JSON and print the command line */
+ if (argc == 3 && !strcmp(argv[1], "-json_cmd_print")) {
+ ret = ffmpeg_json_parse_file(argv[2], &json_argc, &json_argv);
+ if (ret < 0)
+ goto finish;
+ ffmpeg_json_print_cmd(json_argc, json_argv);
+ ret = 0;
+ goto finish;
+ }
+
sch = sch_alloc();
if (!sch) {
ret = AVERROR(ENOMEM);
diff --git a/fftools/ffmpeg_json.c b/fftools/ffmpeg_json.c
index 3fdc1884e5..fb5e25fe6c 100644
--- a/fftools/ffmpeg_json.c
+++ b/fftools/ffmpeg_json.c
@@ -829,3 +829,60 @@ void ffmpeg_json_free_argv(int argc, char ***argv)
av_free(*argv);
*argv = NULL;
}
+
+/**
+ * Check whether a string needs shell quoting.
+ *
+ * @return 1 if the string contains any character that is special in
+ * POSIX shells (space, tab, newline, glob, pipe, redirect,
+ * quotes, etc.), 0 otherwise
+ */
+static int needs_shell_quoting(const char *s)
+{
+ for (; *s; s++) {
+ /* Safe characters that never need quoting */
+ if ((*s >= 'A' && *s <= 'Z') ||
+ (*s >= 'a' && *s <= 'z') ||
+ (*s >= '0' && *s <= '9') ||
+ *s == '-' || *s == '_' || *s == '.' ||
+ *s == '/' || *s == ':' || *s == '=' ||
+ *s == '+' || *s == '@' || *s == ',')
+ continue;
+ return 1;
+ }
+ return 0;
+}
+
+/** @sa ffmpeg_json_print_cmd() in ffmpeg_json.h for full documentation. */
+void ffmpeg_json_print_cmd(int argc, char **argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ const char *arg = argv[i];
+
+ if (i > 0)
+ printf(" ");
+
+ if (!*arg) {
+ /* Empty string: print as '' */
+ printf("''");
+ } else if (!needs_shell_quoting(arg)) {
+ /* Safe to print as-is */
+ printf("%s", arg);
+ } else {
+ /* Single-quote the argument.
+ * Any embedded single quotes are escaped as: '\''
+ * (end current quote, backslash-escaped quote, restart quote) */
+ printf("'");
+ for (; *arg; arg++) {
+ if (*arg == '\'')
+ printf("'\\''");
+ else
+ putchar(*arg);
+ }
+ printf("'");
+ }
+ }
+ printf("\n");
+}
diff --git a/fftools/ffmpeg_json.h b/fftools/ffmpeg_json.h
index d509f142d7..0ed63903cd 100644
--- a/fftools/ffmpeg_json.h
+++ b/fftools/ffmpeg_json.h
@@ -73,4 +73,17 @@ int ffmpeg_json_parse_file(const char *filename, int *argc,
char ***argv);
*/
void ffmpeg_json_free_argv(int argc, char ***argv);
+/**
+ * Print a shell-escaped command line from a parsed argv to stdout.
+ *
+ * Arguments containing shell metacharacters are single-quoted.
+ * Single quotes within arguments are escaped as '\'' (end quote,
+ * escaped quote, restart quote).
+ *
+ * @param argc Number of arguments
+ * @param argv Argument vector (as returned by ffmpeg_json_parse_file())
+ */
+void ffmpeg_json_print_cmd(int argc, char **argv);
+
+
#endif /* FFTOOLS_FFMPEG_JSON_H */
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index abdc81988c..5a0e07af33 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1619,6 +1619,14 @@ static int opt_json_cmd(void *optctx, const char *opt,
const char *arg)
return AVERROR(EINVAL);
}
+static int opt_json_cmd_print(void *optctx, const char *opt, const char *arg)
+{
+ av_log(NULL, AV_LOG_ERROR,
+ "-json_cmd_print must be the only option: "
+ "ffmpeg -json_cmd_print <file.json>\n");
+ return AVERROR(EINVAL);
+}
+
static const char *const alt_channel_layout[] = { "ch_layout", NULL};
static const char *const alt_codec[] = { "c", "acodec", "vcodec",
"scodec", "dcodec", NULL };
static const char *const alt_filter[] = { "af", "vf", NULL };
@@ -1634,6 +1642,9 @@ const OptionDef options[] = {
{ "json_cmd", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXIT,
{ .func_arg = opt_json_cmd },
"read options from a JSON command file", "file" },
+ { "json_cmd_print", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXIT,
+ { .func_arg = opt_json_cmd_print },
+ "print the CLI command from a JSON command file", "file" },
{ "f", OPT_TYPE_STRING, OPT_OFFSET | OPT_INPUT |
OPT_OUTPUT,
{ .off = OFFSET(format) },
"force container format (auto-detected otherwise)", "fmt" },
--
2.49.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]