Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing Camera2 preview frames returns empty buffer

I've been working on a simple Android app designed to pass streaming camera frames from the Android Camera2 API pipeline to my algorithm. I've made several applications already that faithfully do this using the Android Camera1 API, but even after checking (Google docs, forums) to confirm correct coding, I am unable to capture any real data from the ImageReader in onImageAvailable(). Please note the following relevant code:

  1. Setting up the 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. Setting up the 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. Setting up the 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...]
    }
    
    };
    

In code snippet #3, my byte buffer always returns empty (all zeros), regardless of ImageReader format. Has anyone had this issue? Am I missing any code?

like image 225
shandroid Avatar asked Jun 30 '15 19:06

shandroid


1 Answers

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

like image 125
Elena Naumova Avatar answered Sep 30 '22 06:09

Elena Naumova