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 plain copy print ?
- OMXClient mClient;
OMXClient mClient;
让我们看看 OMXClient
[cpp] view plain copy print ?
- class OMXClient {
- public:
- OMXClient();
-
- status_t connect();
- void disconnect();
-
- sp<IOMX> interface() {
- return mOMX;
- }
-
- private:
- sp<IOMX> mOMX;
-
- OMXClient(const OMXClient &);
- OMXClient &operator=(const OMXClient &);
- };
class OMXClient {
public:
OMXClient();
status_t connect();
void disconnect();
sp<IOMX> interface() {
return mOMX;
}
private:
sp<IOMX> mOMX;
OMXClient(const OMXClient &);
OMXClient &operator=(const OMXClient &);
};
OMXClient 有个IOMX 的变量 mOMX ,这个就是和OMX服务进行binder通讯的。
在 AwesomePlayer 的构造函数中会调用
[cpp] view plain copy print ?
- CHECK_EQ(mClient.connect(), (status_t)OK);
CHECK_EQ(mClient.connect(), (status_t)OK);
[cpp] view plain copy print ?
- status_t OMXClient::connect() {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.player"));
- sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
-
- CHECK(service.get() != NULL);
-
- mOMX = service->getOMX();
- CHECK(mOMX.get() != NULL);
-
- if (!mOMX->livesLocally(NULL , getpid())) {
- ALOGI("Using client-side OMX mux.");
- mOMX = new MuxOMX(mOMX);
- }
-
- return OK;
- }
status_t OMXClient::connect() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.player"));
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
CHECK(service.get() != NULL);
mOMX = service->getOMX();
CHECK(mOMX.get() != NULL);
if (!mOMX->livesLocally(NULL /* node */, getpid())) {
ALOGI("Using client-side OMX mux.");
mOMX = new MuxOMX(mOMX);
}
return OK;
}
[cpp] view plain copy print ?
- sp<IOMX> MediaPlayerService::getOMX() {
- Mutex::Autolock autoLock(mLock);
-
- if (mOMX.get() == NULL) {
- mOMX = new OMX;
- }
-
- return mOMX;
- }
sp<IOMX> MediaPlayerService::getOMX() {
Mutex::Autolock autoLock(mLock);
if (mOMX.get() == NULL) {
mOMX = new OMX;
}
return mOMX;
}
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 plain copy print ?
- sp<IOMX> interface() {
- return mOMX;
- }
sp<IOMX> interface() {
return mOMX;
}
[cpp] view plain copy print ?
- mAudioSource = OMXCodec::Create(
- mClient.interface(), mAudioTrack->getFormat(),
- false,
- mAudioTrack);
mAudioSource = OMXCodec::Create(
mClient.interface(), mAudioTrack->getFormat(),
false, // createEncoder
mAudioTrack);
[cpp] view plain copy print ?
- mVideoSource = OMXCodec::Create(
- mClient.interface(), mVideoTrack->getFormat(),
- false,
- mVideoTrack,
- NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
mVideoSource = OMXCodec::Create(
mClient.interface(), mVideoTrack->getFormat(),
false, // createEncoder
mVideoTrack,
NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
[cpp] view plain copy print ?
-