OpenGL播放yuv数据流(着色器SHADER)-windows(一)

点击打开原文链接

OpenGL播放yuv数据流(着色器SHADER)-windows(一)


在写这篇文章之前首先要感谢老雷,http://blog.csdn.net/leixiaohua1020/article/details/40379845这篇文章,可以老雷英年早逝,在此致敬...


下面是代码,具体看注释

//Lvs_OpenGl_Interface.h

[cpp]  view plain  copy
  1. /** Copyright (c/c++) <2016.11.22> <zwg/> 
  2. * Function   
  3. * Opanal for video rendering related implementation and definition, etc. 
  4. * OpanAl 用于视频渲染相关实现及定义,等 
  5. */  
  6.   
  7. #ifndef __LVS_OPENGL_INTERFACE_H__  
  8. #define __LVS_OPENGL_INTERFACE_H__  
  9.   
  10. #include <stdio.h>  
  11. #include <stdlib.h>  
  12. #include <malloc.h>  
  13. #include <string.h>  
  14.   
  15. //windows  
  16. #ifdef WIN32  
  17. //opengl库  
  18. #include "glew.h"  
  19. #include "glut.h"  
  20.   
  21. #pragma comment(lib,"glew32.lib")  
  22. //ios  
  23. #elif __APPLE__  
  24. //opengl库  
  25. #include "glew.h"  
  26. #include "glut.h"  
  27. //ANDROID平台    
  28. #elif __ANDROID__    
  29. //opengl库  
  30. #include "glew.h"  
  31. #include "glut.h"  
  32. //linux  
  33. #else  
  34. //opengl库  
  35. #include "glew.h"  
  36. #include "glut.h"  
  37. #endif  
  38.   
  39. //到处宏定义  
  40. //windows  
  41. #ifdef WIN32  
  42. #define LVS_DLLEXPORT __declspec(dllexport)  
  43. //ios  
  44. #elif __APPLE__  
  45. #define LVS_DLLEXPORT  
  46. //linux  
  47. #else  
  48. #define LVS_DLLEXPORT  
  49. #endif  
  50.   
  51. //着色器用的顶点属性索引 position是由3个(x,y,z)组成,  
  52. #define ATTRIB_VERTEX 3  
  53. //着色器用的像素,纹理属性索引 而颜色是4个(r,g,b,a)  
  54. #define ATTRIB_TEXTURE 4  
  55. //是否旋转图像(纹理)  
  56. #define TEXTURE_ROTATE    0  
  57. //显示图像(纹理)的一半  
  58. #define TEXTURE_HALF      0  
  59.   
  60. //窗口消息函数指针  
  61. typedef void (*WindowRepaintCK)(void);  
  62. //回调读取数据函数指针,数据及时间戳  
  63. typedef int (*DisplayDataCK)(void ** data,int * timer_millis);  
  64.   
  65. //接口初始化  
  66. int lvs_opengl_interface_init(int screen_width,int screen_height,  
  67.     int window_x, int window_y,  
  68.     int yuvdata_width,int uvdata_height,  
  69.     char * shader_vsh_pathname,char * shader_fsh_pathname,  
  70.     DisplayDataCK displaydatack,  
  71.     WindowRepaintCK windowrepaintcallback);  
  72. //接口释放  
  73. void lvs_opengl_interface_uninit();  
  74. //接口渲染数据(定时器,渲染时间,毫秒),数据及渲染定时时间在回调里面做处理  
  75. void lvs_opengl_interface_write(int value);  
  76. //接口opengl消息循环  
  77. void lvs_opengl_interface_messageloop();  
  78.   
  79. //渲染数据(定时器,渲染时间,毫秒),数据及渲染定时时间在回调里面做处理  
  80. void TimerFunc1(int value);   //这里如果有可能则调成类的成员函数,以后处理,暂时不知道怎么解决类成员函数递归??  
  81.   
  82. using namespace std;  
  83.   
  84. class cclass_opengl_interface;  
  85.   
  86. class cclass_opengl_interface  
  87. {  
  88. public:  
  89.     cclass_opengl_interface();  
  90.     virtual ~cclass_opengl_interface();  
  91.     //初始化  
  92.     int initopengl(int screen_width,int screen_height,  
  93.         int window_x, int window_y,  
  94.         int yuvdata_width,int uvdata_height,  
  95.         char * shader_vsh_pathname,char * shader_fsh_pathname,  
  96.         DisplayDataCK displaydatack,  
  97.         WindowRepaintCK windowrepaintcallback);  
  98.     //初始化着色器,类似于告GPU当传进去数据的时候采用什么样的规则。  
  99.     void InitShaders();  
  100.     //具体显示图像的函数  
  101.     int DisplayImage(void * parm);  
  102.     //opengl消息循环  
  103.     void messageloop();  
  104. private:  
  105. public:  
  106.     DisplayDataCK m_displaydatack;                                   //用于显示回调函数,参数数据及时间戳  
  107.     char * m_yuvbuf;                                                 //存放yuv数据的buf指针,申请buffer在外面  
  108.     int m_millis_realtime;                                           //实时的时间戳,每次回调会更新  
  109. private:  
  110.     int m_screen_width;                                              //窗口宽  
  111.     int m_screen_height;                                             //窗口高  
  112.     int m_window_x;                                                  //窗口的x坐标  
  113.     int m_window_y;                                                  //窗口的y坐标  
  114.     int m_yuvdata_width;                                             //数据宽  
  115.     int m_yuvdata_height;                                            //数据高  
  116.     WindowRepaintCK m_windowrepaintcallback;                         //窗口重绘的时候,例如最大化最小化窗口,缩放窗口等让窗口重绘的时候调用。//从而接收消息循环   
  117.     char m_shader_vsh_pathname[256];                                 //shader的vsh源码位置  
  118.     char m_shader_fsh_pathname[256];                                 //shader的fsh源码位置  
  119.     GLuint m_textureid_y, m_textureid_u, m_textureid_v;              //纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用。  
  120.     GLuint m_textureUniformY, m_textureUniformU,m_textureUniformV;   //用于纹理渲染的变量   
  121. };  
  122.   
  123. #endif  


