问题 Android相机2 api BufferQueue已被放弃


我正在测试新的Android camera2 API和我想从相机控制每一帧。我为此做的是创造一个 的ImageReader 并设置分辨率和图像格式。

ImageReader imageReader = ImageReader.newInstance(1280,720,ImageFormat.YUV_420_888,1);
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = reader.acquireLatestImage();
        Log.i(MainActivity.LOG_TAG,"imageReader: "+System.currentTimeMillis());
        image.close();
    }
},null);

之后我创造新的 CaptureRequest 带参数 TEMPLATE_PREVIEW 并为他添加目标 imageReader。对于 cameraCaptureSession 我创造了新的 setRepeatingRequest 有这个要求

 try {
    final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

    builder.addTarget(imageReader.getSurface());

    mCameraDevice.createCaptureSession(
            Arrays.asList(imageReader.getSurface()),
            new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(CameraCaptureSession session) {
                    mSession = session;
                    try {
                        mSession.setRepeatingRequest(builder.build(),null,null);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }
                @Override
                public void onConfigureFailed(CameraCaptureSession session) {

                }
            },
            null
    );
} catch (CameraAccessException e) {
    e.printStackTrace();
}

当我打开相机并开始查看我的预览时,我得到例外。但在异常之前我得到了一些预览图像,之后我有异常

10-30 16:00:32.850    1390-1894/.camera2tutorial E/BufferQueueProducer﹕ [unnamed-1390-1] dequeueBuffer: BufferQueue has been abandoned
10-30 16:00:32.850    1390-1894/.camera2tutorial E/Legacy-CameraDevice-JNI﹕ LegacyCameraDevice_nativeProduceFrame: Error while producing frame No such device (-19).
10-30 16:00:32.850    1390-1894/.camera2tutorial W/SurfaceTextureRenderer﹕ Surface abandoned, dropping frame.
    android.hardware.camera2.legacy.LegacyExceptionUtils$BufferQueueAbandonedException
            at android.hardware.camera2.legacy.LegacyExceptionUtils.throwOnError(LegacyExceptionUtils.java:64)
            at android.hardware.camera2.legacy.LegacyCameraDevice.produceFrame(LegacyCameraDevice.java:516)
            at android.hardware.camera2.legacy.SurfaceTextureRenderer.drawIntoSurfaces(SurfaceTextureRenderer.java:699)
            at android.hardware.camera2.legacy.GLThreadManager$1.handleMessage(GLThreadManager.java:103)
            at android.os.Handler.dispatchMessage(Handler.java:98)
            at android.os.Looper.loop(Looper.java:145)
            at android.os.HandlerThread.run(HandlerThread.java:61)

我怎样才能解决这个问题??

我使用的是三星Galaxy S5和Android API 21


11549
2017-10-30 14:08


起源



答案:


确保您持有对您创建的ImageReader的引用,可能是您定义mSession的位置。

从ImageReader获得的Surface大致相当于一个弱指针 - 它不会阻止ImageReader收集垃圾。因此很可能(基于您的命名)ImageReader被破坏,然后发生放弃错误。


10
2017-11-02 00:19



我从方法中删除了局部变量,并解决了异常问题。谢谢! - mr.leo
@ mr.leo考虑将此答案标记为已接受的答案。这个解决方案也有助于我的情况。有趣的是它是特定于平台的 - 它在Nexues和其他运行Android 6的设备上运行良好,但在运行Android 5的HTC One上失败了。安卓碎片的美妙之处。 - stoiczek
@stoiczek你是如何具体保留对ImageReader的引用的? (除了:“captureRequest.addTarget(imageReader.getSurface())”) - Denis
@Denis在您设置捕获请求的类中,只需为图像读取器创建一个类成员并在那里存储引用。 - stoiczek
@Eddy Talvala,非常感谢你。 - Diego Catalano


答案:


确保您持有对您创建的ImageReader的引用,可能是您定义mSession的位置。

从ImageReader获得的Surface大致相当于一个弱指针 - 它不会阻止ImageReader收集垃圾。因此很可能(基于您的命名)ImageReader被破坏,然后发生放弃错误。


10
2017-11-02 00:19



我从方法中删除了局部变量,并解决了异常问题。谢谢! - mr.leo
@ mr.leo考虑将此答案标记为已接受的答案。这个解决方案也有助于我的情况。有趣的是它是特定于平台的 - 它在Nexues和其他运行Android 6的设备上运行良好,但在运行Android 5的HTC One上失败了。安卓碎片的美妙之处。 - stoiczek
@stoiczek你是如何具体保留对ImageReader的引用的? (除了:“captureRequest.addTarget(imageReader.getSurface())”) - Denis
@Denis在您设置捕获请求的类中,只需为图像读取器创建一个类成员并在那里存储引用。 - stoiczek
@Eddy Talvala,非常感谢你。 - Diego Catalano


在我的应用程序中的活动之间切换时,我遇到了同样的问题 onSurfaceTextureDestroyed() 这只是返回虚假,但我做的是我改变它

public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            Log.e(TAG, "onSurfaceTextureDestroyed");
            if(cameraDevice != null){
                closeCamera();

                cameraDevice = null;
            }
            return false;
        }

这对我有用。


2
2018-01-28 06:55



谢谢。这对我有用。干杯.. - Dehan Wjiesekara
我发回真实和它的工作。 - Pandiri Deepak