1 函数PVPlayer::prepareAsync():
1)判断是否已经设置数据源,
2)如果没有设置,将命令设置播放数据源(PlayerSetDataSource)加入到命令队列中,
3)如果已经设置数据源,则将命令PlayerPrepare加入到命令队列中;
4)返回。
2 函数PlayerSetDataSource(mDataSourcePath,run_init,this)
参数:mDataSourcePath是要播放文件的路径地址(如:/sdcard/video/lvxing.mp3),
run_init:命令在异步模式下执行,作为回调函数;
this:PVPlayer。
3 函数PlayerDriver::handleSetDataSource
对添加数据源命令进行处理,
1)判断是否已经设置过数据源,如果有则将参数mDataSource删除;
2)构造一个PVPlayerDataSourceURL,用mDataSource保存,这个类是继承类PVPlayerDataSource的;
类PVPlayerDataSourceURL,是类PVPlayerDataSource的子类,用于保存数据源;包含许多成员函数对主要是对数据源进行操作;
成员量:
类OneClip
uint32 iCurrentClip:当前源文件序号,主要用于生成播放列表;
Oscl_Vector iClipList:vector量,播放列表,保存源文件;
3)oscl_UTF8ToUnicode将文件的绝对路径转化为Unicode;
4)mDataSource->SetDataSourceURL(wFileName),wFileName包含转化后的Unicode,将wFileName传递给iClipList中保存;
5)判断数据流类型,分为三种情况:rtsp(实时流传输协议流),http(超文本传输协议流),绝对路径;在此是绝对路径文件。
6)mDataSource->SetDataSourceFormatType,设置源文件格式,目前还是PVMF_MIME_FORMAT_UNKNOWN,未知格式;
7)通过url判断文件格式是否是.sdp,如果格式是sdp格式,则不用识别这一个过程,直接将文件格式设置为PVMF_MIME_DATA_SOURCE_SDP_FILE;
8)新建类PVMFSourceContextData用mLocalContextData保存,并调用mDataSource->SetDataSourceContextData关联到mDataSource,将mLocalContextData保存在iClipList[iCurrentClip].iContext;
类PVMFSourceContextData是类PVInterface的子类;
接着调用此类的成员函数:EnableCommonSourceContext(),将类的成员iCommonDataContextValid设置为true,在后面会有所体现;
9)调用mPlayer->AddDataSource(*mDataSource, command),进入到下一层添加数据源,在此mPlayer实际是指向PVPlayerEngine的,在此函数中将mDataSource加入到vector量paramvec中,并将command加入到命令队列,接下来在Run中处理。
此处的command是new PlayerSetDataSource(mDataSourcePath,run_init,this),其中的this是PVPlayer;
paramvec是一个vector量,先分配一个空间,在用param(类型是union PVPlayerEngineCommandParamUnion),保存mDataSource,再将param插入到vector中;
PVPlayerEngineCommand cmd(aCmdType, commandId, aContextData, aParamVector, aAPICommand);
参数:
aCmdType:命令的类型;
commandId:命令的ID;
aContextData:command;
aParamVector:包含mDataSource的vector量;
到目前为止,有关数据源的仍然是mDataSource,而且仅是涉及到源文件的存放路径而已,还没有真正的数据流产生。
4 函数PVPlayerEngine::Run()
此函数是引擎层对命令的处理函数:
iCurrentCmd:是vector类型,大小为1,保存当前正被处理的命令;
iCmdToCancel:大小为1,保存当前正被取消的命令;
iPendingCmds:保存已经被请求的命令,也就是就要处理的命令;
1)首先检查Engine状态,确定不是在PVP_ENGINE_STATE_RESETTING;
2)检查在iPendingCmds中的命令是不是错误处理请求,
3)检查iCurrentCmd当前正在处理的命令,并做相应的操作以完成命令;
4)检查iPendingCmds是否有取消命令的请求;
5)检查参数iRollOverState,做相应操作(?);
6)进入常规命令处理流程,将iPendingCmds中顶层命令取出,在顶部插入到iCurrentCmd中,根据命令的类型做相应处理;
7)调用函数PVPlayerEngine::DoAddDataSource(&cmd);
5 函数PVPlayerEngine::DoAddDataSource(PVPlayerEngineCommand& aCmd);
参数就是上面的cmd;
1)获取mDataSource,不过将其类型转化为PVPlayerDataSource*,保存为iDataSource;
2)调用iDataSource->GetDataSourceContextData(),获取前面构造的mLocalContextData(PVMFSourceContextData*),并将其转化为PVInterface*类型保存于pvInterface中;类PVMFSourceContextData继承于类PVInterface
3)调用pvInterface->queryInterface(localDataSrcUuid, localDataSrc),获取对用UUID的接口指针,queryInterface为虚函数,实际调用其子类PVMFLocalDataSource中的对应函数,返回指向PVMFLocalDataSource的指针,保存于localDataSrc中,做类型转化,回复原来类型,保存于opaqueData中;
也就是构造了类PVMFLocalDataSource,类PVMFLocalDataSource也继承类PVInterface;
类PVMFLocalDataSource保存本地回放的源数据,
4)检查文件格式如果是未知格式(PVMF_MIME_FORMAT_UNKNOWN),调用DoQuerySourceFormatType识别文件格式,处于异步处理模式,先返回,将命令加入对列等待处理;
查询文件格式的函数原型:DoQuerySourceFormatType(aCmd.GetCmdId(), aCmd.GetContext()),此函数的参数是命令ID和类PVPlayerEngineCommand中的成员量iContextData;
5)函数DoAddDataSource退出,返回到Run()中。
6 PVPlayerEngine::DoQuerySourceFormatType(PVCommandId aCmdId, OsclAny* aCmdContext)
参数:命令ID,aContextData:指向PlayerSetDataSource;
context(PVPlayerEngineContext*)保存命令ID和aCmdContext,aCmdContext指向PlayerSetDataSource,包含源文件的绝对路径
1)iDataSource->GetDataSourceContextData()获取mLocalContextData(PVMFSourceContextData*),用opaqueData保存,并将其类型转化为PVInterface,保存于pvInterface;
2)调用pvInterface->queryInterface(SourceContextDataUuid, SourceContextData),实际调用的是类PVMFSourceContextData的成员函数queryInterface,此函数返回一个指向类PVMFSourceContextData的指针,保存于SourceContextData中,就是前面的mLocalContextData;
3)调用SourceContextData->CommonData()获得aSourceContextDataCommon(PVMFSourceContextDataCommon*);
在类PVMFSourceContextDataCommon中有个成员PVMFCPMPluginAccessInterfaceFactory* iRecognizerDataStreamFactory,保存到DataStreamDataFactory
4)iPlayerRecognizerRegistry.QueryFormatType(DataStreamDataFactory, *this, (OsclAny*) context),识别文件格式;
PVPlayerRecognizerRegistry iPlayerRecognizerRegistry,是Engine的识别器的注册类;
5)根据上面函数的执行结果返回。
当目前还没有涉及到文件数据的传递,仅是源文件存储路径的传递;
7 函数PVPlayerRecognizerRegistry::QueryFormatType(PVMFCPMPluginAccessInterfaceFactory* aDataStreamFactory, PVPlayerRecognizerRegistryObserver& aObserver, OsclAny* aCmdContext)
参数:
PVPlayerRecognizerRegistryObserver:this,指向PVPlayerEngine,作为事件的观察者;
OsclAny* aCmdContext,指向类PlayerSetDataSource,包含文件路径;
1)准备工作:略;
2)调用函数PVMFRecognizerRegistry::OpenSession(iRecSessionId, *this),this指向PVPlayerRecognizerRegistry;开启与识别器的会话(?)
3)调用函数
PVMFRecognizerRegistry::Recognize(iRecSessionId, *iDataStreamFactory, NULL, iRecognizerResult, NULL);
其中iRecSessionId是类PVMFRecognizerRegistry的成员,在类构造时会对其设定初值;iRecognizerResult是一个vector量,保存识别的结果;
iDataStreamFactory就是前面指向类PVMFCPMPluginAccessInterfaceFactory的指针。
4)函数结束。
到现在已经没有参数涉及到要播放的源文件的路径了,那后面是怎么读取这个文件的呢???
8 函数PVMFRecognizerRegistry::OpenSession(PVMFSessionId& aSessionId, PVMFRecognizerCommmandHandler& aCmdHandler)
参数:
aSessionId:类型是int32;
aCmdHandler指向类PVMFRecognizerCommmandHandler,是类PVPlayerRecognizerRegistry的父类之一,所以PVPlayerRecognizerRegistry也是此函数的观察者;
1)首先获得指向类PVMFRecognizerRegistryImpl的指针pvrecregimpl,这是一个实现类;
2)调用函数pvrecregimpl->OpenSession(aSessionId, aCmdHandler),此函数的作用就是将这个Session加入到Sessionlist中,并将aSessionId输出;
9 函数
PVMFRecognizerRegistry::Recognize(PVMFSessionId aSessionId, PVMFDataStreamFactory& aSourceDataStreamFactory, PVMFRecognizerMIMEStringList* aFormatHint,
Oscl_Vector& aRecognizerResult, OsclAny* aCmdContext, uint32 aTimeout)
同样是调用对应实现类中的相应函数pvrecregimpl->Recognize(aSessionId, aSourceDataStreamFactory, aFormatHint, aRecognizerResult, aCmdContext, aTimeout),此函数将命令加入到命令队列中处理。
现在函数传递的所有参数中没有涉及到源文件的任何信息!!
10 函数PVMFRecognizerRegistryImpl::Run()
对上面的识别命令进行处理。
根据命令类型,调用函数PVMFRecognizerRegistryImpl::DoRecognize()
1)从当前命令列表中读出某些参数,如返回结果recresult,iDataStreamFactory;
2)调用函数PVMFRecognizerRegistryImpl::CreateDataStream()创建iDataStream,是指向类PVMIDataStreamSyncInterface的指针,函数返回不成功,则退出识别函数,进行错误处理;
3)使用布尔量oRunRecognition进入while循环,直到能真正识别文件格式才退出;
11 函数PVMFRecognizerRegistryImpl::CreateDataStream()
用于创建数据流指针iDataStream,iDataStream指向类PVMIDataStreamSyncInterface,此类继承类PVInterface,这时就会用到iDataStreamFactory了
1)调用iDataStreamFactory->CreatePVMFCPMPluginAccessInterface(uuid),参数uuid是PVMIDataStreamSyncInterfaceUuid,函数返回一个指向类PVInterface的指针intf,再将此指针转化为PVMIDataStreamSyncInterface*类型,此函数是个虚函数。
类PVMIDataStreamSyncInterfaceRefFactory继承于类PVMFDataStreamFactory也就是类PVMFCPMPluginAccessInterfaceFactory,又继承类PVInterface,所以此函数实际调用的是类PVMIDataStreamSyncInterfaceRefFactory的成员函数。
此函数有调用PVMIDataStreamSyncInterfaceRefImpl::CreateDataStreamSyncInterfaceRefImpl(iFileName)来创建,这时涉及到一个参数iFileName,其声明如下:OSCL_wHeapString iFileName,与前面保存Unicode的变量wFileName声明一致,两者应该是共用内存空间
2)调用函数iDataStream->OpenSession(iDataStreamSessionID, PVDS_READ_ONLY),实际调用函数PVMIDataStreamSyncInterfaceRefImpl::OpenSession
此函数会打开要播放的文件,涉及到数据流的传输,iDataStream保存数据流,
3)打开文件成功与否,函数返回标志状态。
12 函数PVMIDataStreamSyncInterfaceRefImpl::OpenSession(PvmiDataStreamSession& aSessionID,
PvmiDataStreamMode aMode,
bool nonblocking)
参数:aSessionID:ID号,作为输出参数;aMode,指明文件的读写模式,输入参数;
在对文件操作时可以通过参数iFileHandle(OsclFileHandle*),也可以通过iFileName,在此是通过后者。
1)新建iFileObject(Oscl_File *);
2)调用函数iFileObject->Open(iFileName.get_cstr(), Oscl_File::MODE_READ, iFs),打开文件,文件打开成功返回0,;
3)
13 函数Oscl_File::Open(const char *filename, uint32 mode, Oscl_FileServer& fileserv)
调用函数CallNativeOpen(filename, mode , params, fileserv)完成操作
多次打开文件,用iDataStream(PVMIDataStreamSyncInterface*)保存数据流,识别文件格式后要关闭会话,将包含数据流的量删除。在识别文件格式后会调用回调函数通知识别格式命令已经完成,用相应参数保存文件格式,
回调函数:
PVPlayerRecognizerRegistry::RecognizerCommandCompleted,在此函数的最后调用函数RunIfNotReady(),通知调度器,运行当前AO,也就是在接下来调用函数PVPlayerRecognizerRegistry::Run(),这个Run函数再去调用iObserver->RecognizeCompleted,此处的观察者就是Engine,接着又调用函数PVPlayerEngine::DoSetupSourceNode;
完成文件格式识别后,要建立源节点