在TMS320C6711 DSP上實(shí)現(xiàn)H.263視頻編碼器的EDMA數(shù)據(jù)存取策略 作者: 時(shí)間:2007-03-09 來源:網(wǎng)絡(luò) 加入技術(shù)交流群 掃碼加入和技術(shù)大咖面對(duì)面交流海量資料庫(kù)查詢 收藏 摘要:提出了在TMS320C6711 DSP平臺(tái)上實(shí)現(xiàn)H.263視頻編碼器的過程中,如何使用EDMA優(yōu)化數(shù)據(jù)存取的策略,從而減少了CPU花費(fèi)在數(shù)據(jù)搬移上的開銷。 關(guān)鍵詞:H.263 DSP EDMA QDMA 數(shù)據(jù)存取策略 目前,將H.263算法在DSP芯片上實(shí)現(xiàn),已成為一種越來越廣泛的應(yīng)用趨勢(shì)。采用DSP實(shí)現(xiàn)H.263算法,相對(duì)于以往的方案,具有更好的擴(kuò)展性,可以很容易地將聲音編解碼和復(fù)用、通信協(xié)議添加進(jìn)來,綜合在一起DSP芯片中,具有很強(qiáng)的實(shí)用性。 本文采用TI公司的TMS320C6711 DSP實(shí)現(xiàn)H.263的編碼,提出一種在DSP平臺(tái)上充分合理使用片上EDMA控制器,進(jìn)行數(shù)據(jù)存取優(yōu)化的策略。 1 TMS320C6711的直接存儲(chǔ)器訪問控制器 直接存儲(chǔ)器訪問(DMA)是C6000 DSP的一種重要的數(shù)據(jù)訪問方式,它可以在沒有CPU參與的情況下,由DMA控制器完成DSP存儲(chǔ)空間內(nèi)的數(shù)據(jù)搬移,數(shù)據(jù)搬移的源/目的地址可以在片內(nèi)存儲(chǔ)器、片內(nèi)外設(shè)和外設(shè)器件。 在TMS320C6711中,EDMA控制器負(fù)責(zé)片內(nèi)存儲(chǔ)器L2和外設(shè)之間的數(shù)據(jù)傳輸,其增強(qiáng)之處在于: %26;#183;提供了16個(gè)通道 %26;#183;通道間的優(yōu)先級(jí)設(shè)置 %26;#183;支持不同結(jié)構(gòu)數(shù)據(jù)傳輸?shù)逆溄樱≦DMA除外) EDMA控制器是基于RAM結(jié)構(gòu)的,EDMA的參數(shù)RAM(PaRAM)存放著傳輸控制參數(shù)。圖1給出了一個(gè)PaRAM的內(nèi)部結(jié)構(gòu),總共6個(gè)字(32bit/word)。選項(xiàng)參數(shù)內(nèi)容如圖2所示。 TMS320C6711 DSP還提供一種快速DMA(QDMA)傳輸方式。QDMA與EDMA相似,支持幾乎所有的EDMA傳輸方式,但是提交傳輸申請(qǐng)的速度要快很多。在應(yīng)用系統(tǒng)中,EDMA適合于固定周期的數(shù)據(jù)傳輸,但如果需要CPU干擾控制搬移數(shù)據(jù),QDMA則比較適合。 QDMA的操作由兩組寄存器進(jìn)行控制。第一組的五個(gè)寄存器寄存了QDMA傳輸所需的參數(shù),與EDMA的PaRAM類似,只是沒重加載/鏈接參數(shù)。第二組的五個(gè)寄存器是第一組寄存器的“偽映射”。 下面就H.263編碼的某些環(huán)節(jié)說明如何采用EDMA技術(shù)對(duì)編碼數(shù)據(jù)數(shù)據(jù)進(jìn)行優(yōu)化存取。 2 原始圖像的獲取 由于待處理的原始圖像都很大,即使QCIF格式的圖像,也要占用38KB左右的存儲(chǔ)空間,顯然不能將待編碼圖像存放于片內(nèi)RAM(L2)中。通常的方法是在CPU干預(yù)下,采用“讀入-寫出”的方式,從視頻設(shè)備讀取數(shù)據(jù),然后存入片外SDRAM中。使用C6000 DSP強(qiáng)大的EDMA,亦可以實(shí)現(xiàn)原始圖像幀的后臺(tái)傳輸,EDMA無需CPU的干預(yù)便可獨(dú)自將視頻設(shè)備的輸出圖像直接送往片外SDRAM。這樣,CPU就可以將搬移數(shù)據(jù)的時(shí)間用于圖像編碼的工作。 在這里使用C6000 DSP的EDMA控制器的QDMA功能。相對(duì)于EDMA的傳輸方式,QDMA的傳輸方式有著更快的申請(qǐng)?zhí)峤凰俣取?img onload="if(this.width>620)this.width=620;" onclick="window.open(this.src)" style="cursor:pointer" src="http://editerupload.eepw.com.cn/fetch/20140414/242405_1_1.jpg" border=0>在片外SDRAM中開辟三塊幀緩沖區(qū)Framel(首地址0xA00000000)、Frame2、Frame3。初始化階段,先提交三個(gè)QDMA請(qǐng)求(此時(shí)也可使用通常的數(shù)據(jù)搬移手段),將視頻序列的前三幀數(shù)據(jù)分別存入三塊幀緩沖區(qū)內(nèi),填滿幀緩沖區(qū)。接著開始對(duì)Frame1內(nèi)的圖像數(shù)據(jù)進(jìn)行編碼,該幀編碼結(jié)束后,對(duì)Frame2內(nèi)的圖像數(shù)據(jù)進(jìn)行編碼,F(xiàn)rame2成為當(dāng)前幀,而Frame1成為Frame2的先前幀,一旦Rrame2編碼完畢,便對(duì)Frame3內(nèi)的圖像數(shù)據(jù)進(jìn)行編碼,同時(shí)立即提交一個(gè)新的QDMA請(qǐng)求,從視頻外設(shè)讀取一幀新的圖像數(shù)據(jù)到Frame1中(因?yàn)閷?duì)Frame3進(jìn)行編碼時(shí),F(xiàn)rame2作為先前幀,F(xiàn)rame1已經(jīng)不需要了)。待Frame3編碼完畢后,F(xiàn)rame2又不需要了,此時(shí)再提交一個(gè)新的QDMA請(qǐng)求,讀取新一幀圖像數(shù)據(jù)到Frame2中。如此循環(huán),每編碼完畢一幀圖像,就提交一個(gè)新的QDMA請(qǐng)求,依次在對(duì)應(yīng)的幀緩沖區(qū)內(nèi)存放新的一幀圖像數(shù)據(jù)。這樣,依次在對(duì)應(yīng)的幀緩沖區(qū)內(nèi)存放新一幀圖像數(shù)據(jù)。這樣,從外設(shè)獲取當(dāng)前編碼圖像的下一幀與當(dāng)前圖像的編碼工作同時(shí)進(jìn)行,DSP每次都直接對(duì)圖像進(jìn)行編碼,而不需要再花費(fèi)開銷從外設(shè)讀取。 要實(shí)現(xiàn)圖3所示的QDMA傳輸,有兩種等價(jià)的方式: %26;#183;1D-1D,幀同步傳輸 %26;#183;1D-2D,陣列同步傳輸 下面以圖3為例,給出采用1D-2D傳輸方式,將圖像數(shù)據(jù)送往Frame1中時(shí)所需提交的QDMA的具體參數(shù)設(shè)置。 Void submit_qdma(void) { EDMA_Config config; Config.opt=(unsigned int)0x28A00001; Config.src=(unsigned int)0x90010000;//視頻外設(shè)的數(shù)據(jù)口地址 Config.cnt=(unsigned int)((288-1)<<16|352); Config.dst=(unsigned int)0xA00000000;//目的地址 Config.idx=(unsigned int)(352<<16);//數(shù)據(jù)單元索引忽略 EDMA_qdmaConfig(%26;amp;config); }圖33 圖像宏塊編碼 從上面已經(jīng)知道,圖像幀存放在片外SDRAM中。因此,在對(duì)I幀所有宏塊和P幀INTRA宏塊編碼時(shí),或?qū)幀INTER宏塊進(jìn)行運(yùn)行估計(jì)時(shí),每個(gè)宏塊都要進(jìn)行片外存儲(chǔ)器訪問,會(huì)占用很大的CPU開銷。所以,最好將當(dāng)前待編碼的宏塊存入于片內(nèi)RAM中。這樣,整個(gè)宏塊的編碼就始終是片內(nèi)訪問,宏塊編碼子函MB_Encode在效率上就能夠提高12%左右。 最直接的做法就是在片內(nèi)SRAM中事先開辟一個(gè)宏塊緩部眍,待將編碼圖像當(dāng)前位置處的現(xiàn)代戰(zhàn)爭(zhēng)宏塊搬移到片內(nèi)RAM中的宏塊緩沖區(qū),之后再調(diào)用宏塊編碼子函MB_Encode。但是這樣仍然會(huì)浪費(fèi)一定CPU時(shí)間在數(shù)據(jù)塊的搬移上,所以還具有改進(jìn)的余地。結(jié)合C6000 DSP強(qiáng)大的EDMA功能,提出了如下改進(jìn)方案: 由于每次塊組(GOB)共有8448個(gè)字節(jié)數(shù)據(jù)(CIF),因此可以在片內(nèi)RAM中開辟兩個(gè)塊緩沖區(qū),采用乒乓方式,通過啟動(dòng)EDMA塊組數(shù)據(jù),使用獨(dú)立于CPU的EDMA數(shù)據(jù)通道,在后臺(tái)從片外搬移到片內(nèi)。這樣一來,每次調(diào)用宏塊編碼時(shí),數(shù)據(jù)都已經(jīng)存放在指定緩沖區(qū)中,不僅無需做數(shù)據(jù)的搬移工作,而且還是在片內(nèi)進(jìn)行數(shù)據(jù)訪問。 初始化時(shí),可以采用普通的數(shù)據(jù)搬移手段(亦可使用EDMA),從片外存儲(chǔ)器將第一幀圖像的前面兩個(gè)塊組搬移到片內(nèi),充滿塊組緩沖區(qū),然后即可開始圖像編碼。在進(jìn)行圖像編碼的過程中,逐一對(duì)塊組的乒緩沖區(qū)中的宏塊進(jìn)行編碼,乒緩沖區(qū)宏塊編碼結(jié)束后,接著進(jìn)行乓緩部眍的宏塊編碼,同時(shí)啟動(dòng)EDMA,從片外存儲(chǔ)器搬移一個(gè)新的塊組到乒緩部眍來,使得編碼乓緩部沖區(qū)和向乒緩沖區(qū)搬移塊組數(shù)據(jù)同時(shí)進(jìn)行,一旦乓緩沖宏塊也編碼完畢,即可處理乒緩沖區(qū)中新的塊組,如此循環(huán)。 C6000系列DSP的EDMA具有高效地從一幀圖像中抽取子幀的能力。以CIF格式的圖像為例,說明如何設(shè)置EDMA參數(shù)。 如圖4所示左側(cè)表示4:2:0亞采樣的一幀YcrCb圖像,亮度分量首地址為A000 0000h,色度分量首地址分別是A0001 8C00h和A001 EF00h;右側(cè)表示塊組的乒乓緩沖區(qū),亮度分量y乒緩沖區(qū)首址在2000h,乓緩沖區(qū)首址為3600h,色度Cr分量的乒乓緩部沖區(qū)首址分別為4C00h和5700h,色度Cb分量的乒乓緩沖區(qū)首址分別為5180h和5C80h。 第一步,使用CPU啟動(dòng)EDMA通道,將一個(gè)GOB的亮度分量y傳輸?shù)紾OB亮度分量的乒緩沖區(qū)。CPU可以通過寫事件置位寄存器ESR啟動(dòng)一個(gè)EDMA通道,向ESR的某一位寫入“1”,強(qiáng)行觸發(fā)對(duì)應(yīng)事件,此時(shí)EDMA的PaRAM中的傳輸控制參數(shù)被送往地址發(fā)生器,開始對(duì)EMIF、L2和片外SDRAM進(jìn)行訪問。也可以使用QDMA進(jìn)行第一步數(shù)據(jù)傳輸,通過設(shè)置QDMA的結(jié)束代碼(選項(xiàng)參數(shù)的TCC字段)啟動(dòng)后續(xù)傳輸。 第二步,EDMA通道完成了對(duì)GOB亮度分量的傳輸后,重新加載下一次傳輸所需要的傳輸控制參數(shù),將該GOB的色度分量Cr傳磁室片內(nèi)對(duì)應(yīng)的Cr兵緩沖區(qū)。由于需要傳輸?shù)脑紨?shù)據(jù),在空間上不是連續(xù)在存儲(chǔ)的,這里使用了C6000系列DSP的EDMA鏈接功能。鏈接功能可以將不同的EDMA傳輸控制參數(shù)連接起來,組成一個(gè)參數(shù)鏈,為同一個(gè)通道服務(wù)。一次EDMA傳輸任務(wù)結(jié)束后,會(huì)自動(dòng)從PaRAM中加載下一次傳輸所需要的參數(shù)。 第三步,同上,將該 GOB的Cb分量送入片內(nèi)對(duì)應(yīng)的Cb兵緩沖區(qū)。圖4將GOB搬移到乒緩沖區(qū)對(duì)應(yīng)的EDMA通道的PaRAM設(shè)置參數(shù)如圖5所示。 選擇幀同步、1D-2D數(shù)據(jù)傳輸數(shù)據(jù),啟動(dòng)EDMA通道后,依次加載參數(shù)鏈,連續(xù)進(jìn)行三次EDMA數(shù)據(jù)傳輸之后,待編碼圖像的一個(gè)GOB即搬移到片內(nèi)的對(duì)應(yīng)緩沖區(qū)中。注意參數(shù)鏈的最后一個(gè)PaRAM,選項(xiàng)參數(shù)的LINK字段要設(shè)置為0。 同樣可以得到將GOB搬移到乓緩沖區(qū)對(duì)應(yīng)的EDMA通道的PaRAM設(shè)置參數(shù),如圖6所示。 下面給出向編碼塊組乒緩沖區(qū)傳輸數(shù)據(jù)的EDMA通道PaRAM參數(shù)鏈的配置程序。 EDMA_Config config; EDMA_Handle hEdma_ping; //向乒緩沖區(qū)傳輸數(shù)據(jù)的EDMA通道句柄 EDMA_Handle hEdma_ping_tab1;//該通道的第一個(gè)鏈接PaRAM的句柄 EDMA_Handle hEdma_ping_tab2;//該通道的第二個(gè)鏈接PaRAM的句柄 Uint32 link_tab1,link_tab2;//該通道兩個(gè)鏈接PaRAM的地址 if(EDMA_allocTableEx(1,%26;amp;hEdma_ping_tab1)) link_tab1=EDMA_getTableAddress(hEdma_ping_tab1); if(EDMA_allocTableEx(1,%26;amp;hEdma_ping_tab2)) link_tab2=EDMA_getTableAddress(hEdma_ping_tab2) hEdma_ping=EDMA_open(EDMA_CHA_ANY,EDMA_OPEN_RESET); config.opt=(Uint32)0x55200003;//第一個(gè)PaRAM的選項(xiàng)參數(shù) config.ser=(Uint32)0xA0000000;//待傳輸塊組Y分量的首地址 config.cnt=(Uint32)0x000f0160;//每行352像素,共16行 config.dst=(Uint32)0x00002000;//設(shè)置在片內(nèi)的塊組緩沖區(qū) config.idx=(Uint32)0; //源采用幀同步、2-D傳輸 config.rld=(Uint32)(0x160<<16| link_tab1 %26;amp; 0xffff);//鏈接到下一個(gè)PaRAM EDMA_config(hEdma_ping,%26;amp;config); Config.src=(Uint32)0xA00191880; Config.cnt=(Uint32)0x000700B0; Config.dst=(Uint32)0x00005700; Config.rld=(Uint32)(0xB0<<16| link_tab2 %26;amp;0xffff); 鏈接到最后一個(gè)PaRAM EDMA_config(hEdma_ping_tab1,%26;amp;config); Config.opt=(Uint32)0x55200001; //最后一個(gè)PaRAM,LINK字段為0 config.src=(Uint32)0xA001F480; config.dst=(Uint32)0x0005C880; config.rld=(Uint32)(0xB0<<16); EDMA_config(hEdma_ping_tab2,%26;amp;config); 4 運(yùn)動(dòng)估計(jì) 在P幀編碼中,對(duì)每個(gè)宏塊進(jìn)行運(yùn)行估計(jì)時(shí),需要訪問存儲(chǔ)在片外存儲(chǔ)器的前一幀圖像??紤]到當(dāng)前幀的每個(gè)宏塊都是在前一幀的搜索窗口內(nèi)進(jìn)行運(yùn)行估計(jì),所以可在片內(nèi)RAM中開設(shè)一個(gè)大小為48字節(jié)%26;#215;48字節(jié)的緩沖區(qū),這個(gè)緩沖區(qū)對(duì)應(yīng)參數(shù)圖像幀中以當(dāng)前宏塊位置為中心的一個(gè)大小為48字節(jié)%26;#215;48字節(jié)的窗口。 依據(jù)與前面一樣的思想,這里同樣使用乒播講方式的搜索窗口緩沖區(qū)。在片內(nèi)RAM中開辟兩個(gè)48字節(jié)%26;#215;48字節(jié)的搜索窗口緩沖區(qū),初始化時(shí),先將搜索窗口緩沖區(qū)充滿。第一次運(yùn)行估計(jì)的參考搜索窗口乒緩沖區(qū);第二次運(yùn)行估計(jì)時(shí)參考乓緩沖區(qū),此時(shí)提交一個(gè)QDMA請(qǐng)求,將下一宏塊需要的搜索窗口數(shù)據(jù)送往搜索窗口乒緩沖區(qū)。如此反復(fù),每次在參考某具搜索窗口緩沖區(qū)進(jìn)行運(yùn)動(dòng)估計(jì)時(shí),都提交一個(gè)QDMA請(qǐng)求,在后臺(tái)將下一宏塊的搜索窗口數(shù)據(jù)送入另一個(gè)搜索窗口緩沖區(qū)。圖5和圖6本節(jié)實(shí)際上是圖像宏塊編碼的反過程,宏塊編碼時(shí)使用EDMA節(jié)省的是從片外SDRAM讀取圖像數(shù)據(jù)的開銷,而本節(jié)使用EDMA節(jié)省的是將重建數(shù)據(jù)幀從片內(nèi)L2存儲(chǔ)器寫到片外SDRAM的開銷。 在片內(nèi)RAM中開辟兩個(gè)塊組緩沖區(qū),同樣采用乒乓方式,用于保存編碼過程中當(dāng)膠編碼宏塊的重建數(shù)據(jù)。之所以開辟塊組大小的緩沖區(qū),而不是宏塊大小的緩沖區(qū),是為了防止過多的片內(nèi)與片外數(shù)據(jù)傳輸?shù)腅DMA要求。這一點(diǎn),圖像宏塊編碼也是一樣的。每當(dāng)乒塊組緩沖區(qū)的宏塊都重建完畢,就通過提交一個(gè)QDMA請(qǐng)求,將該塊組緩沖區(qū)內(nèi)的重建宏塊一次性復(fù)制到片外的重建幀緩沖區(qū)中,同時(shí)開始下一宏塊的重構(gòu),并將重構(gòu)宏塊放在乓塊組緩沖區(qū)。 本文提出的幾個(gè)H.263編碼環(huán)節(jié),最自然的做法是CPU參數(shù)與數(shù)據(jù)塊的搬移工作,然后再進(jìn)行下一步的工序。使用EDMA的數(shù)據(jù)訪問策略,可以減少CPU花費(fèi)在數(shù)據(jù)搬移上的開銷。在CPU和EDMA對(duì)片內(nèi)存儲(chǔ)器L2進(jìn)行各自獨(dú)立的訪問時(shí),可能并不是理想的同時(shí)進(jìn)行,有可能產(chǎn)生沖突。但是CPU對(duì)存儲(chǔ)器L2的訪問優(yōu)先級(jí)高于EDMA對(duì)L2的訪問優(yōu)先級(jí),而且即使出現(xiàn)EDMA在數(shù)據(jù)搬移完畢之前,DSP已經(jīng)處理完了上一步工序這樣一種最惡劣的情況,DSP也只需再稍微等待片刻即可。因?yàn)橐呀?jīng)有部分?jǐn)?shù)據(jù)傳輸完畢,所以整個(gè)數(shù)據(jù)搬移上耗費(fèi)的時(shí)間相對(duì)于不用EDMA只可能減少。如果設(shè)置合理,這個(gè)時(shí)間通常是零。
評(píng)論