H.264中SAD SATD及常見知識點

264標準只定義了碼流的格式編碼器實現是各公司自己的事,只要形成的碼流符合標準就行解碼器必須按照這個格式來,這樣任何符合標準的碼流都可以解出來
Q:什麼是SAD,SAE,SATD,SSD,SSE,MAD,MAE,MSD,MSE?
A:SAD(Sum of Absolute Difference)=SAE(Sum of Absolute Error)即絕對誤差和
SATD(Sum of Absolute Transformed Difference)即hadamard變換後再絕對值求和
SSD(Sum of Squared Difference)=SSE(Sum of Squared Error)即差值的平方和
MAD(Mean Absolute Difference)=MAE(Mean Absolute Error)即平均絕對差值
MSD(Mean Squared Difference)=MSE(Mean Squared Error)即平均平方誤差
 
Q:如果不用率失真最優化,爲什麼選擇SATD+delta×r(mv,mode)作爲模式選擇的依據?爲什麼運動估計中,整象素搜索用SAD,而亞象素用SATD?爲什麼幀內模式選擇要用SATD?
SAD即絕對誤差和,僅反映殘差時域差異,影響PSNR值,不能有效反映碼流的大小。SATD即將殘差經哈德曼變換的4×4塊的預測殘差絕對值總和,可以將其看作簡單的時頻變換,其值在一定程度上可以反映生成碼流的大小。因此,不用率失真最優化時,可將其作爲模式選擇的依據。
一般幀內要對所有的模式進行檢測,幀內預測選用SATD的原因同上。
在做運動估計時,一般而言,離最優匹配點越遠,匹配誤差值SAD越大,這就是有名的單一平面假設,現有的運動估計快速算法大都利用該特性。但是,轉換後SATD值並不滿足該條件,如果在整象素中運用SATD搜索,容易陷入局部最優點。而在亞象素中,待搜索點不多,各點處的SAD差異相對不大,可以用SATD選擇碼流較少的匹配位置
 
Q:下面代碼的功能是什麼?
if(x & (~255))
{
pix[i] = (-x) >> 31;
}
else
{
pix[i] = (unsigned char)x;
}
A:
x的定義是short型,pix定義的是unsigned char型
這段代碼可以這麼理解(這段代碼的功能):
如果x<0,-x爲正,-x左移31位肯定爲0,那麼pix[i]=0,
如果x>255,那麼pix[i]=255,否則pix[i]=x;
 
#include <stdio.h>
main()
 {
 short x;
 unsigned char pix;
 x=1024*16;
if(x & (~255))
pix = (-x) >> 16;
else
pix = (unsigned char)x;
printf("pix=%d\n",pix);
}
 
Q:CABAC中開始時各字符出現的概率是怎麼得到的?
A:基於查表實現的
 
Q:What is RVLC?
A:It is a VLC method which can be decoded from left to right and from right to left exclusively
 
Q:RDO模型用來幹什麼?RQ模型又用來幹什麼?
A:RDO用來確定編碼模式的,保證碼率比特數和圖像失真的最佳權衡點,而RQ是在上一層碼率數一定的情況下用來確定下一層分配的比特數。RQ先於RDO進行。
Q:幀,場,圖像的聯繫與區別是什麼?
frame;逐行掃描圖像
field:隔行掃描圖像,偶數行成爲頂場行,奇數行稱爲爲底場行,所有頂場行稱爲頂場,同樣所有底場行稱爲底場。
pictue:場和幀都可認爲是圖像
[注:SUPERPUMA語]
頂底場分別編碼,對應位置的宏塊叫做宏塊對。頂場對已編碼的頂/底場預測編碼。底場一般對頂場預測編碼
frame;逐行掃描圖像
field:隔行掃描圖像,偶數行成爲頂場行,奇數行稱爲爲底場行,所有頂場行稱爲頂場,同樣所有底場行稱爲底場。
pictue:場和幀都可認爲是圖像
[注:SUPERPUMA語]
頂底場分別編碼,對應位置的宏塊叫做宏塊對。頂場對已編碼的頂/底場預測編碼。底場一般對頂場預測編碼
 
Q: I幀和P幀的概念比較好懂,B幀的概念有些模糊,只知道加了B幀圖像質量會更好,請問對B幀該怎麼理解?
A: B 幀在 MPEG-4 中有四種參考模式如果是同時參考前後的畫面壓縮則記錄的是 和 (前畫面 pixel 值 + 後畫面 pixel 值)/2 的差值,也就是 和 「前後畫面的平均」的差值。所以記錄的差值個數和 P 幀一樣,只有一個,沒有增加。而因爲 B 幀位於前後畫面的中間,以「前後畫面的平均」,也就是「前後畫面的中間值」來作爲預測數值(預測 B 幀的 pixel 數值爲多少?如果有誤差,再記錄差值),這樣這個預測數值會比單獨使用前一個畫面來預測,更接近目前真正的 B 幀的數值,可想而知,如此所需要記錄的差值就會很小甚至可以根本不用記錄,所以便可以省下很多的 bits,提高壓縮率。
除了壓縮率以外,B 幀對畫質的影響也是有的,因爲 B 幀這種參考前後畫面的特性,等於有內插(interpolation)的效果,所以可以減少噪訊。
Golomb 用於運動矢量,模式類型,頭信息等編碼
CAVLC用於殘差編碼
CABAC都可以
 
常用的測試序列選擇:
Coastguard :爲物體的相對運動和鏡頭移動
flower :爲物體的劇烈運動和鏡頭的快速移動
garphone :爲物體的快速轉換
foreman :爲物體轉換和鏡頭移動
mobile&calendar :爲物體的多種運動和鏡頭移動
 
爲什麼幀內預測要用未濾波的圖像而不是濾波後的圖像呢?
幀內預測只能用濾波前的值,因爲幀內預測的時候邊界濾波還不能進行,幀內預測所需要的象素點的邊界的濾波不能進行,因爲需要等到當前宏塊解完後纔開始,但是你現在就在解當前宏塊,所以爲了避免預測和濾波的耦合應該分開來單獨做,prediction的時候保存一個line buffer就解決問題了
 
Q:CQM_4IY,CQM_4IC,CQM_4PY,CQM_4PC,CQM_8IY,CQM_8PY的含義?
A:cqm_4iy->INTRA4X4_LUMA,cqm_4ic->INTRA4X4_CHROMA
cqm_4py->INTER4X4_LUMA,cqm_4ic->INTER4X4_CHROMA
cqm_4py->INTER8X8_LUMA,cqm_4ic->INTER8X8_CHROMA
 
 
 
Q:在x264的x264_cqm_init( x264_t *h )函數中:
for( i = 0; i < 16; i++ )
{
h->dequant4_mf[i_list][q][0] = def_dequant4[q] * h->pps->scaling_list[i_list];
h-> quant4_mf[i_list][q][0] = def_quant4[q] * 16 / h->pps->scaling_list[i_list];
}
第二個式子爲什麼*16?
A:你不要管這個16,這個16是約定成俗的,要和量化,凡量化一直考慮
Q:unquant4_mf[4][52][16]這個矩陣也是量化裏面的,你看量化矩陣和反量化矩陣都是4維的,而這個是3維的
A:unquant4_mf[i_list][q],是0~15,是線性排列,quant4_mf[i_list][q%6][0],是[][]矩陣排列
Q:在上面的程序中量化和反量化矩陣爲什麼第三維只爲0呢?
A:爲0纔對,因爲本來定義[4][4],現在要線性訪問16個成員,就必須[0]了
 
