diff options
author | Nicolas George <nicolas.george@normalesup.org> | 2013-03-31 19:17:57 +0200 |
---|---|---|
committer | Nicolas George <nicolas.george@normalesup.org> | 2013-04-03 17:33:27 +0200 |
commit | 79d8cfacf07863500d4fedec669c49e2552c3876 (patch) | |
tree | de362386cfaf64843de4de9308e695c2f53a9ccc /libavfilter | |
parent | c208576cef0a97903bbeac4f580fa436605a5c3e (diff) | |
download | ffmpeg-streaming-79d8cfacf07863500d4fedec669c49e2552c3876.zip ffmpeg-streaming-79d8cfacf07863500d4fedec669c49e2552c3876.tar.gz |
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.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/avfilter.c | 17 | ||||
-rw-r--r-- | libavfilter/avfilter.h | 11 | ||||
-rw-r--r-- | libavfilter/internal.h | 14 |
3 files changed, 40 insertions, 2 deletions
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 8a907dc..f621941 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -323,6 +323,10 @@ int ff_request_frame(AVFilterLink *link) if (link->closed) return AVERROR_EOF; + av_assert0(!link->frame_requested); + link->frame_requested = 1; + while (link->frame_requested) { + /* TODO reindent */ if (link->srcpad->request_frame) ret = link->srcpad->request_frame(link); else if (link->src->inputs[0]) @@ -332,8 +336,15 @@ int ff_request_frame(AVFilterLink *link) link->partial_buf = NULL; ret = ff_filter_frame_framed(link, pbuf); } - if (ret == AVERROR_EOF) - link->closed = 1; + if (ret < 0) { + link->frame_requested = 0; + if (ret == AVERROR_EOF) + link->closed = 1; + } else { + av_assert0(!link->frame_requested || + link->flags & FF_LINK_FLAG_REQUEST_LOOP); + } + } return ret; } @@ -702,6 +713,7 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) pts = out->pts; ret = filter_frame(link, out); + link->frame_requested = 0; ff_update_link_current_pts(link, pts); return ret; } @@ -713,6 +725,7 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame) int nb_channels = av_frame_get_channels(frame); int ret = 0; + link->flags |= FF_LINK_FLAG_REQUEST_LOOP; /* Handle framing (min_samples, max_samples) */ while (insamples) { if (!pbuf) { diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 455161f..7583dcc 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -682,6 +682,17 @@ struct AVFilterLink { * Number of 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; }; /** diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 9a42ae0..0b28422 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -325,4 +325,18 @@ int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef ** */ 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 */ |