课程介绍
在学习了前面章节OpenGL基础知识后,读者应该具备了复杂界面特效、图片高效处理的开发能力。接下来的章节主要转向Android视频应用开发中的OpenGL ES部分。
一. 视频播放器搭建
1. 视图容器
界面视图容器依旧使用GLSurfaceView,绘制方式是RENDERMODE_CONTINUOUSLY持续绘制的模式(课程演示,减少框架部分,相应的有不必要的性能损耗)。
2. 必要框架
因为本节涉及外部文件读取,所以会涉及到外部存储读写权限的获取、文件URI的解析、媒体文件数据解析,该部分内容非本节重点,因此详情见工程代码。
3. 媒体播放器
要驱动视频进行播放,需要借助到系统的媒体播放器MediaPlayer,它的相关方法如下:
setDataSource:设置数据源,这里直接传入文件路径
isLooping:是否循环播放
prepare:进入准备状态
start:开始播放
pause:暂停
stop:停止
release:释放资源
具体的API可以参见官网,生命周期流程图如下:
mediaplayer_state_diagram
播放器生命周期的逻辑处理,详见工程代码。这里重点讲解下如何将MediaPlayer和GLSurfaceView进行绑定使用,从而可以在GL上进行视频渲染播放。
①. 绑定纹理ID
// 1. 创建纹理ID
val textureIds = ......
// 2. 创建SurfaceTexture、Surface,并绑定到MediaPlayer上,接收画面驱动回调
surfaceTexture = SurfaceTexture(textureIds[0])
surfaceTexture!!.setOnFrameAvailableListener(this)
val surface = Surface(surfaceTexture)
mediaPlayer.setSurface(surface)
这里分为以下几步:
创建纹理ID,用于GL渲染
通过纹理ID创建一个SurfaceTexture对象
通过SurfaceTexture对象创建一个Surface对象
将Surface传入MediaPlayer中
通过以上4步,将纹理ID和MediaPlayer进行关联。
②. 接收画面解析完毕的回调
当视频帧解析完毕时,MediaPlayer会通过层层的接口调用到SurfaceTexture的onFrameAvailable接口,这时候我们可以标志下画面已经解析完毕。
/**
* MediaPlayer有新的画面帧刷新时,通过SurfaceTexture的onFrameAvailable接口进行回调
*/
override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
updateSurface = true
}
③. 驱动画面更新纹理ID
override fun onDrawFrame(glUnused: GL10) {
if (updateSurface) {
// 当有画面帧解析完毕时,驱动SurfaceTexture更新纹理ID到最近一帧解析完的画面,并且驱动底层去解析下一帧画面
surfaceTexture!!.updateTexImage()
updateSurface = false</