<div><br></div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">---------- Пересылаемое сообщение ---------<br>От: <strong class="gmail_sendername" dir="auto">Yurii Monakov</strong> <span dir="auto"><<a href="mailto:monakov.y@gmail.com">monakov.y@gmail.com</a>></span><br>Дата: Чт, 2 марта 2023 г. в 15:47<br>Тема: Re: [Libav-user] How to free an AVBuffer?<br>Кому: Wladislav Artsimovich <ffmpeg@frost.kiwi><br></div><br><br><div dir="ltr"><div>Vlad,</div><div><br></div><div>What is the lifetime of your frame? If it is persistent across calls then you allocate</div><div>new side data in every call and ffmpeg simply grows its side data list.</div><div><br></div><div>You can use av_frame_new_side_data, copy data to it, send a frame to codec and</div><div>then av_frame_remove_side_data. There is no need to allocate a separate buffer,</div><div>av_frame_new_side_data does this internally.<br></div><div><br></div><div>If you wish to save some allocations, you need to check if side data of a given</div><div>type is already present. If message.Length changes from call to call, you have to</div><div>av_buffer_realloc <span>sideData-></span>buf and fix <span>sideData-></span>data/<span>sideData->size fields.</span></div><div><span><br></span></div><div><span>Regards,<br></span></div><div><span>Yurii<br></span></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">чт, 2 мар. 2023 г. в 07:06, Wladislav Artsimovich <ffmpeg@frost.kiwi>:<br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)">Dear Yurii,<br>
<br>
thx for elaborating. Indeed reassigning the pointer was a logical error, <br>
thx for pointing (hah) it out. I tried using `av_buffer_create()` <br>
originally, but couldn't find a way of using that function pointer <br>
callback `av_buffer_default_free()` in C#.<br>
 From C# pMessageData cannot be freed, but is discarded automatically <br>
when the fixed{} block ends. I managed to free that MetaDatabuffer and <br>
the associated memory leak is gone! But not via `av_free()` (which <br>
didn't work, no error, no freeing), but via `av_buffer_unref()`. <br>
However, there still remains another memory leak caused by <br>
`av_frame_new_side_data_from_buf()`<br>
<br>
How can I solve that? I tried following <br>
<a href="https://chromium.googlesource.com/chromium/third_party/ffmpeg/+/refs/heads/master/libavutil/frame.c#66" rel="noreferrer" target="_blank">https://chromium.googlesource.com/chromium/third_party/ffmpeg/+/refs/heads/master/libavutil/frame.c#66</a> <br>
and inserting `ffmpeg.av_buffer_unref(&sideData->buf); <br>
ffmpeg.av_dict_free(&sideData->metadata); ffmpeg.av_freep(sideData);` at <br>
different positions and `av_frame_remove_side_data()` at different <br>
positions, eg. before or after `ffmpeg.av_packet_free(&pPacket);`. The <br>
Encoder just gracefully stops without error, not processing any further <br>
frames.<br>
<br>
What would be the proper procedure to free that AVFrameSideData?<br>
<br>
Here is the full breakdown:<br>
<br>
0 MB memory leaked per 100000 frames:<br>
fixed (byte* pMessageData = message)<br>
{<br>
     //AVBufferRef* MetaDataBuffer = <br>
ffmpeg.av_buffer_alloc((ulong)message.Length);<br>
     //System.Buffer.MemoryCopy(pMessageData, MetaDataBuffer->data, <br>
(ulong)message.Length, (ulong)message.Length);<br>
     //AVFrameSideData* sideData = <br>
ffmpeg.av_frame_new_side_data_from_buf(&frame, <br>
AVFrameSideDataType.AV_FRAME_DATA_SEI_UNREGISTERED, MetaDataBuffer);<br>
     ffmpeg.avcodec_send_frame(_pCodecContext, <br>
&frame).ThrowExceptionIfError();<br>
     //ffmpeg.av_buffer_unref(&MetaDataBuffer);<br>
}<br>
<br>
62 MB leaked per 100000 frames:<br>
fixed (byte* pMessageData = message)<br>
{<br>
     AVBufferRef* MetaDataBuffer = <br>
ffmpeg.av_buffer_alloc((ulong)message.Length);<br>
     System.Buffer.MemoryCopy(pMessageData, MetaDataBuffer->data, <br>
(ulong)message.Length, (ulong)message.Length);<br>
     //AVFrameSideData* sideData = <br>
ffmpeg.av_frame_new_side_data_from_buf(&frame, <br>
AVFrameSideDataType.AV_FRAME_DATA_SEI_UNREGISTERED, MetaDataBuffer);<br>
     ffmpeg.avcodec_send_frame(_pCodecContext, <br>
&frame).ThrowExceptionIfError();<br>
     //ffmpeg.av_buffer_unref(&MetaDataBuffer);<br>
}<br>
<br>
0 MB memory leaked per 100000 frames:<br>
fixed (byte* pMessageData = message)<br>
{<br>
     AVBufferRef* MetaDataBuffer = <br>
ffmpeg.av_buffer_alloc((ulong)message.Length);<br>
     System.Buffer.MemoryCopy(pMessageData, MetaDataBuffer->data, <br>
(ulong)message.Length, (ulong)message.Length);<br>
     //AVFrameSideData* sideData = <br>
ffmpeg.av_frame_new_side_data_from_buf(&frame, <br>
AVFrameSideDataType.AV_FRAME_DATA_SEI_UNREGISTERED, MetaDataBuffer);<br>
     ffmpeg.avcodec_send_frame(_pCodecContext, <br>
&frame).ThrowExceptionIfError();<br>
     ffmpeg.av_buffer_unref(&MetaDataBuffer);<br>
}<br>
<br>
24.5 MB leaked per 100000 frames:<br>
fixed (byte* pMessageData = message)<br>
{<br>
     AVBufferRef* MetaDataBuffer = <br>
ffmpeg.av_buffer_alloc((ulong)message.Length);<br>
     System.Buffer.MemoryCopy(pMessageData, MetaDataBuffer->data, <br>
(ulong)message.Length, (ulong)message.Length);<br>
     AVFrameSideData* sideData = <br>
ffmpeg.av_frame_new_side_data_from_buf(&frame, <br>
AVFrameSideDataType.AV_FRAME_DATA_SEI_UNREGISTERED, MetaDataBuffer);<br>
     ffmpeg.avcodec_send_frame(_pCodecContext, <br>
&frame).ThrowExceptionIfError();<br>
     ffmpeg.av_buffer_unref(&MetaDataBuffer);<br>
}<br>
<br>
Best regards,<br>
<br>
Vlad<br>
<br>
On 3/2/2023 09:35, Yurii Monakov wrote:<br>
> av_buffer_alloc allocates buffer of given length (it’s data pointer is <br>
> not null). And after that you replace that pointer to with your own <br>
> pointer. So, the first allocation get definitely lost.<br>
> You should copy pMessageData to MetaDataBuffer->data (and free <br>
> pMessageData manually) or use av_buffer_create function.<br>
><br>
> Yurii<br>
><br>
> Ср, 1 марта 2023 г. в 06:55, Wladislav Artsimovich <ffmpeg@frost.kiwi>:<br>
><br>
>     Dear FFmpeg and libav users,<br>
><br>
>     I am using FFmpeg.AutoGen in my C# Program to write out frames<br>
>     encoded<br>
>     as a h.264 stream and inject per-frame metadata with an<br>
>     unregistered SEI<br>
>     Message. It works great, but I have a memory leak, which I don't know<br>
>     how to address. Source file attached.<br>
><br>
>     Culprit is<br>
>     ```C#<br>
>     fixed (byte* pMessageData = message)<br>
>     {<br>
>          AVBufferRef* MetaDataBuffer =<br>
>     ffmpeg.av_buffer_alloc((ulong)message.Length);<br>
>          MetaDataBuffer->data = pMessageData;<br>
>          AVFrameSideData* sideData =<br>
>     ffmpeg.av_frame_new_side_data_from_buf(&frame,<br>
>     AVFrameSideDataType.AV_FRAME_DATA_SEI_UNREGISTERED, MetaDataBuffer);<br>
>     }<br>
>     ```<br>
>     I create an AVBuffer, as required by<br>
>     av_frame_new_side_data_from_buf().<br>
>     But I cannot free it, resulting in a memory leak. I went through<br>
>     all of<br>
>     <a href="https://ffmpeg.org/doxygen/trunk/group__lavu__buffer.html" rel="noreferrer" target="_blank">https://ffmpeg.org/doxygen/trunk/group__lavu__buffer.html</a> and<br>
>     tried out<br>
>     different av_freep() av_free(), av_buffer_unref() functions, changing<br>
>     when to free etc. When I think I perform the free correctly, nothing<br>
>     happens. No error, no freeing just nothing. Clearly I misunderstand<br>
>     something.<br>
>     To add insult to injury, the Visual Studio profiler cannot look<br>
>     inside<br>
>     the unmanaged memory of libav and reports, that the heap is fine<br>
>     and not<br>
>     growing, see attached screenshot.<br>
><br>
>     How and when can I free this memory created allocated by<br>
>     av_buffer_alloc() in the attached source file?<br>
><br>
>     I asked the same question in the FFmpeg.AutoGen Questions Repo. Some<br>
>     more context there:<br>
>     <a href="https://github.com/Ruslan-B/FFmpeg.AutoGen.Questions/issues/36" rel="noreferrer" target="_blank">https://github.com/Ruslan-B/FFmpeg.AutoGen.Questions/issues/36</a><br>
><br>
>     Best regards,<br>
><br>
>     Vlad<br>
>     _______________________________________________<br>
>     Libav-user mailing list<br>
>     <a href="mailto:Libav-user@ffmpeg.org" target="_blank">Libav-user@ffmpeg.org</a><br>
>     <a href="https://ffmpeg.org/mailman/listinfo/libav-user" rel="noreferrer" target="_blank">https://ffmpeg.org/mailman/listinfo/libav-user</a><br>
><br>
>     To unsubscribe, visit link above, or email<br>
>     <a href="mailto:libav-user-request@ffmpeg.org" target="_blank">libav-user-request@ffmpeg.org</a> with subject "unsubscribe".<br>
><br>
><br>
> _______________________________________________<br>
> Libav-user mailing list<br>
> <a href="mailto:Libav-user@ffmpeg.org" target="_blank">Libav-user@ffmpeg.org</a><br>
> <a href="https://ffmpeg.org/mailman/listinfo/libav-user" rel="noreferrer" target="_blank">https://ffmpeg.org/mailman/listinfo/libav-user</a><br>
><br>
> To unsubscribe, visit link above, or email<br>
> <a href="mailto:libav-user-request@ffmpeg.org" target="_blank">libav-user-request@ffmpeg.org</a> with subject "unsubscribe".<br>
</blockquote></div>
</div></div>