/* * * AiyaCameraView.java * * Created by Wuwang on 2016/11/18 * Copyright © 2016年 深圳哎吖科技. All rights reserved. */ package com.aiyaapp.camera.sdk.widget; import java.nio.ByteBuffer; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Point; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.util.AttributeSet; import com.aiyaapp.camera.sdk.AiyaEffects; import com.aiyaapp.camera.sdk.base.FrameCallback; import com.aiyaapp.camera.sdk.base.ProcessCallback; import com.aiyaapp.camera.sdk.base.TrackCallback; import com.aiyaapp.camera.sdk.etest.EData; import com.aiyaapp.camera.sdk.filter.AFilter; import com.aiyaapp.camera.sdk.filter.AiyaEffectFilter; import com.aiyaapp.camera.sdk.filter.EasyGlUtils; import com.aiyaapp.camera.sdk.filter.MatrixUtils; import com.aiyaapp.camera.sdk.filter.NoFilter; /** * Description: */ @Deprecated public class AiyaCameraView extends GLSurfaceView implements GLSurfaceView.Renderer { private AiyaCamera mCamera; private AiyaEffectFilter mEffectFilter; private AFilter mShowFilter; private boolean isSetParm=false; private int dataWidth=0,dataHeight=0; private byte[][] cameraBuffer; private Queue<byte[]> mBytesQueue; private int cameraId=1; private AiyaEffects mEffect; private int width,height; private float[] SM=new float[16]; //用于绘制到屏幕上的变换矩阵 private boolean isRecord=false; //录像flag private boolean isShoot=false; //一次拍摄flag private FrameCallback mFrameCallback; //回调 private int frameCallbackWidth, frameCallbackHeight; //回调数据的宽高 private ByteBuffer[] outPutBuffer = new ByteBuffer[3]; //用于存储回调数据的buffer private float[] callbackOM=new float[16]; //用于绘制回调缩放的矩阵 private int indexOutput=0; //回调数据使用的buffer索引 //创建离屏buffer,用于最后导出数据 private int[] fFrame = new int[1]; private int[] fTexture = new int[1]; public AiyaCameraView(Context context) { this(context,null); } public AiyaCameraView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init(){ mEffect= AiyaEffects.getInstance(); setEGLContextClientVersion(2); setRenderer(this); setRenderMode(RENDERMODE_WHEN_DIRTY); setPreserveEGLContextOnPause(true); setCameraDistance(100); mCamera=new AiyaCamera(); IAiyaCamera.Config mConfig=new IAiyaCamera.Config(); mConfig.minPreviewWidth=720; mConfig.minPictureWidth=720; mConfig.rate=1.778f; mCamera.setConfig(mConfig); mEffectFilter=new AiyaEffectFilter(getResources()); mShowFilter=new NoFilter(getResources()); mBytesQueue=new ConcurrentLinkedQueue<>(); } @Override public void onResume() { super.onResume(); if(isSetParm){ open(cameraId); } } public AiyaCamera getCamera(){ return mCamera; } @Override public void onPause() { super.onPause(); mCamera.close(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { mEffectFilter.create(); if(!isSetParm){ open(cameraId); stickerInit(); } mEffectFilter.setSize(dataWidth,dataHeight); mShowFilter.create(); } private void open(final int cameraId){ mCamera.close(); mCamera.open(cameraId); mEffectFilter.setFlag(cameraId); final Point previewSize=mCamera.getPreviewSize(); dataWidth=previewSize.x; dataHeight=previewSize.y; //预览大小被更改时,回调不为空,需要重新计算最后的导出矩阵 if(mFrameCallback!=null){ setFrameCallback(frameCallbackWidth,frameCallbackHeight,mFrameCallback); } if(cameraBuffer==null){ cameraBuffer=new byte[3][dataWidth*dataHeight*4]; } for (int i=0;i<3;i++){ mCamera.addBuffer(cameraBuffer[i]); } mCamera.setOnPreviewFrameCallbackWithBuffer(new AiyaCamera.PreviewFrameCallback() { @Override public void onPreviewFrame(byte[] bytes, int width, int height) { EData.data.setCameraCallbackTime(System.currentTimeMillis()); if(isSetParm){ mBytesQueue.add(bytes); requestRender(); }else{ mCamera.addBuffer(bytes); } } }); mCamera.setPreviewTexture(mEffectFilter.getTexture()); mCamera.preview(); } public void switchCamera(){ cameraId=cameraId==0?1:0; open(cameraId); } public int getCameraId(){ return cameraId; } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { this.width=width; this.height=height; MatrixUtils.getMatrix(SM,MatrixUtils.TYPE_CENTERCROP,dataWidth,dataHeight,width,height); mShowFilter.setMatrix(SM); mShowFilter.setSize(width, height); deleteFrameBuffer(); GLES20.glGenFramebuffers(1,fFrame,0); EasyGlUtils.genTexturesWithParameter(1,fTexture,0,GLES20.GL_RGBA,dataWidth,dataHeight); } @Override public void onDrawFrame(GL10 gl) { if(isSetParm){ EData.data.setDealStartTime(System.currentTimeMillis()); mEffectFilter.draw(); //显示到屏幕上 GLES20.glViewport(0,0,width,height); mShowFilter.setMatrix(SM); mShowFilter.setTextureId(mEffectFilter.getOutputTexture()); mShowFilter.draw(); EData.data.setDealEndTime(System.currentTimeMillis()); byte[] data=mBytesQueue.poll(); if(data!=null){ mCamera.addBuffer(data); } callbackIfNeeded(); } } //需要回调,则缩放图片到指定大小,读取数据并回调 private void callbackIfNeeded() { if (mFrameCallback != null && (isRecord || isShoot)) { indexOutput = indexOutput++ >= 2 ? 0 : indexOutput; if (outPutBuffer[indexOutput] == null) { outPutBuffer[indexOutput] = ByteBuffer.allocate(frameCallbackWidth * frameCallbackHeight*4); } GLES20.glViewport(0, 0, frameCallbackWidth, frameCallbackHeight); EasyGlUtils.bindFrameTexture(fFrame[0],fTexture[0]); mShowFilter.setMatrix(callbackOM); mShowFilter.draw(); frameCallback(); isShoot = false; EasyGlUtils.unBindFrameBuffer(); mShowFilter.setMatrix(SM); } } //读取数据并回调 private void frameCallback(){ GLES20.glReadPixels(0, 0, frameCallbackWidth, frameCallbackHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, outPutBuffer[indexOutput]); mFrameCallback.onFrame(outPutBuffer[indexOutput].array(),mEffectFilter.getTexture().getTimestamp()); } public void onDestroy(){ setPreserveEGLContextOnPause(false); onPause(); } public void setFrameCallback(int width,int height,FrameCallback frameCallback){ this.frameCallbackWidth =width; this.frameCallbackHeight = height; if (frameCallbackWidth > 0 && frameCallbackHeight > 0) { if(outPutBuffer!=null){ outPutBuffer=new ByteBuffer[3]; } MatrixUtils.getMatrix(callbackOM,MatrixUtils.TYPE_CENTERCROP,dataWidth, dataHeight, frameCallbackWidth, frameCallbackHeight); MatrixUtils.flip(callbackOM,false,true); this.mFrameCallback = frameCallback; } else { this.mFrameCallback = null; } } private void deleteFrameBuffer() { GLES20.glDeleteFramebuffers(1, fFrame, 0); GLES20.glDeleteTextures(1, fTexture, 0); } public void setFairLevel(int level){ mEffect.set(AiyaEffects.SET_BEAUTY_LEVEL,level); } public void setEffect(String effect){ mEffect.setEffect(effect); } public void startRecord(){ isRecord=true; } public void stopRecord(){ isRecord=false; } public void takePhoto(){ isShoot=true; } /** * 增加自定义滤镜 * @param filter 自定义滤镜 * @param isBeforeSticker 是否增加在贴纸之前 */ public void addFilter(AFilter filter,boolean isBeforeSticker){ mEffectFilter.addFilter(filter,isBeforeSticker); } private void stickerInit(){ if(!isSetParm&&dataWidth>0&&dataHeight>0) { isSetParm = true; mEffect.set(AiyaEffects.SET_IN_WIDTH,dataWidth); mEffect.set(AiyaEffects.SET_IN_HEIGHT,dataHeight); mEffect.setProcessCallback(mcallback); mEffect.setTrackCallback(mTrackCallback); } } private ByteBuffer[] mBuffer=new ByteBuffer[3]; private int i=0; private ProcessCallback mcallback = new ProcessCallback() { @Override public void onFinished() { } }; private float[] infos=new float[20]; private TrackCallback mTrackCallback=new TrackCallback() { @Override public void onTrack(int trackCode,float[] info) { EData.data.setTrackCode(trackCode); } }; }