glsurfaceview播放视频怎么实现?(跟着这几步轻松搞定)

吉云

今天来聊聊用GLSurfaceView播视频的事儿。平时咱们用安卓播视频,要么直接扔个VideoView控件上去,要么就是MediaPlayer配个SurfaceView或者TextureView,简单方便。但有时候,就想搞点特殊的,比如想在视频上加些OpenGL的特效啥的,这时候SurfaceView或者TextureView就不太够用,得请出GLSurfaceView这大神。

为啥要折腾GLSurfaceView

主要还是为控制。普通的播放控件,位置、大小甚至画面内容都给你框死,想自己画点东西上去,或者做些滤镜、变形之类的效果,基本没戏。GLSurfaceView就不一样,它本质上就是一块能用OpenGL ES来画图的画布。视频的每一帧,咱可以把它当成一张纹理(Texture),用OpenGL画到这块画布上。这样一来,画面怎么画、画之前加点啥料,就都是咱说算。

glsurfaceview播放视频怎么实现?(跟着这几步轻松搞定)

开始动手

第一步:准备好画布和画笔

先得有个GLSurfaceView。布局文件里放一个,或者代码里new一个都行。然后,关键是得给它配个Renderer。这Renderer是个接口,里面有三个方法要我们实现:onSurfaceCreatedonSurfaceChangedonDrawFrame。简单说,就是画布创建好时、画布大小变时、以及每一帧要画图时,系统会分别喊我们去干活。

第二步:准备好视频源

视频播放还是得靠MediaPlayer老哥。创建一个MediaPlayer实例。然后告诉它视频文件在哪,比如SD卡里的某个路径,或者网络上的地址也行。就是干这个的。设置好之后,别忘调用或者prepareAsync()让它准备一下,解码器啥的都得就位。

第三步:搭桥,把视频接到OpenGL

glsurfaceview播放视频怎么实现?(跟着这几步轻松搞定)

这是最关键的一步。普通的SurfaceView或者TextureView,可以直接通过*(surfaceHolder)或者*(surface)把画面输出过去。但GLSurfaceView不一样,它自己管理OpenGL的渲染,不能直接这么塞。咋办?

这里就得用到一个中间人:SurfaceTexture。这玩意儿挺神的,它可以接收来自MediaPlayer的图像流,并且把这些图像流转成OpenGL能用的纹理。

具体操作大概是这样:

  • RendereronSurfaceCreated方法里,创建一个OpenGL纹理ID。
  • 用这个纹理ID创建一个SurfaceTexture对象。surfaceTexture = new SurfaceTexture(textureId)
  • glsurfaceview播放视频怎么实现?(跟着这几步轻松搞定)

  • 这个SurfaceTexture内部有个Surface,通过new Surface(surfaceTexture)可以把它拿出来。
  • 把这个Surface设置给MediaPlayer*(surface)

这样,MediaPlayer解码出来的视频帧就会源源不断地流向SurfaceTexture

第四步:在OpenGL里画出来

桥搭好,数据也流过来,一步就是在RendereronDrawFrame方法里把视频帧画到GLSurfaceView上。

glsurfaceview播放视频怎么实现?(跟着这几步轻松搞定)

每次onDrawFrame被调用时:

  • 先调用一下。这一步是让SurfaceTexture去抓取最新的视频帧,更新到它关联的那个OpenGL纹理上。
  • 然后就是标准的OpenGL绘制流程:设置视口、清屏、使用我们准备好的shader程序、绑定那个包含视频帧的纹理、设置顶点坐标和纹理坐标、调用glDrawArrays或者glDrawElements把它画出来。

这里可能还需要处理一下纹理坐标的变换,因为SurfaceTexture输出的纹理可能需要翻转或者旋转才能正确显示,可以用*(mtx)拿到变换矩阵,传给顶点着色器去处理。

glsurfaceview播放视频怎么实现?(跟着这几步轻松搞定)

收尾

基本上,上面几步搞定,GLSurfaceView就能播放视频。实际做起来还有不少细节要注意,比如线程问题(MediaPlayer的操作最好别放UI线程,SurfaceTexture的操作要在OpenGL线程),资源释放(播放完或者Activity销毁,MediaPlayerSurfaceTexture、OpenGL资源都要记得释放干净),还有OpenGL的着色器代码也得自己写。

总结一下,用GLSurfaceView播视频,比直接用TextureView要麻烦不少,得多写不少OpenGL相关的代码。但好处就是自由度高,能在视频上玩出花来。如果只是简单播个视频,那还是用老老实实用TextureView或者SurfaceView,省心。要是想搞点特效,那这番折腾就是值得的。

好,这回的实践记录就到这儿,希望能给同样想折腾的朋友一点参考。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]