mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-13 02:20:07 +01:00
lavfi: make filter_frame non-recursive.
A lot of changes happen at the same time: - Add a framequeue fifo to AVFilterLink. - split AVFilterLink.status into status_in and status_out: requires changes to the few filters and programs that use it directly (f_interleave, split, filtfmts). - Add a field ready to AVFilterContext, marking when the filter is ready and its activation priority. - Add flags to mark blocked links. - Change ff_filter_frame() to enqueue the frame. - Change all filtering functions to update the ready field and the blocked flags. - Update ff_filter_graph_run_once() to use the ready field. - buffersrc: always push the frame immediately.
This commit is contained in:
@@ -32,6 +32,9 @@
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
|
||||
#define FF_INTERNAL_FIELDS 1
|
||||
#include "framequeue.h"
|
||||
|
||||
#include "avfilter.h"
|
||||
#include "formats.h"
|
||||
#include "internal.h"
|
||||
@@ -87,6 +90,7 @@ AVFilterGraph *avfilter_graph_alloc(void)
|
||||
|
||||
ret->av_class = &filtergraph_class;
|
||||
av_opt_set_defaults(ret);
|
||||
ff_framequeue_global_init(&ret->internal->frame_queues);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1377,10 +1381,10 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link)
|
||||
heap_bubble_down(graph, link, link->age_index);
|
||||
}
|
||||
|
||||
|
||||
int avfilter_graph_request_oldest(AVFilterGraph *graph)
|
||||
{
|
||||
AVFilterLink *oldest = graph->sink_links[0];
|
||||
int64_t frame_count;
|
||||
int r;
|
||||
|
||||
while (graph->sink_links_count) {
|
||||
@@ -1400,7 +1404,8 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
|
||||
if (!graph->sink_links_count)
|
||||
return AVERROR_EOF;
|
||||
av_assert1(oldest->age_index >= 0);
|
||||
while (oldest->frame_wanted_out) {
|
||||
frame_count = oldest->frame_count_out;
|
||||
while (frame_count == oldest->frame_count_out) {
|
||||
r = ff_filter_graph_run_once(graph);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1408,41 +1413,17 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static AVFilterLink *graph_run_once_find_filter(AVFilterGraph *graph)
|
||||
{
|
||||
unsigned i, j;
|
||||
AVFilterContext *f;
|
||||
|
||||
/* TODO: replace scanning the graph with a priority list */
|
||||
for (i = 0; i < graph->nb_filters; i++) {
|
||||
f = graph->filters[i];
|
||||
for (j = 0; j < f->nb_outputs; j++)
|
||||
if (f->outputs[j]->frame_wanted_in)
|
||||
return f->outputs[j];
|
||||
}
|
||||
for (i = 0; i < graph->nb_filters; i++) {
|
||||
f = graph->filters[i];
|
||||
for (j = 0; j < f->nb_outputs; j++)
|
||||
if (f->outputs[j]->frame_wanted_out)
|
||||
return f->outputs[j];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ff_filter_graph_run_once(AVFilterGraph *graph)
|
||||
{
|
||||
AVFilterLink *link;
|
||||
int ret;
|
||||
AVFilterContext *filter;
|
||||
unsigned i;
|
||||
|
||||
link = graph_run_once_find_filter(graph);
|
||||
if (!link) {
|
||||
av_log(NULL, AV_LOG_WARNING, "Useless run of a filter graph\n");
|
||||
av_assert0(graph->nb_filters);
|
||||
filter = graph->filters[0];
|
||||
for (i = 1; i < graph->nb_filters; i++)
|
||||
if (graph->filters[i]->ready > filter->ready)
|
||||
filter = graph->filters[i];
|
||||
if (!filter->ready)
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
ret = ff_request_frame_to_filter(link);
|
||||
if (ret == AVERROR_EOF)
|
||||
/* local EOF will be forwarded through request_frame() /
|
||||
set_status() until it reaches the sink */
|
||||
ret = 0;
|
||||
return ret < 0 ? ret : 1;
|
||||
return ff_filter_activate(filter);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user