首页 > 代码库 > yuv视频用opengl播放
yuv视频用opengl播放
// 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); }
编译脚本:
@echo off
cd %~d0
cd %cd%
@echo on
qmake -project
qmake "QT+=opengl"
nmake
pause
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。