现在的位置: 首页 > 综合 > 正文

opengles 显示 yuv

2012年09月25日 ⁄ 综合 ⁄ 共 6844字 ⁄ 字号 评论关闭
// 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.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";
//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";

抱歉!评论已关闭.