视频实时OpenGL渲染并保存渲染结果合成MP4

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hongdameng/article/details/77679438
    这是一个能实时播放多个视频、图片在一个GL容器里的控件,通过这个控件,可以在一个view中绘制固定坐标、自由随机滚动的视频和图片,然后从该view中截取数据帧,实时保存成YUV格式的文件,最后合成MP4。

一、OpenGL 渲染视频模块

1.结构简介
a. GLEngine是一个全局控制GL绘制各个子view的类,结构图如下:
GLEngine结构图

b.Java层封装后的View控件结构如下:
这里写图片描述

    GLEngine直接提供接口给上层调用,通过该对象实现创建、绘制、释放子view,和获取GL绘制结果,以及释放整个GL。
    MyGLView是对底层的封装,提供方法给Android直接使用。

2.工作原理

    底层GLEngine实例化后,会返回一个long型的对象句柄给上层的MyGLView,MyGLView对象就可以通过该句柄实现对底层GLEngine的引用。
    MyGLView对象通过addStaticView()、addScrollView()方法调用底层对应的createStaticView()、createScrollView()函数,拿到子view long型的句柄,然提供给使用MyGLView的开发者保存下来,开发者就可以通过这些子view的句柄来绘制GL里面的各个子view。

二、视频编解码模块

  1. 结构简介
    a. GetRgbFremer
    MP4解码器,能从MP4文件中取出RGB帧,类结构图如下:
    这里写图片描述

    b.RgbToYuv420P
    对RGB帧转换成YUV420P帧的转换,并保存为文件,结构图如下:
    这里写图片描述

    c.H264Encoder
    能把YUV编码成H264,结构图如下:
    这里写图片描述

    d.Mp4Muxer
    视频复合器,能把AAC音频流和H264视频流合成MP4,结构图如下:
    这里写图片描述

三、视频编解码和OpenGL渲染整合使用指南

  1. 首选创建多个线程解码多个视频,获取到的帧数据缓存起来。
    /**
     * 解码线程1
     */
    private FFGetRgbFramer mFFGetRgbFramer = new FFGetRgbFramer(mInMp4Path, mVideoWidth1, mVideoHeight1);
    private byte[] mVideoData1;
    private void decodeThread1() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                while (mRun) {
                    if (mVideoData1 == null) {
                        mVideoData1 = mFFGetRgbFramer.getNextRgbFrame();
                        if (mVideoData1 == null) {
                            break;
                        }
                    }
                }
            }
        }).start();
    }

……
……
  1. 在SurfaceView的Renderer下的回调onSurfaceChanged下初始化MyGLView,并添加子view,拿到句柄保存下来,在回调onDrawFrame下把调用MyGLView对象的drawFrame()方法,并且把要绘制的子view对应的句柄和RGB帧数据传进去,该方法返回获取到的GL绘制结果,然后使用FFRgbToYuv420p保存成YUV文件,以备后续合成MP4使用。例如:
GLSurfaceView.Renderer mRenderer = new GLSurfaceView.Renderer() {

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            mGLView.initGL();
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            mGLView.onChangeGL(width,height);
            mStaticHandle1 = mGLView.addStaticView(0, 0, mVideoWidth1, mVideoHeight1, width, height);
            ……
            ……
            mHandles.clear();
            mHandles.add(mStaticHandle1);
            mHandles.add(mStaticHandle2);
            ……
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            if (mVideoData1 != null && mVideoData2 != null) {
                List<byte[]> byteList = new ArrayList<>();
                byteList.add(mVideoData1);
                ……
                mVideoData1 = null;
                ……
                byte[] rgbResultByte = mGLView.drawFrame(mHandles,byteList);

                if (rgbResultByte != null) {
                    mFFRgbToYuv420p.pushRgbData(rgbResultByte);
                }
            }
        }
    };

最后再分别利用H264Encoder、Mp4Muxer合成MP4。

OpenGL实现部分源码地址:https://github.com/hondameng/OpenGLES2Test

展开阅读全文

没有更多推荐了,返回首页