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

114 篇文章 1 订阅
25 篇文章 0 订阅

 基本思路参考如下文章,用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);
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 Android 中使用 OpenGL ES 2.0 和 C/C++ 实现使用 MediaCodec 解码 MP4 视频格式并将其转换为 RGB 图像,需要完成以下步骤: 1. 创建 Android 应用程序并引入必要的库文件 在 Android Studio 中创建一个新的 Android 应用程序,并在 build.gradle 文件中添加以下库文件的引用: ``` // For decoding MP4 video format implementation 'com.google.android.exoplayer:exoplayer-core:2.X.X' implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X' // For using OpenGL ES in Android implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' // For using C/C++ in Android implementation 'com.android.support:support-compat:28.0.0' implementation 'com.android.support:support-core-utils:28.0.0' implementation 'com.android.support:support-annotations:28.0.0' implementation 'com.android.support:support-core-ui:28.0.0' // For using MediaCodec in Android implementation 'com.android.support:support-media-compat:28.0.0' ``` 2. 创建 OpenGL 上下文并加载着色器程序 在 C/C++ 中使用 OpenGL ES 2.0,需要创建一个 OpenGL 上下文并加载着色器程序。可以使用 Android 提供的 NativeActivity 类来创建一个带有 OpenGL 上下文的活动,并使用 GLES20.glCreateProgram() 和 GLES20.glAttachShader() 等方法来加载着色器程序。 3. 使用 MediaCodec 解码 MP4 视频格式并将其转换为 RGB 图像 可以使用 Android 提供的 MediaCodec 类来解码 MP4 视频格式,并使用 GLES20.glTexImage2D() 和 GLES20.glTexSubImage2D() 等方法将解码后的视频帧转换为 RGB 图像。需要注意的是,由于 MediaCodec 解码后的视频帧是 YUV 格式的,需要进行 YUV 到 RGB 的转换。 4. 在 OpenGL 中渲染 RGB 图像 将转换后的 RGB 图像渲染到 OpenGL 中,可以使用 GLES20.glDrawArrays() 和 GLES20.glEnableVertexAttribArray() 等方法。需要注意的是,由于 RGB 图像的数据格式是 GL_UNSIGNED_BYTE,需要使用 GLES20.glPixelStorei() 方法设置像素存储模式。 以上是大致的代码实现步骤,实际上还有很多细节需要注意,比如使用 OpenGL ES 2.0 的版本号、将 YUV 转换为 RGB 的算法等。如果需要深入了解,可以查看 Android 官方文档和相关的开源库代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值