Files

237 lines
6.5 KiB
C

#include <common.h>
#include <command.h>
#include <cpu_func.h>
#include <amlogic/jpeg.h>
#include <amlogic/fb.h>
static long splash_rd_offset;
static pjpeg_image_info_t pjpeg;
static uint32_t *fb_addr;
static unsigned long fb_width;
typedef struct splash_t
{
u32 addr;
u32 length;
}jpeg_splash_t;
typedef unsigned char (*pjpeg_need_bytes_callback_t)(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data);
unsigned char pjpeg_need_bytes_callback(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data)
{
uint n;
jpeg_splash_t *splash = (jpeg_splash_t *)pCallback_data;
if (splash_rd_offset >= splash->length) {
splash_rd_offset = 0;
return PJPG_STREAM_READ_ERROR;
}
n = min((unsigned int)(splash->length - splash_rd_offset), (unsigned int)buf_size);
memcpy(pBuf, (void *)(splash->addr + splash_rd_offset), n);
splash_rd_offset += n;
*pBytes_actually_read = n;
return 0;
}
int pjpeg_decode(pjpeg_image_info_t *image_info, uint32_t *pImage)
{
int mcu_x = 0;
int mcu_y = 0;
uint8_t status = 0;
#ifdef PJPEG_DECODE_DBG
printf("pjpeg_decode mcu:%dx%d size:%dx%d\n",
image_info->m_MCUSPerRow, image_info->m_MCUSPerCol,
image_info->m_MCUWidth, image_info->m_MCUHeight);
#endif
for ( ; ; ) {
int x, y;
uint32_t *pDst_row;
if (mcu_y >= image_info->m_MCUSPerCol)
break;
status = pjpeg_decode_mcu();
if (status) {
if (status != PJPG_NO_MORE_BLOCKS) {
printf("pjpeg_decode_mcu() failed with status %u\n", status);
return status;
}
break;
}
// Copy MCU's pixel blocks into the destination bitmap.
pDst_row = pImage + mcu_y * image_info->m_MCUHeight * fb_width + mcu_x * image_info->m_MCUWidth;
for (y = 0; y < image_info->m_MCUHeight; y += 8) {
const int by_limit = min(8, image_info->m_height - (mcu_y * image_info->m_MCUHeight + y));
for (x = 0; x < image_info->m_MCUWidth; x += 8) {
// Compute source byte offset of the block in the decoder's MCU buffer.
const uint src_ofs = (x * 8U) + (y * 16U);
uint8_t *pSrcR = image_info->m_pMCUBufR + src_ofs;
uint8_t *pSrcG = image_info->m_pMCUBufG + src_ofs;
uint8_t *pSrcB = image_info->m_pMCUBufB + src_ofs;
const int bx_limit = min(8, image_info->m_width - (mcu_x * image_info->m_MCUWidth + x));
int bx, by;
uint32_t *pDst_block = pDst_row + x;
for (by = 0; by < by_limit; by++) {
uint32_t *pDst = pDst_block;
for (bx = 0; bx < bx_limit; bx++) {
*pDst = (0xff << 24) | (*pSrcR << 16) | (*pSrcG << 8) | (*pSrcB);
pSrcR++;
pSrcG++;
pSrcB++;
pDst++;
}
pSrcR += (8 - bx_limit);
pSrcG += (8 - bx_limit);
pSrcB += (8 - bx_limit);
pDst_block += image_info->m_width;
}
}
pDst_row += image_info->m_width * 8;
}
mcu_x++;
if (mcu_x == image_info->m_MCUSPerRow) {
mcu_x = 0;
mcu_y++;
}
}
flush_cache((unsigned long)pImage,
image_info->m_width * image_info->m_height * 4);
#ifdef PJPEG_DECODE_DBG
printf("Decode completed %dx%d to %p.\n",
image_info->m_width, image_info->m_height, pImage);
#endif
return status;
}
jpeg_splash_t get_splash_image (void)
{
jpeg_splash_t splash_t;
splash_t.addr = 0;
splash_t.length = 0;
/*need to ask wu yihui how to load jpeg logo,get jpeg addr and length*/
return splash_t;
}
static unsigned long env_strtoul(const char *name, int base)
{
unsigned long ret = 0;
char *str = NULL;
str = env_get(name);
if (str) {
ret = simple_strtoul(str, NULL, base);
}
if (base == 16)
printf("%s: 0x%lx\n", name, ret);
else if (base == 10)
printf("%s: %ld\n", name, ret);
return ret;
}
static int jpeg_display(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
int ret;
jpeg_splash_t splash;
if (argc != 3) {
printf("jpeg display parameter num error\n");
return -1;
}
splash.addr = simple_strtoul(argv[1], NULL, 16);
splash.length = simple_strtoul(argv[1], NULL, 16);
fb_addr = (uint32_t *)get_fb_addr();
fb_width = env_strtoul("fb_width", 10);
if (!fb_addr || !fb_width) {
printf("get fb error\n");
return -1;
}
splash_rd_offset = 0;
ret = pjpeg_decode_init(&pjpeg, pjpeg_need_bytes_callback, (void *)&splash);
if (ret) {
printf("pjpeg_decode_init() failed with status %d.\n", ret);
if (ret == PJPG_UNSUPPORTED_MODE)
printf("Progressive JPEG files are not supported.\n");
return -1;
}
ret = pjpeg_decode(&pjpeg, (uint32_t *)fb_addr);
if (ret) {
printf("decode JPG image failed with status %d.\n", ret);
return -1;
}
return 0;
}
static int jpeg_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
int ret;
jpeg_splash_t splash;
char buf[16];
if (argc < 2) {
printf("Usage: jpeg info <addr>\n");
return CMD_RET_USAGE;
}
splash.addr = simple_strtoul(argv[1], NULL, 16);
splash.length = 0x1000;
splash_rd_offset = 0;
ret = pjpeg_decode_init(&pjpeg, pjpeg_need_bytes_callback, (void *)&splash);
if (ret) {
printf("Error: Failed to parse JPEG header (status %d)\n", ret);
return CMD_RET_FAILURE;
}
printf("jpeg image size :%d x %d\n", pjpeg.m_width, pjpeg.m_height);
//sprintf(buf, "%d", pjpeg.m_width);
//env_set("fb_width", buf);
//sprintf(buf, "%d", pjpeg.m_height);
//env_set("fb_height", buf);
sprintf(buf, "%d", pjpeg.m_comps == 1 ? 8 : 32);
env_set("display_bpp", buf);
env_set("display_color_index", buf);
return 0;
}
static cmd_tbl_t cmd_jpeg_sub[] = {
U_BOOT_CMD_MKENT(display, 3, 0, jpeg_display, "", ""),
U_BOOT_CMD_MKENT(info, 2, 0, jpeg_info, "", ""),
};
static int do_jpeg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
cmd_tbl_t *c;
argc--;
argv++;
c = find_cmd_tbl(argv[0], &cmd_jpeg_sub[0], ARRAY_SIZE(cmd_jpeg_sub));
if (c)
return c->cmd(cmdtp, flag, argc, argv);
else
return CMD_RET_USAGE;
}
U_BOOT_CMD(
jpeg, 5, 0, do_jpeg,
"jpeg sub-system",
"jpeg display - jpeg decode\n"
"jpeg info <addr> - get jpeg width and height\n"
);