jeofferyli 4 tahun lalu
induk
melakukan
01e9d66b18

+ 144 - 0
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/CacheBuffer.kt

@@ -0,0 +1,144 @@
+package com.tencent.qgame.animplayer
+
+import android.opengl.GLES11Ext
+import android.opengl.GLES20
+import android.util.Log
+import com.tencent.qgame.animplayer.util.*
+import android.util.DisplayMetrics
+
+import android.view.WindowManager
+
+
+
+
+/**
+ * Date: 2022/1/11
+ * Time: 3:00 下午
+ * Author: jeoffery
+ * Description :
+ */
+class CacheBuffer {
+
+    companion object {
+        const val TAG = "CacheBuffer"
+    }
+
+    private val vertexArray = GlFloatArray()
+    private val alphaArray = GlFloatArray()
+    private val rgbArray = GlFloatArray()
+    private var shaderProgram = 0
+    private var uTextureLocation: Int = 0
+    private var aPositionLocation: Int = 0
+    private var aTextureAlphaLocation: Int = 0
+    private var aTextureRgbLocation: Int = 0
+
+    
+    // 输入纹理ID
+    private var textureId = -1
+    // FBO纹理ID
+    private var fboTextureId = -1
+    // 帧缓冲
+    private var fboFrameBuffer: Int = -1
+
+    fun setVertexArr(vertexArray: FloatArray) {
+        ALog.d(TAG, "setVertexArr fbo : vertexArray: ${vertexArray.toList()}")
+        this.vertexArray.setArray(vertexArray)
+    }
+
+    fun setTexArr(texRgbArray: FloatArray, texAlphaArray: FloatArray) {
+        val fboTexRgbArr = texRgbArray.copyOf()
+        val fboTexAlphaArr = texAlphaArray.copyOf()
+        TexCoordsUtil.rotateE(fboTexRgbArr)
+        TexCoordsUtil.rotateE(fboTexAlphaArr)
+        ALog.d(TAG, "setTexArr fbo : fboTexRgbArr: ${fboTexRgbArr.toList()}")
+        ALog.d(TAG, "setTexArr fbo : fboTexAlphaArr: ${fboTexAlphaArr.toList()}")
+        this.rgbArray.setArray(fboTexRgbArr)
+        this.alphaArray.setArray(fboTexAlphaArr)
+
+    }
+
+    /**
+     * 初始化Catch FBO
+     */
+    fun init(textureId: Int) : Int {
+        if (textureId < 1) {
+            throw RuntimeException("CacheBuffer init ERROR: input textureId = $textureId")
+            return -1
+        }
+        this.textureId = textureId
+
+        shaderProgram = ShaderUtil.createProgram(RenderConstant.VERTEX_SHADER, RenderConstant.FBO_FRAGMENT_SHADER)
+        uTextureLocation = GLES20.glGetUniformLocation(shaderProgram, "texture")
+        aPositionLocation = GLES20.glGetAttribLocation(shaderProgram, "vPosition")
+        aTextureAlphaLocation = GLES20.glGetAttribLocation(shaderProgram, "vTexCoordinateAlpha")
+        aTextureRgbLocation = GLES20.glGetAttribLocation(shaderProgram, "vTexCoordinateRgb")
+
+        // 创建纹理id
+        val textures = IntArray(1)
+        GLES20.glGenTextures(1, textures, 0)
+        checkGLError("glGenTextures mFboTextureId")
+        fboTextureId = textures[0]
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fboTextureId)
+        checkGLError("glBindTexture mFboTextureId")
+        // 配置边缘过渡参数
+        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat())
+        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR.toFloat())
+        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE.toFloat())
+        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE.toFloat())
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, GLES20.GL_NONE)
+
+        // 创建frameBuffer
+        val fbs = IntArray(1)
+        GLES20.glGenFramebuffers(1, fbs, 0)
+        fboFrameBuffer = fbs[0]
+
+        return fboTextureId
+    }
+
+    /**
+     * 根据宽高生成纹理
+     */
+    fun genCatch(width: Int, height: Int) {
+        ALog.d(TAG, "genCatch: $width x $height")
+        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboFrameBuffer)
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fboTextureId)
+        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, fboTextureId, 0)
+        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null)
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, GLES20.GL_NONE)
+        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_NONE)
+    }
+
+    /**
+     * 绘制外部纹理到FBO
+     */
+    fun draw() {
+        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboFrameBuffer)
+        checkGLError("glBindFramebuffer drawFBO")
+        GLES20.glUseProgram(shaderProgram)
+        checkGLError("glUseProgram drawFBO")
+
+        //激活指定纹理单元
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
+        checkGLError("glActiveTexture drawFBO")
+        //绑定纹理ID到纹理单元
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId)
+        checkGLError("glBindTexture drawFBO $textureId")
+        //将激活的纹理单元传递到着色器里面
+        GLES20.glUniform1i(uTextureLocation, 0)
+        checkGLError("glUniform1i drawFBO")
+        // 设置顶点坐标
+        vertexArray.setVertexAttribPointer(aPositionLocation)
+        // 设置纹理坐标
+        alphaArray.setVertexAttribPointer(aTextureAlphaLocation)
+        rgbArray.setVertexAttribPointer(aTextureRgbLocation)
+        //开始绘制
+        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
+        checkGLError("glDrawArrays drawFBO")
+
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0)
+        checkGLError("glBindTexture 0 drawFBO")
+        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0)
+        checkGLError("glBindFramebuffer 0 drawFBO")
+    }
+
+}

