JM、H.264中一些参数的设置和含义


一·参数说明 
这一节阐述的是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;

你可能感兴趣的:(X264编码)