Merge pull request #2755 from kwagyeman/kwabena/fix_update_jpeg_fb
Some checks are pending
🔥 Firmware Build / build-firmware (ARDUINO_GIGA) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_33_BLE_SENSE) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_RP2040_CONNECT) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NICLA_VISION) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_PORTENTA_H7) (push) Waiting to run
🔥 Firmware Build / build-firmware (DOCKER) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV2) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4P) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMVPT) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_AE3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_N6) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_RT1060) (push) Waiting to run
🔥 Firmware Build / code-size-report (push) Blocked by required conditions
🔥 Firmware Build / stable-release (push) Blocked by required conditions
🔥 Firmware Build / development-release (push) Blocked by required conditions

lib/imlib: Fix update_jpeg_buffer to update from the passed image.
This commit is contained in:
Ibrahim Abdelkader 2025-07-08 10:43:59 +03:00 committed by GitHub
commit 5f119db05f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 90 additions and 379 deletions

View File

@ -411,7 +411,9 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
}
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
framebuffer_update_jpeg_buffer(fb);
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
if (csi->pixformat == PIXFORMAT_INVALID) {

View File

@ -69,7 +69,9 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
}
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
framebuffer_update_jpeg_buffer(fb);
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
if (fb->n_buffers != 1) {

View File

@ -61,7 +61,6 @@ void framebuffer_init_fb(framebuffer_t *fb, size_t size, bool dynamic) {
memset(fb, 0, sizeof(*fb));
fb->raw_size = size;
fb->streaming_enabled = true;
fb->dynamic = dynamic;
framebuffer_set_buffers(fb, 1);
}
@ -83,7 +82,7 @@ void framebuffer_init_from_image(framebuffer_t *fb, image_t *img) {
fb->pixfmt = img->pixfmt;
}
static void jpegbuffer_init_from_image(framebuffer_t *fb, image_t *img) {
static void jpegbuffer_init_from_image(image_t *img) {
if (img == NULL) {
jpegbuffer->w = 0;
jpegbuffer->h = 0;
@ -95,39 +94,22 @@ static void jpegbuffer_init_from_image(framebuffer_t *fb, image_t *img) {
}
}
void framebuffer_update_jpeg_buffer(framebuffer_t *fb) {
void framebuffer_update_jpeg_buffer(image_t *src) {
static int overflow_count = 0;
image_t main_fb_src;
framebuffer_init_image(fb, &main_fb_src);
image_t *src = &main_fb_src;
if (src->pixfmt != PIXFORMAT_INVALID &&
fb->streaming_enabled && jpegbuffer->enabled) {
if (src->pixfmt != PIXFORMAT_INVALID && jpegbuffer->enabled) {
if (src->is_compressed) {
bool does_not_fit = false;
if (mutex_try_lock_alternate(&jpegbuffer->lock, MUTEX_TID_OMV)) {
if (OMV_JPEG_BUFFER_SIZE_MAX < src->size) {
jpegbuffer_init_from_image(fb, NULL);
does_not_fit = true;
jpegbuffer_init_from_image(NULL);
mp_printf(MP_PYTHON_PRINTER, "\x1b[40O\n");
} else {
jpegbuffer_init_from_image(fb, src);
jpegbuffer_init_from_image(src);
memcpy(jpegbuffer->pixels, src->pixels, src->size);
}
mutex_unlock(&jpegbuffer->lock, MUTEX_TID_OMV);
}
if (does_not_fit) {
printf("Warning: JPEG/PNG too big! Trying framebuffer transfer using fallback method!\n");
int new_size = framebuffer_encoded_size(fb, src);
fb_alloc_mark();
uint8_t *temp = fb_alloc(new_size, FB_ALLOC_NO_HINT);
framebuffer_encode(fb, temp, src);
(MP_PYTHON_PRINTER)->print_strn((MP_PYTHON_PRINTER)->data, (const char *) temp, new_size);
fb_alloc_free_till_mark();
}
} else if (src->pixfmt != PIXFORMAT_INVALID) {
if (mutex_try_lock_alternate(&jpegbuffer->lock, MUTEX_TID_OMV)) {
image_t dst = {
@ -180,7 +162,7 @@ void framebuffer_update_jpeg_buffer(framebuffer_t *fb) {
jpegbuffer->quality = IM_MAX(1, (jpegbuffer->quality / 2));
}
jpegbuffer_init_from_image(fb, NULL);
jpegbuffer_init_from_image(NULL);
} else {
if (overflow_count) {
overflow_count--;
@ -195,7 +177,7 @@ void framebuffer_update_jpeg_buffer(framebuffer_t *fb) {
jpegbuffer->quality++;
}
jpegbuffer_init_from_image(fb, &dst);
jpegbuffer_init_from_image(&dst);
}
mutex_unlock(&jpegbuffer->lock, MUTEX_TID_OMV);
@ -236,53 +218,6 @@ int32_t framebuffer_get_depth(framebuffer_t *fb) {
return fb->bpp;
}
void framebuffer_set_streaming(framebuffer_t *fb, bool enable) {
fb->streaming_enabled = enable;
}
bool framebuffer_get_streaming(framebuffer_t *fb) {
return fb->streaming_enabled;
}
void framebuffer_encode(framebuffer_t *fb, uint8_t *ptr, image_t *img) {
*ptr++ = 0xFE;
for (int i = 0, j = (img->size / 3) * 3; i < j; i += 3) {
int x = 0;
x |= img->data[i + 0] << 0;
x |= img->data[i + 1] << 8;
x |= img->data[i + 2] << 16;
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
*ptr++ = 0x80 | ((x >> 18) & 0x3F);
}
if ((img->size % 3) == 2) {
// 2 bytes -> 16-bits -> 24-bits sent
int x = 0;
x |= img->data[img->size - 2] << 0;
x |= img->data[img->size - 1] << 8;
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
}
if ((img->size % 3) == 1) {
// 1 byte -> 8-bits -> 16-bits sent
int x = 0;
x |= img->data[img->size - 1] << 0;
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
}
*ptr++ = 0xFE;
}
int framebuffer_encoded_size(framebuffer_t *fb, image_t *img) {
return (((img->size * 8) + 5) / 6) + 2;
}
// Returns the current frame buffer size, factoring in the space taken by fb_alloc.
static uint32_t framebuffer_max_buffer_size(framebuffer_t *fb) {
uint32_t fb_total_size = FB_ALIGN_SIZE_ROUND_DOWN(fb->raw_size);

View File

@ -42,7 +42,6 @@ typedef struct framebuffer {
int32_t w, h;
int32_t u, v;
PIXFORMAT_STRUCT;
int32_t streaming_enabled;
uint32_t raw_size;
uint32_t buff_size;
uint32_t n_buffers;
@ -96,14 +95,6 @@ int32_t framebuffer_get_width(framebuffer_t *fb);
int32_t framebuffer_get_height(framebuffer_t *fb);
int32_t framebuffer_get_depth(framebuffer_t *fb);
// Force fb streaming to the IDE off.
void framebuffer_set_streaming(framebuffer_t *fb, bool enable);
bool framebuffer_get_streaming(framebuffer_t *fb);
// Encode jpeg data for transmission over a text channel.
void framebuffer_encode(framebuffer_t *fb, uint8_t *ptr, image_t *img);
int framebuffer_encoded_size(framebuffer_t *fb, image_t *img);
// Return the number of bytes in the current buffer.
uint32_t framebuffer_get_buffer_size(framebuffer_t *fb);
@ -121,7 +112,7 @@ void framebuffer_init_from_image(framebuffer_t *fb, image_t *img);
// Compress src image to the JPEG buffer if src is mutable, otherwise copy src to the JPEG buffer
// if the src is JPEG and fits in the JPEG buffer, or encode and stream src image to the IDE if not.
void framebuffer_update_jpeg_buffer(framebuffer_t *fb);
void framebuffer_update_jpeg_buffer(image_t *src);
// Clear the framebuffer FIFO. If fifo_flush is true, reset and discard all framebuffers,
// otherwise, retain the last frame in the fifo.

View File

@ -137,7 +137,9 @@ 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);
framebuffer_update_jpeg_buffer(csi->fb);
image_t tmp;
framebuffer_init_image(csi->fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_0(py_omv_csi_flush_obj, py_omv_csi_flush);

View File

@ -177,8 +177,9 @@ 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);
framebuffer_update_jpeg_buffer(self->csi->fb);
image_t tmp;
framebuffer_init_image(self->csi->fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(py_csi_flush_obj, py_csi_flush);

View File

@ -1108,8 +1108,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_t *fb = framebuffer_get(0);
framebuffer_update_jpeg_buffer(fb);
framebuffer_update_jpeg_buffer(&dst_img);
}
return py_image_from_struct(&dst_img);
}

View File

@ -400,28 +400,21 @@ static mp_obj_t py_image_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
static void py_image_print(const mp_print_t *print, mp_obj_t self, mp_print_kind_t kind) {
image_t *image = py_image_cobj(self);
if (image->is_compressed
&& image->pixels[0] == 0xFE
&& image->pixels[image->size - 1] == 0xFE) {
// print for ide.
print->print_strn(print->data, (const char *) image->pixels, image->size);
} else {
mp_printf(print, "{\"w\":%d, \"h\":%d, \"type\":\"%s\", \"size\":%d}",
image->w,
image->h,
(image->pixfmt == PIXFORMAT_BINARY) ? "binary" :
(image->pixfmt == PIXFORMAT_GRAYSCALE) ? "grayscale" :
(image->pixfmt == PIXFORMAT_RGB565) ? "rgb565" :
(image->pixfmt == PIXFORMAT_BAYER_BGGR) ? "bayer_bggr" :
(image->pixfmt == PIXFORMAT_BAYER_GBRG) ? "bayer_gbrg" :
(image->pixfmt == PIXFORMAT_BAYER_GRBG) ? "bayer_grbg" :
(image->pixfmt == PIXFORMAT_BAYER_RGGB) ? "bayer_rggb" :
(image->pixfmt == PIXFORMAT_YUV422) ? "yuv422" :
(image->pixfmt == PIXFORMAT_YVU422) ? "yvu422" :
(image->pixfmt == PIXFORMAT_JPEG) ? "jpeg" :
(image->pixfmt == PIXFORMAT_PNG) ? "png" : "unknown",
image_size(image));
}
mp_printf(print, "{\"w\":%d, \"h\":%d, \"type\":\"%s\", \"size\":%d}",
image->w,
image->h,
(image->pixfmt == PIXFORMAT_BINARY) ? "binary" :
(image->pixfmt == PIXFORMAT_GRAYSCALE) ? "grayscale" :
(image->pixfmt == PIXFORMAT_RGB565) ? "rgb565" :
(image->pixfmt == PIXFORMAT_BAYER_BGGR) ? "bayer_bggr" :
(image->pixfmt == PIXFORMAT_BAYER_GBRG) ? "bayer_gbrg" :
(image->pixfmt == PIXFORMAT_BAYER_GRBG) ? "bayer_grbg" :
(image->pixfmt == PIXFORMAT_BAYER_RGGB) ? "bayer_rggb" :
(image->pixfmt == PIXFORMAT_YUV422) ? "yuv422" :
(image->pixfmt == PIXFORMAT_YVU422) ? "yvu422" :
(image->pixfmt == PIXFORMAT_JPEG) ? "jpeg" :
(image->pixfmt == PIXFORMAT_PNG) ? "png" : "unknown",
image_size(image));
}
static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
@ -993,8 +986,8 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(py_image_set_pixel_obj, 2, py_image_set_pixel)
static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palette, bool default_copy,
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {
ARG_x_scale, ARG_y_scale, ARG_roi, ARG_channel, ARG_alpha, ARG_color_palette, ARG_alpha_palette, ARG_hint,
ARG_copy, ARG_copy_to_fb, ARG_quality, ARG_encode_for_ide, ARG_subsampling
ARG_x_scale, ARG_y_scale, ARG_roi, ARG_channel, ARG_alpha, ARG_color_palette, ARG_alpha_palette,
ARG_hint, ARG_copy, ARG_copy_to_fb, ARG_quality, ARG_subsampling
};
const mp_arg_t allowed_args[] = {
{ MP_QSTR_x_scale, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
@ -1008,7 +1001,6 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
{ MP_QSTR_copy, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = default_copy} },
{ MP_QSTR_copy_to_fb, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_quality, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 90} },
{ MP_QSTR_encode_for_ide, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_subsampling, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = JPEG_SUBSAMPLING_AUTO} },
};
@ -1045,7 +1037,9 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
if (args[ARG_copy_to_fb].u_bool) {
framebuffer_t *fb = framebuffer_get(0);
framebuffer_update_jpeg_buffer(fb);
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
image_t dst_img = {
@ -1128,19 +1122,11 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
|| ((dst_img.pixfmt == PIXFORMAT_PNG) && png_compress(&temp, &dst_img_tmp))) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Compression Failed!"));
}
} else if (args[ARG_encode_for_ide].u_bool) {
dst_img_tmp.data = fb_alloc(image_size(&dst_img_tmp), FB_ALLOC_NO_HINT);
memcpy(dst_img_tmp.data, src_img->data, dst_img_tmp.size);
} else {
dst_img_tmp.data = src_img->data;
}
if (args[ARG_encode_for_ide].u_bool) {
framebuffer_t *fb = framebuffer_get(0);
dst_img.size = framebuffer_encoded_size(fb, &dst_img_tmp);
} else {
dst_img.size = dst_img_tmp.size;
}
dst_img.size = dst_img_tmp.size;
}
uint32_t size = image_size(&dst_img);
@ -1161,10 +1147,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
}
if (dst_img.is_compressed) {
if (args[ARG_encode_for_ide].u_bool) {
framebuffer_t *fb = framebuffer_get(0);
framebuffer_encode(fb, dst_img.data, &dst_img_tmp);
} else if (dst_img.data != dst_img_tmp.data) {
if (dst_img.data != dst_img_tmp.data) {
memcpy(dst_img.data, dst_img_tmp.data, dst_img.size);
}
fb_alloc_free_till_mark();
@ -1268,8 +1251,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_t *fb = framebuffer_get(0);
framebuffer_update_jpeg_buffer(fb);
framebuffer_update_jpeg_buffer(py_image_cobj(img_obj));
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(py_image_flush_obj, py_image_flush);
@ -6235,8 +6217,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_t *fb = framebuffer_get(0);
framebuffer_update_jpeg_buffer(fb);
framebuffer_update_jpeg_buffer(&image);
}
return py_image_from_struct(&image);
}

View File

@ -415,8 +415,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_t *fb = framebuffer_get(0);
framebuffer_update_jpeg_buffer(fb);
framebuffer_update_jpeg_buffer(&image);
}
return py_image_from_struct(&image);
}

View File

@ -76,17 +76,6 @@ static mp_obj_t py_omv_debug_mode() {
}
static MP_DEFINE_CONST_FUN_OBJ_0(py_omv_debug_mode_obj, py_omv_debug_mode);
static mp_obj_t py_omv_disable_fb(size_t n_args, const mp_obj_t *args) {
framebuffer_t *fb = framebuffer_get(0);
if (!n_args) {
return mp_obj_new_bool(!framebuffer_get_streaming(fb));
}
framebuffer_set_streaming(fb, !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) },
@ -96,8 +85,7 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
{ 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_debug_mode), MP_ROM_PTR(&py_omv_debug_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_fb), MP_ROM_PTR(&py_omv_disable_fb_obj) }
{ MP_ROM_QSTR(MP_QSTR_debug_mode), MP_ROM_PTR(&py_omv_debug_mode_obj) }
};
static MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table);

View File

@ -589,8 +589,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_t *fb = framebuffer_get(0);
framebuffer_update_jpeg_buffer(fb);
framebuffer_update_jpeg_buffer(&dst_img);
}
return py_image_from_struct(&dst_img);
}

View File

@ -240,7 +240,11 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
}
// Compress the framebuffer for the IDE preview.
framebuffer_update_jpeg_buffer(fb);
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
// Free the current FB head.
framebuffer_free_current_buffer(fb);

View File

@ -351,7 +351,11 @@ int imx_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
}
// Compress the framebuffer for the IDE preview.
framebuffer_update_jpeg_buffer(fb);
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
// Free the current FB head.
framebuffer_free_current_buffer(fb);

View File

@ -125,7 +125,11 @@ static int nrf_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
// Compress the framebuffer for the IDE preview, only if it's not the first frame,
// the framebuffer is enabled and the image sensor does not support JPEG encoding.
// Note: This doesn't run unless the IDE is connected and the framebuffer is enabled.
framebuffer_update_jpeg_buffer(fb);
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
// This driver supports a single buffer.
if (fb->n_buffers != 1) {

View File

@ -156,7 +156,11 @@ static int rp2_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
framebuffer_t *fb = csi->fb;
// Compress the framebuffer for the IDE preview.
framebuffer_update_jpeg_buffer(fb);
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
if (omv_csi_check_framebuffer_size(csi) != 0) {
return OMV_CSI_ERROR_FRAMEBUFFER_OVERFLOW;

View File

@ -554,7 +554,9 @@ static int stm_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
// Compress the framebuffer for the IDE preview, if not the first frame, the
// framebuffer is enabled, and the image sensor doesn't support JPEG encoding.
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
framebuffer_update_jpeg_buffer(fb);
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
// Ensure that the raw frame fits into the FB. It will be switched from RGB565 to BAYER

View File

@ -1,101 +0,0 @@
# This work is licensed under the MIT license.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Image Transfer - As The Remote Device
#
# This script is meant to talk to the "image_transfer_jpg_as_the_controller_device.py" on your computer.
#
# This script shows off how to transfer the frame buffer to your computer as a jpeg image.
import omv
import rpc
import sensor
import struct
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)
# Turn off the frame buffer connection to the IDE from the OpenMV Cam side.
#
# This needs to be done when manually compressing jpeg images at higher quality
# so that the OpenMV Cam does not try to stream them to the IDE using a fall back
# mechanism if the JPEG image is too large to fit in the IDE JPEG frame buffer on the OpenMV Cam.
omv.disable_fb(True)
# The RPC library above is installed on your OpenMV Cam and provides multiple classes for
# allowing your OpenMV Cam to be controlled over USB or LAN/WLAN.
################################################################
# Choose the interface you wish to control your OpenMV Cam over.
################################################################
# Uncomment the below line to setup your OpenMV Cam for control over a USB VCP.
#
interface = rpc.rpc_usb_vcp_slave()
# Uncomment the below line to setup your OpenMV Cam for control over the lan.
# import network
#
# network_if = network.LAN()
# network_if.active(True)
# network_if.ifconfig('dhcp')
#
# interface = rpc.rpc_network_slave(network_if)
# Uncomment the below line to setup your OpenMV Cam for control over the wlan.
#
# import network
# network_if = network.WLAN(network.STA_IF)
# network_if.active(True)
# network_if.connect('your-ssid', 'your-password')
#
# interface = rpc.rpc_network_slave(network_if)
################################################################
# Call Backs
################################################################
# When called sets the pixformat and framesize, takes a snapshot
# and then returns the frame buffer jpg size to store the image in.
#
# data is a pixformat string and framesize string.
def jpeg_image_snapshot(data):
pixformat, framesize = bytes(data).decode().split(",")
sensor.set_pixformat(eval(pixformat))
sensor.set_framesize(eval(framesize))
img = sensor.snapshot()
img.to_jpeg(quality=90)
return struct.pack("<I", img.size())
def jpeg_image_read_cb():
interface.put_bytes(sensor.get_fb().bytearray(), 5000) # timeout
# Read data from the frame buffer given a offset and size.
# If data is empty then a transfer is scheduled after the RPC call finishes.
#
# data is a 4 byte size and 4 byte offset.
def jpeg_image_read(data):
if not len(data):
interface.schedule_callback(jpeg_image_read_cb)
return bytes()
else:
offset, size = struct.unpack("<II", data)
return memoryview(sensor.get_fb().bytearray())[offset : offset + size]
# Register call backs.
interface.register_callback(jpeg_image_snapshot)
interface.register_callback(jpeg_image_read)
# Once all call backs have been registered we can start
# processing remote events. interface.loop() does not return.
interface.loop()

View File

@ -1,93 +0,0 @@
# This work is licensed under the MIT license.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Image Transfer - As The Remote Device
#
# This script is meant to talk to the "image_transfer_jpg_streaming_as_the_controller_device.py" on your computer.
#
# This script shows off how to transfer the frame buffer to your computer as a jpeg image.
import omv
import rpc
import sensor
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)
# Turn off the frame buffer connection to the IDE from the OpenMV Cam side.
#
# This needs to be done when manually compressing jpeg images at higher quality
# so that the OpenMV Cam does not try to stream them to the IDE using a fall back
# mechanism if the JPEG image is too large to fit in the IDE JPEG frame buffer on the OpenMV Cam.
omv.disable_fb(True)
# The RPC library above is installed on your OpenMV Cam and provides multiple classes for
# allowing your OpenMV Cam to be controlled over USB or LAN/WLAN.
################################################################
# Choose the interface you wish to control your OpenMV Cam over.
################################################################
# Uncomment the below line to setup your OpenMV Cam for control over a USB VCP.
#
interface = rpc.rpc_usb_vcp_slave()
# Uncomment the below line to setup your OpenMV Cam for control over the lan.
#
# import network
# network_if = network.LAN()
# network_if.active(True)
# network_if.ifconfig('dhcp')
#
# interface = rpc.rpc_network_slave(network_if)
# Uncomment the below line to setup your OpenMV Cam for control over the wlan.
#
# import network
# network_if = network.WLAN(network.STA_IF)
# network_if.active(True)
# network_if.connect('your-ssid', 'your-password')
#
# interface = rpc.rpc_network_slave(network_if)
################################################################
# Call Backs
################################################################
# This is called repeatedly by interface.stream_writer().
def stream_generator_cb():
img = sensor.snapshot()
img.to_jpeg(quality=90)
return img.bytearray()
# Transmits a stream of bytes()'s generated by stream_generator_cb to the master device.
def jpeg_image_stream_cb():
interface.stream_writer(stream_generator_cb)
# When called sets the pixformat and framesize, and then schedules
# frame streaming to start after the RPC call finishes.
#
# data is a pixformat string and framesize string.
def jpeg_image_stream(data):
pixformat, framesize = bytes(data).decode().split(",")
sensor.set_pixformat(eval(pixformat))
sensor.set_framesize(eval(framesize))
interface.schedule_callback(jpeg_image_stream_cb)
return bytes()
# Register call backs.
interface.register_callback(jpeg_image_stream)
# Once all call backs have been registered we can start
# processing remote events. interface.loop() does not return.
interface.loop()

