不过简易的视音频播放示例5:OpenGL播放RGB/YUV

本文记录OpenGL播放视频的艺。OpenGL是一个及Direct3D同一层面的技术。相比于Direct3D,OpenGL具有超过平台的优势。尽管以嬉戏世界,DirectX的影响力已慢慢超越OpenGL并为大部分PC游戏开发商所动,但当正儿八经高端绘图领域,OpenGL因为色彩准确,仍然是不可知叫代表的骨干。

图片 1

OpenGL简介

自网上征集了有有关OpenGL简介方面的学识,在此处列下。
开图形库(英语:Open Graphics
Library,缩写为OpenGL)是单概念了一个跨编程语言、跨平台的应用程序接口(API)的专业,它用来生成二维、三维图像。
OpenGL规范由1992年成立之OpenGL架构评审委员会(ARB)维护。ARB由一些针对性创建一个合并的、普遍可用之API特别感谢兴趣的局组成。根据OpenGL官方网站,2002年6月底ARB投票成员包括3Dlabs、Apple
Computer、ATI Technologies、Dell Computer、Evans &
Sutherland、Hewlett-Packard、IBM、Intel、Matrox、NVIDIA、SGI和Sun
Microsystems,Microsoft曾是创建成员有,但曾经受2003年3月淡出。
OpenGL仍然是唯一能替代微软本着3D图形技术之完全控制的API。它依然具有一定的精力,但是Silicon
Graphics已经不复以任何让微软不悦的计推广OpenGL,因而它们在比较高的风险。在高端的图片设备和规范应用方面OpenGL占据着统治地位(Direct3D目前还无支持)。开放源码社区(尤其是Mesa项目)一直从为提供OpenGL支持。
 

OpenGL渲染管线

下文也是网上看之,搞明白了同等片段,但是由3D方面基础不稳固有些方面尚并未了将明白。

OpenGL渲染管线(OpenGL
Pipeline)按照一定的逐条对图纸信息进行拍卖,这些图片信息方可分为两独片:顶点信息(坐标、法向量等)和像素信息(图像、纹理等)。图形信息最终给描写入帧缓存中,存储于帧缓存中之数量(图像),可以为应用程序获得(用于保存结果,或当应用程序的输入等,见下图中灰色虚线)。

图片 2

Display List(显示列表)
来得列表是一律组OpenGL命令,被储存(编译)起来用于后续之执行。所有数据,几何(顶点)数据与像素数量都足以存入显示列表。数据以及指令缓存到展示列表中好增进性。
Vertex Operation(顶点处理)
及点坐标和法线坐标经过模式视图矩阵从物体坐标系(object
coordinates)转换为考察坐标系(eye
coordinates)。若启用了光照,对转移后的稳定及法线坐标执行光照计算。光照计算更新了终点的颜色值。

图片 3

Primitive Assembly(图元装配)

极限处理后,基本图元(点、线、多边形)经过投影矩阵变换,再吃视见体裁剪平面裁剪,从考察坐标系转换为裁剪坐标系。之后,进行透视除法(除以w)和视口变换(viewport
transform),将3d场景投影到窗口坐标系。

Pixel Transfer Operation(像素操作)

像素从客户内存中解包出来下,要通过缩放、偏移、映射、箝拉(clamping)。这些处理就为像素转换操作。转换的数额有纹理内存还是直接通过光栅化转为片段(fragment)。

Texture Memory(纹理内存)

纹理图像载入到纹理内存中,然后利用至几乎哪对象及。 

Raterization(光栅化)

光栅化就是拿几哪里(顶点坐标等)和像素数量易为片(fragment)的历程,每个片对应于帧缓冲区中的一个像素,该像素对应屏幕及一些之颜色跟莫透明度信息。片段是一个矩形数组,包含了颜色、深度、线宽、点的深浅相等信息(反锯齿计算相当于)。如果渲染模式于装置也GL_FILL,多边形内部的像素信息于此阶段会被填。

图片 4

如若齐图备受的三角形,输入三角形的老三个极坐标以及那颜色,顶点操作会对三角形的极限坐标以及法向量进行转移,颜色信息不需要经变换,但光照计算会影响顶点的颜色信息。经过光栅化后,三角形被离散为一个个接触,不以是三独坐标表示,而是由于同样雨后春笋之触发构成,每个点储存了对应的水彩、深度和不透明度等信息。
 
