繁体   English   中英

获取android camera2预览帧而不会滞后屏幕预览

[英]Getting android camera2 preview frames without lagging the screen preview

在原始(现已弃用)的相机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上复制相同的行为,但我找不到一种方法来做到这一点而不会滞后于屏幕预览。 如果我向预览请求添加第二个目标(与屏幕1相同的分辨率,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示例的修改版本, 这就是我改变的内容

如果有人仍然感兴趣。

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

以下是从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) {

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM