在Camera2中切换手电筒而不中断预览

时间:2015-12-04 16:56:11

标签: android delay preview flashlight camera2

刚开始使用Camera2框架,因为它提供了相机的低级功能的增强控制。但是,我在快速打开和关闭手电筒时遇到了一些麻烦。使用旧的Camera API,我可以在提供预览时切换闪光:

try
{
    android.hardware.Camera.Parameters parameters = c.getParameters();
    if (parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF))
    {
        parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
        Log.i("HeartBeatAlgorithm", "LightOn");
    }
    else if (parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH))
    {
        parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
        Log.i("HeartBeatAlgorithm", "LightOff");
    }
    c.setParameters(parameters);
}
catch (Exception exception)
{
    c.release();
    c = null;
}

手电筒会快速打开或关闭,没有任何明显的中断。然而,使用Camera2,似乎闪存模式是CaptureSession的一个属性,这意味着需要创建一个全新的CaptureSession来改变闪存模式,即:

try
{
    SurfaceTexture texture = mTextureView.getSurfaceTexture();
    assert texture != null;

    texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
    Surface surface = new Surface(texture);
    mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

    if (mLightNowOn == true)
    {
        mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
    }
    else
    {
        mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
    }

    mPreviewRequestBuilder.addTarget(surface);
    mPreviewRequest = mPreviewRequestBuilder.build();
    mCameraDevice.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, null);
}
catch (CameraAccessException e)
{
    e.printStackTrace();
}

如开发人员文档中所述,"创建会话是一项昂贵的操作,可能需要几百毫秒,因为它需要配置摄像头设备的内部管道并分配内存缓冲区以便将图像发送到期望的目标。"肯定会这样,当我的应用程序切换闪光模式时会有明显的延迟。

我真的需要能够在不中断预览的情况下快速切换闪光模式。有什么方法可以解决这个问题,还是由于新的API管道而无法避免?

2 个答案:

答案 0 :(得分:0)

每次只更改闪光模式时,必须创建全新的捕获会话,这是不正确的。相反,您可以在现有捕获会话上创建重复预览请求,并且每次都只需要setNewRepeating请求:

mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,CaptureRequest.FLASH_MODE_TORCH); ... mPreviewRequest = mPreviewRequestBuilder.build(); ... mCaptureSession.setRepeatingRequest(mPreviewRequest,captureCallBack,backgroundHandler);

您可以多次重复此序列。

答案 1 :(得分:0)

看起来有点hacky但Ivan的输入对我有用......

如果不明显,变量名称应该看起来像类/接口名称。您必须在外部范围内声明它们。

captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);

captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
captureRequest = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(captureRequest, null, backgroundHandler);

torchButton = findViewById(R.id.button);
torchButton.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        if(!lightOn) {
            try {
                captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
                captureRequest = captureRequestBuilder.build();
                cameraCaptureSession.setRepeatingRequest(captureRequest, null, backgroundHandler);
                lightOn = true;
            } catch (CameraAccessException e) {}
        }
        else if(lightOn) {
            try {
                captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
                captureRequest = captureRequestBuilder.build();
                cameraCaptureSession.setRepeatingRequest(captureRequest, null, backgroundHandler);
                lightOn = false;
            } catch (CameraAccessException e) {}
        }
    }
});

这样,您可以在关闭手电筒的情况下开始预览,但可以通过点击按钮来控制。