TCPMP流媒体插件模块分析

TCPMP流媒体插件模块分析

一:TCPMP模块工作流程

 

二:加载介质流程分析

加载介质的流程主要在common工程中player.c文件的Load函数

static int Load(player_base* p,bool_t Silent,bool_t OnlyLocal,bool_t Nested)

 

//首先获取播放地址串的MIME,即scheme。如:file,mem,http,mms等。

URL = p->PlayList[p->Current].URL;

GetMime(URL,Mime,TSIZEOF(Mime),&p->HasHost);

//枚举STREAM_CLASS中的所有流式输入模块,取得MIME对应的流式输入模块

Input = GetStream(URL,Silent);

p->Input = Input;

 

//获取播放介质的显示标题

if (p->PlayList[p->Current].Title[0])

       tcscpy_s(p->Title,TSIZEOF(p->Title),p->PlayList[p->Current].Title);

else

       URLToTitle(p->Title,TSIZEOF(p->Title),URL);

 

//为流式输入模块设置参数commentsilenturl等。

//网络流式输入模块在设置url后一般就会启动网络流程,获取介质基本信息。

Comment.No = PLAYER_COMMENT;

Comment.Node = (node*)p;

p->Input->Set(p->Input,STREAM_COMMENT,&Comment,sizeof(pin));

p->Input->Set(p->Input,STREAM_SILENT,&Silent,sizeof(Silent));

p->Input->Set(p->Input,STREAM_URL,URL,TSIZEOF(p->PlayList[p->Current].URL));

 

//获取该介质的长度

if (p->Input->Get(p->Input,STREAM_LENGTH,&Length,sizeof(int))!=ERR_NONE)

       Length = -1;

 

//分配4KB数据空间,先从流式模块中尝试读取4KB数据作Probe之用。

if (!AllocBlock(PROBE_SIZE,&Probe,0,HEAP_ANY))

{

       Unload(p,Silent,0,1);

       return ERR_OUT_OF_MEMORY;

}

ProbeSize = p->Input->ReadBlock(p->Input,&Probe,0,PROBE_SIZE);

 

//获取介质的Content-Type

p->Input->Get(p->Input,STREAM_CONTENTTYPE,ContentType,sizeof(ContentType));

 

//根据介质的后缀名,Content-Type以及Probe数据枚举STREAMPROCESS_CLASS分支下的所有模块,一般情况下该分支下并没有模块。

NodeEnumClassEx(&List,STREAMPROCESS_CLASS,ContentType,URL,Probe.Ptr,ProbeSize);

 

//根据介质的后缀名,Content-Type以及Probe数据枚举FORMAT_CLASS分支下的所有模块,找到对应的容器格式解析模块。

NodeEnumClassEx(&List,FORMAT_CLASS,ContentType,URL,Probe.Ptr,ProbeSize);

 

//其中NodeEnumClassEx函数枚举的匹配顺序为Content-TypeExtensionsProbe

if ((ContentType || URL || Data) &&

 (!ContentType || !CheckContentType(ContentType,LangStrDef(Id,NODE_CONTENTTYPE))) &&

 (!URL || !CheckExts(URL,LangStrDef(Id,NODE_EXTS))) &&

 (!Data || !DataProbe(Data,Length,LangStrDef(Id,NODE_PROBE))))

continue;

 

//设置匹配出的解析模块的输入为之前的流媒体输入模块

if (p->Format->Set(p->Format,FORMAT_INPUT,&p->Input,sizeof(stream*)) == ERR_NONE)

break;

 

//如果FORMAT_CLASS分支没有合适的解析模块,则播放串可能指向一个播放列表文件,尝试枚举PLAYLIST_CLASS中的所有模块。

if (!p->Format && !Nested)                       NodeEnumClassEx(&List,PLAYLIST_CLASS,ContentType,URL,Probe.Ptr,ProbeSize);

 

Flush(p);

StopLoadMode(p);

UpdatePlay(p);

UpdateRunInput(p);

UpdateRunProcess(p);

UpdateTimeouts(p);

 

三:网络流媒体插件模块实现参考

TCPMP中的Stream节点是用于处理媒体数据输入的模块,其中common工程包含文件输入(FILE)以及内存输入(MEM)。Network工程则以插件形式实现了基于HTTPMMS协议的流媒体插件模块。下面以HTTP模块为例进行分析。

 

static const nodedef HTTP =

{

       sizeof(http),

       HTTP_ID,

       STREAM_CLASS,

       PRI_MINIMUM,

       (nodecreate)Create,

       (nodedelete)Delete,

};

 

其中http是一个自定义结构体,里面有一个stream结构体类型的变量Stream,记录当前的数据流及其接口函数。http模块的WinCE平台实现主要依赖WinInet API函数完成。

继承自STREAM的模块需要实现的接口主要包括:SetGetDataAvailableReadReadBlockSeekEnumDir等函数。

 

static int Set(http* p, int No, const void* Data, int Size)

提供设置URLCommentSilent等参数。当设置播放URL时,就会调用Open函数启动网络进行HTTP下载。

 

static int Get(http* p, int No, void* Data, int Size)

提供获取URLCommentSilentLength等参数

 

static int DataAvailable(http* p)

检查当前还有多少可读的数据。WinCE平台通过调用InternetQueryDataAvailable实现。

Format_base模块在读取数据(ReadBlock)之前会先调用DataAvailable,以便设定读取的数据量上限。以下为format_base.c相关代码:

int Available = Reader->Input->DataAvailable(Reader->Input);

if (Left > Available) Left = Available;

Length = Reader->Input->ReadBlock(Reader->Input,&Buffer->Block,Buffer->Length,Left);

 

static int Read(http* p,void* Data,int Size)

static int ReadBlock(http* p,block* Block,int Ofs,int Size)

ReadBlock函数实际内部调用Read函数,而Read函数则调用InternetReadFile函数从网络读取数据。这两个函数都实现为阻塞刑读取,设定读操作超时时间为180秒。读操作成功后立即更新http结构内部变量Pos

 

static filepos_t Seek(http* p,filepos_t Pos,int SeekMode)

Seek函数为支持上层Seek操作所用,目前支持两种模式:

SeekModeSEEK_CUR时,则从当前播放点平移Pos值。(Pos正负不限)

SeekModeSEEK_SET时,则从介质文件开始处开始平移Pos值。(Pos>=0

SeekModeSEEK_END时,则从介质文件末尾处开始平移Pos值。(Pos<=0

 

static int EnumDir(http* p,const tchar_t* URL,const tchar_t* Exts,bool_t ExtFilter,streamdir* Item)

EnumDir支持枚举一个URL指向的HTML网页中所有的介质文件的地址串。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值