5.1 Player的组成
OpenCore的Player的编译文件是pvplayer/Android.mk,将生成动态库文件libopencoreplayer.so。这个库包含了两方面的内容:一方是Player的engine(引擎),一方面是为 Android构件的Player,这实际上是一个适配器(adapter)。engine的路径是engine/player;adapter的路径是 android。
5.2 Player Engine部分
OpenCore的Player Engine具有清晰明确的接口。在这个接口之上,不同的系统可一个根据自己的情况实现不同Player。目录engines中的文件结构如下所示:
engines/player/
|-- Android.mk
|-- build
| |-- linux_nj
| |-- make
| `-- makefile.conf
|-- config
| `-- linux_nj
|-- include
| |-- pv_player_datasink.h
| |-- pv_player_datasinkfilename.h
| |-- pv_player_datasinkpvmfnode.h
| |-- pv_player_datasource.h
| |-- pv_player_datasourcepvmfnode.h
| |-- pv_player_datasourceurl.h
| |-- pv_player_events.h
| |-- pv_player_factory.h
| |-- pv_player_interface.h
| |-- pv_player_license_acquisition_interface.h
| |-- pv_player_registry_interface.h
| |-- pv_player_track_selection_interface.h
| `-- pv_player_types.h
|-- sample_app
| |-- Android.mk
| |-- build
| |-- sample_player_app_release.txt
| `-- src
|-- src
| |-- pv_player_datapath.cpp
| |-- pv_player_datapath.h
| |-- pv_player_engine.cpp
| |-- pv_player_engine.h
| |-- pv_player_factory.cpp
| |-- pv_player_node_registry.h
| `-- pv_player_sdkinfo.h
`-- test
|-- Android.mk
|-- build
|-- config
`-- src
其中,engines/player/include目录中是接口头文件,engines/player/src目录源文件和私有头文件,主要头文件的功能如下所示:
pv_player_types.h:定义一些数据结构和枚举值
pv_player_events.h:定义UUID和一些错误值。
pv_player_datasink.h:datasink是媒体数据的输出,定义类PVPlayerDataSink,这是媒体数据输出的基类,作为接口使用
pv_player_datasinkfilename.h:定义类PVPlayerDataSinkFilename继承PVPlayerDataSink。
pv_player_datasinkpvmfnode.h:定义类PVPlayerDataSinkPVMFNode继承PVPlayerDataSink。
pv_player_datasource.h:datasource是媒体数据的输入,定义类PVPlayerDataSource,这是媒体数据输入的基类,作为接口使用。
pv_player_datasourcepvmfnode.h:定义类PVPlayerDataSourcePVMFNode继承PVPlayerDataSource。
pv_player_datasourceurl.h:定义类PVPlayerDataSourceURL继承PVPlayerDataSource。
pv_player_interface.h:定义Player的接口PVPlayerInterface,这是一个接口类。
pv_player_factory.h:主要定义工厂类PVPlayerFactory,用于创建和销毁PVPlayerInterface。
事实上,在engines/player/src目录中,主要实现类为pv_player_engine.cpp,其中定义了类PVPlayerEngine,PVPlayerEngine继承了PVPlayerInterface,这是一个实现类,在PVPlayerFactory创建PVPlayerInterface接口的时候,实际创建的是PVPlayerEngine。
在Player Engine的实现中,包含了编解码和流控制等功能,而输出的介质需要从外部设置近来。PVPlayerInterface定义的接口基本是按照操作顺序的,主要的接口如下所示:
在Player Engine的实现中,包含了编解码和流控制等功能,而输出的介质需要从外部设置近来。PVPlayerInterface定义的接口基本是按照操作顺序的,主要的接口如下所示:
PVCommandId AddDataSource(PVPlayerDataSource& aDataSource, const OsclAny* aContextData = NULL);
PVCommandId Init(const OsclAny* aContextData = NULL);
PVCommandId AddDataSink(PVPlayerDataSink& aDataSink, const OsclAny* aContextData = NULL);
PVCommandId Prepare(const OsclAny* aContextData = NULL);
PVCommandId Start(const OsclAny* aContextData = NULL);
PVCommandId Pause(const OsclAny* aContextData = NULL);
PVCommandId Resume(const OsclAny* aContextData = NULL);
PVCommandId Stop(const OsclAny* aContextData = NULL);
PVCommandId RemoveDataSink(PVPlayerDataSink& aDataSink, const OsclAny* aContextData = NULL);
PVCommandId Reset(const OsclAny* aContextData = NULL);
PVCommandId RemoveDataSource(PVPlayerDataSource& aDataSource, const OsclAny* aContextData = NULL);
这里面的DataSink可能包含Video的输出和Audio的输出两者部分。在pv_player_types.h文件中,定义了Player的状态机,以PVP_STATE_为开头,如下所示:
typedef enum
{
PVP_STATE_IDLE = 1,
PVP_STATE_INITIALIZED = 2,
PVP_STATE_PREPARED = 3,
PVP_STATE_STARTED = 4,
PVP_STATE_PAUSED = 5,
PVP_STATE_ERROR = 6
} PVPlayerState;
PVPlayerInterface中的各个操作如果成功,可以更改Player的状态机:初始化的时候Player是PVP_STATE_IDLE状态,调用Init后,进入PVP_STATE_INITIALIZED状态;调用AddDataSink,进入PVP_STATE_PREPARED状态;调用Prepare后,进入PVP_STATE_PREPARED状态;调用start后进入PVP_STATE_STARTED状态,之后可以调用 pause进入PVP_STATE_PAUSED状态。
PVP_STATE_STARTED和PVP_STATE_PAUSED状态是播放情况下的状态,可以使用start和pause函数在这两个状态中切换。
在播放过程中,调用stop可以返回PVP_STATE_INITIALIZED状态,在调用RemoveDataSource返回PVP_STATE_IDLE状态。
5.3 Android Player Adapter
在android目录中定义为Player的适配器,这个目录主要包含的文件如下所示:
android
|-- Android.mk
|-- android_audio_mio.cpp
|-- android_audio_mio.h
|-- android_audio_output.cpp
|-- android_audio_output.h
|-- android_audio_output_threadsafe_callbacks.cpp
|-- android_audio_output_threadsafe_callbacks.h
|-- android_audio_stream.cpp
|-- android_audio_stream.h
|-- android_log_appender.h
|-- android_surface_output.cpp
|-- android_surface_output.h
|-- mediascanner.cpp
|-- metadatadriver.cpp
|-- metadatadriver.h
|-- playerdriver.cpp
|-- playerdriver.h
`-- thread_init.cpp
这个Android的Player的“适配器”需要调用OpenCore的Player Engine的接口,实现Android的媒体播放器的服务所需要接口,即最终实现一个PVPlayer,而PVPlayer实际上是继承了 MediaPlayerInterface。
在实现过程中,首先实现了一个PlayerDriver,然后再使用PVPlayer,PVPlayer通过调用PlayerDriver来完成具体的功能。整个实现的结构图如图所示:
对PVPlayerDriver的各种操作使用各种命令来完成,这些命令在playerdriver.h中进行的定义。
enum player_command_type {
PLAYER_QUIT = 1,
PLAYER_SETUP = 2,
PLAYER_SET_DATA_SOURCE = 3,
PLAYER_SET_VIDEO_SURFACE = 4,
PLAYER_SET_AUDIO_SINK = 5,
PLAYER_INIT = 6,
PLAYER_PREPARE = 7,
PLAYER_START = 8,
PLAYER_STOP = 9,
PLAYER_PAUSE = 10,
PLAYER_RESET = 11,
PLAYER_SET_LOOP = 12,
PLAYER_SEEK = 13,
PLAYER_GET_POSITION = 14,
PLAYER_GET_DURATION = 15,
PLAYER_GET_STATUS = 16,
PLAYER_REMOVE_DATA_SOURCE = 17,
PLAYER_CANCEL_ALL_COMMANDS = 18,
};
这些命令一般实现的是PVPlayerInterface各个接口的简单封装,例如对于较为简单的暂停播放这个操作,整个系统执行的过程如下所示:
1.在PVPlayer中的pause函数(在playerdriver.cpp文件中)
status_t PVPlayer::pause()
{
LOGV("pause");
return mPlayerDriver->enqueueCommand(new PlayerPause(0,0));
}
这时调用其成员mPlayerDriver(PlayerDriver类型)的函数,将一个PlayerPause命令加入了命令序列,具体的各种命令功能在playerdriver.h文件中。
2.PlayerDriver类的enqueueCommand将间接调用各个以handle为开头的函数,对于PlayerPause命令,调用的函数是handlePause
void PlayerDriver::handlePause(PlayerPause* ec)
{
LOGV("call pause");
mPlayer->Pause(0);
FinishSyncCommand(ec);
}
这里的mPlayer是一个PVPlayerInterface类型的指针,使用这个指针调用到了OpenCore的 Player Engine中的PVPlayerEngine类。
在这个播放器适配器的实现中,一个主要的工作是将Android框架中定义的媒体的输出(包括Audio的输出和Video的输出)转换成,OpenCore的 Player Engine需要的形式。在这里两个重要的类是android_surface_output.cpp实现的 AndroidSurfaceOutput,android_audio_output.cpp实现的AndroidAudioOutput。
对于Video输出的设置过程,在类PlayerDriver中定义了3个成员:
PVPlayerDataSink *mVideoSink;
PVMFNodeInterface *mVideoNode;
PvmiMIOControl *mVideoOutputMIO;
这里的mVideoSink 的类型为PVPlayerDataSink,这是Player Engine中定义的类接口,mVideoNode的类型为VMFNodeInterface,在pvmi/pvmf/include的 pvmf_node_interface.h中定义,这是所有的PVMF的NODE都需要继承的统一接口,mVideoOutputMIO的类型为 PvmiMIOControl也在pvmi/pvmf/include中定义,这是媒图输出控制的接口类。
1.在PVPlayer的setVideoSurface用以设置一个Video输出的界面,这里使用的参数的类型是ISurface指针:
status_t PVPlayer::setVideoSurface(const sp& surface)
{
LOGV("setVideoSurface(%p)", surface.get());
mSurface = surface;
return OK;
}
setVideoSurface函数设置的是PVPlayer中的一个成员mSurface,真正设置Video输出的界面的功能在run_set_video_surface()函数中实现:
void PVPlayer::run_set_video_surface(status_t s, void *cookie)
{
LOGV("run_set_video_surface s=%d", s);
if (s == NO_ERROR) {
PVPlayer *p = (PVPlayer*)cookie;
if (p->mSurface == NULL) {
run_set_audio_output(s, cookie);
} else {
p->mPlayerDriver->enqueueCommand(new PlayerSetVideoSurface(p->mSurface, run_set_audio_output, cookie));
}
}
}
这时使用的命令是PlayerSetVideoSurface,最终将调用到PlayerDriver中的handleSetVideoSurface函数。
2.handleSetVideoSurface函数的实现如下所示:
void PlayerDriver::handleSetVideoSurface(PlayerSetVideoSurface* ec)
{
int error = 0;
mVideoOutputMIO = new AndroidSurfaceOutput(ec->surface());
mVideoNode = PVMediaOutputNodeFactory::CreateMediaOutputNode(mVideoOutputMIO);
mVideoSink = new PVPlayerDataSinkPVMFNode;
((PVPlayerDataSinkPVMFNode *)mVideoSink)->SetDataSinkNode(mVideoNode);
((PVPlayerDataSinkPVMFNode *)mVideoSink)->SetDataSinkFormatType(PVMF_YUV420);
OSCL_TRY(error, mPlayer->AddDataSink(*mVideoSink, ec));
OSCL_FIRST_CATCH_ANY(error, commandFailed(ec));
}
在这里首先建立的创建成员mVideoOutputMIO(类型为PvmiMIOControl),这时建立的类是类 AndroidSurfaceOutput,这个类继承了PvmiMIOControl,所以可以作为PvmiMIOControl使用。然后调用 PVMediaOutputNodeFactory::CreateMediaOutputNode建立了PVMFNodeInterface 类型的mVideoNode。随后创建PVPlayerDataSinkPVMFNode类型的 mVideoSink,PVPlayerDataSinkPVMFNode本身继承了PVPlayerDataSink,因此可以作为 PVPlayerDataSink使用。调用SetDataSinkNode函数将mVideoNode设置为mVideoSink的数据输出节点。
事实上,对于Video的输出,基本的功能都是在类AndroidSurfaceOutput中完成的,在这个类当中,主要的工作是将Android的 ISurface输出作为Player Engine的输出。最后调用了AddDataSink将mVideoSink增加为了PVPlayerInterface的输出。
在android_surface_output.cpp文件中实现了类AndroidSurfaceOutput,这个类相当于一个OpenCore Player Engine的Video输出和Android输出的“适配器”。AndroidSurfaceOutput类本身继承了类 PvmiMIOControl,而其构造函数又以ISurface类型为参数。这个类的实现是使用ISurface实现PvmiMIOControl的各个接口。
分享到:
相关推荐
### PVPlayer Engine Unit Test Guide #### 1. 引言 本文档主要介绍了PVPlayer引擎单元测试的使用方法以及覆盖的测试案例。PVPlayer引擎单元测试是一个基于命令行的应用程序,它通过驱动PVPlayer引擎执行多种不同...
标题:PVPlayer开发指南 描述:本文档详细介绍了Android平台上PVPlayer的工作原理,为开发者提供了深入理解PVPlayer SDK的关键信息,以及如何在不同场景下应用这些知识。 知识点: ### PVPlayer SDK定义与范围 ...
这个“Opencore-pvplayer.rar_I AM_opencore”压缩包似乎包含了与OpenCore相关的学习资料,特别是“Opencore pvplayer.doc”文档,可能详细介绍了如何配置和使用OpenCore来播放PV(可能是音乐或视频文件)。...
在Android平台上,PVPlayer是一个关键的组件,它是由OpenCore框架提供的一种多媒体播放器。OpenCore是一个综合的多媒体处理解决方案,包含了编解码、流处理和播放器引擎等功能。PVPlayer的核心在于其Player Engine和...
- PVPlayer Engine:PVPlayer的引擎部分,负责实际的播放操作。 - PVAuthor Engine:PVAuthor的引擎部分,用于媒体的录制操作。 OpenCore的源代码结构如下: - `external/opencore`:OpenCore的源码根目录,下含...
**PVPlayer**:PVPlayer是OpenCore的核心组件之一,负责多媒体内容的播放。它能够处理多种格式的音频和视频文件,并支持网络流媒体播放。 **PVAuthor**:PVAuthor则专注于媒体内容的录制,支持通过摄像头、麦克风等...
OpenCore由多个模块组成,包括PVMF(Platform Video Middleware Framework)、PVPlayer、PVRecorder、PVCodec Manager和PVStream Control等。这些模块各自承担不同的职责,共同构建了一个完整的多媒体处理框架。 1....
2. **PVPlayer**:PVPlayer是OpenCore中的播放器模块,它可以处理各种媒体格式,包括本地文件和网络流媒体。PVPlayer通过PVMF来实现媒体的解码和播放,提供了暂停、停止、快进、快退等功能,确保了良好的用户体验。 ...
2. **PVPlayer Engine**:PVPlayer是OpenCore中的关键组件,全称为PVMediaPlayerEngine,它是播放引擎,负责视频和音频的解码及渲染。PVPlayer Engine代码是实现多媒体播放的核心部分,包含了解码器、渲染器、时间...
4. 在MediaPlayerService中,根据请求创建一个BnMediaPlayer对象,该对象通常与OpenCORE的PVPlayer对象关联,PVPlayer是实际处理媒体数据的底层组件。 5. MediaPlayerService将创建的BnMediaPlayer对象添加到clients...
- **PVPlayer Engine**和**PVAuthor Engine**:分别是PVPlayer和PVAuthor的核心引擎,负责具体的播放和录制操作。 3. **OpenCore的代码结构** OpenCore的源代码分布在不同的目录下,如`external/opencore`: - *...
开发者可以利用OpenCore提供的接口实现自定义的多媒体处理功能,例如,通过OMX组件开发新的编码器或解码器,或者通过PVMF和PVPlayer来实现个性化的播放器。 在实际应用中,OpenCore不仅支持常见的多媒体格式,还...
- **PVPlayer的处理逻辑**: PVPlayer层初始化编解码器,准备接收数据。 - **Playerdriver的处理逻辑**: PlayerDriver层检查硬件资源是否可用。 - **引擎层的处理**: PVPLAYERENGINE层设置状态机,等待进一步的指令。...
PVPlayer提供了媒体播放器的功能,可以处理音频和视频流的回放。它可以从本地文件或网络流中获取数据,并将其解码后发送到音频和视频输出设备。PVPlayer支持RTSP流,允许实现实时流媒体播放。 另一方面,PVAuthor则...
2.6 OpenCore 的 PVPlayer 介绍 【文件格式处理和编解码部分简介】 3.1 文件格式的处理 3.2 编解码 3.3 3OpenMAX 的功能 【Android 多媒体开发技巧】 4.1 Android 多媒体开发相关技巧一 4.2 Android 多媒体开发相关...
OpenCore的代码结构包括多个模块,如PVMF(Platform Media Framework)、PVPlayer、PVAuthor等,分别对应不同的多媒体处理任务。PVMF是OpenCore的基础框架,PVPlayer用于播放,PVAuthor则用于内容创建。 2.1 Open...
eoeAndroid特刊第十五期:Android多媒体,Android 多媒体框架,OpenCore 的代码结构(Open Core 的核心概念/PVPlayer 介绍播放器介绍),文件格式处理和编解码部分简介(编码与解码/3OpenMAX 的功能)/Android 多媒体开发...