Incorrect transformation of frames from YUV_420_888 format to NV21 within an image reader
Asked Answered
B

1

5

I configured my code in order to get a stream of YUV_420_888 frames from my device's camera using an imageReader object and the rest of the well known camera2 API. Now I need to transform these frames to NV21 pixel format and call a native function which expect a frame in this format to perform certain computations. This is the code I am using inside the imagereader callback to rearrange the bytes of the frame:

        ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader mReader) {
                Image image = null;
                image = mReader.acquireLatestImage();
                if (image == null) {
                    return;
                }                           

                byte[] bytes = convertYUV420ToNV21(image);

                nativeVideoFrame(bytes);
                image.close();   
            }
        };

private byte[] convertYUV420ToNV21(Image imgYUV420) {

    byte[] rez;

    ByteBuffer buffer0 = imgYUV420.getPlanes()[0].getBuffer();
    ByteBuffer buffer1 = imgYUV420.getPlanes()[1].getBuffer();
    ByteBuffer buffer2 = imgYUV420.getPlanes()[2].getBuffer();

    int buffer0_size = buffer0.remaining();
    int buffer1_size = buffer1.remaining();
    int buffer2_size = buffer2.remaining();

    byte[] buffer0_byte = new byte[buffer0_size];
    byte[] buffer1_byte = new byte[buffer1_size];
    byte[] buffer2_byte = new byte[buffer2_size];
    buffer0.get(buffer0_byte, 0, buffer0_size);
    buffer1.get(buffer1_byte, 0, buffer1_size);
    buffer2.get(buffer2_byte, 0, buffer2_size);


    ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
    try {
        outputStream.write( buffer0_byte );
        outputStream.write( buffer1_byte );
        outputStream.write( buffer2_byte );
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    rez = outputStream.toByteArray( );   

    return rez;
}

But I dont know why, the resulting frame is "flipped" in the horizontal direction. In other word, when I move the camera to the right, the frame after the packing procedure I have described is moving to the left, like if the sensor is placed in an antinatural position.

I hope you may understand what I mean

Thanks,

JM

Brittanybritte answered 18/8, 2016 at 17:32 Comment(2)
Blue and Red colors are swapped, after convertYUV420ToNV21 and compressToJpeg.Intrigante
@VladimirKulyk when writing to the output stream, re-order to 0 / 2 / 1 to un-swap Blue & RedParry
S
1

It's ok for camera to produce mirrored image. If you don't want it to be mirrored - you need to perform horizontal mirroring, swapping pixels in each row.

Selfinductance answered 18/8, 2016 at 17:40 Comment(1)
You save my day. That was the hint I was looking forBrittanybritte

© 2022 - 2024 — McMap. All rights reserved.