Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40782
  • 博文数量: 18
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-05 10:27
文章分类
文章存档

2011年(1)

2009年(1)

2008年(16)

我的朋友

分类:

2008-10-31 15:46:04

代碼分析之State_Slideshow

一、State分類

1.1 State ID及相應的處理程序入口

Smedia DPF V2 版本中,整個系統是由各種不同的State組成的,不同的State下響應不同的動作。在我們系統中,分為如下幾個State(在state.hstate.c裡面定義),用來控制各種界面下的動作:

typedef enum SMTK_STATE_ID_TAG

{

    SMTK_STATE_SPLASH,

    SMTK_STATE_MAINTOP,

    SMTK_STATE_THUMBNAIL,

    SMTK_STATE_BROWSE,

    SMTK_STATE_SLIDE_SHOW,

    SMTK_STATE_VIDEO,

    SMTK_STATE_AUDIO,

    SMTK_STATE_SYSTEMSETTING,

    SMTK_STATE_MENU,

    SMTK_STATE_CARD,

       SMTK_STATE_CLIENT,

    SMTK_STATE_POWER_OFF,

    SMTK_STATE_BURN_FLASH,

    SMTK_STATE_ALARM,

    SMTK_STATE_CALENDAR,

#ifdef SMTK_COIN_STATE_ENABLE

    SMTK_STATE_COIN,

#endif

} SMTK_STATE_ID;

 

static SMTK_STATE* stateEntries[] =

{

    &smtkSplashState,

    &smtkMainTopState,

    &smtkThumbnailState,

    &smtkBrowseState,

    &smtkSlideShowState,

    &smtkVideoState,

    &smtkAudioState,

    &smtkSystemSettingState,

    &smtkMenuState,

    &smtkCardState,

    &smtkClientState,

    &smtkPowerOffState,

    &smtkBurnFlashState,

    &smtkAlarmState,

    &smtkCalendarState,

#ifdef SMTK_COIN_STATE_ENABLE

    &smtkCoinState,

#endif

};

1  左邊為各種StateID,右邊為各種State的程序入口

1.2 State切換

首先分析系統中各個State切換,整個系統從MAIN函數開始執行(其流程圖可參考Smedia DPF SDK V2的幫助文檔),首先進入SMTK_STATE_BURN_FLASH,處理完這個狀態後,進入正常的開機啟動狀態SMTK_STATE_SPLASH,顯示開機Logo,最後進入SMTK_STATE_SLIDE_SHOW,以各種特效動態顯示圖片。

在系統中,用全局變量stateMgrState.c中定義)來標誌目前系統所處State,各個State之間切換都是調用函數smtkStateMgrChangeStateState.c)來實現的,在這個函數中進行各State的初使化操作stateMgr.currState->Initialize

 

下面介紹smtkSlideShowState下,系統中有的響應動作,並進行相關的代碼分析。

二、smtkSlideShowState分析

我們系統中對各種State的處理都包含三個部分(InitializeProcTerminate),其主要的處理都在文件state_*.csmtkSlideShowState的主要處理動作在文件state_slideshow.cslideshow.c裡面。

2.1 Initialize分析

各种State在切換時都要調用Initialize函數。系統中State的切換都是調用smtkStateMgrChangeState來完成的,下面是Initialize的流程圖,在smtkStateMgrChangeState函數中對stateMgr重新賦值,保存上一個state,並由stateMgr.currState = stateEntries[id]得到State的程序入口。

       其中,函數smtkSlideShowMgrInitializeSlideShow進行初始化,主要對SlideShow管理的結構體slideShowMgr和特效管理的結構體smtkEffectMgr進行設置。

       結構體定義:

 

/**

 * Slide show manager definition

 */

typedef struct SMTK_SLIDE_SHOW_MGR_TAG

{

    SMTK_SLIDE_SHOW_MGR_CONFIG*     cfg;

    SMTK_STATE_ID           stateId;       //State ID

    SLIDESHOW_FLAG          flag;        //indicate JPEG docode status

       MMP_UINT                currentIndex;     //Current JPEG Index

       MMP_BOOL                updated;    //Effect Updated or Move to next jpeg

       MMP_WCHAR*                         filename; //JPEG Filename

 

    /** for slideshow effect */

    MMP_UINT                changedCount;   // Finished change to next slide when it's count-down to zero

MMP_UINT                effectIndex;       //????Not used       

 

    // for unsupported picture

    MMP_UINT                decodeCounter;         //已經decodejpeg數量(不管docode是否成功)

    MMP_UINT                supportCounter;        //可以支持的jpeg數量

    MMP_UINT                allPicUnsupported;      // if all pictures are unsupported, turn this flag on

 

} SMTK_SLIDE_SHOW_MGR;

 

