【问题标题】:android camera2 preview lag when getting frame获取帧时android camera2预览滞后
【发布时间】:2018-05-31 18:22:02
【问题描述】:

我正在使用 Android camera2 以在预览模式下实时提取帧以将它们拼接到 NDK 端(openCv)。 我使用ImageReader 表面来获取帧,但它被限制为最大帧值。

ImageReader.newInstance(800,600,ImageFormat.YUV_420_888, MAX_FRAME); 

效果很好,但由于我们需要所有帧,因此必须从CaptureRequest.Builder 中删除ImageReader 目标表面并重新添加。所以我们在这一点上有一个滞后。

我们如何在没有最大帧的情况下获得ImageReader,或者我们如何从camera2 中的实时视频中获取所有帧而没有任何预览延迟?

我的代码:

    private void startPreview() {
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
            return;
        }
        try {

            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            Surface previewSurface = new Surface(texture);
            surfaces = new ArrayList<>();
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            surfaces.add(previewSurface);
            mPreviewBuilder.addTarget(previewSurface);
            mPreviewCaptureCallback = new CameraCaptureSession.StateCallback() {

                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
//                    closePreviewSession();
                    mPreviewSession = session;
                    try {
                        session.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    Activity activity = getActivity();
                    if (null != activity) {
                        Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
                    }
                }
            };
            mCameraDevice.createCaptureSession(surfaces, mPreviewCaptureCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void addImageReaderSurface() {
        try {

            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            Surface previewSurface = new Surface(texture);
            surfaces = new ArrayList<>();
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            surfaces.add(previewSurface);
            mPreviewBuilder.addTarget(previewSurface);
            newImageReader(10);
            surfaces.add(mImageReader.getSurface());
            mPreviewBuilder.addTarget(mImageReader.getSurface());

            mPreviewCaptureCallback = new CameraCaptureSession.StateCallback() {

                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    mPreviewSession = session;
                    try {
                        mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    Activity activity = getActivity();
                    if (null != activity) {
                        Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
                    }
                }
            };
            mCameraDevice.createCaptureSession(surfaces, mPreviewCaptureCallback, mBackgroundHandler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void newImageReader(final int count) {
        mImageReader = ImageReader.newInstance(800, 600, ImageFormat.YUV_420_888, count);
        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                index++;
                Log.e("xxx", "frame " + index + " received");
                if (index == count) {
                    index = 0;
//                    remove it before reached max value
                    addImageReaderSurface();
                }
            }
        }, mBackgroundHandler);
    }

【问题讨论】:

  • 您不需要重新启动 ImageReader。 MAX_FRAME 是队列大小,如果你的回调足够快,它永远不会被填满,并且预览帧会不断流入。
  • 找到解决方案了吗?

标签: preview android-camera2 screen-capture previewcallback image-reader


【解决方案1】:

使用Image img = reader.acquireLatestImage()从阅读器获取图像后,必须调用img.close()

public void onImageAvailable(ImageReader reader) {
    Image img = reader.acquireLatestImage();
    if (img == null) { return; }
    // do work
    img.close();
}

【讨论】:

    猜你喜欢
    • 2017-01-19
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 2017-09-09
    • 2015-09-22
    • 1970-01-01
    相关资源
    最近更新 更多