android openGL 预览camera/camear2

//权限请求和切换摄像头
class CameraActivity : Activity() {
    private var surface: CodecSurface? = null
    private var btn: Button? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.CAMERA
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            initView()
        } else {
            ActivityCompat.requestPermissions(
                this, arrayOf(
                    Manifest.permission.CAMERA,
                    Manifest.permission.RECORD_AUDIO,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                ), 0
            )
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        initView()
    }

    private var curCameraId: Int = 0
    private fun initView() {
        setContentView(R.layout.activity_codec)
        btn = findViewById
//界面刷新和设置渲染模式
public class CodecSurface constructor(context: Context, att: AttributeSet?) :
    GLSurfaceView(context, att),SurfaceTexture.OnFrameAvailableListener{
    constructor(context: Context) : this(context, null)

    private var renderer: CodecRender? = null

    init {
        setEGLContextClientVersion(2)
        renderer = CodecRender(this)
        renderer!!.setFrameListener(this)
        renderer
        preserveEGLContextOnPause=true
        setRenderer(renderer)
        renderMode = RENDERMODE_WHEN_DIRTY
    }

    public fun changeCameraId(id: Int) {
        renderer!!.setCameraId(id)
    }

    public fun release() {
        renderer!!.release()
    }

    override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
        requestRender()
    }

}
//camera的选用和绘画操作
class CodecRender(val surface: CodecSurface) : GLSurfaceView.Renderer {
    private val TAG: String = "CodecRender"
    var textureId: Int = 0;
    private var filter: OesFilter? = null
    var surfaceTexture: SurfaceTexture? = null
    private var cameraId: Int = 0;
    private var listener: SurfaceTexture.OnFrameAvailableListener? = null

    init {
        filter = OesFilter()
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
        surfaceTexture!!.updateTexImage()
        if (cameraUtil!!.isOpenFinish) {
            filter!!.drawFrame()
        }
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height);
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        textureId = filter!!.createTextureId()
        surfaceTexture = SurfaceTexture(textureId)
        surfaceTexture!!.setOnFrameAvailableListener {
            surface!!.requestRender()
        }
        cameraUtil!!.setTexture(surfaceTexture!!)
        setCameraId(cameraId);
        filter!!.setTextureId(textureId)
        filter!!.create(cameraId)
    }

    public fun setCameraId(id: Int) {
        cameraId = id;
        filter!!.setCoodData(cameraId)
        cameraUtil!!.open(cameraId.toString())
    }

    private var cameraUtil: CameraUtil? = null
    public fun release() {
        surfaceTexture!!.setOnFrameAvailableListener(null)
        surfaceTexture!!.release()
        surfaceTexture = null
        cameraUtil!!.close()
    }

    public fun setFrameListener(listener: SurfaceTexture.OnFrameAvailableListener) {
        this.listener = listener;
    }

    init {
        cameraUtil = CameraUtil(surface.context)
    }
}
//低版本camera
class CameraUtil(val context: Context) : CameraState {
    private val TAG: String = "CameraUtil"
    private var textureView: SurfaceTexture? = null
    private var myCamera: Camera? = null
    private var holder: SurfaceHolder? = null
    private var isOpenSuccess = true
    public fun setTexture(view: SurfaceTexture) {
        textureView = view;
    }

    public fun setDiaPlay(holder: SurfaceHolder) {
        this.holder = holder
    }

    public fun open(cameraId: String) {
        try {
            isOpenSuccess = false
            close()
            myCamera = Camera.open(cameraId.toInt())
            val mParameters = myCamera!!.getParameters();
            //设置将保存的图片旋转90°(竖着拍摄的时候)
            var PreviewWidth = 0
            var PreviewHeight = 0
            val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager;//获取窗口的管理器
            val display = wm.defaultDisplay;//获得窗口里面的屏幕
            val parameters  = myCamera!!.getParameters();
            // 选择合适的预览尺寸
            val sizeList = mParameters.getSupportedPreviewSizes();
            if (sizeList.size > 1) {
                val itor= sizeList.iterator();
                while (itor.hasNext()) {
                    val cur = itor.next();
                    if (cur.width >= PreviewWidth
                        && cur.height >= PreviewHeight) {
                        PreviewWidth = cur.width;
                        PreviewHeight = cur.height;
                        break;
                    }
                }
            }
            LogUtil.e("-->width=$PreviewWidth height=$PreviewHeight")
            mParameters.setPreviewSize(PreviewWidth, PreviewHeight); //获得摄像区域的大小
            mParameters.set("jpeg-quality", 85);//设置照片质量
            mParameters.setRotation(90);
            myCamera!!.setParameters(mParameters)//如果出现异常则为参数问题,逐个删减
            myCamera!!.setDisplayOrientation(90)
            myCamera!!.setPreviewTexture(textureView)
            myCamera!!.setPreviewCallback(object : Camera.PreviewCallback {
                override fun onPreviewFrame(data: ByteArray?, camera: Camera?) {
                    try {
                        isOpenSuccess = true
                        camera!!.addCallbackBuffer(data)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            })
            myCamera!!.startPreview()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    public fun close() {
        myCamera?.setPreviewCallback(null)
        myCamera?.stopPreview()
        myCamera?.release()
        myCamera = null
    }

    override fun isOpenFinish(): Boolean {
        return isOpenSuccess
    }
}
//5.0以上的camear
class Camera2Util constructor(private val context: Context) : CameraState {
    private val TAG: String = "CameraUtil"
    private var cameraDevice: CameraDevice? = null
    private var cameraManager: CameraManager? = null
    private var cameraBuild: CaptureRequest.Builder? = null
    private var isOpenSuccess = true
    private var stateCallback: CameraDevice.StateCallback = object : CameraDevice.StateCallback() {
        override fun onOpened(camera: CameraDevice) {
            cameraDevice = camera
            try {
                val surface: Surface = Surface(textureView)
                cameraBuild = cameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
                cameraBuild!!.set(
                    CaptureRequest.CONTROL_AE_MODE,
                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH
                )
                cameraBuild!!.set(
                    CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
                )
                cameraBuild!!.addTarget(surface)
                cameraDevice!!.createCaptureSession(listOf(surface), sessionCallback, camearHandler)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onDisconnected(camera: CameraDevice) {
        }

        override fun onError(camera: CameraDevice, error: Int) {
            LogUtil.e(TAG, "error=$error")
        }
    }
    private var sessionCallback: CameraCaptureSession.StateCallback = object :
        CameraCaptureSession.StateCallback() {
        override fun onConfigureFailed(session: CameraCaptureSession) {
        }

        override fun onConfigured(session: CameraCaptureSession) {
            isOpenSuccess = true
            session.setRepeatingRequest(cameraBuild!!.build(), captureCallback, camearHandler)
        }

    }
    private var captureCallback: CameraCaptureSession.CaptureCallback = object :
        CameraCaptureSession.CaptureCallback() {
        override fun onCaptureCompleted(
            session: CameraCaptureSession,
            request: CaptureRequest,
            result: TotalCaptureResult
        ) {
            super.onCaptureCompleted(session, request, result)
        }

        override fun onCaptureFailed(
            session: CameraCaptureSession,
            request: CaptureRequest,
            failure: CaptureFailure
        ) {
            super.onCaptureFailed(session, request, failure)
        }

        override fun onCaptureProgressed(
            session: CameraCaptureSession,
            request: CaptureRequest,
            partialResult: CaptureResult
        ) {
            super.onCaptureProgressed(session, request, partialResult)
        }
    }
    private val camearHandler = object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
        }
    }

    init {
        cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
    }

    public fun open(cameraId: String) {
        try {
            isOpenSuccess = false
            if (ActivityCompat.checkSelfPermission(
                    context,
                    Manifest.permission.CAMERA
                ) == PackageManager.PERMISSION_GRANTED
            ) {
                cameraDevice?.close()
                cameraManager!!.openCamera(cameraId, stateCallback, camearHandler)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private var textureView: SurfaceTexture? = null;
    public fun setTexture(view: SurfaceTexture) {
        textureView = view;
    }

    public fun close() {
        cameraDevice!!.close()
    }

    override fun isOpenFinish(): Boolean {
        return isOpenSuccess
    }
}
//预览摄像头数据,后续与其他滤镜混合
class OesFilter {
    private val TAG: String = "OesFilter"
    private var positionFloat: FloatBuffer? = null
    private var coodFloat: FloatBuffer? = null
    private var glHPosition: Int = 0
    private var glHCoordinate: Int = 0
    private var glHTexture: Int = 0
    private var mHCoord: Int = 0
    private var mHMatrix: Int = 0
    private var coordinate: FloatArray? = null
    private var textureId: Int = 0
    private var programsId: Int = 0
    private val vertexPosition = floatArrayOf(
        -1.0f, 1.0f,
        -1.0f, -1.0f,
        1.0f, 1.0f,
        1.0f, -1.0f
    )

    public fun create(cameraId: Int) {
        setCoodData(cameraId)
        val frag_id = createShader(fragmentShaderCode, GLES20.GL_FRAGMENT_SHADER)
        val vertex_id = createShader(vertexShaderCode, GLES20.GL_VERTEX_SHADER)
        programsId = GLES20.glCreateProgram();
        GLES20.glAttachShader(programsId, frag_id)
        GLES20.glAttachShader(programsId, vertex_id)
        GLES20.glLinkProgram(programsId)
        val linkState = IntArray(1)
        GLES20.glGetProgramiv(programsId, GLES20.GL_LINK_STATUS, linkState, 0)
        LogUtil.e(TAG, "state=${linkState[0]}   programsId=$programsId")
        if (linkState[0] == 0) {
            LogUtil.e(
                TAG,
                "Could not link program: "
            )
            LogUtil.e(
                TAG,
                GLES20.glGetProgramInfoLog(programsId)
            )
            GLES20.glDeleteProgram(programsId)
            programsId = 0;
        }
    }

    private fun userProgram(programsId: Int) {
        GLES20.glUseProgram(programsId)
        var bb: ByteBuffer = ByteBuffer.allocateDirect(vertexPosition.size * 4)
        bb.order(ByteOrder.nativeOrder())
        positionFloat = bb.asFloatBuffer()
        positionFloat!!.put(vertexPosition)
        positionFloat!!.position(0)

        var cbb: ByteBuffer = ByteBuffer.allocateDirect(coordinate!!.size * 4)
        cbb.order(ByteOrder.nativeOrder())
        coodFloat = cbb.asFloatBuffer()
        coodFloat!!.put(coordinate)
        coodFloat!!.position(0)
        glHPosition = GLES20.glGetAttribLocation(programsId, "vPosition")
        glHCoordinate = GLES20.glGetAttribLocation(programsId, "vTextureCoordinate")
        glHTexture = GLES20.glGetUniformLocation(programsId, "vTexture")
        mHCoord = GLES20.glGetAttribLocation(programsId, "vCoord")
        mHMatrix = GLES20.glGetUniformLocation(programsId, "vMatrix")
    }

    public fun createTextureId(): Int {
        val texture = IntArray(1)
        GLES20.glGenTextures(1, texture, 0)
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0])
        GLES20.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER,
            GL10.GL_LINEAR.toFloat()
        )
        GLES20.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER,
            GL10.GL_LINEAR.toFloat()
        )
        GLES20.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_S,
            GL10.GL_CLAMP_TO_EDGE.toFloat()
        )
        GLES20.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_T,
            GL10.GL_CLAMP_TO_EDGE.toFloat()
        )
        return texture[0]
    }

    public fun setTextureId(id: Int) {
        textureId = id
    }

    private fun createShader(str: String, style: Int): Int {
        val shader: Int = GLES20.glCreateShader(style);
        GLES20.glShaderSource(shader, str)
        GLES20.glCompileShader(shader)
        val state = IntArray(1)
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, state, 0)
        if (state[0] == 0) {
            LogUtil.e(TAG, "Could not compile shader " + shader + ":");
            LogUtil.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
            GLES20.glDeleteShader(shader)
            throw IllegalStateException("Could not compile shader")
        }
        return shader;
    }

    private val vertexShaderCode = "attribute vec4 vPosition;" +
            "attribute vec2 vCoord;" +
            "varying vec2 vTextureCoordinate;" +
            "uniform mat4 vMatrix;" +
            "void main() {" +
            "  gl_Position = vMatrix*vPosition;" +
            "vTextureCoordinate = vCoord;" +
            "}"

    private val fragmentShaderCode = "#extension GL_OES_EGL_image_external : require" +
            "precision mediump float;" +
            "varying vec2 vTextureCoordinate;" +
            "uniform samplerExternalOES vTexture;" +
            "void main() {" +
            "    gl_FragColor = texture2D(vTexture, vTextureCoordinate);" +
            "}"
    private val matrix: FloatArray = LogUtil.getOriginalMatrix()
    public fun drawFrame() {
        userProgram(programsId)
        GLES20.glEnableVertexAttribArray(glHPosition)
        GLES20.glEnableVertexAttribArray(mHCoord)
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId)
        GLES20.glUniform1i(glHTexture, 0)
        GLES20.glVertexAttribPointer(glHPosition, 2, GLES20.GL_FLOAT, false, 0, positionFloat)
        GLES20.glVertexAttribPointer(mHCoord, 2, GLES20.GL_FLOAT, false, 0, coodFloat)
        GLES20.glUniformMatrix4fv(mHMatrix, 1, false, matrix, 0)
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
        GLES20.glDisableVertexAttribArray(glHPosition)
        GLES20.glDisableVertexAttribArray(mHCoord)
    }

    public fun setCoodData(cameraId: Int) {
        coordinate = if (cameraId == 0) {//后置摄像头
            floatArrayOf(
                0.0f, 1.0f,
                1.0f, 1.0f,
                0.0f, 0.0f,
                1.0f, 0.0f
            )
        } else {//前置摄像头
            floatArrayOf(
                1.0f, 1.0f,
                0.0f, 1.0f,
                1.0f, 0.0f,
                0.0f, 0.0f
            )
        }
    }
}

 

你可能感兴趣的:(android)