2024年4月28日发(作者:)

TCPMP(The Core Pocket Media Player),这是一个应用于智能设备上的开源媒体播放软

件。

TCPMP是一个功能强大开放式的开源多媒体播放器,播放器主要由核心框架模块

(common工程)和解码器分离器插件组成。

TCPMP的插件非常多,联合几个最常用的插件(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.29),虽然解码精度会有

损失,但是极大提高了解码效率,特别是在嵌入式设备上也可以实现高码率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;