tcpmp 編譯 源代碼分析

TCPMP源代碼分析

TCPMP源代碼分析

??? ?播放器主要由核心框架模塊(common工程)和解碼器、分離器插件組成。TCPMP的插件非常多,其中主要的插件有:interface插件實現了TCPMP的界面,ffmpeg是系統主要的音視頻解碼模塊,splitter是媒體文件分離器。

???? 由于ffmpeg的解碼效率不高,系統僅使用了ffmpeg的部分功能。并且未使用其中的libavformat模塊,而使用splitter模塊進行。其他插件暫時沒有研究。本周主要分析的是common工程。

????? common工程是核心模塊,是一個開放的集數據輸入、轉換、音/視頻解碼、信號輸出等功能為一體的完整的多媒體播放框架。這個框架自身不包含任何的Decode和Split功能,這些功能由插件實現,核心模塊以一個樹狀結構管理所有的功能模塊和插件模塊,實現數據Render功能,對輸入、轉換、輸出流程的控制,接受播放過程中的操作和對事件進行處理,同時也實現系統運行中經常使用的一些共用函數,比如解碼過程中經常使用的逆離散余弦變換,內存操作,界面中需要使用的多語言字符處理等。

????? common工程的主目錄下主要有:blit、dyncode、overlay、pcm、softidct、win32、zlib等子目錄。其中blit和overlay存放是視頻信號渲染模塊,pcm存放PCM音頻信號轉換模塊,softidct存放逆離散余弦變換函數,win32存放內存操作等常用模塊,dyncode這個目錄的代碼比較晦澀,存放的是程序運行時動態生成代碼模塊,針對不同的CPU指令集,PCM數據聲道和采樣率不同,視頻渲染數據格式和色深等不同情況動態生成不同的優化代碼,zlib則提供了內存中壓縮和解壓縮的函數,包括未壓縮數據的完整性檢查。

以下是common工程核心模塊中幾個重要的概念:
(1)上下文對象context
?? 該對象在初始化函數bool_t Context_Init中創建了一個該對象實例(context.h)。該對象實例記錄管理各個功能模塊,用戶界面可以通過該對象和核心模塊交互,管理控制播放過程。

(2)功能模塊
???? 功能模塊包括定義對象nodedef和數據對象node,定義對象描述功能模塊相互間的邏輯結構,數據對象記錄模塊屬性和方法。所有的功能模塊結構按一個樹狀結構來組織,結構關系如下,NODE是整個結構的根結點,其下為子節點,節點按類型可分為實節點,全局節點,設置節點,抽象節點。

???? 抽象節點沒有對應的對象實例,類似C++的抽象基類,為了按照邏輯關系組織系統結構而存在,例如NODE就是抽象節點。全局節點只有一個對象的實例,如播放控制模塊PLAYER_ID。設置節點表示和系統播放設置相關,比如聲音均衡器模塊EQUALIZER_ID,顏色控制模塊COLOR_ID。實節點與抽象節點不同,指可以生成對象實例的節點,實節點沒有特殊標識,一般以數據對象占用內存大小表示是否是一個實節點,創建節點時要根據該信息分配內存單元,實節點也可以有子節點,例如:MMS_ID的父節點是HTTP_ID。全局節點,設置節點和實節點可以相互組合,比如播放控制節點同時是全局節點,設置節點和實節點。

下面是主要的節點樹狀分布圖:

NODE (根節點)
??? ├─FLOW (流控制模塊)
??? │? ├─CODEC (解碼模塊)
??? │? │? ├─EQUALIZER_ID (聲音均衡器模塊)
??? │? │? ├─VBUFFER_ID (視頻緩沖模塊)
??? │? │? ├─DMO (DirectX Media Object)
??? │? │? │? ├─WMV_ID
??? │? │? │? ├─WMS_ID
??? │? │? │? ├─WMVA_ID
??? │? │? │? ├─WMA_ID
??? │? │? │? └─WMAV_ID
??? │? │? ├─FFMPEG VIDEO (FFMpeg 解碼模塊)
??? │? │? └─LIBMAD_ID (Libmad Mp3解碼模塊)
??? │? ├─OUT (信號渲染模塊)
??? │? │? ├─AOUT (音頻信號渲染)
??? │? │? │? ├─NULLAUDIO_ID
??? │? │? │? └─WAVEOUT_ID
??? │? │? └─VOUT (視頻信號渲染)
??? │? │????? ├─NULLVIDEO_ID
??? │? │????? └─OVERLAY
??? │? ├─IDCT (離散余弦解碼模塊)
??? │? │? └─SOFTIDCT_ID
??? │? └─CODECIDCT(離散余弦解碼模塊,函數比IDCT要少)
??? │????? └─MPEG1_ID
??? ├─MEDIA (媒體文件格式編碼解析模塊)
??? │? ├─FORMAT (格式解析模塊)
??? │? │? └─FORMATBASE
??? │? │????? ├─RAWAUDIO
??? │? │????? │? └─MP3_ID
??? │? │????? ├─RAWIMAGE
??? │? │????? ├─ASF_ID
??? │? │????? ├─AVI_ID
??? │? │????? ├─MP4_ID
??? │? │????? ├─MPG_ID
??? │? │????? ├─NSV_ID
??? │? │????? └─WAV_ID
??? │? ├─PLAYLIST (播放列表模塊)
??? │? │? ├─ASX_ID
??? │? │? ├─M3U_ID
??? │? │? └─PLS_ID
??? │? └─STREAMPROCESS (數據流處理模塊)
??? ├─STREAM (數據輸入模塊)
??? │? ├─MEMSTREAM_ID (內存數據流模塊)
??? │? ├─FILE_ID (文件IO模塊)
??? │? └─HTTP_ID (網絡數據獲取模塊)
??? ├─TIMER (定時器模塊)
??? │? └─SYSTIMER_ID
??? ├─ASSOCIATION_ID (文件擴展名自動關聯模塊)
??? ├─ADVANCED_ID (高級設置模塊)
??? ├─COLOR_ID (顏色控制模塊)
??? ├─PLATFORM_ID (平臺信息模塊)
??? ├─XSCALEDRIVER_ID
??? ├─PLAYER_ID (播放控制模塊)
??? └─PLAYER_BUFFER_ID (播放緩沖模塊)

以下是common工程核心模塊的幾個重要數據結構:
(1)context 上下文對象
typedef struct context

{

?? int Version;//版本信息

?? uint32_t ProgramId;//應用程序句柄

?? const tchar_t* ProgramName;//應用程序名稱

?? const tchar_t* ProgramVersion;//程序版本號,字符串

?? const tchar_t* CmdLine;//程序命令行信息

?? void* Wnd;//視頻渲染窗口句柄

?? void* NodeLock;//功能模塊訪問臨界區互斥變量

?? array Node; //功能模塊數據對象數組

?? array NodeClass; // ordered by id功能模塊定義對象數組,按照系統邏輯關系組織

?? array NodeClassPri; // ordered by priority|id功能模塊定義對象數組,按照系統邏輯關系和優先級排列

?? array NodeModule;//外部插件模塊數組

?? int LoadModuleNo;//當前正在加載的外部插件序號

?? void* LoadModule;//當前正在加載的外部插件

?? array StrTable[2];//字符串資源數組,字符串分為:給底層使用的標準字符串資源、給界面使用的顯示字符串資源,兩個資源用兩個數組表示

?? array StrBuffer;

?? array StrModule;//未使用

?? void* StrLock;//字符串數組訪問臨界區互斥變量

?? uint32_t Lang;//當前使用語言標志

?? int CodePage;//當前使用代碼頁標志

?? struct pcm_soft* PCM;//PCM音頻信號轉換模塊

?? struct blitpack* Blit;//視頻信號渲染模塊

?? struct node* Platform;//得到平臺相關信息

?? struct node* Advanced;//得到播放模塊高級信息

?? struct node* Player;//播放控制模塊

?? notify Error;//信息錯誤回調函數

?? int (*HwOrientation)(void*);

?? void *HwOrientationContext;

?? bool_t TryDynamic;//未使用

?? int SettingsPage;//未使用

?? size_t StartUpMemory;//可以使用的有效內存數

?? bool_t InHibernate;//是否進入休眠狀態

?? bool_t WaitDisable;//未使用

?? int FtrId;//未使用

?? bool_t LowMemory;//可以使用的有效內存數是否小于系統要求的最低要求

?? //動態代碼生成中間狀態及數據

?? bool_t CodeFailed;

?? bool_t CodeMoveBack;

?? bool_t CodeDelaySlot;

?? void* CodeLock;

?? void* CodeInstBegin;

?? void* CodeInstEnd;

?? int NextCond;

?? bool_t NextSet;

?? bool_t NextByte;

?? bool_t NextHalf;

?? bool_t NextSign;

?? uint32_t* FlushCache;//未使用

?? void* CharConvertUTF8;//未使用

?? void* CharConvertCustom;//未使用

?? int CustomCodePage;//未使用

?? void* CharConvertAscii;//未使用

?? void* Application;

?? void* Logger;//未使用

?? bool_t KeepDisplay;//是否保持背光長亮

?? int DisableOutOfMemory;//未使用

?

} context;

(2)nodedef? 功能模塊定義對象
功能模塊樹狀結構通常由若干個靜態定義對象(nodedef)實例實現,
typedef struct nodedef

{

??????? int???? Flags;//功能模塊節點的類型:抽象、實節點、全局、設置。

??????? int???? Class;//功能模塊節點的標識,如MEDIA_CLASS或ASF_ID等等。

??????? int???? ParentClass;//功能模塊父節點的標識,如SYSTIMER_ID對象的父節點是TIMER_CLASS。

??????? int???? Priority;//表示功能模塊節點優先級。

??????? nodecreate Create;//創建功能模塊定義對象的函數指針

??????? nodedelete Delete;//銷毀功能模塊定義對象的函數指針

?

} nodedef;//功能模塊定義對象

?

如解碼器功能模塊靜態定義對象:

static const nodedef Codec =

{

??????? sizeof(codec)|CF_ABSTRACT,

??????? CODEC_CLASS,

??????? FLOW_CLASS,

??????? PRI_DEFAULT,

??????? (nodecreate)Create,

??????? (nodedelete)Delete,

};

(3)nodeclass? 功能模塊定義對象鏈表結構
用鏈表的方式實現了功能模塊樹狀結構,每個鏈表代表樹狀結構的一個分支。

typedef struct nodeclass

{

??????? nodedef Def;//功能模塊定義對象

??????? bool_t Registered;//是否注冊

??????? int ModuleNo;//模塊標識

??????? struct nodeclass* Parent;//功能模塊定義對象的父對象

?

} nodeclass;//功能模塊定義節點對象鏈表結構

(4)node? 功能模塊數據對象
typedef struct node

{

??????? int???????????????????? Class;//功能模塊節點的類型,如MEDIA_CLASS等等,與nodedef相同。

??????? nodeenum? Enum;//枚舉節點屬性函數指針

??????? nodeget???????????? Get;//獲取節點屬性的函數指針

??????? nodeset???????????? Set;//設置節點屬性的函數指針

?

} node;//功能模塊數據對象

?

上述幾個數據對象的相互關系:

??????? 在系統上下文對象context中有兩個元素記錄功能模塊信息array Node和array NodeClass,array是數組數據類型(在buffer.h/c中定義和實現),Node是功能模塊數據對象的數組,NodeClass功能模塊定義對象的數組,按照系統邏輯關系組織。

??????? 創建功能模塊時傳入nodedef對象到功能模塊創建函數,函數會根據nodedef信息生成對應nodeclass對象添加到NodeClass數組,同時根據nodedef信息分配數據對象的內存空間。在該節點的Create函數里面再初始化該功能模塊的數據對象node。

?

(5)datadef 功能模塊屬性
typedef struct datadef

{

??????? int???? No;//屬性的標識,如播放控制模塊的#define PLAYER_PLAY 0x32 就表示控制播放器播放或暫停。

??????? int???? Type;//屬性的數據類型,在node.h中定義,如TYPE_BOOL?????????????

??????? int Flags;//屬性數據的標志,是屬性數據的標志,表示該數據是不是只讀數據,是否有最大最小值等等,node.h中定義,如DF_RDONLY

??????? int Format1;

??????? int???? Format2;

??????? const tchar_t* Name;

??????? int Class;???????????????????

??????? int Size;????????????????????

?

} datadef;//屬性對象定義

其中Format1和Format2是可選標志與Flags配合使用,比如如果Flags表示該屬性存在最大最小值,Format1就是最大值,Format2則是最小值;

另外,如果(!(Flags & DF_NOSAVE) && !(Flags & DF_RDONLY))即屬性標識為保存且可讀寫,則會被記錄到注冊表中,下次啟動時用注冊表的數據初始化該屬性表。

?

(6)datatable? 功能模塊屬性列表
typedef struct datatable

