diff mbox series

[FFmpeg-devel] avcodec/avcodec: don't free AVOption settable fields in avcodec_close()

Message ID 20220320231809.40398-1-jamrial@gmail.com
State New
Headers show
Series [FFmpeg-devel] avcodec/avcodec: don't free AVOption settable fields in avcodec_close() | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_aarch64_jetson success Make finished
andriy/make_fate_aarch64_jetson success Make fate finished
andriy/make_armv7_RPi4 success Make finished
andriy/make_fate_armv7_RPi4 success Make fate finished

Commit Message

James Almer March 20, 2022, 11:18 p.m. UTC
It can uninitialize fields that may still be used after the context was closed,
so do it instead in avcodec_free_context().

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/avcodec.c | 1 -
 libavcodec/options.c | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

Comments

Andreas Rheinhardt March 20, 2022, 11:26 p.m. UTC | #1
James Almer:
> It can uninitialize fields that may still be used after the context was closed,
> so do it instead in avcodec_free_context().
> 
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libavcodec/avcodec.c | 1 -
>  libavcodec/options.c | 2 +-
>  2 files changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
> index 38bdaad4fa..122d09b63a 100644
> --- a/libavcodec/avcodec.c
> +++ b/libavcodec/avcodec.c
> @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>  
>      if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
>          av_opt_free(avctx->priv_data);
> -    av_opt_free(avctx);
>      av_freep(&avctx->priv_data);
>      if (av_codec_is_encoder(avctx->codec)) {
>          av_freep(&avctx->extradata);
> diff --git a/libavcodec/options.c b/libavcodec/options.c
> index 33f11480a7..91335415c1 100644
> --- a/libavcodec/options.c
> +++ b/libavcodec/options.c
> @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>      av_freep(&avctx->intra_matrix);
>      av_freep(&avctx->inter_matrix);
>      av_freep(&avctx->rc_override);
> -    av_channel_layout_uninit(&avctx->ch_layout);
> +    av_opt_free(avctx);
>  
>      av_freep(pavctx);
>  }

This will lead to memleaks for users that use avcodec_close(avctx) +
av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
encoders do this). Notice that avcodec_free_context() violates the
documentation of AVCodecContext.extradata (documented to not be freed
for decoders) and AVCodecContext.subtitle_header and
AVCodecContext.rc_override (documented to not be freed by lavc for
encoders), so there is a reason for using it instead of
avcodec_free_context() (even when not reusing the context).

- Andreas
James Almer March 20, 2022, 11:29 p.m. UTC | #2
On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
> James Almer:
>> It can uninitialize fields that may still be used after the context was closed,
>> so do it instead in avcodec_free_context().
>>
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   libavcodec/avcodec.c | 1 -
>>   libavcodec/options.c | 2 +-
>>   2 files changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>> index 38bdaad4fa..122d09b63a 100644
>> --- a/libavcodec/avcodec.c
>> +++ b/libavcodec/avcodec.c
>> @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>   
>>       if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
>>           av_opt_free(avctx->priv_data);
>> -    av_opt_free(avctx);
>>       av_freep(&avctx->priv_data);
>>       if (av_codec_is_encoder(avctx->codec)) {
>>           av_freep(&avctx->extradata);
>> diff --git a/libavcodec/options.c b/libavcodec/options.c
>> index 33f11480a7..91335415c1 100644
>> --- a/libavcodec/options.c
>> +++ b/libavcodec/options.c
>> @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>>       av_freep(&avctx->intra_matrix);
>>       av_freep(&avctx->inter_matrix);
>>       av_freep(&avctx->rc_override);
>> -    av_channel_layout_uninit(&avctx->ch_layout);
>> +    av_opt_free(avctx);
>>   
>>       av_freep(pavctx);
>>   }
> 
> This will lead to memleaks for users that use avcodec_close(avctx) +
> av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
> encoders do this). Notice that avcodec_free_context() violates the
> documentation of AVCodecContext.extradata (documented to not be freed
> for decoders) and AVCodecContext.subtitle_header and
> AVCodecContext.rc_override (documented to not be freed by lavc for
> encoders), so there is a reason for using it instead of
> avcodec_free_context() (even when not reusing the context).

That's an absolute mess of a situation. av_free(avctx) should not be an 
allowed or supported scenario when avcodec_free_context() exists. And 
why is the latter violating its own documentation?

> 
> - Andreas
> _______________________________________________
> 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".
Andreas Rheinhardt March 20, 2022, 11:34 p.m. UTC | #3
James Almer:
> 
> 
> On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>> James Almer:
>>> It can uninitialize fields that may still be used after the context
>>> was closed,
>>> so do it instead in avcodec_free_context().
>>>
>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>> ---
>>>   libavcodec/avcodec.c | 1 -
>>>   libavcodec/options.c | 2 +-
>>>   2 files changed, 1 insertion(+), 2 deletions(-)
>>>
>>> diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>> index 38bdaad4fa..122d09b63a 100644
>>> --- a/libavcodec/avcodec.c
>>> +++ b/libavcodec/avcodec.c
>>> @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>>         if (avctx->priv_data && avctx->codec &&
>>> avctx->codec->priv_class)
>>>           av_opt_free(avctx->priv_data);
>>> -    av_opt_free(avctx);
>>>       av_freep(&avctx->priv_data);
>>>       if (av_codec_is_encoder(avctx->codec)) {
>>>           av_freep(&avctx->extradata);
>>> diff --git a/libavcodec/options.c b/libavcodec/options.c
>>> index 33f11480a7..91335415c1 100644
>>> --- a/libavcodec/options.c
>>> +++ b/libavcodec/options.c
>>> @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>>>       av_freep(&avctx->intra_matrix);
>>>       av_freep(&avctx->inter_matrix);
>>>       av_freep(&avctx->rc_override);
>>> -    av_channel_layout_uninit(&avctx->ch_layout);
>>> +    av_opt_free(avctx);
>>>         av_freep(pavctx);
>>>   }
>>
>> This will lead to memleaks for users that use avcodec_close(avctx) +
>> av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>> encoders do this). Notice that avcodec_free_context() violates the
>> documentation of AVCodecContext.extradata (documented to not be freed
>> for decoders) and AVCodecContext.subtitle_header and
>> AVCodecContext.rc_override (documented to not be freed by lavc for
>> encoders), so there is a reason for using it instead of
>> avcodec_free_context() (even when not reusing the context).
> 
> That's an absolute mess of a situation. av_free(avctx) should not be an
> allowed or supported scenario when avcodec_free_context() exists. And
> why is the latter violating its own documentation?
> 

It is not violating its own documentation, but the documentation of the
relevant AVCodecContext fields. IIRC Anton wanted a function that just
frees the whole context, even if this meant that fields which are
documented as being owned by the user are freed. Even documenting the
current state of affairs in avcodec.h doesn't change the fact that there
is a valid reason to use avcodec_close()+av_free(), so we can't pretend
it doesn't happen.

- Andreas
James Almer March 20, 2022, 11:41 p.m. UTC | #4
On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
> James Almer:
>>
>>
>> On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>> James Almer:
>>>> It can uninitialize fields that may still be used after the context
>>>> was closed,
>>>> so do it instead in avcodec_free_context().
>>>>
>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>> ---
>>>>    libavcodec/avcodec.c | 1 -
>>>>    libavcodec/options.c | 2 +-
>>>>    2 files changed, 1 insertion(+), 2 deletions(-)
>>>>
>>>> diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>> index 38bdaad4fa..122d09b63a 100644
>>>> --- a/libavcodec/avcodec.c
>>>> +++ b/libavcodec/avcodec.c
>>>> @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>>>          if (avctx->priv_data && avctx->codec &&
>>>> avctx->codec->priv_class)
>>>>            av_opt_free(avctx->priv_data);
>>>> -    av_opt_free(avctx);
>>>>        av_freep(&avctx->priv_data);
>>>>        if (av_codec_is_encoder(avctx->codec)) {
>>>>            av_freep(&avctx->extradata);
>>>> diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>> index 33f11480a7..91335415c1 100644
>>>> --- a/libavcodec/options.c
>>>> +++ b/libavcodec/options.c
>>>> @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>>>>        av_freep(&avctx->intra_matrix);
>>>>        av_freep(&avctx->inter_matrix);
>>>>        av_freep(&avctx->rc_override);
>>>> -    av_channel_layout_uninit(&avctx->ch_layout);
>>>> +    av_opt_free(avctx);
>>>>          av_freep(pavctx);
>>>>    }
>>>
>>> This will lead to memleaks for users that use avcodec_close(avctx) +
>>> av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>> encoders do this). Notice that avcodec_free_context() violates the
>>> documentation of AVCodecContext.extradata (documented to not be freed
>>> for decoders) and AVCodecContext.subtitle_header and
>>> AVCodecContext.rc_override (documented to not be freed by lavc for
>>> encoders), so there is a reason for using it instead of
>>> avcodec_free_context() (even when not reusing the context).
>>
>> That's an absolute mess of a situation. av_free(avctx) should not be an
>> allowed or supported scenario when avcodec_free_context() exists. And
>> why is the latter violating its own documentation?
>>
> 
> It is not violating its own documentation, but the documentation of the
> relevant AVCodecContext fields. IIRC Anton wanted a function that just
> frees the whole context, even if this meant that fields which are
> documented as being owned by the user are freed. Even documenting the
> current state of affairs in avcodec.h doesn't change the fact that there
> is a valid reason to use avcodec_close()+av_free(), so we can't pretend
> it doesn't happen.
> 
> - Andreas

Ok, do i add a codecpar copy like i suggested in 
http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, then? 
It works, but it feels really weird doing that in what's the cleanup 
portion of the function.
Alternatively, add the dance from 
https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/ 
which should have the same effect and never fail, unlike param copy.
Marton Balint March 21, 2022, 12:04 a.m. UTC | #5
On Sun, 20 Mar 2022, James Almer wrote:

