1 Player的组成

  OpenCore的Player的编译文件是pvplayer/Android.mk,将生成动态库文件
libopencoreplayer.so。这个库包括了双方面的内容:一方是Player的engine(引擎),一方面是为
Android构件的Player,这实际上是一个适配器(adapter)。engine的路径是engine/player;adapter的路径是
android。

  

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状态。

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<ISurface>& 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的各
个接口。

Android的PVPlayer介绍的更多相关文章

  1. Android sdk目录介绍

    android sdk目录介绍 build-tools 各版本SDK编译工具 docs 离线开发者文档Android SDK API参考文档 extras 扩展开发包,如兼容架包. platforms ...

  2. 我的Android第三章:Android的组件介绍

    小编摘录了Android文档介绍Android四大组件的基本内容,感觉文档的内容写的很详细所以小编将它写入了博客 Android 使用Java语言开发.Android SDK 工具编译代码-以及任意数 ...

  3. GitHub上排名前100的Android开源库介绍(来自github)

    本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍,至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果,然后过滤了 ...

  4. android MVP模式介绍与实战

    android MVP模式介绍与实战 描述 MVP模式是什么?MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数 ...

  5. Android 不同文件名介绍

    Android 不同文件名介绍

  6. Android发展简单介绍

    Android一词的本义指“机器人”,同一时候也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统.中间件.用户界面和应用软件组成,号称是首个为移动 ...

  7. Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...

  8. Android Jetpack 组建介绍(一)——Lifecycler

    转自带你领略Android Jetpack组件的魅力 Android Jetpack 对于任何一个产品来说,我们开发中都会面对哪些问题?如:产品交互.用户体验.代码结构.数据获取.数据存储.网络优化. ...

  9. [原创]AndroBugs_Framework Android漏洞扫描器介绍

    [原创]AndroBugs_Framework Android漏洞扫描器介绍 1 AndroBugs_Framework Android 漏洞扫描器简介 一款高效的Android漏洞扫描器,可以帮助开 ...

随机推荐

  1. html练习(3)

    1.这个小练习用到了css的四种选择器id选择器,类选择器,html选择器,通配符选择器. (1)假设一个元素中用到了各种选择器,而且选择器中的属性发生了冲突,则 优先级为id选择器>类选择器& ...

  2. 【SPOJ 694】Distinct Substrings

    [链接]h在这里写链接 [题意]     给你一个长度最多为1000的字符串     让你求出一个数x,这个x=这个字符串的不同子串个数; [题解]     后缀数组题.     把原串复制一份,加在 ...

  3. [Nuxt] Add CSS Libraries to Nuxt

    You can easily add CSS libraries to Nuxt using yarn or npm to install them, then simply adding them ...

  4. 为什么一款优秀的移动工具类应用必须开发PCclient?

    移动大潮气势汹汹,PC端似乎已经一条腿跨进了坟墓. 作为一个windows开发者.难免有些焦灼. windows真的已死吗?真的无用武之地了吗? 或许是人云亦云吧. 突然看到了这篇文章,感触颇深. 文 ...

  5. C语言主要做哪些方面的开发---一个来自“IT技术学习”微信群的问题及答复

    近期,在"IT技术学习"微信群中,有同学问了这样一个问题:C语言主要做哪些方面的开发?在这篇文章中,我想结合自身的经验,对这个问题进行下解答. C语言是计算机及其相关专业(如通信. ...

  6. 结合Wireshark捕获分组深入理解TCP/IP协议栈之TCP协议(TCP报文格式+三次握手实例)

    摘要:     本文简单介绍了TCP面向连接理论知识,详细讲述了TCP报文各个字段含义,并从Wireshark俘获分组中选取TCP连接建立相关报文段进行分析. 一.概述     TCP是面向连接的可靠 ...

  7. 关于stm32的输入输出

    https://blog.csdn.net/u011556018/article/details/72629082

  8. 【Codeforces Round #185 (Div. 2) D】Cats Transport

    [链接] 链接 [题意] 有n座山,m只猫. 每只猫都在其中的一些山上玩. 第i只猫在h[i]山上玩,且会在t[i]时刻出现在山脚下(然后就一直在那里等) 然后有p个人. 它们听从你的安排. 在某个时 ...

  9. [Angular2 Form] Reactive form: valueChanges, update data model only when form is valid

    For each formBuild, formControl, formGroup they all have 'valueChanges' prop, which is an Observable ...

  10. [Docker] Build a Simple Node.js Web Server with Docker

    Learn how to build a simple Node.js web server with Docker. In this lesson, we'll create a Dockerfil ...