2010年2月28日 星期日

H.264 進度報告 --- 雙魚

== 2010.02.28===

在程式中去找intra prediction幾種比對模式的程式碼
luma有分成16*16和4*4兩種,Chroma提供4種兩個8*8模式

(1)luma 16*16是以一個16*16大小block去作預測,提供4種模式


(2)luma 4*4是把一個16*16 block再切成4個4*4去作預測,提供9種模式


(3)Chroma提供4種兩個8*8模式,分別是DC Mode、Horizontal Mode、
Vertical Mode、和 Plane Mode , 其中DC Mode會把8*8再切成4*4 block
依照每個4*4 block上側和左側資訊而有不同的數學式子去進行預測

這邊有從網路上找資料,資料pdf中有每一種預測模式的數學式子
從式子去推導每一點像素的式子數字,接著再和程式碼的寫法相對照
參考的pdf連結: http://0rz.com/LnhA

這學期理想的進度甘特圖

希望一個月可以完成一個元件的改寫,先從intra prediction開始
下禮拜會看AVS中intra prediction的文件內容

== 2010.02.01===

對quatization後的Y數值來壓縮和解壓縮
利用上次產生出來的codeword table來練習

(1)去找每個數值對應的codeword
ex:有三個數值5,13,-5, 5的codeword是101
13的codeword是0101 ,-5的codeword是1111

(2)codeword累積到8個以1個byte寫入新的檔案
設一個變數unsigned char c去記錄要寫入檔案的數值
a陣列記錄要壓縮數值所對應的codeword
當a[i]=1 , c = c先往左shift一個 再和00000001 作or
當a[i]=0 , c = c往左shift一個
如果c未滿8個 後面也沒有其他數值要壓縮
c=c往左shift讓剩下位置補0到滿8個

ex: 要壓數值5,13,-5 , codeword如(1)
第一次a陣列中是101, 判斷完a陣列中每個位置後 c=00000101
第二次a陣列中是0101, 判斷完a陣列中每個位置後 c=01010101
第三次a陣列中是1111, 判斷完a[0]位置後 c=10101011 已經達到8個
這時候就要把c寫入檔案 , 寫檔後讓c=0 再繼續判斷a陣列中剩下的位置
判斷完剩下的位置 c=00000111 , 因為後面沒有數值要壓縮所以補0
c = 11100000 , 最後再把此值寫入檔案中


(3)把(2)寫入的檔案讀出 , 把1個byte拆成8個bit
讀出1個unsigned char c 後 ,下面的動作要作8次
先 c= c和10000000作and , 再讓c往左shift一位
把解出來的bit放在buf 陣列中

ex: 把(2)產生的檔案數值讀出做完拆解判斷後
buf中會是: 10101011 11100000


(4)到table中找codeword對應的數值
table會先依照codeword大小排序 , 從小到大排序
buf會一個一個位置去找現在停在哪個codeword中的哪bit
如果此codeword下一個bit是'\0' , 代表找到一個對應的數值

ex: 假設table只有三種codeword , 設定如(1)
codeword排序後是: 0101 , 101 , 1111
buf是: 10101011 11100000

當buf[0]=1 , 會停在 codeword 101 中的第0個bit
當buf[1]=0 , 會停在 codeword 101 中的第1個bit
當buf[2]=1 , 會停在 codeword 101 中的第2個bit
codeword 101 第三個bit是 '\0' , 所以就找到一個對應數值5


== 2010.01.22===

建立 huffman tree來產生對應的codeword
拿上禮拜作完quatization後的Y數值來練習

(1)去計算Y數值中每一種數值出現的機率
假設4種節點機率分別為0.15 , 0.2 , 0.25 , 0.4 (圖中紫色點)

(2)開始建立 huffman tree
S為所有節點的集合 , 從S中找出機率最小的兩個 : t1 t2
用t1 t2來產生一新節點N, N 是 t1 和 t2 的 parent節點
而且N的機率為 t1 + t2 , 接著把 t1 t2 從S中刪掉, 把新節點 N 加入S中

