Skip to content

Commit 7e51ff7

Browse files
authored
Merge pull request #2 from MicroDev1/master
Merge upstream updates
2 parents 54c3f61 + 80b5754 commit 7e51ff7

File tree

14 files changed

+228
-110
lines changed

14 files changed

+228
-110
lines changed

.github/workflows/build.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,25 @@ jobs:
2222
target: ${{ matrix.idf_target }}
2323
path: 'examples'
2424

25+
build-release-v5_0:
26+
name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }}
27+
runs-on: ubuntu-latest
28+
strategy:
29+
matrix:
30+
idf_ver: ["release-v5.0"]
31+
idf_target: ["esp32", "esp32s2", "esp32s3"]
32+
steps:
33+
- name: Checkout repo
34+
uses: actions/checkout@v2
35+
with:
36+
submodules: 'recursive'
37+
- name: esp-idf build
38+
uses: espressif/esp-idf-ci-action@main
39+
with:
40+
esp_idf_version: ${{ matrix.idf_ver }}
41+
target: ${{ matrix.idf_target }}
42+
path: 'examples'
43+
2544
build-release-v4_4:
2645
name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }}
2746
runs-on: ubuntu-latest

Kconfig

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ menu "Camera configuration"
142142
bool "Subsample Mode"
143143
endchoice
144144

145+
config CAMERA_TASK_STACK_SIZE
146+
int "CAM task stack size"
147+
default 2048
148+
help
149+
Camera task stack size
150+
145151
choice CAMERA_TASK_PINNED_TO_CORE
146152
bool "Camera task pinned to core"
147153
default CAMERA_CORE0
@@ -163,8 +169,8 @@ menu "Camera configuration"
163169
default 32768
164170
help
165171
Maximum value of DMA buffer
166-
Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent
167-
172+
Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent.
173+
168174
config CAMERA_CONVERTER_ENABLED
169175
bool "Enable camera RGB/YUV converter"
170176
depends on IDF_TARGET_ESP32S3
@@ -184,4 +190,16 @@ menu "Camera configuration"
184190
config LCD_CAM_CONV_BT709_ENABLED
185191
bool "BT709"
186192
endchoice
193+
194+
config LCD_CAM_CONV_FULL_RANGE_ENABLED
195+
bool "Camera converter full range mode"
196+
depends on CAMERA_CONVERTER_ENABLED
197+
default y
198+
help
199+
Supports format conversion under both full color range mode and limited color range mode.
200+
If full color range mode is selected, the color range of RGB or YUV is 0~255.
201+
If limited color range mode is selected, the color range of RGB is 16~240, and the color range of YUV is Y[16~240], UV[16~235].
202+
Full color range mode has a wider color range, so details in the image show more clearly.
203+
Please confirm the color range mode of the current camera sensor, incorrect color range mode may cause color difference in the final converted image.
204+
Full range mode is used by default. If this option is not selected, the format conversion function will be done using the limited range mode.
187205
endmenu

conversions/to_bmp.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,13 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
302302
*out_len = 0;
303303

