您的位置:首页 > 运维架构

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

2017-08-29 16:14 2731 查看
这是一个能实时播放多个视频、图片在一个GL容器里的控件,通过这个控件,可以在一个view中绘制固定坐标、自由随机滚动的视频和图片,然后从该view中截取数据帧,实时保存成YUV格式的文件,最后合成MP4。


一、OpenGL 渲染视频模块

1.结构简介

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



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。


二、视频编解码模块

结构简介

a. GetRgbFremer

MP4解码器,能从MP4文件中取出RGB帧,类结构图如下:



b.RgbToYuv420P

对RGB帧转换成YUV420P帧的转换,并保存为文件,结构图如下:



c.H264Encoder

能把YUV编码成H264,结构图如下:



d.Mp4Muxer

视频复合器,能把AAC音频流和H264视频流合成MP4,结构图如下:



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

首选创建多个线程解码多个视频,获取到的帧数据缓存起来。

/**
* 解码线程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();
}

……
……


在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opengl 视频
相关文章推荐