之前曾经写过用SurfaceView,TextureView+MediaPlayer 播放视频,和 ffmpeg avi解码后SurfaceView播放视频,今天再给大家来一篇openGL ES+MediaPlayer来播放视频。。。。当年也曾呆过camera开发组近一年时间,可惜那时候没写博客的意识,没能给自己给大家留下多少干货分享。。。
上个效果图吧:
这里写图片描述
用openGL着色器实现黑白(灰度图)效果。
即 0.299,0.587,0.114 CRT中转灰度的模型
这里写图片描述
下面看具体实现的逻辑:
如果你曾用openGL实现过贴图,那么就容易理解多了。和图片不同的是,视频需要不断地刷新,每当有新的一帧来时,我们都应该更新纹理,然后重新绘制。用openGL播放视频就是把视频贴到屏幕上。
对openGL不熟的同学先看这里:学openGL必知道的图形学知识
1.先写顶点着色器和片段着色器(我的习惯是这样,你也可以后边根据需要再写这个)
顶点着色器:
attribute vec4 aPosition;//顶点位置
attribute vec4 aTexCoord;//S T 纹理坐标
varying vec2 vTexCoord;
uniform mat4 uMatrix;
uniform mat4 uSTMatrix;
void main() {
vTexCoord = (uSTMatrix * aTexCoord).xy;
gl_Position = uMatrix*aPosition;
}
片段着色器:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 vTexCoord;
uniform samplerExternalOES sTexture;
void main() {
gl_FragColor=texture2D(sTexture, vTexCoord);
}
samplerExternalOES代替贴图片时的sampler2D,作用就是和surfaceTexture配合进行纹理更新和格式转换
2.MediaPlayer的输出
在GLVideoRenderer的构造函数中初始化MediaPlayer:
mediaPlayer=new MediaPlayer();
try{
mediaPlayer.setDataSource(context, Uri.parse(videoPath));
}catch (IOException e){
e.printStackTrace();
}
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(true);
mediaPlayer.setOnVideoSizeChangedListener(this);
onSurfaceCreated函数中使用SurfaceTexture来设置MediaPlayer的输出
我们要用SurfaceTexture 创建一个Surface,然后将这个Surface作为MediaPlayer的输出表面。
SurfaceTexture的主要作用就是,从视频流和相机数据流获取新一帧的数据,获取新数据调用的方法是updateTexImage。
需要注意的是MediaPlayer的输出往往不是RGB格式(一般是YUV),而GLSurfaceView需要RGB格式才能正常显示。
所以我们先在onSurfaceCreated中将生成纹理的代码改成这样:
textureId = textures[0];
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
ShaderUtils.checkGlError("ws-------glBindTexture mTextureID");
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES11Ext.GL_TEXTURE_EXTERNAL_OES的用处是什么?