Fragment Operation(片段操作)
当下是用有些转为帧缓冲区中的像素要进行的末段处理。首先是纹理单元(texel)生成。一个纹理单元由纹理内存中的数码变动,然后用及每个有及。之后进行雾计算。
雾计算好后,还要照次进行多少部分测试,依次为蒙板(scissor)测试,alpha测试,模版(stencil)测试,深度测试。最后,执行混合,抖动,逻辑操作与屏蔽操作,最终的例如素存入framebuffer。
 

OpenGL与Direct3D的对比

关于视频展示的技能于《Direct3D》文章被就生了叙述,在这里不再另行。在网上看了瞬间有关于他们不同点的稿子,写得简单明了,在此处引用一下:
OpenGL与Direct3D的一点点对照
OGL比D3D好之地方:
OGL是业界规范,许多非Windows操作系统下还摸索不顶D3D
OGL的情调比D3D的和睦,表面还光滑
OGL的函数很有规律,不像D3D的,都是恃针method,函数叫作最长了!!
OGL是右手坐标系,这是数学里之所以惯了底.D3D虽然为可以转成右坐标系,但是需要d3dx9_36.dll的支持
OGL的常用Matrix,如WorldMatrix都打包好了,D3D要协调写。
OGL的绘图方式要命灵敏,而D3D的尽管只要优先定义好FVF,要对等有消息写上Stream中才绘制。这即使它们发了VertexBuffer和IndexBuffer.好象微软厌恶D3D的Buffer不够多?搞的多糟糕学??看户OGL,哪里而之事物?
D3D有那么些本,要是显卡不支持就废柴一垛了。而OGL从几年前哪怕径直没有换了,所以大部分显卡都支持。
再有,我发觉D3D的半透明功能有不行特别之题目!!就是鲜单半晶莹剔透底体前后相继的题目——前面的相会受后的遮挡。
 
而D3D也来比OGL好的地方:
D3D支持多格式的图片文件,而OGL载入jpg都得和谐写代码。
为D3D是指针调用模式,所以做D3D的钩有难度,从而增加了外挂的做难度。
D3D是DirectX的积极分子。程序员要促成动静播放可以就此DirectMusic,配套用连续好之,而OGL则只能写
D3D是于微软大力推广的连接库。相反,微软虽奋力抑制OGL(都是Microsoft参与研制出来的制品,待遇怎这么大?)
碰巧因是,D3D已化作中华大型游戏界的主流(我认为她们是不足为训跟风。其实国外众多游戏还是因此OGL)
 

OpenGL视频显示的流程

下OpenGL播放视频最为简单易行的情下需要如下步骤:
1.       初始化

1)         初始化
2)         创建窗口
3)         设置绘图函数
4)         设置定时器
5)         进入信息循环

2.       循环显示画面

1)       调整显示位置,图像大小
2)       画图
3)       显示

在此间有少数欲证实。即OpenGL不需用Direct3D那种以WinMain()作为主函数之先后初始化窗口。在Direct3D中是必须使这样做的,即祭Win32之窗口程序同时调用CreateWindow()创建一个会话框,然后才好于对话框上绘图。OpenGL只待采取普通的控制台程序即可(入口函数为main())。当然,OpenGL也可以像Direct3D那样将图像绘制在Win32顺序的窗口被。
 
下结合OpenGL播放YUV/RGB的言传身教代码,详细分析一下上文的流程。
以前述播放流程之前,再说一些融洽上OpenGL时候的一个显而易见的感到:OpenGL的函数好多呀。OpenGL的函数的特性是数码多,但是每个函数的参数少。而Direct3D的表征以及它正好反过来,函数少,但是每个函数的参数多。

1.       初始化

1)         初始化
glutInit()用于初始化glut库。它原型如下:

[cpp] view
plaincopy图片 5图片 6

 

  1. void glutInit(int *argcp, char **argv);  

其含两个参数:argcp和argv。一般景象下,直接把main()函数中的argc,argv传递给它们即可。
在这边大概介绍OpenGL中的3独仓库:glu,glut,glew
glu是实用库,包含有43个函数,函数称的前缀为glu。Glu
为了减轻繁重的编程工作,封装了OpenGL函数,Glu函数通过调用核心库的函数,为开发者提供相对简单的用法,实现有比较复杂的操作。
  glut是实用工具库,基本上是用于做窗口界面的,并且是跨平台的。

       