Q:關於skip模式的問題
A:When a Skipped macroblock is signalled in the bitstream, no further data is sent for that macroblock. The decoder calculates a vector for the skipped macroblock and reconstructs the macroblock using motion-compensated prediction from the first reference picture in list 0.
p_skip 就是說只計算參考幀中的mv,傳輸的是0數據,直接把參考中的匹配宏塊拿過來就行了,skip模式只傳送mb_type,其他信息都是從參考楨中獲取,在解碼端計算MV及恢復殘差數據,MV不是從參考幀獲得的,是在解碼端計算,mv是根據周圍的相鄰塊的mv進行計算,好像是取中間值,有點像MV在運動估計時候的預測,是隻傳送mb_type,其他信息都可以計算出來,這就是skip。
To have a SKIP mode in H.264, a macroblock should meet following conditions all together [5]:
(i) the best motion compensation block size is 16x16,
(ii) reference frame is just one previous one,
(iii) motion vector is (0,0) or the same as its PMV, and(iv) its transform coefficients are all quantized to zero.
(iv) its transform coefficients are all quantized to zero
 
FrameSkip,該參數是對原始YUV幀丟棄數,就是說每隔一幀(I或者P,不包括B)丟棄FrameSkip幀。
NumberBFrames,就是兩個編碼幀中間B幀的數目,該數必須小於FrameSkip
FramesToBeEncoded,總共要編碼的幀數,不包括B幀.因爲在編碼過程中 b幀對其他幀並不產生影響,而且在實時編碼中,如果負擔過重;或帶寬有限,可以有選擇的丟棄b幀
IntraPeriod,每IntraPeriod幀(I/P幀)有一個I幀編碼
如果你選擇的frameskip>=1,numberbframes=0,intraperiod>1,序列類型:ipp...ipp...
如果你選擇的frameskip>=1,numberbframes=1,intraperiod>1,序列類型:ipbpb...ipbpb...
如果你選擇的frameskip>=2,numberbframes=2,intraperiod>1,序列類型:ipbbpbb...ipbbpbb...
 
P_Skip的特別之處在於碼流中不傳輸MVD數據,預測塊的大小肯定史16*16。當下面四個條件滿足任意一個時,當前宏塊的MV預測值直接置爲(0,0),不滿足時當作普通P宏塊處理
– mbAddrA is not available
– mbAddrB is not available
– refIdxL0A is equal to 0 and both components of mvL0A are equal to 0
– refIdxL0B is equal to 0 and both components of mvL0B are equal to 0
 
Q:爲何在cavlc編碼的時候,第一個負數要加1?
A:如果拖尾小於3,說明第一個level的絕對值值肯定大於1。因此,level爲正時,減1;爲負時加1。可降低碼流
Q:H.264中,術語IDR的意思是什麼,有什麼用?
A:IDR-instantaneous decoding refresh (IDR)picture;
A coded picture in which all slices are I or SI slices that causes the decoding process to mark all reference pictures as "unused for reference" immediately after decoding the IDR picture. After the decoding of an IDR picture all following coded pictures in decoding order can be decoded without inter prediction from any picture decoded prior to the IDR picture. The first picture of each coded video sequence is an IDR picture.
也就是說,IDR的出現其實是相當於向解碼器發出了一個清理reference buffer的信號吧,上面說前於這一幀的所有已編碼幀不能爲inter做參考幀了。
 
Q:jm各個版本之間的代碼做了些什麼改動,有沒有說明這些的文檔啊?
A:每個版本源代碼的根目錄下都有一個 change.txt 文件,裏面詳細記錄了所有版本的更新。
  針對對象不同,jm90以上全部是針對高保真的視頻的。86基本上可以滿足一般處理的所有要求。
 
Q:在VC環境下是如何讀入*.yuv序列的?
A:把*.yuv文件當作一般的文件讀就可以了。
   如下:

#include <stdio.h>
#include <malloc.h>

