zoukankan      html  css  js  c++  java
  • Android的PVPlayer介绍

    1 Player的组成

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

      Android PVPlayer介绍(图一)

    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。

    Android PVPlayer介绍(图二)
               在 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来完毕详细的功能。整个实现的结构图如图所看到的:

    Android PVPlayer介绍(图三)
     对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的数据输出节点。

    Android PVPlayer介绍(图四)

           其实,对于Video的输出,基本的功能都是在类AndroidSurfaceOutput中完毕的,在这个类其中,基本的工作是将Android的 ISurface输出作为Player Engine的输出。最后调用了AddDataSink将mVideoSink添加为了PVPlayerInterface的输出。
          在android_surface_output.cpp文件里实现了类AndroidSurfaceOutput,这个类相当于一个OpenCore Player Engine的Video输出和Android输出的“适配器”。AndroidSurfaceOutput类本身继承了类 PvmiMIOControl,而其构造函数又以ISurface类型为參数。这个类的实现是使用ISurface实现PvmiMIOControl的各 个接口。

  • 相关阅读:
    452.用最少数量的箭引爆气球
    134.加油站
    Javascript
    spring-JDBC模板
    AOP注解方式ApsectJ开发
    AOP通知类型
    AOP的使用
    AOP相关术语
    AOP
    IOC注解详解
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4329887.html
Copyright © 2011-2022 走看看