捕获Camera2预览帧将返回空缓冲区

时间:2015-06-30 19:52:01

标签: android camera buffer preview frames

我一直致力于开发一款简单的Android应用程序,旨在将Android Camera2 API管道中的流式相机帧传递给我的算法。我已经使用Android Camera1 API忠实地做了几个应用程序,但即使在检查(Google文档,论坛)以确认正确编码之后,我也无法从onImageAvailable()中的ImageReader捕获任何真实数据。请注意以下相关代码:

  1. 设置ImageReaders:

    private void setUpCameraOutputs(int width, int height) {
    
    [....code....]
    
    mImageReader = ImageReader.newInstance(smallestJPEG.getWidth(), 
                                           smallestJPEG.getHeight(),
                                           ImageFormat.JPEG, /*maxImages*/2);
    // mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, null);
    mPreviewImageReader = ImageReader.newInstance(smallest.getWidth(), 
                                                  smallest.getHeight(), 
                                                  ImageFormat.YUV_420_888, 2);
    mPreviewImageReader.setOnImageAvailableListener(mOnPreviewImageAvailableListener,
                                                    mBackgroundHandler);
    
    [....code....]
    
    }
    
    1. 设置CaptureSession:

      private void createCameraPreviewSession() {
      try {
          //Create Texture from Screen's TextureView
          SurfaceTexture texture = mTextureView.getSurfaceTexture();
      
          assert texture != null;
      
          //Configure Default Buffer Size
          texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
      
          //Create Output Surface from Texture
          Surface surface = new Surface(texture);
      
          // Set up a CaptureRequest.Builder with the output Surface.
          mPreviewRequestBuilder
                  = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
      
          //Add Output Display surface
          mPreviewRequestBuilder.addTarget(surface);
      
          //Add Preview frame-grabbing surface 
          mPreviewRequestBuilder.addTarget(mPreviewImageReader.getSurface());
      
          mCameraDevice.createCaptureSession(Arrays.asList(surface, mPreviewImageReader.getSurface()),
                  new CameraCaptureSession.StateCallback() {
      
                      @Override
                      public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                          // The camera is already closed
                          if (null == mCameraDevice) {
                              return;
                          }
      
                          // When the session is ready, we start displaying the preview.
                          mCaptureSession = cameraCaptureSession;
                          try {
                              // Auto focus should be continuous for camera preview. [...code...]
                              mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                      CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                              // Flash is automatically enabled when necessary.
                              mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                                      CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
      
                              // Finally, we start displaying the camera preview.
                              mPreviewRequest = mPreviewRequestBuilder.build();
                              mCaptureSession.setRepeatingRequest(mPreviewRequest,
                                      mCaptureCallback, mBackgroundHandler);
                          } catch (CameraAccessException e) {
                              [...code...]
                          }
                      }
      
                      @Override
                      public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                          [...code...]
                      }
                  }, null
          );
      } catch (CameraAccessException e) {
          [...code...]
      }
      }
      
      1. 设置OnImageAvailableListener:

        private ImageReader mPreviewImageReader;
        private final ImageReader.OnImageAvailableListener mOnPreviewImageAvailableListener
        = new ImageReader.OnImageAvailableListener() {
        
        @Override
        public void onImageAvailable(ImageReader reader) {
        
            //Acquire Image, ByteBuffer, then byte array
            Image image = reader.acquireLatestImage();
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
        
            //Check bytes array for anydata
            int cnt = 0;
            for (int i = 0; i < bytes.length; i++){
                if (bytes[i] != 0)cnt++;
            }
            Log.i(TAG, "cnt = " + cnt);
            image.close();
        
            //At this point, byte[] bytes is empty (all zero)
            [...code...]
        }
        
        };
        
      2. 在代码片段#3中,无论ImageReader格式如何,我的字节缓冲区始终返回空(全为零)。有人有这个问题吗?我错过了任何代码吗?

2 个答案:

答案 0 :(得分:5)

byte [] bytes = new byte [buffer.remaining()];

之后添加 buffer.get(bytes);

答案 1 :(得分:0)

you miss some code check this,

 ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        FileOutputStream output = null;
        try {
            output = new FileOutputStream(mFile);
            output.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mImage.close();
            if (null != output) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }