mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Remove the JPEG offset buffer.
* Set the address of the DMA transfer to addr + offset to allow JPEG Compression of the framebuffer without overwriting image pixels. * This saves 1KBs of stack and conditionals in jpeg_put_bytes/char.
This commit is contained in:
parent
544dee93ae
commit
d76fa2b558
@ -19,4 +19,13 @@ static struct framebuffer {
|
|||||||
uint8_t pixels[];
|
uint8_t pixels[];
|
||||||
// Note all instances of fb point to the same memory address.
|
// Note all instances of fb point to the same memory address.
|
||||||
}*fb = (struct framebuffer *) &_fb_base;
|
}*fb = (struct framebuffer *) &_fb_base;
|
||||||
|
|
||||||
|
// The JPEG offset allows JPEG compression of the framebuffer without overwriting the pixels.
|
||||||
|
// The offset size may need to be adjusted depending on the quality, otherwise JPEG data may
|
||||||
|
// overwrite image pixels before they are compressed (see framebuffer.h)
|
||||||
|
#define FB_JPEG_OFFS_SIZE (1024)
|
||||||
|
|
||||||
|
// Use this macro to get a pointer to the free SRAM area located after the framebuffer.
|
||||||
|
// If JPEG is enabled, this macro returns (framebuffer->pixels + fb_width * fb_height).
|
||||||
|
#define FB_PIXELS() ((fb->bpp > 2)? (fb->pixels+fb->w*fb->h) : (fb->pixels+fb->w*fb->h+FB_JPEG_OFFS_SIZE))
|
||||||
#endif /* __FRAMEBUFFER_H__ */
|
#endif /* __FRAMEBUFFER_H__ */
|
||||||
|
|||||||
@ -17,7 +17,7 @@ void imlib_integral_image_alloc(struct integral_image *i_img, int w, int h)
|
|||||||
{
|
{
|
||||||
i_img->w = w;
|
i_img->w = w;
|
||||||
i_img->h = h;
|
i_img->h = h;
|
||||||
i_img->data = (uint32_t*) (fb->pixels+(fb->w * fb->h));
|
i_img->data = (uint32_t*) FB_PIXELS();
|
||||||
}
|
}
|
||||||
|
|
||||||
void imlib_integral_image(struct image *src, struct integral_image *sum)
|
void imlib_integral_image(struct image *src, struct integral_image *sum)
|
||||||
|
|||||||
@ -24,16 +24,8 @@ typedef struct {
|
|||||||
int idx;
|
int idx;
|
||||||
int length;
|
int length;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
// The offset buffer allows JPEG compression in place (src and dst pointers passed to jpeg_compress() can be the same).
|
|
||||||
// JPEG headers and data are written to this buffer until enough image pixels has been read and compressed. The offset
|
|
||||||
// buffer is then swapped with the destination buffer.
|
|
||||||
uint8_t *offs_buf;
|
|
||||||
} jpeg_buf_t;
|
} jpeg_buf_t;
|
||||||
|
|
||||||
// Note: The offset buffer size may need to be adjusted depending on the quality, otherwise JPEG data may
|
|
||||||
// overwrite the image before compression. However, note that the offset buffer is allocated on the stack.
|
|
||||||
#define OFFS_BUF_SIZE (1024)
|
|
||||||
|
|
||||||
// Quantization tables
|
// Quantization tables
|
||||||
static float fdtbl_Y[64], fdtbl_UV[64];
|
static float fdtbl_Y[64], fdtbl_UV[64];
|
||||||
static uint8_t YTable[64], UVTable[64];
|
static uint8_t YTable[64], UVTable[64];
|
||||||
@ -185,12 +177,6 @@ static void jpeg_put_char(jpeg_buf_t *jpeg_buf, char c)
|
|||||||
jpeg_buf->buf = xrealloc(jpeg_buf->buf, jpeg_buf->length);
|
jpeg_buf->buf = xrealloc(jpeg_buf->buf, jpeg_buf->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jpeg_buf->idx == OFFS_BUF_SIZE) {
|
|
||||||
// exausted the offset buffer
|
|
||||||
memcpy(jpeg_buf->offs_buf, jpeg_buf->buf, OFFS_BUF_SIZE);
|
|
||||||
jpeg_buf->buf = jpeg_buf->offs_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_buf->buf[jpeg_buf->idx++]=c;
|
jpeg_buf->buf[jpeg_buf->idx++]=c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,13 +187,6 @@ static void jpeg_put_bytes(jpeg_buf_t *jpeg_buf, const void *data, int size)
|
|||||||
jpeg_buf->buf = xrealloc(jpeg_buf->buf, jpeg_buf->length);
|
jpeg_buf->buf = xrealloc(jpeg_buf->buf, jpeg_buf->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jpeg_buf->idx+size >= OFFS_BUF_SIZE
|
|
||||||
&& jpeg_buf->buf != jpeg_buf->offs_buf) {
|
|
||||||
// Exhausted the offset buffer
|
|
||||||
memcpy(jpeg_buf->offs_buf, jpeg_buf->buf, OFFS_BUF_SIZE);
|
|
||||||
jpeg_buf->buf = jpeg_buf->offs_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(jpeg_buf->buf+jpeg_buf->idx, data, size);
|
memcpy(jpeg_buf->buf+jpeg_buf->idx, data, size);
|
||||||
jpeg_buf->idx += size;
|
jpeg_buf->idx += size;
|
||||||
}
|
}
|
||||||
@ -446,8 +425,6 @@ void jpeg_write_headers(jpeg_buf_t *jpeg_buf, int width, int height)
|
|||||||
|
|
||||||
void jpeg_compress(image_t *src, image_t *dst, int quality)
|
void jpeg_compress(image_t *src, image_t *dst, int quality)
|
||||||
{
|
{
|
||||||
uint8_t offs_buf[1024];
|
|
||||||
|
|
||||||
int bitBuf=0, bitCnt=0;
|
int bitBuf=0, bitCnt=0;
|
||||||
int DCY=0, DCU=0, DCV=0;
|
int DCY=0, DCU=0, DCV=0;
|
||||||
int YDU[64], UDU[64], VDU[64];
|
int YDU[64], UDU[64], VDU[64];
|
||||||
@ -455,8 +432,7 @@ void jpeg_compress(image_t *src, image_t *dst, int quality)
|
|||||||
// JPEG buffer
|
// JPEG buffer
|
||||||
jpeg_buf_t jpeg_buf = {
|
jpeg_buf_t jpeg_buf = {
|
||||||
.idx =0,
|
.idx =0,
|
||||||
.buf = offs_buf,
|
.buf = dst->pixels,
|
||||||
.offs_buf = dst->pixels,
|
|
||||||
.length = dst->bpp,
|
.length = dst->bpp,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -314,6 +314,9 @@ int sensor_write_reg(uint8_t reg, uint8_t val)
|
|||||||
return SCCB_Write(sensor.slv_addr, reg, val);
|
return SCCB_Write(sensor.slv_addr, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The JPEG offset allows JPEG compression of the framebuffer without overwriting the pixels.
|
||||||
|
// The offset size may need to be adjusted depending on the quality, otherwise JPEG data may
|
||||||
|
// overwrite image pixels before they are compressed.
|
||||||
int sensor_snapshot(struct image *image)
|
int sensor_snapshot(struct image *image)
|
||||||
{
|
{
|
||||||
volatile uint32_t addr;
|
volatile uint32_t addr;
|
||||||
@ -324,7 +327,7 @@ int sensor_snapshot(struct image *image)
|
|||||||
if (sensor.pixformat != PIXFORMAT_JPEG) {
|
if (sensor.pixformat != PIXFORMAT_JPEG) {
|
||||||
// The framebuffer is compressed in place.
|
// The framebuffer is compressed in place.
|
||||||
// Assuming we have at least 128KBs of SRAM.
|
// Assuming we have at least 128KBs of SRAM.
|
||||||
image_t src = {.w=fb->w, .h=fb->h, .bpp=fb->bpp, .pixels=fb->pixels};
|
image_t src = {.w=fb->w, .h=fb->h, .bpp=fb->bpp, .pixels=fb->pixels+FB_JPEG_OFFS_SIZE};
|
||||||
image_t dst = {.w=fb->w, .h=fb->h, .bpp=128*1024, .pixels=fb->pixels};
|
image_t dst = {.w=fb->w, .h=fb->h, .bpp=128*1024, .pixels=fb->pixels};
|
||||||
|
|
||||||
// Note: lower quality results in a faster IDE
|
// Note: lower quality results in a faster IDE
|
||||||
@ -346,16 +349,15 @@ int sensor_snapshot(struct image *image)
|
|||||||
}
|
}
|
||||||
fb->ready = 0;
|
fb->ready = 0;
|
||||||
|
|
||||||
// Setup the address of the transfer
|
// Setup the size and address of the transfer
|
||||||
addr = (uint32_t) (fb->pixels);
|
|
||||||
|
|
||||||
// Setup the size of the transfer
|
|
||||||
if (sensor.pixformat == PIXFORMAT_JPEG) {
|
if (sensor.pixformat == PIXFORMAT_JPEG) {
|
||||||
// Sensor has hardware JPEG set max frame size.
|
// Sensor has hardware JPEG set max frame size.
|
||||||
length = MAX_XFER_SIZE;
|
length = MAX_XFER_SIZE;
|
||||||
|
addr = (uint32_t) (fb->pixels);
|
||||||
} else {
|
} else {
|
||||||
// No hardware JPEG, set w*h*2 bytes per pixel.
|
// No hardware JPEG, set w*h*2 bytes per pixel.
|
||||||
length =(fb->w * fb->h * 2)/4;
|
length =(fb->w * fb->h * 2)/4;
|
||||||
|
addr = (uint32_t) (fb->pixels+FB_JPEG_OFFS_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock framebuffer mutex
|
// Lock framebuffer mutex
|
||||||
@ -384,8 +386,9 @@ int sensor_snapshot(struct image *image)
|
|||||||
fb->bpp = 1;
|
fb->bpp = 1;
|
||||||
|
|
||||||
// If GRAYSCALE extract Y channel from YUV
|
// If GRAYSCALE extract Y channel from YUV
|
||||||
|
uint8_t *pixels = fb->pixels + FB_JPEG_OFFS_SIZE;
|
||||||
for (int i=0; i<(fb->w * fb->h); i++) {
|
for (int i=0; i<(fb->w * fb->h); i++) {
|
||||||
fb->pixels[i] = fb->pixels[i<<1];
|
pixels[i] = pixels[i<<1];
|
||||||
}
|
}
|
||||||
} else if (sensor.pixformat == PIXFORMAT_JPEG) {
|
} else if (sensor.pixformat == PIXFORMAT_JPEG) {
|
||||||
// The frame readout has finished, however the DMA's still waiting for data
|
// The frame readout has finished, however the DMA's still waiting for data
|
||||||
@ -404,6 +407,9 @@ int sensor_snapshot(struct image *image)
|
|||||||
image->h = fb->h;
|
image->h = fb->h;
|
||||||
image->bpp = fb->bpp;
|
image->bpp = fb->bpp;
|
||||||
image->pixels = fb->pixels;
|
image->pixels = fb->pixels;
|
||||||
|
if (sensor.pixformat != PIXFORMAT_JPEG) {
|
||||||
|
image->pixels += FB_JPEG_OFFS_SIZE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock framebuffer mutex
|
// Unlock framebuffer mutex
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user