Android通过OpenGl Es渲染NV21格式视频

Android通过OpenGl Es渲染NV21格式视频

第一次写博客(主要是写给自己的),请各位大神多多指教!!!

提取NV21格式视频中的YUV分量

  1. YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
  2. 对于Android Camera录制视频,大多数使用的是NV21(默认格式)和NV12格式的数据
  3. NV21格式数据的排列方式是YYYYYYYYYY(w*h)vuvuvuvuvu(w*h/2)。对于NV12的格式,排列方式是YYYYYYY(w*h)uvuvuvuvuvuv(w*h/2)。

根据上面说的NV21数据排列格式,其实提取YUV分量很简单(以下代码亲自测试过)

//NV21格式的宽和高,对于Camera就是所选择的分辨率
final int size = width * height;
final byte[] y = new byte[size];
//这里注意,uv统一占Y的1/2,那么各自占1/4
final byte[] u = new byte[size/4];
final byte[] v = new byte[size/4];
//提取Y分量
System.arraycopy(data, 0, y, 0, size);
//提取vu分量
for (int i = 0,k = 0; i < size/4; i++,k += 2) {
       v[i] = data[size + k];
       u[i] =data[size + k +1];
}

根据上面提取NV21格式的YUV分量,其实提取NV12或者其他的都很简单

//提取NV12格式的YUV分量
final int size = width * height;
final byte[] y = new byte[size];
final byte[] u = new byte[size/4];
final byte[] v = new byte[size/4];
System.arraycopy(data, 0, y, 0, size);
for (int i = 0,k = 0; i < size/4; i++,k += 2) {
    u[i] = data[size + k];
    v[i] =data[size + k +1];
}

OpenGL ES进行显示

我不懂OpenGl Es,这方面现在只是在学习,所以只能在网上复制代码,感谢博主大神提供的办法:Android上使用OpenGLES2.0显示YUV数据

在这里,我把自己的使用方式做一下说明,我主要用于Android Camera数据的渲染上。


  1. 在打开Camera 预览之前,我通过调用 mGlRenderer.update(width, height),设置宽高
    2、在Camera数据回调中,分离YUV分量并且调用mGlRenderer.update(yData, uData, vData);

我的改动

1、为了实现竖屏预览效果,我修改GlProgram中的coordVertices
java
// 横屏
private static float[] coordVertices = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }
//竖屏
private static float[] coordVertices = {1.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f,};

至于原理,请看http://www.lai18.com/content/1455210.html

2、我需要用到的是全屏预览形式,就算图像拉升了也没有关系,所以需要改动update(int w, int h)方法:

  if (mScreenWidth > 0 && mScreenHeight > 0) {
         prog.createBuffers(GLProgram.squareVertices);
   }
 if (w != mVideoWidth && h != mVideoHeight) {
     this.mVideoWidth = w;
     this.mVideoHeight = h;
     int yarraySize = w * h;
     int uvarraySize = yarraySize / 4;
     synchronized (this) {
     y = ByteBuffer.allocate(yarraySize);
     u = ByteBuffer.allocate(uvarraySize);
     v = ByteBuffer.allocate(uvarraySize);
    }
}

好了,经过以上的改动,我的程序就已经可以跑起来了!!

以后还要多写写博客。写的不好,请多多指教…..

你可能感兴趣的:(android,OpenGL,es,yuv)