mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-18 05:24:42 +00:00
lavfi: make request_frame() non-recursive.
Instead of calling the input filter request_frame() method, ff_request_frame() now marks the link and returns immediately. buffersink is changed to activate the marked filters until a frame is obtained.
This commit is contained in:
parent
108b4de552
commit
1655788712
@ -186,6 +186,7 @@ void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
|
||||
void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)
|
||||
{
|
||||
link->status = status;
|
||||
link->frame_wanted_in = link->frame_wanted_out = 0;
|
||||
ff_update_link_current_pts(link, pts);
|
||||
}
|
||||
|
||||
@ -354,11 +355,21 @@ void ff_tlog_link(void *ctx, AVFilterLink *link, int end)
|
||||
|
||||
int ff_request_frame(AVFilterLink *link)
|
||||
{
|
||||
int ret = -1;
|
||||
FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
|
||||
|
||||
if (link->status)
|
||||
return link->status;
|
||||
link->frame_wanted_in = 1;
|
||||
link->frame_wanted_out = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_request_frame_to_filter(AVFilterLink *link)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1);
|
||||
link->frame_wanted_in = 0;
|
||||
if (link->srcpad->request_frame)
|
||||
ret = link->srcpad->request_frame(link);
|
||||
else if (link->src->inputs[0])
|
||||
@ -367,6 +378,9 @@ int ff_request_frame(AVFilterLink *link)
|
||||
AVFrame *pbuf = link->partial_buf;
|
||||
link->partial_buf = NULL;
|
||||
ret = ff_filter_frame_framed(link, pbuf);
|
||||
ff_avfilter_link_set_in_status(link, AVERROR_EOF, AV_NOPTS_VALUE);
|
||||
link->frame_wanted_out = 0;
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (ret != AVERROR(EAGAIN) && ret != link->status)
|
||||
@ -1136,6 +1150,9 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame)
|
||||
if (pbuf->nb_samples >= link->min_samples) {
|
||||
ret = ff_filter_frame_framed(link, pbuf);
|
||||
pbuf = NULL;
|
||||
} else {
|
||||
if (link->frame_wanted_out)
|
||||
link->frame_wanted_in = 1;
|
||||
}
|
||||
}
|
||||
av_frame_free(&frame);
|
||||
@ -1177,6 +1194,7 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
|
||||
}
|
||||
}
|
||||
|
||||
link->frame_wanted_out = 0;
|
||||
/* Go directly to actual filtering if possible */
|
||||
if (link->type == AVMEDIA_TYPE_AUDIO &&
|
||||
link->min_samples &&
|
||||
|
@ -520,6 +520,20 @@ struct AVFilterLink {
|
||||
* A pointer to a FFVideoFramePool struct.
|
||||
*/
|
||||
void *video_frame_pool;
|
||||
|
||||
/**
|
||||
* True if a frame is currently wanted on the input of this filter.
|
||||
* Set when ff_request_frame() is called by the output,
|
||||
* cleared when the request is handled or forwarded.
|
||||
*/
|
||||
int frame_wanted_in;
|
||||
|
||||
/**
|
||||
* True if a frame is currently wanted on the output of this filter.
|
||||
* Set when ff_request_frame() is called by the output,
|
||||
* cleared when a frame is filtered.
|
||||
*/
|
||||
int frame_wanted_out;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1367,11 +1367,14 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link)
|
||||
|
||||
int avfilter_graph_request_oldest(AVFilterGraph *graph)
|
||||
{
|
||||
AVFilterLink *oldest = graph->sink_links[0];
|
||||
int r;
|
||||
|
||||
while (graph->sink_links_count) {
|
||||
AVFilterLink *oldest = graph->sink_links[0];
|
||||
int r = ff_request_frame(oldest);
|
||||
oldest = graph->sink_links[0];
|
||||
r = ff_request_frame(oldest);
|
||||
if (r != AVERROR_EOF)
|
||||
return r;
|
||||
break;
|
||||
av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n",
|
||||
oldest->dst ? oldest->dst->name : "unknown",
|
||||
oldest->dstpad ? oldest->dstpad->name : "unknown");
|
||||
@ -1381,5 +1384,52 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
|
||||
oldest->age_index);
|
||||
oldest->age_index = -1;
|
||||
}
|
||||
return AVERROR_EOF;
|
||||
if (!graph->sink_links_count)
|
||||
return AVERROR_EOF;
|
||||
av_assert1(oldest->age_index >= 0);
|
||||
while (oldest->frame_wanted_out) {
|
||||
r = ff_filter_graph_run_once(graph);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
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;
|
||||
|
||||
link = graph_run_once_find_filter(graph);
|
||||
if (!link) {
|
||||
av_log(NULL, AV_LOG_WARNING, "Useless run of a filter graph\n");
|
||||
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;
|
||||
}
|
||||
|
@ -140,6 +140,11 @@ int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFr
|
||||
return AVERROR(EAGAIN);
|
||||
if ((ret = ff_request_frame(inlink)) < 0)
|
||||
return ret;
|
||||
while (inlink->frame_wanted_out) {
|
||||
ret = ff_filter_graph_run_once(ctx->graph);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & AV_BUFFERSINK_FLAG_PEEK) {
|
||||
|
@ -334,6 +334,8 @@ int ff_poll_frame(AVFilterLink *link);
|
||||
*/
|
||||
int ff_request_frame(AVFilterLink *link);
|
||||
|
||||
int ff_request_frame_to_filter(AVFilterLink *link);
|
||||
|
||||
#define AVFILTER_DEFINE_CLASS(fname) \
|
||||
static const AVClass fname##_class = { \
|
||||
.class_name = #fname, \
|
||||
@ -379,6 +381,11 @@ AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
|
||||
*/
|
||||
void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter);
|
||||
|
||||
/**
|
||||
* Run one round of processing on a filter graph.
|
||||
*/
|
||||
int ff_filter_graph_run_once(AVFilterGraph *graph);
|
||||
|
||||
/**
|
||||
* Normalize the qscale factor
|
||||
* FIXME the H264 qscale is a log based scale, mpeg1/2 is not, the code below
|
||||
|
Loading…
Reference in New Issue
Block a user