surface在android4.2跟4.4系统中本地service里使用上的差异
surface在android4.2跟4.4系统中本地service里使用上的差异
了解android的人都知道,android的应用是java写的,运行的效率应该比C/C++要低一些,这是不争的事实。为了提高运行效率,运算量大的任务大多都是采用本地service的形式存在,比如我们比较熟悉的audiofliger、surfacefliger,都是采用本地service的形式做的。笔者的研发项目中,使用到了视频输入,鉴于一些运算量运行效率考虑,也是采用本地service的形式来完成的,我们暂且认为这个本地service的名字就是“media.tvd”吧。
在“media.tvd”中肯定需要做一下surface相关的传递,以供视频数据能够跟这个surface的window挂上钩,再通过surfacefliger显示出来。笔者在4.2上使用的这个相关接口如下:
status_t setPreviewDisplay(constsp<Surface>& surface);
我们在creatSurface后会得到一个surface的对象,如果是app调用这个接口就是通过JNIcall下来的,JNI传递surface是没有问题。
/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/edsam49原创,转载请注明出处,谢谢!
/*****************************************************************************************************/
我们先来回顾一下android4.2surface里面有两个非常重要的接口,也就是下面这个两个;
static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);
static sp<Surface> readFromParcel(const Parcel& data);
所以在4.2系统里,如果要传surface,我们可以通过这两个接口就完成了client到server的传递。但是到4.4系统surface已经发生了很大变化,已经没有这两个接口了,那怎么完成client到server的传递呢?
笔者刚开始也很郁闷,4.2都用得好好的,移植到4.4编译都过不了,哎!有什么办法呢,工作总是要继续的,生活也是要继续的。在网上也找了一些资料看了,基本上没有找到什么有价值的东西,所以笔者还是从源码中来,到源码中去,静下心来看看4.4系统的相关源码。笔者首先想到了camera系统也是一个本地service,那它同样也存在同样的需求吧。Camera这一块的代码也不少啊!不熟悉的话,也是要折腾一下的。
上周晚上笔者自己在家看源码,晚上11点多了,把camera相关的看了后,得到了启发,信心立马上来了,解决问题有戏了。如果把“media.tvd”写成lib的形式,当然也是可以的,这样做得好会牺牲一些效率,关键是也要裁剪代码,调试,也不那么方便了,所以笔者还是先坚持用“media.tvd”本地service的形式继续推进。
在android4.4系统中,确实不能直接传surface了,但是新增了一个好东西,也就是IGraphicBufferProducer,按意思也就是图形buffer的生产者了。笔者把以前穿surface的地方都改成传IGraphicBufferProducer就行了。当然在client调用的使用要从surface转一下到IGraphicBufferProducer,surface里面有这样的接口,如下:
sp<IGraphicBufferProducer> gbp
gbp =mFlingerSurface->getIGraphicBufferProducer();
这样就把这个gbp传递下去就是了,那么到service实体部分,需要做一些变通,反正后面的目的就是得到一个ANativeWindow的对象,代码如下:
+status_t TVDecoderService::setPreviewDisplay(const sp<IGraphicBufferProducer>& bufferProducer) { int ret = OK; // sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0); - sp<ANativeWindow> window(surface); + ALOGD("setPreviewTarget(%p) (pid %d)", bufferProducer.get(), + getCallingPid()); + + sp<IBinder> binder; + sp<ANativeWindow> window; + if (bufferProducer != 0) { + binder = bufferProducer->asBinder(); + // Using controlledByApp flag to ensure that the buffer queue remains in + // async mode for the old camera API, where many applications depend + // on that behavior. + window = new Surface(bufferProducer, /*controlledByApp*/ true); + } + +// sp<ANativeWindow> window(surface); mPreviewWindow = window;
中间的一些部分传递都是比较简单的,笔者就不介绍了,重要的就是找到这么一条通路。每次android系统版本的升级,都会带来很多已经完成的工作重新研究实现的问题,这也是做android比较累的地方,当然想要android的好,得包容android的累!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。