diff mbox series

[FFmpeg-devel] fftools/ffmpeg: Avoid temporary frame

Message ID AM7PR03MB66609A1D82CA5FDCB2E6B0648F9C9@AM7PR03MB6660.eurprd03.prod.outlook.com
State Superseded
Headers show
Series [FFmpeg-devel] fftools/ffmpeg: Avoid temporary frame
Related show

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Andreas Rheinhardt Nov. 19, 2021, 4:43 p.m. UTC
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.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 fftools/ffmpeg.c     | 22 +++++++---------------
 fftools/ffmpeg.h     |  1 -
 fftools/ffmpeg_opt.c |  4 ----
 3 files changed, 7 insertions(+), 20 deletions(-)

Comments

James Almer Nov. 19, 2021, 4:53 p.m. UTC | #1
On 11/19/2021 1:43 PM, Andreas Rheinhardt wrote:
> 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.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
>   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 e88ca554ae..bdbbc23cfd 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,7 +2170,7 @@ 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 buffersrc_flags)
>   {
>       FilterGraph *fg = ifilter->graph;
>       AVFrameSideData *sd;
> @@ -2217,7 +2216,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 +2241,8 @@ 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,
> +                                       AV_BUFFERSRC_FLAG_PUSH | buffersrc_flags);

nit: It may look nicer if you instead make ifilter_send_frame() like

static int ifilter_send_frame(InputStream *ist, AVFrame *frame, int idx)
{
     InputFilter *ifilter = ist->filters[idx];
     int flags = AV_BUFFERSRC_FLAG_PUSH;
     [...]
     if (idx < ist->nb_filters - 1)
         flags |= AV_BUFFERSRC_FLAG_KEEP_REF;
     ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, flags);
     [...]
}

Which will simplify the code in send_frame_to_filters() below with a simple

ret = ifilter_send_frame(ist, decoded_frame, i);

>       if (ret < 0) {
>           if (ret != AVERROR_EOF)
>               av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));
> @@ -2306,18 +2305,13 @@ 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);
> +        int flags = 0;
> +        if (i < ist->nb_filters - 1)
> +            flags = AV_BUFFERSRC_FLAG_KEEP_REF;
> +        ret = ifilter_send_frame(ist->filters[i], decoded_frame, flags);
>           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 545ff1c8e7..ce790c4d6f 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);
>
Andreas Rheinhardt Nov. 19, 2021, 5:02 p.m. UTC | #2
James Almer:
> On 11/19/2021 1:43 PM, Andreas Rheinhardt wrote:
>> 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.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>> ---
>>   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 e88ca554ae..bdbbc23cfd 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,7 +2170,7 @@ 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 buffersrc_flags)
>>   {
>>       FilterGraph *fg = ifilter->graph;
>>       AVFrameSideData *sd;
>> @@ -2217,7 +2216,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 +2241,8 @@ 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,
>> +                                       AV_BUFFERSRC_FLAG_PUSH |
>> buffersrc_flags);
> 
> nit: It may look nicer if you instead make ifilter_send_frame() like
> 
> static int ifilter_send_frame(InputStream *ist, AVFrame *frame, int idx)
> {
>     InputFilter *ifilter = ist->filters[idx];
>     int flags = AV_BUFFERSRC_FLAG_PUSH;
>     [...]
>     if (idx < ist->nb_filters - 1)
>         flags |= AV_BUFFERSRC_FLAG_KEEP_REF;
>     ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, flags);
>     [...]
> }
> 
> Which will simplify the code in send_frame_to_filters() below with a simple
> 
> ret = ifilter_send_frame(ist, decoded_frame, i);
> 

I do not really like the thought of ifilter_send_frame() knowing the idx
of the filter it is processing. If you don't like
send_frame_to_filters() setting the buffersrc flags itself, one could
use static int ifilter_send_frame(InputStream *ist, AVFrame *frame, int
const_frame) with the semantics being that if const_frame is set, the
frame is to be treated as const, otherwise ifilter_send_frame() may use
the supplied references. The call would then be ifilter_send_frame(ist,
decoded_frame, i != ist->nb_filters - 1).
(Honestly, the reason I didn't do it in this way is because I didn't
like the const_frame name; but I couldn't come up with something better.)

>>       if (ret < 0) {
>>           if (ret != AVERROR_EOF)
>>               av_log(NULL, AV_LOG_ERROR, "Error while filtering:
>> %s\n", av_err2str(ret));
>> @@ -2306,18 +2305,13 @@ 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);
>> +        int flags = 0;
>> +        if (i < ist->nb_filters - 1)
>> +            flags = AV_BUFFERSRC_FLAG_KEEP_REF;
>> +        ret = ifilter_send_frame(ist->filters[i], decoded_frame, flags);
>>           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 545ff1c8e7..ce790c4d6f 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);
>>
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
James Almer Nov. 19, 2021, 6:04 p.m. UTC | #3
On 11/19/2021 2:02 PM, Andreas Rheinhardt wrote:
> James Almer:
>> On 11/19/2021 1:43 PM, Andreas Rheinhardt wrote:
>>> 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.
>>>
>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>>> ---
>>>    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 e88ca554ae..bdbbc23cfd 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,7 +2170,7 @@ 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 buffersrc_flags)
>>>    {
>>>        FilterGraph *fg = ifilter->graph;
>>>        AVFrameSideData *sd;
>>> @@ -2217,7 +2216,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 +2241,8 @@ 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,
>>> +                                       AV_BUFFERSRC_FLAG_PUSH |
>>> buffersrc_flags);
>>
>> nit: It may look nicer if you instead make ifilter_send_frame() like
>>
>> static int ifilter_send_frame(InputStream *ist, AVFrame *frame, int idx)
>> {
>>      InputFilter *ifilter = ist->filters[idx];
>>      int flags = AV_BUFFERSRC_FLAG_PUSH;
>>      [...]
>>      if (idx < ist->nb_filters - 1)
>>          flags |= AV_BUFFERSRC_FLAG_KEEP_REF;
>>      ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, flags);
>>      [...]
>> }
>>
>> Which will simplify the code in send_frame_to_filters() below with a simple
>>
>> ret = ifilter_send_frame(ist, decoded_frame, i);
>>
> 
> I do not really like the thought of ifilter_send_frame() knowing the idx
> of the filter it is processing. If you don't like
> send_frame_to_filters() setting the buffersrc flags itself, one could
> use static int ifilter_send_frame(InputStream *ist, AVFrame *frame, int
> const_frame) with the semantics being that if const_frame is set, the
> frame is to be treated as const, otherwise ifilter_send_frame() may use
> the supplied references. The call would then be ifilter_send_frame(ist,
> decoded_frame, i != ist->nb_filters - 1).
> (Honestly, the reason I didn't do it in this way is because I didn't
> like the const_frame name; but I couldn't come up with something better.)

In that case maybe just set flags to AV_BUFFERSRC_FLAG_PUSH instead of 
zero below in send_frame_to_filters(), and pass buffersrc_flags alone to 
av_buffersrc_add_frame_flags().
What i wanted to avoid is doing "AV_BUFFERSRC_FLAG_PUSH | 
buffersrc_flags", which to me looks really ugly.

> 
>>>        if (ret < 0) {
>>>            if (ret != AVERROR_EOF)
>>>                av_log(NULL, AV_LOG_ERROR, "Error while filtering:
>>> %s\n", av_err2str(ret));
>>> @@ -2306,18 +2305,13 @@ 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);
>>> +        int flags = 0;
>>> +        if (i < ist->nb_filters - 1)
>>> +            flags = AV_BUFFERSRC_FLAG_KEEP_REF;
>>> +        ret = ifilter_send_frame(ist->filters[i], decoded_frame, flags);
>>>            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 545ff1c8e7..ce790c4d6f 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);
>>>
>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
diff mbox series

Patch

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index e88ca554ae..bdbbc23cfd 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,7 +2170,7 @@  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 buffersrc_flags)
 {
     FilterGraph *fg = ifilter->graph;
     AVFrameSideData *sd;
@@ -2217,7 +2216,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 +2241,8 @@  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,
+                                       AV_BUFFERSRC_FLAG_PUSH | 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 +2305,13 @@  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);
+        int flags = 0;
+        if (i < ist->nb_filters - 1)
+            flags = AV_BUFFERSRC_FLAG_KEEP_REF;
+        ret = ifilter_send_frame(ist->filters[i], decoded_frame, flags);
         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 545ff1c8e7..ce790c4d6f 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);