Android的多媒体框架Opencore代码阅读

Android的多媒体框架Opencore代码阅读

目录结构
OpenCore的代码在以下目录中:external/opencore/。这个目录是OpenCore的根目录,其中包含的子目录如下所示:

    * android:这里面是一个上层的库,它基于PVPlayer和PVAuthor的SDK实现了一个为Android使用的Player和Author。
    * baselibs:包含数据结构和线程安全等内容的底层库
    * codecs_v2:这是一个内容较多的库,主要包含编解码的实现,以及一个OpenMAX的实现
    * engines:包含PVPlayer和PVAuthor引擎的实现
    * extern_libs_v2:包含了khronos的OpenMAX的头文件
    * fileformats:文件格式的据具体解析(parser)类
    * nodes:编解码和文件解析的各个node类。
    * oscl:操作系统兼容库
    * pvmi: 输入输出控制的抽象接口
    * protocols:主要是与网络相关的RTSP、RTP、HTTP等协议的相关内容
    * pvcommon:pvcommon库文件的Android.mk文件,没有源文件。
    * pvplayer:pvplayer库文件的Android.mk文件,没有源文件。
    * pvauthor:pvauthor库文件的Android.mk文件,没有源文件。
    * tools_v2:编译工具以及一些可注册的模块。

Splitter的定义与初始化
以wav的splitter为例,在fileformats目录下有解析wav文件格式的pvwavfileparser.cpp文件,在nodes目录 下有pvmf_wavffparser_factory.cpp,pvmf_wavffparser_node.h, pvmf_wavffparser_port.h等文件。
我们由底往上看,vwavfileparser.cpp中的 PV_Wav_Parser类有 InitWavParser ()GetPCMData ()RetrieveFileInfo ()等解析wav格式的成员函数,此类应该就是最终的解析类。我们搜索 PV_Wav_Parser类被用到的地方可知,在 PVMFWAVFFParserNode类中有 PV_Wav_Parser的一个指针成员变量。再搜索可知, PVMFWAVFFParserNode类是通过 PVMFWAVFFParserNodeFactoryCreatePVMFWAVFFParserNode()成员函数生成的。而 CreatePVMFWAVFFParserNode()函数是在 PVPlayerNodeRegistry::PVPlayerNodeRegistry()类构造函数中通过 PVPlayerNodeInfo类被注册到 Oscl_Vector<PVPlayerNodeInfo, OsclMemAllocator> 的vector中,在这个构造函数中,AMR,mp3等node也是同样被注册的。
由上可知,Opencore中对splitter的管理也是与ffmpeg等类似,都是在框架的初始化时注册的,只不过Opencore注册的是每个splitter的factory函数。
综述一下splitter的定义与初始化过程:
  • 每个splitter都在fileformats目录下有个对应的子目录,其下有各自的解析类。
  • 每个splitter都在nodes目录下有关对应的子目录,其下有各自的统一接口的node类和node factory类。
  • 播放引擎PVPlayerEngine类中有PVPlayerNodeRegistry iPlayerNodeRegistry成员变量。
  • PVPlayerNodeRegistry的构造函数中,将 AMR, AAC, MP3等splitter的输入与输出类型标示和node factory类中的create node与release delete接口通过PVPlayerNodeInfo类push到Oscl_Vector<PVPlayerNodeInfo, OsclMemAllocator> iType成员变量中。

当前Splitter的匹配 过程
PVMFStatus PVPlayerNodeRegistry::QueryRegistry(PVMFFormatType& aInputType, PVMFFormatType& aOutputType, Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids)函数的功能是根据输入类型和输出类型,在已注册的node vector中寻找是否有匹配的node,有的话传回其唯一识别标识PVUuid。
QueryRegistry这个函数至底向上搜索可得到,在 android中splitter的匹配过程如下:
  • android_media_MediaPlayer.cpp之中定义了一个JNINativeMethodJAVA本地调用方法)类型的数组gMethods,供java代码中调用MultiPlayer类的setDataSource成员函数时找到对应的c++函数  
    {"setDataSource",       "(Ljava/lang/String;)V",            (void *)android_media_MediaPlayer_setDataSource},
  • static void android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path)
    此函数中先得到当前的MediaPlayer实例,然后调用其setDataSource函数,传入路径
  • status_t MediaPlayer::setDataSource(const char *url)
    此函数通过调getMediaPlayerService()先得到当前的 MediaPlayerService,  const sp<IMediaPlayerService>& service(getMediaPlayerService());
    然后新建一个IMediaPlayer变量,  sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
    在 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
    调 status_t MediaPlayerService::Client::setDataSource(const char *url)函数, ClientMediaPlayerService的一个内部类。
    在 MediaPlayerService::Client::setDataSource中,调sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
    
生成一个继承自MediaPlayerBase的PVPlayer实例,
    PVPlayer的继承关系如下:
    PVPlayer-->MediaPlayerInterface-->MediaPlayerBase
    最后调PVPlayer的setDataSource()函数
  • status_t PVPlayer::setDataSource(const char *url)
  • status_t PVPlayer::prepare()
    此函数开头执行 ret = mPlayerDriver->enqueueCommand(new PlayerSetDataSource(mDataSourcePath,0,0));
    将 PlayerSetDataSource 的command类加入到PlayerDriver的command处理队列中,
    在void PlayerDriver::Run()函数中处理此command,调用下面的handleSetDataSource函数。
  • void PlayerDriver::handleSetDataSource(PlayerSetDataSource* ec)
  • PVCommandId PVPlayerEngine::AddDataSource(PVPlayerDataSource& aDataSource, const OsclAny* aContextData)
        This function allows a player data source to be specified for playback. This function must be called
  • PVMFStatus PVPlayerEngine::DoAddDataSource(PVPlayerEngineCommand& aCmd)
  • PVMFStatus PVPlayerEngine::DoSetupSourceNode(PVCommandId aCmdId, OsclAny* aCmdContext)







评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值