mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #96 from kwagyeman/master
Update Gif to use fb_alloc_all.
This commit is contained in:
commit
547aa0528e
@ -6,13 +6,12 @@
|
||||
* A super simple GIF encoder.
|
||||
*
|
||||
*/
|
||||
#include "mp.h"
|
||||
#include "ff_wrapper.h"
|
||||
#include "imlib.h"
|
||||
#include "fb_alloc.h"
|
||||
|
||||
#define BLOCK_SIZE (126) // (2^(7)) - 2
|
||||
// TODO fix this, use all available FB memory
|
||||
#define BUFF_SIZE (16*1024) // Multiple of (block size + 2)
|
||||
#define BLOCK_SIZE (126) // (2^(7)) - 2 (DO NOT CHANGE!)
|
||||
|
||||
void gif_open(FIL *fp, int width, int height, bool color, bool loop)
|
||||
{
|
||||
@ -56,20 +55,36 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay)
|
||||
write_word(fp, img->h);
|
||||
write_data(fp, (uint8_t []) {0x00, 0x07}, 2); // 7-bits
|
||||
|
||||
int buf_ofs = 0;
|
||||
int bytes = img->h * img->w;
|
||||
uint32_t size;
|
||||
uint8_t *buf = fb_alloc_all(&size);
|
||||
|
||||
// FatFS writes partial sectors (512-(fptr%512)) before writing the maximum contiguous sectors,
|
||||
// increamenting the buffer during the process. This results in an unaligned buffer sent DMA.
|
||||
// We intentionally misalign the buffer here so FatFS re-aligns it when writing the remainder.
|
||||
int ff_ofs = f_tell(fp) % 4;
|
||||
uint8_t *buf = fb_alloc((BUFF_SIZE+ff_ofs) * sizeof(*buf));
|
||||
buf += ff_ofs;
|
||||
// This should never happen unless someone forgot to free.
|
||||
if (size < (sizeof(uint32_t) * 2)) { // We need atleast 8 bytes.
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError,
|
||||
"Memory leak detected!!!"));
|
||||
}
|
||||
|
||||
int buf_ofs = 0;
|
||||
int bytes = img->h * img->w;
|
||||
|
||||
// When a sector boundary is encountered while writing a file and there are
|
||||
// more than 512 bytes left to write FatFs will detect that it can bypass
|
||||
// its internal write buffer and pass the data buffer passed to it directly
|
||||
// to the disk write function. However, the disk write function needs the
|
||||
// buffer to be aligned to a 4-byte boundary. FatFs doesn't know this and
|
||||
// will pass an unaligned buffer if we don't fix the issue.
|
||||
|
||||
int fat_ofs = f_tell(fp) % 4;
|
||||
buf += fat_ofs;
|
||||
size -= fat_ofs;
|
||||
|
||||
// Since we're about to do a more than 512 byte write which will trigger
|
||||
// the above issue we can fix the problem by misaligning our buffer before
|
||||
// calling write so that the first partial write gets us back aligned.
|
||||
|
||||
for (int x=0; x<bytes; x++) {
|
||||
if (x%BLOCK_SIZE==0) {
|
||||
int block_size = IM_MIN(BLOCK_SIZE, bytes - x);
|
||||
buf[buf_ofs++] = 1 + block_size;
|
||||
if ((x%BLOCK_SIZE)==0) {
|
||||
buf[buf_ofs++] = 1 + IM_MIN(BLOCK_SIZE, bytes - x);
|
||||
buf[buf_ofs++] = 0x80; // clear code
|
||||
}
|
||||
|
||||
@ -83,9 +98,13 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay)
|
||||
buf[buf_ofs++] = (red << 5) | (green << 2) | blue;
|
||||
}
|
||||
|
||||
if (buf_ofs==BUFF_SIZE) { // flush data
|
||||
if (buf_ofs==size) { // flush data
|
||||
buf_ofs = 0;
|
||||
write_data(fp, buf, BUFF_SIZE);
|
||||
write_data(fp, buf, size);
|
||||
// Undo alignment fix. fp will be aligned from now on.
|
||||
buf -= fat_ofs;
|
||||
size += fat_ofs;
|
||||
fat_ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -63,6 +63,12 @@ static mp_obj_t py_gif_size(mp_obj_t gif_obj)
|
||||
return mp_obj_new_int(f_size(&arg_gif->fp));
|
||||
}
|
||||
|
||||
static mp_obj_t py_gif_loop(mp_obj_t gif_obj)
|
||||
{
|
||||
py_gif_obj_t *arg_gif = gif_obj;
|
||||
return mp_obj_new_int(arg_gif->loop);
|
||||
}
|
||||
|
||||
static mp_obj_t py_gif_add_frame(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
py_gif_obj_t *arg_gif = args[0];
|
||||
@ -96,6 +102,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_gif_width_obj, py_gif_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_gif_height_obj, py_gif_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_gif_format_obj, py_gif_format);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_gif_size_obj, py_gif_size);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_gif_loop_obj, py_gif_loop);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_gif_add_frame_obj, 2, py_gif_add_frame);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_gif_close_obj, py_gif_close);
|
||||
static const mp_map_elem_t locals_dict_table[] = {
|
||||
@ -103,6 +110,7 @@ static const mp_map_elem_t locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_height), (mp_obj_t)&py_gif_height_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_format), (mp_obj_t)&py_gif_format_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_size), (mp_obj_t)&py_gif_size_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_loop), (mp_obj_t)&py_gif_loop_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_add_frame), (mp_obj_t)&py_gif_add_frame_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&py_gif_close_obj },
|
||||
{ NULL, NULL },
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
import time, sensor, image, gif
|
||||
# Gif recording example:
|
||||
#
|
||||
# You can use your OpenMV Cam to record gif files. You can either feed the
|
||||
# recorder object RGB565 frames or Grayscale frames. Use photo editing software
|
||||
# like GIMP to compress and optimize the Gif before uploading it to the web.
|
||||
|
||||
import sensor, image, time, gif
|
||||
|
||||
# Reset sensor
|
||||
sensor.reset()
|
||||
|
||||
# Set sensor settings
|
||||
sensor.set_contrast(1)
|
||||
sensor.set_brightness(1)
|
||||
sensor.set_saturation(1)
|
||||
sensor.set_gainceiling(16)
|
||||
sensor.set_framesize(sensor.QQVGA)
|
||||
sensor.set_pixformat(sensor.GRAYSCALE)
|
||||
sensor.set_pixformat(sensor.RGB565) # you can also use grayscale
|
||||
|
||||
for i in range(30):
|
||||
img = sensor.snapshot()
|
||||
# Warm up the cam
|
||||
for i in range(10):
|
||||
sensor.snapshot()
|
||||
|
||||
# FPS clock
|
||||
clock = time.clock()
|
||||
gif = gif.Gif("/test.gif", loop=True)
|
||||
gif = gif.Gif("/test.gif", loop=True) # video setup to use current resolution
|
||||
|
||||
for i in range(30):
|
||||
clock.tick()
|
||||
img = sensor.snapshot()
|
||||
gif.add_frame(img, delay=10)
|
||||
gif.add_frame(img, delay=10) # centi seconds
|
||||
# Print FPS.
|
||||
# Note: Actual FPS is higher, the IDE slows down streaming.
|
||||
print(clock.fps())
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#
|
||||
# You can use your OpenMV Cam to record mjpeg files. You can either feed the
|
||||
# recorder object JPEG frames or RGB565/Grayscale frames. Once you've finished
|
||||
# recording an Mjpeg file you can use VLC to play it. If you're on Ubuntu then
|
||||
# recording a Mjpeg file you can use VLC to play it. If you are on Ubuntu then
|
||||
# the built-in video player will work too.
|
||||
|
||||
import sensor, image, time, mjpeg
|
||||
@ -19,7 +19,7 @@ for i in range(10):
|
||||
clock = time.clock()
|
||||
mjpeg = mjpeg.Mjpeg("/test.mjpeg") # video setup to use current resolution
|
||||
|
||||
for i in range(300):
|
||||
for i in range(100):
|
||||
clock.tick()
|
||||
img = sensor.snapshot()
|
||||
mjpeg.add_frame(img)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user