Merge pull request #2826 from openmv/refactor_jpegbuffer

lib/imlib: Use framebuffer_t for main and streaming buffers.
This commit is contained in:
Ibrahim Abdelkader 2025-09-02 17:16:59 +03:00 committed by GitHub
commit 30a62c2c05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 291 additions and 260 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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).

View File

@ -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).

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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)) {

View File

@ -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.

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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);

View File

@ -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));

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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):

View File

@ -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;
}