📄 gif_decoder_v2.c
字号:
for(i=0; i<=my_info->LCT_size; i++)
{
kal_uint8 r,g,b;
kal_uint32 e;
r = GIF_GET_U8();
g = GIF_GET_U8();
b = GIF_GET_U8();
e = (r<<16)|(g<<8)|(b);
// replace MMI's source key color with XOR 1
if(cfg->out_format == GIF_OUT_RGB565)
{
kal_uint16 x;
x = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
if(x == cfg->src_key)
{
e ^= 0x8;
}
}
else // 888 and index color type
{
if(e == cfg->src_key)
{
e ^= 1;
}
}
cfg->LCT_adrs[i] = e;
}
}
// get minimum code size
my_info->min_code = GIF_GET_U8();
gif_decode_hw(cfg);
goto end;
}
break;
case GIF_TRAILER_LABEL: // 0x3b, trailer
gif_dcb.trailer = KAL_TRUE;
cache->total_fn = gif_dcb.cur_fn-1;
status = GIF_NO_FRAME;
gif_state = GIF_STATE_READY;
goto end;
}
} while(GIF_IS_EOF()!= KAL_TRUE);
end:
return status;
}
/*************************************************************************
* FUNCTION
* gif_decode_start
*
* DESCRIPTION
* start to decode a specified frame of a gif image (non blocking)
*
* PARAMETERS
*
* RETURNS
* GIF_DECODING
* GIF_INVALID_FORMAT
* GIF_NO_FRAME
*
* GLOBALS AFFECTED
* gif_dcb
*************************************************************************/
gif_report_status_enum gif_decode_start(gif_config_struct *cfg, gif_info_struct *info)
{
kal_uint32 offset;
gif_cache_struct *cache;
kal_bool cache_hit;
gif_report_status_enum status;
gif_info_struct *my_info = &gif_dcb.info;
ASSERT(gif_state == GIF_STATE_READY);
gif_state = GIF_STATE_BUSY;
// ASSERT(cfg->file_buffer_size >= GIF_MIN_FILE_BUF_SIZE);
ASSERT(cfg->gif_cb != NULL);
kal_mem_set(&gif_dcb, 0, sizeof(gif_dcb));
gif_dcb.cfg = cfg;
gif_dcb.gif_cb = cfg->gif_cb;
gif_last_disposal_method = 0;
if(cfg->decode_mode == GIF_DECODE_FILE)
{
gif_dcb.file_size = hw_bytestream_create_file(HW_BYTESTREAM_GIF, cfg->file_handle,(kal_uint8*)cfg->file_buffer_adrs, cfg->file_buffer_size);
if(gif_dcb.file_size)
{
if(gif_dcb.file_size > cfg->file_buffer_size)
gif_dcb.partial_enable = KAL_TRUE;
}
}
else // GIF_DECODE_MEMORY: the total gif file is in the memory
{
hw_bytestream_create(HW_BYTESTREAM_GIF,(kal_uint8*)cfg->file_buffer_adrs,cfg->file_buffer_size);
gif_dcb.file_size = cfg->file_buffer_size;
}
GIF_TRY
// get a cache
cache_hit = gif_get_cache(cfg->cache_id, &cache, KAL_TRUE);
offset = 0;
if( cache_hit == KAL_TRUE)
{
gif_get_cache_offset(cfg->frame_number,&offset);
if(cfg->frame_number > cache->total_fn || (offset+10) >= gif_dcb.file_size)
{
gif_state = GIF_STATE_READY;
return GIF_NO_FRAME;
}
GIF_SEEK(offset);
}
else
{
kal_uint8 a;
if(GIF_GET_U8()!= 'G' || GIF_GET_U8() != 'I' || GIF_GET_U8() != 'F')
{
kal_print("GIF_INVALID_FORMAT");
cache->id = 0;
status = GIF_INVALID_FORMAT;
gif_state = GIF_STATE_READY;
goto end;
}
GIF_FLUSH(3);
cache->lwidth = GIF_GET_U16();
cache->lheight = GIF_GET_U16();
a = GIF_GET_U8();
cache->GCT_flag = ((a&0x80) == 0x80);
cache->bpp = ((a&0x7)+1);
if(cfg->pack_enable == KAL_TRUE)
ASSERT(cache->bpp == 1 || cache->bpp == 2 || cache->bpp == 4 || cache->bpp == 8);
cache->GCT_size = (1 << (cache->bpp))-1; // 255 means 256
cache->bg_index = GIF_GET_U8();
GIF_FLUSH(1);
// retreive the golbal color table
if(cache->GCT_flag)
{
kal_uint32 i;
for(i=0; i<=cache->GCT_size; i++)
{
kal_uint8 r,g,b;
kal_uint32 e;
r = GIF_GET_U8();
g = GIF_GET_U8();
b = GIF_GET_U8();
e = (r<<16)|(g<<8)|(b);
// replace MMI's source key color with XOR 1 Blue
if(cfg->out_format == GIF_OUT_RGB565)
{
kal_uint16 x;
x = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
if(x == cfg->src_key)
{
e ^= 0x8;
}
}
else // 888 and index color type
{
if(e == cfg->src_key)
{
e ^= 1;
}
}
cache->GCT[i]=e;
}
}
cache->frame_offset[0] = GIF_TELL(NULL);
}
if(cfg->out_format == GIF_OUT_INDEX && cfg->GCT_adrs != NULL)
{
kal_mem_cpy(cfg->GCT_adrs,cache->GCT,sizeof(cache->GCT) );
}
my_info->lwidth = cache->lwidth;
my_info->lheight = cache->lheight;
my_info->GCT_flag = cache->GCT_flag;
my_info->GCT_size = cache->GCT_size;
my_info->bg_index = cache->bg_index;
my_info->bpp = cache->bpp;
status = gif_decode_process(cfg);
if(status == GIF_NO_FRAME)
cache->total_fn = cfg->frame_number -1;
*info = gif_dcb.info;
GIF_CATCH_BEGIN
gif_state = GIF_STATE_READY;
status = GIF_INVALID_FORMAT;
GIF_CATCH_END
end:
return status;
}
/*************************************************************************
* FUNCTION
* gif_decode_resume
*
* DESCRIPTION
* get resource memeory from caller(share the same resource with SW decoder)
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
* gif_dcb
*************************************************************************/
gif_report_status_enum gif_decode_resume(gif_config_struct *cfg, gif_info_struct *info)
{
hw_bytestream_dcb_struct *bytestream;
gif_status_enum int_status;
gif_report_status_enum status = GIF_DECODING;
// kal_uint32 offset;
GIF_TRY
int_status = gif_dcb.int_status;
if(int_status == GIF_STATUS_INEMPTY)
{
DRVPDN_Disable(DRVPDN_CON3,DRVPDN_CON3_GIF,PDN_GIF);
GIF_TELL(&bytestream);
GIF_FLUSH(bytestream->type.file.buffer_content_size);
GIF_REFILL();
gif_dcb.lzw_start = (kal_uint32)bytestream->type.file.buffer_ptr;
DRV_WriteReg32(GIF_INFILE_START_ADDR, gif_dcb.lzw_start);
DRV_WriteReg32(GIF_INFILE_COUNT, bytestream->type.file.buffer_size);
// status = GIF_DECODING;
GIF_START_TIMER();
GIF_RESUME();
}
else if(int_status == GIF_STATUS_COMPLETE)
{
status = gif_decode_process(cfg);
*info = gif_dcb.info;
}
GIF_CATCH_BEGIN
gif_state = GIF_STATE_READY;
status = GIF_INVALID_FORMAT;
GIF_CATCH_END
return status;
}
/*************************************************************************
* FUNCTION
* gif_decode_stop
*
* DESCRIPTION
* get resource memeory from caller(share the same resource with SW decoder)
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
* gif_dcb
*************************************************************************/
void gif_decode_stop(void)
{
gif_state = GIF_STATE_READY;
DRVPDN_Disable(DRVPDN_CON3,DRVPDN_CON3_GIF,PDN_GIF);
GIF_RESET();
DRVPDN_Enable(DRVPDN_CON3,DRVPDN_CON3_GIF,PDN_GIF);
}
// #define GIF_UINT_TEST
#if defined (GIF_UINT_TEST)
#include "lcd_if.h"
#include "lcd_sw.h"
#include "lcd_sw_inc.h"
#include "msdc_def.h"
#include "sd_def.h"
#include "rtfiles.h"
// unit test code start here
#define FILE_BUFFER_SIZE (32*1024)
#define OUT_BUFFER_SIZE (LCD_WIDTH*LCD_HEIGHT*2)
#define GIF_STACK_SIZE (0x1000+4)
#define GIF_TREE_SIZE (0x4000+4)
#define GIF_CT_SIZE (256) // x4
gif_config_struct gif_config;
gif_info_struct gif_info;
kal_uint8 in_buffer[FILE_BUFFER_SIZE];
kal_uint16 lcd_buffer[LCD_WIDTH*LCD_HEIGHT];
kal_uint16 lcd_buffer_i[LCD_WIDTH*LCD_HEIGHT];
kal_uint32 gif_tree[GIF_TREE_SIZE/sizeof(kal_uint32)];
kal_uint32 gif_stack[GIF_STACK_SIZE/ sizeof(kal_uint32)];
kal_uint32 gif_lct[GIF_CT_SIZE];
kal_uint8 file_name[256];
kal_wchar file_name_w[256];
kal_uint32 file_size;
#define GIF_NUM 4
gif_config_struct gif_cfg[GIF_NUM];
kal_uint8 in_buf[GIF_NUM][FILE_BUFFER_SIZE];
kal_uint8 f_name[GIF_NUM][256];
kal_wchar f_name_w[GIF_NUM][256];
kal_uint32 fs[GIF_NUM];
kal_eventgrpid GIF_Events;
gif_status_enum cb_status;
kal_uint32 cb_fn;
volatile kal_bool gif_stop_now = KAL_FALSE;
// test case 1: one file, in order
// test case 2: one image in memory, in order
// test case 3: one file in any order
// test case 4: one image in memory decoded in any order.
// test case 5: four images (2 files and 2 in memory) decoded in order.
// test case 6: 8 images (4 files and 4 in memory) decoded in any order.
// test case 7: one image more than 100 frames decoded in order
// test case 8: one image more than 100 frames decoded in order
// test case 9: various clip, resizing ratio, and dest_x, dest_y
// test case 10: pack mode
// test case 11: various output mode(RGB888) ???
// test case 12: decode a very large file of 1,792,163 bytes(it takes about 2.9s)
// test case 13: verify timeout mechanism
void GPT3_Init_my(void)
{
// clear pdn bit of GPT
DRV_Reg(0x80000324) = 1;
// set clock
DRV_Reg(0x80100024) = 4; // 4: 1k, 7: 125hz
// start free running
DRV_Reg(0x8010001c) = 1;
}
kal_uint32 GPT3_GetCount(void)
{
return DRV_Reg(0x80100020);
}
kal_uint32 GPT3_TimeDiff(kal_uint32 time1)
{
kal_uint32 time2;
time2 = DRV_Reg(0x80100020);
if(time2 >= time1)
return (time2 - time1);
return (0xffff - time1 + time2);
}
static void init_lcd_layer_window(void)
{
lcd_layer_struct layer_data = {0};
layer_data.source_key=0xFFFF;
layer_data.source_key_enable=KAL_FALSE;
layer_data.color_palette_enable=KAL_FALSE;
layer_data.color_palette_select=0;
layer_data.opacity_enable=KAL_FALSE;
layer_data.opacity_value=10;
layer_data.x_offset=0;
layer_data.y_offset=0;
layer_data.frame_buffer_address=(kal_uint32) lcd_buffer;
layer_data.row_number=LCD_HEIGHT;
layer_data.column_number=LCD_WIDTH;
layer_data.rotate_value=0;
layer_data.source_color_format = LCD_LAYER_SOURCE_COLOR_RGB565;
config_lcd_layer_window(0,&layer_data);
} /* init_lcd_layer_window() */
static void LCD_Init(void)
{
lcd_init(MAIN_LCD,0xF800);
init_lcd_layer_window();
SET_LCD_ROI_WINDOW_OFFSET(0,0);
SET_LCD_ROI_WINDOW_SIZE(LCD_WIDTH,LCD_HEIGHT);
memset(lcd_buffer, 0x55, sizeof lcd_buffer);
}
static void LCDDisplay_adrs( kal_uint16 w, kal_uint16 h, kal_uint16 x, kal_uint16 y, void* adrs)
{
lcd_frame_update_struct lcd_data;
lcd_power_up();
SET_LCD_LAYER0_WINDOW_SIZE(w,h);
SET_LCD_LAYER0_WINDOW_OFFSET(x,y);
REG_LCD_LAYER0_BUFF_ADDR = (kal_uint32) adrs;
lcd_data.module_id=LCD_UPDATE_MODULE_MEDIA;
lcd_data.lcd_id=MAIN_LCD;
lcd_data.fb_update_mode=LCD_SW_TRIGGER_MODE;
lcd_data.lcm_start_x=0;
lcd_data.lcm_start_y=0;
lcd_data.lcm_end_x=LCD_WIDTH-1;
lcd_data.lcm_end_y=LCD_HEIGHT-1;
lcd_data.roi_offset_x=0;
lcd_data.roi_offset_y=0;
lcd_data.update_layer=LCD_LAYER0_ENABLE;
lcd_fb_update(&lcd_data);
}
static void GIF_Display(void *adrs, kal_uint16 w, kal_uint16 h)
{
LCDDisplay_adrs(w,h,0,0,adrs);
}
kal_uint32 fast_semi_crc(kal_uint8* src,kal_uint32 size)
{
register kal_uint32 crc,temp,i;
crc = 0;
for(i=0;i<size;i++)
{
if(crc >>15) temp=1; else temp=0;
crc = (((crc<<1) & 0x0ffff) + temp) ^ (kal_uint32)*src;
src++;
}
return crc;
}
kal_uint32 gif_get_cache_key_from_file(kal_uint8* filename,kal_uint32 file_size)
{
// Compute the cache key by filename and file size
kal_uint32 cache_id;
cache_id = (kal_uint32) fast_semi_crc((kal_uint8 *) filename, (kal_uint32)strlen((char *)filename));
cache_id ^= (kal_uint32) file_size;
return cache_id;
}
void gif_callback(gif_status_enum status, kal_uint32 fn)
{
cb_status = status;
cb_fn = fn;
kal_set_eg_events(GIF_Events,1,KAL_OR);
}
// file mode, multi frame, no partila input, no resizing
void test_case_1(void)
{
gif_config_struct *p = &gif_config;
gif_report_status_enum status;
//sprintf(file_name, "c:\\gif\\test1.gif"); // single frame
sprintf(file_name, "c:\\gif\\3d_book2.gif"); // multi frame
kal_wsprintf(file_name_w,(char*)file_name);
p->decode_mode = GIF_DECODE_FILE;
p->file_handle = DRM_open_file(file_name_w,FS_READ_ONLY|FS_OPEN_NO_DIR,0);
if(p->file_handle < 0 )
ASSERT(0);
DRM_file_size(p->file_handle, &file_size);
p->cache_id = gif_get_cache_key_from_file(file_name, file_size);
p->file_buffer_adrs = in_buffer;
p->file_buffer_size = file_size;
p->output_buffer_adrs = (kal_uint8*)lcd_buffer;
p->output_buffer_size = sizeof lcd_buffer;
p->stack_adrs = gif_stack;
p->stack_size = GIF_STACK_SIZE;
p->tree_adrs = gif_tree;
p->tree_size = GIF_TREE_SIZE;
p->LCT_adrs = gif_lct;
p->shadow_w = LCD_WIDTH;
p->shadow_h = LCD_HEIGHT;
p->clip_x1 = 0;
p->clip_y1 = 0;
p->clip_x2 = LCD_WIDTH-1;
p->clip_y2 = LCD_HEIGHT-1;
p->dest_x = 0;
p->dest_y = 0;
p->expect_w = LCD_WIDTH;
p->expect_h = LCD_HEIGHT;
p->pack_enable = KAL_FALSE;
// 1:1 ratio (pack mode)
p->p_resz_w_Q = 0;
p->p_resz_w_N = 1;
p->p_resz_w_D = 0;
p->p_resz_h_Q = 0;
p->p_resz_h_N = 1;
p->p_resz_h_D = 0;
p->clip_enable = KAL_TRUE;
p->out_format = GIF_OUT_RGB565;
p->gif_cb = gif_callback;
p->frame_number = 0;
// decoding until GIF_NO_FRAME is occurs
while(1)
{
kal_uint32 flag;
status = gif_decode_start(p, &gif_info);
if(status == GIF_INVALID_FORMAT || status == GIF_NO_FRAME)
goto end;
kal_retrieve_eg_events(GIF_Events,(1),KAL_OR_CONSUME,&flag,KAL_SUSPEND);
while(1)
{
if(cb_status == GIF_STATUS_INEMPTY)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -