黃 興,宋建新
(南京郵電大學(xué) 圖像處理與圖像通信實(shí)驗(yàn)室,江蘇 南京 210003)
隨著多種視頻壓縮標(biāo)準(zhǔn)的廣泛應(yīng)用,以及接收終端和內(nèi)容表現(xiàn)形式的多樣化,不同系統(tǒng)和網(wǎng)絡(luò)之間的交互則越發(fā)重要。在這種情況下,需要對(duì)已經(jīng)編碼的視頻數(shù)據(jù)根據(jù)實(shí)際的應(yīng)用需求進(jìn)行相應(yīng)的轉(zhuǎn)換。最新提出的H.264/AVC標(biāo)準(zhǔn)在圖像質(zhì)量和壓縮率方面都有了很大提高,該標(biāo)準(zhǔn)在視頻壓縮和網(wǎng)絡(luò)傳輸方面具有廣泛的應(yīng)用。而MPEG-2是當(dāng)前數(shù)字電視和DVD采用的壓縮標(biāo)準(zhǔn),因此本文所研究的從MPEG-2到H.264的視頻轉(zhuǎn)換極具研究?jī)r(jià)值。然而,視頻轉(zhuǎn)碼是個(gè)復(fù)雜的過(guò)程,它需要對(duì)已經(jīng)壓縮過(guò)的視頻流進(jìn)行解碼然后經(jīng)過(guò)處理轉(zhuǎn)換成滿足信道傳輸特性和解碼終端要求的目標(biāo)碼流。視頻轉(zhuǎn)碼密集的運(yùn)算量使得 CPU 承受著巨大的壓力[1-2]。
近年來(lái),低成本、高性能且可編程的圖形處理器(GPU)不斷推出并普及,使得GPU被越來(lái)越多地用在通用計(jì)算上,人們意識(shí)到可以將一些運(yùn)算量巨大的工作通過(guò)GPU來(lái)完成。本文根據(jù)視頻轉(zhuǎn)碼的要求和GPU的運(yùn)算特點(diǎn),提出了一種利用GPU強(qiáng)大的并行計(jì)算能力來(lái)幫助視頻轉(zhuǎn)碼的方法,該方法將視頻轉(zhuǎn)碼過(guò)程中耗時(shí)最多、最復(fù)雜的運(yùn)動(dòng)估計(jì)和模式選擇轉(zhuǎn)移到GPU上并行執(zhí)行。在開(kāi)發(fā)GPU并行計(jì)算能力時(shí),該方法采用NVIDIA公司的CUDA(統(tǒng)一計(jì)算設(shè)備架構(gòu))計(jì)算平臺(tái),實(shí)現(xiàn)了在GPU上執(zhí)行的并行幀間預(yù)測(cè),有效地提高了視頻轉(zhuǎn)碼的速度和效率[3-4]。
CUDA是NVIDIA公司推出的開(kāi)發(fā)圖形處理器通用計(jì)算能力(GPGPU)并行計(jì)算模型。近年來(lái)計(jì)算機(jī)顯卡運(yùn)算單元的速度越來(lái)越快,在某些應(yīng)用方面甚至已經(jīng)大幅超越CPU,基于GPU的通用計(jì)算已成為一個(gè)新的研究領(lǐng)域,它主要研究在圖形處理的范圍之外如何利用GPU來(lái)進(jìn)行更為廣泛的應(yīng)用計(jì)算。CUDA計(jì)算平臺(tái)以C語(yǔ)言為基礎(chǔ),它使開(kāi)發(fā)者無(wú)需學(xué)習(xí)特定的顯示芯片的指令或其他3D API就可以寫出在圖形處理器上執(zhí)行的程序,為開(kāi)發(fā)GPU的通用計(jì)算能力提供了便捷的開(kāi)發(fā)研究平臺(tái)。
CUDA模型的計(jì)算核心由流處理器SP(Stream Multiprocessor)組成,SP是由GPU中的頂點(diǎn)渲染器和像素渲染器組成的統(tǒng)一計(jì)算單元。每8個(gè)SP組成1個(gè)流多處理器SM(Streaming Multi-processor),每個(gè)SM含有4種不同的片上內(nèi)存:本地寄存器、共享內(nèi)存(shared memory)、只讀常量存儲(chǔ)器(constant cache)和紋理內(nèi)存(texture memo-ry)。而且每個(gè)SM都是基于 SIMT(Single Instruction,Multiple Thread,單指令多線程)的指令架構(gòu),用相同的指令執(zhí)行不同的線程。雖然SM之間不能直接交換數(shù)據(jù),但每個(gè)SM都可以讀取和修改設(shè)備內(nèi)存(Device Memory),所以SM之間可以通過(guò)設(shè)備內(nèi)存來(lái)交換數(shù)據(jù)。但由于設(shè)備內(nèi)存屬于外部存儲(chǔ)器,并且沒(méi)有緩沖,以致于讀取設(shè)備內(nèi)存的速度延遲比片上內(nèi)存大,因此在程序設(shè)計(jì)上要盡量避免從設(shè)備內(nèi)存交換數(shù)據(jù)。另外,SM線程之間的同步是通過(guò)每個(gè)SM內(nèi)的SP執(zhí)行同步函數(shù)來(lái)實(shí)現(xiàn)。
在進(jìn)行CUDA并行程序設(shè)計(jì)時(shí),可以將GPU看作真正并行執(zhí)行很多個(gè)線程的計(jì)算設(shè)備,它作為CPU的協(xié)處理器(Co-processor)而運(yùn)作。在CPU上執(zhí)行的程序稱為Host程序,而在GPU上執(zhí)行的程序稱為Device程序或Kernel程序。一般情況下,GPU與CPU協(xié)同工作,CPU負(fù)責(zé)進(jìn)行邏輯性強(qiáng)的事務(wù)處理和串行計(jì)算,而GPU則專注于執(zhí)行高度線程化的并行處理任務(wù)。通常,Host端程序會(huì)將數(shù)據(jù)準(zhǔn)備好后復(fù)制到顯卡內(nèi)存中,由GPU執(zhí)行完Kernel程序后,再由Host端程序?qū)⑺璧慕Y(jié)果從顯卡內(nèi)存中取回。數(shù)據(jù)在Host端和Device端傳輸使用高性能直接內(nèi)存訪問(wèn)(DMA)引擎。
Kernel執(zhí)行的最小單位是線程(Thread),若干個(gè)線程組成線程塊(Block),1個(gè)線程塊所包含的線程數(shù)目是有限的,本文用的GT240M中1個(gè)線程塊最多可以容納512個(gè)線程。1個(gè)線程塊的所有線程都在1個(gè)SM(Streaming Multiprocessor)上執(zhí)行,因此,同1個(gè)線程塊中的線程可以通過(guò)共享內(nèi)存來(lái)相互共享數(shù)據(jù)。在1個(gè)SM中處于執(zhí)行狀態(tài)的線程塊稱為活動(dòng)塊(Active),每個(gè)活動(dòng)塊都劃分到被稱為線程束(Warp)的線程組中,其中每個(gè)Warp包含相同數(shù)量的線程,一般為32個(gè),其通過(guò)SIMT的方式由SM執(zhí)行,多個(gè)Warp分時(shí)復(fù)用SM。每個(gè)線程都有唯一的線程ID(Thread ID)作為標(biāo)識(shí),同樣每個(gè)線程塊也有唯一的ID(Block ID),它們都處于全局狀態(tài)供程序使用。CUDA線程塊模型結(jié)構(gòu)如圖1所示,若干個(gè)線程組成線程塊(Block),數(shù)個(gè)線程塊再組成1個(gè)網(wǎng)格(Grid),具有相同維度和大小的塊可以分批組合到1個(gè)塊網(wǎng)格中。這樣,單個(gè)內(nèi)核可以啟動(dòng)的線程總數(shù)就將變得很大,大大提高了并行計(jì)算的能力[5]。
由于本文的重點(diǎn)是研究利用GPU的參與來(lái)加速視頻轉(zhuǎn)碼,MPEG-2到H.264視頻轉(zhuǎn)碼只完成格式間的轉(zhuǎn)換,并未涉及分辨力的轉(zhuǎn)換和目標(biāo)碼率的控制,因此轉(zhuǎn)碼器的框架采用級(jí)聯(lián)式的像素域轉(zhuǎn)碼結(jié)構(gòu)[6]。
圖1 CUDA線程塊模型結(jié)構(gòu)圖
在從MPEG-2到H.264的轉(zhuǎn)碼過(guò)程中,由于解碼過(guò)程相對(duì)簡(jiǎn)單,大約只占10%的運(yùn)算量,故解碼過(guò)程仍由CPU來(lái)完成。而計(jì)算量較大的步驟如H.264編碼過(guò)程中的運(yùn)動(dòng)估計(jì)和模式選擇,占據(jù)著轉(zhuǎn)碼過(guò)程絕大部分的計(jì)算復(fù)雜度,所以在設(shè)計(jì)利用GPU來(lái)參與轉(zhuǎn)碼的方法時(shí),首先考慮將運(yùn)動(dòng)估計(jì)和模式選擇的過(guò)程轉(zhuǎn)移到GPU上來(lái)加速實(shí)現(xiàn)。其他步驟諸如量化和反量化、VLC和VLD、DCT和IDCT仍然在CPU上完成。
整個(gè)轉(zhuǎn)碼過(guò)程采用級(jí)聯(lián)式的像素域轉(zhuǎn)碼結(jié)構(gòu),轉(zhuǎn)碼框架圖如圖2所示。首先在對(duì)MPEG-2視頻流經(jīng)過(guò)熵解碼、反量化、IDCT和運(yùn)動(dòng)補(bǔ)償將其解碼到像素域,然后GPU執(zhí)行CUDA內(nèi)核函數(shù),完成并行運(yùn)動(dòng)估計(jì)和初步的模式選擇,并將搜索得到的運(yùn)動(dòng)矢量和模式選擇信息從顯存上傳送給主機(jī),主機(jī)對(duì)收到的GPU的運(yùn)動(dòng)矢量進(jìn)行精細(xì)化搜索并完成剩余的編碼步驟[7]。
圖2 MPEG-2到H.264的視頻轉(zhuǎn)碼框架圖
2.2.1 算法介紹
幀間預(yù)測(cè)是為了消除視頻序列之間的時(shí)間冗余而采用的時(shí)域壓縮方法。在H.264標(biāo)準(zhǔn)中,幀間預(yù)測(cè)采用可變塊的多種模式的運(yùn)動(dòng)估計(jì)來(lái)實(shí)現(xiàn),比如亮度塊的模式可分為P16×16,P16×8,P8×16和 P8×8這4種,而每個(gè)P8×8塊又有4種子宏塊模式:P8×4,P4×8和P4×4。除了這7種模式之外,H.264的幀間預(yù)測(cè)在P幀中還支持SKIP編碼模式和I4×4,I16×16這2種幀內(nèi)編碼模式。SKIP模式是針對(duì)P16×16的宏塊在運(yùn)動(dòng)矢量為(0,0)時(shí)采用的模式。
目前雖然有不少學(xué)者和研究人員提出了很多有效的快速運(yùn)動(dòng)估計(jì)算法,但這些算法并不適合于CUDA并行環(huán)境。所以本文設(shè)計(jì)了一種在CUDA并行環(huán)境中運(yùn)行的并行運(yùn)動(dòng)估計(jì)算法,這里的并行通過(guò)兩方面來(lái)實(shí)現(xiàn):一是線程塊中的線程各自獨(dú)立的計(jì)算搜索位置的SAD(Sum of Absolute Difference);二是多個(gè)線程塊并發(fā)的完成16×16塊的運(yùn)動(dòng)搜索。該算法在GPU上采用全搜索來(lái)實(shí)現(xiàn)整數(shù)像素的運(yùn)動(dòng)搜索,然后在CPU上實(shí)行1/4像素的精細(xì)化[8]。
據(jù)統(tǒng)計(jì),在P幀編碼中,P16×16,P16×8,P8×16和P8×8這4種模式占7種模式的80%以上,所以在設(shè)計(jì)算法時(shí)考慮到算法的改進(jìn)效率,只將P16×16,P16×8,P8×16和P8×8這4種模式放在GPU上執(zhí)行,而將其余3種模式仍留在CPU上執(zhí)行。
由于GPU上的運(yùn)動(dòng)估計(jì)是宏塊級(jí)并行,所以該算法在運(yùn)動(dòng)搜索之前要將所需的參考幀和當(dāng)前待編碼幀一次傳送到GPU顯存,經(jīng)過(guò)GPU運(yùn)算得到4種模式的代價(jià)之后,再選擇最佳模式并計(jì)算其運(yùn)動(dòng)矢量。當(dāng)轉(zhuǎn)碼器的編碼端收到GPU回傳的運(yùn)動(dòng)矢量時(shí),對(duì)其進(jìn)行簡(jiǎn)單的精細(xì)化后即可利用其計(jì)算殘差進(jìn)行后續(xù)編碼環(huán)節(jié)。算法流程如圖3所示,具體實(shí)現(xiàn)步驟見(jiàn)2.2.2節(jié)所述[9]。
2.2.2 并行運(yùn)動(dòng)估計(jì)算法實(shí)現(xiàn)步驟
為了便于并行程序的設(shè)計(jì)和執(zhí)行,該并行運(yùn)動(dòng)估計(jì)算法的并行粒度為宏塊級(jí),將CUDA線程塊的大小設(shè)計(jì)為16×16=256,正好與1個(gè)宏塊(MB)的大小相對(duì)應(yīng)。該算法在GPU上進(jìn)行整像素的全搜索和最佳宏塊模式選擇,將分?jǐn)?shù)像素插值和1/4像素精細(xì)化搜索的過(guò)程放在GPU上進(jìn)行,主要步驟為:
1)讀入當(dāng)前的參考幀,并對(duì)其進(jìn)行邊界擴(kuò)展,以便于全搜索。邊界擴(kuò)展是在原參考幀圖像的四周分別擴(kuò)展32行和32列,擴(kuò)展的像素值和邊界處的像素值相等。
2)在顯存上開(kāi)辟全局內(nèi)存,用于存儲(chǔ)當(dāng)前編碼幀和經(jīng)過(guò)邊界擴(kuò)展之后的參考幀。
3)將當(dāng)前待編碼的幀和經(jīng)過(guò)邊界擴(kuò)展之后的參考幀從主機(jī)(CPU)拷貝到設(shè)備端(顯存),并綁定到顯存的紋理內(nèi)存(Texture Memory)。
4)根據(jù)轉(zhuǎn)碼視頻的分辨力,在GPU上合理劃分線程塊和Grid,設(shè)置好傳入GPU的參數(shù)和分配的Block數(shù)目以及Thread數(shù)目。這里初步將線程塊的大小定為16×16=256,設(shè)定搜索范圍的寬度為16,則線程塊的數(shù)目即Grid網(wǎng)格的大小恰好為1幀中的宏塊數(shù)。
5)在每個(gè)Block內(nèi)部分配每個(gè)Thread都可以訪問(wèn)的共享內(nèi)存。并且計(jì)算線程塊中每1個(gè)8×8子塊對(duì)應(yīng)于搜索范圍內(nèi)每個(gè)位置的SAD。
6)利用上一步驟中計(jì)算得到的SAD值,根據(jù)子塊位置的對(duì)應(yīng)關(guān)系,以4個(gè)8×8塊SAD為基礎(chǔ),直接求和得出P16×8,P8×16,P16×16等塊的 SAD。然后分別以這些塊的SAD作為根據(jù),選擇最小SAD對(duì)應(yīng)的位置為運(yùn)動(dòng)矢量,并記下其最小的SAD值作為該子塊模式的代價(jià)。
7)根據(jù)上一步驟中得到的各個(gè)模式的代價(jià)值,選擇最小的作為最終模式,并將該模式對(duì)應(yīng)的運(yùn)動(dòng)矢量寫入到顯存的全局內(nèi)存并回傳至主機(jī)。
2.2.3 SAD的計(jì)算
首先計(jì)算8×8塊的SAD。8×8塊SAD的計(jì)算由1個(gè)線程塊(Block)中的256個(gè)線程并行完成,每個(gè)線程單獨(dú)計(jì)算1個(gè)對(duì)應(yīng)參考位置的SAD值,如圖4所示。圖中,坐標(biāo)頂點(diǎn)(0,0)處為參考幀搜索范圍的頂點(diǎn),由線程塊中的Thread 0來(lái)完成SAD值計(jì)算,依次類推,最后一個(gè)搜索點(diǎn)為(15,15),由線程塊中的Thread 255來(lái)計(jì)算SAD值。線程塊中的所有線程各自獨(dú)立完成計(jì)算,互不干擾和依賴。計(jì)算完成之后它們通過(guò)同步函數(shù)進(jìn)入同步點(diǎn)掛起。
圖4 8×8塊SAD計(jì)算
當(dāng)P8×8子塊的SAD計(jì)算出來(lái)之后,其他模式比如P16×8,P8×16和P16×16的SAD都可以由相對(duì)應(yīng)位置的8×8子塊的SAD值相加得到,如圖5所示。P16×8塊的SAD分別由Ⅰ、Ⅱ塊和Ⅲ、Ⅳ塊的SAD之和組成;P8×16塊的SAD則分別由Ⅰ、Ⅲ塊和Ⅱ、Ⅳ塊的SAD之和組成;而P16×16塊的SAD則由4個(gè)8×8子塊之和共同組成[10]。
圖5 其它模式的SAD推算
對(duì)于模式選擇,由于在設(shè)計(jì)整個(gè)轉(zhuǎn)碼系統(tǒng)時(shí)只考慮將幀間預(yù)測(cè)轉(zhuǎn)移到GPU上完成,而幀內(nèi)編碼仍然在CPU上執(zhí)行,所以這里將模式選擇分兩步完成。第一步是在GPU上完成,負(fù)責(zé)完成幀間宏塊如P16×16、P16×8等塊的模式選擇;第二步是在CPU上完成的,此步驟在分?jǐn)?shù)像素精細(xì)化之后,主要負(fù)責(zé)將幀間模式選擇的結(jié)果再與幀內(nèi)模式如I16×16、14×4比較,選擇代價(jià)最小的模式作為最終模式。模式選擇流程圖如圖6所示,其中第一步比較在GPU上完成,后面兩個(gè)步驟則在CPU上完成。
圖6 模式選擇過(guò)程
為了驗(yàn)證該方法對(duì)視頻轉(zhuǎn)碼的加速效果,本文對(duì)基于GPU的轉(zhuǎn)碼方法和傳統(tǒng)的CPU轉(zhuǎn)碼方法分別進(jìn)行性能測(cè)試。實(shí)驗(yàn)環(huán)境為Intel Core 2 Duo T6600 2.2G CPU+NVIDIA Geforce GTX280M。使用的測(cè)試視頻為CIF格式的MPEG-2視頻源mother-daughter.m2v和QCIF格式的視頻源foreman.m2v,測(cè)試的轉(zhuǎn)碼視頻長(zhǎng)度均為30幀,測(cè)試結(jié)果如表1所示,該表記錄的是兩種轉(zhuǎn)碼方法分別轉(zhuǎn)碼30幀MPEG-2視頻所需的時(shí)間。
表1 算法性能對(duì)比
由表1可以看出,采用GPU來(lái)幫助視頻轉(zhuǎn)碼的方法比傳統(tǒng)的CPU轉(zhuǎn)碼的方法在速度上提高了3~4倍。實(shí)驗(yàn)證明,利用GPU的通用計(jì)算能力來(lái)加快視頻處理的設(shè)計(jì)思路是可行的。
本文提出了使用GPU來(lái)加速視頻轉(zhuǎn)碼的算法,并通過(guò)實(shí)驗(yàn)驗(yàn)證了基于CUDA的視頻轉(zhuǎn)碼算法的可行性,且取得了較好的效果。在此基礎(chǔ)上可以在以下兩個(gè)方面進(jìn)行深入研究:一是考慮將更多的模塊轉(zhuǎn)移到GPU上實(shí)現(xiàn);二是設(shè)計(jì)另外一種框架,讓GPU在執(zhí)行幀間預(yù)測(cè)的同時(shí),CPU也執(zhí)行量化編碼模塊而不是被掛起。這樣可以進(jìn)一步改善轉(zhuǎn)碼器的性能。
[1] AHMAD I,WEI Xiaohui,SUN Yu,et al.Video transcoding:an overview of various techniques and research issues[J].IEEE Transactions on Multimedia,2005,7(5):793-804.
[2]程愷英,王宏遠(yuǎn),樊淳標(biāo).數(shù)字視頻轉(zhuǎn)碼技術(shù)綜述[J].電視技術(shù),2005,29(4):13-16.
[3]NVIDIA Corporation.NVIDIA CUDA compute unified device architectureprogramming guide version 3.2[EB/OL].[2010-08-10].http://www.nvidia.cn.
[4]NVIDIA Corporation.NVIDIA CUDA compute unified device architecturebest practices guide version 3.2[EB/OL].[2010-08-10].http://www.nvidia.cn.
[5]張舒,褚艷利.GPU高性能運(yùn)算之CUDA[M].北京:中國(guó)水利水電出版社,2009.
[6]KALVA H,PETLJANSKI B,F(xiàn)URHT B.Complexity reduction tools for MPEG-2 to H.264 video transcoding[J].WSEAS Transactions on Information Science & Applications,2005,2(2):295-300.
[7]LIU Y,TANG C,CHIEN S.Coding mode analysis of MPEG-2 to H.264/AVC transcoding for digital TV applications[C]//Proc.ISCAS 2007.[S.l.]:IEEE Press,2007:1995-1998.
[8]CHEN W,HANG H.H.264/AVC motion estimation implementation on compute unified device archetecture(CUDA)[C]//Proc.ICME 2008.[S.l.]:IEEE Press,2008,17:697-700.
[9]RODRIGUEZ R,MARTINEZ J,F(xiàn)ERNANDEZ E G,et al.Accelerating H.264 inter prediction in a GPU by using CUDA[C]//Proc.ICCE 2010.[S.l.]:IEEE Press,2010:463-464.
[10]CHEUNG N,F(xiàn)AN X,AU O,et al.Video coding on multicore graphics processors[J].IEEE Signal Processing Magazine,2010,27(2):79-89.