第十八节、关于硬解与软解
硬件解码视频(MediaCodec)、软件解码视频(FFMpeg)
硬件解码视频:
我们知道AVPacket中存放的是视频的压缩数据,在获取到AVPacket后,直接将AVPacket中的data传递到上层交给MediaCodec,
MediaCodec完成解码交给opengl es
软件解码视频:
软件解码需要FFMpeg解码出AVFrame后,将AVFrame中的data(yuv数据)传递到上层交给opengl es
opengl es渲染yuv纹理
vertex_base.glsl
attribute vec4 av_Position;
//定点坐标,应用传入
attribute vec2 af_Position;
//采样纹理坐标,应用传入
varying vec2 v_texPo;
//把获取的纹理坐标传入fragment里面
void main() {
v_texPo = af_Position;
gl_Position = av_Position;
}
片元着色器
fragment_yuv.glsl
precision mediump float;
varying vec2 v_texPo;
uniform sampler2D sampler_y;
uniform sampler2D sampler_u;
uniform sampler2D sampler_v;
void main() {
float y,u,v;
y = texture2D(sampler_y,v_texPo).x;
u = texture2D(sampler_u,v_texPo).x- 128./255.;
v = texture2D(sampler_v,v_texPo).x- 128./255.;
vec3 rgb;
rgb.r = y + 1.403 * v;
rgb.g = y - 0.344 * u - 0.714 * v;
rgb.b = y + 1.770 * u;
//黑白滤镜
//float gray = rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114;
//gl_FragColor = vec4(gray, gray, gray, 1);
//原始效果
gl_FragColor = vec4(rgb,1);
}
【第十八节、关于硬解与软解】这种情况下,在FFMpeg解码获取到AVFrame中的yuv数据后,直接传递给surfaceView即可
public void setFrameData(int w, int h, byte[] y, byte[] u, byte[] v)
{
if(wlGlRender != null)
{
wlGlRender.setFrameData(w, h, y, u, v);
requestRender();
}
}
opengl es渲染MediaCodec解码后的数据 顶点着色器
vertex_base.glsl
attribute vec4 av_Position;
//定点坐标,应用传入
attribute vec2 af_Position;
//采样纹理坐标,应用传入
varying vec2 v_texPo;
//把获取的纹理坐标传入fragment里面
void main() {
v_texPo = af_Position;
gl_Position = av_Position;
}
片元着色器
fragment_mediacodec.glsl
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 v_texPo;
uniform samplerExternalOES sTexture;
void main() {
gl_FragColor=texture2D(sTexture, v_texPo);
//lowp vec4 textureColor = texture2D(sTexture, v_texPo);
//float gray = textureColor.r * 0.299 + textureColor.g * 0.587 + textureColor.b * 0.114;
//gl_FragColor = vec4(gray, gray, gray, textureColor.w);
}
在编写Render的时候注意实现SurfaceTexture.OnFrameAvailableListener接口
/**
* Callback interface for being notified that a new stream frame is available.
*/
public interface OnFrameAvailableListener {
void onFrameAvailable(SurfaceTexture surfaceTexture);
}
就是当surface中有可用的数据的时候,就会被回调,我们在回调中通知
surfaceView,进行刷新(调用surfaceView的requestRender())
wlGlRender.setWlOnRenderRefreshListener(new WlOnRenderRefreshListener() {
@Override
public void onRefresh() {
requestRender();
}
});
推荐阅读
- 一个人的碎碎念
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- Shell-Bash变量与运算符
- 清明,是追思、是传承、是感恩。
- 牛人进化+|牛人进化+ 按自己的意愿过一生
- 七老修复好敏感、角质层薄、红血丝
- 华为旁!大社区、地铁新盘,佳兆业城市广场五期!
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 螃蟹和这些食物同吃,轻则腹泻、重则中毒!要小心哦~
- 八、「料理风云」