第十八节、关于硬解与软解

硬件解码视频(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();
            }
        });

你可能感兴趣的:(第十八节、关于硬解与软解)