Copy ByteBuffer from PBO on android make weird error

I implemented PBO follow the answer: https://stackoverflow.com/a/56663353/9901781
But after call

ByteBuffer pixelsBuffer = (ByteBuffer) GLES30.glMapBufferRange(GLES30.GL_PIXEL_PACK_BUFFER, 0, mViewWidth * mViewHeight * 4, GLES30.GL_MAP_READ_BIT);
if(mSkipFirstFrame)
{
        // Skip the first frame as the PBO's have nothing in them until the second render cycle
try {
// this make weird error (or even only pixelsBuffer.array() also make weird error)
    System.arraycopy(pixelsBuffer.array(), 0, arrayForTest, 0, mViewWidth * mViewHeight * 4);
// ... SOME CODE AT HERE WILL BE NOT EXCUTE

// this work perfectly
//  Bitmap bm = Bitmap.createBitmap(frameWidth, frameHeight, Bitmap.Config.ARGB_8888);
//  bm.copyPixelsFromBuffer(pixelsBuffer);
//  save bm to file
} catch (Exception e) { log exception}

// ... SOME CODE AT HERE WILL BE EXCUTE
}

If I store pixelsBuffer to file, then everything work perfectly.
Else if I copy pixelsBuffer to byte array or other ByteBuffer (using System.arraycopy), then this make weird error. Are there any way (fastest speed) to copy pixelsBuffer ?

What error exactly?

ByteBuffer.array() will throw UnsupportedOperationException if the buffer isn’t backed by an array (byte[]) (and a mapped region won’t be). You’re supposed to call .hasArray() to check that it’s backed by an array before calling .array(). Reference.

If you want to copy the contents of a ByteBuffer to a byte[], use the .get() method.

1 Like

Thanks @GClements , I tried get() method, it worked, but its runtime too slow (150 ms), even slower than store to file (70 ms). Frame resolution is 1920x1080. Are there fastest way to copy it ?

Copy it to what?

Are you trying to read from the PBO before the glReadPixels has completed? If you call glFinish before the .get(), does that affect the timing?

My task is draw filter (skin smooth) and encode it (with software encoder). Currently, applied filter frame is stored in pixelsBuffer. So I need send it to JNI (JNI will convert rgba to I420 for encoder), then wakeup encoder thread excute encode incoming frame (encoder must be Software Encoder)

How to know glReadPixels is done ?

I found bottleneck point. It slow because copying data bytebuffer.get(dest).
This not happen when I dont use PBO. Because after glReadPixels call, I got bytebuffer that has array backs this buffer. So I pass bytebuffer.array() to JNI. This verry fast.