• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Do What You think !!

             

            水煮TCPMP (轉)

            去年年底幫別人做一個項目,了解了一下TCPMP,覺得這個軟件的結構寫得很好就做了些記錄,今天偶然翻出來看看覺得可能對正在研究這個軟件的人有點幫助就貼出來。如果轉載請注明出處,謝謝。

            TCPMP是一個功能強大開放式的開源多媒體播放器,
            播放器主要由核心框架模塊(common工程)和解碼器分離器插件組成。
            TCPMP的插件非常多,、libmad我們聯合幾個最常用的插件(ffmpeg、splitter)來說明,其中interface插件實現TCPMP的界面,由于他和媒體播放沒有什么關系,這部分可以完全被替換掉,替換成自己的界面。
            ffmpeg工程是系統主要的音視頻解碼模塊,ffmpeg是一個集錄制、轉換、音/視頻編碼解碼功能為一體的完整的開源解決方案。FFmpeg的開發是基于Linux操作系統,但是可以在大多數操作系統中編譯和使用。ffmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多種編碼,AVI、MPEG、OGG、Matroska、ASF等90多種解碼。很多開源播放器都用到了ffmpeg。但是ffmpeg程序解碼效率不是很高,系統僅僅使用了FFmpeg的部分解碼功能。
            ffmpeg主目錄下主要有libavcodec、libavformat和libavutil等子目錄。其中libavcodec用于存放各個encode/decode模塊,libavformat用于存放muxer/demuxer模塊,libavutil用于存放內存操作等常用模塊。本系統的媒體文件分離器有單獨的splitter模塊完成所以不需要libavformat子目錄。ffmpeg目錄下libavcodec、libavutil保留子目錄。

            libmad工程用于MP3文件解碼,該工程包含兩個功能模塊,一個負責解析MP3文件格式,包括MPEG1音頻文件 (MP1,MP2,MP3,MPA),讀取每一幀音頻數據;另一個負責解碼MPEG1音頻數據,解碼代碼在libmad子目錄中。
            libmad是一個開源的高精度 MPEG1音頻解碼庫,支持 MPEG-1(Layer I, Layer II 和 LayerIII,也就是 MP3)。libmad提供 24-bit 的 PCM 輸出,完全是定點計算,非常適合沒有浮點支持的平臺上使用。使用 libmad 提供的一系列 API,就可以非常簡單地實現 MP3 數據解碼工作。在 libmad 的源代碼文件目錄下的 mad.h 文件中,可以看到絕大部分該庫的數據結構和 API 等。libmad是用的fixed-integer,通過整數模擬小數計算的,精度只能保證到小數點后第9位(大于0的最小值 0.00000000372529),雖然解碼精度會有損失,但是極大提高了解碼效率,特別是在嵌入式設備上也可以實現高碼率MP3文件的解碼。

            splitter工程用于解析多種音視頻文件格式。可以解析的文件格式包括:ASF媒體文件,視頻文件 (AVI,DIVX),Windows波形文件 (WAV,RMP),MPEG電影文件 (MPEG,MPG,MPV),MPEG4文件 (MP4,3GP,M4A,M4B,K3G)。以上格式可以被解析但是數據編碼不一定能正確解碼,需要依賴系統的解碼器。

            common工程是核心模塊,是一個開放的集數據輸入、轉換、音/視頻解碼、信號輸出等功能為一體的完整的多媒體播放框架。這個框架自身不包含任何的Decode和Split功能,這些功能由插件實現,核心模塊以一個樹狀結構管理所有的功能模塊和插件模塊,實現數據Render功能,對輸入、轉換、輸出流程的控制,接受播放過程中的操作和對事件進行處理,同時也實現系統運行中經常使用的一些共用函數,比如解碼過程中經常使用的逆離散余弦變換,內存操作,界面中需要使用的多語言字符處理等。common工程的主目錄下主要有:blit、dyncode、overlay、pcm、softidct、win32、zlib等子目錄。其中blit和overlay存放是視頻信號渲染模塊,pcm存放PCM音頻信號轉換模塊,softidct存放逆離散余弦變換函數,win32存放內存操作等常用模塊,dyncode這個目錄的代碼比較晦澀,存放的是程序運行是動態生成代碼模塊,針對不同的CPU指令集,PCM數據數據聲道和采樣率不同,視頻渲染數據格式和色深等不同情況動態生成不同的優化代碼(這段代碼非常精彩,不能不讓人佩服TCPMP作者的高超水平)。核心模塊有一個上下文對象context,該對象在初始化函數bool_t Context_Init(……)中候創建了一個該對象實例。該對象實例記錄管理各個功能模塊,用戶界面可以通過該對象和核心模塊交互,管理控制播放過程。
             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;  //功能模塊定義對象數組,按照系統邏輯關系組織
             array NodeClassPri; //功能模塊定義對象數組,按照系統邏輯關系和模塊優先級排列
             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;   //信息錯誤回調函數
             //屏幕旋轉信息,在某些系統中屏幕可以旋轉90度或180度
             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;
            核心模塊上下文指針可以通過全局函數獲得context* Context();
            初始化上下文對象的全局函數是bool_t Context_Init(const tchar_t* Name,const tchar_t* Version,int Id,const tchar_t* CmdLine,void* Application);其中Name參數為應用程序名稱,Version為版本信息字符串。
            釋放上下文對象的全局函數是void Context_Done();。
            void Context_Wnd(void*);函數將視頻播放窗口句柄初始化給設備上下文。

            功能模塊包含定義對象和數據對象,定義對象描述功能模塊相互間的邏輯結構,數據對象記錄模塊屬性和方法。
            所有的功能模塊結構按一個樹狀結構來組織,結構關系如下,NODE是整個結構的根結點,其下為子節點,節點按類型可分為實節點,全局節點,設置節點,抽象節點。
            #define CF_SIZE   0x00FFFFFF
            #define CF_GLOBAL  0x01000000
            #define CF_SETTINGS  0x02000000
            #define CF_ABSTRACT  0x08000000
            抽象節點沒有對應的對象實例,類似C++的抽象基類,為了按照邏輯關系組織系統結構而存在,例如NODE就是抽象節點。全局節點全局只有一個對象的實例,如播放控制模塊PLAYER_ID。設置節點表示和系統播放設置相關,比如聲音均衡器模塊EQUALIZER_ID,顏色控制模塊COLOR_ID。實節點與抽象節點不同,指可以生成對象實例的節點,實節點沒有特殊標識,一般以數據對象占用內存大小表示是否是一個實節點,創建節點時要根據該信息分配內存單元,實節點也可以有子節點,例如:MMS_ID的父節點是HTTP_ID。全局節點,設置節點和實節點可以相互組合,比如播放控制節點同時是全局節點,設置節點和實節點。節點名稱后帶_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 (Intel XScale CPU 信息模塊)
                ├─PLAYER_ID (播放控制模塊)
                └─PLAYER_BUFFER_ID (播放緩沖模塊)
               
                節點樹狀結構由若干個靜態定義對象(nodedef)實例實現,
                    typedef struct nodedef
              {
               int    Flags;
               int    Class;
               int    ParentClass;
               int    Priority;
               nodecreate  Create;
               nodedelete  Delete;
              } nodedef;
             Flags表示當前節點的類型:抽象、實節點、全局、設置。
             Class表示當前節點的標識,如MEDIA_CLASS或ASF_ID等等。
             ParentClass表示當前節點的父節點標識,如SYSTIMER_ID對象的父節點是TIMER_CLASS。
             Priority表示當前節點優先級。
             Create和Delete是兩個函數指針,表示該節點的創建函數和銷毀函數。
             如播放控制模塊的結構定義是
             static const nodedef Player =
             {
              sizeof(player_base)|CF_GLOBAL|CF_SETTINGS,
              PLAYER_ID,
              NODE_CLASS,
              PRI_MAXIMUM+600,
              (nodecreate)Create,
              (nodedelete)Delete,
             };
             
             絕大多數節點都有一個對應的數據對象,記錄該節點的數據和方法,每一個子節點對象都是以父節點對象作為該節點一個元素,類似C++的封裝繼承機制。如果子節點的父節點沒有數據對象,該節點可以從node節點直接繼承。每一個節點都可以看成Node節點的直接或間接子節點,所以所有節點頭以一個相同的node結構開頭,子節點可能還有自己的屬性,在繼承父對象后就是子節點自己的元素。
                typedef struct node
             {
              int   Class;
              nodeenum Enum;
              nodeget  Get;
              nodeset  Set;
             } node;
             Class表示該對象的標識,如PLAYER_ID。
             Enum是一個函數指針,指向一個函數用于枚舉當前節點的屬性。
             Get是一個函數指針,得到當前節點某一屬性值。
             Set是一個函數指針,設置當前節點的某一屬性數值。
             
             節點的屬性值數據特性在一個static const datatable xxxParams[] = {……};的靜態數組里定義。
             typedef struct datatable
             {
              int No;
              int Type;
              int Flags;
              int Format1;
              int Format2;
             } datatable;
             
             No表示屬性的標識,如播放控制模塊的#define PLAYER_PLAY 0x32 就表示控制播放器播放或暫停。
             Type表示屬性的數據類型,可用值在node.h中定義。
             Flags是屬性數據的標志,表示該數據是不是只讀數據,是否有最大最小值等等,可用值在node.h中定義,如果該標志包含DF_SETUP同時不包含DF_NOSAVE和DF_RDONLY屬性,該屬性會被記錄在注冊表中,下次啟動時用注冊表的數據初始化該屬性。
             Format1和Format2是可選標志與Flags配合使用,比如如果Flags表示該屬性存在最大最小值,Format1和Format2可以分別表示最小和最大數值。
             
             在在系統上下文對象中有兩個元素記錄節點信息array Node;和array NodeClass;,array是數組數據類型,Node是節點數據對象的數組,NodeClass節點對象的數組,按照系統邏輯關系組織。
             創建節點時傳入nodedef對象到節點創建函數,函數會根據nodedef信息生成對應nodeclass對象添加到NodeClass數組,同時根據nodedef信息分配數據對象的內存空間。在該節點的Create函數里面再初始化該節點的數據對象。

            在所有功能模塊中和界面加交互的主要就是播放控制模塊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文件中。比較重要的控制參數有
            // play or pause (bool_t)
            #define PLAYER_PLAY   0x32
            // position in fraction (fraction)
            #define PLAYER_PERCENT  0x25
            // position in time (tick_t)
            #define PLAYER_POSITION  0x28
            // current format (format*)
            #define PLAYER_FORMAT  0x2B
            // current file in playlist (int)
            #define PLAYER_LIST_CURRENT 0x2F
            // current file index (suffled) in playlist (int)
            #define PLAYER_LIST_CURRIDX 0xA2
            // fullscreen mode (bool_t)
            #define PLAYER_FULLSCREEN 0x3E
            // stop
            #define PLAYER_STOP   0xB2
            // skin viewport rectangle (rect)
            #define PLAYER_SKIN_VIEWPORT 0x3C
            播放控制模塊所有可用參數見static const datatable PlayerParams[]結構。

            添加一個媒體文件到播放模塊使用int PlayerAdd(player* Player,int Index, const tchar_t* Path, const tchar_t* Title);
            第一個參數為播放模塊指針,第二個參數是添加到播放模塊文件隊列的序號,如果是使文件成為第一個文件該參數設為0,第三個參數是媒體文件的目錄和名稱,第四個參數為媒體文件標題,該參數可以忽略。

            核心模塊也管理多語言字符串,使用函數const tchar_t* LangStr(int Class, int Id);和const tchar_t* LangStrDef(int Class, int Id)可以得到對應字符串,系統字符串資源有兩種,標準字符串和特殊字符集字符串。標準字符串資源文件是工程目錄下的lang_std.txt文件,該文件字符串為ASCII字符,可與其他代碼頁字符兼容。該文件記錄的是核心模塊運行時需要使用的字符串,Decode和Splite模塊可以處理的編碼格式和文件格式也在這個文件中記錄,例如lang_std.txt文件中的
            MP3_0001=audio/mpeg
            MP3_0002=mp1:A;mp2:A;mp3:A;mpa:A
            MP3_0200=acodec/0x0055
            紀錄了MP3文件分離器對應的文件類型、擴展名和文件特征碼。
            要得到標準字符串使用函數LangStrDef,第一個參數表示字符類別,第二個參數表示字符ID。界面相關的是特殊字符集的字符串,使用函數LangStr,第一個參數表示字符類別,第二個參數表示字符ID。關于字符串資源文件結構含義將在以后的文檔中說明。http://blog.csdn.net/navi_dx/archive/2007/11/14/1885780.aspx

            posted on 2007-11-23 10:28 零宇 閱讀(1108) 評論(0)  編輯 收藏 引用

            導航

            統計

            常用鏈接

            留言簿(4)

            隨筆檔案(8)

            文章分類(4)

            文章檔案(4)

            Windows Mobile 論壇

            道中人

            最新隨筆

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            久久久久国产精品嫩草影院| 国产婷婷成人久久Av免费高清| 色噜噜狠狠先锋影音久久| 亚洲欧洲久久久精品| 欧美熟妇另类久久久久久不卡 | 99国内精品久久久久久久| 99久久精品免费看国产一区二区三区| 夜夜亚洲天天久久| 亚洲天堂久久久| 亚洲国产成人精品女人久久久| 色欲久久久天天天综合网| 亚洲国产综合久久天堂| 精品无码久久久久久尤物| 欧美激情精品久久久久久久| 精品国产婷婷久久久| 精品亚洲综合久久中文字幕| 国产亚洲综合久久系列| 亚洲另类欧美综合久久图片区| 97超级碰碰碰久久久久| 国产精品久久网| 99久久夜色精品国产网站| 久久精品国产清自在天天线| 久久久久久久97| 亚洲国产精品久久66| 少妇高潮惨叫久久久久久 | 97久久精品人人澡人人爽| 亚洲va久久久噜噜噜久久| 成人久久免费网站| 美女久久久久久| 久久伊人影视| 日本国产精品久久| 四虎影视久久久免费观看| 久久国产精品免费一区二区三区| 麻豆成人久久精品二区三区免费| 日本五月天婷久久网站| 麻豆AV一区二区三区久久| 欧美大香线蕉线伊人久久| 亚洲精品乱码久久久久久蜜桃不卡| 久久国产亚洲精品| 国产成人精品综合久久久久| 中文国产成人精品久久不卡|