📄 gif_decoder.c
字号:
else if(status & GIF_STATUS_END) // truncated gif file
{
//ASSERT(0);
return GIF_TRUNCATED_FILE;
}
else if(gif_dcb.is_timeout) // hw decoder failed to decode the gif file
{
//ASSERT(0);
return GIF_DECODE_TIMEOUT;
}
//ASSERT(0);
return GIF_FORMAT_ERROR;
}
/*************************************************************************
* FUNCTION
* GIF_G2D_FillBG
*
* DESCRIPTION
* Fill the logical screen with specified position and background color
*
* PARAMETERS
* gif_para_struct: specifying configuration parameters
* gif_info_struct: specifying logical screen size and background color
* RETURNS
* gif_error_enum
*
* GLOBALS AFFECTED
* gif_dcb
*
*************************************************************************/
kal_bool GIF_G2D_FillBG(const gif_para_struct *s, gif_info_struct *info)
{
g2d_parameter_struct g2d;
// out of clip window
if((s->dest_x+info->lwidth-1)< s->clip_x1)
return KAL_FALSE;
if(s->dest_x > s->clip_x2)
return KAL_FALSE;
if((s->dest_y+info->lheight-1) < s->clip_y1)
return KAL_FALSE;
if(s->dest_y > s->clip_y2)
return KAL_FALSE;
if(s->dest_x < 0)
{
g2d.dest_x = 0;
g2d.dest_width = info->lwidth+s->dest_x;
}
else
{
g2d.dest_x = s->dest_x;
g2d.dest_width = info->lwidth;
}
if(s->dest_y < 0)
{
g2d.dest_y = 0;
g2d.dest_height = info->lheight+s->dest_y;
}
else
{
g2d.dest_y = s->dest_y;
g2d.dest_height = info->lheight;
}
g2d.clip_start_x = s->clip_x1;
g2d.clip_start_y = s->clip_y1;
g2d.clip_end_x = s->clip_x2;
g2d.clip_end_y = s->clip_y2;
// g2d.dest_pitch = s->shadow_width*2;
g2d.dest_pitch_width = s->shadow_width;
// g2d.dest_base_address = (kal_uint32)s->shadow_adrs+(s->shadow_width*g2d.dest_y+g2d.dest_x)*2;
g2d.dest_base_address = (kal_uint32)s->shadow_adrs;
g2d.dest_color_mode = G2D_DEST_16BPP_LUT_DISABLE;
g2d.src_color_mode = G2D_SRC_16BPP_LUT_DISABLE;
g2d.clip_mode = G2D_CLIP_ENABLE;
g2d.pat_fg_color = info->bg_color;
g2d.g2d_operation_mode=G2D_OPERATION_RECTANGLE_FILL;
g2d_accelerator(&g2d);
return KAL_TRUE;
}
/*************************************************************************
* FUNCTION
* GIF_G2D_BitBlt
*
* DESCRIPTION
* Copy the frame into logical screen with transparent color
*
* PARAMETERS
* gif_para_struct: specifying configuration parameters
* gif_info_struct: specifying logical screen size and transparent flag
* RETURNS
* gif_error_enum
*
* GLOBALS AFFECTED
* gif_dcb
*
*************************************************************************/
void GIF_G2D_BitBlt(const gif_para_struct *s, gif_info_struct *info)
{
g2d_parameter_struct g2d;
if((s->dest_x+info->x) < 0)
{
if((s->dest_x+info->x+info->width-1) < 0)
return;
g2d.src_x = -1*(s->dest_x+info->x);
g2d.src_width = info->width+s->dest_x+info->x;
g2d.dest_x = 0;
}
else
{
g2d.src_x = 0;
g2d.src_width =info->width;
g2d.dest_x = s->dest_x+info->x;
}
if((s->dest_y+info->y) < 0)
{
if((s->dest_y+info->y+info->height-1) <0)
return;
g2d.src_y = -1*(s->dest_y+info->y);
g2d.src_height = info->height+s->dest_y+info->y;
g2d.dest_y = 0;
}
else
{
g2d.src_y = 0;
g2d.src_height = info->height;
g2d.dest_y = s->dest_y+info->y;
}
// g2d.src_pitch = info->width*2;
g2d.src_pitch_width = info->width;
g2d.src_key_color = GIF_SOFTKEY;
g2d.dest_width = g2d.src_width;
g2d.dest_height = g2d.src_height;
// g2d.dest_pitch = s->shadow_width*2;
// g2d.src_base_address = (kal_uint32)s->work_adrs+((g2d.src_y*info->width)+g2d.src_x)*2;
// g2d.dest_base_address = (kal_uint32)s->shadow_adrs+((g2d.dest_y*s->shadow_width)+g2d.dest_x)*2;
g2d.dest_pitch_width = s->shadow_width;
g2d.src_base_address = (kal_uint32)s->work_adrs;
g2d.dest_base_address = (kal_uint32)s->shadow_adrs;
g2d.clip_start_x = s->clip_x1;
g2d.clip_start_y = s->clip_y1;
g2d.clip_end_x = s->clip_x2;
g2d.clip_end_y = s->clip_y2;
g2d.src_color_mode = G2D_SRC_16BPP_LUT_DISABLE;
g2d.dest_color_mode = G2D_DEST_16BPP_LUT_DISABLE;
g2d.clip_mode = G2D_CLIP_ENABLE;
g2d.bitblt_mode = BITBLT_TRANSFORM_COPY;
g2d.src_key_mode = gif_dcb.gif_info.transparent_flag;
g2d.g2d_operation_mode=G2D_OPERATION_BITBLT;
g2d_accelerator(&g2d);
}
/*************************************************************************
* FUNCTION
* GIF_Display_HW
*
* DESCRIPTION
* Display a GIF frame with specified parameters
*
* PARAMETERS
* gif_para_struct: specifying configuration parameters
* gif_info_struct: specifying logical screen size and transparent flag
* RETURNS
* gif_error_enum
*
* GLOBALS AFFECTED
* gif_dcb
*
*************************************************************************/
kal_int32 GIF_Display_HW(gif_para_struct *s, gif_info_struct *info)
{
kal_uint8 *GIF_src, *GIF_end;
kal_uint32 n;
gif_disposal_enum gif_disposal;
kal_int32 status;
kal_uint32 *ptr;
//ENTER_CRITICAL();
ASSERT(gif_dcb.state == GIF_STATE_READY);
gif_dcb.state = GIF_STATE_BUSY;
//EXIT_CRITICAL();
if( (s->frame_number != 0)&&
(gif_dcb.frame_counter == 0)&&
(s->reset == KAL_FALSE))
ASSERT(0);
if( (s->clip_x1 > s->clip_x2)||
(s->clip_y1 > s->clip_y2))
return GIF_FINISH_FRAME;
//ASSERT(0);
if(s->reset || (s->frame_number == 0))
{
gif_dcb.img_adrs = s->img_adrs;
gif_dcb.current_adrs = s->img_adrs;
gif_dcb.img_end = s->img_adrs+s->img_size;
GIF_Reset();
}
if(gif_dcb.trailer )
{
status = GIF_NO_FRAME;
goto gif_display_end;
}
// initial guard pattern for stack and tree memorys(for every frame)
ptr = (kal_uint32*)(gif_resource.stack+gif_resource.stack_size-4);
*ptr = GIF_GUARD_PATTERN;
ptr = (kal_uint32*)(gif_resource.tree+gif_resource.tree_size-4);
*ptr = GIF_GUARD_PATTERN;
GIF_src = gif_dcb.current_adrs;
GIF_end = gif_dcb.img_end;
if(gif_dcb.frame_counter == 0)
{
// check gif header
if(GIF_src[0] != 'G' || GIF_src[1] != 'I' || GIF_src[2] != 'F')
{
status = GIF_FORMAT_ERROR;
goto gif_display_end;
}
n = GIF_src[10]; // pack field of LSD
GIF_src += 13;
/* skip the global color palette */
if(n&0x80)
{
n=1<<((n&0x7)+1); // GCT size
GIF_src += 3*n;
}
else
{
//dbg_print("!!!! NO GCT EXIST!!!!\r\n");
//ASSERT(0); // not exist of GCT
}
}
if(GIF_src >= (GIF_end))
{
status = GIF_NO_FRAME;
goto gif_display_end;
}
do
{
kal_uint16 w,h;
switch(*GIF_src++)
{
case '!': // 0x21
if(*GIF_src++==0xf9)
{ // Process the GIF extension block(GCE)
if(GIF_src[1]&0x01)
{
gif_dcb.gif_info.transparent_index = GIF_src[4];
gif_dcb.gif_info.transparent_flag = 1;
}
// use disposal method specified by gif file or user
if(s->disposal_force == GIF_MTK_NO_ACTION)
gif_disposal = (GIF_src[1]&0x1c)>>2;
else
gif_disposal = s->disposal_force;
//dbg_print("disposal %d!\r\n",gif_disposal);
// return delay time
gif_dcb.gif_info.delay_time = GIF_src[2];
GIF_src+=6;
}
else // skip other extensions
{
int offset;
while(1)
{
offset= *GIF_src++;
if(offset==0) break;
GIF_src += offset;
}
}
break;
case ',': // 0x2C, image descriptor
w = (kal_uint16)(GIF_src[5]<< 8)|(kal_uint16)GIF_src[4];
h = (kal_uint16)(GIF_src[7]<< 8)|(kal_uint16)GIF_src[6];
if(w*h*2 > s->work_size)
{
//dbg_print("working memory is not enough, WxH: %dx%d\r\n", w,h);
//ASSERT(0);
status = GIF_MEM_INSUFFICEITN;
goto gif_display_end;
}
gif_dcb.timeout_period = 100 * ((w*h)/(640*480)+1); // 1 second per (640x480)
GIF_src += 8;
// skip LCT if exist
n = *GIF_src++;
if(n&0x80)
{
n=1<<((n&0x7)+1);
GIF_src += n*3;
}
// skip LZW code size
GIF_src++;
// skip data blocks
do{
n = *GIF_src++;
GIF_src += n;
}while(n != 0);
// trigger hw decoder
DRVPDN_Disable(DRVPDN_CON3,DRVPDN_CON3_GIF,PDN_GIF);
if(gif_dcb.frame_counter == 0)
{
status = GIF_DecodeFirst(s->img_adrs,(void*)s->work_adrs, s->img_size);
}
else
{
status = GIF_DecodeNext((void*)s->work_adrs);
}
if(status < 0)
goto gif_display_end;
if(w != gif_dcb.gif_info.width ||
h != gif_dcb.gif_info.height)
{
status = GIF_HW_DECODE_FAIL;
goto gif_display_end;
}
if(status == GIF_LAST_FRAME)
{
gif_dcb.trailer = KAL_TRUE; // hardware detect the trailer
}
else if(GIF_src[0] == 0x3B||GIF_src[1] == 0x3B)
{
gif_dcb.trailer = KAL_TRUE; // software detect the trailer
}
if(/*gif_dcb.frame_counter == 0 || */gif_disposal == GIF_RESTORE_BG)
{
kal_bool tmp;
if(!s->decode_test)
{
tmp = GIF_G2D_FillBG(s,&gif_dcb.gif_info);
if( tmp == KAL_FALSE)
{
if(gif_dcb.trailer == KAL_TRUE)
status = GIF_LAST_FRAME;
else
status = GIF_OUT_OF_RANGE;
goto gif_display_end;
}
}
}
if(!s->decode_test)
GIF_G2D_BitBlt(s,&gif_dcb.gif_info);
if(s->frame_number == gif_dcb.frame_counter)
{
gif_dcb.frame_counter++;
gif_dcb.current_adrs = GIF_src;
if(gif_dcb.trailer == KAL_TRUE)
status = GIF_LAST_FRAME;
goto gif_display_end;
}
gif_dcb.frame_counter++;
break;
case ';': // 0x3b, trailer
//dbg_print("SW file finish!\r\n");
gif_dcb.trailer = KAL_TRUE;
status = GIF_LAST_FRAME;
goto gif_display_end;
break;
}
if(gif_dcb.trailer)
{
status = GIF_LAST_FRAME;
goto gif_display_end;
}
} while(GIF_src < GIF_end);
status = GIF_TRUNCATED_FILE;
gif_display_end:
if(status < 0)
GIF_Reset();
if(status == GIF_LAST_FRAME)
{
if(s->frame_number > (gif_dcb.frame_counter-1))
status = GIF_NO_FRAME;
}
*info = gif_dcb.gif_info;
gif_dcb.state = GIF_STATE_READY;
DRVPDN_Enable(DRVPDN_CON3,DRVPDN_CON3_GIF,PDN_GIF);
return status;
}
#endif // MT6219
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -