分类:
2008-10-31 15:46:04
在Smedia DPF V2 版本中,整個系統是由各種不同的State組成的,不同的State下響應不同的動作。在我們系統中,分為如下幾個State(在state.h,state.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 左邊為各種State的ID,右邊為各種State的程序入口
首先分析系統中各個State切換,整個系統從MAIN函數開始執行(其流程圖可參考Smedia DPF SDK V2的幫助文檔),首先進入SMTK_STATE_BURN_FLASH,處理完這個狀態後,進入正常的開機啟動狀態SMTK_STATE_SPLASH,顯示開機Logo,最後進入SMTK_STATE_SLIDE_SHOW,以各種特效動態顯示圖片。
在系統中,用全局變量stateMgr(State.c中定義)來標誌目前系統所處State,各個State之間切換都是調用函數smtkStateMgrChangeState(State.c)來實現的,在這個函數中進行各State的初使化操作stateMgr.currState->Initialize。
下面介紹smtkSlideShowState下,系統中有的響應動作,並進行相關的代碼分析。
我們系統中對各種State的處理都包含三個部分(Initialize、Proc、Terminate),其主要的處理都在文件state_*.c。smtkSlideShowState的主要處理動作在文件state_slideshow.c和slideshow.c裡面。
各种State在切換時都要調用Initialize函數。系統中State的切換都是調用smtkStateMgrChangeState來完成的,下面是Initialize的流程圖,在smtkStateMgrChangeState函數中對stateMgr重新賦值,保存上一個state,並由stateMgr.currState = stateEntries[id]得到State的程序入口。
其中,函數smtkSlideShowMgrInitialize對SlideShow進行初始化,主要對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; //已經decode的jpeg數量(不管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等操作來完成的。
下面對Proc的處理進行分析,Proc主要是處理各種Keypad、遙控器等相關Event。Event主要包括Timer,Key兩種,在Proc主體中主要實現這兩種Event的處理。
下面是Proc的流程圖:
對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
對Timer Event的處理,主要由函數smtkSlideShowMgrDraw實現,這個函數的主要作用是:進行JPEG檔的decode操作,如果有背景音樂,則找到相應的mp3 Name並進行播放,如果JPEG已經decoded ready,則進行相關的Effect處理,下面是這個函數的流程圖:
1. Start to decode jpeg file
下面是對Start to decode jpeg file操作的分析:先檢查slideShowMgr.changedCount 是否為零,並檢查slideShowMgr.flag是否為SLIDESHOW_FLAG_FORCE_DECODE(force to be decoded),如果滿足這兩個條件,則進行JPEG檔查找,並找到後對其進行decode的操作。
JPEG的解碼是由smtkJpegMgrStartDecode來完成的,其實它的操作就是設置一下smtkJpegShareData的各個屬性和smtkJpegMgr.informFlag。設置好之後,JPEG Decode線程ThreadFunc中會對這些參數進行判斷,並調用smtkJpegDecoderMgrProcess進行解碼操作。
2. Effect Process
Slide Show State下,Timer Event體現為各種特效的顯示,具體的特效處理是在effect.c實現的。
Effect處理的結構體,分為三個部分Start、Stop、Draw,這三個處理函數,其定義如下:
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.step和smtkEffectMgr.actionCount、effectCtrl.pos的大小,控制透明度的顯示效果。
DrawFade:Fade的處理可以細分為三種特效,SMTK_SS_EFFECT_FADE_IN,SMTK_SS_EFFECT_FADEIN_RL,SMTK_SS_EFFECT_FADEIN_TB,它的實現主要是通過mmpM2dSourceCopy,mmpM2dAlphaBlend兩個函數來實現的。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_R
SMTK_SS_EFFECT_WIPE_R
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:從四個角推出。
3. Draw Environment Effect
這個是實現邊框嗎?
每一個State都有一個Terminate的Function,這部分處理主要是實現了一種State的終止,一些資源的釋放,通常在smtkStateMgrChangeState進行State切換的時候調用。
在Slide Show State下,Terminate主要調用了兩個函數:
函數smtkGuiMgrSyncDisplay主要實現了兩個顯示bufferdispSurfA,dispSurfB的內容同步備份。函數smtkSlideShowMgrTerminate終止Slide Show的各種動作:如mp3播放,特效顯示等,其流程圖如下:
在函數smtkEffectMgrTerminate中刪除smtkEffectMgr.surfaces[0], smtkEffectMgr.surfaces[1]兩塊memory。