最近有一个需求,先对相机的预览数据进行处理,然后对处理后的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);