{

??????? int???? No;

??????? int???? Type;

??????? int Flags;???

??????? int Format1;

??????? int???? Format2;

} datatable;//功能模塊屬性列表

各功能模塊的屬性通常以數組的形式定義和存儲,如格式解析模塊屬性列表

static const datatable Params[] =

{

??????? { FORMAT_INPUT,?????????????????????? TYPE_NODE, DF_INPUT|DF_HIDDEN, STREAM_CLASS },

??????? { FORMAT_OUTPUT,???????????? TYPE_NODE, DF_HIDDEN, STREAM_CLASS },

??????? { FORMAT_DURATION,???????? TYPE_TICK },

??????? { FORMAT_FILEPOS,??????????? TYPE_INT, DF_HIDDEN },

??????? { FORMAT_FILESIZE,?????????? TYPE_INT, DF_KBYTE },

??????? { FORMAT_AUTO_READSIZE, TYPE_BOOL, DF_HIDDEN },

??????? { FORMAT_GLOBAL_COMMENT,TYPE_COMMENT, DF_OUTPUT },

??????? { FORMAT_FIND_SUBTITLES,TYPE_BOOL, DF_HIDDEN },

??????? { FORMAT_STREAM_COUNT, TYPE_INT, DF_HIDDEN },

?

??????? DATATABLE_END(FORMAT_CLASS)

};

(7)nodemodule? 外部插件功能模塊
typedef struct nodemodule

{

??????? int Id;//插件標識

??????? int ObjectCount;//該插件的實例個數(引用計數)

??????? bool_t Tmp;//是否是臨時節點

??????? int64_t Date;//設置時間

??????? int KeepAlive;//保持時間

??????? void* Module;//外部插件模塊

??????? void* Db;

??????? void* Func;

??????? uint8_t* Min;

??????? uint8_t* Max;

?

} nodemodule;//外部插件模塊節點

核心模塊的初始化流程及相應代碼對應關系(參考context.c中的Context_Init函數)
??????????? Mem_Init();

//內存等資源初始化(Win32/mem_win32.c)

??????????? DynCode_Init();

//程序運行動態生成代碼模塊,優化PCM,視頻渲染模塊等(DynCode/DynCode.c)

??????????? String_Init();

//系統使用字符串初始化(str.c,Win32/str_win32.c)

??????????? PCM_Init();

//音頻信號轉換模塊初始化(PCM/pcm_soft.c)

??????????? Blit_Init();

//視頻信號渲染模塊初始化(Blit/blit_soft.c)

??????????? Node_Init();

//根節點模塊初始化(node.c,Win32/node_win32.c)

??????????? Platform_Init();

//平臺信息模塊初始化(platform.c,Win32/platform_win32.c)

??????????? Stream_Init();

//輸入數據流模塊初始化(streams.c)

??????????? Advanced_Init();

//高級設置模塊初始化(advance.c)

??????????? Flow_Init();

//流控制模塊初始化(flow.c)

??????????? Codec_Init();

//解碼模塊初始化(codec.c)

??????????? Audio_Init();

//音頻信號處理模塊初始化(audio.c)

??????????? Video_Init();

//視頻信號處理模塊初始化(video.c)

??????????? Format_Init();

//格式解析模塊初始化(format.c)

??????????? Playlist_Init();

//播放列表模塊初始化(playlist.c)

??????????? FormatBase_Init();

//基本格式解析模塊初始化(format_base.c,format_subtitle.c)

??????????? NullOutput_Init();

//無輸出設備模塊初始化(nulloutput.c)

??????????? RawAudio_Init();

//RawAudio模塊初始化(rawaudio.c)

??????????? RawImage_Init();

//RawImage模塊初始化(rawimage.c)

??????????? Timer_Init();

//定時器模塊初始化(timer.c)

??????????? IDCT_Init();

//離散余弦解碼模塊初始化(idct.c)

??????????? Overlay_Init();

//視頻疊加模塊初始化(overlay.c)

??????????? M3U_Init();

//M3U格式播放列表模塊初始化(PlayList/m3u.c)

??????????? PLS_Init();

//PLS格式播放列表模塊初始化(PlayList/pls.c)

??????????? ASX_Init();

//ASX格式播放列表模塊初始化(PlayList/asx.c)

??????????? WaveOut_Init();

//波形輸出模塊初始化(waveout.c,Win32/waveout_win32.c)

??????????? SoftIDCT_Init();

//soft離散余弦解碼模塊初始化(SoftIDCT/softidct.c)

??????????? Plugins_Init();

//外部插件模塊初始化(Win32/node_win32.c)

另外還有文件擴展名自動關聯模塊Association_Init (參考文件Win32/ association_win32.c);顏色控制模塊Color_Init(參考color.c);聲音均衡器模塊Equalizer_Init(參考equalizer.c);播放控制模塊初始化(參考player.c )。

向系統中載入外部插件模塊(參考node.c以及node_win32.c)
node.c中的LoadModule函數,可以在系統中載入外部插件模塊,

static NOINLINE nodemodule* LoadModule(context* p,int No),

第一個參數是上下文對象,

第二個參數是外部插件模塊標識

?

node_win32.c定義了dll的載入與卸載函數以及相應的注冊表操作,如

在功能模塊節點載入外部插件模塊

void* NodeLoadModule(const tchar_t* Path,int* Id,void** AnyFunc,void** Db)

?

?

與界面相交互的播放控制模塊(player.c)
??????? 在所有功能模塊中和界面加交互的主要就是播放控制模塊struct node* Player;使用方法如下:

context* p = Context();

player* myplayer = NULL;

if(p) myplayer = (player*)(p->Player);

?

????????? 控制播放使用

??????? Set(void* This,int No,const void* Data,int Size)

??????? 第一個參數是播放模塊指針,

??????? 第二個參數是控制代碼,即要進行什么操作,

??????? 第三個參數是需要賦值給控制代碼的數值,

??????? 最后一個參數是所賦數值的占用內存的大小。

??????? myplayer->Set(myplayer,PLAYER_PLAY,1,sizeof(int));

??????? PLAYER_PLAY為控制代碼,表示當前控制的是播放暫停功能,數值為1表?????? 示播放為0表示暫停。

??????? 得到某一控制屬性使用Get(void* This,int No,void* Data,int Size);函數,參數含義和Set函數相同。

??????? 控制代碼是一組宏,定義在player.h文件中。比較重要的控制參數有播放控制模塊所有可用參數見static const datatable PlayerParams[]結構。

??????? 添加一個媒體文件到播放模塊使用

int PlayerAdd(player* Player,int Index, const tchar_t* Path, const tchar_t* Title);
??????? 第一個參數為播放模塊指針,

??????? 第二個參數是添加到播放模塊文件隊列的序號,如果是使文件成為第一個文??????????????? 件該參數設為0,

??????? 第三個參數是媒體文件的目錄和名稱,

??????? 第四個參數為媒體文件標題,該參數可以忽略。



TCPMP編譯方法

?本文主要講解TCPMP播放器到WINDOWS CE平臺的移植編譯過程,硬件平臺以ARMV4為主,結束部分會講解到ARMV4I編譯中需要注意的問題

?

????這幾天為公司一個項目做準備,準備編譯移植來自linux系統的超級開源媒體播放器TCPMP(商業版名稱:The Core Player)到Windwos CE平臺,tcpmp是目前支持最多可以用在嵌入式設備中多媒體播放器.除了rm,rmvb等少數幾種格式不支持外,其它常見視、音頻格式幾乎都支持。好東西是好定西,可是編譯起來十分麻煩,網上關于這方面編譯的文章很少,多半針對自己的環境粗略的講一下,系統性不強。今天TCPMP媒體播放器正式編譯成功,將經驗總結一下:

?

開發環境:windows xp sp2 + EVC4.0(SP4)

目標平臺:Windows CE5.0(ARMV4)

?

1.下載源碼,可以去http://picard.exceed.hu/tcpmp/下載TCPMP源代碼。我下載的源碼版本是0.72RC1。

?

2.編譯環境.我安裝的是evc4.2(SP4)+standard sdk+Win32(WCE ARMV4) Release.如果是編譯x86或者Emulator版本的.要下載一個nasm匯編工具.這點在readme.txt里面提到.nasm的下載地址http://nasm.sourceforge.net/.否則的話會因為缺少匯編器而報大量的錯誤。

?

3.下載下來的源碼包中不包含ARM的解碼器源碼,可以從下面2個網址下載AMR的解碼器的源代碼:http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-610.zip

http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-600.zip

并且分別拷貝到AMR目錄下的26104和26204中。同樣,這個信息在readme.txt中提到。????????????

?

4.準備ARM的匯編器,根據實踐經驗,從ARM官網上面下載下來的匯編器編譯時會報錯,不適合使用,建議使用VS2005的ARM匯編器ARMASM.EXE,將其拷貝到C:/Microsoft eMbedded C++ 4.0/EVC/WCE400/BIN下面。

?

5.編譯的時候切勿rebuild all,否則會報大量的錯誤,從Project—-Dependencies下來框里選擇player_ce3(主項目),可以看到子項目間的相互依賴關系,所以player_ce3是最后一個編譯的項目。隨便在下拉框中選擇一個子項目,在依賴項中都會發現common項目,說明該項目應該是首先需要進行編譯的,下面我們首先從common項目入手。

?

6.將player_ce3項目set as active project,編譯版本直接選擇Win32 (WCE ARMV4) Release。這個項目將最后一個進行編譯,最終生成一個player_ce3.exe的應用程序,那我們的目標也就達成了。但編譯這個程序依賴許多的庫。這些庫就是其他的project編譯后提供的。

?

7.在EVC左邊的文件查看模式里首先選擇common files,右鍵菜單Build(selection only)進行common項目的編譯,會很順利的過去。接下來由上而下順序為子項目進行編譯,當然,在Project—-Dependencies中沒有關聯的項目不需要進行編譯(總共6項:player_ce2、sample_ce3、setup_ce2、setup_ce3、template、vorbislq),其它的把asap、flac、player_ce3三項放下來最后處理,這三項需要對編譯器進行額外配置,否則會報大量錯誤。不出意外的話,都會順利編譯過去。接下來我們需要處理剩下來的3個項目。

?

8.編譯asap項目。右鍵點asap files –>settings–>c/c++–>Category–>Preprocessor在Additional include directories:中增加項目路徑(注意這個是相對路徑,以下所有需添加內容都不包括引號)”.,asap,atari800/src”.不然一堆頭文件會找不到.在Preprocessor definitions:中增加一個宏定義”,ASAP”當然這2步動作也可以在源代碼中修改.如此設置完畢后,asap files project就可以正確編譯了.

?

9.編譯flac項目。同8,打開flac的settings到相同界面.在Additional include directories:中增加路徑”flac/include,flac/src/libFLAC/include”,不然一堆頭文件找不到。然后,在Preprocessor definitions添加”,FLAC__NO_DLL”。增加這個定義避免使用_declspec(dllexport)定義函數造成的一大堆c2491錯誤.如此設置后,flac project應該可以正確編譯.

?

10.同理修改player_ce3項目,在Additional include directories中增加路徑 ”../asap/asap,../asap,../asap/atari800/src,flac/include,flac/src/libFLAC/include”。然后在Preprocessor difinitions:增加”,ASAP”。這是最后一個項目文件,也是主項目文件,成功編譯player_ce3.exe。

?

11. 拷貝包含player_ce3.exe在內所有的生成文件到目標板上(所有文件必須放在同一個目錄中),可以運行!但是菜單沒有顯示正確。主要原因是現實語言配置文件沒有加載上去,可以將源碼lang目錄下面的多國語言支持文件拷貝到目標板同一個目錄下面。如果只需要簡體中文和英文的,只要拷貝lang_std.txt lang_en.txt,lang_chs.txt,lang_ca.def四個文件(四個語言配置文件一定要和應用程序放在同一個目錄)就可以了,打開后默認顯示是英語,你可以更改到簡體中文,前提是你的CE平臺支持簡體中文。

?

我是在VS2005中用開發平臺的模擬器跑的,一切正常,就是播放不流暢,后期需要對這塊進行優化。

?

我也嘗試將其編譯到ARMV4I平臺上,結果也是可行的,不過由于的平臺的特殊性,有部分配置需要改動,也有部分插件不被支持,不過不影響使用,大體總結如下:

?

1.經驗總結表明在ARMV4I平臺的編譯工作中,TCPMP有部分模塊不被支持,編譯提示缺少相應文件。由于該部分不被支持的模塊不影響播放器的正常使用,可以在Project–Dependenties中下拉框中選擇player_ce3,然后將以下幾項前面的勾拿掉:ffmpeg、mpc、speex 這三項可以不必編譯。

?

2.Win32 (WCE ARMV4I) Debug及Release版本需要自己手動創建。在Build–Configurations里為每個子項目選擇ADD(上面提到的3項,和依賴項中不需要編譯的6項不必添加),CPU選擇Win32 (WCE ARMV4I),在Copy settings from里選擇Win32 (WCE ARMV4) Release,然后選擇OK,你就為該子項目添加了相應編譯版本。

