Android camera2 抓拍连拍太慢

Posted

技术标签:

【中文标题】Android camera2 抓拍连拍太慢【英文标题】:Android camera2 capture burst is too slow 【发布时间】:2015-05-29 16:22:30 【问题描述】:

我正在尝试修改 android-Camera2Basic 代码以捕获一连串图片。但是,在运行 L 5.0.1 的 Nexus 5 上,我无法让图片之间的延迟超过 200-300 毫秒。

我尝试了很多东西,但这是最基本的。这是我修改的 Camera2Basic 代码的唯一部分。我的预览 TextureView 只有 50x50dp,但这应该没关系吧?

不管怎样,这段代码在我的 Nexus 6 和 L 5.1 上只有大约 50-100 毫秒的延迟。

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 能否附上代码你是如何实现突发模式的? 【参考方案1】:

您遇到的问题是您请求的图像输出格式的产物。 JPEG 编码过程在相机管道上放置了很长的停顿时间,因此在一次曝光结束和下一次曝光开始之间,在此编码发生时有很多停机时间。

引用的 30fps 速率可以通过将 ImageReader 上的输出图像格式设置为 YUV 来实现,因为这对于相机来说是更“原生”的输出。这将是在捕获图像时存储图像的方式,然后您必须在之后进行 JPEG 编码,与相机的内联处理分开。

例如,在 Nexus 5 上,JPEG 编码的输出停滞时间为 243 毫秒,您一直在观察。对于YUV_420_888 输出,为 0ms。同样,由于它们的大小,RAW_SENSOR 编码引入了 200 毫秒的停顿时间。

另请注意,即使您通过选择“更快”格式来消除停顿时间障碍,仍然存在最小帧时间,具体取决于输出图像大小。但是对于 Nexus 5 的全分辨率输出,这是 33 毫秒,这是您所期望的。

相关信息在相机元数据的StreamConfigurationMap对象here中。查看getOutputStallDuration(int format, Size size)getOutputMinFrameDuration(int format, Size size) 方法进行确认。

【讨论】:

YUV_420_888 确实做到了。感谢您的帮助! 实际上,JPEG 格式在某些设备上可能比 YUV(或 RAW)更快。这取决于 JPEG 编码器的固件实现,例如DM3730 支持 jpeg 格式流。 Snapdragon 810 可以以 15 FPS proof 产生 16 兆像素 JPEG 连拍照片:没有足够的带宽用于 RAW 或 YUV。【参考方案2】:

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

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。这是我们代码的主要区别(我刚刚在您回答的后半部分注意到)。所以,我的错。不过,我感谢您的帮助。 工作!在 Galaxy s3 上减少 100 毫秒 - cyanogenmod 12.1(棒棒糖)

以上是关于Android camera2 抓拍连拍太慢的主要内容,如果未能解决你的问题,请参考以下文章

camera2 api 连拍

AndroidCameraHAL3-MultiCamera-CameraX

AndroidCameraHAL3-MultiCamera-CameraX

使用新的 Android camera2 api 从 YUV_420_888 进行 JPEG 编码时的绿色图像

指定间隔定时拍照抓拍摄像头(机)FTP上传照片|内存卡存储 [WiFi/4G传输][太阳能电池供电方案]

无法导入导入 android.hardware.camera2 类