Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leaks in HeifContext::encode_image_as_hevc? #960

Closed
zsuhoo opened this issue Sep 12, 2023 · 7 comments
Closed

Memory leaks in HeifContext::encode_image_as_hevc? #960

zsuhoo opened this issue Sep 12, 2023 · 7 comments

Comments

@zsuhoo
Copy link

zsuhoo commented Sep 12, 2023

@farindk Hi, There maybe a memory leak

x265-3.4
libheif-1.16.2
libvips-8.14.4
Ubuntu 22.04

Steps:

  1. gcc -g -O2 -o thumbnail_heic thumbnail_heic.c `pkg-config vips --cflags --libs`
  2. valgrind --tool=memcheck --log-file=mem_leak.log --leak-check=full --show-leak-kinds=all -s ./thumbnail_heic ./IMG_0512.HEIC

Test case:
IMG_0512.HEIC.zip

thumbnail_heic.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#include <vips/foreign.h>


int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("Usage: %s <heic file path>\n", argv[0]);
        return 1;
    }

    const char *heic_file_path = argv[1];
    const int width = 100;
    const int height = 75;

    // init vips 
    if (VIPS_INIT(argv[0]))
    {
        vips_error_exit("unable to start VIPS");
    }

    // read to buffer
    char *buffer = NULL;
    size_t file_size = 0;
    if (!g_file_get_contents(heic_file_path, &buffer, &file_size, NULL))
    {
        vips_error_exit("g_file_get_contents err");
    }

    VipsImage *thumbnail = NULL;
    if (vips_thumbnail_buffer(buffer, file_size, &thumbnail, width, "height", height, NULL))
    {
        vips_error_exit("vips_thumbnail_buffer err");
    }

    void* buffer_thumbnail = NULL;
    size_t buffer_thumbnail_size = 0;
    int ret = vips_image_write_to_buffer(thumbnail, ".heic", &buffer_thumbnail, &buffer_thumbnail_size, NULL);
    if (0 != ret)
    {
        printf("vips_image_write_to_buffer err %d\n", ret );
    }

    // free
    g_object_unref(thumbnail);
    if (NULL != buffer)
    {
        free(buffer);
    }
    if (NULL != buffer_thumbnail)
    {
        free(buffer_thumbnail);
    }

    return 0;
}

Result: mem_leak.log

==32124== 1,112 bytes in 1 blocks are definitely lost in loss record 7,659 of 7,843
==32124==    at 0x4C2B375: memalign (vg_replace_malloc.c:908)
==32124==    by 0x4C2B43F: posix_memalign (vg_replace_malloc.c:1072)
==32124==    by 0x139413F5: x265::x265_malloc(unsigned long) (in /usr/local/lib/libx265.so.192)
==32124==    by 0x1384AEBE: x265_encoder_open_192 (in /usr/local/lib/libx265.so.192)
==32124==    by 0x135399E7: x265_encode_image(void*, heif_image const*, heif_image_input_class) (in /usr/local/lib64/libheif.so.1.16.2)
==32124==    by 0x134C4CA1: HeifContext::encode_image_as_hevc(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /usr/local/lib64/libheif.so.1.16.2)
==32124==    by 0x134C3BE3: HeifContext::encode_image(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /usr/local/lib64/libheif.so.1.16.2)
==32124==    by 0x134A1AEE: heif_context_encode_image (in /usr/local/lib64/libheif.so.1.16.2)
==32124==    by 0x1323B3E8: vips_foreign_save_heif_write_block (in /usr/local/lib64/vips-modules-8.14/vips-heif.so)
==32124==    by 0x5082791: wbuffer_write_thread (in /usr/local/lib64/libvips.so.42.16.4)
==32124==    by 0x506C229: vips_threadset_work (in /usr/local/lib64/libvips.so.42.16.4)
==32124==    by 0x506BD4E: vips_thread_run (in /usr/local/lib64/libvips.so.42.16.4)

