[zz] 視頻解碼最佳化

來源:互聯網
上載者:User

以下通過剖析一些經驗來瞭解視頻解碼最佳化
1. 在嵌入式系統中實現MPEG4的視頻解碼
有兩種方法可行
(1)採用ffmpeg(mplayer 的核心就是採用ffmpeg),然後對ffmpeg mp4解碼最佳化

1).對IDCT彙編化,並最佳化VLD的實現   ->inline&彙編化
2).根據ARM9 cache&cache line的大小做MB的分組,使得每次可以同時處理多個MB
  即對多個MB在一個迴圈內做VLD--->IDCT-->MC--.......  ->耦合
3).最佳化關鍵程式碼片段的記憶體訪問(MC)    ->inline&彙編化
4).不要使用FFmpeg內建的img_convert()做yuv2rgb轉換  ->inline&彙編化
5).對解碼庫做ARM指令集最佳化    ->體繫結構最佳化
  configured ffmpeg with cpu = ARMV4L would give you a better performance
  If you have IPP,you can enable it, you can obtain huge enhancement
  IPP=Intel? Integrated Performance Primitives intel高效能構件庫(only for xScale)
 
(2)用xvid來做,ffmpeg包含的解碼庫太多,如果你只做MPPEG4解碼,何必用這麼複雜的庫.
btw,在嵌入式系統中最好用0.9.2版的xvid。因為1.1.0的版本包含了很多AS的特性,通常在
嵌入式系統中都不需要用,並且也不容易實現。要自己做編碼演算法的話,不能總想依賴別人
,最好還是需要自己花功夫去實現和最佳化。因此我覺得從實際出發的話,XVID0.9.2版的比
1.1.0的好。實際上,通常在主頻400MHz的平台上,要最佳化XVID的演算法達到CIF即時解碼也還
是很容易的,最多就一個多月

2. 視頻解碼流程對解碼帶來的影響
視頻解碼最佳化一般代碼量大,而且原始碼往往是從其他地方擷取得到的,所以閱讀比較困難
,更別說最佳化了,最近在最佳化realVideo,有幾點心得:
1).閱讀代碼前必須先熟悉流程,抓住關鍵的點,比如視頻解碼不外乎熵解碼,反量化,反變
換,插值,重建,濾波,參考幀插入等。把握住這幾個點,可以將代碼很快分離出來。
2). 分析解碼流程,瞭解解碼需要的最小buffer是多大,各個buffer 的位寬多大。
3).根據已經知道的流程,跟蹤代碼buffer流向,是否存在多餘的記憶體拷貝。想辦法將buffer
減少,經驗說明,減少buffer帶來的速度上的提升遠大於局部演算法的最佳化。 ->耦合
4).觀察程式結構順序是否合理,不合理的程式結構會導致buffer增大。
這兩天研究視頻解碼順序,發現先插值後做反變換要比先做反變換再做插值效率要高許多,
原因是插值後的位寬是8bits,而往往反變換後是9bits,所以在重建之前要儲存插值後的值
要比儲存反變換後的值要省一半的空間,這樣在重建時訪問的記憶體就少很多了。據我瞭解,
大部分高效率的解碼器都是先插值再反變換,而且變換後馬上做重建,這樣既減少記憶體使用量
,也避免記憶體訪問抖動太厲害,最終減少緩衝不命中。 ->修改解碼流程 耦合

3. cache機制對解碼帶來的影響
先看 http://www.hongen.com/pc/diy/know/mantan/cache0.htm
寫透(直寫式)和寫回(回寫式)有著截然不同的操作,在不同的場合,不同的記憶體塊使用
不同的回寫策略(如果你的系統可以實現的話)要比使用一種策略要高效得多。具體一點,
對於反覆存取的記憶體塊置成寫回,而把一次寫入而很長時間以後再使用的記憶體置為寫透,可
以大大提高cache的效率。
第一點很容易理解,第二點就需要琢磨一下了,由於寫透的操作是,當緩衝有該地址的資料
時同時更新緩衝和主存,當緩衝沒有該地址資料直接寫主存,忽略緩衝。當該地址的資料很
長時間後才被使用到,那麼在使用的時候該資料肯定不在cache中(被替換了),所以不如直
接寫入主存來得直接;
相反,如果使用寫回操作,當 cache中有該地址資料,需要更新該資料,設定dirty位,很長
時間後再使用該資料或被替換的時候才將其刷進主存,這有佔了茅坑不拉屎的嫌疑;而當
 cache沒有該地址資料時,情況更糟糕,首先需要將相應的主存資料(一個cache line)導
 入cache,再更新資料,設定dirty位,再等待被刷回記憶體,這種情況不僅佔用了cache的空
 間,還多一次從主存中匯入資料的過程,同樣佔據匯流排,開銷很大。至於為什麼要先從主存
 中匯入資料,是因為cache往主存回寫資料時是按照一個cache line 單位來寫的,但被更新
 的資料可能沒有一個cache line這麼多,所以為了保證資料一致性,必須先把資料匯入
 cache,更新後再刷回來。