View File

@ -11,9 +11,8 @@
# you can use by going to Tools->Video Tools->Play RSTP Stream.
import network
import omv
import rtsp
import sensor
import csi
import time
# If you are using VLC on linux you may need to install the live555 library for RTSP support to
@ -26,18 +25,10 @@ import time
# "show more options" when you open the network stream in VLC. You can reduce this to like 10ms
# to make the video real-time.
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.VGA)
# Turn off the frame buffer connection to the IDE from the OpenMV Cam side.
#
# This needs to be done when manually compressing jpeg images at higher quality
# so that the OpenMV Cam does not try to stream them to the IDE using a fall back
# mechanism if the JPEG image is too large to fit in the IDE JPEG frame buffer on the OpenMV Cam.
omv.disable_fb(True)
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
# Setup Network Interface
@ -67,6 +58,7 @@ def setup_callback(pathname, session):
def play_callback(pathname, session):
global clock
clock.reset()
clock.tick()
print('Playing "%s" in session %d' % (pathname, session))
@ -88,7 +80,9 @@ server.register_teardown_cb(teardown_callback)
# Called each time a new frame is needed.
def image_callback(pathname, session):
img = sensor.snapshot()
global csi0
global clock
img = csi0.snapshot(update=False)
# Markup image and/or do various things.
print(clock.fps())
clock.tick()

View File

@ -11,9 +11,8 @@
# you can use by going to Tools->Video Tools->Play RSTP Stream.
import network
import omv
import rtsp
import sensor
import csi
import time
# If you are using VLC on linux you may need to install the live555 library for RTSP support to
@ -26,18 +25,10 @@ import time
# "show more options" when you open the network stream in VLC. You can reduce this to like 10ms
# to make the video real-time.
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.VGA)
# Turn off the frame buffer connection to the IDE from the OpenMV Cam side.
#
# This needs to be done when manually compressing jpeg images at higher quality
# so that the OpenMV Cam does not try to stream them to the IDE using a fall back
# mechanism if the JPEG image is too large to fit in the IDE JPEG frame buffer on the OpenMV Cam.
omv.disable_fb(True)
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
# Setup Network Interface
@ -70,6 +61,7 @@ def setup_callback(pathname, session):
def play_callback(pathname, session):
global clock
clock.reset()
clock.tick()
print('Playing "%s" in session %d' % (pathname, session))
@ -91,7 +83,9 @@ server.register_teardown_cb(teardown_callback)
# Called each time a new frame is needed.
def image_callback(pathname, session):
img = sensor.snapshot()
global csi0
global clock
img = csi0.snapshot(update=False)
# Markup image and/or do various things.
print(clock.fps())
clock.tick()