Android GPUImage 整体架构 (1)

Posted by

整体架构

CameraLoader

  • 设置Camera
private void setUpCamera(final int id) {
mCameraInstance = getCameraInstance(id);
Parameters parameters = mCameraInstance.getParameters();
// TODO adjust by getting supportedPreviewSizes and then choosing
// the best one for screen size (best fill screen)
if (parameters.getSupportedFocusModes().contains(
Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
mCameraInstance.setParameters(parameters);
int orientation = mCameraHelper.getCameraDisplayOrientation(
ActivityCamera.this, mCurrentCameraId);
CameraInfo2 cameraInfo = new CameraInfo2();
mCameraHelper.getCameraInfo(mCurrentCameraId, cameraInfo);
boolean flipHorizontal = cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT;
mGPUImage.setUpCamera(mCameraInstance, orientation, flipHorizontal, false);
}

GPUImage

  • 控制GPUImageFilter和GPUImageRenderer
  • 设置SurfaceView
  • 设置Camera

控制GPUImageFilter和GPUImageRenderer

mFilter = new GPUImageFilter();
mRenderer = new GPUImageRenderer(mFilter);

设置SurfaceView

mGlSurfaceView.setEGLContextClientVersion(2);
mGlSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
mGlSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
mGlSurfaceView.setRenderer(mRenderer);
mGlSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mGlSurfaceView.requestRender();

设置Camera

  • 自动模式, GLSurfaceView.RENDERMODE_CONTINUOUSLY;GL线程以一 定的时间间隔自动的循环调用用户实现的onDrawFrame方法进行一帧一帧的绘制
  • “脏”模式,GLSurfaceView.RENDERMODE_WHEN_DIRTY;当需要重绘时,调用
    GLSurfaceView.requestRender()

一般情况下使用脏模式,这样可以有效降低cpu负载。

public void setUpCamera(final Camera camera, final int degrees, final boolean flipHorizontal,
final boolean flipVertical) {
mGlSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
setUpCameraGingerbread(camera);
} else {
camera.setPreviewCallback(mRenderer);
camera.startPreview();
}
Rotation rotation = Rotation.NORMAL;
switch (degrees) {
case 90:
rotation = Rotation.ROTATION_90;
break;
case 180:
rotation = Rotation.ROTATION_180;
break;
case 270:
rotation = Rotation.ROTATION_270;
break;
}
mRenderer.setRotationCamera(rotation, flipHorizontal, flipVertical);
}

GPUImageRenderer

实现了PreviewCallback和GLSurfaceView Renderer 的接口。

Renderer的接口

  • onSurfaceCreated:Filter的初始化操作
  • onSurfaceChanged
  • onDrawFrame
public void onSurfaceCreated(final GL10 unused, final EGLConfig config) {
GLES20.glClearColor(mBackgroundRed, mBackgroundGreen, mBackgroundBlue, 1);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
mFilter.init();
}
@Override
public void onSurfaceChanged(final GL10 gl, final int width, final int height) {
mOutputWidth = width;
mOutputHeight = height;
GLES20.glViewport(0, 0, width, height);
GLES20.glUseProgram(mFilter.getProgram());
mFilter.onOutputSizeChanged(width, height);
adjustImageScaling();
synchronized (mSurfaceChangedWaiter) {
mSurfaceChangedWaiter.notifyAll();
}
}
@Override
public void onDrawFrame(final GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
runAll(mRunOnDraw);
mFilter.onDraw(mGLTextureId, mGLCubeBuffer, mGLTextureBuffer);
runAll(mRunOnDrawEnd);
if (mSurfaceTexture != null) {
mSurfaceTexture.updateTexImage();
}
}

PreviewCallback接口

@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();
}
}
});
}
}

GPUImageFilter

  • 初始化:OpenGL ES的初始化操作,顶点着色器、片段着色器;获取着色器的相关变量
  • 绘制过程
public final void init() {
onInit();
mIsInitialized = true;
onInitialized();
}
public void onInit() {
mGLProgId = OpenGlUtils.loadProgram(mVertexShader, mFragmentShader);
mGLAttribPosition = GLES20.glGetAttribLocation(mGLProgId, "position");
mGLUniformTexture = GLES20.glGetUniformLocation(mGLProgId, "inputImageTexture");
mGLAttribTextureCoordinate = GLES20.glGetAttribLocation(mGLProgId,
"inputTextureCoordinate");
mIsInitialized = true;
}
public void onDraw(final int textureId, final FloatBuffer cubeBuffer,
final FloatBuffer textureBuffer) {
GLES20.glUseProgram(mGLProgId);
runPendingOnDrawTasks();
if (!mIsInitialized) {
return;
}
cubeBuffer.position(0);
GLES20.glVertexAttribPointer(mGLAttribPosition, 2, GLES20.GL_FLOAT, false, 0, cubeBuffer);
GLES20.glEnableVertexAttribArray(mGLAttribPosition);
textureBuffer.position(0);
GLES20.glVertexAttribPointer(mGLAttribTextureCoordinate, 2, GLES20.GL_FLOAT, false, 0,
textureBuffer);
GLES20.glEnableVertexAttribArray(mGLAttribTextureCoordinate);
if (textureId != OpenGlUtils.NO_TEXTURE) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
GLES20.glUniform1i(mGLUniformTexture, 0);
}
onDrawArraysPre();
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDisableVertexAttribArray(mGLAttribPosition);
GLES20.glDisableVertexAttribArray(mGLAttribTextureCoordinate);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}

Leave a Reply

Your email address will not be published. Required fields are marked *