espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.35k stars 7.37k forks source link

qr-code recognization occures ESP32 heap error? #3676

Closed p2o5 closed 4 years ago

p2o5 commented 4 years ago

ESP32-Cam_CameraWebServer.zip

Hardware:

Board: ESP32-CAM (ESP32 wrover model) Core Installation/update date: 1.0.4 IDE name: Arduino IDE 1.8.10 Flash Frequency: 80Mhz PSRAM enabled: yes Upload Speed: 115200 Computer OS: Windows 10

Description:

I replace face recognize with qr-code recognize in example "ESP32-camera-CameraWebServer" when i run the application,click face recognize and change resolution in QVGA(320*240) and i place a qr code image in front of the camera, something unknown happened about ESP32 heap

Sketch

example "ESP32-camera-CameraWebServer" replace face recognize with qr code recognize by using library:https://github.com/dlbeer/quirc

"main.ino"=========
...
#define CAMERA_MODEL_AI_THINKER
...
"app_httpd.cpp"============
...
#include "quirc_internal.h"
#include <quirc.h>
static struct quirc *qr_recognizer;
static uint16_t old_width = 0;
static uint16_t old_height = 0;
static uint8_t *image = NULL;
static int id_count = 0;
static struct quirc_code code;
static struct quirc_data data;
...
static void rgb2grayscale(rgb_t *rgb, uint8_t *gray, uint16_t len) {
  uint32_t rgbv;
  for (int i = 0; i < len; i++) {
    rgbv = (rgb->r * 19595 + rgb->g * 38469 + rgb->b * 7472);
    *gray = rgbv >> 16;
    rgb = rgb + 1;
    gray = gray + 1;
  }
}

