通过opengl es 2.0来实现yuv(NV21)的显示

来源:互联网 发布:skype mac 编辑:程序博客网 时间:2024/05/16 11:34

 基本思路参考如下文章,用opengles2.0 来实现yuv(NV21)的显示。

 http://blog.csdn.net/fu_shuwu/article/details/72972312

public static String  VERTEX_SHADER =
        "attribute vec4 vPosition;    \n"+
                "attribute vec2 a_texCoord;   \n"+
                "varying vec2 tc;             \n"+
                "void main()                  \n"+
                "{                            \n"+
                "   gl_Position = vPosition;  \n"+
                "   tc = a_texCoord;          \n"+
                "}                            \n";

 

public static String FRAG_SHADER =
        "precision mediump float;\n"+
                "varying  vec2 tc;                      \n"+
                "uniform sampler2D SamplerY;            \n"+
                "uniform sampler2D SamplerUV;            \n"+
                "const float PI = 3.14159265;           \n"+
                "const mat3 convertMat = mat3( 1.0, 1.0, 1.0, 0.0, -0.39465, 2.03211, 1.13983, -0.58060, 0.0 );\n"+
                "void main(void)                            \n"+
                "{                                          \n"+
                "vec3 yuv;                                  \n"+
                "yuv.x = texture2D(SamplerY, tc).r;         \n"+
                "yuv.z = texture2D(SamplerUV, tc).r - 0.5;   \n"+
                "yuv.y = texture2D(SamplerUV, tc).a - 0.5;   \n"+
                "vec3 color = convertMat * yuv;             \n"+
                "vec4 mainColor = vec4(color, 1.0);         \n"+
                "gl_FragColor =mainColor;                                       \n"+
                "}                                                              \n";
//设置opengl 渲染的坐标系统,从[-1,1]
public static float squareVertices[] = {  //rotate 90
        1.0f1.0f,//rt
        1.0f, -1.0f,//rb
        -1.0f1.0f,//lt
        -1.0f, -1.0f,//lb
};
//设置纹理基本坐标
public static float coordVertices[] = {
        0.0f, 0.0f,//lb
        1.0f, 0.0f,//rb
        0.0f1.0f,//lt
        1.0f1.0f,//rt
};
// 创建纹理
private void createTexture(int width, int height, int format, int[] textureId)
{
    //创建纹理
    GLES20.glGenTextures(1, textureId, 0);
    //绑定纹理
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
    //设置纹理属性
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, format, width, height, 0, format, GLES20.GL_UNSIGNED_BYTE, null);
}
 
//GLSurface Render 子类相关部分  
private void InitShader()
{
    programHandleMain = util.createShaderProgram();
    if ( programHandleMain != -1 )
    {
  //启动纹理
       GLES20.glEnable(GLES20.GL_TEXTURE_2D);
       GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
       GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
        // 获取VertexShader变量
        aPositionMain = getShaderHandle(programHandleMain, "vPosition");
        aTexCoordMain = getShaderHandle(programHandleMain, "a_texCoord");
        // 获取FrameShader变量
        uYTextureMain = getShaderHandle(programHandleMain, "SamplerY");
        uUVTextureMain = getShaderHandle(programHandleMain, "SamplerUV");
        // 使用滤镜着色器程序
        GLES20.glUseProgram(programHandleMain);
        //给变量赋值
        GLES20.glUniform1i(uYTextureMain, 0);
        GLES20.glUniform1i(uUVTextureMain, 1);
        GLES20.glEnableVertexAttribArray(aPositionMain);
        GLES20.glEnableVertexAttribArray(aTexCoordMain);
        // 设置Vertex Shader数据
        squareVertices.position(0);
        GLES20.glVertexAttribPointer(aPositionMain, 2, GLES20.GL_FLOAT, false, 0, squareVertices);
        coordVertices.position(0);
        GLES20.glVertexAttribPointer(aTexCoordMain, 2, GLES20.GL_FLOAT, false, 0, coordVertices);
        //创建yuv纹理
        createTexture(frameWidth, frameHeight, GLES20.GL_LUMINANCE, Ytexture);
        createTexture(frameWidth >> 1, frameHeight >> 1, GLES20.GL_LUMINANCE_ALPHA, UVtexture);
    }
}
public void onDrawFrame(GL10 unused)
{
    // 重绘背景色
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    if ( yBuf != null )
    {
        //y
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, Ytexture[0]);
        GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D,
                0,
                0,
                0,
                frameWidth,
                frameHeight,
                GLES20.GL_LUMINANCE,
                GLES20.GL_UNSIGNED_BYTE,
                yBuf);
        //uv
        GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, UVtexture[0]);
        GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D,
                0,
                0,
                0,
                frameWidth >> 1,
                frameHeight >> 1,
                GLES20.GL_LUMINANCE_ALPHA,
                GLES20.GL_UNSIGNED_BYTE,
                uvBuf);
    }
    //绘制
    GLES20.glViewport(0, 0, viewWidth, viewHeight);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
public void onSurfaceCreated(GL10 unused, EGLConfig config)
{
    //设置背景的颜色为黑色
    GLES20.glClearColor(0.f, 0.f, 0.f, 1.0f);
    InitShader();
}
 
public void onSurfaceChanged(GL10 unused, int width, int height)
{
    viewWidth  = width;
    viewHeight = height;
    GLES20.glViewport(0, 0, viewWidth, viewHeight);
}
camera preview那边一旦有数据callback frame 来,设置这样一个回调接口。
public void onNewFrames(byte[] data, int length)
{
    if (  length != )
    {
        yBuf.clear();
        uvBuf.clear();
        copyYUV(data, length);;//填充camera preview数据到opengl        requestRender();//请求opengl 刷新屏幕一次
    }
}
public void copyYUV(byte[] src,int ilen)
{
    int len =(ilen<<1)/3;
    yBuf.put(src,0,len).position(0);
    uvBuf.put(src,len,len>>1).position(0);
}

 

原创粉丝点击