Overlay Creation Failed —— 莫名的错误,到底孰是孰非?

来源:互联网 发布:jquery权威指南源码 编辑:程序博客网 时间:2024/05/16 12:59

转载请注明出处~

原文链接:http://blog.csdn.net/zgyulongfei/article/details/7680956

在做Android视频直播系统中,遇到了这么一个错误,感到莫名其妙,让我心灰意冷。

事情是这样的,之前已经做好了H.264视频采集部分,用的硬编码,由于将所有代码都写在了一个文件里面,很凌乱,不好维护,所以决定将其重构之,把编码部分单独抽取出来,做成一个编码器,这样如果以后要用到h.264的编码则可以将编码器移植过去。接着,就有了这个让我百感交集的错误,不过还好最后让我解决了,虽然不知道问题的原因是什么,希望知道原因的朋友能够赐教 ^_^

遇到的错误代码如下:

Overlay create failed - retrying

Overlay create failed - retrying

Overlay create failed - retrying

这样的错误日志有若干条,接着最后的日志是 Overlay Creation Failed...

然后视频就无法编码,自然也就没有预览的图像显示


遇到了错误,果断谷歌百度之,可是找了许久都不见得有什么解决方案,这样的错误足足让我卡了2天,搞得我的心拔凉拔凉的……

刚开始,我设计的编码器只需要传递一个SurfaceView对象,然后用此对象来预览录制的视频,代码如下:

public class H264Encoder implements SurfaceHolder.Callback{  SurfaceHolder holder;  public H264Encoder(SurfaceView view){   holder = view.getHolder();   hodler.addCallback(this);   holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); }  public initMediaRecorder(){   ...   mediaRecorder.setPreviewDisplay(holder.getSurface());    ...   mediaRecorder.prepare();//此处出现异常   ... }}

其中的view是传递进去用来显示的预览视频的SurfaceView view = (SurfaceView)this.findViewById(R.id.view)

我认认真真地将代码检查了好几遍,愣是不知道哪里出错了。

在网上查找到报此处异常的c代码如下:

if (mOverlayRef.get() == NULL) {// FIXME:// Surfaceflinger may hold onto the previous overlay reference for some// time after we try to destroy it. retry a few times. In the future, we// should make the destroy call block, or possibly specify that we can// wait in the createOverlay call if the previous overlay is in the // process of being destroyed.for (int retry = 0; retry < 50; ++retry) {mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_YCbCr_420_SP);if (mOverlayRef != NULL) break;LOGD("Overlay create failed - retrying");usleep(20000);}if ( mOverlayRef.get() == NULL ){LOGE("Overlay Creation Failed!");return -EINVAL;}ret = mHardware->setOverlay(new Overlay(mOverlayRef));}

上面的FIXME部分解释了,为什么会打印如此多的Overlay create failed - retrying。这段注释的大致意思是说,你准备destroy的overlay还处于被引用的状态,导致无法创建新的overlay。。尼玛,问题就在这里,我神马时候要destroy某个overlay啊。我明明只是对SurfaceView view进行了引用啊,这样难道不行么?

于是我对代码进行了这样的修改,即不把SurfaceView当参数传递进来,而是将holder传递进来。

代码如下:

public class H264Encoder {  SurfaceHolder holder;  public H264Encoder(SurfaceHolder holder){   this.hoder = holder; }  public initMediaRecorder(){   ...   mediaRecorder.setPreviewDisplay(holder.getSurface());    ...   mediaRecorder.prepare();//传递hodler进来,就无异常   ... }}

传递的holder参数是这样定义的:

SurfaceView view = (SurfaceView)this.findViewById(R.id.view)SurfaceHolder holder = view.getHolder();hodler.addCallback(this);holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

看到没有,我只是将holder在外面定义好,然后传到编码器内就没有错误;可是将view当参数传递进去,然后再定义holder,这样的方式就会报错。

将view传递进去传递的是view对象的引用,我在编码里面的view.getHolder()与在编码器外部定义的view.getHolder()有神马不同么?

为什么同样的事情会有不同的效果,真是郁闷死我了!!!


原创粉丝点击