一·參數說明
這一節闡述的是encoder.cfg 中的參數對編碼過程的影響 要注意的是encoder.cfg 中的參數跟input 結構體中的變量是一一對應的 StartFrame:從視頻流的第幾幀開始編碼 FramesToBeEncoded:指明瞭除去 B幀後將要被編碼的幀數 input->no_frames = FramesToBeEncoded FrameSkip:指明瞭編碼過程中跳過的幀數,中間有 B 幀也算跳過一幀。 NumberBFrames:相鄰 I、P幀或相鄰的 P幀之間的 B 幀個數,必須有 NumberBFrames< FrameSkip input->successive_Bframe = NumberBFrames IntraPeriod:I 幀出現的頻率。若 IntraPeriod="3",則每 3 幀(不含 B 幀)中有一 I 幀; IntraPeriod="0" 時只有第一幀是 I 幀。 IDRIntraEnable:此值爲1時每個 I幀都是 IDR,否則只有第一個 I幀是 IDR。 舉例:在 StartFrame="0" FramesToBeEncoded="5" FrameSkip="3" NumberBFrames="2" IntraPeriod="3" IDRIntraEnable="1" 的情況下編碼情況如下,其中紅色代表 IDR 幀 表 1 視頻流 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 編碼流 I B B P B B P B B I B B P 編碼順序 0 2 3 1 5 6 4 8 9 7 11 12 10 二·pic_order_cnt_type 爲 0 的情況 這種情況下顯式的計算 POC (1) 編碼端 I 幀或 P 幀 toppoc 的計算 這個過程在 main()函數的組循環 “for (img->number=0; img->number < input->no_frames; img->number++){ }” 中實現 z IntraPeriod或 IDRIntraEnable 爲零時 這種情況下只有第一個 I 幀是 IDR 幀,比較簡單。對於 I幀或 P 幀,其頂場的 POC 爲 (img->number) * (2*(input->successive_Bframe+1)) z IntraPeriod和 IDRIntraEnable 都不爲零時 這種情況下每個 I 幀都是 IDR 幀,其 POC 必須設置爲零, I幀出現的頻率爲 IntraPeriod, 故其 toppoc爲 (img->number % input->intra_period) * (2*(input->successive_Bframe+1)) z 說明: 原程序中使用了宏定義 IMG_NUMBER “#define IMG_NUMBER (img->number - start_frame_no_in_this_IGOP)” 通過搜start_frame_no_in_this_IGOP可知這個變量在NumberOfFrameInSecondIGOP爲0 (encoder_main.cfg 中就是這樣設置的)時恆爲 0,故有 IMG_NUMBER = img->number (2) 編碼端 B幀 POC 的計算 由表一可知,在編完一 I 幀或 P 幀之後纔開始對它前面的 B幀進行編碼 for (img->number=0; img->number < input->no_frames; img->number++) { ……I,P 幀編碼…… if ((input->successive_Bframe != 0) && (IMG_NUMBER > 0)) { …… for(img->b_frame_to_code=1; img->b_frame_to_code<=input->successive_Bframe; img->b_frame_to_code++) { } z IntraPeriod或 IDRIntraEnable 爲零時toppoc 等於 2+(img->number-1) * (2*(input->successive_Bframe+1)) +2* (img->b_frame_to_code-1) a) 第一個 2 指得是 IDR 的兩個場; b) img->number要減一是因爲要對當前幀(img->number)前面的 B幀進行編碼; z IntraPeriod和 IDRIntraEnable 都不爲零時 toppoc等於 2+(img->number % input->intra_period-1) * (2*(input->successive_Bframe+1)) +2* (img->b_frame_to_code-1) IDR 幀前面 (3) toppoc 到 pic_order_cnt_lsb 的轉化 img->pic_order_cnt_lsb =img->toppoc & ~((((unsigned int)( –1)) << (log2_max_pic_order_cnt_lsb_minus4+4))) z (unsigned int)(-1)的十六進制形式是 0xffffffff,即它的每一位都是 1; z log2_max_pic_order_cnt_lsb_minus4+4是圖象數目(包括 B 幀)最大值的位數 z 當 toppoc >0時,img->pic_order_cnt_lsb=img->toppoc 當 toppoc <0時,img->pic_order_cnt_lsb= max_pic_order_cnt+ img->toppoc 其中 max_pic_order_cnt=1<<( log2_max_pic_order_cnt_lsb_minus4+4) z 疑問: 不知道 toppoc 到 pic_order_cnt_lsb 這個過程有什麼意義; POC 的值會從 0 變到很大,爲什麼不對它進行熵編碼; (4) 解碼端 toppoc 的恢復 此過程在函數 decode_poc 中執行。其思想是對於 IDR 前的 B 幀 Toppoc = pic_order_cnt_lsb - max_pic_order_cnt 否則 Toppoc = pic_order_cnt_lsb 是否減去 max_pic_order_cnt 由變量 PicOrderCntMsb 決定,對於 IDR 前的 B 幀 PicOrderCntMsb = (– max_pic_order_cnt) 否則 PicOrderCntMsb = 0 到這就不難理解 PicOrderCntMsb 的含義了, PicOrderCntMsb 反映了 toppoc的值是否小於 0。 至於另外兩個參數:PrevPicOrderCntMsb 總是爲 0;PrevPicOrderCntLsb 在當前圖象是 IDR 或 IDR 前(視頻流中)的 B 幀時爲0,否則等於前一圖象(編碼序列中)的 PicOrderCntLsb。 三·pic_order_cnt_type 爲 1 的情況 這種情況下通過 frame_num來計算 POC (1)frame_num 簡介 參考《畢厚傑》7.3.4 節中 frame_num 條款的解釋,對於表 1 中的圖象序列,其 frame_num 的值參考如下: 表 2 視頻流 0 1 2 4 5 6 8 9 10 12 13 14 16 編碼流 I B B P B B P B B I B B P 編碼順序 0 2 3 1 5 6 4 8 9 7 11 12 10 frame_num 0 2 2 1 3 3 2 1 1 0 2 2 1 poc 0 2 4 6 8 10 12 -4 -2 0 2 4 6 (2)算法思想以及其解碼端的實現 z 對於 IDR 幀,poc = 0; z 對於 I 幀或P 幀 poc = frame_num*2*(input->successive_Bframe+1) 或 poc = 2*(input->successive_Bframe+1) + (frame_num – 1)*2*(input->successive_Bframe+1) 解碼端實現 poc = img->ExpectedPicOrderCnt + img->delta_pic_order_cnt[0] (在 I,P 幀下爲 0) z 對於 I 幀或P 幀之前的 B 幀(視頻流中) poc = (frame_num – 1)*2*(input->successive_Bframe+1) – 2*(input->successive_Bframe+1 – img->b_frame_to_code) 或 poc = 2*(input->successive_Bframe+1) + (frame_num – 1 – 1)*2*(input->successive_Bframe+1) + 2*( img->b_frame_to_code – 1) – 2*input->successive_Bframe 解碼端的實現 poc = img->ExpectedPicOrderCnt + img->delta_pic_order_cnt[0] + active_sps->offset_for_non_ref_pic z 變量說明 a) 其中 img->b_frame_to_code請參見標題一·(2) b) img->disposable_flag = (nalu->nal_reference_idc = = 0),而 nal_reference_idc 只在 B 幀時 爲0,即img->disposable_flag只在B幀時爲1。這也是在B幀情況下img->AbsFrameNum 要比 I 幀或P 幀多減去一個 1 的原因。 c) 其它變量參見下面小題; (3)編碼端參數設置 a) img->num_ref_frames_in_pic_order_cnt_cycle: 這個參數在 init_poc( )函數中設置爲 1 後就再沒改動過; b) img->offset_for_ref_frame[0] : 在 StoredBPictures爲0 時等於 2*(input->successive_Bframe+1); c) img->offset_for_ref_frame[1] : 沒什麼用,264 頭文件中不會保存此變量; d) img->delta_pic_order_cnt[0] : 這個變量只對 B 幀有用,等於 2*(img->b_frame_to_code –1); 對於 I 幀或 P 幀, 其值爲 0; e) active_sps->offset_for_non_ref_pic: 只對 B 幀有用,在 StoredBPictures 爲0 時等於–2*input->successive_Bframe,
/////////////////////////////////////////////////////////////////////////
(1) 文件操作參數:#Files
InputFile ="silent.yuv" #輸入序列,YUV 4:2:0 FramesToBeEncoded = 30 #編碼圖象幀數 SourceWidth = 352 #圖象寬度,必須是16像素的倍數 SourceHeight = 288 #圖象高度,必須是16像素的倍數 TraceFile = "silent_enc2.txt" #跟蹤文件 ReconFile = "silent_rec_RD2.yuv" #恢復文件 OutFile = "silent.26l" #輸出文件 (2) 編碼控制參數: #Encoder Control IntraPeriod = 0 #I幀的週期(0=只有第一幀爲I幀) QPFirstFrame = 15 #第一幀量化步長(0-31) QPRemainingFrame = 25 #其它幀量化步長(0-31) FrameSkip = 0 #輸出圖象採樣間隔(如2表示每三幀取一幀) MVResolution = 1 #運動矢量精度:0:1/4像素精度,1:1/8像素精度 UseHamard = 0 #Hadamard變換(0=無效,1=有效) SearchRange = 16 #最大搜索範圍 NumberRefereceFrames = 1 #用於幀間預測的參考幀數(1-5) MbLineIntraUpdate = 0 #錯誤魯棒性0:無效,N:每N幀進行一次幀內編碼GOB InterSearch16x16 = 1 #幀間搜索塊16x16大小(0=無效,1=有效) InterSearch16x8 = 1 #幀間搜索塊16x8大小(0=無效,1=有效) InterSearch8x16 = 1 #幀間搜索塊8x16大小(0=無效,1=有效) InterSearch8x8 = 1 #幀間搜索塊8x8大小(0=無效,1=有效) InterSearch8x4 = 1 #幀間搜索塊8x4大小(0=無效,1=有效) InterSearch4x8 = 1 #幀間搜索塊4x8大小(0=無效,1=有效) InterSearch4x4 = 1 #幀間搜索塊4x4大小(0=無效,1=有效) (3) 定義輸入參數結構體InputParameters typedef struct { int no_frames; //編碼幀數 int qp0; //第一幀量化步長 int qpN; //其餘幀量化步長 int jumpd; //輸出圖象採樣間隔(如2表示每三幀取一幀) int mv_res; //運動矢量精度:0:1/4像素精度1:1/8像素精度 int hadamard; //0:普通1:利用4x4Hadamard變換,計算絕對變換誤差 int search_range; //搜索範圍 - 基於16x16塊整像素搜索,搜索窗是以預測矢量爲中心,對於8x8和4x4塊的搜索範圍是基於16x16塊的1/2 int no_multpred; //1:僅以前一幀做參考,2:以前一幀或大前幀,最多5個參考幀 int img_width; //圖象寬度 int img_height; //圖象高度 int yuv_format; //YUV採樣比(0=4:0:0,1=4:2:0,2=4:2:2,3=4:4:4) int color_depth; //每個像素所需的位數,一般爲8bit/pel int intra_upd; //錯誤魯棒性(0:無效,N:每N幀進行一次幀內編碼GOB) int blc_size[8][2]; //幀間搜索的不同大小塊數組 int slice_mode; //片編碼模式 int UseConstrainedIntraPred; //0:幀間宏塊採用幀內預測 1:無效 int infile_header; //輸出文件的頭信息長度 char infile[100]; //YUV4:2:0輸入文件 char outfile[100]; //H26L壓縮輸出碼流 char ReconFile[100]; //重建圖象文件 char TraceFile[100]; //跟蹤輸出文件 int intra_period; //幀內編碼週期 //B pictures int successive_Bframe; //B幀編碼數目 int pqB; //B幀編碼量化步長 //SP Pictures int sp_periodicity; //SP幀週期 int qpsp; //SP幀預測誤差量化步長 int qpsp_psed; //SP幀預測量化步長 int InterSearch16x16; //搜索塊大小 int InterSearch16x8; int InterSearch8x16; int InterSearch8x8; int InterSearch8x4; int InterSearch4x8; int InterSearch4x4; }InputParameters; |
JM、H.264中一些參數的設置和含義
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
zigzag掃描 簡單介紹
luckylay
2020-02-25 04:53:27
SI 、SP 幀介紹
luckylay
2018-09-04 06:37:13
碼率控制、VBR、CBR
luckylay
2018-09-04 06:37:01
24小時熱門文章
-
再談23種設計模式(3):行爲型模式(學習筆記)
-
Power Automate Desktop 安裝完,登錄後老是提示one driver 錯誤
-
微前端學習筆記(4):從微前端到微模塊之EMP與hel-micro方案探索
-
微前端學習筆記(1):微前端總體架構概述,從微服務發微
-
985 碩士程序員,空窗 4 個月沒有 Offer!
-
一文搞懂 Spring 循環依賴
-
賽博鬥地主——使用大語言模型扮演Agent智能體玩牌類遊戲。
-
VScode右鍵打開(添加到右鍵)
-
記一次 .NET某工控視覺自動化系統 卡死分析
-
WindowsServer--SQL Server搭建主從同步實現讀寫分離 - 事務性分發