人类的悲欢并不相通—鲁迅
-
Android Camera系列(一):SurfaceView+Camera
-
Android Camera系列(二):TextureView+Camera
-
Android Camera系列(三):GLSurfaceView+Camera
-
Android Camera系列(四):TextureView+OpenGL ES+Camera
-
Android Camera系列(五):Camera2
-
Android Camera系列(六):MediaCodec视频编码上-编码YUV
-
Android Camera系列(七):MediaCodec视频编码中-OpenGL ES多线程渲染
-
Android Camera系列(八):MediaCodec视频编码下-OpenGL ES离屏渲染
本系列主要讲述Android开发中Camera的相关操作、预览方式、视频录制等。项目结构简单、代码耦合性低,旨在帮助大家能从中有所收获(方便copy :) ),对于个人来说也是一个总结的好机会
本章我们来讲解GLSurfaceView
进行Camera预览,基于第一篇Android Camera系列(一):SurfaceView+Camera的成果,我们已经对Camera进行了封装,CameraManager拿来直接使用就好
一.GLSurfaceView使用
GLSurfaceView实际上就是继承了SurfaceView,并在其内部封装了EGL环境管理和渲染线程,不了解EGL的请移步至Android OpenGLES开发:EGL环境搭建,使得我们可以直接使用OpenGL ES的API对图像进行变换等操作,如:黑白滤镜、美颜等各种复杂的滤镜效果
- 自定义
CameraGLSurfaceView
继承GLSurfaceView
- 实现
SurfaceTexture.OnFrameAvailableListener
接口,并在onFrameAvailable
回调中请求每一帧数据进行渲染,也就是说Camera的预览需要我们自己绘制完成 - GLSurfaceView提供了绘制接口
Renderer
,我们需要定义CameraSurfaceRenderer
实现该接口,并在GLSurfaceView初始化时设置自定义的渲染类。在onSurfaceCreated
回调中创建外部纹理SurfaceTexture
,并设置OnFrameAvailableListener
监听Camera数据回调 - 实现自定义CameraCallback接口,监听Camera状态
- 一定要实现
onResume
和onPause
接口,并在对应的Activity生命周期中调用。这是所有使用Camera的bug的源头
public class CameraGLSurfaceView extends GLSurfaceView implements SurfaceTexture.OnFrameAvailableListener, CameraCallback {
private static final String TAG = CameraGLSurfaceView.class.getSimpleName();
private Context mContext;
private SurfaceTexture mSurfaceTexture;
private CameraHandler mCameraHandler;
private boolean hasSurface; // 是否存在摄像头显示层
private CameraManager mCameraManager;
private int mRatioWidth = 0;
private int mRatioHeight = 0;
private int mGLSurfaceWidth;
private int mGLSurfaceHeight;
private CameraSurfaceRenderer mRenderer;
public CameraGLSurfaceView(Context context) {
super(context);
init(context);
}
public CameraGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mContext = context;
mCameraHandler = new CameraHandler(this);
mCameraManager = new CameraManager(context);
mCameraManager.setCameraCallback(this);
setEGLContextClientVersion(2);
mRenderer = new CameraSurfaceRenderer(mCameraHandler);
setRenderer(mRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public SurfaceTexture getSurfaceTexture() {
return mSurfaceTexture;
}
private void setAspectRatio(int width, int height) {
if (width < 0 || height < 0) {
throw new IllegalArgumentException("Size cannot be negative.");
}
mRatioWidth = width;
mRatioHeight = height;
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int