OpenGL显示YUV视频

来源:互联网 发布:知鸟保险基础1500题库 编辑:程序博客网 时间:2024/05/18 01:40

某次有用到opengl显示YUV视频,网上一直没找到完整的代码,后凑齐了,就贴在这里,vs2010工程完整代码下载地址http://download.csdn.net/detail/himulakensin/6339791


// windows平台#define WindowWidth  960#define WindowHeight 560#define WindowTitle  "OpenGL_showYUV"#include "GL/glew.h"#include "GL/glut.h"#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <string.h>#include <Windows.h>#pragma comment (lib, "glew32.lib")/* 记时的类,不用理这个类 */class KsTime{private:        __int64 m_base, m_start, m_stop;        bool m_print;public:    KsTime(bool e_print = false);             ~KsTime();    void restart();    void elapsed();            double get_elapsed();            void set_print(bool e_print);};KsTime::KsTime(bool e_print) : m_print(e_print){            QueryPerformanceFrequency((LARGE_INTEGER *)(&m_base));     restart();}KsTime::~KsTime() {    if (m_print) elapsed(); }void KsTime::restart(){ QueryPerformanceCounter((LARGE_INTEGER *)(&m_start)); }void KsTime::elapsed(){            QueryPerformanceCounter((LARGE_INTEGER *)(&m_stop));    printf("%.6f\n", (double)(m_stop - m_start) / m_base);                    }double KsTime::get_elapsed(){            QueryPerformanceCounter((LARGE_INTEGER *)(&m_stop));    return (double)(m_stop - m_start) / m_base;                    }void KsTime::set_print(bool e_print) { m_print = e_print; }/* I420的yuv数据,如果没有现成的,有ffmpeg.exe也行 * cmd里执行类似 * ffmpeg -t 10 -i D:\w.mp4 D:\w.yuv */const int w = 1920, h = 1080;FILE *infile = fopen("D:\\Data\\parkjoy.1920x1080.yuv", "rb");unsigned char buf[w*h*3/2];unsigned char *plane[3];GLuint p;                    // program id,着色器相关GLuint id_y, id_u, id_v; // 纹理idGLuint textureUniformY, textureUniformU,textureUniformV;#define ATTRIB_VERTEX 3#define ATTRIB_TEXTURE 4void display(void){    /* 对于1080P的I420,此读文件操作时非常耗时的,且一般不稳定 */    if (fread(buf, 1, w*h*3/2, infile) != w*h*3/2)    {        // 循环都I420文件        fseek(infile, 0, SEEK_SET);        fread(buf, 1, w*h*3/2, infile);    }        glActiveTexture(GL_TEXTURE0);    glBindTexture(GL_TEXTURE_2D, id_y);    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, plane[0]);         glActiveTexture(GL_TEXTURE1);    glBindTexture(GL_TEXTURE_2D, id_u);    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w/2, h/2, 0, GL_RED, GL_UNSIGNED_BYTE, plane[1]);               glActiveTexture(GL_TEXTURE2);    glBindTexture(GL_TEXTURE_2D, id_v);    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w/2, h/2, 0, GL_RED, GL_UNSIGNED_BYTE, plane[2]);                //glClearColor(0.0, 0.6, 0.0, 1.0);    //glClear(GL_COLOR_BUFFER_BIT);     glActiveTexture(GL_TEXTURE0);    glBindTexture(GL_TEXTURE_2D, id_y);    glUniform1i(textureUniformY, 0);            glActiveTexture(GL_TEXTURE1);    glBindTexture(GL_TEXTURE_2D, id_u);    glUniform1i(textureUniformU, 1);        glActiveTexture(GL_TEXTURE2);    glBindTexture(GL_TEXTURE_2D, id_v);    glUniform1i(textureUniformV, 2);        // Draw    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);    glutSwapBuffers();}KsTime kst;void timeFunc(int value){    kst.restart();    display();    int d = 40 - (int)(kst.get_elapsed()*1000);    if (d <= 0) d = 0;    // 大约25fps    glutTimerFunc(d, timeFunc, 0);}char *textFileRead(char * filename){    char *s = (char *)malloc(8000);    memset(s, 0, 8000);    FILE *infile = fopen(filename, "rb");    int len = fread(s, 1, 8000, infile);    fclose(infile);    s[len] = 0;    return s;}void setShaders(){    GLint vertCompiled, fragCompiled, linked;    // 测试执行结果的        GLint v, f;    const char *vs,*fs;    v = glCreateShader(GL_VERTEX_SHADER);    f = glCreateShader(GL_FRAGMENT_SHADER);    vs = textFileRead("Shader.vsh");    fs = textFileRead("Shader.fsh");    glShaderSource(v, 1, &vs,NULL);    glShaderSource(f, 1, &fs,NULL);    glCompileShader(v);    glGetShaderiv(v, GL_COMPILE_STATUS, &vertCompiled);    glCompileShader(f);    glGetShaderiv(f, GL_COMPILE_STATUS, &fragCompiled);    p = glCreateProgram();     glAttachShader(p,v);    glAttachShader(p,f);     glBindAttribLocation(p, ATTRIB_VERTEX, "position");    glBindAttribLocation(p, ATTRIB_TEXTURE, "TexCoordIn");    glLinkProgram(p);    glGetProgramiv(p, GL_LINK_STATUS, &linked);       glUseProgram(p);    static const GLfloat squareVertices[] = {        -1.0f, -1.0f,         1.0f, -1.0f,        -1.0f,  1.0f,         1.0f,  1.0f,    };        static const GLfloat coordVertices[] = {         0.0f,  1.0f,         1.0f,  1.0f,         0.0f,  0.0f,         1.0f,  0.0f,    };     textureUniformY = glGetUniformLocation(p, "tex_y");    textureUniformU = glGetUniformLocation(p, "tex_u");    textureUniformV = glGetUniformLocation(p, "tex_v");     glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);    glEnableVertexAttribArray(ATTRIB_VERTEX);        glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, coordVertices);    glEnableVertexAttribArray(ATTRIB_TEXTURE);    glGenTextures(1, &id_y);     glBindTexture(GL_TEXTURE_2D, id_y);        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);            glGenTextures(1, &id_u);    glBindTexture(GL_TEXTURE_2D, id_u);       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);        glGenTextures(1, &id_v);     glBindTexture(GL_TEXTURE_2D, id_v);        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);}int main(int argc, char* argv[]){    plane[0] = buf;    plane[1] = plane[0] + w*h;    plane[2] = plane[1] + w*h/4;    // GLUT初始化    glutInit(&argc, argv);        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA /*| GLUT_STENCIL | GLUT_DEPTH*/);    glutInitWindowPosition(100, 100);    glutInitWindowSize(WindowWidth, WindowHeight);    glutCreateWindow(WindowTitle);    printf("%s\n", glGetString(GL_VERSION));    GLenum l = glewInit();    if (glewIsSupported("GL_VERSION_2_0"))        printf("Ready for OpenGL 2.0\n");    else{        printf("OpenGL 2.0 not supported\n");        return 0;    }    glutDisplayFunc(&display);    glutTimerFunc(40, timeFunc, 0);     setShaders();    // 开始显示    glutMainLoop();    return 0;}

GLSL相关的两个小文件


attribute vec4 position; attribute vec2 TexCoordIn;varying vec2 TexCoordOut;void main(void){    gl_Position = position;     TexCoordOut = TexCoordIn;}varying vec2 TexCoordOut;uniform sampler2D tex_y;uniform sampler2D tex_u;uniform sampler2D tex_v;void main(void){    vec3 yuv;    vec3 rgb;        yuv.x = texture2D(tex_y, TexCoordOut).r;    yuv.y = texture2D(tex_u, TexCoordOut).r - 0.5;    yuv.z = texture2D(tex_v, TexCoordOut).r - 0.5;    rgb = mat3( 1,       1,         1,                0,       -0.39465,  2.03211,                1.13983, -0.58060,  0) * yuv;        gl_FragColor = vec4(rgb, 1);}