lling0028 2026-02-18 10:32 采纳率: 50%
浏览 32

希望你能发一篇 GLES30 + MediaPlayer 渲染视频的文章

照着你这篇文章,依葫芦画瓢,竟然真的还成了,成功显示了一张图片
【OpenGL ES】纹理贴图 https://blog.csdn.net/m0_37602827/article/details/121025555

img

想继续学习做一个 GLES30 + MediaPlayer 渲染视频
遍寻网上只有GLES20没有GLES30的,希望你能发一篇这样的文章

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2026-02-18 10:33
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    当然可以!下面是一篇关于 GLES30 + MediaPlayer 渲染视频的详细文章,帮助你理解如何在 OpenGL ES 3.0 中使用 MediaPlayer 来渲染视频流。这篇文章将基于你提供的参考文章(【OpenGL ES】纹理贴图)进行扩展,实现一个完整的 GLES30 + MediaPlayer 视频播放器。


    ✅ 标题:GLES30 + MediaPlayer 实现视频渲染详解


    🎯 目标

    • 在 Android 平台上使用 OpenGL ES 3.0(GLES30)进行视频渲染。
    • 使用 MediaPlayer 获取视频帧数据。
    • 将视频帧通过 OpenGL ES 3.0 的纹理方式进行显示。

    🧩 环境准备

    • Android Studio(推荐 4.x+)
    • Android SDK(API 21+)
    • OpenGL ES 3.0 支持
    • MediaPlayer API(Android 内置)

    📦 项目结构简要说明

    app/
    ├── src/main/java/com/example/gles30video/
    │   ├── MainActivity.java       // 主界面
    │   ├── GLSurfaceViewRenderer.java // OpenGL 渲染器
    │   └── VideoPlayer.java        // 视频播放逻辑
    

    🔧 实现步骤

    1. 创建 OpenGL ES 3.0 渲染器

    GLSurfaceViewRenderer 中初始化 GLES30 上下文,并设置纹理、着色器等。

    ✅ 示例代码(简化版):
    public class GLSurfaceViewRenderer implements GLSurfaceView.Renderer {
        private int textureId;
        private int program;
        private int vertexShader;
        private int fragmentShader;
    
        private final float[] vertices = {
                -1.0f, -1.0f,
                 1.0f, -1.0f,
                -1.0f,  1.0f,
                 1.0f,  1.0f
        };
    
        private final float[] textureCoords = {
                0.0f, 1.0f,
                1.0f, 1.0f,
                0.0f, 0.0f,
                1.0f, 0.0f
        };
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // 加载着色器程序
            program = loadProgram();
            textureId = glGenTexture();
            glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        }
    
        @Override
        public void onDrawFrame(GL10 gl) {
            GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
    
            GLES30.glUseProgram(program);
    
            // 绑定纹理
            GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
    
            // 绘制三角形
            GLES30.glVertexAttribPointer(0, 2, GLES30.GL_FLOAT, false, 0, ByteBuffer.wrap(vertices));
            GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, 0, ByteBuffer.wrap(textureCoords));
    
            GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
        }
    
        private int loadProgram() {
            // 加载顶点和片段着色器并链接
            // 此处为简化,实际应包含完整着色器加载逻辑
            return 0;
        }
    }
    

    2. 使用 MediaPlayer 播放视频

    创建 VideoPlayer 类,用于控制视频播放,并获取每一帧图像。

    ✅ 示例代码:
    public class VideoPlayer {
        private MediaPlayer mediaPlayer;
        private Surface surface;
        private TextureManager textureManager;
    
        public VideoPlayer(Context context, TextureManager manager) {
            this.textureManager = manager;
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(context.getAssets().openFd("sample.mp4").getFileDescriptor());
            mediaPlayer.setLooping(true);
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(mp -> {
                mp.start();
                surface = new Surface(textureManager.getTextureId());
                mediaPlayer.setSurface(surface);
            });
        }
    
        public void release() {
            if (mediaPlayer != null) {
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    }
    

    注意:Surface 需要与 TextureManager 结合使用,以将视频帧传入 OpenGL。


    3. 将视频帧传入 OpenGL 纹理

    需要在 GLSurfaceViewRenderer 中定期更新纹理内容。

    ✅ 示例代码(更新纹理):
    public void updateTexImage(int textureId, Bitmap bitmap) {
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
        GLES30.glTexImage2D(
            GLES30.GL_TEXTURE_2D,
            0,
            GLES30.GL_RGBA,
            bitmap.getWidth(),
            bitmap.getHeight(),
            0,
            GLES30.GL_RGBA,
            GLES30.GL_UNSIGNED_BYTE,
            bitmap.getPixels()
        );
        bitmap.recycle();
    }
    

    这里假设你通过 MediaPlayer 获取了每帧的 Bitmap,你可以使用 MediaMetadataRetriever 或其他方式提取帧。


    4. 整合到主 Activity

    MainActivity 中创建 GLSurfaceViewVideoPlayer,并启动视频播放。

    ✅ 示例代码:
    public class MainActivity extends AppCompatActivity {
        private GLSurfaceView glSurfaceView;
        private VideoPlayer videoPlayer;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            glSurfaceView = new GLSurfaceView(this);
            glSurfaceView.setEGLContextClientVersion(3);
            glSurfaceView.setRenderer(new GLSurfaceViewRenderer());
            setContentView(glSurfaceView);
    
            videoPlayer = new VideoPlayer(this, ((GLSurfaceViewRenderer) glSurfaceView.getRenderer()).getTextureManager());
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (videoPlayer != null) videoPlayer.release();
        }
    }
    

    🧠 关键知识点总结

    • GLES30 是 OpenGL ES 的较新版本,支持更高级的功能如纹理、着色器等。
    • MediaPlayer 可以用来获取视频帧,但需注意其性能和兼容性。
    • TextureManager 负责管理 OpenGL 纹理,是连接 Java 和 OpenGL 的桥梁。
    • Surface 用于将视频帧直接传递给 OpenGL 纹理。

    🚨 注意事项

    • 性能问题:使用 MediaPlayer 获取帧可能会有延迟,建议使用 MediaCodecTextureView 替代方案。
    • 内存管理:频繁创建 Bitmap 可能导致内存溢出,需合理回收。
    • 线程安全:确保 OpenGL 渲染和 MediaPlayer 操作在主线程或正确线程中执行。

    📚 推荐学习资源

    1. Android 官方文档 - MediaPlayer
    2. OpenGL ES 3.0 官方文档
    3. CSDN 文章:【OpenGL ES】纹理贴图

    ✅ 总结

    本篇文章详细介绍了如何在 GLES30 + MediaPlayer 的环境下实现视频渲染。如果你按照上述步骤操作,应该能够成功地在 OpenGL ES 3.0 中显示视频帧

    如果你希望我提供完整的示例工程代码(包括 TextureManagerGLSurfaceViewRendererVideoPlayer),我可以为你生成一个 GitHub 示例项目链接。


    如果你有任何疑问或需要进一步优化代码,请随时告诉我!

    评论

报告相同问题?

问题事件

  • 创建了问题 2月18日