* [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames
@ 2025-06-16 22:43 Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status Marton Balint
` (5 more replies)
0 siblings, 6 replies; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
No functional change.
Signed-off-by: Marton Balint <cus@passwd.hu>
---
fftools/ffmpeg_filter.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index e0c40ffe00..a0dc4c745e 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -2672,7 +2672,7 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
ret = avfilter_graph_request_oldest(fgt->graph);
if (ret == AVERROR(EAGAIN)) {
fgt->next_in = choose_input(fg, fgt);
- break;
+ return 0;
} else if (ret < 0) {
if (ret == AVERROR_EOF)
av_log(fg, AV_LOG_VERBOSE, "Filtergraph returned EOF, finishing\n");
@@ -2702,7 +2702,7 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
did_step = 1;
}
- return (fgp->nb_outputs_done == fg->nb_outputs) ? AVERROR_EOF : 0;
+ return AVERROR_EOF;
}
static void sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb)
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
@ 2025-06-16 22:43 ` Marton Balint
2025-06-18 11:39 ` Nicolas George
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 3/7] avfilter/f_select: port to activate Marton Balint
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
Signed-off-by: Marton Balint <cus@passwd.hu>
---
libavfilter/split.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libavfilter/split.c b/libavfilter/split.c
index bf004358d8..0557f54cce 100644
--- a/libavfilter/split.c
+++ b/libavfilter/split.c
@@ -98,6 +98,7 @@ static int activate(AVFilterContext *ctx)
av_frame_free(&in);
if (ret < 0)
return ret;
+ return 0;
}
if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH 3/7] avfilter/f_select: port to activate
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status Marton Balint
@ 2025-06-16 22:43 ` Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback Marton Balint
` (3 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
Multi-input or multi-output filters should always use activate now.
Fixes ticket #10959.
Signed-off-by: Marton Balint <cus@passwd.hu>
---
libavfilter/f_select.c | 54 +++++++++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 19 deletions(-)
diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c
index aa374c6ad0..38fe56623b 100644
--- a/libavfilter/f_select.c
+++ b/libavfilter/f_select.c
@@ -179,8 +179,6 @@ static const AVOption filt_name##_options[] = { \
{ NULL } \
}
-static int request_frame(AVFilterLink *outlink);
-
static av_cold int init(AVFilterContext *ctx)
{
SelectContext *select = ctx->priv;
@@ -201,7 +199,6 @@ static av_cold int init(AVFilterContext *ctx)
if (!pad.name)
return AVERROR(ENOMEM);
pad.type = ctx->filter->inputs[0].type;
- pad.request_frame = request_frame;
if ((ret = ff_append_outpad_free_name(ctx, &pad)) < 0)
return ret;
}
@@ -349,7 +346,7 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame)
if (isnan(select->var_values[VAR_START_T]))
select->var_values[VAR_START_T] = TS2D(frame->pts) * av_q2d(inlink->time_base);
- select->var_values[VAR_N ] = inl->frame_count_out;
+ select->var_values[VAR_N ] = inl->frame_count_out - 1;
select->var_values[VAR_PTS] = TS2D(frame->pts);
select->var_values[VAR_T ] = TS2D(frame->pts) * av_q2d(inlink->time_base);
select->var_values[VAR_KEY] = !!(frame->flags & AV_FRAME_FLAG_KEY);
@@ -428,24 +425,44 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame)
select->var_values[VAR_PREV_T] = select->var_values[VAR_T];
}
-static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
+static int activate(AVFilterContext *ctx)
{
- AVFilterContext *ctx = inlink->dst;
SelectContext *select = ctx->priv;
+ AVFilterLink *inlink = ctx->inputs[0];
+ AVFrame *in;
+ int nb_eofs = 0;
+ int ret;
- select_frame(ctx, frame);
- if (select->select)
- return ff_filter_frame(ctx->outputs[select->select_out], frame);
+ for (int i = 0; i < ctx->nb_outputs; i++)
+ nb_eofs += ff_outlink_get_status(ctx->outputs[i]) == AVERROR_EOF;
- av_frame_free(&frame);
- return 0;
-}
+ if (nb_eofs == ctx->nb_outputs) {
+ ff_inlink_set_status(inlink, AVERROR_EOF);
+ return 0;
+ }
-static int request_frame(AVFilterLink *outlink)
-{
- AVFilterLink *inlink = outlink->src->inputs[0];
- int ret = ff_request_frame(inlink);
- return ret;
+ while ((ret = ff_inlink_consume_frame(inlink, &in))) {
+ if (ret < 0)
+ return ret;
+ select_frame(ctx, in);
+ if (select->select)
+ return ff_filter_frame(ctx->outputs[select->select_out], in);
+ av_frame_free(&in);
+ };
+
+ FF_FILTER_FORWARD_STATUS_ALL(inlink, ctx);
+
+ for (int i = 0; i < ctx->nb_outputs; i++) {
+ if (ff_outlink_get_status(ctx->outputs[i]))
+ continue;
+
+ if (ff_outlink_frame_wanted(ctx->outputs[i])) {
+ ff_inlink_request_frame(inlink);
+ return 0;
+ }
+ }
+
+ return FFERROR_NOT_READY;
}
static av_cold void uninit(AVFilterContext *ctx)
@@ -486,7 +503,6 @@ static const AVFilterPad avfilter_af_aselect_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.config_props = config_input,
- .filter_frame = filter_frame,
},
};
@@ -542,7 +558,6 @@ static const AVFilterPad avfilter_vf_select_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
- .filter_frame = filter_frame,
},
};
@@ -553,6 +568,7 @@ const FFFilter ff_vf_select = {
.p.flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY,
.init = select_init,
.uninit = uninit,
+ .activate = activate,
.priv_size = sizeof(SelectContext),
FILTER_INPUTS(avfilter_vf_select_inputs),
FILTER_QUERY_FUNC2(query_formats),
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 3/7] avfilter/f_select: port to activate Marton Balint
@ 2025-06-16 22:43 ` Marton Balint
2025-06-16 22:56 ` Andreas Rheinhardt
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 5/7] avfilter/af_aresample: merge request_frame into activate function Marton Balint
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
Sinks without an activate callback (nullsink, anullsink) could cause
AVERROR(EAGAIN)-s in avfilter_graph_request_oldest() even when all the filter
graphs inputs were in EOF state.
Fixes ticket #11624.
Fixes ticket #10988.
Fixes ticket #10990.
Signed-off-by: Marton Balint <cus@passwd.hu>
---
libavfilter/avfiltergraph.c | 38 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 2d6036df74..6f9f46f1ea 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -1423,12 +1423,26 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, FilterLinkInternal *li)
heap_bubble_down(graphi, li, li->age_index);
}
+static int process_legacy_sink_output(FilterLinkInternal *oldesti)
+{
+ AVFilterLink *oldest = &oldesti->l.pub;
+ int ret;
+
+ do {
+ if (oldesti->frame_wanted_out)
+ ret = ff_filter_graph_run_once(oldest->dst->graph);
+ else
+ ret = ff_request_frame(oldest);
+ } while (ret >= 0);
+
+ return ret;
+}
+
int avfilter_graph_request_oldest(AVFilterGraph *graph)
{
FFFilterGraph *graphi = fffiltergraph(graph);
FilterLinkInternal *oldesti = graphi->sink_links[0];
AVFilterLink *oldest = &oldesti->l.pub;
- int64_t frame_count;
int r;
while (graphi->sink_links_count) {
@@ -1437,13 +1451,11 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
if (fffilter(oldest->dst->filter)->activate) {
r = av_buffersink_get_frame_flags(oldest->dst, NULL,
AV_BUFFERSINK_FLAG_PEEK);
- if (r != AVERROR_EOF)
- return r;
} else {
- r = ff_request_frame(oldest);
+ r = process_legacy_sink_output(oldesti);
}
if (r != AVERROR_EOF)
- break;
+ return r;
av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n",
oldest->dst->name,
oldest->dstpad->name);
@@ -1453,21 +1465,7 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
oldesti->age_index);
oldesti->age_index = -1;
}
- if (!graphi->sink_links_count)
- return AVERROR_EOF;
- av_assert1(!fffilter(oldest->dst->filter)->activate);
- av_assert1(oldesti->age_index >= 0);
- frame_count = oldesti->l.frame_count_out;
- while (frame_count == oldesti->l.frame_count_out) {
- r = ff_filter_graph_run_once(graph);
- if (r == AVERROR(EAGAIN) &&
- !oldesti->frame_wanted_out && !oldesti->frame_blocked_in &&
- !oldesti->status_in)
- (void)ff_request_frame(oldest);
- else if (r < 0)
- return r;
- }
- return 0;
+ return AVERROR_EOF;
}
int ff_filter_graph_run_once(AVFilterGraph *graph)
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH 5/7] avfilter/af_aresample: merge request_frame into activate function
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
` (2 preceding siblings ...)
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback Marton Balint
@ 2025-06-16 22:43 ` Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 6/7] avfilter/af_aresample: make aresample return FFERROR_NOT_READY when no progress can be made Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 7/7] avfilter/af_aresample: rework activate logic to follow the advised flow more strictly Marton Balint
5 siblings, 0 replies; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
No functional change.
Signed-off-by: Marton Balint <cus@passwd.hu>
---
libavfilter/af_aresample.c | 38 ++++++++++++++------------------------
1 file changed, 14 insertions(+), 24 deletions(-)
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index 58e09906e0..703fb7c92d 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -302,14 +302,26 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref
return 0;
}
-static int request_frame(AVFilterLink *outlink)
+static int activate(AVFilterContext *ctx)
{
- AVFilterContext *ctx = outlink->src;
AVFilterLink *inlink = ctx->inputs[0];
+ AVFilterLink *outlink = ctx->outputs[0];
AResampleContext *aresample = ctx->priv;
int ret = 0, status;
int64_t pts;
+ FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+ if (!aresample->eof && ff_inlink_queued_frames(inlink)) {
+ AVFrame *frame = NULL;
+
+ ret = ff_inlink_consume_frame(inlink, &frame);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ return filter_frame(inlink, frame);
+ }
+
// First try to get data from the internal buffers
if (aresample->more_data) {
AVFrame *outsamplesref;
@@ -346,28 +358,6 @@ static int request_frame(AVFilterLink *outlink)
return 0;
}
-static int activate(AVFilterContext *ctx)
-{
- AResampleContext *aresample = ctx->priv;
- AVFilterLink *inlink = ctx->inputs[0];
- AVFilterLink *outlink = ctx->outputs[0];
-
- FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
-
- if (!aresample->eof && ff_inlink_queued_frames(inlink)) {
- AVFrame *frame = NULL;
- int ret;
-
- ret = ff_inlink_consume_frame(inlink, &frame);
- if (ret < 0)
- return ret;
- if (ret > 0)
- return filter_frame(inlink, frame);
- }
-
- return request_frame(outlink);
-}
-
static const AVClass *resample_child_class_iterate(void **iter)
{
const AVClass *c = *iter ? NULL : swr_get_class();
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH 6/7] avfilter/af_aresample: make aresample return FFERROR_NOT_READY when no progress can be made
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
` (3 preceding siblings ...)
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 5/7] avfilter/af_aresample: merge request_frame into activate function Marton Balint
@ 2025-06-16 22:43 ` Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 7/7] avfilter/af_aresample: rework activate logic to follow the advised flow more strictly Marton Balint
5 siblings, 0 replies; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
FF_FILTER_FORWARD_WANTED() already sets the ready status as needed.
Signed-off-by: Marton Balint <cus@passwd.hu>
---
libavfilter/af_aresample.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index 703fb7c92d..4b3a732bb9 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -354,8 +354,7 @@ static int activate(AVFilterContext *ctx)
return ff_filter_frame(outlink, outsamplesref);
}
- ff_filter_set_ready(ctx, 100);
- return 0;
+ return FFERROR_NOT_READY;
}
static const AVClass *resample_child_class_iterate(void **iter)
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH 7/7] avfilter/af_aresample: rework activate logic to follow the advised flow more strictly
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
` (4 preceding siblings ...)
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 6/7] avfilter/af_aresample: make aresample return FFERROR_NOT_READY when no progress can be made Marton Balint
@ 2025-06-16 22:43 ` Marton Balint
5 siblings, 0 replies; 12+ messages in thread
From: Marton Balint @ 2025-06-16 22:43 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marton Balint
This should prevent the possibility of audio data accumulating.
The commit also cleans up and simplifies the code a bit so all frame producers
(filter_frame(), flush_frame()) functions follow similar logic as
ff_inlink_consume_frame() for the return code.
Signed-off-by: Marton Balint <cus@passwd.hu>
---
libavfilter/af_aresample.c | 74 ++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 40 deletions(-)
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index 4b3a732bb9..ea9927e7cf 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -43,7 +43,6 @@ typedef struct AResampleContext {
struct SwrContext *swr;
int64_t next_pts;
int more_data;
- int eof;
} AResampleContext;
static av_cold int preinit(AVFilterContext *ctx)
@@ -209,7 +208,7 @@ static int config_output(AVFilterLink *outlink)
return 0;
}
-static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
+static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref, AVFrame **outsamplesref_ret)
{
AVFilterContext *ctx = inlink->dst;
AResampleContext *aresample = ctx->priv;
@@ -220,23 +219,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
AVFrame *outsamplesref;
int ret;
+ *outsamplesref_ret = NULL;
delay = swr_get_delay(aresample->swr, outlink->sample_rate);
if (delay > 0)
n_out += FFMIN(delay, FFMAX(4096, n_out));
outsamplesref = ff_get_audio_buffer(outlink, n_out);
-
- if(!outsamplesref) {
- av_frame_free(&insamplesref);
+ if (!outsamplesref)
return AVERROR(ENOMEM);
- }
av_frame_copy_props(outsamplesref, insamplesref);
outsamplesref->format = outlink->format;
ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout);
if (ret < 0) {
av_frame_free(&outsamplesref);
- av_frame_free(&insamplesref);
return ret;
}
outsamplesref->sample_rate = outlink->sample_rate;
@@ -257,8 +253,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
(void *)insamplesref->extended_data, n_in);
if (n_out <= 0) {
av_frame_free(&outsamplesref);
- av_frame_free(&insamplesref);
- ff_inlink_request_frame(inlink);
return 0;
}
@@ -266,9 +260,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
outsamplesref->nb_samples = n_out;
- ret = ff_filter_frame(outlink, outsamplesref);
- av_frame_free(&insamplesref);
- return ret;
+ *outsamplesref_ret = outsamplesref;
+ return 1;
}
static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret)
@@ -291,7 +284,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref
n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0);
if (n_out <= 0) {
av_frame_free(&outsamplesref);
- return (n_out == 0) ? AVERROR_EOF : n_out;
+ return n_out;
}
outsamplesref->sample_rate = outlink->sample_rate;
@@ -299,7 +292,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref
outsamplesref->pts = pts;
- return 0;
+ return 1;
}
static int activate(AVFilterContext *ctx)
@@ -307,53 +300,54 @@ static int activate(AVFilterContext *ctx)
AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
AResampleContext *aresample = ctx->priv;
+ AVFrame *frame;
int ret = 0, status;
int64_t pts;
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
- if (!aresample->eof && ff_inlink_queued_frames(inlink)) {
- AVFrame *frame = NULL;
+ // First try to get data from the internal buffers
+ if (aresample->more_data) {
+ AVFrame *outsamplesref;
- ret = ff_inlink_consume_frame(inlink, &frame);
+ ret = flush_frame(outlink, 0, &outsamplesref);
if (ret < 0)
return ret;
if (ret > 0)
- return filter_frame(inlink, frame);
+ return ff_filter_frame(outlink, outsamplesref);
}
+ aresample->more_data = 0;
- // First try to get data from the internal buffers
- if (aresample->more_data) {
+ // Then consume frames from inlink
+ while ((ret = ff_inlink_consume_frame(inlink, &frame))) {
AVFrame *outsamplesref;
+ if (ret < 0)
+ return ret;
- if (flush_frame(outlink, 0, &outsamplesref) >= 0) {
+ ret = filter_frame(inlink, frame, &outsamplesref);
+ av_frame_free(&frame);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
return ff_filter_frame(outlink, outsamplesref);
- }
}
- aresample->more_data = 0;
-
- if (!aresample->eof && ff_inlink_acknowledge_status(inlink, &status, &pts))
- aresample->eof = 1;
-
- // Second request more data from the input
- if (!aresample->eof)
- FF_FILTER_FORWARD_WANTED(outlink, inlink);
- // Third if we hit the end flush
- if (aresample->eof) {
+ // If we hit the end flush
+ if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
AVFrame *outsamplesref;
- if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) {
- if (ret == AVERROR_EOF) {
- ff_outlink_set_status(outlink, AVERROR_EOF, aresample->next_pts);
- return 0;
- }
+ ret = flush_frame(outlink, 1, &outsamplesref);
+ if (ret < 0)
return ret;
- }
-
- return ff_filter_frame(outlink, outsamplesref);
+ if (ret > 0)
+ return ff_filter_frame(outlink, outsamplesref);
+ ff_outlink_set_status(outlink, status, aresample->next_pts);
+ return 0;
}
+ // If not, request more data from the input
+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
return FFERROR_NOT_READY;
}
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback Marton Balint
@ 2025-06-16 22:56 ` Andreas Rheinhardt
2025-06-16 23:02 ` Marton Balint
0 siblings, 1 reply; 12+ messages in thread
From: Andreas Rheinhardt @ 2025-06-16 22:56 UTC (permalink / raw)
To: ffmpeg-devel
Marton Balint:
> Sinks without an activate callback (nullsink, anullsink) could cause
> AVERROR(EAGAIN)-s in avfilter_graph_request_oldest() even when all the filter
> graphs inputs were in EOF state.
>
> Fixes ticket #11624.
> Fixes ticket #10988.
> Fixes ticket #10990.
>
> Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
> libavfilter/avfiltergraph.c | 38 ++++++++++++++++++-------------------
> 1 file changed, 18 insertions(+), 20 deletions(-)
>
> diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
> index 2d6036df74..6f9f46f1ea 100644
> --- a/libavfilter/avfiltergraph.c
> +++ b/libavfilter/avfiltergraph.c
> @@ -1423,12 +1423,26 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, FilterLinkInternal *li)
> heap_bubble_down(graphi, li, li->age_index);
> }
>
> +static int process_legacy_sink_output(FilterLinkInternal *oldesti)
Why is considered legacy (instead of being just a different API)?
> +{
> + AVFilterLink *oldest = &oldesti->l.pub;
> + int ret;
> +
> + do {
> + if (oldesti->frame_wanted_out)
> + ret = ff_filter_graph_run_once(oldest->dst->graph);
> + else
> + ret = ff_request_frame(oldest);
> + } while (ret >= 0);
> +
> + return ret;
> +}
> +
> int avfilter_graph_request_oldest(AVFilterGraph *graph)
> {
> FFFilterGraph *graphi = fffiltergraph(graph);
> FilterLinkInternal *oldesti = graphi->sink_links[0];
> AVFilterLink *oldest = &oldesti->l.pub;
> - int64_t frame_count;
> int r;
>
> while (graphi->sink_links_count) {
> @@ -1437,13 +1451,11 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
> if (fffilter(oldest->dst->filter)->activate) {
> r = av_buffersink_get_frame_flags(oldest->dst, NULL,
> AV_BUFFERSINK_FLAG_PEEK);
> - if (r != AVERROR_EOF)
> - return r;
> } else {
> - r = ff_request_frame(oldest);
> + r = process_legacy_sink_output(oldesti);
> }
> if (r != AVERROR_EOF)
> - break;
> + return r;
> av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n",
> oldest->dst->name,
> oldest->dstpad->name);
> @@ -1453,21 +1465,7 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
> oldesti->age_index);
> oldesti->age_index = -1;
> }
> - if (!graphi->sink_links_count)
> - return AVERROR_EOF;
> - av_assert1(!fffilter(oldest->dst->filter)->activate);
> - av_assert1(oldesti->age_index >= 0);
> - frame_count = oldesti->l.frame_count_out;
> - while (frame_count == oldesti->l.frame_count_out) {
> - r = ff_filter_graph_run_once(graph);
> - if (r == AVERROR(EAGAIN) &&
> - !oldesti->frame_wanted_out && !oldesti->frame_blocked_in &&
> - !oldesti->status_in)
> - (void)ff_request_frame(oldest);
> - else if (r < 0)
> - return r;
> - }
> - return 0;
> + return AVERROR_EOF;
> }
>
> int ff_filter_graph_run_once(AVFilterGraph *graph)
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback
2025-06-16 22:56 ` Andreas Rheinhardt
@ 2025-06-16 23:02 ` Marton Balint
2025-06-16 23:54 ` Andreas Rheinhardt
0 siblings, 1 reply; 12+ messages in thread
From: Marton Balint @ 2025-06-16 23:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, 17 Jun 2025, Andreas Rheinhardt wrote:
> Marton Balint:
>> Sinks without an activate callback (nullsink, anullsink) could cause
>> AVERROR(EAGAIN)-s in avfilter_graph_request_oldest() even when all the filter
>> graphs inputs were in EOF state.
>>
>> Fixes ticket #11624.
>> Fixes ticket #10988.
>> Fixes ticket #10990.
>>
>> Signed-off-by: Marton Balint <cus@passwd.hu>
>> ---
>> libavfilter/avfiltergraph.c | 38 ++++++++++++++++++-------------------
>> 1 file changed, 18 insertions(+), 20 deletions(-)
>>
>> diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
>> index 2d6036df74..6f9f46f1ea 100644
>> --- a/libavfilter/avfiltergraph.c
>> +++ b/libavfilter/avfiltergraph.c
>> @@ -1423,12 +1423,26 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, FilterLinkInternal *li)
>> heap_bubble_down(graphi, li, li->age_index);
>> }
>>
>> +static int process_legacy_sink_output(FilterLinkInternal *oldesti)
>
> Why is considered legacy (instead of being just a different API)?
>
The documentation calls it legacy:
doc/filtering_design:
"The design using filter_frame() and request_frame() is legacy, but it is
suitable for filters that have a single input and process one frame at a
time."
avfilter/avfilter.c:
"In order to activate a filter implementing the legacy filter_frame()
and request_frame() methods, perform the first possible of the following
actions:"
But if you have another name in mind for this, I can change it.
Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback
2025-06-16 23:02 ` Marton Balint
@ 2025-06-16 23:54 ` Andreas Rheinhardt
2025-06-17 20:07 ` Marton Balint
0 siblings, 1 reply; 12+ messages in thread
From: Andreas Rheinhardt @ 2025-06-16 23:54 UTC (permalink / raw)
To: ffmpeg-devel
Marton Balint:
>
>
> On Tue, 17 Jun 2025, Andreas Rheinhardt wrote:
>
>> Marton Balint:
>>> Sinks without an activate callback (nullsink, anullsink) could cause
>>> AVERROR(EAGAIN)-s in avfilter_graph_request_oldest() even when all
>>> the filter
>>> graphs inputs were in EOF state.
>>>
>>> Fixes ticket #11624.
>>> Fixes ticket #10988.
>>> Fixes ticket #10990.
>>>
>>> Signed-off-by: Marton Balint <cus@passwd.hu>
>>> ---
>>> libavfilter/avfiltergraph.c | 38 ++++++++++++++++++-------------------
>>> 1 file changed, 18 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
>>> index 2d6036df74..6f9f46f1ea 100644
>>> --- a/libavfilter/avfiltergraph.c
>>> +++ b/libavfilter/avfiltergraph.c
>>> @@ -1423,12 +1423,26 @@ void
>>> ff_avfilter_graph_update_heap(AVFilterGraph *graph,
>>> FilterLinkInternal *li)
>>> heap_bubble_down(graphi, li, li->age_index);
>>> }
>>>
>>> +static int process_legacy_sink_output(FilterLinkInternal *oldesti)
>>
>> Why is considered legacy (instead of being just a different API)?
>>
>
> The documentation calls it legacy:
>
> doc/filtering_design:
>
> "The design using filter_frame() and request_frame() is legacy, but it is
> suitable for filters that have a single input and process one frame at a
> time."
>
> avfilter/avfilter.c:
>
> "In order to activate a filter implementing the legacy filter_frame()
> and request_frame() methods, perform the first possible of the following
> actions:"
>
> But if you have another name in mind for this, I can change it.
>
Why not just call it the "simple" API?
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback
2025-06-16 23:54 ` Andreas Rheinhardt
@ 2025-06-17 20:07 ` Marton Balint
0 siblings, 0 replies; 12+ messages in thread
From: Marton Balint @ 2025-06-17 20:07 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, 17 Jun 2025, Andreas Rheinhardt wrote:
> Marton Balint:
>>
>>
>> On Tue, 17 Jun 2025, Andreas Rheinhardt wrote:
>>
>>> Marton Balint:
>>>> Sinks without an activate callback (nullsink, anullsink) could cause
>>>> AVERROR(EAGAIN)-s in avfilter_graph_request_oldest() even when all
>>>> the filter
>>>> graphs inputs were in EOF state.
>>>>
>>>> Fixes ticket #11624.
>>>> Fixes ticket #10988.
>>>> Fixes ticket #10990.
>>>>
>>>> Signed-off-by: Marton Balint <cus@passwd.hu>
>>>> ---
>>>> libavfilter/avfiltergraph.c | 38 ++++++++++++++++++-------------------
>>>> 1 file changed, 18 insertions(+), 20 deletions(-)
>>>>
>>>> diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
>>>> index 2d6036df74..6f9f46f1ea 100644
>>>> --- a/libavfilter/avfiltergraph.c
>>>> +++ b/libavfilter/avfiltergraph.c
>>>> @@ -1423,12 +1423,26 @@ void
>>>> ff_avfilter_graph_update_heap(AVFilterGraph *graph,
>>>> FilterLinkInternal *li)
>>>> heap_bubble_down(graphi, li, li->age_index);
>>>> }
>>>>
>>>> +static int process_legacy_sink_output(FilterLinkInternal *oldesti)
>>>
>>> Why is considered legacy (instead of being just a different API)?
>>>
>>
>> The documentation calls it legacy:
>>
>> doc/filtering_design:
>>
>> "The design using filter_frame() and request_frame() is legacy, but it is
>> suitable for filters that have a single input and process one frame at a
>> time."
>>
>> avfilter/avfilter.c:
>>
>> "In order to activate a filter implementing the legacy filter_frame()
>> and request_frame() methods, perform the first possible of the following
>> actions:"
>>
>> But if you have another name in mind for this, I can change it.
>>
> Why not just call it the "simple" API?
Ok, changed locally the function name to process_simple_api_sink().
Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status Marton Balint
@ 2025-06-18 11:39 ` Nicolas George
0 siblings, 0 replies; 12+ messages in thread
From: Nicolas George @ 2025-06-18 11:39 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marton Balint
Marton Balint (HE12025-06-17):
> Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
> libavfilter/split.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/libavfilter/split.c b/libavfilter/split.c
> index bf004358d8..0557f54cce 100644
> --- a/libavfilter/split.c
> +++ b/libavfilter/split.c
> @@ -98,6 +98,7 @@ static int activate(AVFilterContext *ctx)
> av_frame_free(&in);
> if (ret < 0)
> return ret;
> + return 0;
> }
>
> if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
LGTM, good catch.
Regards,
--
Nicolas George
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-06-18 11:40 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-16 22:43 [FFmpeg-devel] [PATCH 1/7] fftools/ffmpeg_filter: simplify control flow in read_frames Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 2/7] avfilter/split: consume all frames before forwarding inlink status Marton Balint
2025-06-18 11:39 ` Nicolas George
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 3/7] avfilter/f_select: port to activate Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 4/7] avfilter/avfilter: simplify processing sinks without activate callback Marton Balint
2025-06-16 22:56 ` Andreas Rheinhardt
2025-06-16 23:02 ` Marton Balint
2025-06-16 23:54 ` Andreas Rheinhardt
2025-06-17 20:07 ` Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 5/7] avfilter/af_aresample: merge request_frame into activate function Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 6/7] avfilter/af_aresample: make aresample return FFERROR_NOT_READY when no progress can be made Marton Balint
2025-06-16 22:43 ` [FFmpeg-devel] [PATCH 7/7] avfilter/af_aresample: rework activate logic to follow the advised flow more strictly Marton Balint
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git