10. 目前的 XviD 的 DirectShow Filter 解 B frame 會出錯,當 B frame 的下一張
參考畫面是 I Frame 的時候,B frame 會參照到錯誤的參考方塊,造成解出來
畫面出現一堆亂七八糟的方塊,如下圖:
B-Frame(在 MPEG-4 裡面正確的名稱是 B-VOP)的預測模式有四種:
a. Forward 順向預測,參考前一張畫面,記錄和前一張畫面的差距。
和 P-Frame 的預測方法一樣。
b. Backward 逆向預測,參考下一張畫面,記錄和下一張畫面的的差距。
c. Bi-Directionally 雙向預測,參考前面和後面兩張畫面,記錄的是
和「前後兩張畫面的平均值」的差距。也叫做內插預測,壓縮率最高。
d. Direct Mode,不搜尋、紀錄動作向量,直接由下一張的 P Frame
推導出動作向量。譬如說 IBP,我們可以預測 B 畫面的動作必然
是介於 I 和 P 兩個畫面之間,所以我們可以偷懶不計算 B 的 MV,
直接用 P 的 MV/2 作為 B 的動作向量,這樣可以省去記錄 MV 的空間。
壓縮 B-Frame 的時候會從上面幾種預測模式中選壓出來最小的一個模式來使用。
而現在 XviD 的 bug 就是,當 B-Frame 可以有 Backward MV 指向下一張畫面,
而那一張畫面是 I-Frame 的時候就會造成解碼錯誤。
我沒有分析 bitstream,不過從錯誤的畫面看來,這張 B-Frame 的下一張畫面是
Scene Change 的地方,照理說壓出來會最小的預測模式應該是 Forward 預測,
只參考前一張 P-Frame 壓縮。
但是解出來的畫面卻明顯的是參照下一張 I Frame 解出來結果。
請看上一張錯誤解碼畫面的下一張 I Frame:
可以看出上一張錯誤解碼的畫面是參照到這張 I Frame 來解碼的,
但是真正的 MV 應該是指向前一張 P Frame:
記錄的差距值也是和前一張 P Frame 的差距,拿 I Frame 的相對位置來解碼,
當然會解出錯誤的畫面。
比對錯誤的 B 畫面和前一張 P 畫面,可以發現 B 畫面上沒有亂掉的部分,
是因為:
1) 該區域和前一張畫面差不多相同,所以被 skip 掉沒有壓縮,
解壓縮時直接重送上一個方塊。
2) 該區域和前一張畫面差很多,所以是以 intra-block 壓縮(獨立壓縮,
I-Frame 的壓縮方式),沒有 MV,沒有參照其他畫面,所以沒有解錯。
正確解碼出來的畫面應該是:
我猜想會造成這個錯誤解碼的原因是,如果允許 B-Frame 參照下一張 I,
解碼解到
畫面順序:
PBI
壓縮順序:
PIB
decoder 會先解出 I,然後解碼 B,本來 B 應該參照前一個 P 解碼,
但是不知道為什麼現在 B 參照的是 I 來解碼,所以造成了這種錯誤。
嗚哇,越寫越長 ^^;;
總之目前解決的辦法是把「使用相容 DX50 的 B-VOP」的選項勾起來,禁止 B-Frame
能夠參照下一張 I-Frame,就樣就不會發生這個問題了。
這個 bug 已經回報,應該會在一下版的 XviD 修正。
11. DivX 5.x 的 解碼器可以解碼 XviD 壓出來的 B-Frame,即使連續 B-Frame
的個數超過 1。(不過 DivX 5.x 的 encoder 自己壓的 B-Frame,只能 1 個,
只能為 IBPBPBPBPB.... 這種型態)
12. DivX 5.x 的 解碼器可以解碼使用 MPEG 量化方式壓縮的 XviD 檔案,
同時也可以解碼使用者自行定義的 MPEG 量化矩陣。(雖然 DivX 5.x 自己的
encoder,只能壓縮 H.263 量化方法的檔案)
13. DivX 5.x 的解碼器畫面修飾得比較漂亮,同時 CPU 使用率比現在的 XviD
decoder 少很多,現在的 XviD decoder 解碼負擔實在太重了。
(加上 Qpel,負擔更重,沒有 1G 以上恐怕跑不順)
繼續測試中...