OpenGL ES显示NV21数据的方法

最近有一个需求,先对相机的预览数据进行处理,然后对处理后的nv21数据显示出来。

本人尝试了两种方法,一种是通过RenderScript转化为Bitmap再显示,一种是分离nv21数据通过openGL显示出来,结果发现使用RenderScript的方法在低端机上卡顿明显,比第二种方法低5帧。

一、RenderScript后纹理贴图

        try {
            if (yuvType == null || tempHeight != height || tempWidth != width) {
                yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
                in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
                rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
                out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
            }

            in.copyFrom(nv21);
            yuvToRgbIntrinsic.setInput(in);
            yuvToRgbIntrinsic.forEach(out);

            Bitmap mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
            out.copyTo(mBitmap);


        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.d(TAG, "nv21ToBitmap,Exception e=" + e.getMessage() + ",," + mSurfaceTexture + ",," + mTextureId + ",," + width + "X" + height);
        }        
        LogHelper.d(TAG, "onDrawFrame,time4=" + (System.currentTimeMillis() - time) + ",," + this.toString());
        if (mBitmap == null) {
            return;
        }
        //根据以上指定的参数,生成一个2D纹理
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmap, 0);
        //回收释放
        mBitmap.recycle();

二、分离yuv数据渲染

将nv21数据分为y和uv分量

            if (yBuffer==null) {
                LogHelper.d(TAG,"processPreviewCallback yBuffer==null");
                return;
            }
            yBuffer.clear();
            uvBuffer.clear();

            yBuffer.put(data, 0, mYSize);
            uvBuffer.put(data, mYSize, mYSize/2);
			

将y和uv分量转化为颜色的glsl

    public static final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform sampler2D samplerY;" +
                    "uniform sampler2D samplerU;" +
                    "uniform sampler2D samplerV;" +
                    "uniform sampler2D samplerUV;" +
                    "uniform int yuvType;" +
                    "varying vec2 tc;" +
                    "void main() {" +
                    "  vec4 c = vec4((texture2D(samplerY, tc).r - 16./255.) * 1.164);" +
                    "  vec4 U; vec4 V;" +
                    "  if (yuvType == 0){" +
                    "    U = vec4(texture2D(samplerU, tc).r - 128./255.);" +
                    "    V = vec4(texture2D(samplerV, tc).r - 128./255.);" +
                    "  } else if (yuvType == 1){" +
                    "    U = vec4(texture2D(samplerUV, tc).r - 128./255.);" +
                    "    V = vec4(texture2D(samplerUV, tc).a - 128./255.);" +
                    "  } else {" +
                    "    U = vec4(texture2D(samplerUV, tc).a - 128./255.);" +
                    "    V = vec4(texture2D(samplerUV, tc).r - 128./255.);" +
                    "  } " +
                    "  c += V * vec4(1.596, -0.813, 0, 0);" +
                    "  c += U * vec4(0, -0.392, 2.017, 0);" +
                    "  c.a = 1.0;" +
                    "  gl_FragColor = c;" +
                    "}";

代码加载

GLES20.glTexImage2D(
        GLES20.GL_TEXTURE_2D, 0,
        GLES20.GL_LUMINANCE, mWidth, mHeight, 0,
        GLES20.GL_LUMINANCE,
        GLES20.GL_UNSIGNED_BYTE, yBuffer
GLES20.glTexImage2D(
        GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE_ALPHA, width, height, 0,
        GLES20.GL_LUMINANCE_ALPHA, GLES20.GL_UNSIGNED_BYTE, uvBuffer);

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: NV12是一种非常常见的视频格式,它在媒体应用中得到广泛的使用。使用OpenGL显示NV12,通常需要经过一系列的处理步骤。 首先,需要使用第三方库或API将NV12数据解码成RGB像素数据。通常情况下,解码NV12数据需要使用硬件加速,以确保高效率和稳定性。 接着,将RGB像素数据转换成OpenGL可以处理的纹理格式,例如RGBA或BGRA。在这个过程中,开发人员需要根据设备硬件和功能需求选择合适的纹理格式。 最后,将转换后的纹理作为OpenGL渲染器的输入,并将其绑定到OpenGL对象上。将这个纹理作为图像贴到屏幕上,就能实现将NV12数据在终端中显示出来的效果。 总之,虽然OpenGL是一个非常强大、灵活和高效的图形渲染引擎,但要使用它来显示NV12数据需要先将数据解码和处理。通过这些步骤,开发人员可以实现高质量的媒体应用程序,同时提高用户体验。 ### 回答2: OpenGL可以用来显示NV12格式的视频。NV12是一种颜色空间格式,常用于视频编解码中。它是一种半平面存储的格式,也就是说,Y分量和UV分量(CbCr)被储存在不同的内存空间中,其中UV分量被采样成了半分辨率。在OpenGL中,我们可以将储存NV12格式的内存映射到一张纹理上,并使用着色器程序将其渲染到屏幕上。 具体来说,我们需要进行以下步骤: 1. 创建一张纹理 在OpenGL中,我们可以使用glGenTextures函数创建一张纹理,并使用glBindTexture将其绑定到一个纹理单元上。然后,我们可以使用glTexImage2D函数将NV12数据写入纹理中。 2. 创建着色器程序 着色器程序是OpenGL中用来处理数据的一种程序。我们可以使用GLSL(OpenGL着色器语言)编写顶点着色器和片段着色器,来处理纹理中的数据,并将其显示到屏幕上。 3. 绘制场景 最后,我们可以使用glDrawArrays或者glDrawElements函数将纹理绑定到着色器程序中,并渲染到屏幕上。具体的渲染流程可以在顶点着色器和片段着色器中进行定义。 总之,通过使用OpenGL,我们可以将NV12格式的视频显示出来,从而实现视频编解码、视频播放等功能。需要注意的是,这只是一个简单的示例,具体的实现需要根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值