對於很多視頻解碼來說,幀寫入過程是一個一次性的動作,只有在下一次作為參考幀時才會
被使用到,所以幀緩衝記憶體可以設定為寫透操作,而下一次使用它的時候很可能是作為參考
幀來使用,而作為參考幀不需要反覆的存取,只需一次讀操作就可以了,所以效率並不會因
為不經過cache而降低。實驗證明該方法可以使 mpeg4 sp解碼提高20-30%的效率。
相似的內容cache操作的小技巧還有prefetch操作,prefetch操作是將主存的資料匯入cache
而期間cpu不需要等待,繼續下一條指令的執行,如果下一條指令也是匯流排的操作,那麼就必
須等待prefetch完成以後再開始。所以,在使用該指令時,在prefetch指令後面插入儘可能
大於一次緩衝不命中所需要的clock數對應的指令,那麼prefetch與其後面的指令可以並行執
行,從而省去了等待的過程,相當於抵消緩衝不命中的損失。當然,如果插入的指令太多而
cache太小,有可能prefetch的資料進入cache 後又被替換掉了,所以,這需要自己去評估。 
->cache最佳化

4. 總結
IDCT是視頻解碼中關鍵步驟中的第一步,目前一般採用快速演算法來做,如chen-wang 演算法,
c語言和彙編的效果差別還是比較大的。
對一個8x8的block做idct做變換,如   
    for (i = 0; i < 8; i++)
         idct_row (block + 8 * i);
    for (i = 0; i < 8; i++)
         idct_col (block + i);
把他彙編後,主要是可以減少儲存空間頻寬,提高儲存效率,避免無謂的記憶體讀寫。
mplayer 在此方面做了很多努力,針對armv4(s3c2440屬於armv4l架構)的相關檔案放在
dsputil_arm_s.S檔案中。但遺憾的是,它裡面有一條指令PLD,cache預取指令2440是不支援
的。PLD指令屬於enhanced DSP指令,在armv4E(E 既代表enhanced DSP)才被支援,因此在我
們orchid上跑的代碼必須注釋掉這條指令,否則編譯不過.再把話題轉回來,在IDCT之前,視
頻壓縮流通過VLD(variable lenght decode)變長解碼得到DCT資料。這部分工作一般是通過
查表來加速效能,所有的編碼錶會預先存起來。而取視頻位元流的代碼通常是宏,通過宏的
擴充來達到和彙編同樣的效果。在IDCT後還有關鍵的運動補償和色彩空間轉換兩個步驟。對
運動補償的加速也是通過彙編化,其代碼也同樣放在dsputil_arm_s.S 有必要一提的是在這
部分,如果有SIMD指令將會極大的提高它的速度。
color space轉換是解碼輸出後的最重要的一步。在嵌入式系統中,一般都是採用rgb565既
16bit來表示一個像素的色彩。
一個8x8的block,它的yuv(420格式)表示如下,
        YYYYYYYY
        YYYYYYYY
        YYYYYYYY
        YYYYYYYY
        UUUUUUUU
        VVVVVVVV
注意它的值是8bit的,通過裝換方程計算,可以得到像素值。在實現中通常採用查表來加速
計算,對於每一個Y,U,V都有一個對應表。對於1個320x240的video,共76800像素。如果每
個像素在這個轉換中節省10個cycle,那save下來的cpu還是相當可觀的。
當色彩空間轉換完後,就是通過把這個picture copy到framebuffer的記憶體裡,這裡存在一大
片的copy時間。有兩方面可以注意,一是有人實現過把轉換後的記憶體直接往framebuffer送,
減少最後所需的copy過程,這個idea確實不錯,但是需要一些技巧去實現,二是copy這個過程
本省也是可以加速的,在armv5以上的體繫結構裡,cpu----cache---memory,其中cache和
memory的寬度是32位,但cpu和cache的bus width確是64位,用32位的成本實現了64位的儲存
器。如果這個能被使用,那麼理論上,copy速度可以加倍。在PC機上,一般我們的應用程式會有
fastmemorycopy這個函數,它們是用simd等特殊指令來實現,在armv5上則是通過它的總
線寬度來加速在s3c2440上不可用:( 它是v4架構。
總的來說:
(1).演算法級的最佳化基本用無可用,ffmpeg/mplayer已經實現的相當不錯,除非自己實現一個
新的decoder;
(2).在代碼級,主要是通過關鍵代碼的inline(宏,inline函數)和彙編來加速。這部分在
arm平台還是有一些潛力可挖
(3).硬體級,在這一層,cpu的體繫結構決定指令集、cache的形式和大小等。如指令集是否
有enhanced DSP指令、SIMD指令,cache是否可配置、cache line大小,這些都會影響代碼級
和演算法級的最佳化
(4).系統層最佳化,之所以把它放在最後一層,是由於它建立在整個系統之上,只有對整個系
統包括硬體和軟體有深刻的理解才能做到。
縱觀最佳化,其實質是儘可能的去除冗餘計算,最大化的利用系統硬體資源。
對於RISC架構的cpu來講,先天不足的就是需要比較大的儲存空間頻寬(因為RISC的指令都是基
於寄存器的,必須把運算元都load到記憶體才能計算),cpu資源被過多的使用在記憶體的read和
write。
以下面代碼為例,它是解碼輸出後,把yuv空間裝換成rgb空間的一個片斷
000111c :       
    111c:       e92d4ff0        stmdb   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    1120:       e1a0a000        mov     sl, r0
    1124:       e5900038        ldr     r0, [r0, #56]
    1128:       e1a0c001        mov     ip, r1
    112c:       e3500004        cmp     r0, #4  ; 0x4
    1130:       e24dd034        sub     sp, sp, #52     ; 0x34
    1134:       e1a00002        mov     r0, r2
    1138:       e1a01003        mov     r1, r3
    113c:       0a00055d        beq     157c
    1140:       e59d2058        ldr     r2, [sp, #88]
    1144:       e3520000        cmp     r2, #0  ; 0x0
    1148:       d1a00002        movle   r0, r2
    114c:       da00055b        ble     1574
    1150:       e59d3060        ldr     r3, [sp, #96]
    1154:       e58d1030        str     r1, [sp, #48]
    1158:       e5933000        ldr     r3, [r3]
    115c:       e59f2434        ldr     r2, [pc, #1076] ; 1598 <.text+0x1598>
    1160:       e0213193        mla     r1, r3, r1, r3
    1164:       e58d3018        str     r3, [sp, #24]
    1168:       e59d305c        ldr     r3, [sp, #92]
    116c:       e58d1000        str     r1, [sp]
    1170:       e5933000        ldr     r3, [r3]
    1174:       e79a1002        ldr     r1, [sl, r2]
    1178:       e58d301c        str     r3, [sp, #28]
    117c:       e5903008        ldr     r3, [r0, #8]
    1158:       e5933000        ldr     r3, [r3]
    115c:       e59f2434        ldr     r2, [pc, #1076] ; 1598 <.text+0x1598>
    1160:       e0213193        mla     r1, r3, r1, r3
    1164:       e58d3018        str     r3, [sp, #24]
    1168:       e59d305c        ldr     r3, [sp, #92]
    116c:       e58d1000        str     r1, [sp]
    1170:       e5933000        ldr     r3, [r3]
    1174:       e79a1002        ldr     r1, [sl, r2]
    1178:       e58d301c        str     r3, [sp, #28]
    117c:       e5903008        ldr     r3, [r0, #8]
    1180:       e59c4008        ldr     r4, [ip, #8]
    1184:       e590e000        ldr     lr, [r0]
    1188:       e59c2000        ldr     r2, [ip]
    118c:       e5900004        ldr     r0, [r0, #4]
    1190:       e59cc004        ldr     ip, [ip, #4]
    1194:       e58d3014        str     r3, [sp, #20]
    1198:       e1a011c1        mov     r1, r1, asr #3  ;h_size
    119c:       e3a03000        mov     r3, #0  ; 0x0
    11a0:       e58d4010        str     r4, [sp, #16]
    11a4:       e58d2004        str     r2, [sp, #4]
    11a8:       e58de020        str     lr, [sp, #32]
    11ac:       e58d000c        str     r0, [sp, #12]
    11b0:       e58dc008        str     ip, [sp, #8]
    11b4:       e58d1028        str     r1, [sp, #40]
    11b8:       e58d3024        str     r3, [sp, #36]
    11bc:       e1a08003        mov     r8, r3
    .................................................
    .................................................
我們可以發現在這個片斷中有太多的ldr(load, read from memory)和
str(store, wirte to memory),而且過多的load和str還影響了cpu和memory之間的cache的效
率,形成cache抖動。當發生cache miss時,cahce控制器花了大力氣把內容從memory搬到
cache,但是沒怎麼用這個entry馬上又被替換掉。如果運氣不好,cache就一直這樣"抖動"。
在解碼過程中,各個模組都各自為戰,都各自去佔比較大的memory頻寬
如何減少這種無用的行為呢?必須讓關鍵代碼適應硬體體繫結構,把資料流相關的代碼耦合
在一起。很多代碼通過模組化得到了優秀的可讀性和可擴充性。魚與熊掌不可兼得,耦合在
一起的代碼會顯得比較晦澀難懂。ffmpeg/mplayer在這方面作了一個比較好的trade-off。
1、2、3的知識摘自網上,要比較好的理解以上內容需要一些視頻編、解碼的知識。 

BTW:http://blog.csdn.net/weixianlin/archive/2008/05/01/2358035.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.