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

call to esp_camera_fb_get causes stack overflow after calling set_framesize with bigger resolution than used in esp_camera_init #514

Closed
MichaelXt opened this issue Mar 11, 2023 · 6 comments

Comments

@MichaelXt
Copy link

I'm experiencing the issue, when the result image is close to 100k or more, the esp_camera_fb_get call times out. It is consistent across runs - as long as the resulting jpg image is under 100k bytes, then the image is properly returned, the moment the quality settings + image resolution + scene gets more details: the call starts timing out.

For records:

Arduino flash parameters:
CPU Frequency: "240MHz (WiFi/BT)"
Core Debug Level: "None"
Erase All Flash Before Sketch Upload: "Disabled"
Events Run On: "Core 1"
Flash Frequency: "80MHz"
Flash Mode: "QIO"
Flash Size: "4MB (32Mb)"
JTAG Adapter: "FTDI Adapter”
Arduino Runs On: "Core 1"
Partition Scheme: "Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)"
PSRAM: “Enabled”
Upload Speed: "115200"

What could be the reason for such timeouts, and is there anything can be done to increase the image max size?

@MichaelXt
Copy link
Author

Got the camera driver code compiled in my project and debugged it.

       cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_aligned_alloc(16, alloc_size, _caps);
        // BUG: `alloc_size` depends on `cam_obj->fb_size` and `cam_obj->recv_size,
        // which in turn is calculated as `cam_obj->width * cam_obj->height / 5` in `cam_config(...)`
        // however the `cam_config(...)` is called only on `cam_init(...)`, but
        // subsequent calls to `set_framesize` do not adjust the buffer size, causing the buffer overrun

where size_t alloc_size = fb_size * sizeof(uint8_t) + dma_align, size_t fb_size = cam_obj->fb_size, cam_obj->fb_size = cam_obj->recv_size and cam_obj->recv_size = cam_obj->width * cam_obj->height / 5 in cam_config(...).
cam_config is called only during cam_init and never during set_framesize.
That means that if the cam_init was called with FRAMESIZE_SVGA (800x600 - rather small).
Once the set_framesize is called with FRAMESIZE_UXGA (1600x1200) the buffer size remains the same, causing the buffer overrun in cam_take(...). Due to this, the cam_verify_jpeg_eoi is not able to find the jpeg eoi, causing the recursion at return cam_take(timeout - (xTaskGetTickCount() - start));//recurse!!!!, and hence the stack overflow.

refined repro:

  1. call esp_camera_init with FRAMESIZE_QVGA
  2. do set_framesize with FRAMESIZE_UXGA
  3. attempt to capture scene in good lighting with lots of details using esp_camera_fb_get
    3a. Expected: the image is successfully taken with FRAMESIZE_UXGA resolution
    3b. Actual: the call times out, the logs show that the camera got restarted

Here is the list of the issues, which would be great if they get fixed in the esp32-camera:

  • resize the buffer on set_framesize call
  • add additional validation in the cam_take on the expected buffer size. If the formula (width+height)/5 is ok, then use it to validate that the buffer size is big enough
  • limit the number of retries done using recursion return cam_take(timeout - (xTaskGetTickCount() - start));//recurse!!!! - it is better to return error, rather than causing the stack overflow

@MichaelXt MichaelXt changed the title esp_camera_fb_get timeout if resulting image is more than 100k bytes call to esp_camera_fb_get times out after set_framesize call to a bigger resolution than used in esp_camera_init Mar 12, 2023
@MichaelXt MichaelXt changed the title call to esp_camera_fb_get times out after set_framesize call to a bigger resolution than used in esp_camera_init call to esp_camera_fb_get times out after set_framesize with bigger resolution than used in esp_camera_init Mar 12, 2023
@MichaelXt MichaelXt changed the title call to esp_camera_fb_get times out after set_framesize with bigger resolution than used in esp_camera_init call to esp_camera_fb_get causes stack overflow after set_framesize with bigger resolution than used in esp_camera_init Mar 12, 2023
@MichaelXt MichaelXt changed the title call to esp_camera_fb_get causes stack overflow after set_framesize with bigger resolution than used in esp_camera_init call to esp_camera_fb_get causes stack overflow after calling set_framesize with bigger resolution than used in esp_camera_init Mar 12, 2023
@github-actions
Copy link

This issue appears to be stale. Please close it if its no longer valid.

@RomanLut
Copy link

RomanLut commented Dec 4, 2023

Stack overflow seems to be fixed in:
772aefd
and release 2.0.6

@oldmud0
Copy link

oldmud0 commented Dec 14, 2023

I think the proper fix would be to remove tail call recursion rather than assuming that the compiler will perform TCO.

@me-no-dev
Copy link
Member

proper fix will be everything to happen sequentially in another task. That is planned to happen.

@MikeSnyder360
Copy link

Stack overflow seems to be fixed in: 772aefd and release 2.0.6

Isn't that just in jpg mode?
I'm seeing this problem with PIXFORMAT_GRAYSCALE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants