[FFmpeg-devel] [PATCH 1/4] lavfi: add filter metaframes infrastructure.
Nicolas George
george at nsup.org
Wed Jul 30 23:44:46 CEST 2014
Metaframes are frames without data, identified by a negative
format code, used to carry special conditions.
They are sent only to filter that declare supporting them.
The only metaframe for now is EOF; this mechanism augments
the current mechanism based on request_frame() returning
AVERROR_EOF, with the advantage that the EOF metaframe carries
a timestamp.
The metaframes are a purely internal API and do not leak to
the application.
Signed-off-by: Nicolas George <george at nsup.org>
---
libavfilter/avfilter.c | 73 +++++++++++++++++++++++++++++++++++++++++++++-----
libavfilter/internal.h | 34 +++++++++++++++++++++++
2 files changed, 100 insertions(+), 7 deletions(-)
Changed the name to "metaframes".
Allocate the frame with the classic method.
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 7b11467..7894173 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_metaframe(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_METAFRAMES)) {
+ 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_METAFRAME_EOF:
+ link->closed = 1;
+ break;
+
+ case 0:
+ case FF_METAFRAME_NOP:
+ /* Not implemented yet because not used either for now.
+ Caveat: if the same metaframe 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_metaframe(link, frame);
+
/* Consistency checks */
if (link->type == AVMEDIA_TYPE_VIDEO) {
if (strcmp(link->dst->filter->name, "scale")) {
@@ -1162,6 +1205,22 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
}
}
+int ff_filter_link_close(AVFilterLink *link, int64_t pts)
+{
+ AVFrame *frame;
+ int ret;
+
+ if (link->closed)
+ return 0;
+ if (!(frame = av_frame_alloc()))
+ return AVERROR(ENOMEM);
+ frame->format = FF_METAFRAME_EOF;
+ frame->pts = pts;
+ ret = ff_filter_frame(link, frame);
+ av_frame_free(&frame);
+ return ret;
+}
+
const AVClass *avfilter_get_class(void)
{
return &avfilter_class;
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 308b115..fbe603a 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 metaframes.
+ * Metaframes are AVFrame structures with a negative format field.
+ * The framework will take default actions based on the metaframe type.
+ * The destination filter is allowed to reset the type to inhibit the
+ * default actions.
+ */
+#define FF_FILTER_FLAG_SUPPORT_METAFRAMES (1 << 24)
+
+/**
+ * Types of metaframes that can be passer to a filter.
+ */
+enum {
+ /**
+ * Do not do anything.
+ * Can be used by the destination filter to inhibit default handling.
+ */
+ FF_METAFRAME_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_METAFRAME_EOF = AVERROR_EOF,
+};
+
+/**
+ * Close the link by sending the EOF metaframes 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