TCPMPCodeStructureAnalyse.docx
- 文档编号:30569006
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:14
- 大小:21.79KB
TCPMPCodeStructureAnalyse.docx
《TCPMPCodeStructureAnalyse.docx》由会员分享,可在线阅读,更多相关《TCPMPCodeStructureAnalyse.docx(14页珍藏版)》请在冰豆网上搜索。
TCPMPCodeStructureAnalyse
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_tContext_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(DirectXMediaObject)
│ │ │ ├─WMV_ID
│ │ │ ├─WMS_ID
│ │ │ ├─WMVA_ID
│ │ │ ├─WMA_ID
│ │ │ └─WMAV_ID
│ │ ├─FFMPEGVIDEO(FFMpeg解码模块)
│ │ └─LIBMAD_ID(LibmadMp3解码模块)
│ ├─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上下文对象
typedefstructcontext
{
intVersion;//版本信息
uint32_tProgramId;//应用程序句柄
consttchar_t*ProgramName;//应用程序名称
consttchar_t*ProgramVersion;//程序版本号,字符串
consttchar_t*CmdLine;//程序命令行信息
void*Wnd;//视频渲染窗口句柄
void*NodeLock;//功能模块访问临界区互斥变量
arrayNode;//功能模块数据对象数组
arrayNodeClass;//orderedbyid功能模块定义对象数组,按照系统逻辑关系组织
arrayNodeClassPri;//orderedbypriority|id功能模块定义对象数组,按照系统逻辑关系和优先级排列
arrayNodeModule;//外部插件模块数组
intLoadModuleNo;//当前正在加载的外部插件序号
void*LoadModule;//当前正在加载的外部插件
arrayStrTable[2];//字符串资源数组,字符串分为:
给底层使用的标准字符串资源、给界面使用的显示字符串资源,两个资源用两个数组表示
arrayStrBuffer;
arrayStrModule;//未使用
void*StrLock;//字符串数组访问临界区互斥变量
uint32_tLang;//当前使用语言标志
intCodePage;//当前使用代码页标志
structpcm_soft*PCM;//PCM音频信号转换模块
structblitpack*Blit;//视频信号渲染模块
structnode*Platform;//得到平台相关信息
structnode*Advanced;//得到播放模块高级信息
structnode*Player;//播放控制模块
notifyError;//信息错误回调函数
int(*HwOrientation)(void*);
void*HwOrientationContext;
bool_tTryDynamic;//未使用
intSettingsPage;//未使用
size_tStartUpMemory;//可以使用的有效内存数
bool_tInHibernate;//是否进入休眠状态
bool_tWaitDisable;//未使用
intFtrId;//未使用
bool_tLowMemory;//可以使用的有效内存数是否小于系统要求的最低要求
//动态代码生成中间状态及数据
bool_tCodeFailed;
bool_tCodeMoveBack;
bool_tCodeDelaySlot;
void*CodeLock;
void*CodeInstBegin;
void*CodeInstEnd;
intNextCond;
bool_tNextSet;
bool_tNextByte;
bool_tNextHalf;
bool_tNextSign;
uint32_t*FlushCache;//未使用
void*CharConvertUTF8;//未使用
void*CharConvertCustom;//未使用
intCustomCodePage;//未使用
void*CharConvertAscii;//未使用
void*Application;
void*Logger;//未使用
bool_tKeepDisplay;//是否保持背光长亮
intDisableOutOfMemory;//未使用
}context;
(2)nodedef功能模块定义对象
功能模块树状结构通常由若干个静态定义对象(nodedef)实例实现,
typedefstructnodedef
{
intFlags;//功能模块节点的类型:
抽象、实节点、全局、设置。
intClass;//功能模块节点的标识,如MEDIA_CLASS或ASF_ID等等。
intParentClass;//功能模块父节点的标识,如SYSTIMER_ID对象的父节点是TIMER_CLASS。
intPriority;//表示功能模块节点优先级。
nodecreateCreate;//创建功能模块定义对象的函数指针
nodedeleteDelete;//销毁功能模块定义对象的函数指针
}nodedef;//功能模块定义对象
如解码器功能模块静态定义对象:
staticconstnodedefCodec=
{
sizeof(codec)|CF_ABSTRACT,
CODEC_CLASS,
FLOW_CLASS,
PRI_DEFAULT,
(nodecreate)Create,
(nodedelete)Delete,
};
(3)nodeclass功能模块定义对象链表结构
用链表的方式实现了功能模块树状结构,每个链表代表树状结构的一个分支。
typedefstructnodeclass
{
nodedefDef;//功能模块定义对象
bool_tRegistered;//是否注册
intModuleNo;//模块标识
structnodeclass*Parent;//功能模块定义对象的父对象
}nodeclass;//功能模块定义节点对象链表结构
(4)node功能模块数据对象
typedefstructnode
{
intClass;//功能模块节点的类型,如MEDIA_CLASS等等,与nodedef相同。
nodeenumEnum;//枚举节点属性函数指针
nodegetGet;//获取节点属性的函数指针
nodesetSet;//设置节点属性的函数指针
}node;//功能模块数据对象
上述几个数据对象的相互关系:
在系统上下文对象context中有两个元素记录功能模块信息arrayNode和arrayNodeClass,array是数组数据类型(在buffer.h/c中定义和实现),Node是功能模块数据对象的数组,NodeClass功能模块定义对象的数组,按照系统逻辑关系组织。
创建功能模块时传入nodedef对象到功能模块创建函数,函数会根据nodedef信息生成对应nodeclass对象添加到NodeClass数组,同时根据nodedef信息分配数据对象的内存空间。
在该节点的Create函数里面再初始化该功能模块的数据对象node。
(5)datadef功能模块属性
typedefstructdatadef
{
intNo;//属性的标识,如播放控制模块的#definePLAYER_PLAY0x32就表示控制播放器播放或暂停。
intType;//属性的数据类型,在node.h中定义,如TYPE_BOOL
intFlags;//属性数据的标志,是属性数据的标志,表示该数据是不是只读数据,是否有最大最小值等等,node.h中定义,如DF_RDONLY
intFormat1;
intFormat2;
consttchar_t*Name;
intClass;
intSize;
}datadef;//属性对象定义
其中Format1和Format2是可选标志与Flags配合使用,比如如果Flags表示该属性存在最大最小值,Format1就是最大值,Format2则是最小值;
另外,如果(!
(Flags&DF_NOSAVE)&&!
(Flags&DF_RDONLY))即属性标识为保存且可读写,则会被记录到注册表中,下次启动时用注册表的数据初始化该属性表。
(6)datatable功能模块属性列表
typedefstructdatatable
{
intNo;
intType;
intFlags;
intFormat1;
intFormat2;
}datatable;//功能模块属性列表
各功能模块的属性通常以数组的形式定义和存储,如格式解析模块属性列表
staticconstdatatableParams[]=
{
{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外部插件功能模块
typedefstructnodemodule
{
intId;//插件标识
intObjectCount;//该插件的实例个数(引用计数)
bool_tTmp;//是否是临时节点
int64_tDate;//设置时间
intKeepAlive;//保持时间
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函数,可以在系统中载入外部插件模块,
staticNOINLINEnodemodule*LoadModule(context*p,intNo),
第一个参数是上下文对象,
第二个参数是外部插件模块标识
node_win32.c定义了dll的载入与卸载函数以及相应的注册表操作,如
在功能模块节点载入外部插件模块
void*NodeLoadModule(consttchar_t*Path,int*Id,void**AnyFunc,void**Db)
与界面相交互的播放控制模块(player.c)
在所有功能模块中和界面加交互的主要就是播放控制模块structnode*Player;使用方法如下:
context*p=Context();
player*myplayer=NULL;
if(p)myplayer=(player*)(p->Player);
控制播放使用
Set(void*This,intNo,constvoid*Data,intSize)
第一个参数是播放模块指针,
第二个参数是控制代码,即要进行什么操作,
第三个参数是需要赋值给控制代码的数值,
最后一个参数是所赋数值的占用内存的大小。
myplayer->Set(myplayer,PLAYER_PLAY,1,sizeof(int));
PLAYER_PLAY为控制代码,表示当前控制的是播放暂停功能,数值为1表示播放为0表示暂停。
得到某一控制属性使用Get(void*This,intNo,void*Data,intSize);函数,参数含义和Set函数相同。
控制代码是一组宏,定义在player.h文件中。
比较重要的控制参数有播放控制模块所有可用参数见staticconstdatatablePlayerParams[]结构。
添加一个媒体文件到播放模块使用
intPlayerAdd(player*Player,intIndex,consttchar_t*Path,consttchar_t*Title);
第一个参数为播放模块指针,
第二个参数是添加到播放模块文件队列的序号,如果是使文件成为第一个文件该参数设为0,
第三个参数是媒体文件的目录和名称,
第四个参数为媒体文件标题,该参数可以忽略。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TCPMPCodeStructureAnalyse
![提示](https://static.bdocx.com/images/bang_tan.gif)