typedef struct SMTK_SLIDE_SHOW_MGR_CONFIG_TAG

{

    SMTK_CONFIG                     cfg;    // Config structure definition, Config id

    MMP_ULONG                       duration; //change duration

    SMTK_SLIDE_SHOW_DISPLAY_MODE    displayMode; //display mode

    SMTK_SLIDE_SHOW_EFFECT_CATALOG  effect;       //11 Effects

    MMP_BOOL                        bgm;  //background music

    MMP_BOOL                        autoSlideshow;  //autoSlideshow

} SMTK_SLIDE_SHOW_MGR_CONFIG;

 

 

typedef struct EFFECT__POS_TAG

{

    MMP_INT destX;

    MMP_INT destY;

    MMP_INT destX_Interval;

    MMP_INT destY_Interval;

    MMP_INT srcX;

    MMP_INT srcY;

    MMP_INT srcW;

    MMP_INT srcH;

    MMP_INT srcX_Interval;     //source X地址的邊界?

    MMP_INT srcY_Interval;     //source Y地址的邊界?

    MMP_INT srcW_Interval;     //source W step

    MMP_INT srcH_Interval;     //source H step

    MMP_INT stepCount;    //step Count, control x, y

} EFFECT_POS_CTRL;

 

/** Effect manager definition */

typedef struct SMTK_EFFECT_MGR_TAG

{

    MMP_SURFACE                     surfaces[2];    /**< The surfaces of performing the image effect from surface[0] to surface[1] */

    SMTK_SLIDE_SHOW_EFFECT_CATALOG  effectCatalog;  /**< The specified effect catalog */

    MMP_UINT                        effectItem;     /**< The specified item of the selected catalog */

    MMP_UINT                        actionCount;    /**< The action count of the current effect */

    MMP_INT                         destX;          /**< The starting point of the processed destination rectangle */

    MMP_INT                         destY;          /**< The starting point of the processed destination rectangle */

    MMP_UINT                        width;          /**< The width of the processed destination rectangle */

    MMP_UINT                        height;         /**< The height of the processed destination rectangle */

    MMP_INT                         srcX;           /**< The starting point of the processed source rectangle */

    MMP_INT                         srcY;           /**< The starting point of the processed source rectangle */

    MMP_INT                         srcWidth;       /**< The width of the processed source rectangle */

    MMP_INT                         srcHeight;      /**< The width of the processed source rectangle */

    SMTK_RECT                                             prevRect;       /**< The rectangle information for Zoom-Pan effect */

    MMP_INT                         zoomIn;         /**< The parameter for Zoom-Pan effect to indicate zoom-in or zoom-out */

} SMTK_EFFECT_MGR;

 

 

 

下面是smtkSlideShowMgrInitialize的流程圖:

上图中,函数smtkEffectMgrInitialize:分配了兩塊smtkEffectMgr.surfaces[0]smtkEffectMgr.surfaces[1]內存,供后面的特效操作时使用。JPEG解碼之後一般先保存在smtkEffectMgr.surfaces[1]內存中,特效的顯示,就是通過對這塊memory的內容進行分割、組合、copy等操作來完成的。

 

 

2.2 Proc分析

       下面對Proc的處理進行分析,Proc主要是處理各種Keypad、遙控器等相關EventEvent主要包括TimerKey兩種,在Proc主體中主要實現這兩種Event的處理。

       下面是Proc的流程圖:

      

1. Key Event

Key Event的處理是由函數Keydown_Slideshow來實現的,根據Key的不同,進行不同的處理,下面是函數Keydown_Slideshow(arg1)的流程圖:

 

在這個函數裡,遙控鍵Down, Up, Menu, Enter都將切換到Browse State(這應該是V2版本還不完善的原因),然後在BrowseState裡面實現左邊菜單的顯示和菜單的相關動作,包括

1.       Slide Show的幾種特效,這個主要是Timer Event;

2.       旋轉Rotation(直接用Rotation鍵還沒反應);

3.       返回smtkThumbnailState狀態

4.       上、下一張相片

5.       MENU,進入MainTop State

2. Timer Event

Timer Event的處理,主要由函數smtkSlideShowMgrDraw實現,這個函數的主要作用是:進行JPEG檔的decode操作,如果有背景音樂,則找到相應的mp3 Name並進行播放,如果JPEG已經decoded ready,則進行相關的Effect處理,下面是這個函數的流程圖:

      

. Start to decode jpeg file

下面是對Start to decode jpeg file操作的分析:先檢查slideShowMgr.changedCount 是否為零,並檢查slideShowMgr.flag是否為SLIDESHOW_FLAG_FORCE_DECODEforce to be decoded),如果滿足這兩個條件,則進行JPEG檔查找,並找到後對其進行decode的操作。

 

JPEG的解碼是由smtkJpegMgrStartDecode來完成的,其實它的操作就是設置一下smtkJpegShareData的各個屬性和smtkJpegMgr.informFlag。設置好之後,JPEG Decode線程ThreadFunc中會對這些參數進行判斷,並調用smtkJpegDecoderMgrProcess進行解碼操作。

 

. Effect Process

Slide Show State下,Timer Event體現為各種特效的顯示,具體的特效處理是在effect.c實現的。

Effect處理的結構體,分為三個部分StartStopDraw,這三個處理函數,其定義如下:

typedef struct EFFECT_FUNC_TAG

{

    EFFECT_START Start;   //設定特效參數

    EFFECT_STOP Stop;     //釋放,回收資源(這個其實沒有動作,一般都用StopNone)

    EFFECT_DRAW Draw;  //特效的具體實現

} EFFECT_FUNC;

Effect相关的操作有两个方面:一是如果JPEG Decode已经SMTK_JPEG_STATUS_DECODE_READY,则进行SlideshowUpdateEffectCtrl函数的调用,对Effect的相关参数进行设置Update,实际实现就是通过函数smtkEffectMgrStart来间接调用每一特效的Start函数; 二是smtkEffectMgr.actionCount不为0的时候,进行特效的具体实现,这部分是通过SlideshowProcessEffect来实现的,下面是它的程序流程图。

 

在我們系統中,實現了11種特效,在System/Effect菜單中可以設定你所需要的特效,各種物資的程序對應為下面的一個數組:

static const EFFECT_FUNC effects[] =

{

    { StartNone, StopNone, DrawNone },  //無特效

    { StartFade, StopNone, DrawFade },    //Fade特效

    { StartGreen, StopNone, DrawGreen }, //Gree特效

    { StartWipe, StopNone, DrawWipe },   //Wipe特效

    { StartSide, StopNone, DrawSide },     //Side特效

    { StartSideOut, StopNone, DrawSideOut },//SideOut特效

    { StartPush, StopNone, DrawPush },    //Push特效

    { StartExpand, StopNone, DrawExpand },//Expand特效

    { StartBlinds, StopNone, DrawBlinds },//Blinds特效

    { StartDissolve, StopNone, DrawDissolve },//Dissolve特效

    { StartControl, StopNone, DrawControl },   //Control特效

       { StartZoomPan, StopNone, DrawZoomPan },//Zoompan特效

    { StartRandom, StopNone, DrawNone },     //設定為Random的時候,隨機進行11種顯示

};

下面介紹一下Slide Show 11種特效,在程序中是用下面一個enum來定義的,在system菜單中可以設定所需Effect,下面是各種特效ID定義,各種Effect的具體處理在Effect.c文件裡面定義。

typedef enum SMTK_SLIDE_SHOW_EFFECT_CATALOG_TAG

{

    SMTK_SS_EFFECT_CATALOG_NONE,

    SMTK_SS_EFFECT_CATALOG_FADE,

    SMTK_SS_EFFECT_CATALOG_GREEN,

    SMTK_SS_EFFECT_CATALOG_WIPE,

    SMTK_SS_EFFECT_CATALOG_SIDE,

    SMTK_SS_EFFECT_CATALOG_SIDEOUT,

    SMTK_SS_EFFECT_CATALOG_PUSH,

    SMTK_SS_EFFECT_CATALOG_EXPAND,

    SMTK_SS_EFFECT_CATALOG_BLIND,

    SMTK_SS_EFFECT_CATALOG_DISSOLVE,

    SMTK_SS_EFFECT_CATALOG_CONTROL,

    SMTK_SS_EFFECT_CATALOG_ZOOMPAN,

    SMTK_SS_EFFECT_CATALOG_RANDOM,

    SMTK_SS_EFFECT_CATALOG_MAX,

} SMTK_SLIDE_SHOW_EFFECT_CATALOG;

下面針對各種特效的實現進行說明。其實特效的實現是通過smtkEffectMgr.surfaces[0]smtkEffectMgr.surfaces[1]兩塊memory的切換、切割、copy等操作來實現的,其中比較複雜的是切割大小,步長、顯示位置和顯示效果(透明等)的設置。涉及到相關數據結構有:

typedef union EFFECT_CTRL_TAG

{

    EFFECT_FADE_CTRL    fade;   //控制圖片顯示的透明度和Alpha變化step

    EFFECT_POS_CTRL     pos;     //Effect處理區域的相關設定

} EFFECT_CTRL;

1.             Fade

Fade 效果的實現主要是對Alpha進行相應的設置,實現幾種漸變的效果,這部分處理的實現分為二個部分:

StarFade: 设置smtkEffectMgr.actionCount, effectCtrl.fade.step, effectCtrl.fade.alpha, effectCtrl.pos.destX_Interval, effectCtrl.pos.srcY_Interval. 設定Alpha的值、變化的effectCtrl.fade.stepsmtkEffectMgr.actionCounteffectCtrl.pos的大小,控制透明度的顯示效果。

DrawFadeFade的處理可以細分為三種特效,SMTK_SS_EFFECT_FADE_INSMTK_SS_EFFECT_FADEIN_RLSMTK_SS_EFFECT_FADEIN_TB,它的實現主要是通過mmpM2dSourceCopymmpM2dAlphaBlend兩個函數來實現的。mmpM2dSourceCopy實現內存的拷貝,mmpM2dAlphaBlend進行Alpha的處理和處理後的內存拷貝,通過這兩個函數,在Timer Event下實現不同的處理效果。

SMTK_SS_EFFECT_FADE_IN: 整幅图渐变

SMTK_SS_EFFECT_FADEIN_RL:

左右交叉变化,左右同出两图,透明度渐强, 直至重叠

SMTK_SS_EFFECT_FADEIN_TB:

上下交叉变化,上下同出两图,透明度渐强, 直至重叠

调用函数: mmpM2dSourceCopy, mmpM2dAlphaBlend

 

2.             Green

3.             Wipe

4.             Side

5.             SideOut

6.             Push

7.             Expand

8.             Blinds

9.             Dissolve

10.         Control

11.         ZoomPan

 

DrawWipe:

SMTK_SS_EFFECT_WIPE_L2R:

先显示图片的右边部分,显示的宽度,越来越大,从左到右擦写旧图.

SMTK_SS_EFFECT_WIPE_R2L:

SMTK_SS_EFFECT_WIPE_R2L: 与上面过程左右互换

SMTK_SS_EFFECT_WIPE_T2B: 从上到下

SMTK_SS_EFFECT_WIPE_B2T: 从下往上

SMTK_SS_EFFECT_WIPE_IN: 左右同时往中间擦写

SMTK_SS_EFFECT_WIPE_H: 从下往上, 先显示图的下边区域

SMTK_SS_EFFECT_WIPE_OUT_V: 从右到左, 先显示图的右边区域

SMTK_SS_EFFECT_WIPE_OUT_CT: 从里往外擦写显示, 先显示中间区域

SMTK_SS_EFFECT_WIPE_IN_CT: 从外往内擦写显示, 先显示外围区域(实际上跟上一条一样的操作, 只是两图的显示顺序相反而已)

 

DrawSide:

SMTK_SS_EFFECT_SIDE_TL 左上角移到右下角,先显示图片的右下角

SMTK_SS_EFFECT_SIDE_TR 右上角移到左下角,先显示图片的左下角

SMTK_SS_EFFECT_SIDE_BL: 左下角移到右上角,先显示图片的右上角

SMTK_SS_EFFECT_SIDE_BR: 右下角移到左上角,先显示图片的左上角

 

DrawSideOut:

SMTK_SS_EFFECT_SIDEOUT_LR: 显示的区域的宽度越变越小,从左到右慢慢缩小显示范围

SMTK_SS_EFFECT_SIDEOUT_RL:从右往左移,旧图慢慢移出

SMTK_SS_EFFECT_SIDEOUT_TB SMTK_SS_EFFECT_SIDEOUT_LR相似

SMTK_SS_EFFECT_SIDEOUT_BT 从下往上移,旧图慢慢移出

 

DrawPush

SMTK_SS_EFFECT_PUSH_TL:新图把旧图从右边推出

SMTK_SS_EFFECT_PUSH_TR: 新圖把舊圖從右往左推出

SMTK_SS_EFFECT_PUSH_BL: 從上往下推

SMTK_SS_EFFECT_PUSH_BR:從下往上推

SMTK_SS_EFFECT_PUSH_4CORNER:從四個角推出。

 

       . Draw Environment Effect

       這個是實現邊框嗎?

2.3 Terminate分析

       每一個State都有一個TerminateFunction,這部分處理主要是實現了一種State的終止,一些資源的釋放,通常在smtkStateMgrChangeState進行State切換的時候調用。

       Slide Show State下,Terminate主要調用了兩個函數:

 

       函數smtkGuiMgrSyncDisplay主要實現了兩個顯示bufferdispSurfAdispSurfB的內容同步備份。函數smtkSlideShowMgrTerminate終止Slide Show的各種動作:如mp3播放,特效顯示等,其流程圖如下:

      

在函數smtkEffectMgrTerminate中刪除smtkEffectMgr.surfaces[0], smtkEffectMgr.surfaces[1]兩塊memory

阅读(711) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~