[FFmpeg-devel] Memory leaks using x265 encoder
Oliver Collyer
ovcollyer at mac.com
Wed Jan 2 16:55:54 EET 2019
> On 2 Jan 2019, at 16:03, Oliver Collyer <ovcollyer at mac.com> wrote:
>
>
>
>> On 2 Jan 2019, at 12:58, Oliver Collyer <ovcollyer at mac.com> wrote:
>>
>> Hello
>>
>> So this time I'm reporting some potential memory leaks in the x265 encoder. There are a few hundred following a short encode session, but all seem to have the same call stack as below but varying allocation sizes.
>>
>> I am calling avcodec_open2() to open the encoder and then avcodec_free_context() to clean it up afterwards, as per the documentation.
>>
>> My code is built against the latest from https://github.com/ShiftMediaProject/FFmpeg <https://github.com/ShiftMediaProject/FFmpeg> <https://github.com/ShiftMediaProject/FFmpeg <https://github.com/ShiftMediaProject/FFmpeg>> and I'm using Visual Leak Detector to detect the leaks.
>>
>> Or would this be better posted in whatever mailing list x265 development uses?
>>
>> Regards
>>
>> Oliver
>>
>> ---------- Block 63379 at 0x000000008CC3A370: 262225 bytes ----------
>> Leak Hash: 0x95CBF73D, Count: 15, Total 3933375 bytes
>> Call Stack:
>> ucrtbased.dll!aligned_malloc()
>> emu-server.exe!x265::x265_malloc() + 0x48 bytes
>> emu-server.exe!x265::BitCost::setQP() + 0x9A bytes
>> emu-server.exe!x265::Search::setLambdaFromQP() + 0xF8 bytes
>> emu-server.exe!x265::Analysis::compressIntraCU() + 0x87E bytes
>> emu-server.exe!x265::Analysis::compressCTU() + 0xC8B bytes
>> emu-server.exe!x265::FrameEncoder::processRowEncoder() + 0xFA7 bytes
>> emu-server.exe!x265::FrameEncoder::processRow() + 0x128 bytes
>> emu-server.exe!x265::WaveFront::findJob() + 0x125 bytes
>> emu-server.exe!x265::WorkerThread::threadMain() + 0x18A bytes
>> emu-server.exe!x265::Thread::`scalar deleting destructor'() + 0x14A bytes
>> emu-server.exe!x265::Thread::`scalar deleting destructor'() + 0xD2 bytes
>> KERNEL32.DLL!BaseThreadInitThunk() + 0x14 bytes
>> ntdll.dll!RtlUserThreadStart() + 0x21 bytes
>> Data:
>> 70 A3 C3 8C 4B 02 00 00 ED ED ED ED ED ED ED ED p...K... ........
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>> 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 7D 01 }.}.}.}. }.}.}.}.
>>
>>
>> Visual Leak Detector detected 236 memory leaks (25197214 bytes).
>
> So looking into this some more, according to the x265 docs:
>
> "When the application has completed all encodes, it should call x265_cleanup() to free process global, particularly if a memory-leak detection tool is being used. x265_cleanup() also resets the saved CTU size so it will be possible to create a new encoder with a different CTU size:
> /* x265_cleanup:
> * release library static allocations, reset configured CTU size */
> void x265_cleanup(void);"
>
> This function explicitly frees the allocations being reported by VLD above.
>
> I cannot see that this done anywhere by the ffmpeg libraries though. Maybe this is not considered significant as the OS deals with this on exit?
>
> I did notice in libx265.c...
>
> AVCodec ff_libx265_encoder = {
> .name = "libx265",
> .long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"),
> .type = AVMEDIA_TYPE_VIDEO,
> .id = AV_CODEC_ID_HEVC,
> .init = libx265_encode_init,
> .init_static_data = libx265_encode_init_csp,
> .encode2 = libx265_encode_frame,
> .close = libx265_encode_close,
> .priv_data_size = sizeof(libx265Context),
> .priv_class = &class,
> .defaults = x265_defaults,
> .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,
> .wrapper_name = "libx265",
> };
>
> ...there is the concept of initialisation of static data, but looking at AVCodec there is no similar cleaning-up function (confirmed by looking at avcodec/allcodecs.c).
>
> Is there a precedent for how to handle something like this - I don't see how I can access the x265_api pointer in order to call the x265_cleanup function myself, because it is hidden inside the private libx265context in libx265.c.
>
> Perhaps libx265.c needs to keep track of the number of encoders open, and when the last is closed, call clean-up? In any case, the documentation above states that calling z265_clean_up() is necessary in order to create a new encoder with a different CTU size.
>
So here is a patch that cleans up x265 when the last encoder is closed and gets rid of my VLD errors.
I don't know whether you folks want this as it serialises x265 encoder init/close, but I'm throwing it out there anyway.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: libx265.patch
Type: application/octet-stream
Size: 6219 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20190102/7a0ddd8a/attachment.obj>
-------------- next part --------------
More information about the ffmpeg-devel
mailing list