赞
踩
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-
- }
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
-
- }
- @Override
- public void onDrawFrame(GL10 gl) {
-
- }
- mCamera = Camera.open(cameraId);
- if (mCamera != null){
- /**选择当前设备允许的预览尺寸*/
- Camera.Parameters param = mCamera.getParameters();
- preSize = getPropPreviewSize(param.getSupportedPreviewSizes(), mConfig.rate,
- mConfig.minPreviewWidth);
- picSize = getPropPictureSize(param.getSupportedPictureSizes(),mConfig.rate,
- mConfig.minPictureWidth);
- param.setPictureSize(picSize.width, picSize.height);
- param.setPreviewSize(preSize.width,preSize.height);
-
- mCamera.setParameters(param);
- }
-
- private Camera.Size getPropPictureSize(List<Camera.Size> list, float th, int minWidth){
- Collections.sort(list, sizeComparator);
- int i = 0;
- for(Camera.Size s:list){
- if((s.height >= minWidth) && equalRate(s, th)){
- break;
- }
- i++;
- }
- if(i == list.size()){
- i = 0;
- }
- return list.get(i);
- }
- private Camera.Size getPropPreviewSize(List<Camera.Size> list, float th, int minWidth){
- Collections.sort(list, sizeComparator);
-
- int i = 0;
- for(Camera.Size s:list){
- if((s.height >= minWidth) && equalRate(s, th)){
- break;
- }
- i++;
- }
- if(i == list.size()){
- i = 0;
- }
- return list.get(i);
- }
- private static boolean equalRate(Camera.Size s, float rate){
- float r = (float)(s.width)/(float)(s.height);
- if(Math.abs(r - rate) <= 0.03) {
- return true;
- }else{
- return false;
- }
- }
- private Comparator<Camera.Size> sizeComparator=new Comparator<Camera.Size>(){
- public int compare(Camera.Size lhs, Camera.Size rhs) {
- if(lhs.height == rhs.height){
- return 0;
- }else if(lhs.height > rhs.height){
- return 1;
- }else{
- return -1;
- }
- }
- };
这个代码还是相当简单,这里就不过多介绍了,网上也有很多不同的但是类似功能的适配方法,大家可以多了解下,相互对照。
- public static int uLoadShader(int shaderType,String source){
- int shader= GLES20.glCreateShader(shaderType);
- if(0!=shader){
- GLES20.glShaderSource(shader,source);
- GLES20.glCompileShader(shader);
- int[] compiled=new int[1];
- GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS,compiled,0);
- if(compiled[0]==0){
- glError(1,"Could not compile shader:"+shaderType);
- glError(1,"GLES20 Error:"+ GLES20.glGetShaderInfoLog(shader));
- GLES20.glDeleteShader(shader);
- shader=0;
- }
- }
- return shader;
- }
- /**
- * Buffer初始化
- */
- protected void initBuffer(){
- ByteBuffer a= ByteBuffer.allocateDirect(32);
- a.order(ByteOrder.nativeOrder());
- mVerBuffer=a.asFloatBuffer();
- mVerBuffer.put(pos);
- mVerBuffer.position(0);
- ByteBuffer b= ByteBuffer.allocateDirect(32);
- b.order(ByteOrder.nativeOrder());
- mTexBuffer=b.asFloatBuffer();
- mTexBuffer.put(coord);
- mTexBuffer.position(0);
- }
- /**
- * 绑定默认纹理
- */
- protected void onBindTexture(){
- GLES20.glActiveTexture(GLES20.GL_TEXTURE0+textureType);
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,getTextureId());
- GLES20.glUniform1i(mHTexture,textureType);
- }
- /**
- * 清理画布
- */
- protected void onClear(){
- GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
- }
- public void setFlag(int flag) {
- super.setFlag(flag);
- float[] coord;
- if(getFlag()==1){ //前置摄像头 顺时针旋转90,并上下颠倒
- coord=new float[]{
- 1.0f, 1.0f,
- 0.0f, 1.0f,
- 1.0f, 0.0f,
- 0.0f, 0.0f,
- };
- }else{ //后置摄像头 顺时针旋转90度
- coord=new float[]{
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- };
- }
- mTexBuffer.clear();
- mTexBuffer.put(coord);
- mTexBuffer.position(0);
- }
public class CameraDrawer implements GLSurfaceView.Renderer
然后,在类的构造函数中,进行AFilter的初始化
- public CameraDrawer(Resources resources){
- //初始化一个滤镜 也可以叫控制器
- showFilter = new ShowFilter(resources);
- }
在
onSurfaceCreated中,进行SurfaceTextured的创建,并且和AFilter进行绑定
- @Override
- public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
- textureID = createTextureID();
- mSurfaceTextrue = new SurfaceTexture(textureID);
- showFilter.create();
- showFilter.setTextureId(textureID);
-
- }
在onSurfaceChanged中,进行一些参数的更改和纹理的重新绑定
- @Override
- public void onSurfaceChanged(GL10 gl10, int i, int i1) {
- width = i;
- height = i1;
- /**创建一个帧染缓冲区对象*/
- GLES20.glGenFramebuffers(1,fFrame,0);
- /**根据纹理数量 返回的纹理索引*/
- GLES20.glGenTextures(1, fTexture, 0);
- /**将生产的纹理名称和对应纹理进行绑定*/
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fTexture[0]);
- /**根据指定的参数 生产一个2D的纹理 调用该函数前 必须调用glBindTexture以指定要操作的纹理*/
- GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mPreviewWidth, mPreviewHeight,
- 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
- useTexParameter();
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);
- }
在
onDrawFrame中进行图像的绘制工作。
- @Override
- public void onDrawFrame(GL10 gl10) {
- /**更新界面中的数据*/
- mSurfaceTextrue.updateTexImage();
-
- /**绘制显示的filter*/
- GLES20.glViewport(0,0,width,height);
- showFilter.draw();
- }
CameraDraw目前所做的主要工作就是这样,然后我们将CameraController、CameraDraw和自定义的CameraView控件进行绑定,就可以实现摄像头数据预览了。
- private void init() {
- /**初始化OpenGL的相关信息*/
- setEGLContextClientVersion(2);//设置版本
- setRenderer(this);//设置Renderer
- setRenderMode(RENDERMODE_WHEN_DIRTY);//主动调用渲染
- setPreserveEGLContextOnPause(true);//保存Context当pause时
- setCameraDistance(100);//相机距离
-
- /**初始化Camera的绘制类*/
- mCameraDrawer = new CameraDrawer(getResources());
- /**初始化相机的管理类*/
- mCamera = new CameraController();
- }
然后,分别在三个生命周期的函数中调用CameraController和CameraDrawer的相关方法,以及打开摄像头
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- mCameraDrawer.onSurfaceCreated(gl,config);
- if (!isSetParm){
- open(0);
- stickerInit();
- }
- mCameraDrawer.setPreviewSize(dataWidth,dataHeight);
- }
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- mCameraDrawer.onSurfaceChanged(gl,width,height);
- }
- @Override
- public void onDrawFrame(GL10 gl) {
- if (isSetParm){
- mCameraDrawer.onDrawFrame(gl);
- }
- }
然后在onFrameAvailable函数中,调用即可
- @Override
- public void onFrameAvailable(SurfaceTexture surfaceTexture) {
- this.requestRender();
- }
drawFilter = new ShowFilter(resources);
这里需要注意一下,为了显示在屏幕上是正常的,我们进行了旋转的操作。所以,我们在录制的AFilter里面需要加上矩阵翻转的控制。
- OM= MatrixUtils.getOriginalMatrix();
- MatrixUtils.flip(OM,false,true);//矩阵上下翻转
- drawFilter.setMatrix(OM);
然后同样分别进行drawFilter的create,在onDrawFrame里面讲textureId进行绑定以及绘制。还有就是添加录制控制的相关代码
- GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fFrame[0]);
- GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
- GLES20.GL_TEXTURE_2D, fTexture[0], 0);
- GLES20.glViewport(0,0,mPreviewWidth,mPreviewHeight);
- drawFilter.setTextureId(fTexture[0]);
- drawFilter.draw();
- //解绑
- GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);
-
- if (recordingEnabled){
- /**说明是录制状态*/
- switch (recordingStatus){
- case RECORDING_OFF:
- videoEncoder = new TextureMovieEncoder();
- videoEncoder.setPreviewSize(mPreviewWidth,mPreviewHeight);
- videoEncoder.startRecording(new TextureMovieEncoder.EncoderConfig(
- savePath, mPreviewWidth, mPreviewHeight,
- 3500000, EGL14.eglGetCurrentContext(),
- null));
- recordingStatus = RECORDING_ON;
- break;
- case RECORDING_ON:
- case RECORDING_PAUSED:
- break;
- case RECORDING_RESUMED:
- videoEncoder.updateSharedContext(EGL14.eglGetCurrentContext());
- videoEncoder.resumeRecording();
- recordingStatus = RECORDING_ON;
- break;
-
- case RECORDING_RESUME:
- videoEncoder.resumeRecording();
- recordingStatus=RECORDING_ON;
- break;
- case RECORDING_PAUSE:
- videoEncoder.pauseRecording();
- recordingStatus=RECORDING_PAUSED;
-
- break;
- default:
- throw new RuntimeException("unknown recording status "+recordingStatus);
- }
-
- }else {
- switch (recordingStatus) {
- case RECORDING_ON:
- case RECORDING_RESUMED:
- case RECORDING_PAUSE:
- case RECORDING_RESUME:
- case RECORDING_PAUSED:
- videoEncoder.stopRecording();
- recordingStatus = RECORDING_OFF;
- break;
- case RECORDING_OFF:
- break;
- default:
- throw new RuntimeException("unknown recording status " + recordingStatus);
- }
- }
-
- if (videoEncoder != null && recordingEnabled && recordingStatus == RECORDING_ON){
- videoEncoder.setTextureId(fTexture[0]);
- videoEncoder.frameAvailable(mSurfaceTextrue);
- }
上面主要逻辑是,在数据返回的视频判断当前的录制状态,如果是正在录制,就将SurfaceTexture给到VideoEncoder进行数据的编码,如果没有录制,就跳过该帧,这样就可以实现断点续录,即录制 —>暂停录制—>继续录制,而且这样录制出来的是一个整体的视频文件。
- Camera.Parameters parameters = mCamera.getParameters();
- boolean supportFocus=true;
- boolean supportMetering=true;
- //不支持设置自定义聚焦,则使用自动聚焦,返回
- if (parameters.getMaxNumFocusAreas() <= 0) {
- supportFocus=false;
- }
- if (parameters.getMaxNumMeteringAreas() <= 0){
- supportMetering=false;
- }
- List<Camera.Area> areas = new ArrayList<Camera.Area>();
- List<Camera.Area> areas1 = new ArrayList<Camera.Area>();
- //再次进行转换
- point.x= (int) (((float)point.x)/ MyApplication.screenWidth*2000-1000);
- point.y= (int) (((float)point.y)/MyApplication.screenHeight*2000-1000);
-
- int left = point.x - 300;
- int top = point.y - 300;
- int right = point.x + 300;
- int bottom = point.y + 300;
- left = left < -1000 ? -1000 : left;
- top = top < -1000 ? -1000 : top;
- right = right > 1000 ? 1000 : right;
- bottom = bottom > 1000 ? 1000 : bottom;
- areas.add(new Camera.Area(new Rect(left, top, right, bottom), 100));
- areas1.add(new Camera.Area(new Rect(left, top, right, bottom), 100));
- if(supportFocus){
- parameters.setFocusAreas(areas);
- }
- if(supportMetering){
- parameters.setMeteringAreas(areas1);
- }
-
- try {
- mCamera.setParameters(parameters);// 部分手机 会出Exception(红米)
- mCamera.autoFocus(callback);
- } catch (Exception e) {
- e.printStackTrace();
- }
主要涉及到了一下坐标变换,因为大部分的手机的前置摄像头不支持对焦功能,所以我们不进行前置摄像头的对焦。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。