Android GPUImage performance upgrade to pure GPU + GPUImageRenderer parsing (1)

GPUImage is my enlightenment framework for filter cameras, but it's a bit slow for me to use it in camera.opengl shouldn't be so slow.For reasons, let's look at GPUImage Renderer, the core class of GPUImage.

First of all, we go to this kind of command+f to search onPreview Frame. Everyone who has been a cameraman knows that this is a camera callback method. When a new picture appears, the data will be returned to the first parameter (byte[] data).

    @Override
    public void onPreviewFrame(final byte[] data, final Camera camera) {

        final Size previewSize = camera.getParameters().getPreviewSize();
        if (mGLRgbBuffer == null) {
            mGLRgbBuffer = IntBuffer.allocate(previewSize.width * previewSize.height);
        }
        if (mRunOnDraw.isEmpty()) {
            runOnDraw(new Runnable() {
                @Override
                public void run() {
                    GPUImageNativeLibrary.YUVtoRBGA(data, previewSize.width, previewSize.height,
                            mGLRgbBuffer.array());
                    mGLTextureId = OpenGlUtils.loadTexture(mGLRgbBuffer, previewSize, mGLTextureId);
                    camera.addCallbackBuffer(data);
                    if (mImageWidth != previewSize.width) {
                        mImageWidth = previewSize.width;
                        mImageHeight = previewSize.height;
                        adjustImageScaling();
                    }
                }
            });
        }
    }
 

Looking at this callback, we can see what GPUImage did. Take out each frame, convert YUV-formatted graph into RBGA graph, and then throw it into the texture cache. Return a texture id that is mGLTextureId.

Then we'll search for the next method.

    @Override
    public void onDrawFrame(final GL10 gl) {
        . . . 
        mFilter.onDraw(mGLTextureId, mGLCubeBuffer, mGLTextureBuffer);
        . . . 
    }

This is the way GlSurface View calls back every time it displays a new image, using the image data of each frame of the camera above, which is the texture mGLTextureId.


Well, here is too laggy. I have no problem with the logic. But I took my red rice 700 yuan, and the phone was very stuck. I didn't bring my camera with me. After I checked some information, I made an optimization for him.


First analyze the question, why the card should be for each frame of the picture, and he took it out to transform the image of YUV into BGRA by using cpu, and then turn it into texture ID to mFiler. Using the human eye to recognize 24 frames per second, plus the camera resolution, tentative 1600*1200 means that cpu should run at least 24*1600*1200 size array per second. How can it be slow?

Then comes the solution.

/**
     * Create OES texture id
     *
     * @return
     */
    public static int createOESTextureID() {
        final int[] tex = new int[1];
        GLES20.glGenTextures(1, tex, 0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

        return tex[0];
    }

This texture property is critical
GLES11Ext.GL_TEXTURE_EXTERNAL_OES
It's an external input device property.


    public void initCamera(final Camera camera, SurfaceTexture.OnFrameAvailableListener listener) {
        // Generating Texture Id
        mGLTextureId = GLTextureUtil.createOESTextureID();
        mGLTextureIdText = GLTextureUtil.createOESTextureID();

        // Create Surface Texture (the mSurface Texture is bound to Camera) with Texture Id
        mSurfaceTexture = new SurfaceTexture(mGLTextureId);
        mSurfaceTexture.setOnFrameAvailableListener(listener);
        try {
            camera.setPreviewTexture(mSurfaceTexture);
        } catch (IOException e) {
            e.printStackTrace();
        }
        camera.startPreview();
    }

This is my overloaded method of setting up Camera.
setOnFrameAvailableListener
Here's listener I wrote
new SurfaceTexture.OnFrameAvailableListener() {
            @Override
            public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                mGlSurfaceView.requestRender();
            }
        }

Notify GLSurafecView to update the view


The next chapter describes how to write the shader corresponding to the texture ID of OES attributes.


Finally, your filter camera will fly fast.

http://blog.csdn.net/u010831488/article/details/71404412

Added by IronicSoul on Wed, 03 Jul 2019 01:50:11 +0300