<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 在TMS320C6711 DSP上實現(xiàn)H.263視頻編碼器的EDMA數(shù)據(jù)存取策略

          在TMS320C6711 DSP上實現(xiàn)H.263視頻編碼器的EDMA數(shù)據(jù)存取策略

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

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();