> On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>  James Almer:
>>> 
>>>
>>>  On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>  James Almer:
>>>>>  It can uninitialize fields that may still be used after the context
>>>>>  was closed,
>>>>>  so do it instead in avcodec_free_context().
>>>>>
>>>>>  Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>  ---
>>>>>     libavcodec/avcodec.c | 1 -
>>>>>     libavcodec/options.c | 2 +-
>>>>>     2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>
>>>>>  diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>  index 38bdaad4fa..122d09b63a 100644
>>>>>  --- a/libavcodec/avcodec.c
>>>>>  +++ b/libavcodec/avcodec.c
>>>>>  @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>>>>          if (avctx->priv_data && avctx->codec &&
>>>>>  avctx->codec->priv_class)
>>>>>            av_opt_free(avctx->priv_data);
>>>>>  -    av_opt_free(avctx);
>>>>>         av_freep(&avctx->priv_data);
>>>>>         if (av_codec_is_encoder(avctx->codec)) {
>>>>>             av_freep(&avctx->extradata);
>>>>>  diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>  index 33f11480a7..91335415c1 100644
>>>>>  --- a/libavcodec/options.c
>>>>>  +++ b/libavcodec/options.c
>>>>>  @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>>>>>         av_freep(&avctx->intra_matrix);
>>>>>         av_freep(&avctx->inter_matrix);
>>>>>         av_freep(&avctx->rc_override);
>>>>>  -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>  +    av_opt_free(avctx);
>>>>>           av_freep(pavctx);
>>>>>     }
>>>>
>>>>  This will lead to memleaks for users that use avcodec_close(avctx) +
>>>>  av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>>  encoders do this). Notice that avcodec_free_context() violates the
>>>>  documentation of AVCodecContext.extradata (documented to not be freed
>>>>  for decoders) and AVCodecContext.subtitle_header and
>>>>  AVCodecContext.rc_override (documented to not be freed by lavc for
>>>>  encoders), so there is a reason for using it instead of
>>>>  avcodec_free_context() (even when not reusing the context).
>>>
>>>  That's an absolute mess of a situation. av_free(avctx) should not be an
>>>  allowed or supported scenario when avcodec_free_context() exists. And
>>>  why is the latter violating its own documentation?
>>>
>>
>>  It is not violating its own documentation, but the documentation of the
>>  relevant AVCodecContext fields. IIRC Anton wanted a function that just
>>  frees the whole context, even if this meant that fields which are
>>  documented as being owned by the user are freed. Even documenting the
>>  current state of affairs in avcodec.h doesn't change the fact that there
>>  is a valid reason to use avcodec_close()+av_free(), so we can't pretend
>>  it doesn't happen.
>>
>>  - Andreas
>
> Ok, do i add a codecpar copy like i suggested in 
> http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, then? It 
> works, but it feels really weird doing that in what's the cleanup portion of 
> the function.
> Alternatively, add the dance from 
> https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/ 
> which should have the same effect and never fail, unlike param copy.

The latter would also leak memory on avcodec_close()+av_freep().

Regards,
Marton
Marton Balint March 21, 2022, 12:05 a.m. UTC | #6
On Mon, 21 Mar 2022, Marton Balint wrote:

>
>
> On Sun, 20 Mar 2022, James Almer wrote:
>
>>  On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>>   James Almer:
>>>> 
>>>>
>>>>   On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>>   James Almer:
>>>>>>   It can uninitialize fields that may still be used after the context
>>>>>>   was closed,
>>>>>>   so do it instead in avcodec_free_context().
>>>>>>
>>>>>>   Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>>   ---
>>>>>>      libavcodec/avcodec.c | 1 -
>>>>>>      libavcodec/options.c | 2 +-
>>>>>>      2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>>
>>>>>>   diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>>   index 38bdaad4fa..122d09b63a 100644
>>>>>>   --- a/libavcodec/avcodec.c
>>>>>>   +++ b/libavcodec/avcodec.c
>>>>>>   @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>>>>>           if (avctx->priv_data && avctx->codec &&
>>>>>>   avctx->codec->priv_class)
>>>>>>             av_opt_free(avctx->priv_data);
>>>>>>   -    av_opt_free(avctx);
>>>>>>          av_freep(&avctx->priv_data);
>>>>>>          if (av_codec_is_encoder(avctx->codec)) {
>>>>>>              av_freep(&avctx->extradata);
>>>>>>   diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>>   index 33f11480a7..91335415c1 100644
>>>>>>   --- a/libavcodec/options.c
>>>>>>   +++ b/libavcodec/options.c
>>>>>>   @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext
>>>>>>   **pavctx)
>>>>>>          av_freep(&avctx->intra_matrix);
>>>>>>          av_freep(&avctx->inter_matrix);
>>>>>>          av_freep(&avctx->rc_override);
>>>>>>   -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>>   +    av_opt_free(avctx);
>>>>>>            av_freep(pavctx);
>>>>>>      }
>>>>>
>>>>>   This will lead to memleaks for users that use avcodec_close(avctx) +
>>>>>   av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>>>   encoders do this). Notice that avcodec_free_context() violates the
>>>>>   documentation of AVCodecContext.extradata (documented to not be freed
>>>>>   for decoders) and AVCodecContext.subtitle_header and
>>>>>   AVCodecContext.rc_override (documented to not be freed by lavc for
>>>>>   encoders), so there is a reason for using it instead of
>>>>>   avcodec_free_context() (even when not reusing the context).
>>>>
>>>>   That's an absolute mess of a situation. av_free(avctx) should not be an
>>>>   allowed or supported scenario when avcodec_free_context() exists. And
>>>>   why is the latter violating its own documentation?
>>>> 
>>>
>>>   It is not violating its own documentation, but the documentation of the
>>>   relevant AVCodecContext fields. IIRC Anton wanted a function that just
>>>   frees the whole context, even if this meant that fields which are
>>>   documented as being owned by the user are freed. Even documenting the
>>>   current state of affairs in avcodec.h doesn't change the fact that there
>>>   is a valid reason to use avcodec_close()+av_free(), so we can't pretend
>>>   it doesn't happen.
>>>
>>>   - Andreas
>>
>>  Ok, do i add a codecpar copy like i suggested in
>>  http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, then? It
>>  works, but it feels really weird doing that in what's the cleanup portion
>>  of the function.
>>  Alternatively, add the dance from
>>  https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/
>>  which should have the same effect and never fail, unlike param copy.
>
> The latter would also leak memory on avcodec_close()+av_freep().

