Android中OpenGL展示视频内容和预览摄像头数据用的纹理ID都是GLES11Ext.GL_TEXTURE_EXTERNAL_OES,所以可以直接按照上一篇的预览Camera基础之上,继承OesFilter,共用同一个GlSurfaceView,根据新生成的纹理ID创建SurfaceTexture绘画即可。

class CodecRender(val surface: CodecSurface) : GLSurfaceView.Renderer {    private val TAG: String = "CodecRender"    var textureId: Int = 0;    private var filter: OesFilter? = null    private var videoFilter: VideoFilter? = null    var surfaceTexture: SurfaceTexture? = null    private var cameraId: Int = 0;    private var listener: SurfaceTexture.OnFrameAvailableListener? = null    private var screenWidth: Int = 0    private var screenHight: Int = 0    private var videoWidth: Int = 400    private var videoHeight: Int = 400    init {        filter = OesFilter()        videoFilter = VideoFilter(surface)//将surface传入方便刷新和引用context获取本地视频数据,setOnFrameAvailableListener如果不在创建后设置会出现无法监听的问题    }    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()        GLES20.glViewport(0, 0, screenWidth, screenHight);        if (cameraUtil!!.isOpenFinish) {            filter!!.drawFrame()        }        GLES20.glViewport(0, screenHight - videoHeight, videoWidth, videoHeight);//将视频置于左上角        //绘制视频        videoFilter!!.updateTexImage()        videoFilter!!.drawFrame()    }    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {        screenWidth = width        screenHight = height        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()        //绘制视频        videoFilter!!.createTextureView()    }    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()        videoFilter?.close()    }    public fun setFrameListener(listener: SurfaceTexture.OnFrameAvailableListener) {        this.listener = listener;    }    init {        cameraUtil = CameraUtil(surface.context)    }}
public open 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    public var coordinate: FloatArray = floatArrayOf(        0.0f, 1.0f,        1.0f, 1.0f,        0.0f, 0.0f,        1.0f, 0.0f    )    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 open fun create() {        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\r\n" +            "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            )        }    }}
class VideoFilter(val surface: CodecSurface) : OesFilter() {    private var mediaPlayer: MediaPlayer? = null    private var surfaceTexture: SurfaceTexture? = null    init {        mediaPlayer = MediaPlayer()    }    fun createTextureView() {        create()        val id = createTextureId()        surfaceTexture = SurfaceTexture(id)        coordinate = floatArrayOf(            0.0f, 0.0f,            0.0f, 1.0f,            1.0f, 0.0f,            1.0f, 1.0f        )        setTextureId(id)        surfaceTexture!!.setOnFrameAvailableListener {            surface.requestRender()        }        play()    }    fun updateTexImage() {        surfaceTexture!!.updateTexImage()    }    private fun play() {        try {            mediaPlayer!!.setSurface(Surface(surfaceTexture))            var fd = FileDescriptor()            mediaPlayer!!.reset()            mediaPlayer!!.isLooping = true            var afd = surface.resources.openRawResourceFd(R.raw.test);            mediaPlayer!!.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length)            mediaPlayer!!.setOnPreparedListener { mp ->                mp.start()            }            mediaPlayer!!.prepareAsync()        } catch (e: Exception) {            e.printStackTrace()        }    }    public fun close() {        Thread {            try {                mediaPlayer?.let {                    if (it.isPlaying) {                        it.pause()                        it.stop()                    }                    it.release()                }                mediaPlayer = null            } catch (e: Exception) {            }        }.start()    }}

 

更多相关文章

  1. android支持的视频音频硬解码器
  2. Android(安卓)VideoView简单播放视频
  3. Android(安卓)仿秒拍,微信录制短视频
  4. android_camera
  5. 【备忘】2016最新独家老罗Android视频教程第二季 下载
  6. Android(安卓)关于获取摄像头帧数据
  7. Android(安卓)VideoView简单播放视频
  8. android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)
  9. 【Android(安卓)开源系列】之视频处理框架

随机推荐

  1. Android导出一个JAR库/Android如何将程序
  2. Android开发之旅:活动与任务
  3. Android开发规范--编码规范/性能优化/UI
  4. Android核心分析 之十-------Android(安
  5. 中国电信已加盟Android阵营
  6. Android面试系列文章2018之Android部分之
  7. 移动互联网的新宠:Android之缤纷世界
  8. Android扫盲篇
  9. 不要被虚张声势的 Android(安卓)忽悠了
  10. 在 Android(安卓)上使用协程(三) :Real Work