Search code examples
androidopengl-esandroid-camerayuvandroid-camera2

Android Camera2 preview output sizes


I am trying to setup camera preview through ImageReader(YUV_420_888 format) using Camera2 API. First of all i need to choose supported preview size:

StreamConfigurationMap scmap = camCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size previewSizes[] = scmap.getOutputSizes(ImageReader.class);

My Nexus 5X supports next sizes:

[4032x3024,4000x3000,3840x2160,3288x2480,3200x2400,2592x1944,2688x1512,2048x1536,1920x1080,1600x1200,1440x1080,1280x960,1280x768,1280x720,1024x768,800x600,864x480,800x480,720x480,640x480,640x360,352x288,320x240,176x144,160x120]

Prepare an instance of ImageReader and start CaptureSession with repeating capture request:

mImageReader = ImageReader.newInstance(W,H, ImageFormat.YUV_420_888,1);

Then I'm trying to read each preview frame (for further processing and displaying via GLES) in OnImageAvailableListener. And what i want to know - how many Y-channel bytes i have received:

public void onImageAvailable(ImageReader reader) {
        ByteBuffer yBuffer = mImageReader.acquireNextImage().getPlanes()[0].getBuffer();
        Log.d("Camera2Debug","Y-channel bytes received: " + yBuffer.remaining());
        ...
    }

The Y-channel for YUV_420_888 image should contain WxH bytes, where W - is the width, and H - is the height of the considered image.

Problem: For some supported preview sizes the actual size of yBuffer doesn't match with expected value (WxH).

For example:

Preview Size  | Y-bytes received | Y-bytes expected  |   match
4032x3024     | 12 192 768       | 12 192 768        |    yes
1920x1080     |  2 073 600       |  2 073 600        |    yes
1440x1080     |  1 589 728       |  1 555 200        |    no
1280x960      |  1 228 800       |  1 228 800        |    yes
1280x768      |    983 040       |    983 040        |    yes
800x600       |    499 168       |    480 000        |    no
...
499168

So due to this problem I can't use the neccessary preview size even if it is supported by device.

What am I doing wrong?


Solution

  • You're likely not taking into account https://developer.android.com/reference/android/media/Image.Plane.html#getRowStride(), which may be larger than the width (but is at least equal to it). The actual buffer size will be

    size = rowStride * height - (rowStride - width)
    

    with the subtraction of (rowStride - width) because the last row doesn't include any padding past the last pixel.