通过opengl来实现yuv的显示

来源:互联网 发布:2017音乐软件市场份额 编辑:程序博客网 时间:2024/05/17 18:49

文章转载自:http://blog.csdn.net/eastlhu/article/details/9382431

// OpenGL ES 2.0 code  #include "Shader.vert"  #include "Shader.frag"    #include <jni.h>  #include <android/log.h>    #include <GLES2/gl2.h>  #include <GLES2/gl2ext.h>    #include <stdio.h>  #include <stdlib.h>  #include <math.h>    enum {      ATTRIB_VERTEX,      ATTRIB_TEXTURE,  };    static GLuint g_texYId;  static GLuint g_texUId;  static GLuint g_texVId;  static GLuint simpleProgram;    static char *              g_buffer = NULL;  static int                 g_width = 0;  static int                 g_height = 0;      static void checkGlError(const char* op)   {      GLint error;      for (error = glGetError(); error; error = glGetError())       {          log("error::after %s() glError (0x%x)\n", op, error);      }  }    static GLuint bindTexture(GLuint texture, const char *buffer, GLuint w , GLuint h)  {  //  GLuint texture;  //  glGenTextures ( 1, &texture );      checkGlError("glGenTextures");      glBindTexture ( GL_TEXTURE_2D, texture );      checkGlError("glBindTexture");      glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer);      checkGlError("glTexImage2D");      glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );      checkGlError("glTexParameteri");      glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );      checkGlError("glTexParameteri");      glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );      checkGlError("glTexParameteri");      glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );      checkGlError("glTexParameteri");      //glBindTexture(GL_TEXTURE_2D, 0);        return texture;  }    static void renderFrame()  {  #if 0      // Galaxy Nexus 4.2.2      static GLfloat squareVertices[] = {          -1.0f, -1.0f,          1.0f, -1.0f,          -1.0f,  1.0f,          1.0f,  1.0f,      };        static GLfloat coordVertices[] = {          0.0f, 1.0f,          1.0f, 1.0f,          0.0f,  0.0f,          1.0f,  0.0f,      };  #else   // HUAWEIG510-0010 4.1.1      static GLfloat squareVertices[] = {          0.0f, 0.0f,          1.0f, 0.0f,          0.0f,  1.0f,          1.0f,  1.0f,      };        static GLfloat coordVertices[] = {              -1.0f, 1.0f,              1.0f, 1.0f,              -1.0f,  -1.0f,              1.0f,  -1.0f,      };  #endif        glClearColor(0.5f, 0.5f, 0.5f, 1);      checkGlError("glClearColor");      glClear(GL_COLOR_BUFFER_BIT);      checkGlError("glClear");      //PRINTF("setsampler %d %d %d", g_texYId, g_texUId, g_texVId);      GLint tex_y = glGetUniformLocation(simpleProgram, "SamplerY");      checkGlError("glGetUniformLocation");      GLint tex_u = glGetUniformLocation(simpleProgram, "SamplerU");      checkGlError("glGetUniformLocation");      GLint tex_v = glGetUniformLocation(simpleProgram, "SamplerV");      checkGlError("glGetUniformLocation");          glBindAttribLocation(simpleProgram, ATTRIB_VERTEX, "vPosition");      checkGlError("glBindAttribLocation");      glBindAttribLocation(simpleProgram, ATTRIB_TEXTURE, "a_texCoord");      checkGlError("glBindAttribLocation");        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);      checkGlError("glVertexAttribPointer");      glEnableVertexAttribArray(ATTRIB_VERTEX);      checkGlError("glEnableVertexAttribArray");        glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, coordVertices);      checkGlError("glVertexAttribPointer");      glEnableVertexAttribArray(ATTRIB_TEXTURE);      checkGlError("glEnableVertexAttribArray");        glActiveTexture(GL_TEXTURE0);      checkGlError("glActiveTexture");      glBindTexture(GL_TEXTURE_2D, g_texYId);      checkGlError("glBindTexture");      glUniform1i(tex_y, 0);      checkGlError("glUniform1i");        glActiveTexture(GL_TEXTURE1);      checkGlError("glActiveTexture");      glBindTexture(GL_TEXTURE_2D, g_texUId);      checkGlError("glBindTexture");      glUniform1i(tex_u, 1);      checkGlError("glUniform1i");        glActiveTexture(GL_TEXTURE2);      checkGlError("glActiveTexture");      glBindTexture(GL_TEXTURE_2D, g_texVId);      checkGlError("glBindTexture");      glUniform1i(tex_v, 2);      checkGlError("glUniform1i");        //glEnable(GL_TEXTURE_2D);      //checkGlError("glEnable");      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);      checkGlError("glDrawArrays");  }    static GLuint buildShader(const char* source, GLenum shaderType)   {      GLuint shaderHandle = glCreateShader(shaderType);        if (shaderHandle)      {          glShaderSource(shaderHandle, 1, &source, 0);          glCompileShader(shaderHandle);            GLint compiled = 0;          glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compiled);          if (!compiled)          {              GLint infoLen = 0;              glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &infoLen);              if (infoLen)              {                  char* buf = (char*) malloc(infoLen);                  if (buf)                  {                      glGetShaderInfoLog(shaderHandle, infoLen, NULL, buf);                      log_easy("error::Could not compile shader %d:\n%s\n", shaderType, buf);                      free(buf);                  }                  glDeleteShader(shaderHandle);                  shaderHandle = 0;              }          }        }            return shaderHandle;  }    static GLuint buildProgram(const char* vertexShaderSource,          const char* fragmentShaderSource)   {      GLuint vertexShader = buildShader(vertexShaderSource, GL_VERTEX_SHADER);      GLuint fragmentShader = buildShader(fragmentShaderSource, GL_FRAGMENT_SHADER);      GLuint programHandle = glCreateProgram();        if (programHandle)      {          glAttachShader(programHandle, vertexShader);          checkGlError("glAttachShader");          glAttachShader(programHandle, fragmentShader);          checkGlError("glAttachShader");          glLinkProgram(programHandle);            GLint linkStatus = GL_FALSE;          glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus);          if (linkStatus != GL_TRUE) {              GLint bufLength = 0;              glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &bufLength);              if (bufLength) {                  char* buf = (char*) malloc(bufLength);                  if (buf) {                      glGetProgramInfoLog(programHandle, bufLength, NULL, buf);                      log_easy("error::Could not link program:\n%s\n", buf);                      free(buf);                  }              }              glDeleteProgram(programHandle);              programHandle = 0;          }        }        return programHandle;  }    static unsigned char * readYUV(const char *path)  {        FILE *fp;      unsigned char * buffer;      long size = 1280 * 720 * 3 / 2;        if((fp=fopen(path,"rb"))==NULL)      {          log("cant open the file");         exit(0);      }        buffer = (unsigned char *)malloc(size);      memset(buffer,'\0',size);      long len = fread(buffer,1,size,fp);      //PRINTF("read data size:%ld", len);      fclose(fp);      return buffer;  }    void gl_initialize()   {      g_buffer = NULL;        simpleProgram = buildProgram(VERTEX_SHADER, FRAG_SHADER);      glUseProgram(simpleProgram);      glGenTextures(1, &g_texYId);      glGenTextures(1, &g_texUId);      glGenTextures(1, &g_texVId);  }    void gl_uninitialize()  {        g_width = 0;      g_height = 0;        if (g_buffer)      {          free(g_buffer);          g_buffer = NULL;      }  }  //设置图像数据  void gl_set_framebuffer(const char* buffer, int buffersize, int width, int height)  {            if (g_width != width || g_height != height)      {          if (g_buffer)              free(g_buffer);            g_width = width;          g_height = height;            g_buffer = (char *)malloc(buffersize);      }        if (g_buffer)          memcpy(g_buffer, buffer, buffersize);    }  //画屏  void gl_render_frame()  {      if (0 == g_width || 0 == g_height)          return;    #if 0      int width = 448;      int height = 336;      static unsigned char *buffer = NULL;        if (NULL == buffer)      {          char filename[128] = {0};          strcpy(filename, "/sdcard/yuv_448_336.yuv");          buffer = readYUV(filename);      }    #else      const char *buffer = g_buffer;      int width = g_width;      int height = g_height;  #endif      glViewport(0, 0, width, height);      bindTexture(g_texYId, buffer, width, height);      bindTexture(g_texUId, buffer + width * height, width/2, height/2);      bindTexture(g_texVId, buffer + width * height * 5 / 4, width/2, height/2);     renderFrame();   }  //如果设置图像数据和画屏是两个线程的话,记住要加锁。


Shader.vext:

//Shader.vert文件内容  static const char* 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";  

Shader.frag:

//Shader.frag文件内容  static const char* FRAG_SHADER =      "varying lowp vec2 tc;\n"      "uniform sampler2D SamplerY;\n"      "uniform sampler2D SamplerU;\n"      "uniform sampler2D SamplerV;\n"      "void main(void)\n"      "{\n"          "mediump vec3 yuv;\n"          "lowp vec3 rgb;\n"          "yuv.x = texture2D(SamplerY, tc).r;\n"          "yuv.y = texture2D(SamplerU, tc).r - 0.5;\n"          "yuv.z = texture2D(SamplerV, tc).r - 0.5;\n"          "rgb = mat3( 1,   1,   1,\n"                      "0,       -0.39465,  2.03211,\n"                      "1.13983,   -0.58060,  0) * yuv;\n"          "gl_FragColor = vec4(rgb, 1);\n"      "}\n";