void main()
{
   char *Y;
   char *Cb;
   char *Cr;
   int  width = 352,  height = 288;
   FILE *fp;
   FILE *fy;
   int i;

   Y = (char*)malloc(width*height);
   Cb = (char*)malloc(width*height/4);
   Cr = (char*)malloc(width*height/4);
   fp= fopen("input.yuv","rb");
   if(fp == NULL)
      printf("open input.yuv failed\n");

   fy = fopen("output.yuv", "ab+");
   if(fy == NULL)
      printf("open output.yuv failed\n");
  
   for(i = 0; i<1; i++)
   {
      //fseek(fp, i*width*height, 0);
      if(0 == fread(Y, width*height, 1, fp))
         printf("read error\n");
      if(0 == fwrite(Y, width*height, 1, fy))
         printf("write error\n");
     
      fread(Cb, width*height/4, 1, fp);
      fread(Cr, width*height/4, 1, fp);
      fwrite(Cb, width*height/4, 1, fy);
      fwrite(Cr, width*height/4, 1, fy);
   }
   fclose(fp);
   fclose(fy);
   free(Y);
   free(Cb);
   free(Cr);
}
Q:H.264中,術語IDR的意思是什麼,有什麼用?
A:IDR-instantaneous decoding refresh (解碼即時刷新IDR)picture;
A coded picture in which all slices are I or SI slices that causes the decoding process to mark all reference pictures as "unused for reference" immediately after decoding the IDR picture. After the decoding of an IDR picture all following coded pictures in decoding order can be decoded without inter prediction from any picture decoded prior to the IDR picture. The first picture of each coded video sequence is an IDR picture.
也就是說,IDR的出現其實是相當於向解碼器發出了一個清理reference buffer的信號吧,上面說前於這一幀的所有已編碼幀不能爲inter做參考幀了。

Q: YCrCb 4:2:0是什麼?像4:4:4和4:2:2一樣表示 Y:Cr:Cb是4:2:0嗎?
A: 4 : 2 :0 means that Cr and Cb each have half the horizontal and vertical resolution of Y, as shown. The term ‘4 : 2 : 0’ is rather confusing: the numbers do not actually have a sensible interpretation and appear to have been chosen historically as a ‘code’ to identify this particular sampling pattern. 有點4:1:1的味道。
 
Q:CAVLC的過程
A:
編碼
4×4的殘差塊通過Zig-Zag掃描,得到一系列字符,如:0,3,0,1,-1,-1,0,1,0......
由此序列推導出以下變量:TotalCoeffs(全部的非零係數,包括拖尾係數),TotalZeros(最後一個非零係數前面的所有0的個數,方向爲從左到右,比如上面的序列中,最後一個非零係數爲1),TrailingOnes(託尾係數的個數,並規定不能超過3個),然後通過NC值查表,把
TotalCoeffs ,和TrailingOnes的組合進行編碼,稱爲編碼元素coeff_token。接下來,對每個拖尾係數的符合編碼,0表示+,1表示負。再接下來,對剩下的非零係數編碼(此時拖尾係數已經被編碼了,不再包括),編碼方向爲從右到左,比如上面的序列中,先編碼1,再編碼3。這些係數被編碼後,是由level_prefix和level_suffix兩部分組成的。level_prefix的值通過查表得出,level_suffix是由若干個0組成,0的個數由suffixLength決定。再接着對TotalZeros的值編碼。然後對RunBefore(每個非零係數前零的個數)進行編碼,這個方向也是從右到左,並且最後一個(從左邊數的第一個)非零係數前零的個數不需要編碼,因爲後面的編過後,剩下多少個0只有一個存放位置,就是最前面。
解碼
由計算出的bit串長度讀出相應的bits,通過查表得到TotalCoeffs和TrailingOnes的值,此時無輸出,接着讀取拖尾係數的符合,由編碼的順序知,先讀到的是最後一個拖尾係數。解碼完拖尾係數並依次輸出,接下來是剩下的非零係數的值,通過查表解碼並輸出。然後解碼TotalZeros,此時輸出不變,仍爲以前的解碼值。接下來解碼RunBefore,因爲編碼時是從右往左編的,故第一個解碼出來的RunBefore應該插到第一個解碼出的拖尾係數的前面,即插入的方向也是從右到左,最後一步時,剩下的RunBefore都插入到最前面。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章