glew是一个跨平台的扩展库。不是必要的。它能自动识别当前平台所支持的全方位OpenGL高级扩展函数。还尚无深刻钻研。

glutInitDisplayMode()用于安装初始显示模式。它的原型如下。

[cpp] view
plaincopy图片 7图片 8

 

  1. void glutInitDisplayMode(unsigned int mode)  

其间mode可以选为下值或结:

GLUT_RGB: 指定 RGB 颜色模式之窗口
GLUT_RGBA: 指定 RGBA 颜色模式之窗口
GLUT_INDEX: 指定颜色索引模式之窗口
GLUT_SINGLE: 指定单缓存窗口
GLUT_DOUBLE: 指定双缓存窗口
GLUT_ACCUM: 窗口以累加缓存
GLUT_ALPHA: 窗口的颜料分量包含 alpha 值
GLUT_DEPTH: 窗口用深度缓存
GLUT_STENCIL: 窗口用模板缓存
GLUT_MULTISAMPLE: 指定支持多元随功能的窗口
GLUT_STEREO: 指定立体窗口
GLUT_LUMINANCE: 窗口以亮度颜色模型

待专注的是,如果利用对缓冲(GLUT_DOUBLE),则要用glutSwapBuffers
()绘图。如果用单缓冲(GLUT_SINGLE),则需用glFlush()绘图。
当运OpenGL播放视频的早晚,我们可运用下述代码:

[cpp] view
plaincopy图片 9图片 10

 

  1. glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );  

 
2)         创建窗口
glutInitWindowPosition()用于安装窗口的岗位。可以指定x,y坐标。
glutInitWindowSize()用于安装窗口的大大小小。可以安装窗口的富裕,高。
glutCreateWindow()创建一个窗口。可以指定窗口的题目。
上述几只函数十分基础,不再详细描述。直接贴发出一致截示例代码:

[cpp] view
plaincopy图片 11图片 12

 

  1. glutInitWindowPosition(100, 100);  
  2. glutInitWindowSize(500, 500);  
  3. glutCreateWindow("Simplest Video Play OpenGL");        

 
3)         设置绘图函数
glutDisplayFunc()用于安装绘图函数。操作系统在必要时刻就是会调用该函数对窗体进行重复绘制操作。类似于windows程序设计中拍卖WM_PAINT消息。例如,当把窗口移动至屏幕边上,然后还要倒回来的时光,就见面调用该函数对窗口进行重绘。它的原型如下。

 

[cpp] view
plaincopy图片 13图片 14

 

  1. void glutDisplayFunc(void (*func)(void));  

 

其中(*func)用于指定重绘函数。

像当视频播放的时刻,指定display()函数用于重绘:

[cpp] view
plaincopy图片 15图片 16

 

  1. glutDisplayFunc(&display);  

4)         设置定时器
广播视频的上,每秒需要播放一定的画面(一般是25帧),因此使用定时器每间隔一段时间调用一下绘制函数绘制图形。定时器函数glutTimerFunc()的原型如下。

[cpp] view
plaincopy图片 17图片 18

 

  1. void glutTimerFunc(unsigned int millis, void (*func)(int value), int value);  

其的参数含义如下:
millis:定时底日,单位是毫秒。1秒=1000毫秒。
(*func)(int value):用于指定定时器调用的函数。
value:给回调函数传参。比较高端,没有接触了。
而仅仅以主函数着形容一个glutTimerFunc()函数的言语,会发觉只有见面调用该函数平次。因此待以回调函数中重新写一个glutTimerFunc()函数,并调用回调函数自己。只有这样才会促成重复循环调用回调函数。
比如在视频播放的时段,指定每40毫秒调用一不行timeFunc ()函数:
主函数吃:

[cpp] view
plaincopy图片 19图片 20

 

  1. glutTimerFunc(40, timeFunc, 0);  

尔后在timeFunc()函数中如下设置。

[cpp] view
plaincopy图片 21图片 22

 

  1. void timeFunc(int value){  
  2.     display();  
  3.     // Present frame every 40 ms  
  4.     glutTimerFunc(40, timeFunc, 0);  
  5. }  

如此即便兑现了各40ms调用同次于display()。
 