304304
int pix_count = width*height;
305-
size_t out_size = (pix_count * 3) + BMP_HEADER_LEN;
305+
306+
// With BMP, 8-bit greyscale requires a palette.
307+
// For a 640x480 image though, that's a savings
308+
// over going RGB-24.
309+
int bpp = (format == PIXFORMAT_GRAYSCALE) ? 1 : 3;
310+
int palette_size = (format == PIXFORMAT_GRAYSCALE) ? 4 * 256 : 0;
311+
size_t out_size = (pix_count * bpp) + BMP_HEADER_LEN + palette_size;
306312
uint8_t * out_buf = (uint8_t *)_malloc(out_size);
307313
if(!out_buf) {
308314
ESP_LOGE(TAG, "_malloc failed! %u", out_size);
@@ -314,45 +320,51 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
314320
bmp_header_t * bitmap = (bmp_header_t*)&out_buf[2];
315321
bitmap->reserved = 0;
316322
bitmap->filesize = out_size;
317-
bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN;
323+
bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN + palette_size;
318324
bitmap->dibheadersize = 40;
319325
bitmap->width = width;
320326
bitmap->height = -height;//set negative for top to bottom
321327
bitmap->planes = 1;
322-
bitmap->bitsperpixel = 24;
328+
bitmap->bitsperpixel = bpp * 8;
323329
bitmap->compression = 0;
324-
bitmap->imagesize = pix_count * 3;
330+
bitmap->imagesize = pix_count * bpp;
325331
bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
326332
bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
327333
bitmap->numcolorspallette = 0;
328334
bitmap->mostimpcolor = 0;
329335

330-
uint8_t * rgb_buf = out_buf + BMP_HEADER_LEN;
336+
uint8_t * palette_buf = out_buf + BMP_HEADER_LEN;
337+
uint8_t * pix_buf = palette_buf + palette_size;
331338
uint8_t * src_buf = src;
332339

340+
if (palette_size > 0) {
341+
// Grayscale palette
342+
for (int i = 0; i < 256; ++i) {
343+
for (int j = 0; j < 3; ++j) {
344+
*palette_buf = i;
345+
palette_buf++;
346+
}
347+
// Reserved / alpha channel.
348+
*palette_buf = 0;
349+
palette_buf++;
350+
}
351+
}
333352

334353
//convert data to RGB888
335354
if(format == PIXFORMAT_RGB888) {
336-
memcpy(rgb_buf, src_buf, pix_count*3);
355+
memcpy(pix_buf, src_buf, pix_count*3);
337356
} else if(format == PIXFORMAT_RGB565) {
338357
int i;
339358
uint8_t hb, lb;
340359
for(i=0; i<pix_count; i++) {
341360
hb = *src_buf++;
342361
lb = *src_buf++;
343-
*rgb_buf++ = (lb & 0x1F) << 3;
344-
*rgb_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
345-
*rgb_buf++ = hb & 0xF8;
362+
*pix_buf++ = (lb & 0x1F) << 3;
363+
*pix_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
364+
*pix_buf++ = hb & 0xF8;
346365
}
347366
} else if(format == PIXFORMAT_GRAYSCALE) {
348-
int i;
349-
uint8_t b;
350-
for(i=0; i<pix_count; i++) {
351-
b = *src_buf++;
352-
*rgb_buf++ = b;
353-
*rgb_buf++ = b;
354-
*rgb_buf++ = b;
355-
}
367+
memcpy(pix_buf, src_buf, pix_count);
356368
} else if(format == PIXFORMAT_YUV422) {
357369
int i, maxi = pix_count / 2;
358370
uint8_t y0, y1, u, v;
@@ -364,14 +376,14 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
364376
v = *src_buf++;
365377

366378
yuv2rgb(y0, u, v, &r, &g, &b);
367-
*rgb_buf++ = b;
368-
*rgb_buf++ = g;
369-
*rgb_buf++ = r;
379+
*pix_buf++ = b;
380+
*pix_buf++ = g;
381+
*pix_buf++ = r;
370382

371383
yuv2rgb(y1, u, v, &r, &g, &b);
372-
*rgb_buf++ = b;
373-
*rgb_buf++ = g;
374-
*rgb_buf++ = r;
384+
*pix_buf++ = b;
385+
*pix_buf++ = g;
386+
*pix_buf++ = r;
375387
}
376388
}
377389
*out = out_buf;

driver/cam_hal.c

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
#endif // ESP_IDF_VERSION_MAJOR
3333
#define ESP_CAMERA_ETS_PRINTF ets_printf
3434

35+
#if CONFIG_CAM_TASK_STACK_SIZE
36+
#define CAM_TASK_STACK CONFIG_CAM_TASK_STACK_SIZE
37+
#else
38+
#define CAM_TASK_STACK (2*1024)
39+
#endif
40+
3541
static const char *TAG = "cam_hal";
3642
static cam_obj_t *cam_obj = NULL;
3743

@@ -45,7 +51,7 @@ static int cam_verify_jpeg_soi(const uint8_t *inbuf, uint32_t length)
4551
for (uint32_t i = 0; i < length; i++) {
4652
sig = *((uint32_t *)(&inbuf[i])) & 0xFFFFFF;
4753
if (sig == JPEG_SOI_MARKER) {
48-
ESP_LOGW(TAG, "SOI: %d", i);
54+
ESP_LOGW(TAG, "SOI: %d", (int) i);
4955
return i;
5056
}
5157
}
@@ -117,7 +123,7 @@ static void cam_task(void *arg)
117123
int frame_pos = 0;
118124
cam_obj->state = CAM_STATE_IDLE;
119125
cam_event_t cam_event = 0;
120-
126+
121127
xQueueReset(cam_obj->event_queue);
122128

