安卓相机2的getPreviewFrame函数

16

我正在尝试在预览模式下获取相机帧。我正在运行来自GitHub的示例项目:https://github.com/googlesamples/android-Camera2Basic

我遇到的问题是在预览模式下获取帧。

这里是代码:

private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {

    private void process(CaptureResult result) {
        switch (mState) {
            case STATE_PREVIEW: {

                //HERE, HOW CAN I RETRIEVE THE CURRENT FRAME?

                break;
            }
            case STATE_WAITING_LOCK: {
               ...
                break;
            }
            case STATE_WAITING_PRECAPTURE: {
             ...
                break;
            }
            case STATE_WAITING_NON_PRECAPTURE: {
             ...
                break;
            }
        }
    }

我尝试通过设置mImageReader.setOnImageAvailableListener来获取帧。我期望在onImageAvailable回调中能够获取到帧,但是onImageAvailable从未被调用过。onPreviewFrame是我的自定义方法,我需要将当前帧传递给它。

  mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, /*maxImages*/2);
  mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);

  private final ImageReader.OnImageAvailableListener mOnImageAvailableListener  = new ImageReader.OnImageAvailableListener() {

    @Override
    public void onImageAvailable(ImageReader reader) {
        mTextureView.onPreviewFrame(reader.acquireNextImage().getPlanes([0].getBuffer().array());
    }

};

我做错了什么?谢谢。

1个回答

18

当预览帧可用时,OnImageAvailableListener.onImageAvailable回调永远不会被调用,因为发送到CameraCaptureSession.setRepeatingRequest()方法的CaptureRequest未将ImageReaderSurface列为输出目标。

在向相机发送请求时,需要确定要将每个捕获的数据传输到哪个输出Surface(即原始字节缓冲区)。因此,要使“预览帧”触发onImageAvailable()回调并被发送到onPreviewFrame()方法中,只需添加以下行:

mPreviewRequestBuilder.addTarget(mImageReader.getSurface());

这行代码可以放在其他类似的行之后,以将SurfaceTextureSurface添加到同一个请求构建器中。

请注意,这将把每个预览帧都发送到您的函数,以及从拍照按钮中获取的“输出帧”。您可能需要在onImageAvailable()回调中编写一些代码来进行区分。


你好@Summer,你知道我可以用什么方法在process方法中获取帧吗?谢谢。 - Demian Flavius
1
你是说mCaptureCallback中的process()方法吗?答案是否定的-唯一发送到那里的是有关图像的CaptureResult元数据。图像本身会被发送到你在相应的CaptureRequest中添加为目标的地方。但基本上,上面提出的原始问题就是你希望做的事情,我想...注册一个ImageReader的Surface作为请求的输出,然后使用OnImageAvailableListener()监听输出是否可用。 - rcsumner
很不幸,我也遇到了类似的问题,并且我无法通过上面的答案解决它。我需要创建一个新的CaptureRequest吗?(在示例中有一个用于预览,我可以重复使用它并只需添加目标吗?) - user2924714
1
按照答案中提供的指示,我的应用程序仍然会冻结,即使已经针对大多数传递到imageAvailableListener的帧进行了区分。你们是如何解决这个问题的?是添加表面一段时间然后再移除吗? - Sipty
1
@Sipty 我也遇到了同样的问题。当我添加mPreviewRequestBuilder.addTarget(mImageReader.getSurface());时,预览会冻结。你能详细解释一下吗?谢谢。 - user1154390
显示剩余5条评论

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