| x264編碼詳細文字全過(guò)程2009-03-16 17:40轉載 (1) x264_param_default( x264_param_t *param ) 作用: 對編碼器進(jìn)行參數設定cqm:量化表相關(guān)信息 csp:量化表相關(guān)信息里的memset( param->cqm_4iy, 16, 16 ); memset( param->cqm_4ic, 16, 16 ); memset( param->cqm_4py, 16, 16 ); memset( param->cqm_4pc, 16, 16 ); memset( param->cqm_8iy, 16, 64 ); memset( param->cqm_8py, 16, 64 );
(2)static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) 初始化 1. getopt_long(nargc, nargv, options, long_options, idx) 得到入口地址的向量與方式的選擇 2. getopt_internal(nargc, nargv, options) 解析入口地址向量
(3) static int Encode( x264_param_t *param, cli_opt_t *opt )/* Create a copy of param */ h->param=param/* VUI */vui 信息主要包括幀率、圖像尺寸等信息 /* Init x264_t */ x264_sps_init( h->sps, 0, &h->param ); x264_pps_init( h->pps, 0, &h->param, h->sps);/* Init frames. */ 初始化并開(kāi)辟幀空間/* init mb cache */ 對 前一宏塊的信息保存,因為是初始化,所以作為第一個(gè)宏塊的參考,后面會(huì )有x264_macroblock_cache_load( h, i_mb_x, i_mb_y ); 它是將要編碼的宏塊的周?chē)暮陦K的值讀進(jìn)來(lái), 要想得到當前塊的預測值,要先知道上面,左面的預測值 /* init cabac adaptive model */ /* init CPU functions */ 初始化cpu對各種分塊的參數設定 /* rate control */
1. x264_t *x264_encoder_open ( x264_param_t *param ) 這個(gè)函數是對不正確的參數進(jìn)行修改,并對各結構體參數和cabac編碼,預測等需要的參數進(jìn)行初始化 2、p_read_frame( &pic, opt->hin, i_frame + opt->i_seek, param->i_width, param->i_height ) 讀取一幀,并把這幀設為prev 3. i_file += Encode_frame( h, opt->hout, &pic );
進(jìn)入核碼層核心編碼層的總流程圖:(x264.c) 1. x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out )對幀進(jìn)行編碼 2. i_size = x264_nal_encode( data, &i_data, 1, &nal[i] )網(wǎng)絡(luò )打包編碼 3. i_file += p_write_nalu( hout, data, i_size )把網(wǎng)絡(luò )包寫(xiě)入到輸出文件中去 4. 返回,對下一幀進(jìn)行編碼
下面一頁(yè)是詳細的流程圖: 一.幀內詳細流程圖: 1. x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) 對幀進(jìn)行編碼 1. /* 1: Copy the picture to a frame and move it to a buffer */ x264_frame_t*fenc=x264_frame_get( h->frames.unused ); x264_frame_copy_picture( h, fenc, pic_in ); fenc->i_frame = h->frames.i_input++; x264_frame_put( h->frames.next, fenc ); x264_frame_init_lowres( h->param.cpu, fenc );//里面包含低象素的擴展,很多for循環(huán),應該是抽頭計算和半精度象素的擴展,要認真看
2. 264_slicetype_decide( h ); 對slice類(lèi)型的判定,里面也要看一下
3. while( IS_X264_TYPE_B( h->frames.next[bframes]->i_type ) ) bframes++; x264_frame_put(h->frames.current,x264_frame_get( &h->frames.next[bframes] ) ); 這主要是因為B幀必須等后面的非B幀編碼結束后才能編碼,所以把暫時(shí)不編的一系列B幀存入隊列中,一直到非B幀才取出進(jìn)行編碼,之后再進(jìn)行前面的B幀 編碼do_encode:
4. 建立list0 & list1.我感覺(jué) x264_reference_build_list( h, h->fdec->i_poc, i_slice_type ); 比特率控制初始化x264_ratecontrol_start(h, i_slice_type, h->fenc->i_qpplus1 );
5. 創(chuàng )建slice的頭部數據x264_slice_init( h, i_nal_type, i_slice_type, i_global_qp );
6 i_frame_size = x264_slices_write( h );這是編碼的關(guān)鍵了 1. x264_slice_header_write(&h->out.bs,&h->sh,h->i_nal_ref_idc ); /* Slice header */ 2. 一些初始化工作 3. for(mb_xy=h->sh.i_first_mb, i_skip = 0; mb_xy < h->sh.i_last_mb; mb_xy++ ) 對一個(gè)slice中每個(gè)宏塊進(jìn)行循環(huán)遍歷編碼,其中const int i_mb_y = mb_xy / h->sps->i_mb_width; 和const int i_mb_x = mb_xy % h->sps->i_mb_width; 是對宏塊位置在slice中的x,y坐標的定位,這個(gè)for語(yǔ)句幾乎覆蓋了整個(gè)x264_slices_write()函數 4. x264_macroblock_cache_load( h, i_mb_x, i_mb_y ); 它是將要編碼的宏塊的周?chē)暮陦K的值讀進(jìn)來(lái), 要想得到當前塊的預測值,要先知道上面,左面的預測值! 5. *****x264_macroblock_analyse( h );重點(diǎn)。通過(guò)一系列的SAD算出最優(yōu)化方案,例如把I幀16×16的宏塊分成16個(gè)4×4分別計算SAD和與原16×16SAD比較我感覺(jué),在下面一層再詳細分析。
a. x264_mb_analyse_intra( h, &analysis, COST_MAX ); 我感覺(jué)是在一個(gè)16×16的SAD,4個(gè)8×8的SAD和,16個(gè)4×4SAD和中選出最優(yōu)方式進(jìn)行,可能我的理解不對,里面的 x264_mb_encode_i4x4( h, idx, a->i_qp );i8×8幾個(gè)函數的跟蹤有問(wèn)題,跟得我都找不到,要仔細看(現在又能跟到了)這邊好像如果是直流分量在這里就進(jìn)行量化ZIGZAG掃描了,不用等到x264_macroblock_encode( h )再完成了
b. x264_analyse_update_cache( h, &analysis ); 有對色度塊的模式選擇的計算,好像也有更新信息以為下次的預測作為參考
6. x264_macroblock_encode( h ); a. 判斷宏塊的類(lèi)型 b. 根據判斷的類(lèi)型進(jìn)行DCT,量化,ZIGZAG,并記錄當前的模式為下次編碼宏塊(亞宏塊)做參考ZIGZAG的實(shí)現不明白(原來(lái)ZIGZAG有宏定義,在上面,現在明白了),反量化和IDCT的過(guò)程跟不進(jìn)去,應該是匯編了!函數如下: ( I 4×4 中 x264_mb_encode_i4x4( h, i, i_qp );) x264_mb_dequant_4x4( dct4x4, h->dequant4_mf[CQM_4IY], i_qscale ); h->dctf.add4x4_idct( p_dst, i_stride, dct4x4 ); 還有,這個(gè)函數跟蹤不進(jìn)去,應該是重構圖像的反變換吧 h->dctf.add4x4_idct( p_dst, i_stride, dct4x4 ); h->mb.cache.intra4x4_pred_mode[x264_scan8[i]]=x264_mb_pred_mode4x4_fix(i_mode); 這個(gè)值到底是怎么根據前面的模式改變的,可能是上面兩個(gè)函數沒(méi)能更進(jìn)去所以模糊 c. 對色度塊進(jìn)行編碼,QP限制在0-51之間,選定預測模式(DC的話(huà)值全為128)
x264_mb_encode_8x8_chroma( h, !IS_INTRA( h->mb.i_type ), i_qp );里面對兩個(gè)色度信號分別編碼,與亮度信號類(lèi)似
d. 求亮度和色度的cbp,完全不明白是怎么求的,需要解決!現在有點(diǎn)明白,每個(gè)比特代表子塊是不是全為0,但還沒(méi)有全部明白,色度塊cbp中0x02表示有AC,DC 0x01表示只有DC,
e.利用CBP判斷要不要SKIP.,里面還關(guān)系到向量預測,明天好好看一下 。 其中
h->mb.qp[h->mb.i_mb_xy] = h->mb.i_last_qp;這個(gè)為讀下一個(gè) qp的保存,不然解碼端是讀不出下一個(gè) qp的,
關(guān)于CBP的理解還存在問(wèn)題,他的8位比特各個(gè)代表的意思還不是十分明確,反正是對DC,AC的編碼的選擇。185頁(yè)有介紹(新一代視頻壓縮標準 畢厚杰)
7. 選用CABAC還是CAVLCCABAC的原理實(shí)現沒(méi)仔細看8. x264_macroblock_cache_save( h );保存以為下次的預測作為參考9. 一些收尾工作,為下次宏塊作準備(看的比較粗) http://bbs.rosoo.net/viewthread.php?tid=164 |