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

时间:2023-03-09 16:35:31
使用Android的OpenGL编写视频播放器

  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帧每秒的渲染频率。