==32124== LEAK SUMMARY:
==32124==    definitely lost: 1,112 bytes in 1 blocks
==32124==    indirectly lost: 0 bytes in 0 blocks
==32124==      possibly lost: 3,148,902 bytes in 53 blocks
==32124==    still reachable: 37,989,012 bytes in 19,787 blocks
==32124==                       of which reachable via heuristic:
==32124==                         length64           : 40 bytes in 1 blocks
==32124==                         newarray           : 1,552 bytes in 17 blocks
==32124==         suppressed: 0 bytes in 0 blocks
==32124==
==32124== ERROR SUMMARY: 35 errors from 35 contexts (suppressed: 0 from 0)
@zsuhoo zsuhoo changed the title Memory leak in HeifContext::encode_image_as_hevc? Memory leaks in HeifContext::encode_image_as_hevc? Sep 12, 2023
@bradh
Copy link
Contributor

bradh commented Sep 12, 2023

Appears to be an issue with x265.

@silverbacknet
Copy link

You can see a basic explanation of why x265 is showing this here: https://x265.readthedocs.io/en/3.1.1/api.html#cleanup It's a perennial bug report with everything that uses x265.

libheif doesn't call x265_cleanup(), but that's because the purpose is literally just to appease overly aggressive leak detectors. x265 will re-use the same tiny allocation every time it's re-initialized, and let the OS clean it up with program termination. FFmpeg and most other libraries and tools don't bother to call it either.

Not convinced it's the world's greatest design, but it is what it is, and it's only a few KB in most cases.

@farindk
Copy link
Contributor

farindk commented Sep 12, 2023

@silverbacknet Thanks for mentioning x265_cleanup(). Maybe libheif should simply call this when it deinitializes a plugin.

@zsuhoo
Copy link
Author

zsuhoo commented Sep 13, 2023

Thanks a lot!

@zsuhoo zsuhoo closed this as completed Sep 13, 2023
@farindk farindk reopened this Sep 13, 2023
@farindk
Copy link
Contributor

farindk commented Sep 13, 2023

Please let this open until I've looked into x265_cleanup.

@bradh
Copy link
Contributor

bradh commented Dec 10, 2023

I think we really do have a leak here.

There are two parts - the "definitely lost" and the "possible lost" / "still reachable".

Checking with valgrind --undef-value-errors=no --leak-check=full ./examples/heif-enc /usr/share/wallpapers/Blue_Curl/contents/images/1024x768.jpg --output out.heif with the develop-v1.18.0 branch gives me:

==20281== Memcheck, a memory error detector
==20281== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==20281== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==20281== Command: ./examples/heif-enc /usr/share/wallpapers/Blue_Curl/contents/images/1024x768.jpg --output out.heif

[3 x invalid read removed here]

