BufferQueue has been abandoned解决方案

项目中有个需求,不显示预览的情况下获取Camera的图像数据,找了一下资料发现SurfaceTexture这个类可以实现该功能。于是用SurfaceTexture实现了一下,核心代码片段如下:

private void setupVisCamera() {
        try {
            SurfaceTexture surfaceTexture = new SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);//注意此行,会产生问题
            final int bufferSize = cameraConfig.getVisOriginalWidth() * cameraConfig.getVisOriginalHeight() * 3 / 2;
            vis_camera = Camera.open(cameraConfig.DEF_VIS_CAMERA_ID);
            vis_camera.setPreviewTexture(surfaceTexture);
            vis_camera.addCallbackBuffer(new byte[bufferSize]);
            vis_camera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    if (null == data) {
                        Log.d("Camera", "可见光预览为空值!!!!!!!!");
                        vis_camera.addCallbackBuffer(new byte[bufferSize]);
                    } else {
                        vis_camera.addCallbackBuffer(data);
                        cameraConfig.visYuvData = data;//图像数据赋值到cameraConfig中
                        Log.d("Camera", "可见光预览中______");
                    }
                }
            });
            vis_camera.startPreview();//开始预览
        } catch (IOException e) {
            e.printStackTrace();
        }
 }

在运行后只获取了一帧数据,然后就产生了以下错误,导致不能在onPreviewFrame中继续获取图像数据:

 E/BufferQueueProducer: [unnamed-17383-0] queueBuffer: BufferQueue has been abandoned
 E/BufferQueueProducer: [unnamed-17383-0] dequeueBuffer: BufferQueue has been abandoned

为了解决这个问题,找了好多资料未果,后来在stackoverflow上找到了一篇提问"SurfaceTexture has been abandoned",和我的情况类似,在Danny的回答中写到

The short answer: Keep a reference to your SurfaceTexture so that the object doesn’t get garbage collected (and thereby abandoned).
简单回答一下:保持持有一个SurfaceTexture的引用,如此一来该对象就不会被当做垃圾回收(从而被弃用)


I made a simple change to make the SurfaceTexture a member object of my class, and now the “SurfaceTexture has been abandoned” error is gone - and my preview continues to deliver frames via onPreviewFrame().
我做了一个小改动,把SurfaceTexture 作为类中的成员变量,然后就不再报错了,并且通过onPreviewFrame()方法可以继续获取预览帧了

再回看我写的代码,在方法体内new了一个surfaceTexture ,该对象的生命周期在try中,当try结束后,该对象不被持有,随后就会被标记为垃圾回收掉,而vis_camera.setPreviewTexture(surfaceTexture);只是一个传址引用,并不是真正意义上的持有这个surfaceTexture。因此,按照上述回答,我也把我的surfaceTexture 提升为了成员变量,这样一来就不再出现BufferQueue has been abandoned的问题了。改正后的代码如下:

private SurfaceTexture surfaceTexture = new SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);//提升为成员变量
private void setupVisCamera() {
        try {
            final int bufferSize = cameraConfig.getVisOriginalWidth() * cameraConfig.getVisOriginalHeight() * 3 / 2;
            vis_camera = Camera.open(cameraConfig.DEF_VIS_CAMERA_ID);
            vis_camera.setPreviewTexture(surfaceTexture);
            vis_camera.addCallbackBuffer(new byte[bufferSize]);
            vis_camera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    if (null == data) {
                        Log.d("Camera", "可见光预览为空值!!!!!!!!");
                        vis_camera.addCallbackBuffer(new byte[bufferSize]);
                    } else {
                        vis_camera.addCallbackBuffer(data);
                        cameraConfig.visYuvData = data;//图像数据赋值到cameraConfig中
                        Log.d("Camera", "可见光预览中______");
                    }
                }
            });
            vis_camera.startPreview();//开始预览
        } catch (IOException e) {
            e.printStackTrace();
        }
}

你可能感兴趣的:(BUG解决方案)