// openGL_yuv.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "GL/glew.h"
#include "GL/freeglut.h"
#pragma comment(lib, "glew32.lib")
int g_nQuit=0;
// 视频窗口的宽高
const int WIN_WIDTH = 640;
const int WIN_HEIGHT= 352;
// YUV文件的宽高
const int YUV_WIDTH = 640;
const int YUV_HEIGHT= 352;
FILE *g_fp=NULL;
GLuint g_nProgramId=0, g_nFragmentShaderId=0;
GLubyte *g_pYtex=NULL, *g_pUtex=NULL, *g_pVtex=NULL;
GLuint g_nLumaTexture=0;
GLuint g_nChromaUTexture=0;
GLuint g_pChromaVTexture=0;
// fragment shader的GLSL
const GLchar* g_FProgram =
{
"uniform sampler2DRect Ytex;\n"
"uniform sampler2DRect Utex,Vtex;\n"
"void main(void) {\n"
" float nx,ny,r,g,b,y,u,v;\n"
" vec4 txl,ux,vx;"
" nx=gl_TexCoord[0].x;\n"
" ny=gl_TexCoord[0].y;\n"
" y=texture2DRect(Ytex,vec2(nx,ny)).r;\n"
" u=texture2DRect(Utex,vec2(nx/2.0,ny/2.0)).r;\n"
" v=texture2DRect(Vtex,vec2(nx/2.0,ny/2.0)).r;\n"
" y=1.1643*(y-0.0625);\n"
" u=u-0.5;\n"
" v=v-0.5;\n"
" r=y+1.5958*v;\n"
" g=y-0.39173*u-0.81290*v;\n"
" b=y+2.017*u;\n"
" gl_FragColor=vec4(r,g,b,1.0);\n"
"}\n"
};
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void RenderFunction(void);
void Cleanup(void);
void CreateSurface(void);
void DestroySurface(void);
void CreateShaders(void);
void DestroyShaders(void);
void Initialize(int argc, char* argv[])
{
GLenum GlewInitResult;
InitWindow(argc, argv);
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult) {
fprintf(
stderr,
"ERROR: %s\n",
glewGetErrorString(GlewInitResult)
);
exit(EXIT_FAILURE);
}
fprintf(
stdout,
"INFO: OpenGL Version: %s\n",
glGetString(GL_VERSION)
);
CreateShaders();
CreateSurface();
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
glOrtho(0, WIN_WIDTH, 0, WIN_HEIGHT, -1, 1);
glViewport(0, 0, WIN_WIDTH,WIN_HEIGHT);
//glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
// 创建opengl的窗口
void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitContextVersion(2, 0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
int WindowHandle = glutCreateWindow("ShowYUV");
if(WindowHandle < 1) {
fprintf(
stderr,
"ERROR: Could not create a new rendering window.\n"
);
exit(EXIT_FAILURE);
}
glutDisplayFunc(RenderFunction);
glutCloseFunc(Cleanup);
}
void Cleanup(void)
{
DestroyShaders();
DestroySurface();
}
void RenderFunction(void)
{
// 读入下一帧视频
fread(g_pYtex, YUV_WIDTH*YUV_HEIGHT, 1, g_fp);
fread(g_pUtex, YUV_WIDTH*YUV_HEIGHT/4, 1, g_fp);
fread(g_pVtex, YUV_WIDTH*YUV_HEIGHT/4, 1, g_fp);
glActiveTexture(GL_TEXTURE0);
// 使用glTexSubImage2D来update纹理
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
0, 0,
YUV_WIDTH, YUV_HEIGHT,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pYtex);
glActiveTexture(GL_TEXTURE1);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
0, 0,
YUV_WIDTH/2, YUV_HEIGHT/2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pUtex);
glActiveTexture(GL_TEXTURE2);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
0, 0,
YUV_WIDTH/2, YUV_HEIGHT/2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pVtex);
glClear(GL_COLOR_BUFFER_BIT);
// Draw image
// 注意opengl中y坐标向上为正,而yuv视频向下为正,需要反转一下
glBegin(GL_QUADS);
glTexCoord2i(0, YUV_HEIGHT);
glVertex2i(0, 0);
glTexCoord2i(YUV_WIDTH, YUV_HEIGHT);
glVertex2i(WIN_WIDTH, 0);
glTexCoord2i(YUV_WIDTH, 0);
glVertex2i(WIN_WIDTH, WIN_HEIGHT);
glTexCoord2i(0, 0);
glVertex2i(0,WIN_HEIGHT);
glEnd();
// Flip buffers.
glutSwapBuffers();
glutPostRedisplay();
Sleep(50);
}
void CreateSurface(void)
{
GLint location;
// Load the textures.
g_pYtex = (GLubyte*)malloc(YUV_WIDTH*YUV_HEIGHT);
g_pUtex = (GLubyte*)malloc(YUV_WIDTH*YUV_HEIGHT/4);
g_pVtex = (GLubyte*)malloc(YUV_WIDTH*YUV_HEIGHT/4);
g_fp=fopen("d:\\M640x352_yuv420.yuv","rb");
// This might not be required, but should not hurt.
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &g_nLumaTexture);
glGenTextures(1, &g_nChromaUTexture);
glGenTextures(1, &g_pChromaVTexture);
// Select texture unit 1 as the active unit and bind the U texture.
glActiveTexture(GL_TEXTURE1);
location = glGetUniformLocation(g_nProgramId, "Utex");
glUniform1i(location, 1); // Bind Utex to texture unit 1
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_nChromaUTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
GL_LUMINANCE,
YUV_WIDTH/2, YUV_HEIGHT/2,
0,GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pUtex);
// Select texture unit 2 as the active unit and bind the V texture.
glActiveTexture(GL_TEXTURE2);
location = glGetUniformLocation(g_nProgramId, "Vtex");
glUniform1i(location, 2); // Bind Vtext to texture unit 2
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_pChromaVTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
GL_LUMINANCE,
YUV_WIDTH/2, YUV_HEIGHT/2,
0,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pVtex);
// Select texture unit 0 as the active unit and bind the Y texture.
glActiveTexture(GL_TEXTURE0);
location = glGetUniformLocation(g_nProgramId, "Ytex");
glUniform1i(location, 0); // Bind Ytex to texture unit 0
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_nLumaTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
GL_LUMINANCE,
YUV_WIDTH, YUV_HEIGHT,
0,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pYtex);
}
void DestroySurface(void)
{
free(g_pYtex);
free(g_pUtex);
free(g_pVtex);
glDeleteTextures(1, &g_nLumaTexture);
glDeleteTextures(1, &g_nChromaUTexture);
glDeleteTextures(1, &g_pChromaVTexture);
}
void CreateShaders(void)
{
GLchar messages[256];
GLenum ErrorCheckValue = glGetError();
// Compile the shader.
g_nFragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_nFragmentShaderId, 1, &g_FProgram, NULL);
glCompileShader(g_nFragmentShaderId);
// Print the compilation log.
glGetShaderInfoLog(g_nFragmentShaderId, sizeof(messages), NULL, messages);
printf("Compile Log: %s\n", messages);
// Set up program objects.
g_nProgramId = glCreateProgram();
// Create a complete program object.
glAttachShader(g_nProgramId, g_nFragmentShaderId);
glLinkProgram(g_nProgramId);
// And print the link log.
glGetProgramInfoLog(g_nProgramId, sizeof(messages), NULL, messages);
printf("Link Log: %s\n", messages);
// Finally, use the program.
glUseProgram(g_nProgramId);
}
void DestroyShaders(void)
{
GLenum ErrorCheckValue = glGetError();
glUseProgram(0);
glDetachShader(g_nProgramId, g_nFragmentShaderId);
glDeleteShader(g_nFragmentShaderId);
glDeleteProgram(g_nProgramId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not destroy the shaders: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
int main(int argc, char *argv[])
{
Initialize(argc, argv);
glutMainLoop();
return(0);
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "GL/glew.h"
#include "GL/freeglut.h"
#pragma comment(lib, "glew32.lib")
int g_nQuit=0;
// 视频窗口的宽高
const int WIN_WIDTH = 640;
const int WIN_HEIGHT= 352;
// YUV文件的宽高
const int YUV_WIDTH = 640;
const int YUV_HEIGHT= 352;
FILE *g_fp=NULL;
GLuint g_nProgramId=0, g_nFragmentShaderId=0;
GLubyte *g_pYtex=NULL, *g_pUtex=NULL, *g_pVtex=NULL;
GLuint g_nLumaTexture=0;
GLuint g_nChromaUTexture=0;
GLuint g_pChromaVTexture=0;
// fragment shader的GLSL
const GLchar* g_FProgram =
{
"uniform sampler2DRect Ytex;\n"
"uniform sampler2DRect Utex,Vtex;\n"
"void main(void) {\n"
" float nx,ny,r,g,b,y,u,v;\n"
" vec4 txl,ux,vx;"
" nx=gl_TexCoord[0].x;\n"
" ny=gl_TexCoord[0].y;\n"
" y=texture2DRect(Ytex,vec2(nx,ny)).r;\n"
" u=texture2DRect(Utex,vec2(nx/2.0,ny/2.0)).r;\n"
" v=texture2DRect(Vtex,vec2(nx/2.0,ny/2.0)).r;\n"
" y=1.1643*(y-0.0625);\n"
" u=u-0.5;\n"
" v=v-0.5;\n"
" r=y+1.5958*v;\n"
" g=y-0.39173*u-0.81290*v;\n"
" b=y+2.017*u;\n"
" gl_FragColor=vec4(r,g,b,1.0);\n"
"}\n"
};
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void RenderFunction(void);
void Cleanup(void);
void CreateSurface(void);
void DestroySurface(void);
void CreateShaders(void);
void DestroyShaders(void);
void Initialize(int argc, char* argv[])
{
GLenum GlewInitResult;
InitWindow(argc, argv);
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult) {
fprintf(
stderr,
"ERROR: %s\n",
glewGetErrorString(GlewInitResult)
);
exit(EXIT_FAILURE);
}
fprintf(
stdout,
"INFO: OpenGL Version: %s\n",
glGetString(GL_VERSION)
);
CreateShaders();
CreateSurface();
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
glOrtho(0, WIN_WIDTH, 0, WIN_HEIGHT, -1, 1);
glViewport(0, 0, WIN_WIDTH,WIN_HEIGHT);
//glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
// 创建opengl的窗口
void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitContextVersion(2, 0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
int WindowHandle = glutCreateWindow("ShowYUV");
if(WindowHandle < 1) {
fprintf(
stderr,
"ERROR: Could not create a new rendering window.\n"
);
exit(EXIT_FAILURE);
}
glutDisplayFunc(RenderFunction);
glutCloseFunc(Cleanup);
}
void Cleanup(void)
{
DestroyShaders();
DestroySurface();
}
void RenderFunction(void)
{
// 读入下一帧视频
fread(g_pYtex, YUV_WIDTH*YUV_HEIGHT, 1, g_fp);
fread(g_pUtex, YUV_WIDTH*YUV_HEIGHT/4, 1, g_fp);
fread(g_pVtex, YUV_WIDTH*YUV_HEIGHT/4, 1, g_fp);
glActiveTexture(GL_TEXTURE0);
// 使用glTexSubImage2D来update纹理
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
0, 0,
YUV_WIDTH, YUV_HEIGHT,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pYtex);
glActiveTexture(GL_TEXTURE1);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
0, 0,
YUV_WIDTH/2, YUV_HEIGHT/2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pUtex);
glActiveTexture(GL_TEXTURE2);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
0, 0,
YUV_WIDTH/2, YUV_HEIGHT/2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pVtex);
glClear(GL_COLOR_BUFFER_BIT);
// Draw image
// 注意opengl中y坐标向上为正,而yuv视频向下为正,需要反转一下
glBegin(GL_QUADS);
glTexCoord2i(0, YUV_HEIGHT);
glVertex2i(0, 0);
glTexCoord2i(YUV_WIDTH, YUV_HEIGHT);
glVertex2i(WIN_WIDTH, 0);
glTexCoord2i(YUV_WIDTH, 0);
glVertex2i(WIN_WIDTH, WIN_HEIGHT);
glTexCoord2i(0, 0);
glVertex2i(0,WIN_HEIGHT);
glEnd();
// Flip buffers.
glutSwapBuffers();
glutPostRedisplay();
Sleep(50);
}
void CreateSurface(void)
{
GLint location;
// Load the textures.
g_pYtex = (GLubyte*)malloc(YUV_WIDTH*YUV_HEIGHT);
g_pUtex = (GLubyte*)malloc(YUV_WIDTH*YUV_HEIGHT/4);
g_pVtex = (GLubyte*)malloc(YUV_WIDTH*YUV_HEIGHT/4);
g_fp=fopen("d:\\M640x352_yuv420.yuv","rb");
// This might not be required, but should not hurt.
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &g_nLumaTexture);
glGenTextures(1, &g_nChromaUTexture);
glGenTextures(1, &g_pChromaVTexture);
// Select texture unit 1 as the active unit and bind the U texture.
glActiveTexture(GL_TEXTURE1);
location = glGetUniformLocation(g_nProgramId, "Utex");
glUniform1i(location, 1); // Bind Utex to texture unit 1
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_nChromaUTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
GL_LUMINANCE,
YUV_WIDTH/2, YUV_HEIGHT/2,
0,GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pUtex);
// Select texture unit 2 as the active unit and bind the V texture.
glActiveTexture(GL_TEXTURE2);
location = glGetUniformLocation(g_nProgramId, "Vtex");
glUniform1i(location, 2); // Bind Vtext to texture unit 2
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_pChromaVTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
GL_LUMINANCE,
YUV_WIDTH/2, YUV_HEIGHT/2,
0,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pVtex);
// Select texture unit 0 as the active unit and bind the Y texture.
glActiveTexture(GL_TEXTURE0);
location = glGetUniformLocation(g_nProgramId, "Ytex");
glUniform1i(location, 0); // Bind Ytex to texture unit 0
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_nLumaTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
0,
GL_LUMINANCE,
YUV_WIDTH, YUV_HEIGHT,
0,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
g_pYtex);
}
void DestroySurface(void)
{
free(g_pYtex);
free(g_pUtex);
free(g_pVtex);
glDeleteTextures(1, &g_nLumaTexture);
glDeleteTextures(1, &g_nChromaUTexture);
glDeleteTextures(1, &g_pChromaVTexture);
}
void CreateShaders(void)
{
GLchar messages[256];
GLenum ErrorCheckValue = glGetError();
// Compile the shader.
g_nFragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_nFragmentShaderId, 1, &g_FProgram, NULL);
glCompileShader(g_nFragmentShaderId);
// Print the compilation log.
glGetShaderInfoLog(g_nFragmentShaderId, sizeof(messages), NULL, messages);
printf("Compile Log: %s\n", messages);
// Set up program objects.
g_nProgramId = glCreateProgram();
// Create a complete program object.
glAttachShader(g_nProgramId, g_nFragmentShaderId);
glLinkProgram(g_nProgramId);
// And print the link log.
glGetProgramInfoLog(g_nProgramId, sizeof(messages), NULL, messages);
printf("Link Log: %s\n", messages);
// Finally, use the program.
glUseProgram(g_nProgramId);
}
void DestroyShaders(void)
{
GLenum ErrorCheckValue = glGetError();
glUseProgram(0);
glDetachShader(g_nProgramId, g_nFragmentShaderId);
glDeleteShader(g_nFragmentShaderId);
glDeleteProgram(g_nProgramId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not destroy the shaders: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
int main(int argc, char *argv[])
{
Initialize(argc, argv);
glutMainLoop();
return(0);
}
编译脚本:
@echo off
cd %~d0
cd %cd%
@echo on
qmake -project
qmake "QT+=opengl"
nmake
pause
转载于:http://www.cnblogs.com/tiancun/p/3766352.html