123129
while (1) {
@@ -140,7 +146,7 @@ static void cam_task(void *arg)
140146
case CAM_STATE_READ_BUF: {
141147
camera_fb_t * frame_buffer_event = &cam_obj->frames[frame_pos].fb;
142148
size_t pixels_per_dma = (cam_obj->dma_half_buffer_size * cam_obj->fb_bytes_per_pixel) / (cam_obj->dma_bytes_per_item * cam_obj->in_bytes_per_pixel);
143-
149+
144150
if (cam_event == CAM_IN_SUC_EOF_EVENT) {
145151
if(!cam_obj->psram_mode){
146152
if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) {
@@ -150,8 +156,8 @@ static void cam_task(void *arg)
150156
continue;
151157
}
152158
frame_buffer_event->len += ll_cam_memcpy(cam_obj,
153-
&frame_buffer_event->buf[frame_buffer_event->len],
154-
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
159+
&frame_buffer_event->buf[frame_buffer_event->len],
160+
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
155161
cam_obj->dma_half_buffer_size);
156162
}
157163
//Check for JPEG SOI in the first buffer. stop if not found
@@ -173,8 +179,8 @@ static void cam_task(void *arg)
173179
cnt--;
174180
} else {
175181
frame_buffer_event->len += ll_cam_memcpy(cam_obj,
176-
&frame_buffer_event->buf[frame_buffer_event->len],
177-
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
182+
&frame_buffer_event->buf[frame_buffer_event->len],
183+
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
178184
cam_obj->dma_half_buffer_size);
179185
}
180186
}
@@ -192,7 +198,7 @@ static void cam_task(void *arg)
192198
} else if (!cam_obj->jpeg_mode) {
193199
if (frame_buffer_event->len != cam_obj->fb_size) {
194200
cam_obj->frames[frame_pos].en = 1;
195-
ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, cam_obj->fb_size);
201+
ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, (unsigned) cam_obj->fb_size);
196202
}
197203
}
198204
//send frame
@@ -258,8 +264,9 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
258264
cam_obj->dma_node_cnt = (cam_obj->dma_buffer_size) / cam_obj->dma_node_buffer_size; // Number of DMA nodes
259265
cam_obj->frame_copy_cnt = cam_obj->recv_size / cam_obj->dma_half_buffer_size; // Number of interrupted copies, ping-pong copy
260266

261-
ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d",
262-
cam_obj->dma_buffer_size, cam_obj->dma_half_buffer_size, cam_obj->dma_node_buffer_size, cam_obj->dma_node_cnt, cam_obj->frame_copy_cnt);
267+
ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d",
268+
(int) cam_obj->dma_buffer_size, (int) cam_obj->dma_half_buffer_size, (int) cam_obj->dma_node_buffer_size,
269+
(int) cam_obj->dma_node_cnt, (int) cam_obj->frame_copy_cnt);
263270

264271
cam_obj->dma_buffer = NULL;
265272
cam_obj->dma = NULL;
@@ -289,13 +296,19 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
289296
cam_obj->frames[x].fb_offset = 0;
290297
cam_obj->frames[x].en = 0;
291298
ESP_LOGI(TAG, "Allocating %d Byte frame buffer in %s", alloc_size, _caps & MALLOC_CAP_SPIRAM ? "PSRAM" : "OnBoard RAM");
299+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
300+
// In IDF v4.2 and earlier, memory returned by heap_caps_aligned_alloc must be freed using heap_caps_aligned_free.
301+
// And heap_caps_aligned_free is deprecated on v4.3.
302+
cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_aligned_alloc(16, alloc_size, _caps);
303+
#else
292304
cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_malloc(alloc_size, _caps);
305+
#endif
293306
CAM_CHECK(cam_obj->frames[x].fb.buf != NULL, "frame buffer malloc failed", ESP_FAIL);
294307
if (cam_obj->psram_mode) {
295308
//align PSRAM buffer. TODO: save the offset so proper address can be freed later
296309
cam_obj->frames[x].fb_offset = dma_align - ((uint32_t)cam_obj->frames[x].fb.buf & (dma_align - 1));
297310
cam_obj->frames[x].fb.buf += cam_obj->frames[x].fb_offset;
298-
ESP_LOGI(TAG, "Frame[%d]: Offset: %u, Addr: 0x%08X", x, cam_obj->frames[x].fb_offset, (uint32_t)cam_obj->frames[x].fb.buf);
311+
ESP_LOGI(TAG, "Frame[%d]: Offset: %u, Addr: 0x%08X", x, cam_obj->frames[x].fb_offset, (unsigned) cam_obj->frames[x].fb.buf);
299312
cam_obj->frames[x].dma = allocate_dma_descriptors(cam_obj->dma_node_cnt, cam_obj->dma_node_buffer_size, cam_obj->frames[x].fb.buf);
300313
CAM_CHECK(cam_obj->frames[x].dma != NULL, "frame dma malloc failed", ESP_FAIL);
301314
}
@@ -305,8 +318,8 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
305318
if (!cam_obj->psram_mode) {
306319
cam_obj->dma_buffer = (uint8_t *)heap_caps_malloc(cam_obj->dma_buffer_size * sizeof(uint8_t), MALLOC_CAP_DMA);
307320
if(NULL == cam_obj->dma_buffer) {
308-
ESP_LOGE(TAG,"%s(%d): DMA buffer %d Byte malloc failed, the current largest free block:%d Byte", __FUNCTION__, __LINE__,
309-
cam_obj->dma_buffer_size, heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
321+
ESP_LOGE(TAG,"%s(%d): DMA buffer %d Byte malloc failed, the current largest free block:%d Byte", __FUNCTION__, __LINE__,
322+
(int) cam_obj->dma_buffer_size, (int) heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
310323
return ESP_FAIL;
311324
}
312325

@@ -372,7 +385,7 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
372385
cam_obj->recv_size = cam_obj->width * cam_obj->height * cam_obj->in_bytes_per_pixel;
373386
cam_obj->fb_size = cam_obj->width * cam_obj->height * cam_obj->fb_bytes_per_pixel;
374387
}
375-
388+
376389
ret = cam_dma_config(config);
377390
CAM_CHECK_GOTO(ret == ESP_OK, "cam_dma_config failed", err);
378391

@@ -389,16 +402,16 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
389402
ret = ll_cam_init_isr(cam_obj);
390403
CAM_CHECK_GOTO(ret == ESP_OK, "cam intr alloc failed", err);
391404

392-
405+
393406
#if CONFIG_CAMERA_CORE0
394-
xTaskCreatePinnedToCore(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0);
407+
xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0);
395408
#elif CONFIG_CAMERA_CORE1
396409
#if CONFIG_FREERTOS_UNICORE
397410
#error "Cannot pin to core 1 on unicore"
398411
#endif
399-
xTaskCreatePinnedToCore(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1);
412+
xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1);
400413
#else
401-
xTaskCreate(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle);
414+
xTaskCreate(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle);
402415
#endif
403416

