Commit 79d8cfac authored by Nicolas George's avatar Nicolas George

lavfi: loop on request_frame if necessary.

Some filters need several input frames before producing output.
For these filter, it becomes simpler to return 0 in
request_frame() and let the framework call it again until
output has been produced.
parent c208576c
...@@ -323,6 +323,10 @@ int ff_request_frame(AVFilterLink *link) ...@@ -323,6 +323,10 @@ int ff_request_frame(AVFilterLink *link)
if (link->closed) if (link->closed)
return AVERROR_EOF; return AVERROR_EOF;
av_assert0(!link->frame_requested);
link->frame_requested = 1;
while (link->frame_requested) {
/* TODO reindent */
if (link->srcpad->request_frame) if (link->srcpad->request_frame)
ret = link->srcpad->request_frame(link); ret = link->srcpad->request_frame(link);
else if (link->src->inputs[0]) else if (link->src->inputs[0])
...@@ -332,8 +336,15 @@ int ff_request_frame(AVFilterLink *link) ...@@ -332,8 +336,15 @@ int ff_request_frame(AVFilterLink *link)
link->partial_buf = NULL; link->partial_buf = NULL;
ret = ff_filter_frame_framed(link, pbuf); ret = ff_filter_frame_framed(link, pbuf);
} }
if (ret < 0) {
link->frame_requested = 0;
if (ret == AVERROR_EOF) if (ret == AVERROR_EOF)
link->closed = 1; link->closed = 1;
} else {
av_assert0(!link->frame_requested ||
link->flags & FF_LINK_FLAG_REQUEST_LOOP);
}
}
return ret; return ret;
} }
...@@ -702,6 +713,7 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) ...@@ -702,6 +713,7 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
pts = out->pts; pts = out->pts;
ret = filter_frame(link, out); ret = filter_frame(link, out);
link->frame_requested = 0;
ff_update_link_current_pts(link, pts); ff_update_link_current_pts(link, pts);
return ret; return ret;
} }
...@@ -713,6 +725,7 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame) ...@@ -713,6 +725,7 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame)
int nb_channels = av_frame_get_channels(frame); int nb_channels = av_frame_get_channels(frame);
int ret = 0; int ret = 0;
link->flags |= FF_LINK_FLAG_REQUEST_LOOP;
/* Handle framing (min_samples, max_samples) */ /* Handle framing (min_samples, max_samples) */
while (insamples) { while (insamples) {
if (!pbuf) { if (!pbuf) {
......
...@@ -682,6 +682,17 @@ struct AVFilterLink { ...@@ -682,6 +682,17 @@ struct AVFilterLink {
* Number of channels. * Number of channels.
*/ */
int channels; int channels;
/**
* True if a frame is being requested on the link.
* Used internally by the framework.
*/
unsigned frame_requested;
/**
* Link processing flags.
*/
unsigned flags;
}; };
/** /**
......
...@@ -325,4 +325,18 @@ int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef ** ...@@ -325,4 +325,18 @@ int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **
*/ */
int ff_filter_frame(AVFilterLink *link, AVFrame *frame); int ff_filter_frame(AVFilterLink *link, AVFrame *frame);
/**
* Flags for AVFilterLink.flags.
*/
enum {
/**
* Frame requests may need to loop in order to be fulfilled.
* A filter must set this flags on an output link if it may return 0 in
* request_frame() without filtering a frame.
*/
FF_LINK_FLAG_REQUEST_LOOP = 1,
};
#endif /* AVFILTER_INTERNAL_H */ #endif /* AVFILTER_INTERNAL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment