You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Android MediaCodec解码后的帧显示到GLSurfaceView上

实现步骤

1. 基础环境初始化

  • 自定义GLSurfaceView,同时实现GLSurfaceView.Renderer和SurfaceTexture.OnFrameAvailableListener接口
  • 在Renderer的onSurfaceCreated回调中完成以下操作:
    • 创建OES类型外部纹理,记为纹理IDmTextureID
    • 用mTextureID初始化SurfaceTexture实例,设置帧可用监听
    • 初始化OpenGL着色器程序、顶点数组、矩阵变量等绘图资源
    • 用初始化好的SurfaceTexture创建Surface对象,作为MediaCodec的解码输出目标

2. MediaCodec解码配置调整

官方测试类默认是把解码输出直接输出到普通Surface或者缓存,你需要修改解码器配置逻辑:
在配置MediaCodec的时候,把你上面创建的Surface对象传入configure方法的第二个参数,示意代码如下:

MediaCodec decoder = MediaCodec.createDecoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
// 填入你的H264流相关配置,比如sps、pps、帧率等参数
decoder.configure(format, yourCreatedSurface, null, 0);
decoder.start();

3. 帧渲染联动逻辑

  • 当SurfaceTexture.OnFrameAvailableListener的onFrameAvailable回调触发时,调用GLSurfaceView.requestRender()请求刷新画面
  • 在Renderer的onDrawFrame回调中,先调用surfaceTexture.updateTexImage()更新纹理内容,再调用你提供的drawFrame方法完成绘制
  • 你提供的drawFrame方法本身逻辑是正确的,不需要改动,只要保证用到的着色器符合OES纹理要求即可:
    顶点着色器示例:
    attribute vec4 aPosition;
    attribute vec4 aTextureCoord;
    varying vec2 vTextureCoord;
    uniform mat4 uMVPMatrix;
    uniform mat4 uSTMatrix;
    void main() {
      gl_Position = uMVPMatrix * aPosition;
      vTextureCoord = (uSTMatrix * aTextureCoord).xy;
    }
    
    片段着色器示例:
    #extension GL_OES_EGL_image_external : require
    precision mediump float;
    varying vec2 vTextureCoord;
    uniform samplerExternalOES sTexture;
    void main() {
      gl_FragColor = texture2D(sTexture, vTextureCoord);
    }
    

你提供的drawFrame参考代码如下:

public void drawFrame(SurfaceTexture st) {
    checkGlError("onDrawFrame start");
    st.getTransformMatrix(mSTMatrix);
    GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
    GLES20.glUseProgram(mProgram);
    checkGlError("glUseProgram");
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
    mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
    GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
    checkGlError("glVertexAttribPointer maPosition");
    GLES20.glEnableVertexAttribArray(maPositionHandle);
    checkGlError("glEnableVertexAttribArray maPositionHandle");
    mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
    GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
    checkGlError("glVertexAttribPointer maTextureHandle");
    GLES20.glEnableVertexAttribArray(maTextureHandle);
    checkGlError("glEnableVertexAttribArray maTextureHandle");
    Matrix.setIdentityM(mMVPMatrix, 0);
    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    checkGlError("glDrawArrays");
    GLES20.glFinish();
}

常见注意点

  • OES纹理必须在GL线程中创建,不能在主线程直接创建
  • 如果出现画面旋转/拉伸,只需要调整mMVPMatrix矩阵即可,不需要修改解码逻辑
  • 解码结束后要按顺序释放MediaCodec、SurfaceTexture、GL纹理资源

内容的提问来源于stack exchange,提问作者Ali Has

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:21:00