?

3.右擊需要編譯的子項目,選擇Settings–Link,在Category中選擇General,然后再下面Project Options里將最后一行語句:/MACHINE:ARM 改成 /MACHINE:THUMB (每個項目都必須要改)

?

4.其它步驟按照按照上文ARMV4的過程來就可以了,相應的修改也是需要的,先從common開始,以player_ce3結束。

?

經過以上過程,你就可以定制自己專用的TCPMP播放器了,可以在interface項目中更改TCPMP的外觀,當然,重頭工作還在于對于特定平臺的一些優化工作:)

?

注:如果上面給出網址的解碼器包下載不了,可以在本站軟件專區的windows ce工具中下載ARM匯編器(VS2005提取出)和解碼器包


使用TCPMP解碼顯示JPEG圖片WINCE5.0

張挺哥哥今天給兄弟姐妹們帶來的是使用TCPMP0.72RC1版本的插件解碼JPEG/JPG大圖片的東東.在WINCE下解碼大圖片是很多人都遇到的難題,做起來也不是很順利.所以呢,我就把使用TCPMP解大JPEG圖片的方法告訴兄弟們,兄弟們如果因此而在經濟危機中保住飯碗的話,嘿嘿,有機會請哥哥出去弄幾個妞來整整就非常感謝了(開玩笑哈).

一、大致思路說明:其實要解碼JPEG圖片,只需要用到TCPMP中的兩個插件:COMMON和CAMERA兩個鳥插件.CAMERA插件負責解碼JPEG,COMMON負責顯示圖片.各位兄弟,為了讓解出來的圖象顯示在我們指定的DC中,我們是需要修改COMMON插件的.為什么要把圖象顯示在我們指定的DC中呢?因為我們如果要做顯示的特技的話,就是需要這樣做.比如所謂的"百葉窗"特技等等,那些鳥特級都是使用了雙緩沖的喲.(張挺eMail:zt00@tom.com)

二、步驟

1、先按照我的另一文章《TCPMP0.72RC1的編譯與移植以及自己另外做UI完整方法》把COMMON修改編譯出來。文章地址:http://blog.csdn.net/zhangting00_2000/archive/2009/04/20/4095272.aspx

2、設置COMMON為當前工程,然后把Context_Wnd全部搜出來。修改后的代碼如下:

(1)

void Context_Wnd(void* Wnd,void* hMemDC)
{
?context* p = Context();
?p->hMemDC = hMemDC;//zt00
?if (p)
?{
#ifdef REGISTRY_GLOBAL
? if (Wnd)
?? NodeRegLoadGlobal();
? else
?? NodeRegSaveGlobal();
#endif
? p->Wnd = Wnd; // only set after globals are loaded
? NodeSettingsChanged();
?}
}

(2)

DLL void Context_Wnd(void* Wnd,void* hMemDC);

(3)把context結構增加了一個成員,增加后如下:

typedef struct context
{
?int Version;
?uint32_t ProgramId;
?const tchar_t* ProgramName;
?const tchar_t* ProgramVersion;
?const tchar_t* CmdLine;
?void* Wnd;
?void* NodeLock;
?array Node;
?array NodeClass; // ordered by id
?array NodeClassPri; // ordered by priority|id
?array NodeModule;
?int LoadModuleNo;
?void* LoadModule;
?array StrTable[2];
?array StrBuffer;
?array StrModule;
?void* StrLock;
?uint32_t Lang;
?int CodePage;
?struct pcm_soft* PCM;
?struct blitpack* Blit;
?struct node* Platform;
?struct node* Advanced;
?struct node* Player;
?notify Error;
?int (*HwOrientation)(void*);
?void *HwOrientationContext;
?bool_t TryDynamic;
?int SettingsPage;
?size_t StartUpMemory;
?bool_t InHibernate;
?bool_t WaitDisable;
?int FtrId;
?bool_t LowMemory;
?bool_t CodeFailed;
?bool_t CodeMoveBack;
?bool_t CodeDelaySlot;
?void* CodeLock;
?void* CodeInstBegin;
?void* CodeInstEnd;
?int NextCond;
?bool_t NextSet;
?bool_t NextByte;
?bool_t NextHalf;
?bool_t NextSign;
?uint32_t* FlushCache;
?void* CharConvertUTF8;
?void* CharConvertCustom;
?int CustomCodePage;
?void* CharConvertAscii;
?void* Application;
?void* Logger;
?bool_t KeepDisplay;
?int DisableOutOfMemory;
?void * hMemDC;//這個東西用來繪制內存圖片的。
} context;

(張挺eMail:zt00@tom.com)

(4)進入COMMON下的Overlay,然后打開overlay_gdi.c,找到Blit函數,修改如下:

static int Blit(gdi* p, const constplanes Data, const constplanes DataLast )
{
?HDC DC;

?if (!p->Planes[0] && !AllocBitmap(p))
? return ERR_OUT_OF_MEMORY;

#ifdef BLITTEST
?BlitImage(p->Soft2,p->Planes2,Data,DataLast,-1,-1);
?BlitImage(p->p.Soft,p->Planes,p->Planes2,NULL,-1,-1);
#else
?BlitImage(p->p.Soft,p->Planes,Data,DataLast,-1,-1);
#endif
//
?if (!p->DIBSection)
?{
? if (p->Bitmap)
? {
?? SelectObject(p->DC2,p->Bitmap0);
?? DeleteObject(p->Bitmap);
? }

? p->Bitmap = CreateBitmap( p->Overlay.Width, p->Overlay.Height, 1,
?? p->Overlay.Pixel.BitCount, (char*)p->Planes[0]);

? if (!p->Bitmap)
?? return ERR_OUT_OF_MEMORY;

? p->Bitmap0 = SelectObject(p->DC2,p->Bitmap);
?}
?//MessageBox(NULL,_T("sdhfjshdfk"),_T("fg"),MB_OK);
?DC = GetDC(Context()->Wnd);//zt00
?BitBlt(Context()->hMemDC,p->p.GUIAlignedRect.x,p->p.GUIAlignedRect.y,
???? p->OverlayRect.Width,p->OverlayRect.Height,p->DC2,p->OverlayRect.x,p->OverlayRect.y,SRCCOPY);
?ReleaseDC(Context()->Wnd,DC);//zt00
?PostMessage(Context()->Wnd,WM_USER+1988,100,100);//這里是發個消息出去,表示已經解碼完畢可以顯示了.
?return ERR_NONE;
}