Sorry, I meant the first one.
James Almer March 21, 2022, 12:15 a.m. UTC | #7
On 3/20/2022 9:05 PM, Marton Balint wrote:
> 
> 
> On Mon, 21 Mar 2022, Marton Balint wrote:
> 
>>
>>
>> On Sun, 20 Mar 2022, James Almer wrote:
>>
>>>  On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>>>   James Almer:
>>>>>
>>>>>
>>>>>   On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>>>   James Almer:
>>>>>>>   It can uninitialize fields that may still be used after the 
>>>>>>> context
>>>>>>>   was closed,
>>>>>>>   so do it instead in avcodec_free_context().
>>>>>>>
>>>>>>>   Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>>>   ---
>>>>>>>      libavcodec/avcodec.c | 1 -
>>>>>>>      libavcodec/options.c | 2 +-
>>>>>>>      2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>>>
>>>>>>>   diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>>>   index 38bdaad4fa..122d09b63a 100644
>>>>>>>   --- a/libavcodec/avcodec.c
>>>>>>>   +++ b/libavcodec/avcodec.c
>>>>>>>   @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext 
>>>>>>> *avctx)
>>>>>>>           if (avctx->priv_data && avctx->codec &&
>>>>>>>   avctx->codec->priv_class)
>>>>>>>             av_opt_free(avctx->priv_data);
>>>>>>>   -    av_opt_free(avctx);
>>>>>>>          av_freep(&avctx->priv_data);
>>>>>>>          if (av_codec_is_encoder(avctx->codec)) {
>>>>>>>              av_freep(&avctx->extradata);
>>>>>>>   diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>>>   index 33f11480a7..91335415c1 100644
>>>>>>>   --- a/libavcodec/options.c
>>>>>>>   +++ b/libavcodec/options.c
>>>>>>>   @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext
>>>>>>>   **pavctx)
>>>>>>>          av_freep(&avctx->intra_matrix);
>>>>>>>          av_freep(&avctx->inter_matrix);
>>>>>>>          av_freep(&avctx->rc_override);
>>>>>>>   -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>>>   +    av_opt_free(avctx);
>>>>>>>            av_freep(pavctx);
>>>>>>>      }
>>>>>>
>>>>>>   This will lead to memleaks for users that use 
>>>>>> avcodec_close(avctx) +
>>>>>>   av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>>>>   encoders do this). Notice that avcodec_free_context() violates the
>>>>>>   documentation of AVCodecContext.extradata (documented to not be 
>>>>>> freed
>>>>>>   for decoders) and AVCodecContext.subtitle_header and
>>>>>>   AVCodecContext.rc_override (documented to not be freed by lavc for
>>>>>>   encoders), so there is a reason for using it instead of
>>>>>>   avcodec_free_context() (even when not reusing the context).
>>>>>
>>>>>   That's an absolute mess of a situation. av_free(avctx) should not 
>>>>> be an
>>>>>   allowed or supported scenario when avcodec_free_context() exists. 
>>>>> And
>>>>>   why is the latter violating its own documentation?
>>>>>
>>>>
>>>>   It is not violating its own documentation, but the documentation 
>>>> of the
>>>>   relevant AVCodecContext fields. IIRC Anton wanted a function that 
>>>> just
>>>>   frees the whole context, even if this meant that fields which are
>>>>   documented as being owned by the user are freed. Even documenting the
>>>>   current state of affairs in avcodec.h doesn't change the fact that 
>>>> there
>>>>   is a valid reason to use avcodec_close()+av_free(), so we can't 
>>>> pretend
>>>>   it doesn't happen.
>>>>
>>>>   - Andreas
>>>
>>>  Ok, do i add a codecpar copy like i suggested in
>>>  http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, 
>>> then? It
>>>  works, but it feels really weird doing that in what's the cleanup 
>>> portion
>>>  of the function.
>>>  Alternatively, add the dance from
>>>  https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/ 
>>>
>>>  which should have the same effect and never fail, unlike param copy.
>>
>> The latter would also leak memory on avcodec_close()+av_freep().
> 
> Sorry, I meant the first one.

avformat_free_context() calls avcodec_free_context() on the relevant 
AVCodecContexts.

> _______________________________________________
> 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".
Andreas Rheinhardt March 21, 2022, 12:16 a.m. UTC | #8
Marton Balint:
> 
> 
> On Mon, 21 Mar 2022, Marton Balint wrote:
> 
>>
>>
>> On Sun, 20 Mar 2022, James Almer wrote:
>>
>>>  On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>>>   James Almer:
>>>>>
>>>>>
>>>>>   On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>>>   James Almer:
>>>>>>>   It can uninitialize fields that may still be used after the
>>>>>>> context
>>>>>>>   was closed,
>>>>>>>   so do it instead in avcodec_free_context().
>>>>>>>
>>>>>>>   Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>>>   ---
>>>>>>>      libavcodec/avcodec.c | 1 -
>>>>>>>      libavcodec/options.c | 2 +-
>>>>>>>      2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>>>
>>>>>>>   diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>>>   index 38bdaad4fa..122d09b63a 100644
>>>>>>>   --- a/libavcodec/avcodec.c
>>>>>>>   +++ b/libavcodec/avcodec.c
>>>>>>>   @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext
>>>>>>> *avctx)
>>>>>>>           if (avctx->priv_data && avctx->codec &&
>>>>>>>   avctx->codec->priv_class)
>>>>>>>             av_opt_free(avctx->priv_data);
>>>>>>>   -    av_opt_free(avctx);
>>>>>>>          av_freep(&avctx->priv_data);
>>>>>>>          if (av_codec_is_encoder(avctx->codec)) {
>>>>>>>              av_freep(&avctx->extradata);
>>>>>>>   diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>>>   index 33f11480a7..91335415c1 100644
>>>>>>>   --- a/libavcodec/options.c
>>>>>>>   +++ b/libavcodec/options.c
>>>>>>>   @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext
>>>>>>>   **pavctx)
>>>>>>>          av_freep(&avctx->intra_matrix);
>>>>>>>          av_freep(&avctx->inter_matrix);
>>>>>>>          av_freep(&avctx->rc_override);
>>>>>>>   -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>>>   +    av_opt_free(avctx);
>>>>>>>            av_freep(pavctx);
>>>>>>>      }
>>>>>>
>>>>>>   This will lead to memleaks for users that use
>>>>>> avcodec_close(avctx) +
>>>>>>   av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>>>>   encoders do this). Notice that avcodec_free_context() violates the
>>>>>>   documentation of AVCodecContext.extradata (documented to not be
>>>>>> freed
>>>>>>   for decoders) and AVCodecContext.subtitle_header and
>>>>>>   AVCodecContext.rc_override (documented to not be freed by lavc for
>>>>>>   encoders), so there is a reason for using it instead of
>>>>>>   avcodec_free_context() (even when not reusing the context).
>>>>>
>>>>>   That's an absolute mess of a situation. av_free(avctx) should not
>>>>> be an
>>>>>   allowed or supported scenario when avcodec_free_context() exists.
>>>>> And
>>>>>   why is the latter violating its own documentation?
>>>>>
>>>>
>>>>   It is not violating its own documentation, but the documentation
>>>> of the
>>>>   relevant AVCodecContext fields. IIRC Anton wanted a function that
>>>> just
>>>>   frees the whole context, even if this meant that fields which are
>>>>   documented as being owned by the user are freed. Even documenting the
>>>>   current state of affairs in avcodec.h doesn't change the fact that
>>>> there
>>>>   is a valid reason to use avcodec_close()+av_free(), so we can't
>>>> pretend
>>>>   it doesn't happen.
>>>>
>>>>   - Andreas
>>>
>>>  Ok, do i add a codecpar copy like i suggested in
>>>  http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html,
>>> then? It
>>>  works, but it feels really weird doing that in what's the cleanup
>>> portion
>>>  of the function.
>>>  Alternatively, add the dance from
>>>  https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/
>>>
>>>  which should have the same effect and never fail, unlike param copy.
>>
>> The latter would also leak memory on avcodec_close()+av_freep().
> 
> Sorry, I meant the first one.

This AVCodecContext is ultimately freed with avcodec_free_context(), so
there would be no memleak.

- Andreas
Marton Balint March 21, 2022, 12:21 a.m. UTC | #9
On Sun, 20 Mar 2022, James Almer wrote:

> On 3/20/2022 9:05 PM, Marton Balint wrote:
>>
>>
>>  On Mon, 21 Mar 2022, Marton Balint wrote:
>> 
>>> 
>>>
>>>  On Sun, 20 Mar 2022, James Almer wrote:
>>>
>>>>   On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>>>>    James Almer:
>>>>>> 
>>>>>>
>>>>>>    On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>>>>    James Almer:
>>>>>>>>    It can uninitialize fields that may still be used after the
>>>>>>>>  context
>>>>>>>>    was closed,
>>>>>>>>    so do it instead in avcodec_free_context().
>>>>>>>>
>>>>>>>>    Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>>>>    ---
>>>>>>>>       libavcodec/avcodec.c | 1 -
>>>>>>>>       libavcodec/options.c | 2 +-
>>>>>>>>       2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>>>>
>>>>>>>>    diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>>>>    index 38bdaad4fa..122d09b63a 100644
>>>>>>>>    --- a/libavcodec/avcodec.c
>>>>>>>>    +++ b/libavcodec/avcodec.c
>>>>>>>>    @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext
>>>>>>>>  *avctx)
>>>>>>>>            if (avctx->priv_data && avctx->codec &&
>>>>>>>>    avctx->codec->priv_class)
>>>>>>>>              av_opt_free(avctx->priv_data);
>>>>>>>>    -    av_opt_free(avctx);
>>>>>>>>           av_freep(&avctx->priv_data);
>>>>>>>>           if (av_codec_is_encoder(avctx->codec)) {
>>>>>>>>               av_freep(&avctx->extradata);
>>>>>>>>    diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>>>>    index 33f11480a7..91335415c1 100644
>>>>>>>>    --- a/libavcodec/options.c
>>>>>>>>    +++ b/libavcodec/options.c
>>>>>>>>    @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext
>>>>>>>>    **pavctx)
>>>>>>>>           av_freep(&avctx->intra_matrix);
>>>>>>>>           av_freep(&avctx->inter_matrix);
>>>>>>>>           av_freep(&avctx->rc_override);
>>>>>>>>    -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>>>>    +    av_opt_free(avctx);
>>>>>>>>             av_freep(pavctx);
>>>>>>>>       }
>>>>>>>
>>>>>>>    This will lead to memleaks for users that use avcodec_close(avctx)
>>>>>>>  +
>>>>>>>    av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>>>>>    encoders do this). Notice that avcodec_free_context() violates the
>>>>>>>    documentation of AVCodecContext.extradata (documented to not be
>>>>>>>  freed
>>>>>>>    for decoders) and AVCodecContext.subtitle_header and
>>>>>>>    AVCodecContext.rc_override (documented to not be freed by lavc for
>>>>>>>    encoders), so there is a reason for using it instead of
>>>>>>>    avcodec_free_context() (even when not reusing the context).
>>>>>>
>>>>>>    That's an absolute mess of a situation. av_free(avctx) should not be
>>>>>>  an
>>>>>>    allowed or supported scenario when avcodec_free_context() exists.
>>>>>>  And
>>>>>>    why is the latter violating its own documentation?
>>>>>> 
>>>>>
>>>>>    It is not violating its own documentation, but the documentation of
>>>>>  the
>>>>>    relevant AVCodecContext fields. IIRC Anton wanted a function that
>>>>>  just
>>>>>    frees the whole context, even if this meant that fields which are
>>>>>    documented as being owned by the user are freed. Even documenting the
>>>>>    current state of affairs in avcodec.h doesn't change the fact that
>>>>>  there
>>>>>    is a valid reason to use avcodec_close()+av_free(), so we can't
>>>>>  pretend
>>>>>    it doesn't happen.
>>>>>
>>>>>    - Andreas
>>>>
>>>>   Ok, do i add a codecpar copy like i suggested in
>>>>   http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, then?
>>>>  It
>>>>   works, but it feels really weird doing that in what's the cleanup
>>>>  portion
>>>>   of the function.
>>>>   Alternatively, add the dance from
>>>>   https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/ 
>>>>
>>>>   which should have the same effect and never fail, unlike param copy.
>>>
>>>  The latter would also leak memory on avcodec_close()+av_freep().
>>
>>  Sorry, I meant the first one.
>
> avformat_free_context() calls avcodec_free_context() on the relevant 
> AVCodecContexts.

Sorry, I meant the second case, if you do the dance with 
AVCodecContext->ch_layout in avcodec_close() then 
avcodec_close()+av_freep(avctx) will leak ch_layout.map on custom layouts.

I hope I finally make sense :)

Regards,
Marton
James Almer March 21, 2022, 12:23 a.m. UTC | #10
On 3/20/2022 9:21 PM, Marton Balint wrote:
> 
> 
> On Sun, 20 Mar 2022, James Almer wrote:
> 
>> On 3/20/2022 9:05 PM, Marton Balint wrote:
>>>
>>>
>>>  On Mon, 21 Mar 2022, Marton Balint wrote:
>>>
>>>>
>>>>
>>>>  On Sun, 20 Mar 2022, James Almer wrote:
>>>>
>>>>>   On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>>>>>    James Almer:
>>>>>>>
>>>>>>>
>>>>>>>    On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>>>>>    James Almer:
>>>>>>>>>    It can uninitialize fields that may still be used after the
>>>>>>>>>  context
>>>>>>>>>    was closed,
>>>>>>>>>    so do it instead in avcodec_free_context().
>>>>>>>>>
>>>>>>>>>    Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>>>>>    ---
>>>>>>>>>       libavcodec/avcodec.c | 1 -
>>>>>>>>>       libavcodec/options.c | 2 +-
>>>>>>>>>       2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>>>>>
>>>>>>>>>    diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>>>>>    index 38bdaad4fa..122d09b63a 100644
>>>>>>>>>    --- a/libavcodec/avcodec.c
>>>>>>>>>    +++ b/libavcodec/avcodec.c
>>>>>>>>>    @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext
>>>>>>>>>  *avctx)
>>>>>>>>>            if (avctx->priv_data && avctx->codec &&
>>>>>>>>>    avctx->codec->priv_class)
>>>>>>>>>              av_opt_free(avctx->priv_data);
>>>>>>>>>    -    av_opt_free(avctx);
>>>>>>>>>           av_freep(&avctx->priv_data);
>>>>>>>>>           if (av_codec_is_encoder(avctx->codec)) {
>>>>>>>>>               av_freep(&avctx->extradata);
>>>>>>>>>    diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>>>>>    index 33f11480a7..91335415c1 100644
>>>>>>>>>    --- a/libavcodec/options.c
>>>>>>>>>    +++ b/libavcodec/options.c
>>>>>>>>>    @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext
>>>>>>>>>    **pavctx)
>>>>>>>>>           av_freep(&avctx->intra_matrix);
>>>>>>>>>           av_freep(&avctx->inter_matrix);
>>>>>>>>>           av_freep(&avctx->rc_override);
>>>>>>>>>    -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>>>>>    +    av_opt_free(avctx);
>>>>>>>>>             av_freep(pavctx);
>>>>>>>>>       }
>>>>>>>>
>>>>>>>>    This will lead to memleaks for users that use 
>>>>>>>> avcodec_close(avctx)
>>>>>>>>  +
>>>>>>>>    av_free(avctx) to free an AVCodecContext (e.g. our 
>>>>>>>> frame-threaded
>>>>>>>>    encoders do this). Notice that avcodec_free_context() 
>>>>>>>> violates the
>>>>>>>>    documentation of AVCodecContext.extradata (documented to not be
>>>>>>>>  freed
>>>>>>>>    for decoders) and AVCodecContext.subtitle_header and
>>>>>>>>    AVCodecContext.rc_override (documented to not be freed by 
>>>>>>>> lavc for
>>>>>>>>    encoders), so there is a reason for using it instead of
>>>>>>>>    avcodec_free_context() (even when not reusing the context).
>>>>>>>
>>>>>>>    That's an absolute mess of a situation. av_free(avctx) should 
>>>>>>> not be
>>>>>>>  an
>>>>>>>    allowed or supported scenario when avcodec_free_context() exists.
>>>>>>>  And
>>>>>>>    why is the latter violating its own documentation?
>>>>>>>
>>>>>>
>>>>>>    It is not violating its own documentation, but the 
>>>>>> documentation of
>>>>>>  the
>>>>>>    relevant AVCodecContext fields. IIRC Anton wanted a function that
>>>>>>  just
>>>>>>    frees the whole context, even if this meant that fields which are
>>>>>>    documented as being owned by the user are freed. Even 
>>>>>> documenting the
>>>>>>    current state of affairs in avcodec.h doesn't change the fact that
>>>>>>  there
>>>>>>    is a valid reason to use avcodec_close()+av_free(), so we can't
>>>>>>  pretend
>>>>>>    it doesn't happen.
>>>>>>
>>>>>>    - Andreas
>>>>>
>>>>>   Ok, do i add a codecpar copy like i suggested in
>>>>>   http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, 
>>>>> then?
>>>>>  It
>>>>>   works, but it feels really weird doing that in what's the cleanup
>>>>>  portion
>>>>>   of the function.
>>>>>   Alternatively, add the dance from
>>>>>   https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/ 
>>>>>
>>>>>   which should have the same effect and never fail, unlike param copy.
>>>>
>>>>  The latter would also leak memory on avcodec_close()+av_freep().
>>>
>>>  Sorry, I meant the first one.
>>
>> avformat_free_context() calls avcodec_free_context() on the relevant 
>> AVCodecContexts.
> 
> Sorry, I meant the second case, if you do the dance with 
> AVCodecContext->ch_layout in avcodec_close() then 
> avcodec_close()+av_freep(avctx) will leak ch_layout.map on custom layouts.
> 
> I hope I finally make sense :)

Oh, i meant to say doing that dance in lavf, in the same place the first 
option called param copy, instead of said param copy call. Sorry i 
wasn't explicit.

> 
> Regards,
> Marton
> _______________________________________________
> 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".
Andreas Rheinhardt March 21, 2022, 12:46 a.m. UTC | #11
James Almer:
> On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>> James Almer:
>>>
>>>
>>> On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>> James Almer:
>>>>> It can uninitialize fields that may still be used after the context
>>>>> was closed,
>>>>> so do it instead in avcodec_free_context().
>>>>>
>>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>>> ---
>>>>>    libavcodec/avcodec.c | 1 -
>>>>>    libavcodec/options.c | 2 +-
>>>>>    2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>> index 38bdaad4fa..122d09b63a 100644
>>>>> --- a/libavcodec/avcodec.c
>>>>> +++ b/libavcodec/avcodec.c
>>>>> @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>>>>          if (avctx->priv_data && avctx->codec &&
>>>>> avctx->codec->priv_class)
>>>>>            av_opt_free(avctx->priv_data);
>>>>> -    av_opt_free(avctx);
>>>>>        av_freep(&avctx->priv_data);
>>>>>        if (av_codec_is_encoder(avctx->codec)) {
>>>>>            av_freep(&avctx->extradata);
>>>>> diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>> index 33f11480a7..91335415c1 100644
>>>>> --- a/libavcodec/options.c
>>>>> +++ b/libavcodec/options.c
>>>>> @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>>>>>        av_freep(&avctx->intra_matrix);
>>>>>        av_freep(&avctx->inter_matrix);
>>>>>        av_freep(&avctx->rc_override);
>>>>> -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>> +    av_opt_free(avctx);
>>>>>          av_freep(pavctx);
>>>>>    }
>>>>
>>>> This will lead to memleaks for users that use avcodec_close(avctx) +
>>>> av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>> encoders do this). Notice that avcodec_free_context() violates the
>>>> documentation of AVCodecContext.extradata (documented to not be freed
>>>> for decoders) and AVCodecContext.subtitle_header and
>>>> AVCodecContext.rc_override (documented to not be freed by lavc for
>>>> encoders), so there is a reason for using it instead of
>>>> avcodec_free_context() (even when not reusing the context).
>>>
>>> That's an absolute mess of a situation. av_free(avctx) should not be an
>>> allowed or supported scenario when avcodec_free_context() exists. And
>>> why is the latter violating its own documentation?
>>>
>>
>> It is not violating its own documentation, but the documentation of the
>> relevant AVCodecContext fields. IIRC Anton wanted a function that just
>> frees the whole context, even if this meant that fields which are
>> documented as being owned by the user are freed. Even documenting the
>> current state of affairs in avcodec.h doesn't change the fact that there
>> is a valid reason to use avcodec_close()+av_free(), so we can't pretend
>> it doesn't happen.
>>
>> - Andreas
> 
> Ok, do i add a codecpar copy like i suggested in
> http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, then?
> It works, but it feels really weird doing that in what's the cleanup
> portion of the function.
> Alternatively, add the dance from
> https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/
> which should have the same effect and never fail, unlike param copy.

The other place where the internal context is reinitialized (in
read_frame_internal()) also calls avcodec_parameters_to_context(); yet
this code is reached when the demuxer updates the AVCodecParameters and
sets need_context_update accordingly whereas the other call to
avcodec_close() happens when no such updates were triggered. So I can
live with both.
(Is it actually intended for AVChannelLayout to be movable? If so, it
should be documented.)

- Andreas
James Almer March 21, 2022, 11:17 a.m. UTC | #12
On 3/20/2022 9:46 PM, Andreas Rheinhardt wrote:
> James Almer:
>> On 3/20/2022 8:34 PM, Andreas Rheinhardt wrote:
>>> James Almer:
>>>>
>>>>
>>>> On 3/20/2022 8:26 PM, Andreas Rheinhardt wrote:
>>>>> James Almer:
>>>>>> It can uninitialize fields that may still be used after the context
>>>>>> was closed,
>>>>>> so do it instead in avcodec_free_context().
>>>>>>
>>>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>> ---
>>>>>>     libavcodec/avcodec.c | 1 -
>>>>>>     libavcodec/options.c | 2 +-
>>>>>>     2 files changed, 1 insertion(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
>>>>>> index 38bdaad4fa..122d09b63a 100644
>>>>>> --- a/libavcodec/avcodec.c
>>>>>> +++ b/libavcodec/avcodec.c
>>>>>> @@ -524,7 +524,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
>>>>>>           if (avctx->priv_data && avctx->codec &&
>>>>>> avctx->codec->priv_class)
>>>>>>             av_opt_free(avctx->priv_data);
>>>>>> -    av_opt_free(avctx);
>>>>>>         av_freep(&avctx->priv_data);
>>>>>>         if (av_codec_is_encoder(avctx->codec)) {
>>>>>>             av_freep(&avctx->extradata);
>>>>>> diff --git a/libavcodec/options.c b/libavcodec/options.c
>>>>>> index 33f11480a7..91335415c1 100644
>>>>>> --- a/libavcodec/options.c
>>>>>> +++ b/libavcodec/options.c
>>>>>> @@ -172,7 +172,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
>>>>>>         av_freep(&avctx->intra_matrix);
>>>>>>         av_freep(&avctx->inter_matrix);
>>>>>>         av_freep(&avctx->rc_override);
>>>>>> -    av_channel_layout_uninit(&avctx->ch_layout);
>>>>>> +    av_opt_free(avctx);
>>>>>>           av_freep(pavctx);
>>>>>>     }
>>>>>
>>>>> This will lead to memleaks for users that use avcodec_close(avctx) +
>>>>> av_free(avctx) to free an AVCodecContext (e.g. our frame-threaded
>>>>> encoders do this). Notice that avcodec_free_context() violates the
>>>>> documentation of AVCodecContext.extradata (documented to not be freed
>>>>> for decoders) and AVCodecContext.subtitle_header and
>>>>> AVCodecContext.rc_override (documented to not be freed by lavc for
>>>>> encoders), so there is a reason for using it instead of
>>>>> avcodec_free_context() (even when not reusing the context).
>>>>
>>>> That's an absolute mess of a situation. av_free(avctx) should not be an
>>>> allowed or supported scenario when avcodec_free_context() exists. And
>>>> why is the latter violating its own documentation?
>>>>
>>>
>>> It is not violating its own documentation, but the documentation of the
>>> relevant AVCodecContext fields. IIRC Anton wanted a function that just
>>> frees the whole context, even if this meant that fields which are
>>> documented as being owned by the user are freed. Even documenting the
>>> current state of affairs in avcodec.h doesn't change the fact that there
>>> is a valid reason to use avcodec_close()+av_free(), so we can't pretend
>>> it doesn't happen.
>>>
>>> - Andreas
>>
>> Ok, do i add a codecpar copy like i suggested in
>> http://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294312.html, then?
>> It works, but it feels really weird doing that in what's the cleanup
>> portion of the function.
>> Alternatively, add the dance from
>> https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220319030407.45503-1-jamrial@gmail.com/
>> which should have the same effect and never fail, unlike param copy.
> 
> The other place where the internal context is reinitialized (in
> read_frame_internal()) also calls avcodec_parameters_to_context(); yet
> this code is reached when the demuxer updates the AVCodecParameters and
> sets need_context_update accordingly whereas the other call to
> avcodec_close() happens when no such updates were triggered. So I can
> live with both.

I'll push the codecpar copy one since it's cleaner looking, then, and 
add a comment about why it's there so we can remove it once 
avcodec_close() stops freeing ch_layout, if it happens before the former 
is removed.

> (Is it actually intended for AVChannelLayout to be movable? If so, it
> should be documented.)
> 
> - Andreas
> _______________________________________________
> 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/libavcodec/avcodec.c b/libavcodec/avcodec.c
index 38bdaad4fa..122d09b63a 100644
--- a/libavcodec/avcodec.c
+++ b/libavcodec/avcodec.c
@@ -524,7 +524,6 @@  av_cold int avcodec_close(AVCodecContext *avctx)
 
     if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
         av_opt_free(avctx->priv_data);
-    av_opt_free(avctx);
     av_freep(&avctx->priv_data);
     if (av_codec_is_encoder(avctx->codec)) {
         av_freep(&avctx->extradata);
diff --git a/libavcodec/options.c b/libavcodec/options.c
index 33f11480a7..91335415c1 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -172,7 +172,7 @@  void avcodec_free_context(AVCodecContext **pavctx)
     av_freep(&avctx->intra_matrix);
     av_freep(&avctx->inter_matrix);
     av_freep(&avctx->rc_override);
-    av_channel_layout_uninit(&avctx->ch_layout);
+    av_opt_free(avctx);
 
     av_freep(pavctx);
 }