[FFmpeg-devel] [PATCH] lavfi/blackdetect: add logic for handling stream termination

Stefano Sabatini stefasab at gmail.com
Thu Jun 21 01:19:53 CEST 2012


Add request_frame() which checks the black duration when the end of the
stream is signalled. Allows to detect black video segments at the end of
the stream.
Note that last segment duration is not very accurate, since we still miss
the duration information in the video buffer.

Address trac ticket #1470.
---
 libavfilter/vf_blackdetect.c |   43 +++++++++++++++++++++++++++++++++--------
 1 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c
index 6a51e2f..f3f5885 100644
--- a/libavfilter/vf_blackdetect.c
+++ b/libavfilter/vf_blackdetect.c
@@ -36,6 +36,7 @@ typedef struct {
     int64_t black_min_duration;      ///< minimum duration of detected black, expressed in timebase units
     int64_t black_start;             ///< pts start time of the first black picture
     int64_t black_end;               ///< pts end time of the last black picture
+    int64_t last_picref_pts;         ///< pts of the last input picture
     int black_started;
 
     double       picture_black_ratio_th;
@@ -122,6 +123,35 @@ static int config_input(AVFilterLink *inlink)
     return 0;
 }
 
+static void check_black_end(AVFilterContext *ctx)
+{
+    BlackDetectContext *blackdetect = ctx->priv;
+    AVFilterLink *inlink = ctx->inputs[0];
+
+    if ((blackdetect->black_end - blackdetect->black_start) >= blackdetect->black_min_duration) {
+        av_log(blackdetect, AV_LOG_INFO,
+               "black_start:%s black_end:%s black_duration:%s\n",
+               av_ts2timestr(blackdetect->black_start, &inlink->time_base),
+               av_ts2timestr(blackdetect->black_end, &inlink->time_base),
+               av_ts2timestr(blackdetect->black_end - blackdetect->black_start, &inlink->time_base));
+    }
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    BlackDetectContext *blackdetect = ctx->priv;
+    AVFilterLink *inlink = ctx->inputs[0];
+    int ret = avfilter_request_frame(inlink);
+
+    if (ret == AVERROR_EOF && blackdetect->black_started) {
+        // FIXME: black_end should be set to last_picref_pts + last_picref_duration
+        blackdetect->black_end = blackdetect->last_picref_pts;
+        check_black_end(ctx);
+    }
+    return ret;
+}
+
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
 {
     AVFilterContext *ctx = inlink->dst;
@@ -164,16 +194,10 @@ static void end_frame(AVFilterLink *inlink)
         /* black ends here */
         blackdetect->black_started = 0;
         blackdetect->black_end = picref->pts;
-
-        if ((blackdetect->black_end - blackdetect->black_start) >= blackdetect->black_min_duration) {
-            av_log(blackdetect, AV_LOG_INFO,
-                   "black_start:%s black_end:%s black_duration:%s\n",
-                   av_ts2timestr(blackdetect->black_start, &inlink->time_base),
-                   av_ts2timestr(blackdetect->black_end, &inlink->time_base),
-                   av_ts2timestr(blackdetect->black_end - blackdetect->black_start, &inlink->time_base));
-        }
+        check_black_end(ctx);
     }
 
+    blackdetect->last_picref_pts = picref->pts;
     blackdetect->frame_count++;
     blackdetect->nb_black_pixels = 0;
     avfilter_unref_buffer(picref);
@@ -200,7 +224,8 @@ AVFilter avfilter_vf_blackdetect = {
 
     .outputs = (const AVFilterPad[]) {
         { .name             = "default",
-          .type             = AVMEDIA_TYPE_VIDEO },
+          .type             = AVMEDIA_TYPE_VIDEO,
+          .request_frame    = request_frame, },
         { .name = NULL }
     },
 };
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list