圖中用4種節點來說明步驟 , S= {0.15,0.2,0.25,0.4}
先拿0.15 和 0.2 來組合 , 此樹節點機率為0.35 (圖中藍色點)
把 0.15 和 0.2 從S中刪掉 , 把藍色點的樹0.35加入S中
接著拿0.25 和 藍色點的樹 來組合 , 此樹節點機率為0.6 (圖中咖啡點)
把0.25 和 藍色點的樹從S中刪掉, 把咖啡點的樹0.6加入S中
最後拿0.4和 咖啡點的樹 來組合 , 最後root的機率為1


(3)去找每種數值對應的codeword
左邊樹分支填 0, 右邊樹分支填 1
每個分支的 0 或 1 是圖上的黃底綠色字
每種數值的codeword就是從root到該數值節點的 0 和 1 組合

從圖上標記可以看到:
數值0.4的codeword是 0
數值 0.25的codeword是 10
數值 0.15的codeword是 110
數值 0.2 的codeword是 111


== 2010.01.15===

完成 DCT-> quatization -> IDCT 的練習
一樣是用txt檔案中的YUV數值
分別對YUV去作DCT-> quatization -> IDCT

YUV以4:2:0的方式儲存 , 4個Y共用一個U和V
所以 Y 範圍是352*288 , U和V則是 176 *144
先對Y作處理 , 接著就是U和V , 每次都以8*8為單位
流程如下:
(1)用下列的公式去產生DCT 8*8矩陣的數值
Aij = Ci*(cos((2*j+1)*i*pi)/2*N) ,
when i=0 , Ci= (1/N)^1/2
when i>0 , Ci= (2/N)^1/2

因為DCT是8*8 , 所以N=8
Aij代表的是矩陣中第 i行第j列的數值
DCT陣列的數值是double的形態儲存

(2)利用 D=(A)(X)(T)來作DCT
A是步驟(1)產生的DCT矩陣
T是A矩陣的轉置矩陣
X是圖片切出來的8*8方塊
D是AXT三者作矩陣運算後的8*8矩陣
D也是用double的形態儲存

(3)去網路找 YUV的 quatization table
quatization table也是8*8的矩陣
把經過DCT後的數值除以quatization table上的數值
除以quatization後的數值先做四捨五入
接著以 int的型式儲存起來

(4)把步驟(3)儲存的數值再乘上quatization table的數值
再以double的形態把乘完quatization的數值儲存起來

這時候會發現數值和一開始經過DCT後的數值有稍微的不同
ex: 經過DCT後是527.89 , 除以quatization 16 再四捨五入後
會以33的數值存起來 , 再乘回quatization 16 會變成528
雖然會有些微的不同 但是誤差都不會太大

(5)利用 X=(T)(D)(A) 來作IDCT
A是步驟(1)產生的DCT矩陣
T是A矩陣的轉置矩陣
D是步驟(4)儲存的8*8矩陣
X是TDA三者作矩陣運算得到的8*8矩陣

要去判斷X中的每一點的數值
如果數值>255, 要讓它等於255
如果數值<0 , 要讓它等於0
最後把X中的數值轉成 unsigned char 型式儲存起來

等 Y, U, V的範圍都作完上述流程
最後把數值以二進位模式寫入.yuv檔案中即可

如果quantization的數值比較小 , 被忽略掉的訊息比較少
作出來的圖片結果會和原始圖差距較小
如果quantization的數值稍大,被忽略掉的訊息比較多
可以從圖片上看到一些地方會變得比較模糊


== 2009.12.30===

利用之前txt檔案中YUV數值
此txt檔案中只有影片中第0張的YUV數值
將這些數值以frame型式寫入新的.yuv檔
檢查新檔案顯示的畫面是否和原本影片中第0張一樣

接著把txt檔案中YUV的數值轉成RGB模式
YUV是以4:2:0的方式儲存 , 每4個Y會共用一個U,V
一個MB裡面會有16個Y,4個U和4個V
RGB是4:4:4, 所以要先弄成一個MB裡面有16個Y,16個U和16個V

接著套用 YUV->RGB 的公式去計算
如果轉換後的數值>255, 要讓它等於255
如果轉換後的數值<0 , 要讓它等於0
最後再寫入.rgb的新檔案中即可


== 2009.12.24===

寫了一個小程式去判斷抓出的圖片數值是否正確
1.先讀取存在txt檔中的YUV數值
2.直接寫一個函式去讀取圖片的YUV數值
3.最後比較兩者的YUV是否一致