呵呵,修改完了這些后,把COMMON編譯,編譯出來的插件就是我們需要的插件.

最后呢,自己寫一個程序調用這兩個插件(COMMON和CAMERA)就可以了.我給大家寫了一個這樣的程序,代碼下載地址如下:http://download.csdn.net/source/1235426

呵呵,但愿大家玩的開心.


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhangting00_2000/archive/2009/04/22/4099607.aspx

TCPMP播放器UI的修改方法

TCPMP播放器UI的修改方法

??? 前段時間對TCPMP程序進行了研究,花了點時間把TCPMP程序的UI修改成了自已想要的樣子,現對UI的修改方法簡單介紹下:

??? 網上有文章對于TCPMP程序在ARMV4下的編譯方法和程序的結構介紹比較詳細,但對于inteface方面的修改方法講得并不多.

??? 修改TCPMP界面基本上有兩種方法:

1)???? 建立自已的工程,把TCPMP下的lib移植到這個工程里,這樣界面的修改比較靈活,但是工作量比較大;

2)???? 直接在TCPMP工程里修改interface,這樣工作量相對比較小,但是UI的修改受了定的約束, 沒有前種方法靈活.

??? 本人所修改的UI是按照第二種方法來做的.主要是對win_win32.c文件和inteface.c 文件進行修改.

?? 首先,我們來看看win_win32.c文件里的Win_Init()函數,這個函數可以看作是TCPMP UI部分的一個入口,在這個函數里注冊了兩個窗口類,WinClass和DialogClass.另外還調用了其它控件的初始化函數,下面是這個函數的代碼.

view plaincopy to clipboardprint?
void Win_Init()??
{??
??? HMODULE Module = Context()->LoadModule;??
??? if (!Module) Module = GetModuleHandle(NULL);??
??? InitCommonControls();??
??? WidcommAudio_Init();??
??? stprintf_s(WinClassName,TSIZEOF(WinClassName),T("%s_Win"),Context()->ProgramName);??
?
??? memset(&WinClass,0,sizeof(WinClass));??
??? WinClass.style? = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;??
??? WinClass.lpfnWndProc??? = Proc;??
??? WinClass.cbClsExtra???? = 0;??
??? WinClass.cbWndExtra???? = 0;??
??? WinClass.hInstance????? = Module;??
??? WinClass.hIcon? = LoadIcon?? (GetModuleHandle(NULL), MAKEINTRESOURCE(WIN_ICON));??
??? WinClass.hCursor??????? = WinCursorArrow();??
??? WinClass.hbrBackground? =NULL;??
??? WinClass.lpszMenuName?? = 0;??
??? WinClass.lpszClassName? = WinClassName;??
??? RegisterClass(&WinClass);??
#if 1??
??? memset(&DialogClass,0,sizeof(DialogClass));??
??? DialogClass.style?? = CS_HREDRAW | CS_VREDRAW;??
??? DialogClass.lpfnWndProc???? = DialogProc;??
??? DialogClass.cbClsExtra????? = 0;??
??? DialogClass.cbWndExtra????? = 0;??
??? DialogClass.hInstance?????? = Module;??
??? DialogClass.hCursor???? =? WinCursorArrow();??
#if defined(TARGET_WINCE)??
??? DialogClass.hbrBackground?? = GetSysColorBrush(COLOR_STATIC);//???
#else?????????????
??? DialogClass.hbrBackground?? = GetSysColorBrush(COLOR_BTNFACE);??
#endif??
??? DialogClass.lpszMenuName??? = 0;??
??? DialogClass.lpszClassName?? = T("DialogBase");??
??? RegisterClass(&DialogClass);??
#endif??
??????
??? memset(&FontCache,0,sizeof(FontCache));??
?
#if defined(TARGET_WINCE)??
??? if (Context()->ProgramId >= 3 && !QueryAdvanced(ADVANCED_OLDSHELL))??
??? {??
??? AygShell = LoadLibrary(T("aygshell.dll"));??
??? *(FARPROC*)&FuncSHCreateMenuBar = GetProcAddress(AygShell,T("SHCreateMenuBar"));??
??? *(FARPROC*)&FuncSHInitDialog = GetProcAddress(AygShell,T("SHInitDialog"));??
??? *(FARPROC*)&FuncSHFullScreen = GetProcAddress(AygShell,T("SHFullScreen"));??
??? *(FARPROC*)&FuncSHHandleWMActivate = GetProcAddress(AygShell,MAKEINTRESOURCE(84));??
??? *(FARPROC*)&FuncSHHandleWMSettingChange = GetProcAddress(AygShell,MAKEINTRESOURCE(83));??
??? *(FARPROC*)&FuncSHSendBackToFocusWindow = GetProcAddress(AygShell,MAKEINTRESOURCE(97));??
??? }??
??? CoreDLL = LoadLibrary(T("coredll.dll"));??
??? *(FARPROC*)&FuncUnregisterFunc1 = GetProcAddress(CoreDLL,T("UnregisterFunc1"));??
??? *(FARPROC*)&FuncAllKeys = GetProcAddress(CoreDLL,T("AllKeys"));??
??? *(FARPROC*)&FuncSipShowIM = GetProcAddress(CoreDLL,T("SipShowIM"));??
??? *(FARPROC*)&FuncSipGetInfo = GetProcAddress(CoreDLL,T("SipGetInfo"));??
#endif??
??? NodeRegisterClass(&Win);??
??? QueryKey_Init();??
??? OpenFile_Init();??
??? Interface_Init();??
??? PlaylistWin_Init();??
??? PlaylistNewWin_Init();????
}?
void Win_Init()
{
??? HMODULE Module = Context()->LoadModule;
??? if (!Module) Module = GetModuleHandle(NULL);
??? InitCommonControls();
??? WidcommAudio_Init();
??? stprintf_s(WinClassName,TSIZEOF(WinClassName),T("%s_Win"),Context()->ProgramName);

??? memset(&WinClass,0,sizeof(WinClass));
??? WinClass.style?= CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
??? WinClass.lpfnWndProc?= Proc;
??? WinClass.cbClsExtra??= 0;
??? WinClass.cbWndExtra??= 0;
??? WinClass.hInstance??= Module;
??? WinClass.hIcon?= LoadIcon?? (GetModuleHandle(NULL), MAKEINTRESOURCE(WIN_ICON));
??? WinClass.hCursor??= WinCursorArrow();
??? WinClass.hbrBackground?=NULL;
??? WinClass.lpszMenuName?= 0;
??? WinClass.lpszClassName?= WinClassName;
??? RegisterClass(&WinClass);
#if 1
??? memset(&DialogClass,0,sizeof(DialogClass));
??? DialogClass.style?= CS_HREDRAW | CS_VREDRAW;
??? DialogClass.lpfnWndProc??= DialogProc;
??? DialogClass.cbClsExtra??= 0;
??? DialogClass.cbWndExtra??= 0;
??? DialogClass.hInstance??= Module;
??? DialogClass.hCursor??=? WinCursorArrow();
#if defined(TARGET_WINCE)
??? DialogClass.hbrBackground?= GetSysColorBrush(COLOR_STATIC);//
#else???
??? DialogClass.hbrBackground?= GetSysColorBrush(COLOR_BTNFACE);
#endif
??? DialogClass.lpszMenuName?= 0;
??? DialogClass.lpszClassName?= T("DialogBase");
??? RegisterClass(&DialogClass);
#endif
?
??? memset(&FontCache,0,sizeof(FontCache));

#if defined(TARGET_WINCE)
??? if (Context()->ProgramId >= 3 && !QueryAdvanced(ADVANCED_OLDSHELL))
??? {
?AygShell = LoadLibrary(T("aygshell.dll"));
?*(FARPROC*)&FuncSHCreateMenuBar = GetProcAddress(AygShell,T("SHCreateMenuBar"));
?*(FARPROC*)&FuncSHInitDialog = GetProcAddress(AygShell,T("SHInitDialog"));
?*(FARPROC*)&FuncSHFullScreen = GetProcAddress(AygShell,T("SHFullScreen"));
?*(FARPROC*)&FuncSHHandleWMActivate = GetProcAddress(AygShell,MAKEINTRESOURCE(84));
?*(FARPROC*)&FuncSHHandleWMSettingChange = GetProcAddress(AygShell,MAKEINTRESOURCE(83));
?*(FARPROC*)&FuncSHSendBackToFocusWindow = GetProcAddress(AygShell,MAKEINTRESOURCE(97));
??? }
??? CoreDLL = LoadLibrary(T("coredll.dll"));
??? *(FARPROC*)&FuncUnregisterFunc1 = GetProcAddress(CoreDLL,T("UnregisterFunc1"));
??? *(FARPROC*)&FuncAllKeys = GetProcAddress(CoreDLL,T("AllKeys"));
??? *(FARPROC*)&FuncSipShowIM = GetProcAddress(CoreDLL,T("SipShowIM"));
??? *(FARPROC*)&FuncSipGetInfo = GetProcAddress(CoreDLL,T("SipGetInfo"));
#endif
??? NodeRegisterClass(&Win);
??? QueryKey_Init();
??? OpenFile_Init();
??? Interface_Init();
??? PlaylistWin_Init();
??? PlaylistNewWin_Init();?
}

?

??? 在此函數中我們需要注意??? WinClass.lpfnWndProc= Proc;?? Proc是消息處理函數名.實際上所有的消息處理都是在static LRESULT CALLBACK Proc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)函數里完成的.

下面對此函數中比較重點的消息作下說明:

??? WM_CREATE消息里主要是建立播放的窗口;

?? WM_PAINT消息里可以貼上UI的背景圖片,這樣使UI看上去比較美觀.貼圖部分程序如下:

?view plaincopy to clipboardprint?
case WM_PAINT:??
??? {??
??? hdc = BeginPaint(Wnd,&Paint);??
?
??? MainBkGnd = LoadBitmap(p->Module,MAKEINTRESOURCE(IDB_MAIN_BKG));??
??? MemDC = CreateCompatibleDC(hdc);??
??? bmpOld = (HBITMAP)SelectObject(MemDC,MainBkGnd);??
??? BitBlt(hdc,0,0,LCD_XSIZE,LCD_YSIZE,MemDC,0,0,SRCCOPY);??
??? SelectObject(MemDC,bmpOld);??
??? DeleteObject(bmpOld);?????
??? DeleteDC(MemDC);??
?
??? EndPaint(Wnd,&Paint);??
?? }??
?? break;?
case WM_PAINT:
??? {
??? hdc = BeginPaint(Wnd,&Paint);

??? MainBkGnd = LoadBitmap(p->Module,MAKEINTRESOURCE(IDB_MAIN_BKG));
??? MemDC = CreateCompatibleDC(hdc);
??? bmpOld = (HBITMAP)SelectObject(MemDC,MainBkGnd);
??? BitBlt(hdc,0,0,LCD_XSIZE,LCD_YSIZE,MemDC,0,0,SRCCOPY);
??? SelectObject(MemDC,bmpOld);
??? DeleteObject(bmpOld);?
??? DeleteDC(MemDC);

??? EndPaint(Wnd,&Paint);
?? }
?? break;
?

???????? WM_COMMAND消息是所有菜單 ,按鈕等點擊后處理的入口點,具體的實現在interface.c里的static int Command(intface* p,int Cmd)函數里來做處理。如播放,暫停,前一首,下一首等.還有其它的一些消息處理在此不做介紹了.

??????? Interface.c的程序結構和win_win32.c? 基本差不多,其中最主要的也是static bool_t Proc(intface* p, int Msg, uint32_t wParam, uint32_t lParam, int* Result)函數對消息的處理.在此函數的WM_CREATE消息里可以建立起各種控件的消息處理.然后分別在各控件的消息處理函數里通過上面貼bitmap圖片的方式來改變控件的外觀.

???????? 其實對于TCPMP程序UI部分的修改,最主要的還是要讀懂源代碼.在讀懂源代碼的基礎上再結合Win32程序的結構來修改界面還是比較容易的.


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453704.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453704.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453704.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用zerorpc踩的第一個坑:

Server端代碼:注意s.run() 和 s.run的區別,一個括號搞死我了.如果不加括號,服務端服務是不會啟動的,客戶端就會報連接超時的錯誤 Server端在本機所有IP上監聽4242端口的tcp協議 import zerorpcclass HelloRPC(object):   def __…

django存入mysql數據庫_django如何存數據到一個mysql數據表里面

讓我們聊聊這個話題, django如何存數據至mysql數據表里面,你會用什么方法?正常情況下,我們form邏輯處理后,直接form.save(),是,這個方法沒毛病;但有沒有其他的方法呢?假如…

【Luogu】P3343地震后的幻想鄉(對積分概率進行DP)

題目鏈接 神難qwq。配合rqy的博客食用。 首先我們學到有一個概率函數$p(x)$表示某事件發生概率取值小于x的函數。這個函數有什么特點呢? 那就是$\int_{-∞}^{∞}p(x)dx1$ 這個是顯然的 然后我們令p(x)為首次聯通的時間的概率分布函數 這其實等價于生成樹的最大權邊等…