5)         进入信息循环
glutMainLoop()将会晤进入GLUT事件处理循环。一旦被调用,这个顺序将永久不见面回到。视频播放的时光,调用该函数之后就起来播放视频。
 

2.       循环显示画面

1)       调整显示位置,图像大小
当时等同步要是调动一下图像的大大小小以及职务。如果不举行就同步而一直以glDrawPixels()进行绘图的说话,会发觉图像在窗口的左下角,而且是上下颠倒的(当然,如果窗口及图像一样大之口舌,就不在图像在角落的题材)。效果使下图所著。

图片 23

为解决上述问题,需要调用有关的函数对图像进行转移。变换用到了点滴单函数:glRasterPos3f()和glPixelZoom()。
glRasterPos3f()可以活动图像。它的原型如下。

[cpp] view
plaincopy图片 24图片 25

 

  1. void glRasterPos3f (GLfloat x, GLfloat y, GLfloat z);  

其中x用于指定x坐标;y用于指定y坐标。Z这里还未曾因此到。
在此间介绍一下OpenGL的坐标。原点位于屏幕的中心。屏幕的沿对应之价是1.0。和数学中之坐标系基本上是平的。屏幕的左下角是(-1,-1),左上角是(-1,1)。

图片 26

比如说我们采取glRasterPos3f(-1.0f,0.0f,0),图像就会见走及(-1,0),如下图所著。

图片 27

glPixelZoom()可以放开、缩小同扭转图像。它的原型如下。

[cpp] view
plaincopy图片 28图片 29

 

  1. void glPixelZoom (GLfloat xfactor, GLfloat yfactor);  

内xfactor、yfactor用于指定在x轴,y轴上放的翻番(如果数值低于1虽然是压缩)。如果指定负值,则好实现转。上文已经说了,使用OpenGL直接显示像从数据吧,会发现图像是反着的。因此待在Y轴方向对图像进行翻转。

比如说:像素数据的丰厚高分别吗pixel_w ,pixel_h
;窗口大小也screen_w,screen_h的话,使用下述代码可以将图像拉伸到窗口大小,并且扭:

[cpp] view
plaincopy图片 30图片 31

 

  1. glPixelZoom((float)screen_w/(float)pixel_w, -(float)screen_h/pixel_h);  

重组上述两单函数,即“平移+翻转+拉伸之后”,就得取全屏的图像了,如下图所显示。

图片 32

 

PS:这个点子属于比较笨的方,应该还有复好的法吧。不过又没开展深刻钻研了。

 

2)       画图
运用glDrawPixels()可以绘制指定内存中的像素数量。该函数的原型如下。

[cpp] view
plaincopy图片 33图片 34

 

  1. void glDrawPixels (  
  2. GLsizei width, GLsizei height,  
  3. GLenum format,  
  4. GLenum type,  
  5. const GLvoid *pixels);  

欠函数的参数的义如下所示:
Width:像素数据的松动。
Height:像素数据的高。
Format:像素数据的格式,例如GL_RGB,GL_BGR,GL_BGRA等。
Type:像从数据在内存中的格式。
Pixels:指针,指向存储像素数据的内存。
像绘制RGB24格式的多少,宽为pixel_w,高为pixel_h,像从数据存储在buffer中。可以使如下代码。

[cpp] view
plaincopy图片 35图片 36

 

  1. glDrawPixels(pixel_w, pixel_h,GL_RGB, GL_UNSIGNED_BYTE, buffer);  

 
3)       显示
下对缓冲的时光,调用函数glutSwapBuffers()进行展示。
应用单缓冲的下,调用函数glFlush()进行亮。
 
 

视频展示的流水线总结

视频展示的函数调用结构可以总结为产图

图片 37

 

代码

贴上源代码。

 

[cpp] view
plaincopy图片 38图片 39

 

  1. /** 
  2.  * 最简便的OpenGL播放视频的例子(OpenGL播放RGB/YUV) 
  3.  * Simplest Video Play OpenGL (OpenGL play RGB/YUV)  
  4.  * 
  5.  * 雷霄骅 Lei Xiaohua 
  6.  * leixiaohua1020@126.com 
  7.  * 中国传媒大学/数字电视技术 
  8.  * Communication University of China / Digital TV Technology 
  9.  * http://blog.csdn.net/leixiaohua1020 
  10.  * 
  11.  * 本程序用OpenGL播放RGB/YUV视频像素数据。本程序实际上只能 
  12.  * 播放RGB(RGB24,BGR24,BGRA)数据。如果输入数据也YUV420P 
  13.  * 数据以来,需要事先易为RGB数据后再也开展广播。 
  14.  * 本程序是极致简单易行的以OpenGL播放像素数据的事例,适合OpenGL新手学习。 
  15.  * 
  16.  * 函数调用步骤如下:  
  17.  * 
  18.  * [初始化] 
  19.  * glutInit(): 初始化glut库。 
  20.  * glutInitDisplayMode(): 设置显示模式。 
  21.  * glutCreateWindow(): 创建一个窗口。 
  22.  * glutDisplayFunc(): 设置绘图函数(重绘的下调用)。 
  23.  * glutTimerFunc(): 设置定时器。 
  24.  * glutMainLoop(): 进入信息循环。 
  25.  * 
  26.  * [巡回渲染数据] 
  27.  * glRasterPos3f(),glPixelZoom(): 调整显示位置,图像大小。 
  28.  * glDrawPixels(): 绘制。 
  29.  * glutSwapBuffers(): 显示。 
  30.  * 
  31.  * This software plays RGB/YUV raw video data using OpenGL. This 
  32.  * software support show RGB (RGB24, BGR24, BGRA) data on the screen. 
  33.  * If the input data is YUV420P, it need to be convert to RGB first. 
  34.  * This program is the simplest example about play raw video data 
  35.  * using OpenGL, Suitable for the beginner of OpenGL. 
  36.  * 
  37.  * The process is shown as follows: 
  38.  * 
  39.  * [Init] 
  40.  * glutInit(): Init glut library. 
  41.  * glutInitDisplayMode(): Set display mode. 
  42.  * glutCreateWindow(): Create a window. 
  43.  * glutDisplayFunc(): Set the display callback. 
  44.  * glutTimerFunc(): Set timer. 
  45.  * glutMainLoop(): Start message loop. 
  46.  * 
  47.  * [Loop to Render data] 
  48.  * glRasterPos3f(),glPixelZoom(): Change picture's size and position. 
  49.  * glDrawPixels(): draw. 
  50.  * glutSwapBuffers(): show. 
  51.  */  
  52.   
  53. #include <stdio.h>  
  54.   
  55. #include "glew.h"  
  56. #include "glut.h"  
  57.   
  58. #include <stdlib.h>  
  59. #include <malloc.h>  
  60. #include <string.h>  
  61.   
  62. //set '1' to choose a type of file to play  
  63. #define LOAD_RGB24   1  
  64. #define LOAD_BGR24   0  
  65. #define LOAD_BGRA    0  
  66. #define LOAD_YUV420P 0  
  67.   
  68. int screen_w=500,screen_h=500;  
  69. const int pixel_w = 320, pixel_h = 180;  
  70. //Bit per Pixel  
  71. #if LOAD_BGRA  
  72. const int bpp=32;  
  73. #elif LOAD_RGB24|LOAD_BGR24  
  74. const int bpp=24;  
  75. #elif LOAD_YUV420P  
  76. const int bpp=12;  
  77. #endif  
  78. //YUV file  
  79. FILE *fp = NULL;  
  80. unsigned char buffer[pixel_w*pixel_h*bpp/8];  
  81. unsigned char buffer_convert[pixel_w*pixel_h*3];  
  82.   
  83. inline unsigned char CONVERT_ADJUST(double tmp)  
  84. {  
  85.     return (unsigned char)((tmp >= 0 && tmp <= 255)?tmp:(tmp < 0 ? 0 : 255));  
  86. }  
  87. //YUV420P to RGB24  
  88. void CONVERT_YUV420PtoRGB24(unsigned char* yuv_src,unsigned char* rgb_dst,int nWidth,int nHeight)  
  89. {  
  90.     unsigned char *tmpbuf=(unsigned char *)malloc(nWidth*nHeight*3);  
  91.     unsigned char Y,U,V,R,G,B;  
  92.     unsigned char* y_planar,*u_planar,*v_planar;  
  93.     int rgb_width , u_width;  
  94.     rgb_width = nWidth * 3;  
  95.     u_width = (nWidth >> 1);  
  96.     int ypSize = nWidth * nHeight;  
  97.     int upSize = (ypSize>>2);  
  98.     int offSet = 0;  
  99.   
  100.     y_planar = yuv_src;  
  101.     u_planar = yuv_src + ypSize;  
  102.     v_planar = u_planar + upSize;  
  103.   
  104.     for(int i = 0; i < nHeight; i++)  
  105.     {  
  106.         for(int j = 0; j < nWidth; j ++)  
  107.         {  
  108.             // Get the Y value from the y planar  
  109.             Y = *(y_planar + nWidth * i + j);  
  110.             // Get the V value from the u planar  
  111.             offSet = (i>>1) * (u_width) + (j>>1);  
  112.             V = *(u_planar + offSet);  
  113.             // Get the U value from the v planar  
  114.             U = *(v_planar + offSet);  
  115.   
  116.             // Cacular the R,G,B values  
  117.             // Method 1  
  118.             R = CONVERT_ADJUST((Y + (1.4075 * (V - 128))));  
  119.             G = CONVERT_ADJUST((Y - (0.3455 * (U - 128) - 0.7169 * (V - 128))));  
  120.             B = CONVERT_ADJUST((Y + (1.7790 * (U - 128))));  
  121.             /* 
  122.             // The following formulas are from MicroSoft' MSDN 
  123.             int C,D,E; 
  124.             // Method 2 
  125.             C = Y - 16; 
  126.             D = U - 128; 
  127.             E = V - 128; 
  128.             R = CONVERT_ADJUST(( 298 * C + 409 * E + 128) >> 8); 
  129.             G = CONVERT_ADJUST(( 298 * C - 100 * D - 208 * E + 128) >> 8); 
  130.             B = CONVERT_ADJUST(( 298 * C + 516 * D + 128) >> 8); 
  131.             R = ((R - 128) * .6 + 128 )>255?255:(R - 128) * .6 + 128;  
  132.             G = ((G - 128) * .6 + 128 )>255?255:(G - 128) * .6 + 128;  
  133.             B = ((B - 128) * .6 + 128 )>255?255:(B - 128) * .6 + 128;  
  134.             */  
  135.             offSet = rgb_width * i + j * 3;  
  136.   
  137.             rgb_dst[offSet] = B;  
  138.             rgb_dst[offSet + 1] = G;  
  139.             rgb_dst[offSet + 2] = R;  
  140.         }  
  141.     }  
  142.     free(tmpbuf);  
  143. }  
  144.   
  145. void display(void){  
  146.     if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){  
  147.         // Loop  
  148.         fseek(fp, 0, SEEK_SET);  
  149.         fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);  
  150.     }  
  151.   
  152.     //Make picture full of window  
  153.     //Move to(-1.0,1.0)  
  154.     glRasterPos3f(-1.0f,1.0f,0);  
  155.     //Zoom, Flip  
  156.     glPixelZoom((float)screen_w/(float)pixel_w, -(float)screen_h/(float)pixel_h);  
  157.       
  158.   
  159.   
  160. #if LOAD_BGRA  
  161.     glDrawPixels(pixel_w, pixel_h,GL_BGRA, GL_UNSIGNED_BYTE, buffer);  
  162. #elif LOAD_RGB24  
  163.     glDrawPixels(pixel_w, pixel_h,GL_RGB, GL_UNSIGNED_BYTE, buffer);  
  164. #elif LOAD_BGR24  
  165.     glDrawPixels(pixel_w, pixel_h,GL_BGR_EXT, GL_UNSIGNED_BYTE, buffer);  
  166. #elif LOAD_YUV420P  
  167.     CONVERT_YUV420PtoRGB24(buffer,buffer_convert,pixel_w,pixel_h);  
  168.     glDrawPixels(pixel_w, pixel_h,GL_RGB, GL_UNSIGNED_BYTE, buffer_convert);  
  169. #endif  
  170.     //GLUT_DOUBLE  
  171.     glutSwapBuffers();  
  172.   
  173.     //GLUT_SINGLE  
  174.     //glFlush();  
  175. }  
  176.   
  177. void timeFunc(int value){  
  178.     display();  
  179.     // Present frame every 40 ms  
  180.     glutTimerFunc(40, timeFunc, 0);  
  181. }  
  182.   
  183.   
  184.   
  185. int main(int argc, char* argv[])  
  186. {  
  187. #if LOAD_BGRA  
  188.     fp=fopen("../test_bgra_320x180.rgb","rb+");  
  189. #elif LOAD_RGB24  
  190.     fp=fopen("../test_rgb24_320x180.rgb","rb+");  
  191. #elif LOAD_BGR24  
  192.     fp=fopen("../test_bgr24_320x180.rgb","rb+");  
  193. #elif LOAD_YUV420P  
  194.     fp=fopen("../test_yuv420p_320x180.yuv","rb+");  
  195. #endif  
  196.     if(fp==NULL){  
  197.         printf("Cannot open this file.\n");  
  198.         return -1;  
  199.     }  
  200.   
  201.     // GLUT init  
  202.     glutInit(&argc, argv);    
  203.     //Double, Use glutSwapBuffers() to show  
  204.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );  
  205.     //Single, Use glFlush() to show  
  206.     //glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );  
  207.   
  208.     glutInitWindowPosition(100, 100);  
  209.     glutInitWindowSize(screen_w, screen_h);  
  210.     glutCreateWindow("Simplest Video Play OpenGL");  
  211.     printf("Simplest Video Play OpenGL\n");  
  212.     printf("Lei Xiaohua\n");  
  213.     printf("http://blog.csdn.net/leixiaohua1020\\n");  
  214.     printf("OpenGL Version: %s\n", glGetString(GL_VERSION));  
  215.   
  216.     glutDisplayFunc(&display);  
  217.     glutTimerFunc(40, timeFunc, 0);   
  218.       
  219.     // Start!  
  220.     glutMainLoop();  
  221.   
  222.     return 0;  
  223. }  

 

 

 

 

代码注意事项

  1.      
    可以由此安装定义在文件开始起的偌大,决定读取哪个格式的像素数量(bgra,rgb24,bgr24,yuv420p)。
     

[cpp] view
plaincopy图片 40图片 41

 

  1. //set '1' to choose a type of file to play  
  2. #define LOAD_RGB24   1  
  3. #define LOAD_BGR24   0  
  4. #define LOAD_BGRA    0  
  5. #define LOAD_YUV420P 0  

 

  1.      
    窗口的丰厚高呢screen_w,screen_h。像素数据的充盈高为pixel_w,pixel_h。它们的定义如下。
     

[cpp] view
plaincopy图片 42图片 43

 

  1. //Width, Height  
  2. const int screen_w=500,screen_h=500;  
  3. const int pixel_w=320,pixel_h=180;  
  1.       注意显示方式的不同
    BGRA,BGR24,RGB24这3栽格式可以直接在glDrawPixels()中装置像素格式显示出。而YUV420P凡是不能够一直展示出的。本文示例采用的措施是预先拿YUV420P转移成RGB24,然后开展亮。

运作结果

任凭选择加载哪个文件,运行结果都是同样的,如下图所展示。

图片 44

 

下载

代码位于“Simplest Media Play”中
 
 

SourceForge项目地址:https://sourceforge.net/projects/simplestmediaplay/

CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8054395

 
 

上述工程包含了使各种API(Direct3D,OpenGL,GDI,DirectSound,SDL2)播放多媒体例子。其中音频输入为PCM采样数据。输出到系统的声卡播放出来。视频输入为YUV/RGB像素数据。输出到显示器上之一个窗口播放出来。

通过本工程的代码初家可以快捷学习运用这几乎单API播放视频与旋律的技术。

共计包括了之类几单子工程:

simplest_audio_play_directsound:        
使用DirectSound播放PCM音频采样数据。
simplest_audio_play_sdl2:                      
使用SDL2播放PCM音频采样数据。
simplest_video_play_direct3d:              
 使用Direct3D的Surface播放RGB/YUV视频像素数据。
simplest_video_play_direct3d_texture:使用Direct3D的Texture播放RGB视频像素数据。
simplest_video_play_gdi:                        
 使用GDI播放RGB/YUV视频像素数据。
simplest_video_play_opengl:                  
使用OpenGL播放RGB/YUV视频像素数据。
simplest_video_play_opengl_texture:  
 使用OpenGL的Texture播放YUV视频像素数据。
simplest_video_play_sdl2:                      
 使用SDL2播放RGB/YUV视频像素数据。
 

 

from:http://blog.csdn.net/leixiaohua1020/article/details/40333583

相关文章

Comment ()
评论是一种美德,说点什么吧,否则我会恨你的。。。