Camera2处理预览回调数据时出现native错误的解决方法

前言:在使用camera api 2 时,若是增加了回调数据的监听器,那么需要在OnImageAvailableListener回调函数中从ImageReader获取图像,并转化成我们需要的格式(比如使用自己写的yv12转nv21格式的图像格式转化函数),比如NV21格式。在退出预览界面时,有时候会在图像转化格式函数中出现native错误。原因是相机在释放时,图像转化函数没有执行完成,所以才有native错误。解决方法也不难,就是在图像转化时,不能去释放相机。等图像转化完成后再释放相机。

大致代码实现如下:

一、定义两个变量,用于表明相机状态和图像处理状态,如下:

// 是否调用了释放相机函数
private boolean isReleasingCamera = false;
// 是否已经处理完了预览回调数据,处理完后,才去真正释放相机。
private boolean isProcessImageFinished = true;

二、在OnImageAvailableListener回调中去控制isProcessImageFinished变量的状态。如下:

private ImageReader.OnImageAvailableListener mOnImageAvailableListener
            = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
            isProcessImageFinished = false;

            if (isReleasingCamera) {
                try {
                    Image image1 = reader.acquireLatestImage();
                    image1.close();

                    // 去掉监听
                    if (mImageReader != null && isReleasingCamera) {
                        mImageReader.setOnImageAvailableListener(null, null);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                isProcessImageFinished = true;
                return;
            }

            byte[] imageData = null;
            Image image = null;
            try {
                image = reader.acquireLatestImage();
            } catch (Exception e) {
                e.printStackTrace();
            }
            
			if (image == null) {
				isProcessImageFinished = true;
				return;
			}
			
			try {
				// TODO 将yv12转nv21格式等
				// imageData = nv21格式的数据
			} catch (Exception e) {
				Log.e(TAG, "onImageAvailable e=" + e.getMessage());
			}
			if (image != null) {
				image.close();
			}
            
            if (imageData == null) {
                isProcessImageFinished = true;
                return;
            }
            // TODO 可在子线程中处理转化后的数据:imageData
            isProcessImageFinished = true;
        }
    };

三、 释放相机时,控制isReleasingCamera变量的值,在回调数据处理完后再去释放相机资源,如下:

    // TODO 最好在Activity中的onPause()方法中使用子线程执行
    public void releaseCamera() {
        if (isReleasingCamera) {
            Log.w(TAG, "releaseCamera function has called");
            return;
        }
        // 表示准备释放相机
        isReleasingCamera = true;
        // 等待调用释放函数的开始时间
        long waitReleaseTime = System.currentTimeMillis();

        // 等待回调数据处理结束
        while (!isProcessImageFinished && System.currentTimeMillis() - waitReleaseTime < 50) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //stopPreview();
        //closeCamera();
        // 释放完毕
        isReleasingCamera = false;
    }

你可能感兴趣的:(Java,Android,camera,图像处理,android,java)