mirror of
https://github.com/espressif/esp32-camera.git
synced 2025-08-06 16:40:19 +08:00
fix grayscale mode
Fixes https://github.com/espressif/esp32-camera/issues/276
This commit is contained in:
@ -29,6 +29,14 @@ static int cam_verify_jpeg_soi(const uint8_t *inbuf, uint32_t length)
|
|||||||
{
|
{
|
||||||
uint32_t sig = *((uint32_t *)inbuf) & 0xFFFFFF;
|
uint32_t sig = *((uint32_t *)inbuf) & 0xFFFFFF;
|
||||||
if(sig != JPEG_SOI_MARKER) {
|
if(sig != JPEG_SOI_MARKER) {
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
sig = *((uint32_t *)(&inbuf[i])) & 0xFFFFFF;
|
||||||
|
if (sig == JPEG_SOI_MARKER) {
|
||||||
|
ESP_LOGW(TAG, "SOI: %d", i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGW(TAG, "NO-SOI");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -42,6 +50,7 @@ static int cam_verify_jpeg_eoi(const uint8_t *inbuf, uint32_t length)
|
|||||||
uint16_t sig = *((uint16_t *)dptr);
|
uint16_t sig = *((uint16_t *)dptr);
|
||||||
if (JPEG_EOI_MARKER == sig) {
|
if (JPEG_EOI_MARKER == sig) {
|
||||||
offset = dptr - inbuf;
|
offset = dptr - inbuf;
|
||||||
|
//ESP_LOGW(TAG, "EOI: %d", length - (offset + 2));
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
dptr--;
|
dptr--;
|
||||||
@ -117,16 +126,17 @@ static void cam_task(void *arg)
|
|||||||
|
|
||||||
case CAM_STATE_READ_BUF: {
|
case CAM_STATE_READ_BUF: {
|
||||||
camera_fb_t * frame_buffer_event = &cam_obj->frames[frame_pos].fb;
|
camera_fb_t * frame_buffer_event = &cam_obj->frames[frame_pos].fb;
|
||||||
|
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);
|
||||||
|
|
||||||
if (cam_event == CAM_IN_SUC_EOF_EVENT) {
|
if (cam_event == CAM_IN_SUC_EOF_EVENT) {
|
||||||
if(!cam_obj->psram_mode){
|
if(!cam_obj->psram_mode){
|
||||||
if (cam_obj->recv_size < (frame_buffer_event->len + (cam_obj->dma_half_buffer_size / cam_obj->dma_bytes_per_item))) {
|
if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) {
|
||||||
ESP_LOGW(TAG, "FB-OVF");
|
ESP_LOGW(TAG, "FB-OVF");
|
||||||
ll_cam_stop(cam_obj);
|
ll_cam_stop(cam_obj);
|
||||||
DBG_PIN_SET(0);
|
DBG_PIN_SET(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
frame_buffer_event->len += ll_cam_memcpy(
|
frame_buffer_event->len += ll_cam_memcpy(cam_obj,
|
||||||
&frame_buffer_event->buf[frame_buffer_event->len],
|
&frame_buffer_event->buf[frame_buffer_event->len],
|
||||||
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
|
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
|
||||||
cam_obj->dma_half_buffer_size);
|
cam_obj->dma_half_buffer_size);
|
||||||
@ -135,7 +145,6 @@ static void cam_task(void *arg)
|
|||||||
if (cam_obj->jpeg_mode && cnt == 0 && cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len) != 0) {
|
if (cam_obj->jpeg_mode && cnt == 0 && cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len) != 0) {
|
||||||
ll_cam_stop(cam_obj);
|
ll_cam_stop(cam_obj);
|
||||||
cam_obj->state = CAM_STATE_IDLE;
|
cam_obj->state = CAM_STATE_IDLE;
|
||||||
ESP_LOGW(TAG, "NO-SOI");
|
|
||||||
}
|
}
|
||||||
cnt++;
|
cnt++;
|
||||||
|
|
||||||
@ -146,11 +155,11 @@ static void cam_task(void *arg)
|
|||||||
if (cnt || !cam_obj->jpeg_mode || cam_obj->psram_mode) {
|
if (cnt || !cam_obj->jpeg_mode || cam_obj->psram_mode) {
|
||||||
if (cam_obj->jpeg_mode) {
|
if (cam_obj->jpeg_mode) {
|
||||||
if (!cam_obj->psram_mode) {
|
if (!cam_obj->psram_mode) {
|
||||||
if (cam_obj->recv_size < (frame_buffer_event->len + (cam_obj->dma_half_buffer_size / cam_obj->dma_bytes_per_item))) {
|
if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) {
|
||||||
ESP_LOGW(TAG, "FB-OVF");
|
ESP_LOGW(TAG, "FB-OVF");
|
||||||
cnt--;
|
cnt--;
|
||||||
} else {
|
} else {
|
||||||
frame_buffer_event->len += ll_cam_memcpy(
|
frame_buffer_event->len += ll_cam_memcpy(cam_obj,
|
||||||
&frame_buffer_event->buf[frame_buffer_event->len],
|
&frame_buffer_event->buf[frame_buffer_event->len],
|
||||||
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
|
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
|
||||||
cam_obj->dma_half_buffer_size);
|
cam_obj->dma_half_buffer_size);
|
||||||
@ -168,9 +177,9 @@ static void cam_task(void *arg)
|
|||||||
frame_buffer_event->len = cam_obj->recv_size;
|
frame_buffer_event->len = cam_obj->recv_size;
|
||||||
}
|
}
|
||||||
} else if (!cam_obj->jpeg_mode) {
|
} else if (!cam_obj->jpeg_mode) {
|
||||||
if (frame_buffer_event->len != cam_obj->recv_size) {
|
if (frame_buffer_event->len != cam_obj->fb_size) {
|
||||||
cam_obj->frames[frame_pos].en = 1;
|
cam_obj->frames[frame_pos].en = 1;
|
||||||
ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, cam_obj->recv_size);
|
ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, cam_obj->fb_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//send frame
|
//send frame
|
||||||
@ -242,14 +251,18 @@ static esp_err_t cam_dma_config()
|
|||||||
CAM_CHECK(cam_obj->frames != NULL, "frames malloc failed", ESP_FAIL);
|
CAM_CHECK(cam_obj->frames != NULL, "frames malloc failed", ESP_FAIL);
|
||||||
|
|
||||||
uint8_t dma_align = 0;
|
uint8_t dma_align = 0;
|
||||||
|
size_t fb_size = cam_obj->fb_size;
|
||||||
if (cam_obj->psram_mode) {
|
if (cam_obj->psram_mode) {
|
||||||
dma_align = ll_cam_get_dma_align(cam_obj);
|
dma_align = ll_cam_get_dma_align(cam_obj);
|
||||||
|
if (cam_obj->fb_size < cam_obj->recv_size) {
|
||||||
|
fb_size = cam_obj->recv_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int x = 0; x < cam_obj->frame_cnt; x++) {
|
for (int x = 0; x < cam_obj->frame_cnt; x++) {
|
||||||
cam_obj->frames[x].dma = NULL;
|
cam_obj->frames[x].dma = NULL;
|
||||||
cam_obj->frames[x].fb_offset = 0;
|
cam_obj->frames[x].fb_offset = 0;
|
||||||
cam_obj->frames[x].en = 0;
|
cam_obj->frames[x].en = 0;
|
||||||
cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_malloc(cam_obj->recv_size * sizeof(uint8_t) + dma_align, MALLOC_CAP_SPIRAM);
|
cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_malloc(fb_size * sizeof(uint8_t) + dma_align, MALLOC_CAP_SPIRAM);
|
||||||
CAM_CHECK(cam_obj->frames[x].fb.buf != NULL, "frame buffer malloc failed", ESP_FAIL);
|
CAM_CHECK(cam_obj->frames[x].fb.buf != NULL, "frame buffer malloc failed", ESP_FAIL);
|
||||||
if (cam_obj->psram_mode) {
|
if (cam_obj->psram_mode) {
|
||||||
//align PSRAM buffer. TODO: save the offset so proper address can be freed later
|
//align PSRAM buffer. TODO: save the offset so proper address can be freed later
|
||||||
@ -323,8 +336,10 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
|
|||||||
|
|
||||||
if(cam_obj->jpeg_mode){
|
if(cam_obj->jpeg_mode){
|
||||||
cam_obj->recv_size = cam_obj->width * cam_obj->height / 5;
|
cam_obj->recv_size = cam_obj->width * cam_obj->height / 5;
|
||||||
|
cam_obj->fb_size = cam_obj->recv_size;
|
||||||
} else {
|
} else {
|
||||||
cam_obj->recv_size = cam_obj->width * cam_obj->height * 2;
|
cam_obj->recv_size = cam_obj->width * cam_obj->height * cam_obj->in_bytes_per_pixel;
|
||||||
|
cam_obj->fb_size = cam_obj->width * cam_obj->height * cam_obj->fb_bytes_per_pixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cam_dma_config();
|
ret = cam_dma_config();
|
||||||
@ -431,6 +446,9 @@ camera_fb_t *cam_take(TickType_t timeout)
|
|||||||
cam_give(dma_buffer);
|
cam_give(dma_buffer);
|
||||||
return cam_take(timeout - (xTaskGetTickCount() - start));//recurse!!!!
|
return cam_take(timeout - (xTaskGetTickCount() - start));//recurse!!!!
|
||||||
}
|
}
|
||||||
|
} else if(cam_obj->psram_mode && cam_obj->in_bytes_per_pixel != cam_obj->fb_bytes_per_pixel){
|
||||||
|
//currently this is used only for YUV to GRAYSCALE
|
||||||
|
dma_buffer->len = ll_cam_memcpy(cam_obj, dma_buffer->buf, dma_buffer->buf, dma_buffer->len);
|
||||||
}
|
}
|
||||||
return dma_buffer;
|
return dma_buffer;
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,7 +138,7 @@ static size_t IRAM_ATTR ll_cam_dma_filter_grayscale_highspeed(uint8_t* dst, cons
|
|||||||
dst[1] = dma_el[2].sample1;
|
dst[1] = dma_el[2].sample1;
|
||||||
elements += 1;
|
elements += 1;
|
||||||
}
|
}
|
||||||
return elements * 2;
|
return elements / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t IRAM_ATTR ll_cam_dma_filter_yuyv(uint8_t* dst, const uint8_t* src, size_t len)
|
static size_t IRAM_ATTR ll_cam_dma_filter_yuyv(uint8_t* dst, const uint8_t* src, size_t len)
|
||||||
@ -451,7 +451,7 @@ void ll_cam_dma_sizes(cam_obj_t *cam)
|
|||||||
|
|
||||||
static dma_filter_t dma_filter = ll_cam_dma_filter_jpeg;
|
static dma_filter_t dma_filter = ll_cam_dma_filter_jpeg;
|
||||||
|
|
||||||
size_t IRAM_ATTR ll_cam_memcpy(uint8_t *out, const uint8_t *in, size_t len)
|
size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len)
|
||||||
{
|
{
|
||||||
//DBG_PIN_SET(1);
|
//DBG_PIN_SET(1);
|
||||||
size_t r = dma_filter(out, in, len);
|
size_t r = dma_filter(out, in, len);
|
||||||
|
@ -344,8 +344,23 @@ void ll_cam_dma_sizes(cam_obj_t *cam)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ll_cam_memcpy(uint8_t *out, const uint8_t *in, size_t len)
|
size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len)
|
||||||
{
|
{
|
||||||
|
// YUV to Grayscale
|
||||||
|
if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) {
|
||||||
|
size_t end = len / 8;
|
||||||
|
for (size_t i = 0; i < end; ++i) {
|
||||||
|
out[0] = in[0];
|
||||||
|
out[1] = in[2];
|
||||||
|
out[2] = in[4];
|
||||||
|
out[3] = in[6];
|
||||||
|
out += 4;
|
||||||
|
in += 8;
|
||||||
|
}
|
||||||
|
return len / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just memcpy
|
||||||
memcpy(out, in, len);
|
memcpy(out, in, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ void ll_cam_do_vsync(cam_obj_t *cam)
|
|||||||
|
|
||||||
uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
|
uint8_t ll_cam_get_dma_align(cam_obj_t *cam)
|
||||||
{
|
{
|
||||||
return 64;//16 << GDMA.in[cam->dma_num].conf1.in_ext_mem_bk_size;
|
return 16 << GDMA.in[cam->dma_num].conf1.in_ext_mem_bk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ll_cam_calc_rgb_dma(cam_obj_t *cam){
|
static void ll_cam_calc_rgb_dma(cam_obj_t *cam){
|
||||||
@ -361,8 +361,23 @@ void ll_cam_dma_sizes(cam_obj_t *cam)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ll_cam_memcpy(uint8_t *out, const uint8_t *in, size_t len)
|
size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len)
|
||||||
{
|
{
|
||||||
|
// YUV to Grayscale
|
||||||
|
if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) {
|
||||||
|
size_t end = len / 8;
|
||||||
|
for (size_t i = 0; i < end; ++i) {
|
||||||
|
out[0] = in[0];
|
||||||
|
out[1] = in[2];
|
||||||
|
out[2] = in[4];
|
||||||
|
out[3] = in[6];
|
||||||
|
out += 4;
|
||||||
|
in += 8;
|
||||||
|
}
|
||||||
|
return len / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just memcpy
|
||||||
memcpy(out, in, len);
|
memcpy(out, in, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ typedef struct {
|
|||||||
uint16_t height;
|
uint16_t height;
|
||||||
uint8_t in_bytes_per_pixel;
|
uint8_t in_bytes_per_pixel;
|
||||||
uint8_t fb_bytes_per_pixel;
|
uint8_t fb_bytes_per_pixel;
|
||||||
|
uint32_t fb_size;
|
||||||
|
|
||||||
cam_state_t state;
|
cam_state_t state;
|
||||||
} cam_obj_t;
|
} cam_obj_t;
|
||||||
@ -128,7 +129,7 @@ esp_err_t ll_cam_init_isr(cam_obj_t *cam);
|
|||||||
void ll_cam_do_vsync(cam_obj_t *cam);
|
void ll_cam_do_vsync(cam_obj_t *cam);
|
||||||
uint8_t ll_cam_get_dma_align(cam_obj_t *cam);
|
uint8_t ll_cam_get_dma_align(cam_obj_t *cam);
|
||||||
void ll_cam_dma_sizes(cam_obj_t *cam);
|
void ll_cam_dma_sizes(cam_obj_t *cam);
|
||||||
size_t ll_cam_memcpy(uint8_t *out, const uint8_t *in, size_t len);
|
size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len);
|
||||||
esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint8_t sensor_pid);
|
esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint8_t sensor_pid);
|
||||||
|
|
||||||
// implemented in cam_hal
|
// implemented in cam_hal
|
||||||
|
Reference in New Issue
Block a user