代码改变世界

使用Android的OpenGL编写视频播放器

2017-03-07 20:35  jiayayao  阅读(6548)  评论(0编辑  收藏  举报

  Android自身有MediaPlayer播放器,为什么还要使用OpenGL?因为使用OpenGL可以实现更多的效果,比如对视频翻转一定角度,加任意特效,多视频合并播放等,类似“激萌”的APP应该就是这样做的;相比之下,直接调用MediaPlayer的功能就少太多了。

  OpenGL ES剔除了OpenGL中四边形和多边形的部分,即ES版本只支持三角形的绘制。使用分为三个步骤:

  • 创建GLSurfaceView组件,使用Activity来显示GLSurfaceView;
  • 为GLSurfaceView组件创建GLSurfaceView.Renderer实例,实现GLSurfaceViewRenderer类的三个接口:
// 真正绘制的函数
abstract void onDrawFrame(GL10 gl);
// 当GLSurfaceView的大小改变时回调,如横屏竖屏切换
abstract void onSurfaceChanged(GL10 gl, int width, int height);
// 当GLSurfaceView被创建时回调
abstract void onSurfaceCreated(GL10 gl, EGLConfig config);
  • 调用GLSurfaceView组件的setRenderer()方法指定Renderer对象。

  由以上三个步骤,可以编写OpenGL的渲染框架如下:

public class SampleActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // 创建一个GLSurfaceView,用于显示OpenGL绘制的图形
        GLSurfaceView glView = new GLSurfaceView(this);
        // 创建GLSurfaceView的内容绘制器
        SampleRender myRender = new SampleRender();
        // 为GLSurfaceView设置绘制器
        glView.setRenderer(myRender);
        setContentView(glView);
    }
}
public class SampleRender implements Renderer
{
    @Override
    public void onDrawFrame(GL10 gl)
    {
        // 清除屏幕缓存和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 启用顶点座标数据
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        // 启用顶点颜色数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        // 设置当前矩阵堆栈为模型堆栈,
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        // 重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl.glTranslatef(0.6f, 0.8f, -1.5f);
        gl.glRotatef(rotate, 0f, 0.1f, 0f);
        // 设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, rectDataBuffer);
        // 设置顶点的颜色数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, rectColorBuffer);
        // 根据顶点数据绘制平面图形
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        // 绘制结束
        gl.glFinish();
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

   在此渲染框架的基础上,使用MediaPlayer播放视频,调用MediaPlayer的setSurface()函数set到一个surface上。

    SurfaceTexture mSurfaceTexture = new SurfaceTexture(textureName);
    Surface mSurface = new Surface(mSurfaceTexture);
    mMediaPlayer.setSurface(mSurface);
    mMediaPlayer.setDataSource(fileName);
    mMediaPlayer.prepareAsync();

  这样,播放器播放的视频都显示到了我们设置的texture上,然后调用GLES20.glBindTexture(render.GL_TEXTURE_EXTERNAL_OES,textureName);绑定纹理,将纹理显示出来即可。剩下的就是对SurfaceTexture做伸缩,分屏,加特效图片等具体的业务了。     

  GLSurfaceView自带渲染线程,如果不使用默认的渲染线程,需要进行如下设置,之后调用requestRender()手动渲染:

setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

  自行设计定时器渲染的话,注意保证定时精度,如果精度太小而机器性能有限,可以使用多个定时器大粒度交叉渲染的方式保证30帧每秒的渲染频率。