安卓相机2连拍速度太慢

14

我正在尝试修改android-Camera2Basic代码以捕获一系列图片。然而,在运行L 5.0.1的Nexus 5上,我无法让图片之间的延迟快于200-300ms。

我已经尝试了很多方法,但这是最基本的。这是我修改的Camera2Basic代码的唯一部分。我的预览TextureView只有50x50dp,但那应该没关系,对吗?

值得一提的是,在我的Nexus 6上,运行L 5.1,这个代码只有大约50-100ms的延迟。

private void captureStillPicture() {
    try {
        List<CaptureRequest> captureList = new ArrayList<CaptureRequest>();
        mPreviewRequestBuilder.addTarget(mImageReader.getSurface());

        for (int i=0;i<10;i++) {
            captureList.add(mPreviewRequestBuilder.build());
        }

        mCaptureSession.stopRepeating();
        mCaptureSession.captureBurst(captureList, cameraCaptureCallback, null);
        mPreviewRequestBuilder.removeTarget(mImageReader.getSurface());
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

CameraCaptureSession.CaptureCallback cameraCaptureCallback = new CameraCaptureSession.CaptureCallback() {
    @Override
    public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
            TotalCaptureResult result) {
        Log.d("camera","saved");
        mPictureCounter++;
        if (mPictureCounter >= 10)
            unlockFocus();
    }
};

acheroncaptain 你能否提供一段代码来说明你是如何实现爆发模式的? - user0770
2个回答

21
您遇到的问题是与您请求的图像输出格式有关。JPEG编码过程会在相机管道上产生大量停顿时间,因此在进行编码时,一个曝光结束和下一个开始之间会有很多空闲时间。
声称可以达到30fps的速率是通过将ImageReader上的输出图像格式设置为YUV来实现的,因为这是相机更加“原生”的输出格式。这是以捕获图像的方式存储图像的方式,并且您需要在相机的内联处理之外单独进行JPEG编码。
例如,在Nexus 5上,JPEG编码的输出停顿时间为243毫秒,这是您观察到的。对于YUV_420_888输出,它为0毫秒。同样,由于其较大的大小,RAW_SENSOR编码引入了200毫秒的停顿时间。
还要注意,即使您选择了“更快”的格式删除了停顿时间障碍,仍然存在最小帧时间,取决于输出图像大小。但是对于Nexus 5的全分辨率输出,这是33毫秒,这是您预期的。
相关信息在相机元数据的 StreamConfigurationMap 对象中,这里。查看 getOutputStallDuration(int format, Size size)getOutputMinFrameDuration(int format, Size size) 方法以确认。

1
YUV_420_888绝对做到了。感谢您的帮助! - acheroncaptain
实际上,在某些设备上,JPEG格式可能比YUV(或RAW)更快。这取决于JPEG编码器的固件实现,例如DM3730支持jpeg格式流。Snapdragon 810可以以15 FPS的速度生成16兆像素的JPEG连拍照片证明:没有足够的带宽来处理RAW或YUV。 - Alex Cohn

7

尝试设置以下捕获请求参数

requestBuilder = camDevice
        .createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

requestBuilder.set(CaptureRequest.EDGE_MODE,
        CaptureRequest.EDGE_MODE_OFF);
requestBuilder.set(
        CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,
        CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);
requestBuilder.set(
        CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
        CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
requestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE,
        CaptureRequest.NOISE_REDUCTION_MODE_OFF);
requestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
        CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);

requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);

我不确定信息进入CameraCaptureSession.CaptureCallback的速度有多快。它没有图像数据,并且可能在ImageReader.OnImageAvailableListener之前或之后调用。 尝试测量ImageReader.OnImageAvailableListener调用之间的时间。 并且不要忘记读取图像并释放它们,因为如果缓冲区已满且图像未释放,则新图像将不可用。例如:

private class imageAvailableListener implements
            ImageReader.OnImageAvailableListener {
        @Override
        public void onImageAvailable(ImageReader ir) {
            Log.i(TAG, "Time = " + System.currentTimeMillis());
            Image im = ir.acquireNextImage();
            im.close();
        }
    }

ImageReader mImageReader = ImageReader.newInstance(imageReaderWidth,
                    imageReaderHeight, ImageFormat.YUV_420_888, 2);
mImageReader.setOnImageAvailableListener(
                    new imageAvailableListener(), null);

我应该提到我使用的是JPEG而不是YUV。这是我们代码中的主要区别(我刚刚在你回答的后半部分注意到)。所以,我的错。不过还是非常感谢你的帮助。 - acheroncaptain
工作正常!在Galaxy S3上减少了100毫秒 - CyanogenMod 12.1(棒棒糖) - Lucas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接