On date Wednesday 2014-07-30 23:44:46 +0200, Nicolas George encoded: > 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 <geo...@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; It shall probably execute the remaining part of the function even in case of failure. > + } > + > + 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. */ I find this a bit confusing. Can you explain why the NOP metaframe is needed? > + > + 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 */ LGTM otherwise. -- FFmpeg = Foolish Forgiving Mortal Power Exxagerate Gnome _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel