android中openMax的实现

来源:互联网 发布:宇宙大小的相关数据 编辑:程序博客网 时间:2024/04/19 20:50

1.android中用openmax来干啥?

有了上一篇AwesomePlayer基本框架及播放流程已经很清楚的看到了,android中的 AwesomePlayer就是用openmax来做(code)编解码,其实在openmax接口设计中,他不光能用来当编解码。通过他的组件可以组成一个完整的播放器,包括sourc、demux、decode、output。但是为什么android只用他来做code呢?我认为有以下几方面:


1.在整个播放器中,解码器不得不说是最重要的一部分,而且也是最耗资源的一块。如果全靠软解,直接通过cpu来运算,特别是高清视频。别的事你就可以啥都不干了。所以解码器是最需要硬件提供加速的部分。现在的高清解码芯片都是主芯片+DSP结构,解码的工作都是通过DSP来做,不会在过多的占用主芯片。所有将芯片中DSP硬件编解码的能力通过openmax标准接口呈现出来,提供上层播放器来用。我认为这块是openmax最重要的意义。

2.source 主要是和协议打交道,demux 分解容器部分,大多数的容器格式的分解是不需要通过硬件来支持。只是ts流这种格式最可能用到硬件的支持。因为ts格式比较特殊,单包的大小太小了,只有188字节。所以也是为什么现在常见的解码芯片都会提供硬件ts demux 的支持。

3.音视频输出部分video\audio output 这块和操作系统关系十分紧密。可以看看著名开源播放器vlc。vlc 在mac、linux、Windows都有,功能上差别也不大。所以说他是跨平台的,他跨平台跨在哪?主要的工作量还是在音视频解码完之后的输出模块。因为各个系统的图像渲染和音频输出实现方法不同,所以vlc需要针对每个平台实现不同的output。这部分内容放在openmax来显然不合适。

所以openmax 中硬件抽象的编解码是最为常用的,也是为什么android中只用它来抽象code。

2.android中openmax实现框架



1.上面已经说过了,android系统中只用openmax来做code,所以android向上抽象了一层OMXCodec,提供给上层播放器用。
播放器中音视频解码器mVideosource、mAudiosource都是OMXCodec的实例。

2.OMXCodec通过IOMX 依赖binder机制 获得 OMX服务,OMX服务 才是openmax 在android中 实现。

3. OMX把软编解码和硬件编解码统一看作插件的形式管理起来。
 
代码分析:

AwesomePlayer 中有个变量 

[cpp] view plaincopyprint?
  1. OMXClient mClient;  
让我们看看   OMXClient 
[cpp] view plaincopyprint?
  1. class OMXClient {  
  2. public:  
  3.     OMXClient();  
  4.   
  5.     status_t connect();  
  6.     void disconnect();  
  7.   
  8.     sp<IOMX> interface() {  
  9.         return mOMX;  
  10.     }  
  11.   
  12. private:  
  13.     sp<IOMX> mOMX;  
  14.   
  15.     OMXClient(const OMXClient &);  
  16.     OMXClient &operator=(const OMXClient &);  
  17. };  
OMXClient 有个IOMX 的变量 mOMX ,这个就是和OMX服务进行binder通讯的。
在 AwesomePlayer 的构造函数中会调用 
[cpp] view plaincopyprint?
  1. CHECK_EQ(mClient.connect(), (status_t)OK);  
[cpp] view plaincopyprint?
  1. status_t OMXClient::connect() {  
  2.     sp<IServiceManager> sm = defaultServiceManager();  
  3.     sp<IBinder> binder = sm->getService(String16("media.player"));  
  4.     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);  
  5.   
  6.     CHECK(service.get() != NULL);  
  7.   
  8.     mOMX = service->getOMX();  
  9.     CHECK(mOMX.get() != NULL);  
  10.   
  11.     if (!mOMX->livesLocally(NULL /* node */, getpid())) {  
  12.         ALOGI("Using client-side OMX mux.");  
  13.         mOMX = new MuxOMX(mOMX);  
  14.     }  
  15.   
  16.     return OK;  
  17. }  
[cpp] view plaincopyprint?
  1. sp<IOMX> MediaPlayerService::getOMX() {  
  2.     Mutex::Autolock autoLock(mLock);  
  3.   
  4.     if (mOMX.get() == NULL) {  
  5.         mOMX = new OMX;  
  6.     }  
  7.   
  8.     return mOMX;  
  9. }  

OMXClient::connect函数是通过binder机制 获得到MediaPlayerService,然后通过MediaPlayerService来创建OMX的实例。这样OMXClient就获得到了OMX的入口,接下来就可以通过binder机制来获得OMX提供的服务。
也就是说OMXClient 是android中 openmax 的入口。

在创建音视频解码mVideoSource、mAudioSource的时候会把OMXClient中的sp<IOMX> mOMX的实例 传给mVideoSource、mAudioSource来共享使用这个OMX的入口。
也就是说一个AwesomePlayer对应着 一个IOMX 变量,AwesomePlayer中的音视频解码器共用这个IOMX变量来获得OMX服务。
[cpp] view plaincopyprint?
  1. sp<IOMX> interface() {  
  2.       return mOMX;  
  3.   }  
[cpp] view plaincopyprint?
  1. mAudioSource = OMXCodec::Create(  
  2.                 mClient.interface(), mAudioTrack->getFormat(),  
  3.                 false// createEncoder  
  4.                 mAudioTrack);  
[cpp] view plaincopyprint?
  1. mVideoSource = OMXCodec::Create(  
  2.             mClient.interface(), mVideoTrack->getFormat(),  
  3.             false// createEncoder  
  4.             mVideoTrack,  
  5.             NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);  
[cpp] view plaincopyprint?
  1.   
原创粉丝点击