summaryrefslogtreecommitdiff
path: root/libavfilter
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2013-03-31 19:17:57 +0200
committerNicolas George <nicolas.george@normalesup.org>2013-04-03 17:33:27 +0200
commit79d8cfacf07863500d4fedec669c49e2552c3876 (patch)
treede362386cfaf64843de4de9308e695c2f53a9ccc /libavfilter
parentc208576cef0a97903bbeac4f580fa436605a5c3e (diff)
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.c17
-rw-r--r--libavfilter/avfilter.h11
-rw-r--r--libavfilter/internal.h14
3 files changed, 40 insertions, 2 deletions
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 8a907dc085..f62194136c 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 455161fa34..7583dccfbe 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 9a42ae08df..0b28422f1f 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 */