From a132614bba247afac30d3a8b1378c40bd7f672bc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 19 Nov 2021 17:29:33 +0100 Subject: [PATCH] fftools/ffmpeg: Avoid temporary frame send_frame_to_filters() sends a frame to all the filters that need said frame; for every filter except the last one this involves creating a reference to the frame, because av_buffersrc_add_frame_flags() by default takes ownership of the supplied references. Yet said function has a flag which changes its behaviour to create a reference itself. This commit uses this flag and stops creating the references itself; this allows to remove the spare AVFrame holding the temporary references; it also avoids unreferencing said frame. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 22 +++++++--------------- fftools/ffmpeg.h | 1 - fftools/ffmpeg_opt.c | 4 ---- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index fa66aa1cf9..c9a9cdfcd6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -633,7 +633,6 @@ static void ffmpeg_cleanup(int ret) InputStream *ist = input_streams[i]; av_frame_free(&ist->decoded_frame); - av_frame_free(&ist->filter_frame); av_packet_free(&ist->pkt); av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); @@ -2171,11 +2170,15 @@ static int ifilter_has_all_input_formats(FilterGraph *fg) return 1; } -static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) { FilterGraph *fg = ifilter->graph; AVFrameSideData *sd; int need_reinit, ret; + int buffersrc_flags = AV_BUFFERSRC_FLAG_PUSH; + + if (keep_reference) + buffersrc_flags |= AV_BUFFERSRC_FLAG_KEEP_REF; /* determine if the parameters for this input changed */ need_reinit = ifilter->format != frame->format; @@ -2217,7 +2220,6 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) AVFrame *tmp = av_frame_clone(frame); if (!tmp) return AVERROR(ENOMEM); - av_frame_unref(frame); if (!av_fifo_space(ifilter->frame_queue)) { ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); @@ -2243,7 +2245,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) } } - ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, AV_BUFFERSRC_FLAG_PUSH); + ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, buffersrc_flags); if (ret < 0) { if (ret != AVERROR_EOF) av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); @@ -2306,18 +2308,10 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacke static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) { int i, ret; - AVFrame *f; av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */ for (i = 0; i < ist->nb_filters; i++) { - if (i < ist->nb_filters - 1) { - f = ist->filter_frame; - ret = av_frame_ref(f, decoded_frame); - if (ret < 0) - break; - } else - f = decoded_frame; - ret = ifilter_send_frame(ist->filters[i], f); + ret = ifilter_send_frame(ist->filters[i], decoded_frame, i < ist->nb_filters - 1); if (ret == AVERROR_EOF) ret = 0; /* ignore */ if (ret < 0) { @@ -2385,7 +2379,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, ist->nb_samples = decoded_frame->nb_samples; err = send_frame_to_filters(ist, decoded_frame); - av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } @@ -2511,7 +2504,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ err = send_frame_to_filters(ist, decoded_frame); fail: - av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e86ab61047..1728010f56 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -311,7 +311,6 @@ typedef struct InputStream { AVCodecContext *dec_ctx; const AVCodec *dec; AVFrame *decoded_frame; - AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ AVPacket *pkt; int64_t prev_pkt_pts; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 98bd3b47b6..6732a29625 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -893,10 +893,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) if (!ist->decoded_frame) exit_program(1); - ist->filter_frame = av_frame_alloc(); - if (!ist->filter_frame) - exit_program(1); - ist->pkt = av_packet_alloc(); if (!ist->pkt) exit_program(1);