//Lvs_OpenGl_Interface.cpp

[cpp]  view plain  copy
  1. #include "Lvs_OpenGl_Interface.h"  
  2.   
  3. static cclass_opengl_interface * copengl_interface = NULL;  
  4.   
  5. int lvs_opengl_interface_init(int screen_width,int screen_height,  
  6.     int window_x, int window_y,  
  7.     int yuvdata_width,int uvdata_height,  
  8.     char * shader_vsh_pathname,char * shader_fsh_pathname,  
  9.     DisplayDataCK displaydatack,  
  10.     WindowRepaintCK windowrepaintcallback)  
  11. {  
  12.     int ret = 0;  
  13.     printf("Device : lvs_opengl_interface_init\n");  
  14.     if(copengl_interface == NULL)  
  15.     {  
  16.         copengl_interface = new cclass_opengl_interface();  
  17.         //初始化  
  18.         copengl_interface->initopengl(screen_width,screen_height,  
  19.             window_x,window_y,  
  20.             yuvdata_width,uvdata_height,  
  21.             shader_vsh_pathname,shader_fsh_pathname,  
  22.             displaydatack,  
  23.             windowrepaintcallback);  
  24.   
  25.         //初始化着色器,类似于告GPU当传进去数据的时候采用什么样的规则。  
  26.         copengl_interface->InitShaders();  
  27.     }  
  28.     return ret;  
  29. }  
  30.   
  31. void lvs_opengl_interface_uninit()  
  32. {  
  33.     printf("Device : lvs_opengl_interface_uninit\n");  
  34.   
  35.     if(copengl_interface)  
  36.     {  
  37.         delete copengl_interface;  
  38.         copengl_interface = NULL;  
  39.     }  
  40.     return ;  
  41. }  
  42.   
  43. void lvs_opengl_interface_write(int value)  
  44. {  
  45.      //这里如果有可能则调成类的成员函数,以后处理,暂时不知道怎么解决类成员函数递归  
  46.     TimerFunc1(value);  
  47. }  
  48.   
  49. void lvs_opengl_interface_messageloop()  
  50. {  
  51.     copengl_interface->messageloop();  
  52. }  
  53.   
  54. void TimerFunc1(int value)  
  55. {  
  56.     int ret = 0;  
  57.   
  58.     //调用回调函数获取数据  
  59.     copengl_interface->m_displaydatack((void **)&copengl_interface->m_yuvbuf,&copengl_interface->m_millis_realtime);  
  60.   
  61.     //这里做具体的处理  
  62.     ret = copengl_interface->DisplayImage(NULL);  
  63.   
  64.     //因为glut的定时器是调用一次才产生一次定时,所以如果要持续产生定时的话,  
  65.     //在定时函数末尾再次调用glutTimerFunc  
  66.     //这里如果有可能则调成类的成员函数,以后处理,暂时不知道怎么解决类成员函数递归  
  67.     glutTimerFunc(copengl_interface->m_millis_realtime, TimerFunc1, 0);  
  68. }  
  69.   
  70. cclass_opengl_interface::cclass_opengl_interface()  
  71. {  
  72.     m_screen_width = 0;   
  73.     m_screen_height = 0;   
  74.     m_window_x = 0;  
  75.     m_window_y = 0;  
  76.     m_yuvdata_width = 0;  
  77.     m_yuvdata_height = 0;   
  78.     memset(m_shader_vsh_pathname,0,256);  
  79.     memset(m_shader_fsh_pathname,0,256);  
  80.     m_windowrepaintcallback = NULL;  
  81.     m_textureid_y = 0;  
  82.     m_textureid_u = 0;  
  83.     m_textureid_v = 0;  
  84.     m_textureUniformY = 0;  
  85.     m_textureUniformU = 0;  
  86.     m_textureUniformV = 0;  
  87.     m_displaydatack = NULL;  
  88.     m_yuvbuf = NULL;  
  89.     m_millis_realtime = 0;  
  90. }  
  91.   
  92. cclass_opengl_interface::~cclass_opengl_interface()  
  93. {  
  94.     m_screen_width = 0;   
  95.     m_screen_height = 0;   
  96.     m_window_x = 0;  
  97.     m_window_y = 0;  
  98.     m_yuvdata_width = 0;  
  99.     m_yuvdata_height = 0;   
  100.     memset(m_shader_vsh_pathname,0,256);  
  101.     memset(m_shader_fsh_pathname,0,256);  
  102.     m_windowrepaintcallback = NULL;  
  103.     m_textureid_y = 0;  
  104.     m_textureid_u = 0;  
  105.     m_textureid_v = 0;  
  106.     m_textureUniformY = 0;  
  107.     m_textureUniformU = 0;  
  108.     m_textureUniformV = 0;  
  109.     m_displaydatack = NULL;  
  110.     m_yuvbuf = NULL;  
  111.     m_millis_realtime = 0;  
  112. }  
  113.   
  114. int cclass_opengl_interface::initopengl(int screen_width,int screen_height,  
  115.     int window_x, int window_y,  
  116.     int yuvdata_width,int uvdata_height,  
  117.     char * shader_vsh_pathname,char * shader_fsh_pathname,  
  118.     DisplayDataCK displaydatack,  
  119.     WindowRepaintCK windowrepaintcallback)  
  120. {  
  121.     int ret = 0;  
  122.   
  123.     m_screen_width = screen_width;   
  124.     m_screen_height = screen_height;   
  125.     m_window_x = window_x;  
  126.     m_window_y = window_y;  
  127.     m_yuvdata_width = yuvdata_width;  
  128.     m_yuvdata_height = uvdata_height;   
  129.     sprintf(m_shader_vsh_pathname,"%s",shader_vsh_pathname);  
  130.     sprintf(m_shader_fsh_pathname,"%s",shader_fsh_pathname);  
  131.     m_windowrepaintcallback = windowrepaintcallback;  
  132.     m_displaydatack = displaydatack;  
  133.   
  134.     //初始化 GLUT opengl函数库  
  135.     int zwg_argc=1;  
  136.     //添加函数库名称  
  137.     char* zwg_argv[]={"ZWG_GLUT"};    
  138.     glutInit(&zwg_argc, zwg_argv);   
  139.   
  140.     //设置显示模型  
  141.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA /*| GLUT_STENCIL | GLUT_DEPTH*/);  
  142.     //设置在屏幕上的起始位置  
  143.     glutInitWindowPosition(m_window_x, m_window_y);  
  144.     //设置显示窗口大小,宽高  
  145.     glutInitWindowSize(m_screen_width, m_screen_height);  
  146.     //设置显示窗口名称  
  147.     glutCreateWindow("Lvs_OpenGl");  
  148.   
  149.     //OpenGL扩展库是个简单的工具,opengl纹理程序用的着色程序初始化  
  150.     GLenum lvs_glew = glewInit();  
  151.   
  152.     //输出版本号  
  153.     printf("OpenGl Version: %s\n", glGetString(GL_VERSION));  
  154.   
  155.     //设置绘制窗口时候接收消息的回调函数  
  156.     glutDisplayFunc(m_windowrepaintcallback);  
  157.   
  158.     ret = 1;  
  159.     return ret;  
  160. }  
  161.   
  162. void cclass_opengl_interface::InitShaders()  
  163. {  
  164.     GLint vertCompiled, fragCompiled;  //调试 shader的返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。  
  165.     GLuint p;      //Program着色器程序的id  
  166.     GLint linked;  //调试 param的返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。  
  167.   
  168.     GLint v, f;  //shader的id;  
  169.     char vs[1024 *10] = {0}; //shader源码的字串vsh 是Vertex Shader(顶点着色器)  
  170.     char fs[1024 *10] = {0}; //shader源码的字串fsh 是Fragment Shader(片元着色器)    
  171.     const char * vs_buf = vs;  
  172.     const char * fs_buf = fs;  
  173.   
  174.     //shader的处理类似于将OpenGL Shader Language,简称GLSL的源码编译成2进制程序  
  175.     //“vsh负责搞定像素位置,填写gl_Posizion;fsh负责搞定像素外观,填写 gl_FragColor。”  
  176.     //Shader: step1 创建两个shader 实例。  
  177.     v = glCreateShader(GL_VERTEX_SHADER);  
  178.     f = glCreateShader(GL_FRAGMENT_SHADER);  
  179.     //着色器源码  
  180.     //penGL的着色器有.fsh和.vsh两个文件。这两个文件在被编译和链接后就可以产生可执行程序与GPU交互。  
  181.     //shader.vsh 是Vertex Shader(顶点着色器),用于顶点计算,可以理解控制顶点的位置,在这个文件中我们通常会传入当前顶点的位置,和纹理的坐标。  
  182.     //shader.fsh 是Fragment Shader(片源着色器),在这里面我可以对于每一个像素点进行重新计算。  
  183.     //将Vertex Shader和Fragment Shader源码读取到字符串中。  
  184.     FILE * infile_vsh = fopen(m_shader_vsh_pathname, "rb");  
  185.     int len_vsh = fread((char *)vs, 1, 1024 *10, infile_vsh);  
  186.     fclose(infile_vsh);  
  187.     infile_vsh = NULL;  
  188.     vs[len_vsh] = 0;  
  189.     FILE * infile_fsh = fopen(m_shader_fsh_pathname, "rb");  
  190.     int len_fsh = fread((char *)fs, 1, 1024 *10, infile_fsh);  
  191.     fclose(infile_fsh);  
  192.     infile_fsh = NULL;  
  193.     vs[len_fsh] = 0;  
  194.     //Shader: step2 给Shader实例指定源码。  
  195.     glShaderSource(v, 1, &vs_buf,NULL);  
  196.     glShaderSource(f, 1, &fs_buf,NULL);  
  197.     //Shader: step3 在线编译Shader源码。  
  198.     glCompileShader(v);  
  199.     //Shader: step4 调试一个Shader  
  200.     //void glGetShaderiv(   GLuint shader,GLenum pname,GLint *params);  
  201.     //params:返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。  
  202.     glGetShaderiv(v, GL_COMPILE_STATUS, &vertCompiled);  
  203.     glCompileShader(f);  
  204.     glGetShaderiv(f, GL_COMPILE_STATUS, &fragCompiled);  
  205.   
  206.     //Program有点类似于一个程序的链接器。program对象提供了把需要做的事连接在一起的机制。在一个program中,shader对象可以连接在一起。  
  207.     //Program 这个类似于运行OpenGL Shader Language,简称GLSL的源码编译成2进制程序的执行环境,链接器  
  208.     //Program: Step1 创建program  
  209.     p = glCreateProgram();   
  210.     //Program: Step2 绑定shader到program  
  211.     glAttachShader(p,v);  
  212.     glAttachShader(p,f);   
  213.   
  214.     //通过glBindAttribLocation()把“顶点属性索引”绑定到“顶点属性名”   
  215.     glBindAttribLocation(p, ATTRIB_VERTEX, "vertexIn");  
  216.     //通过glBindAttribLocation()把“像素纹理属性索引”绑定到“像素纹理属性名”   
  217.     glBindAttribLocation(p, ATTRIB_TEXTURE, "textureIn");  
  218.     //Program: Step3 链接program  
  219.     glLinkProgram(p);  
  220.     //void glGetProgramiv (int program, int pname, int[] params, int offset)     
  221.     //参数含义:   
  222.     //  program:一个着色器程序的id;   
  223.     //  pname:GL_LINK_STATUS;   
  224.     //  param:返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。  
  225.     glGetProgramiv(p, GL_LINK_STATUS, &linked);    
  226.     //Program: Step4 在链接了程序以后,我们可以使用glUseProgram()函数来加载并使用链接好的程序  
  227.     glUseProgram(p);  
  228.   
  229.     //获取片源着色器源码中的变量,用于纹理渲染  
  230.     m_textureUniformY = glGetUniformLocation(p, "tex_y");  
  231.     m_textureUniformU = glGetUniformLocation(p, "tex_u");  
  232.     m_textureUniformV = glGetUniformLocation(p, "tex_v");   
  233.   
  234.     //顶点数组(物体表面坐标取值范围是-1到1,数组坐标:左下,右下,左上,右上)  
  235. #if TEXTURE_ROTATE  
  236.     static const GLfloat vertexVertices[] = {  
  237.         -1.0f, -0.5f,  
  238.         0.5f, -1.0f,  
  239.         -0.5f,  1.0f,  
  240.         1.0f,  0.5f,  
  241.     };      
  242. #else  
  243.     static const GLfloat vertexVertices[] = {  
  244.         -1.0f, -1.0f,  
  245.         1.0f, -1.0f,  
  246.         -1.0f,  1.0f,  
  247.         1.0f,  1.0f,  
  248.     };      
  249. #endif  
  250.   
  251.     //像素,纹理数组(纹理坐标取值范围是0-1,坐标原点位于左下角,数组坐标:左上,右上,左下,右下,如果先左下,图像会倒过来)  
  252. #if TEXTURE_HALF  
  253.     static const GLfloat textureVertices[] = {  
  254.         0.0f,  1.0f,  
  255.         0.5f,  1.0f,  
  256.         0.0f,  0.0f,  
  257.         0.5f,  0.0f,  
  258.     };   
  259. #else  
  260.     static const GLfloat textureVertices[] = {  
  261.         0.0f,  1.0f,  
  262.         1.0f,  1.0f,  
  263.         0.0f,  0.0f,  
  264.         1.0f,  0.0f,  
  265.     };   
  266. #endif  
  267.   
  268.     //定义顶点数组  
  269.     glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);  
  270.     //启用属性数组  
  271.     glEnableVertexAttribArray(ATTRIB_VERTEX);   
  272.     //定义像素纹理数组  
  273.     glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);  
  274.     //启用属性数组  
  275.     glEnableVertexAttribArray(ATTRIB_TEXTURE);  
  276.   
  277.     //初始化纹理  
  278.     glGenTextures(1, &m_textureid_y);   
  279.     //绑定纹理  
  280.     glBindTexture(GL_TEXTURE_2D, m_textureid_y);      
  281.     //设置该纹理的一些属性  
  282.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
  283.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);  
  284.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
  285.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  
  286.   
  287.     glGenTextures(1, &m_textureid_u);  
  288.     glBindTexture(GL_TEXTURE_2D, m_textureid_u);     
  289.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
  290.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);  
  291.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
  292.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  
  293.   
  294.     glGenTextures(1, &m_textureid_v);   
  295.     glBindTexture(GL_TEXTURE_2D, m_textureid_v);      
  296.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
  297.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);  
  298.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
  299.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  
  300. }  
  301.   
  302. int cclass_opengl_interface::DisplayImage(void * parm)  
  303. {  
  304.     int ret = 0;  
  305.   
  306.     unsigned char * yuvplaner[3] = {0};                             //存放yuv数据的分量数组(y,u,v)   
  307.     //关联到yuv数据的分量数组  
  308.     yuvplaner[0] = (unsigned char *)m_yuvbuf;  
  309.     yuvplaner[1] = yuvplaner[0] + m_yuvdata_width*m_yuvdata_height;  
  310.     yuvplaner[2] = yuvplaner[1] + m_yuvdata_width*m_yuvdata_height/4;  
  311.   
  312.     //Clear  
  313.     //清除颜色设为黑色,把整个窗口清除为当前的清除颜色,glClear()的唯一参数表示需要被清除的缓冲区。  
  314.     glClearColor(0.0,0.0,0.0,0.0);  
  315.     glClear(GL_COLOR_BUFFER_BIT);  
  316.   
  317.     //显卡中有N个纹理单元(具体数目依赖你的显卡能力),每个纹理单元(GL_TEXTURE0、GL_TEXTURE1等)都有GL_TEXTURE_1D、GL_TEXTURE_2D等     
  318.     //Y  
  319.     //选择当前活跃的纹理单元  
  320.     glActiveTexture(GL_TEXTURE0);  
  321.     //允许建立一个绑定到目标纹理的有名称的纹理  
  322.     glBindTexture(GL_TEXTURE_2D, m_textureid_y);  
  323.     //根据指定的参数,生成一个2D纹理(Texture)。相似的函数还有glTexImage1D、glTexImage3D。  
  324.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_yuvdata_width, m_yuvdata_height, 0, GL_RED, GL_UNSIGNED_BYTE, yuvplaner[0]);   
  325.     glUniform1i(m_textureUniformY, 0);     //设置纹理,按照前面设置的规则怎样将图像或纹理贴上(参数和选择的活跃纹理单元对应,GL_TEXTURE0)  
  326.       
  327.     //U  
  328.     glActiveTexture(GL_TEXTURE1);  
  329.     glBindTexture(GL_TEXTURE_2D, m_textureid_u);  
  330.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_yuvdata_width/2, m_yuvdata_height/2, 0, GL_RED, GL_UNSIGNED_BYTE, yuvplaner[1]);         
  331.     glUniform1i(m_textureUniformU, 1);  
  332.     //V  
  333.     glActiveTexture(GL_TEXTURE2);  
  334.     glBindTexture(GL_TEXTURE_2D, m_textureid_v);  
  335.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_yuvdata_width/2, m_yuvdata_height/2, 0, GL_RED, GL_UNSIGNED_BYTE, yuvplaner[2]);      
  336.     glUniform1i(m_textureUniformV, 2);   
  337.   
  338.     // 绘制  
  339.     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  
  340.     //双缓冲显示  
  341.     glutSwapBuffers();  
  342.     //单缓冲显示  
  343.     //glFlush();  
  344.   
  345.     return 1;  
  346. }  
  347.   
  348. void cclass_opengl_interface::messageloop()  
  349. {  
  350.     //glutMainLoop进入GLUT事件处理循环,让所有的与“事件”有关的函数调用无限循环。开始时间循环  
  351.     glutMainLoop();  
  352. }  

