📄 gif_decoder_v2.c
字号:
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
/*
if(gif_dcb.info.transparent_index == gif_dcb.info.bg_index)
return KAL_FALSE;
*/
g2d_begin(G2D_OWNER_GDI,NULL);
dest.base_address = (kal_uint32)cfg->output_buffer_adrs;
dest.clip_x1 = cfg->clip_x1;
dest.clip_y1 = cfg->clip_y1;
dest.clip_x2 = cfg->clip_x2;
dest.clip_y2 = cfg->clip_y2;
switch(cfg->out_format)
{
case GIF_OUT_INDEX:
dest.color_mode = FIRE_DEST_COLOR_8BPP_LUT_DIS;
break;
default:
case GIF_OUT_RGB565:
dest.color_mode = FIRE_DEST_COLOR_16BPP_RGB565;
break;
case GIF_OUT_RGB888:
dest.color_mode = FIRE_DEST_COLOR_24BPP_RGB888;
break;
}
dest.pitch = cfg->shadow_w;
dest.height = cfg->shadow_h;
dest.width = cfg->shadow_w;
dest.x = 0;
dest.y = 0;
g2d_set_dest_buffer(G2D_OWNER_GDI, &dest);
data.start_x = cfg->dest_x;
data.start_y = cfg->dest_y;
data.width = cfg->expect_w;
data.height = cfg->expect_h;
r=DRV_Reg32(GIF_BG_COLOR)& 0xff;
g=(DRV_Reg32(GIF_BG_COLOR)& 0xff00)>>8;
b=(DRV_Reg32(GIF_BG_COLOR)& 0xff0000)>>16;
data.fill_color = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
data.gradient_fill_mode = KAL_FALSE;
data.tilt_mode = KAL_FALSE;
g2d_fill_rectangle(G2D_OWNER_GDI, &data);
g2d_end(G2D_OWNER_GDI);
return KAL_TRUE;
}
/*INTERNAL_FUNC kal_uint8 gif_resz_ratio(kal_uint16 real, kal_uint16 expect)
{
kal_uint32 ratio, i;
if(real <= expect || expect == 0)
{
return 0;
}
else
{
ratio = real/expect; // must > 1
if(ratio*(kal_uint32)expect < (kal_uint32)real)
ratio++;
i = 1;
while(i<16)
{
if(ratio <= (1<<i))
{
return (i);
}
else
{
i++;
}
}
return ((i-1));
}
}
*/
/*************************************************************************
* FUNCTION
* gif_decode_hw
*
* DESCRIPTION
* 1. decode one following frame
* 2. using polling instead interrupt event
*
* PARAMETERS
*
* RETURNS
* KAL_TRUE : a frame has been decoded
* KAL_FALSE: decode fail
*
* GLOBALS AFFECTED
* gif_dcb
*************************************************************************/
INTERNAL_FUNC void gif_decode_hw(gif_config_struct *cfg)
{
gif_info_struct *info = &gif_dcb.info;
kal_uint32 out_format = cfg->out_format;
kal_uint32 reg;
kal_uint8 resz_w, resz_h, ct_size;
hw_bytestream_dcb_struct *bytestream;
gif_cache_struct *cache = &gif_cache[gif_cache_index];
DRVPDN_Disable(DRVPDN_CON3,DRVPDN_CON3_GIF,PDN_GIF);
DRV_WriteReg32(GIF_IRQ_EN, GIF_IRQ_EN_OFF);
//GIF_RESET();
// the working buffer must be 4 byte aligned(remove after integration)
ASSERT(((kal_uint32)cfg->stack_adrs & 3 ) == 0);
ASSERT(((kal_uint32)cfg->tree_adrs & 3 ) == 0);
ASSERT(((kal_uint32)cfg->LCT_adrs & 3 ) == 0);
DRV_WriteReg32(GIF_TREE_START_ADDR, cfg->tree_adrs);
DRV_WriteReg32(GIF_TREE_END_ADDR, cfg->tree_adrs+cfg->tree_size);
DRV_WriteReg32(GIF_STK_START_ADDR, cfg->stack_adrs);
DRV_WriteReg32(GIF_STK_END_ADDR,cfg->stack_adrs+cfg->stack_size);
// DRV_WriteReg32(GIF_OUTFILE_START_ADDR, cfg->output_buffer_adrs);
// DRV_WriteReg32(GIF_OUTFILE_END_ADDR, cfg->output_buffer_adrs+ cfg->output_buffer_size);
DRV_WriteReg32(GIF_INFILE_COUNT, cfg->file_buffer_size);
// calculate the resize ratio
{
kal_uint32 bytes_per_pixel;
switch(cfg->out_format)
{
case GIF_OUT_INDEX: bytes_per_pixel=1;break;
case GIF_OUT_RGB565: bytes_per_pixel=2;break;
case GIF_OUT_RGB888: bytes_per_pixel=3;break;
default: bytes_per_pixel=1;break;
}
if(cfg->expect_w==0) cfg->expect_w = info->lwidth;
if(cfg->expect_h==0) cfg->expect_h = info->lheight;
cfg->cal_work_buffer_info_func(
&resz_w,
&info->wb_dest_x,&info->wb_dest_y,
&info->wb_width,&info->wb_height,
cfg->work_buffer_size / bytes_per_pixel,
info->lwidth,info->lheight,
cfg->dest_x,cfg->dest_y,
cfg->expect_w,cfg->expect_h,
cfg->clip_x1,cfg->clip_y1,cfg->clip_x2,cfg->clip_y2);
resz_h = resz_w;
}
info->use_work_buf = KAL_FALSE;
info->resz_w = resz_w;
info->resz_h = resz_h;
if((info->lwidth>>resz_w) != cfg->expect_w
||(info->lheight>>resz_h)!= cfg->expect_h)
info->use_work_buf = KAL_TRUE;
if(resz_w || resz_h)
{
gif_dcb.resz_enable = KAL_TRUE;
gif_dcb.resz_w = resz_w;
gif_dcb.resz_h = resz_h;
reg = (resz_h << 6)|(resz_w << 2)|1;
DRV_WriteReg32(GIF_RESZ_CTRL, reg);
}
else
{
DRV_WriteReg32(GIF_RESZ_CTRL, 0);
}
// configure the clipping
if(cfg->clip_enable)
{
kal_int32 x, y;
out_format |= GIF_OUT_FORMAT_CLIP_EN;
if(info->use_work_buf)
{
DRV_WriteReg32(GIF_LCD_WH, (info->wb_width<< 16)|info->wb_height);
DRV_WriteReg32(GIF_CLIP_XY, (0 << 16)|0);
DRV_WriteReg32(GIF_CLIP_WH, (info->wb_width<< 16)|info->wb_height);
x = info->wb_dest_x;
y = info->wb_dest_y;
}
else
{
DRV_WriteReg32(GIF_LCD_WH, ((cfg->shadow_w << 16)|cfg->shadow_h));
DRV_WriteReg32(GIF_CLIP_XY, ((cfg->clip_x1 << 16)|cfg->clip_y1));
DRV_WriteReg32(GIF_CLIP_WH, ((cfg->clip_x2- cfg->clip_x1+1)<< 16)|
(cfg->clip_y2- cfg->clip_y1+1));
x = cfg->dest_x ;
y = cfg->dest_y ;
}
if(x < 0 )
{
x *= -1;
x |= 0x8000;
}
if(y < 0 )
{
y *= -1;
y |= 0x8000;
}
DRV_WriteReg32(GIF_IMG_XY, ((x<< 16)|(y & 0xffff)));
DRV_WriteReg32(GIF_IMG_OFFSET_XY, (((info->x >> resz_w) << 16)|
(info->y >> resz_h)));
}
else
{
DRV_WriteReg32(GIF_IMG_XY, 0);
DRV_WriteReg32(GIF_IMG_OFFSET_XY, 0);
}
if(gif_dcb.partial_enable == KAL_TRUE)
out_format |= GIF_OUT_FORMAT_PARTIAL_EN;
if(cfg->pack_enable)
{
out_format |= (GIF_OUT_FORMAT_PACK_EN)|(info->bpp<< 9);
reg = cfg->p_resz_w_Q|(cfg->p_resz_w_N<<10)|(cfg->p_resz_w_D << 20);
DRV_WriteReg32(GIF_PACK_RESZ_W, reg);
reg = cfg->p_resz_h_Q|(cfg->p_resz_h_N<<10)|(cfg->p_resz_h_D << 20);
DRV_WriteReg32(GIF_PACK_RESZ_H, reg);
}
DRV_WriteReg32(GIF_MIN_CODE_SIZE, info->min_code);
DRV_WriteReg32(GIF_INTERLACE_CTRL, info->interlaced);
GIF_SET_WIDTH_HEIGHT(info->w,info->h);
if(info->LCT_flag)
{
DRV_WriteReg32(GIF_CT_START_ADDR, cfg->LCT_adrs);
ct_size = info->LCT_size;
}
else
{
DRV_WriteReg32(GIF_CT_START_ADDR, cache->GCT);
ct_size = cache->GCT_size;
}
if(!info->use_work_buf && info->transparent_flag && cfg->transparent_enable)
{
// always not output while encounter tc_index
reg = 3|(info->transparent_index << 2);
DRV_WriteReg32(GIF_TRANS_CTRL, reg);
}
else
{
DRV_WriteReg32(GIF_TRANS_CTRL, 0);
}
// set background color (RGB888) or index
if(out_format != GIF_OUT_INDEX)
{
if(cache->GCT_flag)
DRV_WriteReg32(GIF_BG_COLOR, cache->GCT[cache->bg_index]);
else
DRV_WriteReg32(GIF_BG_COLOR, 0xffffff); // use white color as the backgruoud color if no GCT
}
else
{
DRV_WriteReg32(GIF_BG_COLOR, cache->bg_index << 24);
}
// update the lzw start address and the input buffer count
GIF_TELL(&bytestream);
if(cfg->decode_mode == GIF_DECODE_FILE )
{
/* HW issue that the ipnut file count can't be too small */
if(bytestream->type.file.buffer_content_size<GIF_REFILL_THRESH)
GIF_REFILL();
gif_dcb.lzw_start = (kal_uint32)bytestream->type.file.buffer_reader;
DRV_WriteReg32(GIF_INFILE_START_ADDR,gif_dcb.lzw_start);
if(gif_dcb.partial_enable)
DRV_WriteReg32(GIF_INFILE_COUNT,bytestream->type.file.buffer_content_size);
}
else
{
gif_dcb.lzw_start = (kal_uint32)bytestream->type.mem.buffer_ptr+bytestream->type.mem.buffer_offset;
DRV_WriteReg32(GIF_INFILE_START_ADDR,gif_dcb.lzw_start);
}
DRV_WriteReg32(GIF_OUT_FORMAT, out_format);
if( info->use_work_buf)
{
kal_uint8 r,g,b;
kal_uint32 *ct;
kal_uint32 color, src_key,i;
// report src_key(transparent index)
// remove src_key color with different index
DRV_WriteReg32(GIF_OUTFILE_START_ADDR, cfg->work_buffer_adrs);
DRV_WriteReg32(GIF_OUTFILE_END_ADDR, cfg->work_buffer_adrs+ cfg->work_buffer_size);
ct = (kal_uint32*)DRV_Reg32(GIF_CT_START_ADDR);
color = ct[info->transparent_index];
b = (color)&0xff;
g = (color>>8)&0xff;
r = (color>>16)&0xff;
if(cfg->out_format == GIF_OUT_RGB888)
src_key = (r<<16)|(g<<8)|b;
else if(cfg->out_format == GIF_OUT_RGB565)
src_key = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
else // GIF_OUT_INDEX
src_key = info->transparent_index;
// remove the color of differnet trans.index but the same with transparent color
for(i=0;i<=ct_size;i++)
{
if(cfg->out_format == GIF_OUT_RGB888)
{
if(src_key == ct[i])
{
ct[i] ^= (1<<17);
}
}
else if(cfg->out_format == GIF_OUT_RGB565)
{
kal_uint32 r1,b1,g1;
kal_uint32 c;
b1 = (ct[i])&0xff;
g1 = (ct[i]>>8)&0xff;
r1 = (ct[i]>>16)&0xff;
c = ((r1>>3)<<11)|((g1>>2)<<5)|(b1>>3);
if( c == src_key)
{
ct[i] ^= (1<<20);
}
}
}
ct[info->transparent_index] = color; // restore again, because it was be changed.
info->src_key_2d = src_key;
}
else
{
DRV_WriteReg32(GIF_OUTFILE_START_ADDR, cfg->output_buffer_adrs);
DRV_WriteReg32(GIF_OUTFILE_END_ADDR, cfg->output_buffer_adrs+ cfg->output_buffer_size);
}
if(gif_dcb.cur_fn==0)
gif_last_disposal_method=gif_cur_disposal_method;
// handling the disposal method according the the previou frame.
if(cfg->disposal_en && (gif_last_disposal_method == GIF_RESTORE_BG))
gif_g2d_fillbg();
DRV_WriteReg32(GIF_IRQ_EN, GIF_IRQ_EN_ALL);
GIF_START_TIMER();
GIF_START();
}
/*************************************************************************
* FUNCTION
* gif_init
*
* DESCRIPTION
* get resource memeory from caller(share the same resource with SW decoder)
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
* gif_dcb
*************************************************************************/
void gif_init(void)
{
if(gif_hisr == 0)
{
//gif_hisr = kal_create_hisr("GIF_HISR",2,512,gif_hisr_entry,NULL);
VISUAL_Register_HISR(VISUAL_GIF_HISR_ID,gif_hisr_entry);
IRQ_Register_LISR(IRQ_GIF_CODE, gif_lisr_entry,"gif_lisr");
IRQSensitivity(IRQ_GIF_CODE,LEVEL_SENSITIVE);
}
IRQUnmask(IRQ_GIF_CODE);
// initialize the GPT
if(gif_gpt_handle == 0)
GPTI_GetHandle(&gif_gpt_handle);
gif_cache_counter = GIF_CACHE_INIT_COUTNER;
gif_state = GIF_STATE_READY;
}
/*************************************************************************
* FUNCTION
* gif_decode_process
*
* DESCRIPTION
* get resource memeory from caller(share the same resource with SW decoder)
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
* gif_dcb
*************************************************************************/
INTERNAL_FUNC gif_report_status_enum gif_decode_process(gif_config_struct *cfg)
{
gif_info_struct *my_info = &gif_dcb.info;
gif_cache_struct *cache = &gif_cache[gif_cache_index];
gif_report_status_enum status = GIF_DECODING;
gif_cur_disposal_method=GIF_NO_ACTION;
gif_get_last_disposal(gif_dcb.cur_fn,&gif_last_disposal_method);
do
{
switch(GIF_GET_U8())
{
case GIF_EXT_LABEL: // 0x21
if(GIF_GET_U8() == GIF_GCE_LABEL)
{ // Process the GIF extension block(GCE)(0xf9)
kal_uint8 a,b;
GIF_FLUSH(1);
a = GIF_GET_U8();
my_info->disposal = (a>>2)&7;
gif_cur_disposal_method=my_info->disposal;
my_info->delay_time = GIF_GET_U16();
b = GIF_GET_U8();
if(a&GIF_GCE_PACK_TC_FLAG )
{
my_info->transparent_index = b;
my_info->transparent_flag = KAL_TRUE;
}
else
{
my_info->transparent_flag = KAL_FALSE;
}
GIF_FLUSH(1);
}
else // skip other extensions
{
kal_uint32 len;
while(1)
{
len = GIF_GET_U8();
if(len ==0) break;
GIF_FLUSH(len);
}
}
break;
case GIF_IMD_LABEL: // 0x2C, ',' image descriptor
{
kal_uint8 a;
my_info->x = GIF_GET_U16();
my_info->y = GIF_GET_U16();
my_info->w = GIF_GET_U16();
my_info->h = GIF_GET_U16();
gif_dcb.timeout_period = GIF_TIMEOUT_PERIOD;
a = GIF_GET_U8();
my_info->LCT_flag = ((a&GIF_IMD_PACK_LCT_FLAG) != 0);
my_info->interlaced = ((a&GIF_IMD_PACK_INTERLACE) != 0);
if(my_info->LCT_flag)
{ // retreive the LCT
kal_uint32 i,bpp;
bpp = (a&GIF_IMD_PACK_LCT_SIZE) + 1;
my_info->bpp = bpp;
my_info->LCT_size = (1 << bpp)-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -