Commit eda45008 authored by Stefano Sabatini's avatar Stefano Sabatini

lavfi/blackdetect: add logic for handling stream termination

Add request_frame() which checks the black duration when the end of the
stream is signalled. Allow to detect black video segments at the end of
the stream.

Note that the reported last black video segment duration is not very
accurate, since we still miss the duration information in the video
buffer.

Address trac ticket #1470.
parent 5bc87f1c
......@@ -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 }
},
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment