===================================================
前言
近期研究了一下Windows平台下的视音频播放的技术。
在Windows平台下的视频播放技术主要有下面三种:GDI,Direct3D和OpenGL。音频播放技术主要是DirectSound。这些技术属于比較底层的技术。因此使用起来相对来说还是比較复杂的。我在学习的过程中也发现这一领域一直缺少比較简单直观的演示样例程序。因此打算做些演示样例程序,同一时候写一些相关的文章。方便这一领域的人学习相关的知识。
打算重点记录一下视频播放的技术。之前的研究一直集中于视频的编解码方面的技术,而非常少接触到视频播放显示方面的技术。此前的程序一直採用了调用SDL的方式播放显示视频画面。而其实,SDL本身并不具有播放显示的功能。它仅仅是封装了底层播放显示的代码。为了做到“知其然知其所以然”。须要分析一下视频播放的底层技术。
在Windows平台下视频的播放显示主要能够使用下面两种技术:Direct3D和OpenGL。以上两种显示技术是最好的。
除了以上两种之外,还有其它的选择。
比方说DirectDraw或者GDI。
可是微软已经停止了对DirectDraw的支持。
而GDI也并非主要用于视频显示领域(主要用于软件开发)。有关于他们这几个显示技术之间的比較的文章比較多,在这里不再细说。
计划写5篇文章记录三种视频显示技术:GDI,Direct3D,OpenGL。
当中Direct3D包括简单和复杂的两种显示方式:使用Surface和使用Texture。OpenGL也包括简单和复杂的两种显示方式:直接画像素和使用Texture。最后再写一篇文章记录一下使用SDL2显示视频的技术,与以上技术的代码做一个对照。须要注意的是,Direct3D,OpenGL这些技术在3D的领域拥有大量的功能。但这些功能并非这些文章的側重点。这些文章面向于视频技术人员而非3D游戏开发者。因而更加側重于它们在视频显示领域的应用。对于3D方面的功能则基本上会一笔带过。
先说一点我自己的感受。我发现作为一个搞视频技术的人研究Direct3D,OpenGL这些显示技术还是有一些困难的。一方面。虽然网络上有大量的Direct3D。OpenGL方面的资料(感觉比视频编解码领域的资料要多非常多),可是这些资料基本上都是面向于3D游戏编程的。
因而翻阅了大量的资料,会学到非常多和视频显示相关性不大的知识:比方说投影,光线等等。
虽然经过这样“坚持不懈”的学习。最后也能够掌握与视频显示相关性比較强的东西(比方说像纹理这方面的知识),可是这样会消耗掉大量的时间与精力。正可谓“时间就是金钱”,这样学习不是非常经济。还有一方面,虽然偶尔还是能够找到一些OpenGL,Direct3D的显示视频的样例。又比較复杂。这些样例基本上都是一些“大神”的劳动成果。
他们不但为了使用方便而对非常多函数进行了封装,并且还考虑到非常多可能出错的地方而写了非常多错误推断的语句。
这样做对于成熟的应用来说是一件好事,可是对新手来说却是一件坏事。因为过多的封装会让新手搞不清究竟哪些函数是Direct3D。OpenGL的API。哪些函数是“大神”后加的。而添加过多的错误推断等方面的语句之后代码会变得非常长。新手就非常难分辨出究竟哪些函数才是关键的API。因为以上问题的存在,使得Direct3D,OpenGL这些显示技术的学习门槛比較高。非常多人也不愿意投入太多的精力去研究它。
我记录这几篇文章正是为了解决之几方面的问题而写的。这几篇文章在知识叙述方面仅仅记录OpenGL,Direct3D中和视频显示相关的技术,其它方面的技术尽量不写。做到“功夫用在刀刃上”;在演示样例代码方面,尽量剔除无关紧要的代码。仅仅保留最关键的函数。相信这样会有助于很多其它的人学习视频显示方面的技术。
这几篇文章中的演示样例程序,输入都是YUV/RGB的像素数据(注意是没有文件头的那种),输出都是一个显示视频的窗体。
因为像素数据体积比較大,因此输入视频的长度非常短,仅仅有几秒钟。
Simplest Media Play
有关使用Direct3D,OpenGL,GDI。DirectSound这些技术播放视音频的代码已经整合到了一个名为“Simplest Media Play”的project里。
该project已经配置好并且包括了測试素材(YUV,RGB,PCM数据),直接执行就可以看到结果。
项目主页
SourceForge:https://sourceforge.net/projects/simplestmediaplay/
Github:https://github.com/leixiaohua1020/simplest_media_play
1.1版更新(2014.12.21)=====================
修复了一些小问题
SourceForge已经更新。
上述project包括了使用各种API(Direct3D,OpenGL。GDI,DirectSound。SDL2)播放多媒体样例。当中音频输入为PCM採样数据。输出至系统的声卡播放出来。视频输入为YUV/RGB像素数据。
输出至显示器上的一个窗体播放出来。
通过本project的代码刚開始学习的人能够高速学习使用这几个API播放视频和音频的技术。
一共包括了例如以下几个子project:
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视频像素数据。
project中除了几个子project的源码之外,还包括了下面内容:
关键函数调用结构图
project包括了每一个project的关键函数调用。
比例如以下图是使用Direct3D的Surface播放视频的时候的函数调用结构图。
不再一一列举。
測试素材
test_bgr24_320x180.rgb:在硬盘上的存储顺序是B1G1R1, B2G2R2, B3G3R3.....
test_bgra_320x180.rgb:在硬盘上的存储顺序是B1G1R1A1, B2G2R2A2, B3G3R3A3.....
test_rgb24_320x180.rgb:在硬盘上的存储顺序是R1G1B1, R2G2B2, R3G3B3.....
test_yuv420p_320x180.yuv:
在硬盘上的存储顺序是
YYYYYYYYYY...
YYYYYYYYYY...
UUUUU...
VVVVV...
内容截图例如以下所看到的:
分辨率为320x180,长度为50帧(2秒)。
内容为阴天的故宫。
注:能够使用Vooya查看RGB/YUV数据,强大并且方便。地址:http://www.offminor.de/
NocturneNo2inEflat_44.1k_s16le.pcm:在硬盘上的存储顺序是L1L1,R1R1,L2L2,R2R2,…
採样率为44.1kHz。採样位数为16bit,立体声。内容为肖邦的《夜曲》 (Nocturne in E flat major, Op9 No2)中的起始片段。
注:能够使用Audition这类的音频编辑软件查看PCM数据。
结果
project中的视频显示的结果都是一样的。弹出的窗体都是统一的500x500的大小,显示的内容也是一模一样。这样也有利于比对它们之间的技术。
同理,音频播放的素材也是一模一样。
下面截图显示一下它们的执行结果:
Simplest Audio Play DirectSound
Simplest Audio Play SDL2
Simplest Video Play Direct3D (Surface)
Simplest Video Play Direct3D (Texture)
Simplest Video Play GDI
Simplest Video Play OpenGL
Simplest Video Play OpenGL (Texture)
Simplest Video Play SDL2