【问题标题】:error :Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers错误:无法获取锁定缓冲区,很可能客户端尝试锁定超过 maxImages 缓冲区
【发布时间】:2016-07-25 00:03:10
【问题描述】:

我正在使用 camera2 api 捕获图像并在缩略图中显示。在所有设备上一切正常,但是当使用Micromax Q382 设备时,然后在缩略图预览中显示黑色图像。我遇到了以下问题

Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers

我正在使用下面的代码来捕获侦听器回调

final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback()
        {

            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                                           TotalCaptureResult result)
            {

                super.onCaptureCompleted(session, request, result);

                startPreview();
            }

        };

        mCameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback()
        {

            @Override
            public void onConfigured(CameraCaptureSession session)
            {

                try {
                    session.capture(captureBuilder.build(), captureListener, backgroudHandler);
                } catch (CameraAccessException e) {
                    AppLogger.exception(myContext, getClass().getSimpleName(), e);
                    // e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session)
            {

            }
        }, backgroudHandler);

    } catch (CameraAccessException e) {
        AppLogger.exception(myContext, getClass().getSimpleName(), e);
        // e.printStackTrace();
    }

以下代码用于 OnImageAvailableListener

ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener()
        {

            @Override
            public void onImageAvailable(ImageReader reader)
            {

                Image image = null;
                try {
                    image = reader.acquireLatestImage();
                    // ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    // final byte[] bytes = new byte[buffer.capacity()];

                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    final byte[] bytes = new byte[buffer.remaining()];

                    buffer.get(bytes);
                    save(bytes);
                    buffer.clear();
                    runOnUiThread(new Runnable()
                    {

                        @Override
                        public void run()
                        {
                            mThumbnail.setVisibility(View.VISIBLE);
                            filePathLabel.setVisibility(View.VISIBLE);
                            filePathValue.setText(file.getAbsolutePath());

                            Bitmap bmp =
                                    UtilityMethods.getScaledBitmap(CameraImageTestActivityLoliipop.this, bytes);
                            mThumbnail.setImageBitmap(bmp);
                        }
                    });

                } catch (FileNotFoundException e) {
                    AppLogger.exception(myContext, getClass().getSimpleName(), e);
                    // e.printStackTrace();
                } catch (IOException e) {
                    AppLogger.exception(myContext, getClass().getSimpleName(), e);
                    // e.printStackTrace();
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }

【问题讨论】:

  • 请同时提供错误前的日志输出,以及整个异常堆栈跟踪,以查看错误是在哪里产生的以及在什么情况下产生的。
  • 它没有抛出任何异常,但我发现当我捕捉图片时,最后移动相机预览一秒钟变黑,这意味着我正在捕捉的照片是黑色的。我认为这应该是问题所在。但我试图改变财产,但还没有得到任何解决方案......
  • 你解决过这个问题吗?
  • 你在初始化ImageReader时设置了什么ImageFormat
  • @tropicalfish ImageFormat.JPEG

标签: android image-processing camera android-camera


【解决方案1】:

您可以为方法ImageReader.newInstance 提供参数maxImages 作为1acquireLatestImage 在关闭唯一的一个图像缓冲区之前调用acquireNextSurfaceImage,这会导致此警告。

在这种情况下使用acquireNextImage。如果maxImages大于1acquireLatestImage就没有这个问题。

【讨论】:

  • 我是这个菜鸟。请您详细说明,在何处以及如何进行更改。对我来说是迫切的要求。请考虑。
  • @KartikArora 在 ImageReader 的 maxImages 变量设置为 1 时使用 Image.acquireNextImage() 而不是 Image.acquireLatestImage()
【解决方案2】:

在将 maxImages 设置为 2 并使用 acquireLatestImage 后,如果您仍然遇到停止获取 onImageAvailable 回调的问题,那么很可能您没有释放从 acquireLatestImage() 获得的图像缓冲区,除非您调用,否则缓冲区将不可用Image.close() 在该图像上,并允许重复使用相同的缓冲区。

    Image raw = imageReader.acquireLatestImage();
    raw.close();

这是文档的链接: https://developer.android.com/reference/android/media/Image.html#close()

【讨论】:

    【解决方案3】:

    来自ImageReader.acquireLatestImage()的文档:

    从 ImageReader 的队列中获取最新的图像,丢弃旧的 图片。如果没有新图像可用,则返回 null。该操作将 从 ImageReader 获取所有可能的图像,但 close() all 不是最新的图像。

    此功能推荐使用 over acquireNextImage() 对于大多数用例,因为它更适合 实时处理。请注意,ma​​xImages 应至少为 2 acquireLatestImage() 与 acquireNextImage() 不同 - 丢弃所有但最新的图像需要临时获取两个 一次图像。

    因此,对于实时处理用途:

    • ImageReader.newInstance(..., maxImages = 2)
    • imageReader.acquireLatestImage()

    如果您的用例不同(例如批处理/后台处理),请使用例如:

    • ImageReader.newInstance(..., maxImages = 1)
    • imageReader.acquireNextImage()
    • 请注意,(来自acquireNextImage() 的文档:

    如果发生以下情况,此操作将失败并抛出 IllegalStateException maxImages 已通过 acquireNextImage() 或 获取最新图像()。特别是acquireNextImage()的序列 或 acquireLatestImage() 调用大于 maxImages 而不调用 中间的 close() 将耗尽底层队列。在这样的时候, IllegalStateException 将被抛出,直到释放更多图像 使用 close()。

    【讨论】:

      猜你喜欢
      • 2021-01-22
      • 1970-01-01
      • 2011-08-14
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多