==20281== HEAP SUMMARY:
==20281==     in use at exit: 8,914,228 bytes in 82 blocks
==20281==   total heap usage: 4,220 allocs, 4,138 frees, 48,830,078 bytes allocated
==20281== 
==20281== Thread 1:
==20281== 1,168 bytes in 1 blocks are definitely lost in loss record 1 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51374F2: x265_encoder_open_199 (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4980713: x265_encode_image(void*, heif_image const*, heif_image_input_class) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48E0000: HeifContext::encode_image_as_hevc(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48DED99: HeifContext::encode_image(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48C1ED2: heif_context_encode_image (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x110FB5: main (in /home/bradh/libheif/build/examples/heif-enc)
==20281== 
==20281== 262,146 bytes in 1 blocks are possibly lost in loss record 2 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB15E: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50FD4BD: x265::Lookahead::create() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51241BC: x265::Encoder::create() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x5137656: x265_encoder_open_199 (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4980713: x265_encode_image(void*, heif_image const*, heif_image_input_class) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48E0000: HeifContext::encode_image_as_hevc(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48DED99: HeifContext::encode_image(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48C1ED2: heif_context_encode_image (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x110FB5: main (in /home/bradh/libheif/build/examples/heif-enc)
==20281== 
==20281== 262,152 bytes in 4 blocks are possibly lost in loss record 3 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB10D: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50FD4BD: x265::Lookahead::create() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51241BC: x265::Encoder::create() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x5137656: x265_encoder_open_199 (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4980713: x265_encode_image(void*, heif_image const*, heif_image_input_class) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48E0000: HeifContext::encode_image_as_hevc(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48DED99: HeifContext::encode_image(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48C1ED2: heif_context_encode_image (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x110FB5: main (in /home/bradh/libheif/build/examples/heif-enc)
==20281== 
==20281== 524,292 bytes in 1 blocks are possibly lost in loss record 4 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EAF97: x265::BitCost::CalculateLogs() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB154: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50FD4BD: x265::Lookahead::create() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51241BC: x265::Encoder::create() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x5137656: x265_encoder_open_199 (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4980713: x265_encode_image(void*, heif_image const*, heif_image_input_class) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48E0000: HeifContext::encode_image_as_hevc(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48DED99: HeifContext::encode_image(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x48C1ED2: heif_context_encode_image (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20281==    by 0x110FB5: main (in /home/bradh/libheif/build/examples/heif-enc)
==20281== 
==20281== 524,292 bytes in 2 blocks are possibly lost in loss record 5 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB15E: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D8E1E: x265::Search::setLambdaFromQP(x265::CUData const&, int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D78CF: x265::Analysis::compressCTU(x265::CUData&, x265::Frame&, x265::CUGeom const&, x265::Entropy const&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51094FB: x265::FrameEncoder::processRowEncoder(int, x265::ThreadLocalData&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x510B713: x265::FrameEncoder::processRow(int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51869B2: x265::WaveFront::findJob(int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x518C59A: x265::WorkerThread::threadMain() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51868DD: ??? (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4F16AD9: start_thread (pthread_create.c:444)
==20281==    by 0x4FA72E3: clone (clone.S:100)
==20281== 
==20281== 524,304 bytes in 8 blocks are possibly lost in loss record 6 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB10D: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D8E1E: x265::Search::setLambdaFromQP(x265::CUData const&, int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D78CF: x265::Analysis::compressCTU(x265::CUData&, x265::Frame&, x265::CUGeom const&, x265::Entropy const&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51094FB: x265::FrameEncoder::processRowEncoder(int, x265::ThreadLocalData&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x510B713: x265::FrameEncoder::processRow(int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51869B2: x265::WaveFront::findJob(int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x518C59A: x265::WorkerThread::threadMain() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51868DD: ??? (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4F16AD9: start_thread (pthread_create.c:444)
==20281==    by 0x4FA72E3: clone (clone.S:100)
==20281== 
==20281== 3,407,898 bytes in 13 blocks are possibly lost in loss record 7 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB15E: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D8E1E: x265::Search::setLambdaFromQP(x265::CUData const&, int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50CC14A: x265::Analysis::compressIntraCU(x265::CUData const&, x265::CUGeom const&, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D7DE7: x265::Analysis::compressCTU(x265::CUData&, x265::Frame&, x265::CUGeom const&, x265::Entropy const&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51094FB: x265::FrameEncoder::processRowEncoder(int, x265::ThreadLocalData&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x510B713: x265::FrameEncoder::processRow(int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51869B2: x265::WaveFront::findJob(int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x518C59A: x265::WorkerThread::threadMain() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51868DD: ??? (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4F16AD9: start_thread (pthread_create.c:444)
==20281== 
==20281== 3,407,976 bytes in 52 blocks are possibly lost in loss record 8 of 8
==20281==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20281==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50EB10D: x265::BitCost::setQP(unsigned int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D8E1E: x265::Search::setLambdaFromQP(x265::CUData const&, int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50CC14A: x265::Analysis::compressIntraCU(x265::CUData const&, x265::CUGeom const&, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x50D7DE7: x265::Analysis::compressCTU(x265::CUData&, x265::Frame&, x265::CUGeom const&, x265::Entropy const&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51094FB: x265::FrameEncoder::processRowEncoder(int, x265::ThreadLocalData&) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x510B713: x265::FrameEncoder::processRow(int, int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51869B2: x265::WaveFront::findJob(int) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x518C59A: x265::WorkerThread::threadMain() (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x51868DD: ??? (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20281==    by 0x4F16AD9: start_thread (pthread_create.c:444)
==20281== 
==20281== LEAK SUMMARY:
==20281==    definitely lost: 1,168 bytes in 1 blocks
==20281==    indirectly lost: 0 bytes in 0 blocks
==20281==      possibly lost: 8,913,060 bytes in 81 blocks
==20281==    still reachable: 0 bytes in 0 blocks
==20281==         suppressed: 0 bytes in 0 blocks
==20281== 
==20281== For lists of detected and suppressed errors, rerun with: -s
==20281== ERROR SUMMARY: 16143 errors from 11 contexts (suppressed: 0 from 0)

Adding an x265_cleanup() call, like:

diff --git a/libheif/plugins/encoder_x265.cc b/libheif/plugins/encoder_x265.cc
index cbc80fa..20a7371 100644
--- a/libheif/plugins/encoder_x265.cc
+++ b/libheif/plugins/encoder_x265.cc
@@ -299,6 +299,7 @@ static void x265_init_plugin()
 
 static void x265_cleanup_plugin()
 {
+  x265_cleanup();
 }

gets to:

==20502== Memcheck, a memory error detector
==20502== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==20502== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==20502== Command: ./examples/heif-enc /usr/share/wallpapers/Blue_Curl/contents/images/1024x768.jpg --output out.heif
[Same 3 x invalid read removed here]

==20502== HEAP SUMMARY:
==20502==     in use at exit: 1,168 bytes in 1 blocks
==20502==   total heap usage: 4,220 allocs, 4,219 frees, 48,830,078 bytes allocated
==20502== 
==20502== Thread 1:
==20502== 1,168 bytes in 1 blocks are definitely lost in loss record 1 of 1
==20502==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==20502==    by 0x5189CE7: x265::x265_malloc(unsigned long) (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20502==    by 0x51374F2: x265_encoder_open_199 (in /usr/lib/x86_64-linux-gnu/libx265.so.199)
==20502==    by 0x4980738: x265_encode_image(void*, heif_image const*, heif_image_input_class) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20502==    by 0x48E0020: HeifContext::encode_image_as_hevc(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20502==    by 0x48DEDB9: HeifContext::encode_image(std::shared_ptr<HeifPixelImage> const&, heif_encoder*, heif_encoding_options const&, heif_image_input_class, std::shared_ptr<HeifContext::Image>&) (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20502==    by 0x48C1EF2: heif_context_encode_image (in /home/bradh/libheif/build/libheif/libheif.so.1.17.5)
==20502==    by 0x110FB5: main (in /home/bradh/libheif/build/examples/heif-enc)
==20502== 
==20502== LEAK SUMMARY:
==20502==    definitely lost: 1,168 bytes in 1 blocks
==20502==    indirectly lost: 0 bytes in 0 blocks
==20502==      possibly lost: 0 bytes in 0 blocks
==20502==    still reachable: 0 bytes in 0 blocks
==20502==         suppressed: 0 bytes in 0 blocks
==20502== 
==20502== For lists of detected and suppressed errors, rerun with: -s
==20502== ERROR SUMMARY: 16136 errors from 4 contexts (suppressed: 0 from 0)

So now for the definitely lost part. After staring at x265 source code for an afternoon, I think its a problem in x265. The problem occurs with the x265 command line tool too.

==33263== Thread 1:
==33263== 1,168 bytes in 1 blocks are definitely lost in loss record 1 of 1
==33263==    at 0x484B1F9: posix_memalign (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==33263==    by 0x4970CE7: x265::x265_malloc(unsigned long) (common.cpp:81)
==33263==    by 0x491E4F2: x265_encoder_open_199 (api.cpp:98)
==33263==    by 0x11CB6E: x265::PassEncoder::init(int&) (in /usr/bin/x265)
==33263==    by 0x11CE99: x265::AbrEncoder::AbrEncoder(x265::CLIOptions*, unsigned char, int&) (in /usr/bin/x265)
==33263==    by 0x111ECD: main (in /usr/bin/x265)

It allocates zoneParam at https://github.com/videolan/x265/blob/master/source/encoder/api.cpp#L98 and then only does the required param_free() in case of failure. The code is so intricate in x265 that I couldn't even patch it with confidence - perhaps pass the zone param into the Encoder class and then free it in Encoder::destroy(), but it'd be voodoo coding.

@farindk
Copy link
Contributor

farindk commented Dec 19, 2023

Resolved in #1061

@farindk farindk closed this as completed Dec 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants