mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
Merge pull request #2826 from openmv/refactor_jpegbuffer
lib/imlib: Use framebuffer_t for main and streaming buffers.
This commit is contained in:
commit
30a62c2c05
@ -139,8 +139,8 @@
|
||||
#define OMV_FB_ALLOC_SIZE (1M) // minimum fb alloc size
|
||||
#define OMV_FB_OVERLAY_MEMORY SRAM0 // Fast fb_alloc memory.
|
||||
#define OMV_FB_OVERLAY_SIZE (448K) // Fast fb_alloc memory size.
|
||||
#define OMV_JPEG_MEMORY DRAM // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (1M) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY DRAM // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY SRAM3 // Misc DMA buffers memory.
|
||||
#define OMV_DMA_MEMORY_D1 SRAM0 // Domain 1 DMA buffers.
|
||||
#define OMV_DMA_MEMORY_D2 SRAM3 // Domain 2 DMA buffers.
|
||||
|
@ -70,7 +70,7 @@
|
||||
#define OMV_FB_ALLOC_SIZE (16K) // minimum fb alloc size
|
||||
#define OMV_GC_BLOCK0_MEMORY SRAM // Main GC block.
|
||||
#define OMV_GC_BLOCK0_SIZE (64K)
|
||||
#define OMV_JPEG_SIZE (16K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_SIZE (16K) // Streaming buffer size.
|
||||
|
||||
#define OMV_TEXT_ORIGIN 0x00026000
|
||||
#define OMV_FFS_LENGTH 64K
|
||||
|
@ -69,7 +69,7 @@ extern unsigned char *OMV_BOARD_UID_ADDR; // Unique address.
|
||||
#define OMV_FB_ALLOC_SIZE (16K) // minimum fb alloc size
|
||||
#define OMV_GC_BLOCK0_MEMORY RAM // Main GC block
|
||||
#define OMV_GC_BLOCK0_SIZE (60 * 1024) // MicroPython's heap
|
||||
#define OMV_JPEG_SIZE (20K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_SIZE (20K) // Streaming buffer size.
|
||||
|
||||
// GP LED
|
||||
#define OMV_LED_PIN (6)
|
||||
|
@ -123,8 +123,8 @@
|
||||
#define OMV_FB_MEMORY SRAM0 // Framebuffer, fb_alloc
|
||||
#define OMV_FB_SIZE (400K) // FB memory: header + VGA/GS image
|
||||
#define OMV_FB_ALLOC_SIZE (76K) // minimum fb alloc size
|
||||
#define OMV_JPEG_MEMORY SRAM0 // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (32K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY SRAM0 // Streaming buffer memory
|
||||
#define OMV_SB_SIZE (32K) // Streaming buffer size
|
||||
#define OMV_DMA_MEMORY SRAM2 // DMA buffers memory.
|
||||
#define OMV_DMA_MEMORY_D1 SRAM0 // Domain 1 DMA buffers.
|
||||
#define OMV_DMA_MEMORY_D2 SRAM2 // Domain 2 DMA buffers.
|
||||
|
@ -132,8 +132,8 @@
|
||||
#define OMV_FB_ALLOC_SIZE (1M) // minimum fb alloc size
|
||||
#define OMV_FB_OVERLAY_MEMORY SRAM0 // Fast fb_alloc memory.
|
||||
#define OMV_FB_OVERLAY_SIZE (480K) // Fast fb_alloc memory size.
|
||||
#define OMV_JPEG_MEMORY DRAM // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (1M) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY DRAM // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY SRAM3 // Misc DMA buffers memory.
|
||||
#define OMV_DMA_MEMORY_D1 SRAM0 // Domain 1 DMA buffers.
|
||||
#define OMV_DMA_MEMORY_D2 SRAM3 // Domain 2 DMA buffers.
|
||||
|
@ -88,7 +88,7 @@
|
||||
#define OMV_DMA_MEMORY SRAM2 // Misc DMA buffers
|
||||
#define OMV_GC_BLOCK0_MEMORY DTCM // Main GC block
|
||||
#define OMV_GC_BLOCK0_SIZE (46K)
|
||||
#define OMV_JPEG_SIZE (8K) // IDE JPEG buffer size (header + data).
|
||||
#define OMV_SB_SIZE (8K) // IDE JPEG buffer size (header + data).
|
||||
#define OMV_MSC_BUF_SIZE (2K) // USB MSC bot data
|
||||
#define OMV_FFS_BUF_SIZE (16K) // Flash filesystem cache
|
||||
#define OMV_LINE_BUF_SIZE (2 * 1024) // Image line buffer round(320 * 2BPP * 2 buffers).
|
||||
|
@ -88,7 +88,7 @@
|
||||
#define OMV_DMA_MEMORY DTCM // Misc DMA buffers
|
||||
#define OMV_GC_BLOCK0_MEMORY DTCM // Main GC block
|
||||
#define OMV_GC_BLOCK0_SIZE (53K)
|
||||
#define OMV_JPEG_SIZE (22K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_SIZE (22K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_MSC_BUF_SIZE (2K) // USB MSC bot data
|
||||
#define OMV_FFS_BUF_SIZE (32K) // Flash filesystem cache
|
||||
#define OMV_LINE_BUF_SIZE (3 * 1024) // Image line buffer round(640 * 2BPP * 2 buffers).
|
||||
|
@ -131,8 +131,8 @@
|
||||
#define OMV_FB_MEMORY SRAM0 // Framebuffer, fb_alloc
|
||||
#define OMV_FB_SIZE (400K) // FB memory: header + VGA/GS image
|
||||
#define OMV_FB_ALLOC_SIZE (80K) // minimum fb alloc size
|
||||
#define OMV_JPEG_MEMORY SRAM0 // JPEG buffer memory.
|
||||
#define OMV_JPEG_SIZE (32K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY SRAM0 // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (32K) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY SRAM2 // Misc DMA buffers memory.
|
||||
#define OMV_GC_BLOCK0_MEMORY SRAM4 // Main GC block.
|
||||
#define OMV_GC_BLOCK0_SIZE (64K)
|
||||
|
@ -118,8 +118,8 @@
|
||||
#define OMV_FB_ALLOC_SIZE (11M) // minimum fb alloc size
|
||||
#define OMV_FB_OVERLAY_MEMORY SRAM0 // Fast fb_alloc memory.
|
||||
#define OMV_FB_OVERLAY_SIZE (496K) // Fast fb_alloc memory size.
|
||||
#define OMV_JPEG_MEMORY DRAM // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (1M) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY DRAM // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY SRAM3 // Misc DMA buffers memory.
|
||||
#define OMV_DMA_MEMORY_D1 SRAM0 // Domain 1 DMA buffers.
|
||||
#define OMV_DMA_MEMORY_D2 SRAM3 // Domain 2 DMA buffers.
|
||||
|
@ -111,8 +111,8 @@
|
||||
#define OMV_FB_ALLOC_SIZE (23M) // minimum fb alloc size
|
||||
#define OMV_FB_OVERLAY_MEMORY SRAM0 // Fast fb_alloc memory.
|
||||
#define OMV_FB_OVERLAY_SIZE (496K) // Fast fb_alloc memory size.
|
||||
#define OMV_JPEG_MEMORY DRAM // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (1M) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY DRAM // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY SRAM3 // DMA buffers memory.
|
||||
#define OMV_DMA_MEMORY_D1 SRAM0 // Domain 1 DMA buffers.
|
||||
#define OMV_DMA_MEMORY_D2 SRAM3 // Domain 2 DMA buffers.
|
||||
|
@ -103,8 +103,8 @@ extern unsigned char OMV_BOARD_UID_ADDR[12]; // Unique address.
|
||||
#define OMV_FB_ALLOC_SIZE (464K) // Minimum fb alloc size
|
||||
#define OMV_FB_OVERLAY_MEMORY DTCM // Fast fb_alloc memory.
|
||||
#define OMV_FB_OVERLAY_SIZE (256K) // Fast fb_alloc memory size.
|
||||
#define OMV_JPEG_MEMORY SRAM6_A // JPEG buffer.
|
||||
#define OMV_JPEG_SIZE (1M)
|
||||
#define OMV_SB_MEMORY SRAM6_A // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY DTCM // Misc DMA buffers memory.
|
||||
#define OMV_GPU_MEMORY SRAM9_B // GPU heap.
|
||||
#define OMV_GPU_SIZE (256K)
|
||||
@ -123,8 +123,8 @@ extern unsigned char OMV_BOARD_UID_ADDR[12]; // Unique address.
|
||||
#define OMV_FB_MEMORY SRAM6_B // Main Frame buffer, fb_alloc
|
||||
#define OMV_FB_SIZE (256K)
|
||||
#define OMV_FB_ALLOC_SIZE (256K) // Minimum fb alloc size
|
||||
#define OMV_JPEG_MEMORY SRAM6_B // JPEG buffer.
|
||||
#define OMV_JPEG_SIZE (500K)
|
||||
#define OMV_SB_MEMORY SRAM6_B // JPEG buffer.
|
||||
#define OMV_SB_SIZE (500K)
|
||||
#define OMV_DMA_MEMORY DTCM // Misc DMA buffers memory.
|
||||
#define OMV_OPENAMP_MEMORY SRAM9_A // Open-AMP SHM
|
||||
#define OMV_OPENAMP_SIZE (64K)
|
||||
|
@ -142,15 +142,15 @@
|
||||
#define OMV_HEAP_MEMORY SRAM1 // libc/sbrk heap memory
|
||||
#define OMV_HEAP_SIZE (256K)
|
||||
#define OMV_FB_MEMORY DRAM // Framebuffer, fb_alloc
|
||||
#define OMV_FB_SIZE (20M) // FB memory.
|
||||
#define OMV_FB_ALLOC_SIZE (11M) // minimum fb_alloc size
|
||||
#define OMV_JPEG_MEMORY DRAM // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (1M) // IDE JPEG buffer (header + data).
|
||||
#define OMV_FB_SIZE (20M) // FB memory.
|
||||
#define OMV_FB_ALLOC_SIZE (11M) // minimum fb_alloc size
|
||||
#define OMV_SB_MEMORY DRAM // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_DMA_MEMORY SRAM1 // Misc DMA buffers memory.
|
||||
#define OMV_DMA_MEMORY_D2 SRAM7 // Domain 2 DMA buffers.
|
||||
#define OMV_GC_BLOCK0_MEMORY SRAM2 // Main GC block
|
||||
#define OMV_GC_BLOCK0_SIZE (1M)
|
||||
#define OMV_GC_BLOCK1_MEMORY DRAM // Main GC block
|
||||
#define OMV_GC_BLOCK1_MEMORY DRAM // Main GC block
|
||||
#define OMV_GC_BLOCK1_SIZE (24M)
|
||||
#define OMV_MSC_BUF_SIZE (4K) // USB MSC bot data
|
||||
#define OMV_VOSPI_DMA_BUFFER ".d2_dma_buffer"
|
||||
|
@ -70,8 +70,8 @@
|
||||
#define OMV_MAIN_MEMORY DTCM // Data/BSS memory
|
||||
#define OMV_STACK_MEMORY ITCM1 // stack memory
|
||||
#define OMV_STACK_SIZE (32K)
|
||||
#define OMV_JPEG_MEMORY DRAM // JPEG buffer memory buffer.
|
||||
#define OMV_JPEG_SIZE (1M) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_MEMORY DRAM // Streaming buffer memory.
|
||||
#define OMV_SB_SIZE (1M) // Streaming buffer size.
|
||||
#define OMV_FB_MEMORY DRAM // Framebuffer, fb_alloc
|
||||
#define OMV_FB_SIZE (13M) // FB memory: header + VGA/GS image
|
||||
#define OMV_FB_ALLOC_SIZE (10M) // minimum fb alloc size
|
||||
|
@ -53,7 +53,7 @@ extern unsigned char *OMV_BOARD_UID_ADDR; // Unique ID address.
|
||||
#define OMV_FB_MEMORY RAM // Framebuffer, fb_alloc
|
||||
#define OMV_FB_SIZE (151K) // FB memory: header + QVGA/GS image
|
||||
#define OMV_FB_ALLOC_SIZE (12K) // minimum fb alloc size
|
||||
#define OMV_JPEG_SIZE (20K) // IDE JPEG buffer (header + data).
|
||||
#define OMV_SB_SIZE (20K) // IDE JPEG buffer (header + data).
|
||||
|
||||
// GP LED
|
||||
#define OMV_LED_PIN (25)
|
||||
|
@ -121,16 +121,16 @@ OMV_GC_BLOCK_NEW(4)
|
||||
PROVIDE(__stack = __StackTop);
|
||||
#endif
|
||||
|
||||
/* JPEG framebuffer memory */
|
||||
#if defined(OMV_JPEG_MEMORY)
|
||||
.jpeg_memory (NOLOAD) :
|
||||
/* Streaming buffer memory */
|
||||
#if defined(OMV_SB_MEMORY)
|
||||
.sb_memory (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_jpeg_memory_start = .;
|
||||
. = . + OMV_JPEG_SIZE;
|
||||
_sb_memory_start = .;
|
||||
. = . + OMV_SB_SIZE;
|
||||
. = ALIGN(4);
|
||||
_jpeg_memory_end = .;
|
||||
} >OMV_JPEG_MEMORY
|
||||
_sb_memory_end = .;
|
||||
} >OMV_SB_MEMORY
|
||||
#endif
|
||||
|
||||
/* GPU memory */
|
||||
@ -211,11 +211,11 @@ PROVIDE(__stack = __StackTop);
|
||||
. = . + OMV_MSC_BUF_SIZE;
|
||||
#endif
|
||||
|
||||
#if defined(OMV_JPEG_SIZE) && !defined(OMV_JPEG_MEMORY)
|
||||
#if defined(OMV_SB_SIZE) && !defined(OMV_SB_MEMORY)
|
||||
. = ALIGN(16);
|
||||
_jpeg_memory_start = .;
|
||||
. = . + OMV_JPEG_SIZE;
|
||||
_jpeg_memory_end = .;
|
||||
_sb_memory_start = .;
|
||||
. = . + OMV_SB_SIZE;
|
||||
_sb_memory_end = .;
|
||||
#endif
|
||||
|
||||
/* FFS (internal) filesystem buffer */
|
||||
|
@ -64,13 +64,13 @@ void fb_alloc_init0() {
|
||||
}
|
||||
|
||||
uint32_t fb_avail() {
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
uint32_t temp = pointer - framebuffer_pool_end(fb) - sizeof(uint32_t);
|
||||
return (temp < sizeof(uint32_t)) ? 0 : temp;
|
||||
}
|
||||
|
||||
void fb_alloc_mark() {
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
char *new_pointer = pointer - sizeof(uint32_t);
|
||||
|
||||
// Check if allocation overwrites the framebuffer pixels
|
||||
@ -137,7 +137,7 @@ void fb_alloc_free_till_mark_past_mark_permanent() {
|
||||
|
||||
// returns null pointer without error if size==0
|
||||
void *fb_alloc(uint32_t size, int hints) {
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
|
||||
if (!size) {
|
||||
return NULL;
|
||||
@ -198,7 +198,7 @@ void *fb_alloc0(uint32_t size, int hints) {
|
||||
}
|
||||
|
||||
void *fb_alloc_all(uint32_t *size, int hints) {
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
uint32_t temp = pointer - framebuffer_pool_end(fb) - sizeof(uint32_t);
|
||||
|
||||
if (temp < sizeof(uint32_t)) {
|
||||
|
@ -185,7 +185,7 @@ __weak int omv_csi_init() {
|
||||
memset(csi, 0, sizeof(omv_csi_t));
|
||||
csi->i2c = &csi_i2c;
|
||||
csi->clk = &csi_clk;
|
||||
csi->fb = framebuffer_get(-1);
|
||||
csi->fb = framebuffer_get(FB_MAINFB_ID);
|
||||
csi->color_palette = rainbow_table;
|
||||
memcpy(csi->resolution, csi_resolution, sizeof(csi_resolution));
|
||||
omv_csi_ops_init(csi);
|
||||
@ -223,7 +223,7 @@ __weak int omv_csi_init() {
|
||||
}
|
||||
|
||||
// Clear fb_enabled flag.
|
||||
JPEG_FB()->enabled = 0;
|
||||
framebuffer_set_enabled(framebuffer_get(FB_STREAM_ID), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1282,24 +1282,25 @@ __weak int omv_csi_set_framebuffers(omv_csi_t *csi, size_t count, bool expand) {
|
||||
return OMV_CSI_ERROR_INVALID_FRAMESIZE;
|
||||
}
|
||||
|
||||
// TODO pass this to resize.
|
||||
#if OMV_CSI_HW_CROP_ENABLE
|
||||
// If hardware cropping is supported, use window size.
|
||||
csi->fb->frame_size = csi->fb->u * csi->fb->v * 2;
|
||||
size_t frame_size = csi->fb->u * csi->fb->v * 2;
|
||||
#else
|
||||
// Otherwise, use the real frame size.
|
||||
csi->fb->frame_size = csi->resolution[csi->framesize][0] * csi->resolution[csi->framesize][1] * 2;
|
||||
size_t frame_size = csi->resolution[csi->framesize][0] * csi->resolution[csi->framesize][1] * 2;
|
||||
#endif
|
||||
|
||||
if (count == -1) {
|
||||
for (size_t i=3; i>0; i--) {
|
||||
if (!framebuffer_resize(csi->fb, i, expand)) {
|
||||
if (!framebuffer_resize(csi->fb, i, frame_size, expand)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return framebuffer_resize(csi->fb, count, expand);
|
||||
return framebuffer_resize(csi->fb, count, frame_size, expand);
|
||||
}
|
||||
|
||||
__weak int omv_csi_set_special_effect(omv_csi_t *csi, omv_csi_sde_t sde) {
|
||||
@ -1583,8 +1584,8 @@ __weak int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
if (buffer && (buffer->flags & VB_FLAG_USED)) {
|
||||
if (flags & OMV_CSI_FLAG_UPDATE_FB) {
|
||||
image_t tmp;
|
||||
framebuffer_init_image(csi->fb, &tmp);
|
||||
framebuffer_update_jpeg_buffer(&tmp);
|
||||
framebuffer_to_image(csi->fb, &tmp);
|
||||
framebuffer_update_preview(&tmp);
|
||||
}
|
||||
|
||||
// Release the previous buffer from used queue -> free queue.
|
||||
|
@ -168,16 +168,17 @@ void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback) {
|
||||
// Return 0 if FB is locked or not ready.
|
||||
uint32_t buffer[3] = { 0 };
|
||||
// Try to lock FB. If header size == 0 frame is not ready
|
||||
if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_IDE)) {
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
if (mutex_try_lock(&fb->lock, MUTEX_TID_IDE)) {
|
||||
// If header size == 0 frame is not ready
|
||||
if (JPEG_FB()->size == 0) {
|
||||
if (fb->size == 0) {
|
||||
// unlock FB
|
||||
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
|
||||
mutex_unlock(&fb->lock, MUTEX_TID_IDE);
|
||||
} else {
|
||||
// Return header w, h and size/bpp
|
||||
buffer[0] = JPEG_FB()->w;
|
||||
buffer[1] = JPEG_FB()->h;
|
||||
buffer[2] = JPEG_FB()->size;
|
||||
buffer[0] = fb->w;
|
||||
buffer[1] = fb->h;
|
||||
buffer[2] = fb->size;
|
||||
}
|
||||
}
|
||||
cmd = USBDBG_NONE;
|
||||
@ -187,12 +188,13 @@ void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback) {
|
||||
|
||||
case USBDBG_FRAME_DUMP:
|
||||
if (xfer_offs < xfer_size) {
|
||||
write_callback(JPEG_FB()->pixels + xfer_offs, size);
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
write_callback(fb->raw_base + xfer_offs, size);
|
||||
xfer_offs += size;
|
||||
if (xfer_offs == xfer_size) {
|
||||
cmd = USBDBG_NONE;
|
||||
JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0;
|
||||
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
|
||||
fb->w = 0; fb->h = 0; fb->size = 0;
|
||||
mutex_unlock(&fb->lock, MUTEX_TID_IDE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -251,20 +253,21 @@ void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback) {
|
||||
#endif // OMV_PROFILER_ENABLE
|
||||
|
||||
// Limit the frames sent over USB to 20Hz.
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
if (check_timeout_ms(last_update_ms, 50) &&
|
||||
mutex_try_lock_fair(&JPEG_FB()->lock, MUTEX_TID_IDE)) {
|
||||
mutex_try_lock_fair(&fb->lock, MUTEX_TID_IDE)) {
|
||||
// If header size == 0 frame is not ready
|
||||
if (JPEG_FB()->size == 0) {
|
||||
if (fb->size == 0) {
|
||||
// unlock FB
|
||||
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
|
||||
mutex_unlock(&fb->lock, MUTEX_TID_IDE);
|
||||
} else {
|
||||
// Set valid frame flag.
|
||||
buffer[0] |= USBDBG_FLAG_FRAMEBUF_LOCKED;
|
||||
|
||||
// Set frame width, height and size/bpp
|
||||
buffer[1] = JPEG_FB()->w;
|
||||
buffer[2] = JPEG_FB()->h;
|
||||
buffer[3] = JPEG_FB()->size;
|
||||
buffer[1] = fb->w;
|
||||
buffer[2] = fb->h;
|
||||
buffer[3] = fb->size;
|
||||
last_update_ms = mp_hal_ticks_ms();
|
||||
}
|
||||
}
|
||||
@ -320,11 +323,14 @@ void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback) {
|
||||
void usbdbg_data_out(uint32_t size, usbdbg_read_callback_t read_callback) {
|
||||
switch (cmd) {
|
||||
case USBDBG_FB_ENABLE: {
|
||||
read_callback(&(JPEG_FB()->enabled), 4);
|
||||
if (JPEG_FB()->enabled == 0) {
|
||||
uint32_t enabled = 0;
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
read_callback(&enabled, 4);
|
||||
framebuffer_set_enabled(fb, enabled);
|
||||
if (fb->enabled == 0) {
|
||||
// When disabling framebuffer, the IDE might still be holding FB lock.
|
||||
// If the IDE is not the current lock owner, this operation is ignored.
|
||||
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
|
||||
mutex_unlock(&fb->lock, MUTEX_TID_IDE);
|
||||
}
|
||||
cmd = USBDBG_NONE;
|
||||
break;
|
||||
|
@ -440,7 +440,7 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
fb->pixfmt = csi->pixformat;
|
||||
|
||||
image_t fb_image;
|
||||
framebuffer_init_image(fb, &fb_image);
|
||||
framebuffer_to_image(fb, &fb_image);
|
||||
|
||||
LEP_SYS_FPA_TEMPERATURE_KELVIN_T kelvin;
|
||||
if (lepton.measurement_mode && (!lepton.radiometry)) {
|
||||
@ -481,7 +481,7 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
fb_alloc_free_till_mark();
|
||||
framebuffer_init_image(fb, image);
|
||||
framebuffer_to_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -84,8 +84,8 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
fb->h = csi->transpose ? fb->u : fb->v;
|
||||
|
||||
// The new buffer hasn't been released yet, so the data pointer
|
||||
// has to be set manually after calling framebuffer_init_image.
|
||||
framebuffer_init_image(fb, image);
|
||||
// has to be set manually after calling framebuffer_to_image.
|
||||
framebuffer_to_image(fb, image);
|
||||
image->pixels = buffer->data;
|
||||
|
||||
static uint32_t step = 0;
|
||||
@ -129,7 +129,7 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
|
||||
// Move the buffer from free queue -> used queue.
|
||||
framebuffer_release(fb, FB_FLAG_FREE);
|
||||
framebuffer_init_image(fb, image);
|
||||
framebuffer_to_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -30,73 +30,86 @@
|
||||
#include "framebuffer.h"
|
||||
#include "omv_boardconfig.h"
|
||||
|
||||
// Main framebuffer memory
|
||||
extern char _fb_memory_start;
|
||||
extern char _fb_memory_end;
|
||||
static framebuffer_t framebuffer;
|
||||
|
||||
extern char _jpeg_memory_start;
|
||||
extern char _jpeg_memory_end;
|
||||
jpegbuffer_t jpegbuffer;
|
||||
// Streaming buffer memory
|
||||
extern char _sb_memory_start;
|
||||
extern char _sb_memory_end;
|
||||
|
||||
// Framebuffers array.
|
||||
static framebuffer_t framebuffers[2];
|
||||
|
||||
void framebuffer_init0() {
|
||||
// Save enable flag before resetting the state.
|
||||
int fb_enabled = jpegbuffer.enabled;
|
||||
// Reuse the last enabled flag after resetting the state.
|
||||
bool enabled = framebuffer_get(FB_STREAM_ID)->enabled;
|
||||
|
||||
// Initialize the static frame buffer.
|
||||
framebuffer_init(&framebuffer, &_fb_memory_start, &_fb_memory_end - &_fb_memory_start, false);
|
||||
// Initialize the main framebuffer.
|
||||
framebuffer_init(framebuffer_get(FB_MAINFB_ID), &_fb_memory_start,
|
||||
&_fb_memory_end - &_fb_memory_start, false, true);
|
||||
|
||||
// Initialize jpeg buffer.
|
||||
memset(&jpegbuffer, 0, sizeof(jpegbuffer_t));
|
||||
mutex_init0(&jpegbuffer.lock);
|
||||
jpegbuffer.enabled = fb_enabled;
|
||||
jpegbuffer.pixels = (uint8_t *) &_jpeg_memory_start;
|
||||
jpegbuffer.quality = ((OMV_JPEG_QUALITY_HIGH - OMV_JPEG_QUALITY_LOW) / 2) + OMV_JPEG_QUALITY_LOW;
|
||||
// Initialize the streaming buffer.
|
||||
framebuffer_init(framebuffer_get(FB_STREAM_ID), &_sb_memory_start,
|
||||
&_sb_memory_end - &_sb_memory_start, false, enabled);
|
||||
}
|
||||
|
||||
void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic) {
|
||||
void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic, bool enabled) {
|
||||
// Clear framebuffers
|
||||
memset(fb, 0, sizeof(framebuffer_t));
|
||||
|
||||
fb->raw_size = size;
|
||||
fb->raw_base = buff;
|
||||
fb->dynamic = dynamic;
|
||||
fb->enabled = enabled;
|
||||
#if OMV_RAW_PREVIEW_ENABLE
|
||||
fb->raw_w = OMV_RAW_PREVIEW_WIDTH;
|
||||
fb->raw_h = OMV_RAW_PREVIEW_HEIGHT;
|
||||
#endif
|
||||
fb->quality = ((OMV_JPEG_QUALITY_HIGH - OMV_JPEG_QUALITY_LOW) / 2) + OMV_JPEG_QUALITY_LOW;
|
||||
mutex_init0(&fb->lock);
|
||||
}
|
||||
|
||||
void framebuffer_init_image(framebuffer_t *fb, image_t *img) {
|
||||
void framebuffer_to_image(framebuffer_t *fb, image_t *img) {
|
||||
if (img != NULL) {
|
||||
vbuffer_t *buffer = framebuffer_acquire(fb, FB_FLAG_USED | FB_FLAG_PEEK);
|
||||
|
||||
img->w = fb->w;
|
||||
img->h = fb->h;
|
||||
img->size = fb->size;
|
||||
img->pixfmt = fb->pixfmt;
|
||||
img->pixels = (buffer == NULL) ? NULL : buffer->data;
|
||||
|
||||
// For streaming buffers (no queues), use raw_base directly
|
||||
if (fb->used_queue == NULL) {
|
||||
img->pixels = (uint8_t *)fb->raw_base;
|
||||
} else {
|
||||
vbuffer_t *buffer = framebuffer_acquire(fb, FB_FLAG_USED | FB_FLAG_PEEK);
|
||||
img->pixels = (buffer == NULL) ? NULL : buffer->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void framebuffer_init_from_image(framebuffer_t *fb, image_t *img) {
|
||||
fb->w = img->w;
|
||||
fb->h = img->h;
|
||||
fb->size = img->size;
|
||||
fb->pixfmt = img->pixfmt;
|
||||
}
|
||||
|
||||
static void jpegbuffer_init_from_image(image_t *img) {
|
||||
void framebuffer_from_image(framebuffer_t *fb, image_t *img) {
|
||||
if (img == NULL) {
|
||||
jpegbuffer.w = 0;
|
||||
jpegbuffer.h = 0;
|
||||
jpegbuffer.size = 0;
|
||||
fb->w = 0;
|
||||
fb->h = 0;
|
||||
fb->size = 0;
|
||||
fb->pixfmt = PIXFORMAT_INVALID;
|
||||
} else {
|
||||
jpegbuffer.w = img->w;
|
||||
jpegbuffer.h = img->h;
|
||||
jpegbuffer.size = img->size;
|
||||
fb->w = img->w;
|
||||
fb->h = img->h;
|
||||
fb->size = img->size;
|
||||
fb->pixfmt = img->pixfmt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
framebuffer_t *framebuffer_get(size_t id) {
|
||||
return &framebuffer;
|
||||
if (id >= FB_MAX_ID) {
|
||||
return NULL;
|
||||
}
|
||||
return &framebuffers[id];
|
||||
}
|
||||
|
||||
|
||||
char *framebuffer_pool_start(framebuffer_t *fb, size_t buf_count) {
|
||||
size_t qsize = (buf_count <= 3) ? 0 : queue_calc_size(buf_count);
|
||||
return fb->raw_base + OMV_ALIGN_TO(qsize * 2, FRAMEBUFFER_ALIGNMENT);
|
||||
@ -138,14 +151,14 @@ void framebuffer_flush(framebuffer_t *fb) {
|
||||
}
|
||||
}
|
||||
|
||||
int framebuffer_resize(framebuffer_t *fb, size_t count, bool expand) {
|
||||
int framebuffer_resize(framebuffer_t *fb, size_t count, size_t frame_size, bool expand) {
|
||||
size_t buf_size = 0;
|
||||
// Queue size given the requested buffer count.
|
||||
size_t queue_size = queue_calc_size(count);
|
||||
|
||||
// Maximum usable memory size without queues.
|
||||
size_t min_size = frame_size + sizeof(vbuffer_t);
|
||||
size_t max_size = fb->raw_size - queue_size * 2;
|
||||
size_t min_size = fb->frame_size + sizeof(vbuffer_t);
|
||||
|
||||
// Use the frame buffer memory for big queues.
|
||||
char *queue_memory = (count > 3) ? fb->raw_base : fb->raw_static;
|
||||
@ -238,99 +251,102 @@ vbuffer_t *framebuffer_release(framebuffer_t *fb, uint32_t flags) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void framebuffer_update_jpeg_buffer(image_t *src) {
|
||||
void framebuffer_update_preview(image_t *src) {
|
||||
static int overflow_count = 0;
|
||||
const size_t max_size = (&_jpeg_memory_end - &_jpeg_memory_start) - sizeof(jpegbuffer_t);
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
|
||||
// Check if JPEG buffer is disabled, image is NULL or format is not set.
|
||||
if (!jpegbuffer.enabled || !src->data || src->pixfmt == PIXFORMAT_INVALID) {
|
||||
while (fb->quality == 0) {
|
||||
}
|
||||
// Check if the streaming buffer is disabled, image is NULL or format is not set.
|
||||
if (!fb->enabled || !src->data || src->pixfmt == PIXFORMAT_INVALID) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Lock the JPEG buffer.
|
||||
if (!mutex_try_lock_fair(&jpegbuffer.lock, MUTEX_TID_OMV)) {
|
||||
// Lock the streaming buffer.
|
||||
if (!mutex_try_lock_fair(&fb->lock, MUTEX_TID_OMV)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->is_compressed) {
|
||||
if (max_size < src->size) {
|
||||
jpegbuffer_init_from_image(NULL);
|
||||
if (src->size > fb->raw_size) {
|
||||
framebuffer_from_image(fb, NULL);
|
||||
mp_printf(MP_PYTHON_PRINTER, "\x1b[40O\n");
|
||||
} else {
|
||||
jpegbuffer_init_from_image(src);
|
||||
memcpy(jpegbuffer.pixels, src->pixels, src->size);
|
||||
framebuffer_from_image(fb, src);
|
||||
memcpy(fb->raw_base, src->pixels, src->size);
|
||||
}
|
||||
} else {
|
||||
image_t dst = {
|
||||
.w = src->w,
|
||||
.h = src->h,
|
||||
.pixfmt = PIXFORMAT_JPEG,
|
||||
.size = max_size,
|
||||
.pixels = jpegbuffer.pixels
|
||||
};
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
bool compress = true;
|
||||
bool overflow = false;
|
||||
image_t dst = {
|
||||
.w = src->w,
|
||||
.h = src->h,
|
||||
.pixfmt = PIXFORMAT_JPEG,
|
||||
.size = fb->raw_size,
|
||||
.pixels = (uint8_t *) fb->raw_base
|
||||
};
|
||||
|
||||
#if OMV_RAW_PREVIEW_ENABLE
|
||||
if (src->is_mutable) {
|
||||
// Down-scale the frame (if necessary) and send the raw frame.
|
||||
dst.size = src->bpp;
|
||||
dst.pixfmt = src->pixfmt;
|
||||
if (src->w <= OMV_RAW_PREVIEW_WIDTH && src->h <= OMV_RAW_PREVIEW_HEIGHT) {
|
||||
if (image_size(&dst) <= max_size) {
|
||||
memcpy(dst.pixels, src->pixels, image_size(src));
|
||||
compress = false;
|
||||
}
|
||||
} else {
|
||||
float x_scale = OMV_RAW_PREVIEW_WIDTH / (float) src->w;
|
||||
float y_scale = OMV_RAW_PREVIEW_HEIGHT / (float) src->h;
|
||||
float scale = IM_MIN(x_scale, y_scale);
|
||||
dst.w = fast_floorf(src->w * scale);
|
||||
dst.h = fast_floorf(src->h * scale);
|
||||
if (image_size(&dst) <= max_size) {
|
||||
imlib_draw_image(&dst, src, 0, 0, scale, scale, NULL, -1, 255, NULL, NULL,
|
||||
IMAGE_HINT_BILINEAR | IMAGE_HINT_BLACK_BACKGROUND,
|
||||
NULL, NULL, NULL, NULL);
|
||||
compress = false;
|
||||
}
|
||||
bool compress = true;
|
||||
bool overflow = false;
|
||||
|
||||
#if OMV_RAW_PREVIEW_ENABLE
|
||||
if (src->is_mutable) {
|
||||
// Down-scale the frame (if necessary) and send the raw frame.
|
||||
dst.size = src->bpp;
|
||||
dst.pixfmt = src->pixfmt;
|
||||
if (src->w <= fb->raw_w && src->h <= fb->raw_h) {
|
||||
if (image_size(&dst) <= fb->raw_size) {
|
||||
memcpy(dst.pixels, src->pixels, image_size(src));
|
||||
compress = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (compress) {
|
||||
// For all other formats, send a compressed frame.
|
||||
overflow = jpeg_compress(src, &dst, jpegbuffer.quality, false, JPEG_SUBSAMPLING_AUTO);
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
// JPEG buffer overflowed, reduce JPEG quality for the next frame
|
||||
// and skip the current frame. The IDE doesn't receive this frame.
|
||||
if (jpegbuffer.quality > 1) {
|
||||
// Keep this quality for the next n frames
|
||||
overflow_count = 60;
|
||||
jpegbuffer.quality = IM_MAX(1, (jpegbuffer.quality / 2));
|
||||
}
|
||||
|
||||
jpegbuffer_init_from_image(NULL);
|
||||
} else {
|
||||
if (overflow_count) {
|
||||
overflow_count--;
|
||||
float scale = IM_MIN((fb->raw_w / (float) src->w),
|
||||
(fb->raw_h / (float) src->h));
|
||||
dst.w = fast_floorf(src->w * scale);
|
||||
dst.h = fast_floorf(src->h * scale);
|
||||
if (image_size(&dst) <= fb->raw_size) {
|
||||
imlib_draw_image(&dst, src, 0, 0, scale, scale, NULL, -1, 255, NULL, NULL,
|
||||
IMAGE_HINT_BILINEAR | IMAGE_HINT_BLACK_BACKGROUND,
|
||||
NULL, NULL, NULL, NULL);
|
||||
compress = false;
|
||||
}
|
||||
|
||||
// Dynamically adjust our quality if the image is huge.
|
||||
bool big_frame = image_size(src) > OMV_JPEG_QUALITY_THRESHOLD;
|
||||
int quality_max = big_frame ? OMV_JPEG_QUALITY_LOW : OMV_JPEG_QUALITY_HIGH;
|
||||
|
||||
// No buffer overflow, increase quality up to max quality based on frame size...
|
||||
if ((!overflow_count) && (jpegbuffer.quality < quality_max)) {
|
||||
jpegbuffer.quality++;
|
||||
}
|
||||
|
||||
jpegbuffer_init_from_image(&dst);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock the JPEG buffer.
|
||||
mutex_unlock(&jpegbuffer.lock, MUTEX_TID_OMV);
|
||||
#endif
|
||||
|
||||
// Compress the frame if the raw image didn't fit or the format is non-mutable.
|
||||
if (compress) {
|
||||
overflow = jpeg_compress(src, &dst, fb->quality, false, JPEG_SUBSAMPLING_AUTO);
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
// JPEG buffer overflowed, reduce JPEG quality for the next frame
|
||||
// and skip the current frame. The IDE doesn't receive this frame.
|
||||
if (fb->quality > 1) {
|
||||
// Keep this quality for the next n frames
|
||||
overflow_count = 60;
|
||||
fb->quality = IM_MAX(1, (fb->quality / 2));
|
||||
}
|
||||
|
||||
framebuffer_from_image(fb, NULL);
|
||||
} else {
|
||||
if (overflow_count) {
|
||||
overflow_count--;
|
||||
}
|
||||
|
||||
// Dynamically adjust our quality if the image is huge.
|
||||
bool big_frame = image_size(src) > OMV_JPEG_QUALITY_THRESHOLD;
|
||||
int quality_max = big_frame ? OMV_JPEG_QUALITY_LOW : OMV_JPEG_QUALITY_HIGH;
|
||||
|
||||
// No buffer overflow, increase quality up to max quality based on frame size...
|
||||
if ((!overflow_count) && (fb->quality < quality_max)) {
|
||||
fb->quality++;
|
||||
}
|
||||
|
||||
framebuffer_from_image(fb, &dst);
|
||||
}
|
||||
|
||||
exit_cleanup:
|
||||
// Unlock the streaming buffer.
|
||||
mutex_unlock(&fb->lock, MUTEX_TID_OMV);
|
||||
}
|
||||
|
@ -35,11 +35,12 @@
|
||||
#define FRAMEBUFFER_ALIGNMENT OMV_CACHE_LINE_SIZE
|
||||
#endif
|
||||
|
||||
// TODO these should just be removed.
|
||||
#define framebuffer_get_width(fb) (fb->w)
|
||||
#define framebuffer_get_height(fb) (fb->h)
|
||||
#define framebuffer_get_depth(fb) (fb->bpp)
|
||||
#define framebuffer_get_buffer_size(fb) (fb->buf_size)
|
||||
// Framebuffer ID
|
||||
typedef enum {
|
||||
FB_MAINFB_ID = 0,
|
||||
FB_STREAM_ID = 1,
|
||||
FB_MAX_ID = 2,
|
||||
} fb_id_t;
|
||||
|
||||
// If FB_FLAG_CHECK_LAST is set and this is the last buffer in
|
||||
// the free queue the release logic depends on the buffer mode:
|
||||
@ -85,19 +86,25 @@ typedef enum {
|
||||
// ² Unused frame buffer space can be used to expand buffers up
|
||||
// to the maximum available size (raw size minus queue size).
|
||||
typedef struct framebuffer {
|
||||
int32_t x, y, w, h, u, v;
|
||||
PIXFORMAT_STRUCT;
|
||||
bool dynamic; // Dynamically allocated or not.
|
||||
bool expanded; // True if buffers were expanded.
|
||||
size_t raw_size; // Raw buffer size and address.
|
||||
char *raw_base;
|
||||
size_t buf_size; // Buffers size and count
|
||||
size_t buf_count;
|
||||
size_t frame_size; // Actual frame size
|
||||
queue_t *used_queue;
|
||||
queue_t *free_queue;
|
||||
// Static memory for small queues.
|
||||
char raw_static[queue_calc_size(3) * 2];
|
||||
int32_t x, y; // Framebuffer offset
|
||||
int32_t w, h; // Framebuffer dimensions
|
||||
int32_t u, v; // Backup dimensions
|
||||
int16_t raw_w; // Raw streaming width
|
||||
int16_t raw_h; // Raw streaming height
|
||||
PIXFORMAT_STRUCT; // Pixel format struct.
|
||||
uint8_t dynamic; // Dynamically allocated or not.
|
||||
uint8_t expanded; // True if buffers were expanded.
|
||||
uint8_t enabled; // Enable/disable framebuffer
|
||||
uint8_t quality; // JPEG compression quality (1-100)
|
||||
uint8_t raw_enabled; // Enable raw streaming
|
||||
size_t raw_size; // Raw buffer size.
|
||||
char *raw_base; // Raw buffer address.
|
||||
size_t buf_size; // Vbuffer size.
|
||||
size_t buf_count; // Vbuffer count
|
||||
mutex_t lock; // Thread-safe access
|
||||
queue_t *used_queue; // Vbuffer used/read queue.
|
||||
queue_t *free_queue; // Vbuffer free/write queue.
|
||||
char raw_static[queue_calc_size(3) * 2]; // Static memory for small queues.
|
||||
} framebuffer_t;
|
||||
|
||||
// Drivers can add more flags:
|
||||
@ -116,29 +123,30 @@ typedef struct vbuffer {
|
||||
OMV_ATTR_ALIGNED(uint8_t data[], FRAMEBUFFER_ALIGNMENT); // Data.
|
||||
} vbuffer_t;
|
||||
|
||||
typedef struct jpegbuffer {
|
||||
int32_t w, h;
|
||||
int32_t size;
|
||||
int32_t enabled;
|
||||
int32_t quality;
|
||||
uint8_t *pixels;
|
||||
mutex_t lock;
|
||||
} jpegbuffer_t;
|
||||
|
||||
void framebuffer_init0();
|
||||
|
||||
// Initializes a frame buffer instance.
|
||||
void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic);
|
||||
void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic, bool enabled);
|
||||
|
||||
// Initializes an image from the frame buffer.
|
||||
void framebuffer_init_image(framebuffer_t *fb, image_t *img);
|
||||
void framebuffer_to_image(framebuffer_t *fb, image_t *img);
|
||||
|
||||
// Sets the frame buffer from an image.
|
||||
void framebuffer_init_from_image(framebuffer_t *fb, image_t *img);
|
||||
void framebuffer_from_image(framebuffer_t *fb, image_t *img);
|
||||
|
||||
// Return the static frame buffer instance.
|
||||
framebuffer_t *framebuffer_get(size_t id);
|
||||
|
||||
// Return the current buffer size
|
||||
static inline size_t framebuffer_get_buffer_size(framebuffer_t *fb) {
|
||||
return fb->buf_size;
|
||||
}
|
||||
|
||||
// Enable/disable framebuffer.
|
||||
static inline void framebuffer_set_enabled(framebuffer_t *fb, bool enabled) {
|
||||
fb->enabled = enabled;
|
||||
}
|
||||
|
||||
// Returns a pointer to the end of the framebuffer(s).
|
||||
char *framebuffer_pool_end(framebuffer_t *fb);
|
||||
|
||||
@ -148,7 +156,7 @@ void framebuffer_flush(framebuffer_t *fb);
|
||||
// Change the number of buffers in the frame buffer.
|
||||
// If expand is true, the buffer size will expand to use all of the
|
||||
// available memory, otherwise it will equal the current frame size.
|
||||
int framebuffer_resize(framebuffer_t *fb, size_t count, bool expand);
|
||||
int framebuffer_resize(framebuffer_t *fb, size_t count, size_t frame_size, bool expand);
|
||||
|
||||
// Return true if free queue is not empty.
|
||||
bool framebuffer_writable(framebuffer_t *fb);
|
||||
@ -170,12 +178,13 @@ static inline void framebuffer_reset(vbuffer_t *buffer) {
|
||||
memset(buffer, 0, offsetof(vbuffer_t, data));
|
||||
}
|
||||
|
||||
// Compress src image to the JPEG buffer if src is mutable,
|
||||
// otherwise copy src to the JPEG buffer.
|
||||
void framebuffer_update_jpeg_buffer(image_t *src);
|
||||
|
||||
// Use this macro to get a pointer to the JPEG buffer.
|
||||
extern jpegbuffer_t jpegbuffer;
|
||||
#define JPEG_FB() (&jpegbuffer)
|
||||
// Set raw preview dimensions.
|
||||
static inline void framebuffer_set_preview(framebuffer_t *fb, uint16_t width, uint16_t height) {
|
||||
fb->raw_w = width;
|
||||
fb->raw_h = height;
|
||||
}
|
||||
|
||||
// Compress the source image into the streaming buffer if it is mutable
|
||||
// and raw preview is disabled, or copy it directly if already compressed.
|
||||
void framebuffer_update_preview(image_t *src);
|
||||
#endif /* __FRAMEBUFFER_H__ */
|
||||
|
@ -138,8 +138,8 @@ static MP_DEFINE_CONST_FUN_OBJ_1(py_omv_csi_shutdown_obj, py_omv_csi_shutdown);
|
||||
static mp_obj_t py_omv_csi_flush() {
|
||||
omv_csi_t *csi = omv_csi_get(-1);
|
||||
image_t tmp;
|
||||
framebuffer_init_image(csi->fb, &tmp);
|
||||
framebuffer_update_jpeg_buffer(&tmp);
|
||||
framebuffer_to_image(csi->fb, &tmp);
|
||||
framebuffer_update_preview(&tmp);
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_0(py_omv_csi_flush_obj, py_omv_csi_flush);
|
||||
@ -215,7 +215,7 @@ static mp_obj_t py_omv_csi_get_fb() {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
framebuffer_init_image(csi->fb, &image);
|
||||
framebuffer_to_image(csi->fb, &image);
|
||||
return py_image_from_struct(&image);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_0(py_omv_csi_get_fb_obj, py_omv_csi_get_fb);
|
||||
|
@ -179,8 +179,8 @@ static MP_DEFINE_CONST_FUN_OBJ_2(py_csi_sleep_obj, py_csi_sleep);
|
||||
static mp_obj_t py_csi_flush(mp_obj_t self_in) {
|
||||
py_csi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
image_t tmp;
|
||||
framebuffer_init_image(self->csi->fb, &tmp);
|
||||
framebuffer_update_jpeg_buffer(&tmp);
|
||||
framebuffer_to_image(self->csi->fb, &tmp);
|
||||
framebuffer_update_preview(&tmp);
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(py_csi_flush_obj, py_csi_flush);
|
||||
@ -1350,7 +1350,7 @@ mp_obj_t py_csi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
||||
if (csi->fb == NULL) {
|
||||
size_t fb_size = args[ARG_fb_size].u_int;
|
||||
csi->fb = (framebuffer_t *) m_malloc(sizeof(framebuffer_t));
|
||||
framebuffer_init(csi->fb, m_malloc(fb_size), fb_size, true);
|
||||
framebuffer_init(csi->fb, m_malloc(fb_size), fb_size, true, true);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_IMU
|
||||
@ -1383,7 +1383,6 @@ static void py_csi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
|
||||
mp_printf(print, " Expanded : %s\n", csi->fb->expanded ? "true" : "false");
|
||||
mp_printf(print, " Raw Buffer Size : %u\n", (unsigned) csi->fb->raw_size);
|
||||
mp_printf(print, " Raw Buffer Addr : 0x%p\n", csi->fb->raw_base);
|
||||
mp_printf(print, " Frame Size : %u\n", (unsigned) csi->fb->frame_size);
|
||||
mp_printf(print, " Vbuffer Size : %u\n", (unsigned) csi->fb->buf_size);
|
||||
mp_printf(print, " Vbuffer Count : %u\n", (unsigned) csi->fb->buf_count);
|
||||
mp_printf(print, " Used Queue Size : %u\n", queue_size(csi->fb->used_queue));
|
||||
|
@ -977,7 +977,7 @@ mp_obj_t py_fir_snapshot(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
|
||||
fb_alloc_free_till_mark();
|
||||
|
||||
if (args[ARG_copy_to_fb].u_bool) {
|
||||
framebuffer_update_jpeg_buffer(&dst_img);
|
||||
framebuffer_update_preview(&dst_img);
|
||||
}
|
||||
return py_image_from_struct(&dst_img);
|
||||
}
|
||||
|
@ -129,12 +129,12 @@ static mp_obj_t py_gif_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
py_gif_obj_t *gif = mp_obj_malloc_with_finaliser(py_gif_obj_t, &py_gif_type);
|
||||
|
||||
gif->width = (args[ARG_width].u_int == -1) ? framebuffer_get_width(fb) : args[ARG_width].u_int;
|
||||
gif->height = (args[ARG_height].u_int == -1) ? framebuffer_get_height(fb) : args[ARG_height].u_int;
|
||||
gif->color = (args[ARG_color].u_int == -1) ? (framebuffer_get_depth(fb) >= 2) : args[ARG_color].u_bool;
|
||||
gif->width = (args[ARG_width].u_int == -1) ? fb->w : args[ARG_width].u_int;
|
||||
gif->height = (args[ARG_height].u_int == -1) ? fb->h : args[ARG_height].u_int;
|
||||
gif->color = (args[ARG_color].u_int == -1) ? (fb->bpp >= 2) : args[ARG_color].u_bool;
|
||||
gif->loop = args[ARG_loop].u_bool;
|
||||
|
||||
file_open(&gif->fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
|
@ -584,7 +584,7 @@ const uint8_t *py_helper_keyword_alpha_palette(size_t n_args, const mp_obj_t *ar
|
||||
}
|
||||
|
||||
bool py_helper_is_equal_to_framebuffer(image_t *img) {
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
vbuffer_t *buffer = framebuffer_acquire(fb, FB_FLAG_USED | FB_FLAG_PEEK);
|
||||
|
||||
return (buffer != NULL) && (img->data == buffer->data);
|
||||
@ -592,7 +592,7 @@ bool py_helper_is_equal_to_framebuffer(image_t *img) {
|
||||
|
||||
void py_helper_update_framebuffer(image_t *img) {
|
||||
if (py_helper_is_equal_to_framebuffer(img)) {
|
||||
framebuffer_init_from_image(framebuffer_get(0), img);
|
||||
framebuffer_from_image(framebuffer_get(FB_MAINFB_ID), img);
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,11 +604,11 @@ void py_helper_set_to_framebuffer(image_t *img) {
|
||||
|
||||
omv_csi_abort(csi, true, false);
|
||||
#else
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
#endif
|
||||
|
||||
// Resize the frame buffer to use all memory for one buffer.
|
||||
framebuffer_resize(fb, 1, true);
|
||||
framebuffer_resize(fb, 1, 0, true);
|
||||
|
||||
// This should never be NULL after resizing the frame buffer.
|
||||
vbuffer_t *buffer = framebuffer_acquire(fb, FB_FLAG_FREE | FB_FLAG_PEEK);
|
||||
@ -617,6 +617,6 @@ void py_helper_set_to_framebuffer(image_t *img) {
|
||||
PY_ASSERT_TRUE_MSG((image_size(img) <= framebuffer_get_buffer_size(fb)),
|
||||
"The image doesn't fit in the frame buffer!");
|
||||
|
||||
framebuffer_init_from_image(fb, img);
|
||||
framebuffer_from_image(fb, img);
|
||||
img->data = buffer->data;
|
||||
}
|
||||
|
@ -1082,10 +1082,10 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
|
||||
float *transform = py_helper_arg_to_transform(args[ARG_transform].u_obj);
|
||||
|
||||
if (args[ARG_copy_to_fb].u_bool) {
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
image_t tmp;
|
||||
framebuffer_init_image(fb, &tmp);
|
||||
framebuffer_update_jpeg_buffer(&tmp);
|
||||
framebuffer_to_image(fb, &tmp);
|
||||
framebuffer_update_preview(&tmp);
|
||||
}
|
||||
|
||||
image_t dst_img = {
|
||||
@ -1185,7 +1185,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
|
||||
image_alloc(&dst_img, size);
|
||||
} else {
|
||||
// Convert in place.
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
bool is_fb = py_helper_is_equal_to_framebuffer(src_img);
|
||||
size_t buf_size = is_fb ? framebuffer_get_buffer_size(fb) : image_size(src_img);
|
||||
PY_ASSERT_TRUE_MSG((size <= buf_size), "The image doesn't fit in the frame buffer!");
|
||||
@ -1297,7 +1297,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_obj, 2, py_image_save);
|
||||
#endif //IMLIB_ENABLE_IMAGE_FILE_IO
|
||||
|
||||
static mp_obj_t py_image_flush(mp_obj_t img_obj) {
|
||||
framebuffer_update_jpeg_buffer(py_image_cobj(img_obj));
|
||||
framebuffer_update_preview(py_image_cobj(img_obj));
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(py_image_flush_obj, py_image_flush);
|
||||
@ -6305,7 +6305,7 @@ mp_obj_t py_image_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw
|
||||
}
|
||||
|
||||
if (args[ARG_copy_to_fb].u_bool) {
|
||||
framebuffer_update_jpeg_buffer(&image);
|
||||
framebuffer_update_preview(&image);
|
||||
}
|
||||
return py_image_from_struct(&image);
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ static mp_obj_t py_imageio_read(size_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
py_helper_update_framebuffer(&image);
|
||||
|
||||
if (args[ARG_copy_to_fb].u_bool) {
|
||||
framebuffer_update_jpeg_buffer(&image);
|
||||
framebuffer_update_preview(&image);
|
||||
}
|
||||
return py_image_from_struct(&image);
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ static mp_obj_t py_mjpeg_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
framebuffer_t *fb = framebuffer_get(0);
|
||||
framebuffer_t *fb = framebuffer_get(FB_MAINFB_ID);
|
||||
py_mjpeg_obj_t *mjpeg = mp_obj_malloc_with_finaliser(py_mjpeg_obj_t, &py_mjpeg_type);
|
||||
|
||||
mjpeg->frames = 0;
|
||||
@ -196,8 +196,8 @@ static mp_obj_t py_mjpeg_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t
|
||||
mjpeg->us_old = 0;
|
||||
mjpeg->us_avg = 0;
|
||||
mjpeg->closed = 0;
|
||||
mjpeg->width = (args[ARG_width].u_int == -1) ? framebuffer_get_width(fb) : args[ARG_width].u_int;
|
||||
mjpeg->height = (args[ARG_height].u_int == -1) ? framebuffer_get_height(fb) : args[ARG_height].u_int;
|
||||
mjpeg->width = (args[ARG_width].u_int == -1) ? fb->w : args[ARG_width].u_int;
|
||||
mjpeg->height = (args[ARG_height].u_int == -1) ? fb->h : args[ARG_height].u_int;
|
||||
|
||||
file_open(&mjpeg->fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
mjpeg_open(&mjpeg->fp, mjpeg->width, mjpeg->height);
|
||||
|
@ -590,7 +590,7 @@ mp_obj_t py_tof_snapshot(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
|
||||
fb_alloc_free_till_mark();
|
||||
|
||||
if (args[ARG_copy_to_fb].u_bool) {
|
||||
framebuffer_update_jpeg_buffer(&dst_img);
|
||||
framebuffer_update_preview(&dst_img);
|
||||
}
|
||||
return py_image_from_struct(&dst_img);
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
|
||||
}
|
||||
|
||||
// Initialize a frame using the frame buffer.
|
||||
framebuffer_init_image(fb, dst_image);
|
||||
framebuffer_to_image(fb, dst_image);
|
||||
|
||||
// Set the frame's pixel format to bayer for raw sensors.
|
||||
if (csi->raw_output && csi->pixformat != PIXFORMAT_BAYER) {
|
||||
|
@ -470,7 +470,7 @@ int imx_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
}
|
||||
|
||||
// Set the user image.
|
||||
framebuffer_init_image(fb, image);
|
||||
framebuffer_to_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ static int nrf_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
framebuffer_release(fb, FB_FLAG_FREE);
|
||||
|
||||
// Set the user image.
|
||||
framebuffer_init_image(fb, image);
|
||||
framebuffer_to_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ static int rp2_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
fb->pixfmt = csi->pixformat;
|
||||
|
||||
// Set the user image.
|
||||
framebuffer_init_image(fb, image);
|
||||
framebuffer_to_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -210,10 +210,10 @@ SECTIONS
|
||||
_fb_alloc_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
_jpeg_memory_start = .;
|
||||
. = . + OMV_JPEG_SIZE;
|
||||
_sb_memory_start = .;
|
||||
. = . + OMV_SB_SIZE;
|
||||
. = ALIGN(4);
|
||||
_jpeg_memory_end = .;
|
||||
_sb_memory_end = .;
|
||||
} >OMV_FB_MEMORY
|
||||
|
||||
.heap (COPY):
|
||||
|
@ -758,7 +758,7 @@ static int stm_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
#endif
|
||||
|
||||
// Set the user image.
|
||||
framebuffer_init_image(fb, image);
|
||||
framebuffer_to_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user