static int q_resize(struct quirc *q, int w, int h)
{
  int ret;
  uint8_t   *image  = NULL;
  quirc_pixel_t *pixels = NULL;
  size_t olddim, newdim, min;
  Serial.printf("q_resize w=%d,h=%d\n", w, h);
  /*
     XXX: w and h should be size_t (or at least unsigned) as negatives
     values would not make much sense. The downside is that it would break
     both the API and ABI. Thus, at the moment, let's just do a sanity
     check.
  */
  if (w < 0 || h < 0) {
    Serial.printf("q_resize2 w=%d,h=%d\n", w, h);
    ret = -8;
    goto fail;
  }

  /*
     alloc a new buffer for q->image. We avoid realloc(3) because we want
     on failure to be leave `q` in a consistant, unmodified state.
  */
  //image = (uint8_t*)calloc(w, h);
  image = (uint8_t*)heap_caps_malloc(w*h,MALLOC_CAP_SPIRAM);
  if (!image) {
    Serial.printf("largest free block=%d\n", heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
    ret = -9;
    goto fail;
  }

  /* compute the "old" (i.e. currently allocated) and the "new"
     (i.e. requested) image dimensions */
  olddim = q->w * q->h;
  newdim = w * h;
  min = (olddim < newdim ? olddim : newdim);

  /*
     copy the data into the new buffer, avoiding (a) to read beyond the
     old buffer when the new size is greater and (b) to write beyond the
     new buffer when the new size is smaller, hence the min computation.
  */
  (void)memcpy(image, q->image, min);

  /* alloc a new buffer for q->pixels if needed */
  if (!QUIRC_PIXEL_ALIAS_IMAGE) {
    pixels = (quirc_pixel_t*)calloc(newdim, sizeof(quirc_pixel_t));
    if (!pixels) {
      ret = -55;
      goto fail;
    }
  }

  /* alloc succeeded, update `q` with the new size and buffers */
  q->w = w;
  q->h = h;
  free(q->image);
  q->image = image;
  if (!QUIRC_PIXEL_ALIAS_IMAGE) {
    free(q->pixels);
    q->pixels = pixels;
  }

  return 0;
  /* NOTREACHED */
fail:
  free(image);
  free(pixels);

  return ret;
}

static esp_err_t stream_handler(httpd_req_t *req) {
...
  qr_recognizer = quirc_new();
  if (!qr_recognizer) {
    res = ESP_FAIL;
    return res;
  }

  httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  while (true) {
...
            fr_ready = esp_timer_get_time();
            if (detection_enabled) {
              bool donext = false;
              if (old_width != fb->width || old_height != fb->height) {
                Serial.println("Resize the QR-code recognizer.");
                // Resize the QR-code recognizer.
                Serial.printf("step-3 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-3 HeapSize = %d\n", xPortGetFreeHeapSize());
                int ret = q_resize(qr_recognizer, fb->width, fb->height) ;
                Serial.printf("step-4 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-4 HeapSize = %d\n", xPortGetFreeHeapSize());
                if (ret < 0) {
                  Serial.printf("ret=%d,w=%d,h=%d\n", ret, fb->width, fb->height);
                  Serial.println("Resize the QR-code recognizer err.");
                } else {
                  old_width = fb->width;
                  old_height = fb->height;
                  donext = true;
                }
              }
              else {
                donext = true;
              }
              if (donext) {
                Serial.printf("step-5 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-5 HeapSize = %d\n", xPortGetFreeHeapSize());
                image = quirc_begin(qr_recognizer, NULL, NULL);
                Serial.printf("step-6 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-6 HeapSize = %d\n", xPortGetFreeHeapSize());
                rgb2grayscale((rgb_t*)image_matrix->item, image, fb->width * fb->height);
                dl_matrix3du_free(image_matrix);
                Serial.printf("step-7 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-7 HeapSize = %d\n", xPortGetFreeHeapSize());
                fr_face = esp_timer_get_time();
                fr_recognize = fr_face;
                Serial.printf("step-8 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-8 HeapSize = %d\n", xPortGetFreeHeapSize());
                quirc_end(qr_recognizer);//<---------something unknown happened 
                Serial.printf("step-9 StackSize = %d\n", uxTaskGetStackHighWaterMark( NULL ));
                Serial.printf("step-9 HeapSize = %d\n", xPortGetFreeHeapSize());
                fr_recognize = esp_timer_get_time();
                // Return the number of QR-codes identified in the last processed image.
                id_count = quirc_count(qr_recognizer);
                if (0 == id_count) {
                  Serial.println("Error: not a valid qrcode");
                }
                else {
                  for (int qri = 0; qri < id_count; qri++) {
                    quirc_decode_error_t err;
                    quirc_extract(qr_recognizer, qri, &code);
                    // Decoding stage
                    err = quirc_decode(&code, &data);
                    if (err) {
                      Serial.printf("DECODE FAILED:%d\n", quirc_strerror(err));
                    }
                    else {
                      detected = true;
                      Serial.printf("Data:%s\n", (char*)data.payload);
                    }
                  }
                }
              }//if(donext)
            }//if (detection_enabled) 
            /*
              box_array_t *net_boxes = NULL;
              if(detection_enabled){
                net_boxes = face_detect(image_matrix, &mtmn_config);
              }
              if (net_boxes || fb->format != PIXFORMAT_JPEG){
                if(net_boxes){
                    detected = true;
                    if(recognition_enabled){
                        face_id = run_face_recognition(image_matrix, net_boxes);
                    }
                    fr_recognize = esp_timer_get_time();
                    draw_face_boxes(image_matrix, net_boxes, face_id);
                    free(net_boxes->score);
                    free(net_boxes->box);
                    free(net_boxes->landmark);
                    free(net_boxes);
                }
                if(!fmt2jpg(image_matrix->item, fb->width*fb->height*3, fb->width, fb->height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len)){
                    Serial.println("fmt2jpg failed");
                    res = ESP_FAIL;
                }
                esp_camera_fb_return(fb);
                fb = NULL;
              } else {
                _jpg_buf = fb->buf;
                _jpg_buf_len = fb->len;
              }
            */
            fr_encode = esp_timer_get_time();

Debug Messages:

step-1 StackSize = 1868
step-1 HeapSize = 3397760
step-2 StackSize = 1868
step-2 HeapSize = 3050480
step-5 StackSize = 1868
step-5 HeapSize = 3052072
step-6 StackSize = 1868
step-6 HeapSize = 3052072
step-7 StackSize = 1868
step-7 HeapSize = 3407332
step-8 StackSize = 1868
step-8 HeapSize = 3407332
step-9 StackSize = 1868
step-9 HeapSize = 3407332
Error: not a valid qrcode
step-1 StackSize = 1868
step-1 HeapSize = 3404152
step-2 StackSize = 1868
step-2 HeapSize = 3050012
step-5 StackSize = 1868
step-5 HeapSize = 3052076
step-6 StackSize = 1868
step-6 HeapSize = 3052076
step-7 StackSize = 1868
step-7 HeapSize = 3407332
step-8 StackSize = 1868
step-8 HeapSize = 3407332
Guru Meditation Error: Core  0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x4008ebaa  PS      : 0x00060233  A0      : 0x80090a36  A1      : 0x3ffd8610  
A2      : 0x00000001  A3      : 0x0000cdcd  A4      : 0xb33fffff  A5      : 0x00000001  
A6      : 0x00060220  A7      : 0x0000abab  A8      : 0x0000cdcd  A9      : 0x3ffd8610  
A10     : 0x00000003  A11     : 0x00060223  A12     : 0x00060220  A13     : 0x00000001  
A14     : 0x00060020  A15     : 0x00000000  SAR     : 0x00000018  EXCCAUSE: 0x0000001d  
EXCVADDR: 0x00000001  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0xffffffff  

Backtrace: 0x4008ebaa:0x3ffd8610 0x40090a33:0x3ffd8640 0x400911c3:0x3ffd8660 0x400872d8:0x3ffd8680 0x4008730d:0x3ffd86a0 0x40087891:0x3ffd86c0 0x4000beaf:0x3ffd86e0 0x400819b9:0x3ffd8700 0x40148593:0x3ffd8720 0x40152cd9:0x3ffd8760 0x400947c5:0x3ffd87e0 0x4008db91:0x3ffd8820

Rebooting...

=======================
ESP Exception Decoder:

PC: 0x4008ebaa: vTaskEnterCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/include/freertos/portmacro.h line 285
EXCVADDR: 0x00000001

Decoding stack results
0x4008ebaa: vTaskEnterCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/include/freertos/portmacro.h line 285
0x40090a33: multi_heap_internal_lock at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap.c line 375
0x400911c3: multi_heap_malloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 190
0x400872d8: heap_caps_malloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 111
0x4008730d: heap_caps_malloc_default at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 140
0x40087891: _malloc_r at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/syscalls.c line 37
0x400819b9: wifi_malloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/esp_adapter.c line 68
0x4008db91: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143
p2o5 commented 4 years ago

@me-no-dev I did have post source code in my issue,top of it ,here is the link(https://github.com/espressif/arduino-esp32/files/4116182/ESP32-Cam_CameraWebServer.zip), Please try it

stale[bot] commented 4 years ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.

modiestas commented 1 year ago

@p2o5 Did you find solution?