一,概念解释android
什么是渲染?这是高大上的说法,翻译成正常语言,就是把图像缓冲区的数据显示到屏幕的过程,就是渲染。程序员
原理说白了很简单,但实际操做中有太多因素须要考量。算法
OS/硬件提供的加速机制/解码后图像数据格式/字幕数据的格式。。。。编程
刚开始查找资料时,我老是试图找到全部的渲染方式,后来发现这实在错的比较离谱。由于说到底,这是一个图形学的问题:如何在计算机屏幕上绘图。不一样的图形库有不一样的绘图接口,太多的厂商有本身的图形库,根本不可能穷举出全部的图形库。咱们只能讨论一些相对主流的方式。另外去找全部的图形渲染方式也是没有意义的,由于他们的理念大致上又是差很少的,只是API不一样。惟一的要求是,你要画的足够快,由于若是你想一张张图像看起来是连续的,那么速度要达到24帧以上。固然,对于一些特殊应用,好比视频会议,15帧的速度不会让人有卡顿感,这个帧数也彻底Ok。windows
二,问题的概念空间与一些解决方案api
说完了,回到开始的问题,如何渲染。ide
这里又有两个问题须要解释:性能
1.图像缓冲区里面的数据是什么样的?RGB仍是YUV,又是哪一种RGB,哪一种YUV?google
2.如何把缓冲区的数据搬到屏幕?CPU,普通的2D加速,仍是GPU,用GPU时,是OpenGL仍是D3D?spa
第一个问题:
这里咱们只说几个常见的。这里的图像缓冲区,特指解码后的数据,而非对应屏幕显示的那块。由于对于目前的真彩色显示器来讲,屏幕对应的数据只有一种,就是RGB888。不管你给到的数据如何,传输到屏幕点亮色点的数据都会被驱动/硬件/总线给处理成这种格式。这是由屏幕的物理属性决定的,物理屏幕就是TTL电路点亮的一堆小灯。
常见的有RGB888/RGB565/YV12/I420p。
ps:实际解码器出来的都是YUV数据,若是获得RGB数据,一般也都是解码器后面加了一步YUV2RGB的转换,不过一般咱们也会把这块功能算成是解码器的。不过不绝对,须要看lib的做者如何看待这个问题。
第二个问题:
1.纯粹的CPU(如今貌似不多有这种了),就是一个一个的往屏幕上画点了,一个pixel一个pixel的画,不太常见,也比较慢,由于操做内存太过频繁。有些库封装了overlay/bitblt等操做,虽然看起来像CPU在作,实际上已经调用了2D加速了。
2.用2D加速的
Overlay
之前看资料,老看到Overlay什么的东东,找了好久,彷佛也没有谁专门给出一个标准定义,说什么才叫Overlay。说下个人理解,Overlay一般是一个硬件意义上的名词,由于屏幕上的东西,一般有不少层次,Overlay能够作的就是直接把这层放到全部图层上面。一般的用法是YUV数据直接给屏幕,Overlay硬件会替你作YUV2RGB转换。这个词貌似来自ms的directshow,有什么主表面,离屏表面,overlay之分,实际上就是硬件图层的意思。貌似有些硬件能够支持RGB Overlay,不多见。有些图形硬件能够支持多个Overlay图层,也就是说,你可使用Overlay同时在屏幕上显示几个不一样的视频。视频监控的宫格多半就是这样来的。
嵌入式里面,Overlay还有一种常见作法,好比:一些有很高优先级的提示,要给用户,这时就得把普通的提示框作成YUV的,而后提示显示出来,能够直接盖到全部的图层上去。
关于模拟Overlay,呵呵,凌乱了吧,实际上就是接口叫xxxOverlay,其实是把YUV转成RGB,而后画点的方式显示,SDL中有这种接口。
最多见的Overlay类型是YV12,一是数据量小,二视频压缩的标准有关,由于Mpeg2/h264等标准,都强制要求这种格式,固然这两点是相符相成的。
优势就是快,缺点也比较明显,若是要作视频图像后处理,好比放大缩小,人脸识别等操做,会比较麻烦。
Bitblt
比较常见的2d加速方式,把内存数据的数据直接传输到屏幕,或者搬到另外一块内存中(内存拷贝)。
blit是个有渊源的词语,这个词的本意就是块(block)移动(transfer)的缩写blt,由于这个缩写缺乏元音很差读,因此后来加上了i,就变成blit。
实际上我搞不清这和DMA有什么区别,但愿有人指点一下区别。难道区别仅仅是BitBlt能够同时缩放/旋转,而DMA不能?
另外与Android提出的CopyBit有区别么?我看没啥区别啊。
优势是在内存拷贝时,能够同时作缩放/旋转,缺点是只能用RGB格式。
(2014.03.30更新:
1.查了一些资料,看了一下bitblt实现原理,除去缩放/旋转的算法以外,涉及到内存搬移的应该是调用memcpy实现的,从这个角度来看,是用到了dma功能的,看来是没有什么区别的。只是memcpy的实现一般是考验硬件性能和程序员水平的地方。
2.从copybit规定的interface来看,实际就是bitblt,估计只是bitlt这个单词是ms提出的,google以为不爽,起个新名子而已。
实际android到了4.0以后,已经取消掉了copybit HAL module,2d加速所有采用了GPU操做。在android 2.3代码里还残存着一些痕迹。)
3.GPU
其实OpenGL和D3D就是GPU在软件接口层面上的抽象。用opengl和d3d显示视频一般都是用texture方式来实现的,把一帧一帧图像生成纹理数据,而后贴到vertex上去。
简单解释一下就是,先创建顶点坐标,再创建纹理坐标,再把顶点坐标与纹理坐标一一映射,完成贴图。具体的要看一下OpenGL编程书籍了,这实在是一个复杂的题目。
先把屏幕四个点当成两个三角形(由于3d api用三角形来表示平面,固然多边形也支持,但遇到不支持的状况,用两个三角形就能够组成一个矩形),把数据的一个点一个点对应到这个矩形上,就显示了一帧。由于GPU一般是并行操做,像素生成率一般也足够高。
这块了解不够多。很少说了。
三,常见的库
这个一般又与OS有关系了,讨厌死了。
先说Windows,又分几个层次。先从底层提及。
纯api就是
Windows GDI,windows平台对图形硬件的抽象,不少年了,比较成熟,效率应该比较OK。
DirectDraw,这个封装的就是Overlay的操做接口,可是微软已经中止支持了,不建议使用。
D3D,微软的3D API,门槛比较高一些。
Direct2D,层级和GDI貌似差很少,Win7时代出现新玩意,看过一些资料,说这套API是取代GDI的,不过貌似微软已经尾大不调了。
上述几个API,VLC播放器里面都有一些具体的实现,能够看一下下。
另外就是DirectShow中的filter级别的。
VMR7,底层用DirectDraw封装的,资料说只有XP好用,更老更新的平台都不支持。
VMR9,底层用D3D实现,还在支持。
EVR,vista时代出现的东西,好像也是D3D作的(微软你到底要闹哪样。。。。这么多选择)
其实dshow还有什么overlay mixer,video render之类的filter,我以为都没有跑出我上面说的范围。
说Linux吧。
X-window的api算一种,虽然一直用X,但对X的超多bug也很不满,历来没看过。。。(吐血)
DirectFB,一般在嵌入式平台才会使用,桌面平台上极少见到,抽象了几乎全部的2D加速机制,接口操做和DirectDraw几乎如出一辙。
直接用FrameBuffer提供的接口,嵌入式多见,不过一般这些接口里面已经封装了Overlay/BitBlt接口,不要只见树木不见森林就好。
跨平台的
SDL,算是比较经常使用的,API的使用还比较简单,可是看代码真心以为太乱了,不过人家是跨平台的,代码乱真心是难以免。
最后有个比较惨痛的事实,由于你在写播放器时,这些API可能都没用,由于。。。。。你的图形库会再给你提供一套。。。。好吧,懂得原理,不少事情会简单一些。