summaryrefslogtreecommitdiff
path: root/libavfilter/vf_decimate.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2020-12-21 23:09:58 +0100
committerPaul B Mahol <onemda@gmail.com>2020-12-21 23:34:10 +0100
commitcd82c6e4efb639c5ee0750c857392527d98881b8 (patch)
tree7b084a074b22fa66f691fc4d6df30cabd1d46403 /libavfilter/vf_decimate.c
parent204a90643713b03003b4d818dbc9dddddbd465bd (diff)
avfilter/vf_decimate: switch to activate
Diffstat (limited to 'libavfilter/vf_decimate.c')
-rw-r--r--libavfilter/vf_decimate.c96
1 files 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<<INPUT_MAIN | dm->ppsrc<<INPUT_CLEANSRC;
-
- if ((dm->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,