+ 3 - 0
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/Decoder.kt

@@ -76,8 +76,11 @@ abstract class Decoder(val player: AnimPlayer) : IAnimListener {
 
     abstract fun start()
 
+    abstract fun renderLastFrame()
+
     fun stop() {
         isStopReq = true
+        renderLastFrame()
     }
 
     fun pause() {

+ 6 - 1
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/HardDecoder.kt

@@ -73,7 +73,12 @@ class HardDecoder(player: AnimPlayer) : Decoder(player), SurfaceTexture.OnFrameA
         renderData()
     }
 
-    fun renderData() {
+    override fun renderLastFrame() {
+        ALog.d(TAG, "CacheRender renderLastFrame")
+        renderData()
+    }
+
+    private fun renderData() {
         renderThread.handler?.post {
             try {
                 glTexture?.apply {

+ 64 - 16
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/Render.kt

@@ -18,13 +18,8 @@ package com.tencent.qgame.animplayer
 import android.graphics.SurfaceTexture
 import android.opengl.GLES11Ext
 import android.opengl.GLES20
-import com.tencent.qgame.animplayer.util.GlFloatArray
-import com.tencent.qgame.animplayer.util.ShaderUtil
-import com.tencent.qgame.animplayer.util.TexCoordsUtil
-import com.tencent.qgame.animplayer.util.VertexUtil
-import java.nio.ByteBuffer
-import java.nio.ByteOrder
-import java.nio.ShortBuffer
+import android.util.Log
+import com.tencent.qgame.animplayer.util.*
 
 class Render(surfaceTexture: SurfaceTexture): IRenderListener {
 
@@ -46,24 +41,53 @@ class Render(surfaceTexture: SurfaceTexture): IRenderListener {
     private var aTextureAlphaLocation: Int = 0
     private var aTextureRgbLocation: Int = 0
 
+    private var catchTextureId = -1
+
+    private var useFbo = true
+
+    private val catchBuf by lazy { CacheBuffer() }
+
+    private val mTextureCoors by lazy { floatArrayOf(
+        0.0f, 0.0f,
+        0.0f, 1.0f,
+        1.0f, 0.0f,
+        1.0f, 1.0f
+    ) }
+
     init {
         eglUtil.start(surfaceTexture)
         initRender()
     }
 
     private fun setVertexBuf(config: AnimConfig) {
-        vertexArray.setArray(VertexUtil.create(config.width, config.height, PointRect(0, 0, config.width, config.height), vertexArray.array))
+        val fArr = VertexUtil.create(config.width, config.height, PointRect(0, 0, config.width, config.height), vertexArray.array)
+        ALog.d(CacheBuffer.TAG, "setVertexArr: ${fArr.toList()}")
+
+        if (useFbo) {
+            catchBuf.setVertexArr(fArr)
+        }
+        vertexArray.setArray(fArr)
     }
 
     private fun setTexCoords(config: AnimConfig) {
-        val alpha = TexCoordsUtil.create(config.videoWidth, config.videoHeight, config.alphaPointRect, alphaArray.array)
         val rgb = TexCoordsUtil.create(config.videoWidth, config.videoHeight, config.rgbPointRect, rgbArray.array)
-        alphaArray.setArray(alpha)
-        rgbArray.setArray(rgb)
+        val alpha = TexCoordsUtil.create(config.videoWidth, config.videoHeight, config.alphaPointRect, alphaArray.array)
+        ALog.d(CacheBuffer.TAG, "setTexArr: texRgbArray: ${rgb.toList()}")
+        ALog.d(CacheBuffer.TAG, "setTexArr: texAlphaArray: ${alpha.toList()}")
+
+        if (useFbo) {
+            catchBuf.setTexArr(rgb, alpha)
+            catchBuf.genCatch(config.width, config.height)
+            rgbArray.setArray(mTextureCoors)
+            alphaArray.setArray(mTextureCoors)
+        } else {
+            rgbArray.setArray(rgb)
+            alphaArray.setArray(alpha)
+        }
     }
 
     override fun initRender() {
-        shaderProgram = ShaderUtil.createProgram(RenderConstant.VERTEX_SHADER, RenderConstant.FRAGMENT_SHADER)
+        shaderProgram = ShaderUtil.createProgram(RenderConstant.VERTEX_SHADER, if (useFbo) RenderConstant.FRAGMENT_SHADER else RenderConstant.FRAGMENT_SHADER_OES)
         uTextureLocation = GLES20.glGetUniformLocation(shaderProgram, "texture")
         aPositionLocation = GLES20.glGetAttribLocation(shaderProgram, "vPosition")
         aTextureAlphaLocation = GLES20.glGetAttribLocation(shaderProgram, "vTexCoordinateAlpha")
@@ -75,15 +99,29 @@ class Render(surfaceTexture: SurfaceTexture): IRenderListener {
         GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
         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)
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_NONE)
+
+        if (useFbo) {
+            catchTextureId = catchBuf.init(genTexture[0])
+        }
     }
 
     override fun renderFrame() {
         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
         GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
         if (surfaceSizeChanged && surfaceWidth>0 && surfaceHeight>0) {
+            ALog.d("renderFrame","surfaceWidth : $surfaceWidth, surfaceHeight : $surfaceHeight")
             surfaceSizeChanged = false
             GLES20.glViewport(0,0, surfaceWidth, surfaceHeight)
+            if (useFbo) {
+                catchBuf.genCatch(surfaceWidth, surfaceHeight)
+            }
         }
+
+        if (useFbo) {
+            catchBuf.draw()
+        }
+
         draw()
     }
 
@@ -114,7 +152,7 @@ class Render(surfaceTexture: SurfaceTexture): IRenderListener {
      * 显示区域大小变化
      */
     override fun updateViewPort(width: Int, height: Int) {
-        if (width <=0 || height <=0) return
+        if (width <= 0 || height <= 0) return
         surfaceSizeChanged = true
         surfaceWidth = width
         surfaceHeight = height
@@ -133,13 +171,17 @@ class Render(surfaceTexture: SurfaceTexture): IRenderListener {
 
     private fun draw() {
         GLES20.glUseProgram(shaderProgram)
-        // 设置顶点坐标
-        vertexArray.setVertexAttribPointer(aPositionLocation)
         // 绑定纹理
         GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
-        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, genTexture[0])
+        if (useFbo) {
+            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, catchTextureId)
+        } else {
+            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, genTexture[0])
+        }
         GLES20.glUniform1i(uTextureLocation, 0)
 
+        // 设置顶点坐标
+        vertexArray.setVertexAttribPointer(aPositionLocation)
         // 设置纹理坐标
         // alpha 通道坐标
         alphaArray.setVertexAttribPointer(aTextureAlphaLocation)
@@ -148,6 +190,12 @@ class Render(surfaceTexture: SurfaceTexture): IRenderListener {
 
         // draw
         GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
+
+        if (useFbo) {
+            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, GLES20.GL_NONE)
+        } else {
+            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_NONE)
+        }
     }
 
 }

+ 26 - 1
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/RenderConstant.kt

@@ -29,7 +29,32 @@ object RenderConstant {
             "    v_TexCoordinateRgb = vec2(vTexCoordinateRgb.x, vTexCoordinateRgb.y);\n" +
             "    gl_Position = vPosition;\n" +
             "}"
+
+    const val FRAGMENT_SHADER_OES = "#extension GL_OES_EGL_image_external : require\n" +
+            "precision mediump float;\n" +
+            "uniform samplerExternalOES texture;\n" +
+            "varying vec2 v_TexCoordinateAlpha;\n" +
+            "varying vec2 v_TexCoordinateRgb;\n" +
+            "\n" +
+            "void main () {\n" +
+            "    vec4 alphaColor = texture2D(texture, v_TexCoordinateAlpha);\n" +
+            "    vec4 rgbColor = texture2D(texture, v_TexCoordinateRgb);\n" +
+            "    gl_FragColor = vec4(rgbColor.r, rgbColor.g, rgbColor.b, alphaColor);\n" +
+            "}"
+
     const val FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" +
+            "precision mediump float;\n" +
+            "uniform sampler2D texture;\n" +
+            "varying vec2 v_TexCoordinateAlpha;\n" +
+            "varying vec2 v_TexCoordinateRgb;\n" +
+            "\n" +
+            "void main () {\n" +
+            "    vec4 alphaColor = texture2D(texture, v_TexCoordinateAlpha);\n" +
+            "    vec4 rgbColor = texture2D(texture, v_TexCoordinateRgb);\n" +
+            "    gl_FragColor = vec4(rgbColor.r, rgbColor.g, rgbColor.b, alphaColor);\n" +
+            "}"
+
+    const val FBO_FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" +
             "precision mediump float;\n" +
             "uniform samplerExternalOES texture;\n" +
             "varying vec2 v_TexCoordinateAlpha;\n" +
@@ -38,6 +63,6 @@ object RenderConstant {
             "void main () {\n" +
             "    vec4 alphaColor = texture2D(texture, v_TexCoordinateAlpha);\n" +
             "    vec4 rgbColor = texture2D(texture, v_TexCoordinateRgb);\n" +
-            "    gl_FragColor = vec4(rgbColor.r, rgbColor.g, rgbColor.b, alphaColor.r);\n" +
+            "    gl_FragColor = vec4(rgbColor.r, rgbColor.g, rgbColor.b, alphaColor);\n" +
             "}"
 }

+ 20 - 0
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/util/GlTools.kt

@@ -0,0 +1,20 @@
+package com.tencent.qgame.animplayer.util
+
+import android.opengl.GLES20
+
+/**
+ * Date: 2022/1/12
+ * Time: 1:58 下午
+ * Author: jeoffery
+ * Description :
+ */
+
+/**
+ * 检查GL错误
+ */
+fun checkGLError(extMsg: String? = "none") {
+    var error: Int
+    if (GLES20.glGetError().also { error = it } != GLES20.GL_NO_ERROR) {
+        ALog.e("CheckGLError", "extMsg: $extMsg, >> ERROR: $error <<")
+    }
+}

+ 30 - 0
Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/util/TexCoordsUtil.kt

@@ -81,4 +81,34 @@ object TexCoordsUtil {
         return array
     }
 
+    /**
+     * 顺时针180度
+     */
+    fun rotateE(array: FloatArray): FloatArray {
+        val tx = array[0]
+        val ty = array[1]
+
+        // 1->0
+        array[0] = array[2]
+        array[1] = array[3]
+
+        // 0->1
+        array[2] = tx
+        array[3] = ty
+
+        val tx2 = array[4]
+        val ty2 = array[5]
+
+        // 3->2
+        array[4] = array[6]
+        array[5] = array[7]
+
+        // 2->3
+        array[6] = tx2
+        array[7] = ty2
+
+
+        return array
+    }
+
 }

+ 9 - 1
Android/PlayerProj/app/src/main/java/com/tencent/qgame/playerproj/player/AnimSimpleDemoActivity.kt

@@ -21,6 +21,7 @@ import android.os.Bundle
 import android.os.Environment
 import android.os.Handler
 import android.os.Looper
+import android.util.DisplayMetrics
 import android.util.Log
 import android.view.View
 import com.tencent.qgame.animplayer.AnimConfig
@@ -65,6 +66,13 @@ class AnimSimpleDemoActivity : Activity(), IAnimListener {
         setContentView(R.layout.activity_anim_simple_demo)
         // 文件加载完成后会调用init方法
         loadFile()
+
+        val dm = DisplayMetrics()
+        windowManager.defaultDisplay.getMetrics(dm)
+        val screenWidth = dm.widthPixels
+        val screenHeight = dm.heightPixels
+
+        ALog.d(TAG, "screenWidth: $screenWidth, screenHeight: $screenHeight")
     }
 
     private fun init() {
@@ -153,7 +161,7 @@ class AnimSimpleDemoActivity : Activity(), IAnimListener {
     override fun onPause() {
         super.onPause()
         // 页面切换是停止播放
-        animView.stopPlay()
+//        animView.stopPlay()
     }
 
 

+ 1 - 1
Android/PlayerProj/app/src/main/java/com/tencent/qgame/playerproj/player/AnimVapxDemoActivity.kt

@@ -228,7 +228,7 @@ class AnimVapxDemoActivity : Activity(), IAnimListener {
 
 
     private fun initLog() {
-        ALog.isDebug = false
+        ALog.isDebug = true
         ALog.log = object : IALog {
             override fun i(tag: String, msg: String) {
                 Log.i(tag, msg)