[FFmpeg-devel] [PATCH 1/4] lavfi: add filter messages infrastructure.
Nicolas George
george at nsup.org
Thu Jul 24 15:39:42 CEST 2014
Messaages are passed as frames with a negative format code,
only to filter that declare supporting them.
The only message for now is EOF; this mechanism augments
the current mechanism based on request_frame() returning
AVERROR_EOF, with the advantage that the EOF message carries
a timestamp.
The messages are a purely internal API and do not leak to
the application.
Signed-off-by: Nicolas George <george at nsup.org>
---
libavfilter/avfilter.c | 68 ++++++++++++++++++++++++++++++++++++++++++++------
libavfilter/internal.h | 34 +++++++++++++++++++++++++
2 files changed, 95 insertions(+), 7 deletions(-)
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 7b11467..fb41e71 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -346,15 +346,16 @@ int ff_request_frame(AVFilterLink *link)
ret = link->srcpad->request_frame(link);
else if (link->src->inputs[0])
ret = ff_request_frame(link->src->inputs[0]);
- if (ret == AVERROR_EOF && link->partial_buf) {
- AVFrame *pbuf = link->partial_buf;
- link->partial_buf = NULL;
- ret = ff_filter_frame_framed(link, pbuf);
- }
if (ret < 0) {
+ if (!link->frame_requested) {
+ av_assert0(ret == AVERROR_EOF);
+ ret = 0;
+ }
link->frame_requested = 0;
- if (ret == AVERROR_EOF)
- link->closed = 1;
+ if (ret == AVERROR_EOF) {
+ ret = ff_filter_link_close(link, AV_NOPTS_VALUE);
+ return ret < 0 ? ret : AVERROR_EOF;
+ }
} else {
av_assert0(!link->frame_requested ||
link->flags & FF_LINK_FLAG_REQUEST_LOOP);
@@ -1132,10 +1133,52 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame)
return ret;
}
+static int ff_filter_frame_message(AVFilterLink *link, AVFrame *frame)
+{
+ AVFrame *pbuf = link->partial_buf;
+ int ret;
+
+ if (pbuf) {
+ link->partial_buf = NULL;
+ if ((ret = ff_filter_frame_framed(link, pbuf)) < 0)
+ return ret;
+ }
+
+ if ((link->dst->filter->flags & FF_FILTER_FLAG_SUPPORT_MESSAGES)) {
+ ret = link->dstpad->filter_frame ?
+ link->dstpad->filter_frame(link, frame) :
+ default_filter_frame(link, frame);
+ if (ret < 0)
+ return ret;
+ }
+
+ switch (frame->format) {
+
+ case FF_FRAME_MSG_EOF:
+ link->closed = 1;
+ break;
+
+ case 0:
+ case FF_FRAME_MSG_NOP:
+ /* Not implemented yet because not used either for now.
+ Caveat: if the same message frame is forwarded to the next filter
+ and the next filter changes the type, the type change must not be
+ taken into account for the first link. */
+
+ default:
+ av_assert0(!"reached");
+ }
+
+ return ret;
+}
+
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
{
FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
+ if (frame->format < -1)
+ return ff_filter_frame_message(link, frame);
+
/* Consistency checks */
if (link->type == AVMEDIA_TYPE_VIDEO) {
if (strcmp(link->dst->filter->name, "scale")) {
@@ -1162,6 +1205,17 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
}
}
+int ff_filter_link_close(AVFilterLink *link, int64_t pts)
+{
+ AVFrame frame = { };
+
+ if (link->closed)
+ return 0;
+ frame.format = FF_FRAME_MSG_EOF;
+ frame.pts = pts;
+ return ff_filter_frame(link, &frame);
+}
+
const AVClass *avfilter_get_class(void)
{
return &avfilter_class;
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 308b115..de249a4 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -374,4 +374,38 @@ AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
*/
void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter);
+/**
+ * The filter can accept messages.
+ */
+#define FF_FILTER_FLAG_SUPPORT_MESSAGES (1 << 24)
+
+/**
+ * Types of messages that can be passer to a filter.
+ * Messages are passed as AVFrame structures with a negative format field.
+ * The framework will take default actions based on the message type.
+ * The destination filter is allowed to reset the type to inhibit the
+ * default actions.
+ */
+enum {
+ /**
+ * Do not do anything.
+ * Can be used by the destination filter to inhibit default handling.
+ */
+ FF_FRAME_MSG_NOP = -1,
+
+ /**
+ * The input has reached EOF.
+ * The pts field holds the timestamp of the end of the stream,
+ * therefore allowing to compute the duration of the last frame.
+ * The frame structure still belongs to the framework and must not be
+ * stored by the destination filter; it also may be incomplete.
+ */
+ FF_FRAME_MSG_EOF = AVERROR_EOF,
+};
+
+/**
+ * Close the link by sending the EOF message to the destination filter.
+ */
+int ff_filter_link_close(AVFilterLink *link, int64_t pts);
+
#endif /* AVFILTER_INTERNAL_H */
--
2.0.1
More information about the ffmpeg-devel
mailing list