项目中有个需求,不显示预览的情况下获取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();
}
}