//main.cpp

[cpp]  view plain  copy
  1. #include "Lvs_OpenGl_Interface.h"  
  2.   
  3. //要显示的yuv文件路径及名称  
  4. #define YUV_STREAM_PATH_NAME  "../yuv_stream/352_288_yuv420p.yuv"  
  5. //yuv数据宽  
  6. #define YUVDATA_WIDTH  352   
  7. //yuv数据高  
  8. #define YUVDATA_HEIGHT 288  
  9. //shader的vsh源码位置  
  10. #define SHADER_VSH_SOURCE  "../opengl_win32/Shader.vsh"  
  11. //shader的fsh源码位置  
  12. #define SHADER_FSH_SOURCE  "../opengl_win32/Shader.fsh"  
  13.   
  14. static FILE * m_inyuvfile = NULL;                                       //yuv文件句柄  
  15. static unsigned char m_yuvbuf[YUVDATA_WIDTH*YUVDATA_HEIGHT*3/2];        //存放yuv数据的buf  
  16. static unsigned char * m_yuvplane[3] = {0};                             //存放yuv数据的分量数组(y,u,v)   
  17. static int m_timer_realtime = 40;                                       //每一次回调渲染数据定时器时间,可根据时间戳变化,毫秒  
  18.   
  19.   
  20. //窗口重绘的时候,例如最大化最小化窗口,缩放窗口等让窗口重绘的时候调用。  
  21. //从而接收消息循环  
  22. void WindowRepaintCallback();  
  23. //回调读取数据函数,参数数据及时间戳  
  24. int DisplayDataCallback(void * data,int * timer_millis);  
  25.   
  26. //窗口重绘的时候,例如最大化最小化窗口,缩放窗口等让窗口重绘的时候调用。  
  27. //从而接收消息循环  
  28. void WindowRepaintCallback()  
  29. {  
  30.     //可以做一些处理  
  31.     printf("窗口重绘了...\n");  
  32. }  
  33.   
  34. int DisplayDataCallback(void ** data,int * timer_millis)  
  35. {  
  36.     int ret = 0;  
  37.   
  38.     //循环读取文件  
  39.     ret = fread(m_yuvbuf, 1, YUVDATA_WIDTH*YUVDATA_HEIGHT*3/2, m_inyuvfile);  
  40.     if (ret != YUVDATA_WIDTH*YUVDATA_HEIGHT*3/2)  
  41.     {  
  42.         //seek到文件开头  
  43.         fseek(m_inyuvfile, 0, SEEK_SET);  
  44.         fread(m_yuvbuf, 1,YUVDATA_WIDTH*YUVDATA_HEIGHT*3/2, m_inyuvfile);  
  45.     }  
  46.   
  47.     //将数据返回去  
  48.     *data = m_yuvbuf;  
  49.     *timer_millis = m_timer_realtime;  
  50.   
  51.     return ret;  
  52. }  
  53.   
  54. int main()  
  55. {  
  56.     int ret = 0;  
  57.   
  58.     //打开 YUV420P 文件  
  59.     if((m_inyuvfile = fopen(YUV_STREAM_PATH_NAME, "rb")) == NULL)  
  60.     {  
  61.         printf("filed open file : %s\n",YUV_STREAM_PATH_NAME);  
  62.         return getchar();  
  63.     }  
  64.     else  
  65.     {  
  66.         printf("success open file : %s\n",YUV_STREAM_PATH_NAME);  
  67.     }  
  68.   
  69.     //初始化  
  70.     ret = lvs_opengl_interface_init(500,500,  
  71.             100,100,  
  72.             YUVDATA_WIDTH,YUVDATA_HEIGHT,  
  73.             SHADER_VSH_SOURCE,SHADER_FSH_SOURCE,  
  74.             DisplayDataCallback,  
  75.             WindowRepaintCallback);  
  76.   
  77.     //渲染,带定时器,数据回调,及渲染时间回调  
  78.     lvs_opengl_interface_write(m_timer_realtime);  
  79.   
  80.     //glutMainLoop进入GLUT事件处理循环,让所有的与“事件”有关的函数调用无限循环。开始时间循环  
  81.     lvs_opengl_interface_messageloop();  
  82.   
  83.     //关闭yuv420p文件  
  84.     if (m_inyuvfile != NULL)  
  85.     {  
  86.         fclose(m_inyuvfile);  
  87.         m_inyuvfile = NULL;  
  88.     }  
  89.       
  90.     return 1;  
  91. }  


程序运行效果:



暂时不知道怎么解决类成员函数递归,以后待解决。


本demo还需完善。

如有错误请指正:

交流请加QQ群:62054820
QQ:379969650.


猜你喜欢

转载自blog.csdn.net/maigao1/article/details/79229690
今日推荐