[FFmpeg-devel] [PATCH 1/4] lavfi: add filter metaframes infrastructure.

Stefano Sabatini stefasab at gmail.com
Sat Aug 2 17:20:44 CEST 2014


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 <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;

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


More information about the ffmpeg-devel mailing list