android openGL 预览camera/camear2
16lz
2021-01-23
//权限请求和切换摄像头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) }}
//低版本cameraclass 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以上的camearclass 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 判断手机是否支持前置摄像头
- android1.5---2.1实现js调摄像头,调Java代码
- Activity切换 窗口绘制显示
- Android 去掉窗口标题和程序全屏
- Android 之窗口小部件详解--App Widget
- android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)
- [转]Android 调用系统摄像头
- 如何将一个Activity设置成窗口的样式