404417
ESP_LOGI(TAG, "cam config ok");

driver/esp_camera.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static const sensor_func_t g_sensors[] = {
141141

142142
static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model)
143143
{
144+
esp_err_t ret = ESP_OK;
144145
*out_camera_model = CAMERA_NONE;
145146
if (s_state != NULL) {
146147
return ESP_ERR_INVALID_STATE;
@@ -158,10 +159,15 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
158159

159160
if (config->pin_sccb_sda != -1) {
160161
ESP_LOGD(TAG, "Initializing SCCB");
161-
SCCB_Init(config->pin_sccb_sda, config->pin_sccb_scl);
162+
ret = SCCB_Init(config->pin_sccb_sda, config->pin_sccb_scl);
162163
} else {
163164
ESP_LOGD(TAG, "Using existing I2C port");
164-
SCCB_Use_Port(config->sccb_i2c_port);
165+
ret = SCCB_Use_Port(config->sccb_i2c_port);
166+
}
167+
168+
if(ret != ESP_OK) {
169+
ESP_LOGE(TAG, "sccb init err");
170+
goto err;
165171
}
166172

167173
if (config->pin_pwdn >= 0) {
@@ -191,15 +197,14 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
191197
vTaskDelay(10 / portTICK_PERIOD_MS);
192198
}
193199

194-
195200
ESP_LOGD(TAG, "Searching for camera address");
196201
vTaskDelay(10 / portTICK_PERIOD_MS);
197202

198203
uint8_t slv_addr = SCCB_Probe();
199204

200205
if (slv_addr == 0) {
201-
CAMERA_DISABLE_OUT_CLOCK();
202-
return ESP_ERR_NOT_FOUND;
206+
ret = ESP_ERR_NOT_FOUND;
207+
goto err;
203208
}
204209

205210
ESP_LOGI(TAG, "Detected camera at address=0x%02x", slv_addr);
@@ -224,19 +229,21 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
224229
}
225230

226231
if (CAMERA_NONE == *out_camera_model) { //If no supported sensors are detected
227-
CAMERA_DISABLE_OUT_CLOCK();
228232
ESP_LOGE(TAG, "Detected camera not supported.");
229-
return ESP_ERR_NOT_SUPPORTED;
233+
ret = ESP_ERR_NOT_SUPPORTED;
234+
goto err;
230235
}
231236

232237
ESP_LOGI(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x",
233238
id->PID, id->VER, id->MIDH, id->MIDL);
234239

235240
ESP_LOGD(TAG, "Doing SW reset of sensor");
236241
vTaskDelay(10 / portTICK_PERIOD_MS);
237-
s_state->sensor.reset(&s_state->sensor);
238242

239-
return ESP_OK;
243+
return s_state->sensor.reset(&s_state->sensor);
244+
err :
245+
CAMERA_DISABLE_OUT_CLOCK();
246+
return ret;
240247
}
241248

242249
#if CONFIG_CAMERA_CONVERTER_ENABLED

0 commit comments

Comments
 (0)