`

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源码相关知识点的详细解析: 1. **TCPMP架构**: TCPMP的核心架构基于FFmpeg库,这是一个跨平台的音频和视频解码框架,它支持多种编码格式,如MPEG、H.264、AAC等。源码中会包含与FFmpeg交互的代码,...

    TCPMP源码导读

    TCPMP的源代码不仅提供了学习多媒体播放器实现的宝贵资源,也鼓励了社区参与和持续改进。通过深入理解TCPMP的源码,开发者可以更有效地扩展和优化播放器功能,以适应不断变化的技术环境和用户需求。

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

    源码分析可以帮助定位问题,修复bug,并提供更好的错误报告和处理机制。 6. **移植与编译**:将TCPMP源码移植到其他Wince6.0设备或不同版本的Windows CE,需要理解源码结构和依赖关系,进行必要的配置和编译。 7. ...

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

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

    wince下TCPMP原代码

    总的来说,TCPMP的源代码提供了一个深入理解Windows CE平台多媒体处理、图形界面设计和资源管理的绝佳机会。通过仔细研究和学习这些源码,开发者可以提升自己的技能,甚至构建出更强大、更个性化的媒体播放解决方案...

    TCPMP播放器源代码

    **TCPMP播放器源代码详解** TCPMP(The Core Pocket Media Player)是一款广泛使用的开源媒体播放器,尤其在嵌入式系统中具有很高的应用价值。它的设计目标是跨平台、高性能,支持多种视频和音频格式,为用户提供...

    用于tcpmp的flv格式解码源码

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

    wince 5.0 ARMV4I 上可以调试的TCPMP源码。。

    5. **作者的修改分析**:由于描述中提到“不知道作者做了什么修改”,我们需要对比原始TCPMP源码和提供的版本,找出可能的改动。这可能包括优化算法、修复已知问题、增加新功能或是针对ARMV4I平台的特殊适配。 6. *...

    TCPMP开源代码导读

    通过理解和分析TCPMP的源代码,我们可以学习到多媒体播放器的设计原理、音视频解码技术以及优化方法,这对进一步开发和优化媒体播放应用有着深远的意义。 总结来说,TCPMP作为一个开源的多媒体播放器,其设计和实现...

    WINCE tcp,WINCE下很好用的TCPMP源程序!界面配置等

    在描述中提到的“TCPMP源程序”意味着这个压缩包可能包含了该媒体播放器的源代码,用户可以对其进行编译、修改或深入研究。 在Windows CE环境下,TCPMP提供了强大的多媒体播放功能,支持多种视频和音频格式,如AVI...

    tcpmp播放器 手机播放器源码

    在“tcpmp.src.0.72RC1”这个文件中,我们预计会找到TCPMP播放器的源代码,包括但不限于以下几个部分: 1. 用户界面:这部分代码负责播放器的图形用户界面,包括播放控制、设置菜单、文件浏览器等功能。 2. 文件...

    tcpmp.src.0.72RC1.rar_264_tcpmp ce source_tcpmp for windows ce_t

    TCPMP(The Core Pocket Media Player)是一款在Windows CE操作系统上广泛应用的媒体播放器,因其强大的视频解码能力和广泛的格式...对于学习和研究移动设备上的多媒体处理技术,TCPMP源代码无疑是一个宝贵的教育资源。

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

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

    tcpmp.src.0.72RC1.rar_TCPMP 0.72R_tcpmp_tcpmp 0.72 sp_tcpmp wind

    TCPMP 0.72RC1是该软件的一个版本,其源代码被包含在"tcpmp.src.0.72RC1.rar"这个压缩包中,提供给开发者研究和定制。下面我们将深入探讨TCPMP及其0.72R版本的相关知识点。 1. **TCPMP简介** TCPMP是一款跨平台的...

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

    6. **跨平台移植**:虽然这里主要是ARM平台的源码,但TCPMP原本也支持其他平台,因此源代码中可能会有关于跨平台兼容性的处理,对于进行类似移植工作有一定的指导意义。 通过深入研究TCPMP的源代码,开发者不仅可以...

    tcpmp.rar_播放器 源码_播放器C

    《TCPMP播放器源码解析:打造掌上影音体验》 TCPMP,全称为The Core Pocket Media Player,是一款经典的掌上设备媒体播放器,尤其在Windows Mobile和Pocket PC平台上享有盛誉。它以其强大的多媒体解码能力和丰富的...

    tcpmp.src.0.72RC1.rar

    通过分析源代码,可以学习到如何实现高效的媒体解码、如何处理各种编码格式、如何优化播放性能,以及如何在不同的设备上实现跨平台兼容性。 总的来说,"tcpmp.src.0.72RC1.rar"提供了一个宝贵的开源项目,对于那些...

    tcpmp.src.0.72RC1.zip.zip_tcpmp_tcpmp.src.0.72RC1

    对于开发者而言,TCPMP的源代码是一个宝贵的教育资源,可以学习到如何处理多媒体播放中的各种技术问题,比如解码流程、文件格式解析、播放控制以及性能优化等。同时,通过分析源代码,开发者还可以了解软件架构设计...

    TCPMP播放器源码

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

Global site tag (gtag.js) - Google Analytics