在PC機上,對於YUV格式的視頻如YV12,YUY2等的顯示方法,一般是采用DIRECTDRAW,使用顯卡的OVERLAY表面顯示。OVERLAY技術主要是為了解決在PC上播放VCD而在顯卡上實現的一個基於硬件的技術。OVERLAY的出現,很好的解決了在PC上播放VCD所遇到的困難。早期PC處理能力有限,播放VCD時,不但要做視頻解碼工作,還需要做YUV到RGB的顏色空間轉換,軟件實現非常耗費資源,於是,YUV OVERLAY表面出現了,顏色空間轉換被轉移到顯卡上去實現,顯卡做這些工作是具有天生優勢的。
隨着顯卡技術的發展,OVERLAY的局限性也越來越充分的暴露出來。一般顯卡只支持一個OVERLAY表面,用OVERLAY實現多畫面比較困難,視頻和文本的疊加也有困難,當然,要實現一些特效就更難了。更重要的是,OVERLAY技術在顯卡上是屬於2D模塊,在高品質3D游戲的推動下,現在的顯卡的功能和性能,主要體現在3D模塊上,廠商投入最大的,也是在GPU的3D模塊上。OVERLAY技術無法利用和發揮顯卡GPU的3D性能。微軟早就停止了對DIRECTDRAW的支持,鼓勵開發人員轉向DIRECT3D,所以OVERLAY也無法使用新的API。
早期的3D渲染,主要是使用CPU做的,顯卡做的較少。后來,顯卡GPU的處理能力越來越強,承擔的3D渲染功能也越來越多,開始使用的是固定渲染管線,也就是說所有的渲染算法都是顯卡內置的,我們只能組合使用這些算法。現在的顯卡采用的都是可編程的渲染管線,也就是說我們可以編寫自己的渲染算法,下載到顯卡上去執行,替換固定渲染管線算法,靈活性大大提高。隨着GPU效能的提高,顯卡在圖像處理、視頻處理、科學計算等領域得到了廣泛的應用。
使用D3D渲染YUV視頻,可以采用D3D SURFACE渲染,也可以采用D3D紋理來渲染。SURFACE渲染比較簡單,但功能限制較多,下面我們只討論D3D紋理視頻渲染。紋理視頻渲染,就是把視頻數據填充到二維紋理中,結合我們自己寫的一段像素Shader代碼,送到顯卡的GPU渲染管線中去渲染。
以下假設讀者了解所討論的視頻格式細節。
對於YV12視頻數據,可以創建三個紋理,分別填充Y、U、V視頻數據。對於缺失的U、V采樣點,我們可以利用顯卡內置的雙線性濾波算法插值出來,這是簡單的方法。當然,也可以采用更好的圖像插值算法,以達到更高的圖像質量,這需要我們通過Shader實現我們的插值算法,然后分別把U、V渲染到紋理,實現更好的插值。相對與雙線性濾波,缺點是復雜更度高,效率低。U、V插值后,視頻數據從YUV420轉換為YUV444,然后做顏色空間轉換,從YUV444轉換為RGB32,轉換的Shader代碼很簡單,就是一個矩陣乘法運算。對於I420數據,就是把YV12數據的U、V數據在內存中的位置對調,其他處理和YV12一樣。
NV12格式,Y平面和YV12一樣,UV部分是打包格式。所以UV部分需要單獨處理,先把UV部分填充到一個紋理中,然后對UV紋理做兩次簡單的渲染到紋理,從而把U、V數據分別渲染到兩個紋理。經過這樣的處理,我們得到的數據就和YV12的數據一樣了,接下來的處理就可以參照YV12的處理流程和方法了。
對於打包格式的數據YUY2,渲染時需要插值出缺失的U、V采樣。YUY2在只在奇數像素上缺失U、V采樣,這樣處理的時候需要區分奇偶像素,對於偶數像素,不需要做U、V插值,直接做顏色空間轉換。對於奇數像素,需要利用相鄰的U、V采樣做插值,可以采用Catmull-Rom插值算法或者線性插值算法。插值后,就可以做顏色空間轉換。UYVY的做法和YUY2類似。
對於RGB格式,我所使用的NVIDIA GeForce 9800 GT顯卡支持RGB32,RGB555,RGB565,不支持RGB24。所以對於RGB24,需要在Shader代碼中分別取出R、G、B,再組成RGB32輸出即可。RGB32,RGB555,RGB565不需要額外處理,可以直接渲染。
對於平面文本疊加,采用了微軟提供的CD3DFont類,但這個類不支持中文,我在這個類的基礎上做了一些修改,實現了一個支持中文的文本疊加類。這兩個類互相配合,可以高效地實現平面文本疊加。
以上所討論的內容,均使用Direct3D9.0c進行了驗證測試。對OpenGL了解不多,但我想這些方法對於OpenGL應該同樣適用,畢竟這兩個3D架構在PC上實現的功能是相近的。
使用3D渲染平面視頻,可以實現多種特效,像多畫面、畫中畫、文本疊加、縮放,都很容易實現,性能也很好。如果結合其他3D技術,還可以做出很炫很酷的特效,就看我們的想象力了。
from:http://blog.csdn.net/dengzikun/article/details/5824874