From 98e1a1e51da3a2c57c82c3fab9ca5bc6a010017e Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Tue, 28 Apr 2020 14:36:46 -0700 Subject: [PATCH] Add disable_fb. Allow user control to disable the frame buffer. Necessary for high speed frame streaming. --- src/omv/framebuffer.c | 122 +++++++++++++++++++++------------------ src/omv/framebuffer.h | 6 +- src/omv/py/py_omv.c | 14 ++++- src/omv/py/qstrdefsomv.h | 1 + 4 files changed, 86 insertions(+), 57 deletions(-) diff --git a/src/omv/framebuffer.c b/src/omv/framebuffer.c index 627ac0f80..15035b7d6 100644 --- a/src/omv/framebuffer.c +++ b/src/omv/framebuffer.c @@ -18,6 +18,16 @@ framebuffer_t *fb_framebuffer = (framebuffer_t *) &_fb_base; extern char _jpeg_buf; jpegbuffer_t *jpeg_fb_framebuffer = (jpegbuffer_t *) &_jpeg_buf; +void set_fb_streaming_disabled(bool en) +{ + MAIN_FB()->fb_streaming_disable = en; +} + +bool is_fb_streaming_disabled() +{ + return MAIN_FB()->fb_streaming_disable; +} + int encode_for_ide_new_size(image_t *img) { return (((img->bpp * 8) + 5) / 6) + 2; @@ -82,64 +92,66 @@ void fb_update_jpeg_buffer() { static int overflow_count = 0; - if ((MAIN_FB()->bpp > 3) && JPEG_FB()->enabled) { - bool does_not_fit = false; - // Lock FB - if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) { - if((OMV_JPEG_BUF_SIZE-64) < MAIN_FB()->bpp) { - // image won't fit. so don't copy. - JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0; - does_not_fit = true; - } else { - memcpy(JPEG_FB()->pixels, MAIN_FB()->pixels, MAIN_FB()->bpp); - JPEG_FB()->w = MAIN_FB()->w; JPEG_FB()->h = MAIN_FB()->h; JPEG_FB()->size = MAIN_FB()->bpp; + if ((!MAIN_FB()->fb_streaming_disable) && JPEG_FB()->enabled) { + if (MAIN_FB()->bpp > 3) { + bool does_not_fit = false; + // Lock FB + if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) { + if((OMV_JPEG_BUF_SIZE-64) < MAIN_FB()->bpp) { + // image won't fit. so don't copy. + JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0; + does_not_fit = true; + } else { + memcpy(JPEG_FB()->pixels, MAIN_FB()->pixels, MAIN_FB()->bpp); + JPEG_FB()->w = MAIN_FB()->w; JPEG_FB()->h = MAIN_FB()->h; JPEG_FB()->size = MAIN_FB()->bpp; + } + + // Unlock the framebuffer mutex + mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV); } - - // Unlock the framebuffer mutex - mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV); - } - if (does_not_fit) { - image_t out = { .w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=MAIN_FB()->bpp, .data=MAIN_FB()->pixels }; - int new_size = encode_for_ide_new_size(&out); - fb_alloc_mark(); - uint8_t *temp = fb_alloc(new_size, FB_ALLOC_NO_HINT); - encode_for_ide(temp, &out); - (MP_PYTHON_PRINTER)->print_strn((MP_PYTHON_PRINTER)->data, (const char *) temp, new_size); - fb_alloc_free_till_mark(); - } - } else if ((MAIN_FB()->bpp >= 0) && JPEG_FB()->enabled) { - // Lock FB - if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) { - // Set JPEG src and dst images. - image_t src = {.w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=MAIN_FB()->bpp, .pixels=MAIN_FB()->pixels}; - image_t dst = {.w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=(OMV_JPEG_BUF_SIZE-64), .pixels=JPEG_FB()->pixels}; - - // Note: lower quality saves USB bandwidth and results in a faster IDE FPS. - bool overflow = jpeg_compress(&src, &dst, JPEG_FB()->quality, false); - if (overflow == true) { - // JPEG buffer overflowed, reduce JPEG quality for the next frame - // and skip the current frame. The IDE doesn't receive this frame. - if (JPEG_FB()->quality > 1) { - // Keep this quality for the next n frames - overflow_count = 60; - JPEG_FB()->quality = IM_MAX(1, (JPEG_FB()->quality/2)); - } - JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0; - } else { - if (overflow_count) { - overflow_count--; - } - // No buffer overflow, increase quality up to max quality based on frame size - if (overflow_count == 0 && JPEG_FB()->quality - < ((fb_buffer_size() > JPEG_QUALITY_THRESH) ? JPEG_QUALITY_LOW:JPEG_QUALITY_HIGH)) { - JPEG_FB()->quality++; - } - // Set FB from JPEG image - JPEG_FB()->w = dst.w; JPEG_FB()->h = dst.h; JPEG_FB()->size = dst.bpp; + if (does_not_fit) { + image_t out = { .w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=MAIN_FB()->bpp, .data=MAIN_FB()->pixels }; + int new_size = encode_for_ide_new_size(&out); + fb_alloc_mark(); + uint8_t *temp = fb_alloc(new_size, FB_ALLOC_NO_HINT); + encode_for_ide(temp, &out); + (MP_PYTHON_PRINTER)->print_strn((MP_PYTHON_PRINTER)->data, (const char *) temp, new_size); + fb_alloc_free_till_mark(); } + } else if (MAIN_FB()->bpp >= 0) { + // Lock FB + if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) { + // Set JPEG src and dst images. + image_t src = {.w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=MAIN_FB()->bpp, .pixels=MAIN_FB()->pixels}; + image_t dst = {.w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=(OMV_JPEG_BUF_SIZE-64), .pixels=JPEG_FB()->pixels}; - // Unlock the framebuffer mutex - mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV); + // Note: lower quality saves USB bandwidth and results in a faster IDE FPS. + bool overflow = jpeg_compress(&src, &dst, JPEG_FB()->quality, false); + if (overflow == true) { + // JPEG buffer overflowed, reduce JPEG quality for the next frame + // and skip the current frame. The IDE doesn't receive this frame. + if (JPEG_FB()->quality > 1) { + // Keep this quality for the next n frames + overflow_count = 60; + JPEG_FB()->quality = IM_MAX(1, (JPEG_FB()->quality/2)); + } + JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0; + } else { + if (overflow_count) { + overflow_count--; + } + // No buffer overflow, increase quality up to max quality based on frame size + if (overflow_count == 0 && JPEG_FB()->quality + < ((fb_buffer_size() > JPEG_QUALITY_THRESH) ? JPEG_QUALITY_LOW:JPEG_QUALITY_HIGH)) { + JPEG_FB()->quality++; + } + // Set FB from JPEG image + JPEG_FB()->w = dst.w; JPEG_FB()->h = dst.h; JPEG_FB()->size = dst.bpp; + } + + // Unlock the framebuffer mutex + mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV); + } } } } diff --git a/src/omv/framebuffer.h b/src/omv/framebuffer.h index 710ca92fc..f39bdc8b2 100644 --- a/src/omv/framebuffer.h +++ b/src/omv/framebuffer.h @@ -19,7 +19,7 @@ typedef struct framebuffer { int32_t w,h; int32_t u,v; int32_t bpp; - int32_t padding; + int32_t fb_streaming_disable; // NOTE: This buffer must be aligned on a 16 byte boundary uint8_t pixels[]; } framebuffer_t; @@ -47,6 +47,10 @@ extern jpegbuffer_t *jpeg_fb_framebuffer; // Use this macro to get a pointer to the free SRAM area located after the framebuffer. #define JPEG_FB_PIXELS() (JPEG_FB()->pixels + JPEG_FB()->size) +// Force fb streaming to the IDE off. +void set_fb_streaming_disabled(bool en); +bool is_fb_streaming_disabled(); + // Encode jpeg data for transmission over a text channel. int encode_for_ide_new_size(image_t *img); void encode_for_ide(uint8_t *ptr, image_t *img); diff --git a/src/omv/py/py_omv.c b/src/omv/py/py_omv.c index 7a4572fc8..bb013a165 100644 --- a/src/omv/py/py_omv.c +++ b/src/omv/py/py_omv.c @@ -10,6 +10,7 @@ */ #include #include "usbdbg.h" +#include "framebuffer.h" #include "omv_boardconfig.h" static mp_obj_t py_omv_version_string() @@ -48,6 +49,16 @@ static mp_obj_t py_omv_board_id() } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_omv_board_id_obj, py_omv_board_id); +static mp_obj_t py_omv_disable_fb(uint n_args, const mp_obj_t *args) +{ + if (!n_args) { + return mp_obj_new_bool(is_fb_streaming_disabled()); + } + set_fb_streaming_disabled(mp_obj_get_int(args[0])); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(py_omv_disable_fb_obj, 0, 1, py_omv_disable_fb); + static const mp_rom_map_elem_t globals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_omv) }, { MP_ROM_QSTR(MP_QSTR_version_major), MP_ROM_INT(FIRMWARE_VERSION_MAJOR) }, @@ -56,7 +67,8 @@ static const mp_rom_map_elem_t globals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_version_string), MP_ROM_PTR(&py_omv_version_string_obj) }, { MP_ROM_QSTR(MP_QSTR_arch), MP_ROM_PTR(&py_omv_arch_obj) }, { MP_ROM_QSTR(MP_QSTR_board_type), MP_ROM_PTR(&py_omv_board_type_obj) }, - { MP_ROM_QSTR(MP_QSTR_board_id), MP_ROM_PTR(&py_omv_board_id_obj) } + { MP_ROM_QSTR(MP_QSTR_board_id), MP_ROM_PTR(&py_omv_board_id_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable_fb), MP_ROM_PTR(&py_omv_disable_fb_obj) } }; STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table); diff --git a/src/omv/py/qstrdefsomv.h b/src/omv/py/qstrdefsomv.h index c55d11688..f60d07728 100644 --- a/src/omv/py/qstrdefsomv.h +++ b/src/omv/py/qstrdefsomv.h @@ -18,6 +18,7 @@ Q(version_string) Q(arch) Q(board_type) Q(board_id) +Q(disable_fb) // Image module Q(image)