【问题标题】:Getting android camera2 preview frames without lagging the screen preview获取android camera2预览帧而不滞后屏幕预览
【发布时间】:2017-01-19 12:53:29
【问题描述】:

在原始(现已弃用)相机 API 中,我们过去能够在 Camera.PreviewCallback 中获取预览帧并能够处理它(可能需要很长时间)并释放缓冲区以便能够接收另一个帧, 不滞后屏幕预览,代码如下:

public void onPreviewFrame(final byte[] data, Camera camera) {
    new AsyncTask<Void, Void, Void>() {

        @Override
        protected Void doInBackground(Void... params) {
            (... do some slow processing ...)
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            mCamera.addCallbackBuffer(data); // free the buffer to be able
                                               // to process another frame
        }
    }.execute();
}

如果有另一个缓冲区可用于接收新帧,API 只会回调一个新帧,而不会延迟屏幕预览。

我正在尝试在新的 Camera2 API 上复制相同的行为,但我找不到不延迟屏幕预览的方法。如果我在预览请求中添加第二个目标(与屏幕分辨率相同,YUV_420_888):

mPreviewRequestBuilder.addTarget(surface);
mPreviewRequestBuilder.addTarget(previewImageReader.getSurface());
mCameraDevice.createCaptureSession(
    Arrays.asList(surface, previewImageReader.getSurface()), ...

屏幕预览会滞后,即使我一得到图像就关闭它:

@Override
public void onImageAvailable(ImageReader reader) {
    reader.acquireNextImage().close();
}

使用 Camera2 模拟原始相机 API 行为的正确方法是什么(即,只要有一个空闲的缓冲区并且不减慢屏幕预览速度,就拥有一个新缓冲区)?

更新:如果有人想知道其余代码的外观,它只是标准 android-camera2Basic 示例 here's what I've changed 的修改版本。

【问题讨论】:

  • 立即关闭图像应该很快。您对 previewImageReader 使用什么分辨率和格式?您正在测试什么硬件级别的设备?
  • 显然至少是正常预览速度的一半(即,仅作为目标配置的屏幕表面)。以下是详细信息:分辨率 960x720、YUV_420_888 格式、LEGACY 级别设备(Moto G 第二代)。
  • @EddyTalvala 我还刚刚添加了我对问题中标准 android-camera2Basic 示例所做的更改,以便人们可以自己尝试/看看问题出在哪里。
  • 您找到解决方法了吗?
  • @nhoxbypass nope :( 最终在另一个项目中工作

标签: android android-camera android-camera2


【解决方案1】:

如果还有人感兴趣的话。

创建一个SurfaceTextureListener 并从onSurfaceTextureUpdated 方法调用您的异步函数。在使用 BarcodeDetection API 和 Camera 2 API 检查条码帧时,我已成功使用此功能。

【讨论】:

  • 您能否发布一个异步函数的示例。我需要对人脸检测做类似的事情。
【解决方案2】:

这是从onSurfaceTextureUpdated 方法启动的异步函数的示例。如果您一次只想在后台运行一个异步任务,您可以使用一个标志来检查上一个任务是否已完成。

private final TextureView.SurfaceTextureListener mSurfaceTextureListener
    = new TextureView.SurfaceTextureListener() {

    boolean processing;

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
        openCamera(width, height);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
        configureTransform(width, height);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture texture) {
        if (processing) {
            return;
        }

        processing = true;

        Bitmap photo = mTextureView.getBitmap();

        new ImageTask(photo, new ImageResponse() {
                @Override
                public void processFinished() {
                    processing = false;
                }
            }).execute();
    }
};

private interface ImageResponse {
    void processFinished();
}

private class ImageTask extends AsyncTask<Void, Void, Exception> {
    private Bitmap photo;
    private ImageResponse imageResponse;
    ImageTask(Bitmap photo, ImageResponse imageResponse) {
        this.photo = photo;
        this.imageResponse = imageResponse;
    }

    @Override
    protected Exception doInBackground(Void... params) {
        // do background work here
        imageResponse.processFinished();
        return null;
    }

    @Override
    protected void onPostExecute(Exception result) {

    }
}

【讨论】:

    猜你喜欢
    • 2018-05-31
    • 1970-01-01
    • 2020-04-06
    • 2015-06-07
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多