Skip to content

Commit 50f29e5

Browse files
committed
Ensure image codecs are allocated in C heap
See #17
1 parent a3f6cd5 commit 50f29e5

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

src/imgcodecs.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@ extern "C" {
1313

1414
using namespace cv;
1515

16+
// Fix for https://github.com/sparkfun/micropython-opencv/issues/17
17+
//
18+
// TLDR; The `g_codecs` object (which stores all image encoders and decoders) is
19+
// allocated once, whenever the first OpenCV function that needs it happens to
20+
// be called. That will only happen from the user's code, after the GC has been
21+
// initialized, meaning it gets allocated on the GC heap (see `__wrap_malloc()`)
22+
// If a soft reset occurs, the GC gets reset and overwrites the memory location,
23+
// but the same memory location is still referenced for the the `g_codecs`
24+
// object, resulting in bogus values and subsequent `imread()` and `imwrite()`
25+
// calls fail
26+
//
27+
// The solution here is to create a global variable that subsequently creates
28+
// the `g_codecs` object before the GC has been initialized, so it's allocated
29+
// on the C heap and persists through soft resets. `g_codecs` is initialized
30+
// when calling `getCodecs()`, which is not publicly exposed. The next best
31+
// option is to call `haveImageWriter()`, which calls `findEncoder()`, which
32+
// calls `getCodecs()`
33+
volatile bool haveImageWriterPNG = haveImageWriter(".png");
34+
1635
// Helper macro to create an empty mp_map_t, derived from MP_DEFINE_CONST_MAP.
1736
// Primarily used for function calls with no keyword arguments, since we can't
1837
// just pass `NULL` or mp_const_none (crash occurs otherwise)

src/opencv_upy.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ target_link_libraries(usermod INTERFACE usermod_cv2)
2323

2424
# OpenCV creates some global variables on the heap. These get created before
2525
# the GC is initialized, so we need to allocate some space for them on the C
26-
# heap. 10kB seems sufficient. TODO: See if we can get away with less.
27-
set(MICROPY_C_HEAP_SIZE 10240)
26+
# heap. 64kB seems sufficient.
27+
set(MICROPY_C_HEAP_SIZE 65536)
2828

2929
# Makes m_tracked_calloc() and m_tracked_free() available. These track pointers
3030
# in a linked list to ensure the GC does not free them. Needed for some OpenCV

0 commit comments

Comments
 (0)