I'm writing an android application to capture screen data, and make an MP4 out of it. The first step in this is to use some openGL calls to read out the pixels from the screen.
private void screenScrape() {
Log.d(TAG, "In screenScrape");
//read pixels from frame buffer into PBO (GL_PIXEL_PACK_BUFFER)
mySurface.queueEvent(new Runnable() {
@Override
public void run() {
Log.d(TAG, "In Screen Scrape 1");
//generate and bind buffer ID
GLES30.glGenBuffers(1, pboIds);
checkGlError("Gen Buffers");
GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pboIds.get(0));
checkGlError("Bind Buffers");
//creates and initializes data store for PBO. Any pre-existing data store is deleted
GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER, (mWidth * mHeight * 4), null, GLES30.GL_STATIC_READ);
checkGlError("Buffer Data");
glReadPixelsPBO(0, 0, mWidth, mHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, 0);
checkGlError("Read Pixels");
}
});
//map PBO data into client address space
mySurface.queueEvent(new Runnable() {
@Override
public void run() {
Log.d(TAG, "In Screen Scrape 2");
//read pixels from PBO into a byte buffer for processing. Unmap buffer for use in next pass
mapBuffer = ((ByteBuffer) GLES30.glMapBufferRange(GLES30.GL_PIXEL_PACK_BUFFER, 0, 4 * mWidth * mHeight, GLES30.GL_MAP_READ_BIT)).order(ByteOrder.nativeOrder());
checkGlError("Map Buffer");
GLES30.glUnmapBuffer(GLES30.GL_PIXEL_PACK_BUFFER);
checkGlError("Unmap Buffer");
//openGL calls return pixels in a flipped format. Flip buffer so image presented right side up
for (int i = 0; i < mWidth; ++i) {
for (int j = 0; j < mHeight; ++j) {
for (int k = 0; k < 4; ++k) {
flippedBuffer.put((i + j * mWidth) * 4 + k, mapBuffer.get((i + (mHeight - 1 - j) * mWidth) * 4 + k));
}
}
}
isByteBufferEmpty(mapBuffer, "MAP BUFFER");
Log.d(TAG, "Flipped Buffer Position: " + flippedBuffer.position() + "Remaining: " + flippedBuffer.remaining() + " Limit: " + flippedBuffer.limit());
convertColorSpaceByteArray(flippedBuffer);
mapBuffer.clear();
}
});
}
mySurface
is a GLMapsurface that I initialize from an input parameter.
e.g. GLMapSurface mySurface = inputSurface
where inputSurface
is a passed parameter.
Now my issue is that the call to glMapBufferRange blocks the UI. How can I get this call to run in a background thread so it doesn't block the UI?
I've attempted creating a new GLMapSurface
object and queuing up events to that, but they never get executed.