package com.laifeng.sopcastsdk.video; import android.annotation.TargetApi; import android.graphics.SurfaceTexture; import android.opengl.GLES11Ext; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.os.Looper; import com.laifeng.sopcastsdk.camera.CameraHolder; import com.laifeng.sopcastsdk.camera.CameraListener; import com.laifeng.sopcastsdk.camera.CameraUtils; import com.laifeng.sopcastsdk.camera.exception.CameraDisabledException; import com.laifeng.sopcastsdk.camera.exception.CameraHardwareException; import com.laifeng.sopcastsdk.camera.exception.CameraNotSupportException; import com.laifeng.sopcastsdk.camera.exception.NoCameraException; import com.laifeng.sopcastsdk.configuration.VideoConfiguration; import com.laifeng.sopcastsdk.entity.Watermark; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import com.laifeng.sopcastsdk.mediacodec.VideoMediaCodec; import com.laifeng.sopcastsdk.utils.WeakHandler; import com.laifeng.sopcastsdk.video.effect.Effect; import com.laifeng.sopcastsdk.video.effect.NullEffect; /** * @Title: MyRenderer * @Package com.laifeng.sopcastsdk.video * @Description: * @Author Jim * @Date 16/9/14 * @Time 下午2:06 * @Version */ @TargetApi(18) public class MyRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener{ private int mSurfaceTextureId = -1; private SurfaceTexture mSurfaceTexture; private Watermark mWatermark; private RenderScreen mRenderScreen; private RenderSrfTex mRenderSrfTex; private CameraListener mCameraOpenListener; private WeakHandler mHandler = new WeakHandler(Looper.getMainLooper()); private GLSurfaceView mView; private boolean isCameraOpen; private Effect mEffect; private int mEffectTextureId; private VideoConfiguration mVideoConfiguration; private boolean updateSurface = false; private final float[] mTexMtx = GlUtil.createIdentityMtx(); private int mVideoWidth; private int mVideoHeight; public MyRenderer(GLSurfaceView view) { mView = view; mEffect = new NullEffect(mView.getContext()); } public void setCameraOpenListener(CameraListener cameraOpenListener) { this.mCameraOpenListener = cameraOpenListener; } public void setVideoConfiguration(VideoConfiguration videoConfiguration) { mVideoConfiguration = videoConfiguration; mVideoWidth = VideoMediaCodec.getVideoSize(mVideoConfiguration.width); mVideoHeight = VideoMediaCodec.getVideoSize(mVideoConfiguration.height); if(mRenderScreen != null) { mRenderScreen.setVideoSize(mVideoWidth, mVideoHeight); } } public void setRecorder(MyRecorder recorder) { synchronized(this) { if (recorder != null) { mRenderSrfTex = new RenderSrfTex(mEffectTextureId, recorder); mRenderSrfTex.setVideoSize(mVideoWidth, mVideoHeight); if(mWatermark != null) { mRenderSrfTex.setWatermark(mWatermark); } } else { mRenderSrfTex = null; } } } @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { synchronized(this) { updateSurface = true; } mView.requestRender(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { initSurfaceTexture(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { startCameraPreview(); if(isCameraOpen) { if (mRenderScreen == null) { initScreenTexture(); } mRenderScreen.setSreenSize(width, height); if (mVideoConfiguration != null) { mRenderScreen.setVideoSize(mVideoWidth, mVideoHeight); } if (mWatermark != null) { mRenderScreen.setWatermark(mWatermark); } } } @Override public void onDrawFrame(GL10 gl) { synchronized(this) { if (updateSurface) { mSurfaceTexture.updateTexImage(); mSurfaceTexture.getTransformMatrix(mTexMtx); updateSurface = false; } } mEffect.draw(mTexMtx); if(mRenderScreen != null) { mRenderScreen.draw(); } if (mRenderSrfTex != null) { mRenderSrfTex.draw(); } } private void initSurfaceTexture() { int[] textures = new int[1]; GLES20.glGenTextures(1, textures, 0); mSurfaceTextureId = textures[0]; mSurfaceTexture = new SurfaceTexture(mSurfaceTextureId); mSurfaceTexture.setOnFrameAvailableListener(this); GLES20.glDisable(GLES20.GL_DEPTH_TEST); GLES20.glDisable(GLES20.GL_CULL_FACE); GLES20.glDisable(GLES20.GL_BLEND); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mSurfaceTextureId); GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 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); } private void initScreenTexture() { mEffect.setTextureId(mSurfaceTextureId); mEffect.prepare(); mEffectTextureId = mEffect.getEffertedTextureId(); mRenderScreen = new RenderScreen(mEffectTextureId); } private void startCameraPreview() { try { CameraUtils.checkCameraService(mView.getContext()); } catch (CameraDisabledException e) { postOpenCameraError(CameraListener.CAMERA_DISABLED); e.printStackTrace(); return; } catch (NoCameraException e) { postOpenCameraError(CameraListener.NO_CAMERA); e.printStackTrace(); return; } CameraHolder.State state = CameraHolder.instance().getState(); CameraHolder.instance().setSurfaceTexture(mSurfaceTexture); if (state != CameraHolder.State.PREVIEW) { try { CameraHolder.instance().openCamera(); CameraHolder.instance().startPreview(); if(mCameraOpenListener != null) { mHandler.post(new Runnable() { @Override public void run() { mCameraOpenListener.onOpenSuccess(); } }); } isCameraOpen = true; } catch (CameraHardwareException e) { e.printStackTrace(); postOpenCameraError(CameraListener.CAMERA_OPEN_FAILED); } catch (CameraNotSupportException e) { e.printStackTrace(); postOpenCameraError(CameraListener.CAMERA_NOT_SUPPORT); } } } private void postOpenCameraError(final int error) { if(mCameraOpenListener != null) { mHandler.post(new Runnable() { @Override public void run() { if(mCameraOpenListener != null) { mCameraOpenListener.onOpenFail(error); } } }); } } public boolean isCameraOpen() { return isCameraOpen; } public void setWatermark(Watermark watermark) { mWatermark = watermark; if(mRenderScreen != null) { mRenderScreen.setWatermark(watermark); } if(mRenderSrfTex != null) { mRenderSrfTex.setWatermark(watermark); } } public void setEffect(Effect effect) { mEffect.release(); mEffect = effect; effect.setTextureId(mSurfaceTextureId); effect.prepare(); mEffectTextureId = effect.getEffertedTextureId(); if(mRenderScreen != null) { mRenderScreen.setTextureId(mEffectTextureId); } if(mRenderSrfTex != null) { mRenderSrfTex.setTextureId(mEffectTextureId); } } }