深度學習目標檢測之 YOLO v3

論文名:《YOLOv3: An Incremental Improvement》論文地址 https://pjreddie.com/media/files/papers/YOLOv3.pdfhttps://arxiv.org/abs/1804.02767v1 論文代碼 https://github.com/yjh0410/yolov2-yolov3_PyTorchkeras:https://github.com/qqwweee/keras…

30本pdf完整版的經典Linux學習和開發教程和資料下載 android arm java 資料大全

史上最牛的Linux內核學習方法論 點擊下載我的arm_linux移植筆記 點擊下載S3C2440完全開發流程 點擊下載Linux系統命令及其使用詳解完整版 點擊下載Linux主要shell命令詳解 點擊下載深入理解Linux內核(第三版 pdf英文版) 點擊下載深入分析Linux內核源代碼教程pdf完整版 點擊下…

Fedex Ship Manager Software安裝

本文出自Simmy的個人blog:西米在線 http://simmyonline.com/archives/552.html 這個軟件的安裝頗費了我一番周章,特地Log之。下載:http://www.fedex.com/apac_english/fsmsoftware/ 安裝完后,接著輸入用戶信息,然后連…

mysql5.7.11解壓版安裝_Mysql5.7.11在windows10上的安裝與配置(解壓版)

第一步my-default.ini 添加配置:#綁定IPv4和3306端bind-address 127.0.0.1port 3306# 設置mysql的安裝目basedir E:\mysql# 設置mysql數據庫的數據的存放目datadirE:\mysql\data# 允許最大連接數max_connections200#設置默認字符集為utf8default-character-setutf…

【轉】博客美化(3)為博客添加一個漂亮的分享按鈕

閱讀目錄 1.社會化分享2.選擇一個分享按鈕3.添加到博客園博客博客園美化相關文章目錄:博客園博客美化相關文章目錄 在前2篇博客“博客美化(1)基本后臺設置與樣式設置”與"博客美化(2)自定義博客樣式細節"中詳細介紹了博客樣式設置的相關問題,當…

深度學習目標檢測之 YOLO v4

論文原文:https://arxiv.org/abs/2004.10934代碼 原版c: https://github.com/AlexeyAB/darknetkeras:https://github.com/Ma-Dan/keras-yolo4pytorch:https://github.com/Tianxiaomo/pytorch-YOLOv4 前言 2020年YOLO系列的作者…

[Android] 年年有魚手機主題

自制的年年有魚手機主題,希望大家喜歡!~ 下載地址:https://yunpan.cn/cqauQbiM97idd (提取碼:d272) 本文轉自haiyang45751CTO博客,原文鏈接: http://blog.51cto.com/haiyang457/1…

mysql 小數做索引_10 分鐘掌握 MySQL 的索引查詢優化技巧

本文的內容是總結一些MySQL的常見使用技巧,以供沒有DBA的團隊參考。如無特殊說明,存儲引擎以InnoDB為準。MySQL的特點了解MySQL的特點有助于更好的使用MySQL,MySQL和其它常見數據庫最大的不同在于存在存儲引擎這個概念,存儲引擎負…

模塊與包

一 模塊介紹 1、什么是模塊? #常見的場景:一個模塊就是一個包含了一組功能的python文件,比如spam.py,模塊名為spam,可以通過import spam使用。#在python中,模塊的使用方式都是一樣的,但其實細說的話&#x…

Linux 狀態命令之 sar

簡介 sar(System Activity Reporter 系統活動情況報告)是目前 Linux 上最為全面的系統性能分析工具之一,可以從多方面對系統的活動進行報告,包括:文件的讀寫情況、系統調用的使用情況、磁盤 I/O、CPU 效率、內存使用狀…

解決eclipse + pydev 編譯過程中有中文的問題

最近在學習python編程,開發環境設置好了,是用eclipse pydev 來做開發的環境,配置好了之后,需要解決的一個關鍵問題就是老問題了:如何解決代碼中的中文問題。。。 其實但我們在配置編程環境的時候,就需要設…

程序員的思考--終于確定了自己的技術發展方向

經過了將近5年的工作沉淀以后,終于確定了自己的職業發展方向。從現在開始終于可以有的放矢了,不再迷茫了。回想以往,找到這個方向,確實不是一件容易的事情,一路也是迷茫的走過來,隨著知識和工作經驗的積累&…

mysql正在運行安全文件怎么辦_MySQL服務器運行的安全文件化選項,所以它不能執行該語句什么情? 愛問知識人...

MySQL的事務支持不是綁定在MySQL服務器本身,而是與存儲引擎相關1。MyISAM:不支持事務,用于只讀程序提高性能 2。InnoDB:支持ACID事務、行級鎖、并發 3。Berkeley DB:支持事務一個事務是一個連續的一組數據庫操作&#…

C++項目參考解答:累加求圓周率

【項目-累加求圓周率】 用例如以下公式求π的近似值&#xff08;計算直到最后一項的絕對值小于10?5&#xff09; π41?1315?17...【參考解答】 #include <iostream> using namespace std; int main( ) {int n,sign;double total,f;n1;total0;sign1;f1; //用f代表待累加…

[ASP.NET AJAX]類似.NET框架的JavaScript擴展

最近AJAX風靡全世界&#xff0c;在CommunityServer中他運用了自己定義的封裝了js&#xff0c;并且可以跨瀏覽器&#xff0c;在較小的應用程序中&#xff0c;他比較適合&#xff0c;而且使用也比較簡單。但是對微軟的Microsoft AJAX還是一點不了解的我&#xff0c;從今天開始也要…

mysql 連接 指定字符集_關于Mysql連接池配置指定字符集的問題

問題是這樣的&#xff0c;我在寫一個網站&#xff0c;打算使用連接池。我使用J2EE開發&#xff0c;開始使用的是直連的方式&#xff0c;附上代碼public class ConnDb {private String getDriver "com.mysql.jdbc.Driver";private String getUrl "jdbc:mysql:/…

【原】iOS:手把手教你發布代碼到CocoaPods(Trunk方式)

概述 關于CocoaPods的介紹不在本文的主題范圍內&#xff0c;如果你是iOS開發者卻不知道CocoaPods&#xff0c;那可能要面壁30秒了。直奔主題&#xff0c;這篇文章主要介紹如果把你的代碼發布到CocoaPods代碼庫中&#xff0c;讓別人可以使用“pod search yourOpenProject”命令查…