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:
iabdalkader 2016-02-06 17:13:53 +02:00
parent 544dee93ae
commit d76fa2b558
4 changed files with 23 additions and 32 deletions

View File

@ -19,4 +19,13 @@ static struct framebuffer {
uint8_t pixels[];
// Note all instances of fb point to the same memory address.
}*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__ */

View File

@ -17,7 +17,7 @@ void imlib_integral_image_alloc(struct integral_image *i_img, int w, int h)
{
i_img->w = w;
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)

View File

@ -24,16 +24,8 @@ typedef struct {
int idx;
int length;
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;
// 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
static float fdtbl_Y[64], fdtbl_UV[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);
}
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;
}
@ -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);
}
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);
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)
{
uint8_t offs_buf[1024];
int bitBuf=0, bitCnt=0;
int DCY=0, DCU=0, DCV=0;
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_buf_t jpeg_buf = {
.idx =0,
.buf = offs_buf,
.offs_buf = dst->pixels,
.buf = dst->pixels,
.length = dst->bpp,
};

View File

@ -314,6 +314,9 @@ int sensor_write_reg(uint8_t reg, uint8_t 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)
{
volatile uint32_t addr;
@ -324,7 +327,7 @@ int sensor_snapshot(struct image *image)
if (sensor.pixformat != PIXFORMAT_JPEG) {
// The framebuffer is compressed in place.
// 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};
// Note: lower quality results in a faster IDE
@ -346,16 +349,15 @@ int sensor_snapshot(struct image *image)
}
fb->ready = 0;
// Setup the address of the transfer
addr = (uint32_t) (fb->pixels);
// Setup the size of the transfer
// Setup the size and address of the transfer
if (sensor.pixformat == PIXFORMAT_JPEG) {
// Sensor has hardware JPEG set max frame size.
length = MAX_XFER_SIZE;
addr = (uint32_t) (fb->pixels);
} else {
// No hardware JPEG, set w*h*2 bytes per pixel.
length =(fb->w * fb->h * 2)/4;
addr = (uint32_t) (fb->pixels+FB_JPEG_OFFS_SIZE);
}
// Lock framebuffer mutex
@ -384,8 +386,9 @@ int sensor_snapshot(struct image *image)
fb->bpp = 1;
// 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++) {
fb->pixels[i] = fb->pixels[i<<1];
pixels[i] = pixels[i<<1];
}
} else if (sensor.pixformat == PIXFORMAT_JPEG) {
// 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->bpp = fb->bpp;
image->pixels = fb->pixels;
if (sensor.pixformat != PIXFORMAT_JPEG) {
image->pixels += FB_JPEG_OFFS_SIZE;
}
}
// Unlock framebuffer mutex