ffmpeg: add abort_on option to allow aborting on empty output
authorMarton Balint <cus@passwd.hu>
Sat, 17 Oct 2015 21:46:09 +0000 (23:46 +0200)
committerMarton Balint <cus@passwd.hu>
Thu, 22 Oct 2015 17:03:01 +0000 (19:03 +0200)
Reviewed-by: Michael Niedermayer <michael@niedermayer.cc>
Signed-off-by: Marton Balint <cus@passwd.hu>
doc/ffmpeg.texi
ffmpeg.c
ffmpeg.h
ffmpeg_opt.c

index 76ea238..651c33c 100644 (file)
@@ -1260,6 +1260,14 @@ Discard all frames excepts keyframes.
 Discard all frames.
 @end table
 
+@item -abort_on @var{flags} (@emph{global})
+Stop and abort on various conditions. The following flags are available:
+
+@table @option
+@item empty_output
+No packets were passed to the muxer, the output is empty.
+@end table
+
 @item -xerror (@emph{global})
 Stop and exit on error
 
index 5e9a127..a19c816 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -4054,6 +4054,7 @@ static int transcode(void)
     OutputStream *ost;
     InputStream *ist;
     int64_t timer_start;
+    int64_t total_packets_written = 0;
 
     ret = transcode_init();
     if (ret < 0)
@@ -4134,6 +4135,12 @@ static int transcode(void)
         if (ost->encoding_needed) {
             av_freep(&ost->enc_ctx->stats_in);
         }
+        total_packets_written += ost->packets_written;
+    }
+
+    if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) {
+        av_log(NULL, AV_LOG_FATAL, "Empty output\n");
+        exit_program(1);
     }
 
     /* close each decoder */
index e8066f8..cdcb3b4 100644 (file)
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -383,6 +383,8 @@ enum forced_keyframes_const {
     FKF_NB
 };
 
+#define ABORT_ON_FLAG_EMPTY_OUTPUT (1 <<  0)
+
 extern const char *const forced_keyframes_const_names[];
 
 typedef enum {
@@ -527,6 +529,7 @@ extern int start_at_zero;
 extern int copy_tb;
 extern int debug_ts;
 extern int exit_on_error;
+extern int abort_on_flags;
 extern int print_stats;
 extern int qp_hist;
 extern int stdin_interaction;
index 0da1ffd..8f6416c 100644 (file)
@@ -106,6 +106,7 @@ int start_at_zero     = 0;
 int copy_tb           = -1;
 int debug_ts          = 0;
 int exit_on_error     = 0;
+int abort_on_flags    = 0;
 int print_stats       = -1;
 int qp_hist           = 0;
 int stdin_interaction = 1;
@@ -199,6 +200,24 @@ static AVDictionary *strip_specifiers(AVDictionary *dict)
     return ret;
 }
 
+static int opt_abort_on(void *optctx, const char *opt, const char *arg)
+{
+    static const AVOption opts[] = {
+        { "abort_on"        , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
+        { "empty_output"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = ABORT_ON_FLAG_EMPTY_OUTPUT     },    .unit = "flags" },
+        { NULL },
+    };
+    static const AVClass class = {
+        .class_name = "",
+        .item_name  = av_default_item_name,
+        .option     = opts,
+        .version    = LIBAVUTIL_VERSION_INT,
+    };
+    const AVClass *pclass = &class;
+
+    return av_opt_eval_flags(&pclass, &opts[0], arg, &abort_on_flags);
+}
+
 static int opt_sameq(void *optctx, const char *opt, const char *arg)
 {
     av_log(NULL, AV_LOG_ERROR, "Option '%s' was removed. "
@@ -3123,6 +3142,8 @@ const OptionDef options[] = {
         "timestamp error delta threshold", "threshold" },
     { "xerror",         OPT_BOOL | OPT_EXPERT,                       { &exit_on_error },
         "exit on error", "error" },
+    { "abort_on",       HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_abort_on },
+        "abort on the specified condition flags", "flags" },
     { "copyinkf",       OPT_BOOL | OPT_EXPERT | OPT_SPEC |
                         OPT_OUTPUT,                                  { .off = OFFSET(copy_initial_nonkeyframes) },
         "copy initial non-keyframes" },