From cd82c6e4efb639c5ee0750c857392527d98881b8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 21 Dec 2020 23:09:58 +0100 Subject: [PATCH] avfilter/vf_decimate: switch to activate --- libavfilter/vf_decimate.c | 96 +++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c index 549b281418..8407d9942c 100644 --- a/libavfilter/vf_decimate.c +++ b/libavfilter/vf_decimate.c @@ -23,6 +23,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/timestamp.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #define INPUT_MAIN 0 @@ -43,6 +44,7 @@ typedef struct DecimateContext { AVFrame **clean_src; ///< frame queue for the clean source int got_frame[2]; ///< frame request flag for each input stream AVRational ts_unit; ///< timestamp units for the output frames + int64_t last_pts; ///< last output timestamp int64_t start_pts; ///< base for output timestamps uint32_t eof; ///< bitmask for end of stream int hsub, vsub; ///< chroma subsampling values @@ -217,16 +219,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&dm->queue[i].frame); } else { AVFrame *frame = dm->queue[i].frame; + if (!frame) + continue; dm->queue[i].frame = NULL; if (frame->pts != AV_NOPTS_VALUE && dm->start_pts == AV_NOPTS_VALUE) dm->start_pts = frame->pts; if (dm->ppsrc) { av_frame_free(&frame); frame = dm->clean_src[i]; + if (!frame) + continue; dm->clean_src[i] = NULL; } frame->pts = av_rescale_q(outlink->frame_count_in, dm->ts_unit, (AVRational){1,1}) + (dm->start_pts == AV_NOPTS_VALUE ? 0 : dm->start_pts); + dm->last_pts = frame->pts; ret = ff_filter_frame(outlink, frame); if (ret < 0) break; @@ -236,6 +243,60 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ret; } +static int activate(AVFilterContext *ctx) +{ + DecimateContext *dm = ctx->priv; + AVFrame *frame = NULL; + int ret = 0, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + + if ((dm->got_frame[INPUT_MAIN] == 0) && !(dm->eof & (1 << INPUT_MAIN)) && + (ret = ff_inlink_consume_frame(ctx->inputs[INPUT_MAIN], &frame)) > 0) { + ret = filter_frame(ctx->inputs[INPUT_MAIN], frame); + if (ret < 0) + return ret; + } + if (ret < 0) + return ret; + if (dm->ppsrc && + (dm->got_frame[INPUT_CLEANSRC] == 0) && !(dm->eof & (1 << INPUT_CLEANSRC)) && + (ret = ff_inlink_consume_frame(ctx->inputs[INPUT_CLEANSRC], &frame)) > 0) { + ret = filter_frame(ctx->inputs[INPUT_CLEANSRC], frame); + if (ret < 0) + return ret; + } + if (ret < 0) { + return ret; + } else if (dm->eof & ((1 << INPUT_MAIN) | (dm->ppsrc << INPUT_CLEANSRC))) { + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, dm->last_pts); + return 0; + } else if (!(dm->eof & (1 << INPUT_MAIN)) && ff_inlink_acknowledge_status(ctx->inputs[INPUT_MAIN], &status, &pts)) { + if (status == AVERROR_EOF) { // flushing + dm->eof |= 1 << INPUT_MAIN; + if (!dm->ppsrc) + return filter_frame(ctx->inputs[INPUT_MAIN], NULL); + } + } else if (dm->ppsrc && !(dm->eof & (1 << INPUT_CLEANSRC)) && ff_inlink_acknowledge_status(ctx->inputs[INPUT_CLEANSRC], &status, &pts)) { + if (status == AVERROR_EOF) { // flushing + dm->eof |= 1 << INPUT_CLEANSRC; + return filter_frame(ctx->inputs[INPUT_CLEANSRC], NULL); + } + } + + if (ff_inlink_queued_frames(ctx->inputs[INPUT_MAIN]) > 0 && + (dm->ppsrc && ff_inlink_queued_frames(ctx->inputs[INPUT_CLEANSRC]) > 0)) { + ff_filter_set_ready(ctx, 100); + } else if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (dm->got_frame[INPUT_MAIN] == 0) + ff_inlink_request_frame(ctx->inputs[INPUT_MAIN]); + if (dm->ppsrc && (dm->got_frame[INPUT_CLEANSRC] == 0)) + ff_inlink_request_frame(ctx->inputs[INPUT_CLEANSRC]); + } + return 0; +} + static int config_input(AVFilterLink *inlink) { int max_value; @@ -275,7 +336,6 @@ static av_cold int decimate_init(AVFilterContext *ctx) AVFilterPad pad = { .name = "main", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, .config_props = config_input, }; int ret; @@ -320,38 +380,6 @@ static av_cold void decimate_uninit(AVFilterContext *ctx) av_freep(&dm->clean_src); } -static int request_inlink(AVFilterContext *ctx, int lid) -{ - int ret = 0; - DecimateContext *dm = ctx->priv; - - if (!dm->got_frame[lid]) { - AVFilterLink *inlink = ctx->inputs[lid]; - ret = ff_request_frame(inlink); - if (ret == AVERROR_EOF) { // flushing - dm->eof |= 1 << lid; - ret = filter_frame(inlink, NULL); - } - } - return ret; -} - -static int request_frame(AVFilterLink *outlink) -{ - int ret; - AVFilterContext *ctx = outlink->src; - DecimateContext *dm = ctx->priv; - const uint32_t eof_mask = 1<ppsrc<eof & eof_mask) == eof_mask) // flush done? - return AVERROR_EOF; - if ((ret = request_inlink(ctx, INPUT_MAIN)) < 0) - return ret; - if (dm->ppsrc && (ret = request_inlink(ctx, INPUT_CLEANSRC)) < 0) - return ret; - return 0; -} - static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { @@ -398,7 +426,6 @@ static const AVFilterPad decimate_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = config_output, }, { NULL } @@ -408,6 +435,7 @@ AVFilter ff_vf_decimate = { .name = "decimate", .description = NULL_IF_CONFIG_SMALL("Decimate frames (post field matching filter)."), .init = decimate_init, + .activate = activate, .uninit = decimate_uninit, .priv_size = sizeof(DecimateContext), .query_formats = query_formats,