Skip to content

Commit

Permalink
avfilter/internal: Add flag to free filtered AVFrames generically
Browse files Browse the repository at this point in the history
Up until now, an AVFilterPad's filter_frame callback was always
responsible for passing the frame to the next filter or freeing it.
Yet there are several filter_frame callbacks that need to free this
frame on every exit, so it makes sense to do this generically.
This commit adds a flag which if set shifts the responsibility to free
the frame to the caller of filter_frame.

In the future this might be extended to avoid allocating+freeing the
frame for filters with this flag set.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
  • Loading branch information
mkver committed Aug 15, 2021
1 parent 0a6e37a commit 8fec2d7
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
8 changes: 6 additions & 2 deletions libavfilter/avfilter.c
Expand Up @@ -958,7 +958,7 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
int (*filter_frame)(AVFilterLink *, AVFrame *);
AVFilterContext *dstctx = link->dst;
AVFilterPad *dst = link->dstpad;
int ret;
int ret, needs_free = dst->flags & AVFILTERPAD_FLAG_GENERIC_FREE;

if (!(filter_frame = dst->filter_frame))
filter_frame = default_filter_frame;
Expand All @@ -973,9 +973,13 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
dstctx->is_disabled = !ff_inlink_evaluate_timeline_at_frame(link, frame);

if (dstctx->is_disabled &&
(dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC))
(dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) {
filter_frame = default_filter_frame;
needs_free = 0;
}
ret = filter_frame(link, frame);
if (needs_free)
av_frame_free(&frame);
link->frame_count_out++;
return ret;

Expand Down
11 changes: 10 additions & 1 deletion libavfilter/internal.h
Expand Up @@ -68,6 +68,14 @@ struct AVFilterPad {
*/
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE (1 << 0)

/**
* AVFilterPad.filter_frame does not free its input frame at all
* and expects its caller to do so all the time.
*
* input pads only.
*/
#define AVFILTERPAD_FLAG_GENERIC_FREE (1 << 1)

/**
* A combination of AVFILTERPAD_FLAG_* flags.
*/
Expand Down Expand Up @@ -97,7 +105,8 @@ struct AVFilterPad {
*
* @return >= 0 on success, a negative AVERROR on error. This function
* must ensure that frame is properly unreferenced on error if it
* hasn't been passed on to another filter.
* hasn't been passed on to another filter unless the
* AVFILTERPAD_FLAG_GENERIC_FREE flag is set.
*/
int (*filter_frame)(AVFilterLink *link, AVFrame *frame);

Expand Down

0 comments on commit 8fec2d7

Please sign in to comment.