`
dahui
  • 浏览: 50187 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论
阅读更多
写得很好、很有用,不得不转载。
http://blog.csdn.net/navi_dx/archive/2007/11/14/1885780.aspx


去年年底帮别人做一个项目,了解了一下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。关于字符串资源文件结构含义将在以后的文档中说明。

分享到:
评论

相关推荐

    TCPMP

    TCPMP(The Core Pocket Media Player)是一款专为winCE平台设计的强大ARM播放器,被誉为该平台上最佳的多媒体播放软件。它的出现,极大地丰富了Windows CE系统设备的多媒体体验,如智能手机、PDA和个人媒体播放器等...

    TCPMP 0.81视频播放器_wince

    TCPMP(The Core Pocket Media Player)是一款经典的开源多媒体播放器,尤其在掌上设备如Windows CE(wince)系统上非常流行。版本0.81是该软件的一个稳定版本,适用于Windows CE 6.0操作系统。它以其强大的媒体兼容...

    tcpmp.src.0.72RC1.rar_tcpmp_tcpmp src_tcpmp 0.72 sour_tcpmp.src

    TCPMP源代码的分析与学习,对于开发者来说具有很高的价值。它提供了多媒体处理的底层实现,包括视频解码、音频解码、渲染和播放控制等功能。以下是一些相关知识点: 1. **多媒体框架**:TCPMP基于一个强大的多媒体...

    tcpmp player

    TCPMP(The Core Pocket Media Player)是一款开源的多媒体播放器,专为各种移动设备设计,如掌上电脑、智能手机和平板电脑。它以其强大的媒体格式支持和高度自定义的界面而受到用户喜爱。TCPMP的核心在于其高效能的...

    国外开源Wince全能播放器TCPMP源码

    源码分析: 1. **解码引擎**:TCPMP采用模块化设计,解码引擎是其核心部分,包含了各种编解码库。例如,FFmpeg库用于处理多种音频和视频编码格式,提供高效的解码能力。开发者可以通过阅读源码,了解如何集成和调用...

    tcpmp 源码

    TCPMP(The Core Pocket Media Player)是一款开源的多媒体播放器,以其强大的兼容性和自定义性在用户中广受欢迎。源码的提供使开发者能够深入理解其内部机制,并根据需要进行定制化开发。以下是对TCPMP源码相关知识...

    tcpmp for win32

    TCPMP(The Core Pocket Media Player)是一款非常知名的跨平台媒体播放器,专为掌上设备设计,但在Windows操作系统上也有其Win32版本,即"tcpmp for win32"。这款播放器以其强大的多媒体兼容性和自定义能力而受到...

    TCPMP.rar_Windows CE_ce 播放器_tcpmp

    TCPMP(The Core Pocket Media Player)是一款经典的多媒体播放器,专为Windows CE操作系统设计。它在掌上设备和嵌入式系统中广受欢迎,因为其强大的兼容性和丰富的功能。TCPMP能够支持多种视频和音频格式,使用户...

    TCPMP 0.81

    TCPMP(The Core Pocket Media Player)是一款非常知名的多媒体播放软件,尤其在早期的智能手机和平板电脑,如PDA(个人数字助手)上广泛使用。它以其强大的兼容性和出色的性能著称,能够支持多种格式的音频和视频...

    tcpmp.zip_TCPMP CE_tcpmp wince6_tcpmp源码_wince6.0_wince6.0tcpmp报错

    总之,TCPMP源码的分析和研究不仅可以帮助开发者了解一个成熟的多媒体播放器的实现,也可以为他们在Windows CE和Wince6.0平台上开发自己的媒体应用提供宝贵经验。通过深入源码,可以学习到多媒体处理、系统集成、...

    TCPMP_0.81player.rar_tcpmp

    TCPMP(The Core Pocket Media Player)是一款经典的多媒体播放器,尤其在Windows CE操作系统上备受推崇。这个名为"TCPMP_0.81player.rar_tcpmp"的压缩包文件包含了该播放器的版本0.81,是专为Windows CE设备优化的...

    掌上影霸(TCPMP) V0.81 汉化版

    掌上影霸(TCPMP)是一款著名的开源媒体播放器,专为移动设备设计,支持多种格式的音频和视频播放。其V0.81汉化版是针对中国用户特别优化的版本,界面语言转换为简体中文,方便国内用户操作和使用。这款软件在功能性...

    TCPMP播放器源码

    TCPMP的源码分析可以从以下几个关键知识点入手: 1. **跨平台技术**:TCPMP采用C/C++编写,利用了标准库和底层API,使其能在不同的操作系统上运行。对于Win32和WinCE平台,需要理解和适配各自的API调用和系统特性。...

    用于tcpmp的flv格式解码源码

    标题中的“用于tcpmp的flv格式解码源码”是指提供了一套源代码,用于在TCPMP(The Core Pocket Media Player)这款媒体播放器上解码FLV(Flash Video)格式的视频文件。TCPMP是一款跨平台的开源媒体播放器,支持多种...

    tcpmp.src.0.66.rar_66视频源码_arm_arm 视频_tcpmp0._视频 解码

    TCPMP(The Core Pocket Media Player)是一款著名的开源媒体播放器,尤其在嵌入式设备如ARM架构的智能手机和平板电脑上广泛应用。这个“tcpmp.src.0.66.rar”压缩包包含了TCPMP 0.66版本的源代码,是开发者研究、...

    tcpmp.rar_comingscc_faad.c_roadoqi_tcpmp_tcpmp ce5 vs2005

    标题中的"tcpmp.rar_comingscc_faad.c_roadoqi_tcpmp_tcpmp ce5 vs2005"表明这是一个关于TCPMP播放器的源代码压缩包,其中包含了多个相关的组件和开发环境信息。TCPMP(The Core Pocket Media Player)是一款流行于...

    winceTcpmp全插件播放器

    TCPMP(The Core Pocket Media Player)是一款经典的多媒体播放器,尤其在Windows CE(简称wince)平台上备受青睐。它以其强大的兼容性和流畅的播放性能而闻名,为用户提供了一站式的媒体解决方案。"winceTcpmp全...

    TCPMP(0.72)

    TCPMP(The Core Pocket Media Player)是一款经典的多媒体播放器,尤其在Windows CE操作系统上广受欢迎。版本0.72RC1是该软件的一个特定发行版,提供了强大的视频和音频解码能力,支持多种格式,包括但不限于AVI、...

    tcpmp编解码详解

    TCPMP(The Core Pocket Media Player)是一款著名的跨平台媒体播放器,因其强大的视频和音频编解码能力而受到用户喜爱。TCPMP支持多种格式的媒体文件,包括但不限于AVI、MP4、3GP、WMV、ASF、MP3、AAC等。在深入...

    TCPMP完整版(支持APE)

    TCPMP(The Core Pocket Media Player)是一款著名的多媒体播放器,尤其在掌上设备如Windows CE平台上广受欢迎。它以其强大的媒体格式支持、优秀的性能和高度的可定制性而著称。"TCPMP完整版(支持APE)"意味着这个...

Global site tag (gtag.js) - Google Analytics