這邊是練習對MB 和 frame的位置概念
參考圖片 , 整張圖是352*288, MB是16*16 (圖中紅色方塊)
txt檔中是把每個MB中16的點 由左至右 由上到下寫入
一個MB寫完在換下一個 , MB也是由左至右 由上到下
frame是一個點一個點讀取 由左至右 由上到下 (圖中紫色方塊)

所以讀出txt檔每一個數值, 都要放回它在圖片的原本位置
步驟2是把圖片一個點一個點的讀入,然後儲存起來
最後再比較這兩個種數值是否有一致


== 2009.12.10===

目前已經把上次提的數值抓出
除了bitrate, 其他數值都以binary型式寫入檔案

1. 每個16*16 (MB) 的數值
圖片大小352*288 , 每16*16切成一塊
把16*16裡每點的pixel數值寫入檔案

2. 每個MB作完intra prediction的different值
intra prediction 分成 4*4和 16*16 兩種
(1) 4*4有9種mode , 每一種mode都會算出一個different值
先用一個陣列暫存每種mode算出來的different值
接著計算每種mode的cost大小, 找出一個最好的mode
這邊也會有個變數去記錄哪個mode是cost最小的
最後把此種mode的different值存進陣列(a4)
以4*4 去算different值 , 但最後要的是16*16
所以每次算完的4*4 要按著順序存進陣列(a4)

(2)16*16則有4種mode , 作法同上
差別在於 這邊是用16*16去算different值
只要把最好mode的different值存進陣列(a16)即可

作完上述兩點 , 每個MB會有 4*4 和 16*16算完的最佳解
會從中選一個來當作這個MB使用的different值
所以最後選出的different值才是要寫入檔案的


3. 每個MB作完 DCT+ quantization 後的數值
程式作完 DCT+ quantization的值存在 nMBQuant_Y變數裡
而且大小也是宣告成 16*16
只要將 此變數中 256個數值 寫入檔案即可
有記錄 Frame_I DCT+ quantization 後的數值
以及 Frame_P DCT+ quantization 後的數值


4. 得到每個MB需要的bits數量
此數值存在nRDBitRate變數裡
只要將此變數的值寫入檔案即可
一樣要記錄 Frame_I 和 Frame_P的BitRate


== 2009.11.18 ===

已經跟小新學長拿了程式
為了達成了解基本的H.264運作流程
計畫先取出下列幾個數值:
1.抓出MB pixel值
2.抓出MB pixel值 做過 Prediction(inter or intra)
3.抓出MB 4x4 DCT值
4.抓出MB 4x4 DCT值做過 quantization
5.得到MB壓縮所需要的bits數量

把這五個項目的數值取出來,分別存成一個新檔
這些檔案裡面的數值是後續步驟會使用到的
存檔的類型沒有限制 , 我想說把每項的數據存成txt檔
就從第一項開始作起 , 現在剛看程式 大略知道第一項要的數值在哪
這邊會再問一下學長 , 希望下禮拜可以抓出第一項的數值

5 則留言:

SCREAMLab 提到...

你可以說明上面你列的這些數據要做什麼嗎? 之後可以做什麼研究呢? 要改進什麼嗎?

假如你有一個列表, 用表格的方式呈現那些數據的含義與用途, 那會更好喔!

SCREAMLab 提到...

很不錯, 有進步. 加油.

SCREAMLab 提到...

假如我沒說錯的話, 應該是對AVS的一個個元件的改寫在八月會完成.

另外要請小新規劃平行記算的架構.

SCREAMLab 提到...

這串的Title可以改嗎?我想變成264/AVS。

本來希望是平行的架構,但是跟小新談過後,覺的改做SIMD對你以後比較有幫助。

而比起X86 SSE,我們覺得ARM Cortex Neon比較有前途,所以今後請你報Neon。這會跟以前用Cell比較像,也會是你比較熟的。這部分請你另外開串。

至於Cortex平台,我有買一片,但是建議你先找 Simulator來用,其他toolchain如Compiler等請跟小新一起找,學著用,兩星期後開始講。

雙魚 提到...

我已經把此篇的內容合併到AVS那篇,
AVS那篇的標題改成 AVS/H.264

目前規畫6月底之前畫完intra prediction的流程,這樣7月可以來寫這個部分

ARM Cortex Neon的東西在7月以後的咪聽會開始報告