Xvid編碼器流程(基于xvid1.1.0)

調用Xvid編碼器流程(基于xvid1.1.0)

編者按:本文為Xvid最新源代碼V1.1.0版本的學習筆記,內

部資料,僅供學習參考,未經授權,不得轉載

xvid有兩種編碼方式:single pass和twopass

single pass模式編碼簡單,速度也快,但最終效果不如twopass。

twopass就是視頻壓制需要經過兩次編碼,分別為twopass-1st pass(簡稱1pass)和twopass-2nd pass(簡稱2pass)

1pass時,編碼器會用最高質量編碼采集可供第2次運算參考的畫面信息,而在2 pass時。編碼器會根據第一次壓縮獲得的信息和用戶指定的文件大小,自動分配比特率,使需要高流量的運動畫面分配到更多的空間,更高的比特率來保證畫面質量。相對的,對于那些不包含太多運動信息的靜態畫面則用較低的比特率。追求畫質的朋友當然會選擇這種方式,但運算比single pass更費時。

接下來介紹一些基本概念:

Q值——量化值,它被用來描述1幀的質量,每幀都有一個Q值,取值范圍在1-31之間。Q值越小,畫質越好,比特率越大

I-frame——關鍵幀,常被縮寫為IF。關鍵幀是構成一個幀組的第一幀。IF保留了一個場景的所有信息

P-frame——未來單項預測幀,縮寫為PF,只儲存與之前一個已解壓畫面的差值

B-frame——雙向預測幀,縮寫為BF,除了參考之前解壓的畫面以外,也會參考后一幀的畫面信息

編碼流程:

各變量的設置:創建xvid_enc_frame_t和xvid_enc_stats_t,分別用于傳入參數和統計編碼結果。

具體過程:

設置傳入圖像數據和圖像色彩空間

設置傳出的碼流

設置vol的標志

設置幀的編碼類型

設置量化因子

設置運動估計算法集合

設置vop的標志

編碼器提供的函數

1,???????????????????????? xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);

含義:根據cpu的特性使用相應匯編優化的函數

2, xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);

含義:初始化編碼器。

具體過程:

創建編碼器句柄,并根據傳入的參數設置各變量的值,并且分配要使用的內存,用于存放重建幀,參考幀(1/2像素精度)。以及各種臨時變量。并且做好碼率控制的初始化。

3, xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame, &xvid_enc_stats);

目的:編碼一幀

具體過程:

{

初始化寫碼流。

如果有必要,轉換色彩空間,并且把原始圖像拷貝到有邊框的圖像空間,但是沒有擴展邊框。

將重建幀交換成參考幀

從幀隊列中獲取當前幀

設置Encoder結構體的current結構體的vol_flags,vop_flags,motion_flags,fcode,bcode和quant字段。

調用call_plugins,在里面調用rc_single_before做碼率控制的初始化,以及對current結構體的其他變量進一步設置通過幀號或者MEanalysis函數分析來確定編碼類型,并且根據用戶的設置作修正。

MEanalysis的原理是,如果某個宏塊的殘差的sad大于該宏塊的平均值的偏離,那么使用intra方式,否則使用inter方式,然后對這些宏塊進行統計,得到整幀的編碼方式。

如果編碼類型是I_VOP

{

設置Encoder->mbParam->vol_flags

設置Encoder->mbParam.par

根據vol_flags設置vop_flags

調用FrameCodeI以I幀的方式編碼

調用call_plugins,在里面調用rc_single_after,進行碼率控制。

}

如果編碼類型是P_VOP

{

用mbParam.vol_flags固定pEnc->current->vol_flags

調用FrameCodeP以P幀的方式編碼

調用call_plugins,在里面調用rc_single_after,進行碼率控制。

}

}// xvid_encore

編者按:本文為Xvid最新源代碼V1.1.0版本的學習筆記,內部資料,僅供學習參考,未經授權,不得轉載

xvid有兩種編碼方式:single pass和twopass

single pass模式編碼簡單,速度也快,但最終效果不如twopass。

twopass就是視頻壓制需要經過兩次編碼,分別為twopass-1st pass(簡稱1pass)和twopass-2nd pass(簡稱2pass)

1pass時,編碼器會用最高質量編碼采集可供第2次運算參考的畫面信息,而在2 pass時。編碼器會根據第一次壓縮獲得的信息和用戶指定的文件大小,自動分配比特率,使需要高流量的運動畫面分配到更多的空間,更高的比特率來保證畫面質量。相對的,對于那些不包含太多運動信息的靜態畫面則用較低的比特率。追求畫質的朋友當然會選擇這種方式,但運算比single pass更費時。

接下來介紹一些基本概念:

Q值——量化值,它被用來描述1幀的質量,每幀都有一個Q值,取值范圍在1-31之間。Q值越小,畫質越好,比特率越大

I-frame——關鍵幀,常被縮寫為IF。關鍵幀是構成一個幀組的第一幀。IF保留了一個場景的所有信息

P-frame——未來單項預測幀,縮寫為PF,只儲存與之前一個已解壓畫面的差值

B-frame——雙向預測幀,縮寫為BF,除了參考之前解壓的畫面以外,也會參考后一幀的畫面信息

編碼流程:

各變量的設置:創建xvid_enc_frame_t和xvid_enc_stats_t,分別用于傳入參數和統計編碼結果。

具體過程:

設置傳入圖像數據和圖像色彩空間

設置傳出的碼流

設置vol的標志

設置幀的編碼類型

設置量化因子

設置運動估計算法集合

設置vop的標志

編碼器提供的函數

1, xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);

含義:根據cpu的特性使用相應匯編優化的函數

2, xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);

含義:初始化編碼器。

具體過程:

創建編碼器句柄,并根據傳入的參數設置各變量的值,并且分配要使用的內存,用于存放重建幀,參考幀(1/2像素精度)。以及各種臨時變量。并且做好碼率控制的初始化。

3, xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame, &xvid_enc_stats);

目的:編碼一幀

具體過程:

{

初始化寫碼流。

如果有必要,轉換色彩空間,并且把原始圖像拷貝到有邊框的圖像空間,但是沒有擴展邊框。

將重建幀交換成參考幀

從幀隊列中獲取當前幀

設置Encoder結構體的current結構體的vol_flags,vop_flags,motion_flags,fcode,bcode和quant字段。

調用call_plugins,在里面調用rc_single_before做碼率控制的初始化,以及對current結構體的其他變量進一步設置

通過幀號或者MEanalysis函數分析來確定編碼類型,并且根據用戶的設置作修正。

MEanalysis的原理是,如果某個宏塊的殘差的sad大于該宏塊的平均值的偏離,那么使用intra方式,否則使用inter方式,然后對這些宏塊進行統計,得到整幀的編碼方式。

如果編碼類型是I_VOP

{

設置Encoder->mbParam->vol_flags

設置Encoder->mbParam.par

根據vol_flags設置vop_flags

調用FrameCodeI以I幀的方式編碼

調用call_plugins,在里面調用rc_single_after,進行碼率控制。

}

如果編碼類型是P_VOP

{

用mbParam.vol_flags固定住pEnc->current->vol_flags

調用FrameCodeP以P幀的方式編碼

調用call_plugins,在里面調用rc_single_after,進行碼率控制。

}

}// xvid_encore

4, static int FrameCodeI(Encoder * pEnc, Bitstream * bs)

目的:將一幀圖像編碼成一個I幀

具體過程:

以XVID_PLG_FRAME參數調用call_plugins,該函數目前的作用是設置dquant,可以在該函數中設置最好質量。 調用SetMacroblockQuants,為每個宏塊設置量化因子,所以也可以在這里設置最好質量

調用BitstreamWriteVolHeader,寫vol

調用set_timecodes,設置時間編碼。

調用BitstreamPad,填充bit至字節對齊

調用BitstreamWriteVopHeader,填寫vop頭

依次讀取每一個宏塊,進行編碼

{

調用CodeIntraMB設置編碼模式為intra,將所有和運動有關的變量設為0

調用MBTransQuantIntra進行變換編碼

{

調用MBTrans8to16將像素的表示方法從8bit擴大到16bit

調用MBfDCT對像素進行變換編碼

調用MBQuantIntra對dct系數進行intra方式的量化

調用MBDeQuantIntra對dct系數進行intra方式的反量化

調用MBiDCT將恢復的dct系數進行反變換

調用MBTrans16to8將恢復的16bit像素飽和到8bit,組成重建宏塊

}//MBTransQuantIntra

調用MBPrediction作acdc預測

{

調用get_dc_scaler函數得到量化系數

調用predict_acdc得到預測方向以及在該預測方向上的和當前塊的同一量化水平的預測值

調用calc_acdc_bits以確定是只使用DC預測,還是DCAC預測。原理是分別作DC預測和DCAC預測,分別計算在這2種情況下需要的碼流長度,以確定哪種方式更節約碼流。

調用CodeCoeffIntra_CalcBits,用于確定各種方式下的碼流長度

根據預測模式的不同,恢復成相應的系數

最后計算該宏塊的cbp

}//MBPrediction

調用MBCoding將宏塊編制成碼流

{

調用CodeBlockIntra將intra宏塊編制成碼流

{

編碼mcbpc

編碼ac預測標記

編碼cbpy

對于6個塊里的每個塊

首先編碼DC系數

調用CodeCoeffIntra對剩下的63個系數進行編碼

}//CodeBlockIntra

}//MBCoding

}//依次讀取每一個宏塊,進行編碼 填充bit,直到字節對齊

5, static int FrameCodeP(Encoder * pEnc, Bitstream * bs)

含義:將一幀圖片編碼成P幀具體過程:

{

如果參考幀還沒有設置邊框,那么就調用image_setedges設置邊框

如果需要半像素運動估計,那么就調用image_interpolate進行插值

將一幀填充邊框后的參考幀,分成8*8的小塊,對于每個小塊進行插值,如下:

調用interpolate8x8_halfpel_h進行水平插值

調用interpolate8x8_halfpel_v進行垂直插值

調用interpolate8x8_halfpel_hv進行對角線插值

用參數XVID_PLG_FRAME調用call_plugins,該函數目前的作用是設置dquant,可以在該函數中設置最好質量。

調用SetMacroblockQuants,為每個宏塊設置量化因子,所以也可以在這里設置最好質量

調用MotionEstimation做運動估計

{

使用MotionFlags變量保存要使用的運動算法集合

使用skip_thresh保存要達到skip模式的閥值

使用Data保存運動估計要用到的相應變量

對于每個宏塊,依次執行如下操作

{

調用sad16v計算本宏塊與參考幀對應位置宏塊的亮度的殘差,將其保存在pMB->sad16中,并按照4個塊的方式分別存放pMB->sad8[0-3]中 用sad00記錄最大亮度塊殘差的4倍

如果還需要考慮色差塊的因素

調用sad8兩次,分別計算u分量和v分量的殘差,都加入pMB->sad16中,并且也加入sad00中

如果該宏塊的量化差值為0,并且sad00又沒有超過skip模式的閥值

如果已經考慮了色差因素,或者使用xvid_me_SkipDecisionP確認符合skip模式。

調用ZeroMacroblockP將其編碼為skip模式,并置標記pMB->mode = MODE_NOT_CODED

根據采用的運動估計算法不同,做相應的設置

調用SearchP做該宏塊的運動估計

{

確定是否使用inter4v模式,并記錄之

調用get_range確定運動搜索的范圍,并記錄在Data中

調用get_pmvdata2,以獲得左,上,右上的運動向量,以及它們對應的sad,存入pmv[1-3]和Data->temp[1-3]。然后計算它們的中值,并且存放于pmv[0],并且把最小的sad存放于Data->temp[0]

設置Data的當前宏塊的yuv字段。設置Data->RefP[0-5]為參考幀的同一宏塊的整像素y,水平半象素y,垂直半象素y,對角線y,u,v。

設置Data->lambda16和Data->lambda8,其含義可能是運動向量對帶寬的占用折合到sad的值

設置qpel和方向

如果采用qpel,調用get_qpmv2計算用qple方式下的估計中值,存入ata->predMV;否則,Data->predMV為0。

調用d_mv_bits計算mv需要的編碼bit,用于修正pMB->sad16和pMB->sad8[0],并將Data->iMinSAD[0-4]設置為pMB->sad16和pMB->sad8[0-3],也就是0向量對應的各SAD。

如果不采用率失真決策模型,并且不是當前幀的第一宏塊,那么使用一種方法設置閥值threshA,否則閥值threshA為512。

調用PreparePredictionsP,對pmv作進一步的設置,做運算前的準備。

{

設置pmv[0]為0向量

設置pmv[1]為中值向量的偶數值

設置pmv[2]為參考幀相同位置宏塊的第0塊運動向量的偶數值

如果該宏塊有左邊宏塊,設置pmv[3]為左邊宏塊的第1塊的運動向量的偶數值,否則為0

如果該宏塊有上面宏塊,設置pmv[4]為上面宏塊的第2塊的運動向量的偶數值,否則為0

如果該宏塊有右上宏塊,設置pmv[5]為右上宏塊的第2塊的運動向量的偶數值,否則為0

如果該宏塊有右下宏塊,設置pmv[6]為參考幀的相同宏塊的右下宏塊的第0塊的運動向量的偶數值,否則為0。

}//PreparePredictionsP

如果使用inter4v,設置CheckCandidate為CheckCandidate16,否則設置為CheckCandidate16no4v

逐一檢查mpv[1-6]這六個最可能運動向量,如果發現他們與以前的運動不同,就調用CheckCandidate做運動估計,過程如下:

{

檢查要做運動估計的運動向量是否越界

通過該運動向量獲得所指向數據塊的指針

調用sad16v,記錄下4個8*8塊的SAD值,存入data->temp[0-3]中,并將他們的和存入臨時變量sad中。 對sad和data->temp[0]做基于運動向量的修正。

如果要考慮色差因素,調用xvid_me_ChromaSAD計算額外的SAD,累加至sad中。

如果sad小于data->iMinSAD[0],那么設置data->iMinSAD[0],data->currentMV[0],和data->dir。注意,此時的data->dir記錄的不是鉆石搜索的方向,而是當前向量是pmv數組的第幾個元素。

逐一檢查data->temp[0-3],如果他們小于data->iMinSAD[1-4],那么修改data->iMinSAD[1-4]和data->currentMV[1-4]

}//CheckCandidate

如果當前最優運動向量,即Data->iMinSAD[0],小于threshA?或者當前最優運動向量等于參考幀相同位置宏塊的運動向量,并且對應的SAD值又比他的小?

就不再做inter4v的搜索

否則,就做inter4v的搜索

{

使用make_mask逐一檢查存放于pmv的所有運動向量,察看是否位于欲搜索的鉆石形的頂點。如果是,則在mask變量中標記之。

根據MotionFlags確定使用的搜索函數,根據當前設置,MainSearchPtr = xvid_me_AdvDiamondSearch

調用xvid_me_AdvDiamondSearch進行搜索,過程如下:

{

bDirection既表明了上次嘗試的方向,又表明本次可以嘗試的方向

x,y為鉆石搜索的位置的中心點坐標

for(;;)

{

如果可以嘗試左邊,那么調用CheckCandidate嘗試左邊

如果可以嘗試右邊,那么調用CheckCandidate嘗試右邊

如果可以嘗試上邊,那么調用CheckCandidate嘗試上邊

如果可以嘗試下邊,那么調用CheckCandidate嘗試下邊

如果有更好的方向

{

bDirection = 更好的方向

如果更好的方向是左右方向,那么測試該位置的上下方向

否則,那么測試該位置的左右方向

如果這次又找到了更好的方向

將更好的方向累加到bDirection

將更好的位置存入x,y

}

否則

{

根據去搜索臨近未搜索的點,具體規則如下:

如果bDirection = = 2,表明搜索方向是趨向右邊的,那么搜索當前中心點的右上點和右下點。

如果bDirection = = 1,表明搜索方向是趨向左邊的,那么搜索當前中心點的左上點和左下點。

如果bDirection = = 2+4,表明搜索方向是趨向右上的,那么再搜索當前中心點的左上點,右上點和右下點。

如果bDirection = = 4,表明搜索方向是趨向上邊的,那么搜索當前中心點的左上點和右上點。

如果bDirection = = 8,表明搜索方向是趨向下邊的,那么搜索當前中心點的左下點和右下點。

如果bDirection = = 1+4,表明搜索方向是趨向左上的,那么再搜索當前中心點的左下點,左上點和右上點。

如果bDirection = = 2+8,表明搜索方向是趨向右下的,那么再搜索當前中心點的左下點,左上點和右上點。

如果bDirection = = 1+8,表明搜索方向是趨向左下的,那么再搜索當前中心點的左上點,左下點和右下點。

否則的話,則認為本輪搜索沒有找到更好的點,那么再搜索當前中心點的左上點,左下點,右上點,右下點。

}

如果沒有找到更好的方向,從函數中返回

更新bDirection為更好的方向

更新x,y為更好的位置

}//for(;;)

}//xvid_me_AdvDiamondSearch

如果運動估計算法使用了XVID_ME_EXTSEARCH16,那么

{

設置startMV = Data->predMV

設置backupMV為當前最佳運動向量

如果startMV和backupMV不相等

{

調用CheckCandidate計算位置為startMV的SAD

調用xvid_me_DiamondSearch做以startMV為起點的搜索,過程如下:

{

for(;;)

{

如果可以嘗試左邊,那么調用CheckCandidate嘗試左邊

如果可以嘗試右邊,那么調用CheckCandidate嘗試右邊

如果可以嘗試上邊,那么調用CheckCandidate嘗試上邊

如果可以嘗試下邊,那么調用CheckCandidate嘗試下邊

如果沒有更好的方向,退出

bDirection = 更好的方向

x,y = 更好的位置

如果更好的方向是左右方向,那么測試該位置的上下方向

否則,那么測試該位置的左右方向

如果這次又找到了更好的方向

{

bDirection += 更好的方向

x,y = 更好的位置

}

}

}//xvid_me_DiamondSearch

將這次搜索結果和上次搜索結果比較,記錄最佳的SAD和位置。

}//如果startMV和backupMV不相等

設置startMV = {1,1}

設置backupMV為當前最佳運動向量

如果startMV和backupMV不相等

{

調用CheckCandidate計算位置為startMV的SAD

調用xvid_me_DiamondSearch做以startMV為起點的搜索,過程如下:

將這次搜索結果和上次搜索結果比較,記錄最佳的SAD和位置。

}

}//如果運動估計算法使用了XVID_ME_EXTSEARCH16

}//否則,就做inter4v的搜索

如果沒有采用1/4像素運動估計算法

{

如果采用了XVID_ME_HALFPELREFINE16算法

調用xvid_me_SubpelRefine

按順時針方向8次調用CheckCandidate16,得到最好的1/2像素位置

}

否則

如果當前SAD足夠小,那么inter4v = 0

如果采用inter4v

{

4次調用Search8來搜索4個8*8塊的最佳運動向量,每一次搜索的規則如下:

{

如果采用1/4像素運動估計,略。否則

調用get_pmv2取得本塊的中值

計算第一塊以外快的d_mv_bits

用Data->lambda8修正該塊當前的SAD,但是第0塊是不用修正的。

如果使用了XVID_ME_EXTSEARCH8 | XVID_ME_HALFPELREFINE8 | XVID_ME_QUARTERPELREFINE8,那么

{

Data->RefP[0-3] = 參考幀的整像素,水平半象素,垂直半象素,對角線半象素的對應宏塊的對應塊的起始地址。

Data->Cur = 當前幀的當前宏塊的當前塊的起始地址

利用get_range得到運動搜索的范圍

根據MotionFlags的指示,設定運動估計MainSearchPtr的算法,當前設置為MainSearchPtr = xvid_me_AdvDiamondSearch。

調用xvid_me_AdvDiamondSearch做運動估計,其中做SAD的函數是CheckCandidate8,該函數類似于CheckCandidate16

如果不采用1/4像素運動估計,并且又采用了XVID_ME_HALFPELREFINE8,那么調用xvid_me_SubpelRefine

按順時針方向8次調用CheckCandidate8,得到最好的1/2像素位置

如果采用了1/4像素運動估計,略

}// XVID_ME_EXTSEARCH8 | XVID_ME_HALFPELREFINE8 | XVID_ME_QUARTERPELREFINE8

如果采用1/4運動估計

否則

記錄pMB->pmvs[block] = 當前找到的最佳位置與預測位置的差值

將這次的搜索存入相應OldData的字段,以及pMB的相應字段

}// Search8

如果考慮色差的因素,并且又不考慮率失真算法 =

{

根據是否采用1/4像素運動估計算出色差的運動向量

計算u,v的SAD,將其作為Data->iMinSAD[1]的修正

}

} //如果采用inter4v

否則,Data->iMinSAD[1]為足夠大的值

}//SearchP

調用ModeDecision_SAD確定該宏塊的類型

判斷該宏塊要采取的編碼方式,MODE_INTER,MODE_INTER4V,MODE_NOT_CODED,MODE_INTRA

調用motionStatsPVOP做一些統計工作

具體過程略

}//對于每個宏塊,依次執行如下操作

做一些最后的設置

}//MotionEstimation

調用set_timecodes設置時間戳

調用BitstreamWriteVopHeader寫VOP頭

具體過程略

對于每一個宏塊,依次執行如下操作

{

如果該宏塊的編碼模式是MODE_INTRA或者MODE_INTRA_Q

{

調用CodeIntraMB設置編碼模式為intra,將所有和運動有關的變量設為0

調用MBTransQuantIntra進行變換編碼

調用MBCoding將該宏塊編制成碼流

Continue

}

調用MBMotionCompensation做運動補償

{

如果編碼模式是MODE_NOT_CODED

用參考幀的相應宏塊替代當前幀的當前宏塊

Return

如果編碼模式是MODE_NOT_CODED或者MODE_INTER或者MODE_INTER_Q

{

如果mb->mcsel不為0

做GMC的處理

Return

計算運動向量dx,dy

調用compensate16x16_interpolate進行運動補償

{

如果采用1/4像素運動估計

否則,調用get_ref計算用于運動補償的參考宏塊的指針

調用4次transfer_8to16sub做亮度塊的運動補償,使得臨時數組里存放的是殘差,而原始圖像里存放的是參考快的數據。

}//compensate16x16_interpolate

計算出用于色差運動補償的dx,dy

}//MODE_NOT_CODED或者MODE_INTER或者MODE_INTER_Q

否則,那就是MODE_INTER4V

{

根據是否使用1/4像素運動估計,計算出4個色度塊的運動向量

以這4個運動向量為參數,調用4次compensate8x8_interpolate ,該操作類似于compensate16x16_interpolate,不同在于一次只計算一個塊。

計算出用于色差運動補償的dx,dy

}

調用CompensateChroma計算色差塊的運動補償

{

調用interpolate8x8_switch2計算出u的插值

調用interpolate8x8_halfpel_v或者interpolate8x8_halfpel_h或者interpolate8x8_halfpel_hv做實際的插值操作,或者直接返回

調用transfer_8to16sub_c做u份量的運動補償

調用interpolate8x8_switch2計算出v的插值

調用interpolate8x8_halfpel_v或者interpolate8x8_halfpel_h或者interpolate8x8_halfpel_hv做實際的插值操作,或者直接返回

調用transfer_8to16sub_c做v份量的運動補償

}//CompensateChroma

}//MBMotionCompensation

如果需要編碼,那么用MBTransQuantInter進行編碼,并把結果返回給pMB->cbp

{

調用MBfDCT進行宏塊變換編碼

調用6次fdct

調用MBQuantInter進行量化

{

對于宏塊里的每一塊

{

調用quant_h263_inter進行量化

如果在量化后,前三個系數為0,并且系數的絕對值之和小于閥值,那么標記該塊為全0塊,將標記存入cbp。否則,標記為非全0塊,也將標記存入cbp

}

}//MBQuantInter

調用MBDeQuantInter反量化

{

確定要使用的反量化函數

對于六個塊里的每個塊,如果cbp表示許可,都調用dequant_h263_inter反量化

}//MBDeQuantInter

調用MBiDCT做反離散余弦變換

對于六個塊里的每個塊,如果cbp表示許可,都調用idct_int32反量化

調用MBTrans16to8將恢復出的殘差構成重建圖像

{

確定具體執行的函數,分為transfer_16to8copy和transfer_16to8add

找到該宏塊的y,u,v分量起始地址

對于六個塊里的每個塊,如果cbp表示許可,調用相應得函數執行重建。

}// MBTrans16to8

}//MBTransQuantInter

如果無殘差,并且編碼方式為MODE_INTER,并且幀方式是P幀,并且向量2分量都為0,那么可以考慮skip模式

如果可以考慮skip模式,則做進一步檢驗,如果檢驗通過,那么

{

編碼模式為MODE_NOT_CODED,并且在碼流里做標記

Continue

}

調用MBCoding將這個宏塊寫入碼流

{

寫入非NOT_CODED標記

調用CodeBlockInter寫入碼流

{

編碼mcbpc

編碼cbpy

調用CodeVector編碼運動向量

對六個塊,如果cbp只是需要編碼,調用CodeCoeffInter進行編碼

}//CodeBlockInter

}// MBCoding

}//對于每一個宏塊,依次執行如下操作

更新fcode

為下一幀的編碼做簡單的更新設置

統計該幀編碼長度

}// FrameCodeP


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254626.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254626.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254626.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

置換矩陣

來源:百度百科 定義: 設P 是一個 mn 的 (0,1) 矩陣,如 m≤n且 PxPtE,則稱 P為一個 mn的置換矩陣。其中Pt是P的轉置矩陣,E是m階單位方陣。 判定條件: 定理 1 當 m≦n時,一個 mn 的(0,1) 矩陣P為置…

halcon Matching-3D 3D匹配,持續更新

目錄Matching-3D 3D匹配Deformable Surface-Based基于可變形表面1. add_deformable_surface_model_reference_point2.add_deformable_surface_model_sample3. clear_deformable_surface_matching_result4.clear_deformable_surface_model5. create_deformable_surface_model6. …

CVE-2009-3459

Adobe Acrobat和Reader都是美國Adobe公司開發的非常流行的PDF文件閱讀器。 Adobe Reader和Acrobat 7.1.4之前的7.x版本,8.1.7之前的8.x版本以及9.2之前的9.x版本中存在基于堆的緩沖區溢出漏洞。遠程攻擊者可借助觸發內存破壞的特制PDF文件執行任意代碼。 轉…

leetcode-665-Non-decreasing Array

題目描述&#xff1a; Given an array with n integers, your task is to check if it could become non-decreasing by modifying at most 1 element. We define an array is non-decreasing if array[i] < array[i 1] holds for every i (1 < i < n). Example 1: I…

halcon 3D Object Model 三維物體模型算子,持續更新

目錄3D Object Model 三維物體模型Creation創建1.clear_object_model_3d2.copy_object_model_3d3. deserialize_object_model_3d4. gen_box_object_model_3d5. gen_cylinder_object_model_3d6. gen_empty_object_model_3d7. gen_object_model_3d_from_points8. gen_plane_objec…

linux下kafka與zookeeper集群部署

*********************************配置主機名&#xff0c;通過主機名連接機器********************************* 比如說&#xff0c;已經有了三臺主機 1&#xff0c;在linux上設置hostname&#xff0c;通過hostname來訪問linux虛擬機 1.1. 修改hosts文件 vim /etc/hosts#/etc…

調用Xvid編碼器流程(基于xvid1.1.0)

xvid有兩種編碼方式&#xff1a;single pass和twopass single pass模式編碼簡單&#xff0c;速度也快&#xff0c;但最終效果不如twopass。 twopass就是視頻壓制需要經過兩次編碼&#xff0c;分別為twopass&#xff0d;1st pass&#xff08;簡稱1pass&#xff09;和twopass…

關于box-shadow屬性的一點心得

一般我用到box-shadow都是用于諸如按鈕&#xff0c;文本塊&#xff0c;某些圖標&#xff0c;css類似為: box-shadow: 1px 1px 5px rgba(0, 0, 0, .8);這樣&#xff0c;樣式看上去會更加柔和&#xff0c;或者增加了立體感。 我個人的理解上&#xff0c;box-shadow的本質就是本體…

Laravel核心解讀--控制器

控制器 控制器能夠將相關的請求處理邏輯組成一個單獨的類&#xff0c; 通過前面的路由和中間件兩個章節我們多次強調Laravel應用的請求在進入應用后首現會通過Http Kernel里定義的基本中間件 protected $middleware [\Illuminate\Foundation\Http\Middleware\CheckForMaintena…

C#枚舉、值、字符串的相互轉換

目錄枚舉的定義使用方式優點代碼示例枚舉的定義 枚舉是整數類型&#xff0c;用戶自定義的整數類型的一個集合。 使用方式 public enum A {a0,b1,c2 }注意&#xff1a;枚舉定義的不同變量之間要用“&#xff0c;”分割&#xff0c;結尾不需要加上“&#xff0c;” 優點 可以…

制作404頁面的重要性

在網站的運行過程中會面臨很多問題&#xff0c;當用戶搜索頁面時&#xff0c;會提示服務器出錯&#xff0c;請求的頁面不存在&#xff0c;程序配置錯誤等問題。用戶請求瀏覽網頁碰到這些的情況時&#xff0c;會自動跳出系統默認的錯誤提示&#xff0c;對用戶體驗造成不好的感觸…

明晰C++內存分配的五種方法的區別

在C中&#xff0c;內存分成5個區&#xff0c;他們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區。 棧&#xff0c;就是那些由編譯器在需要的時候分配&#xff0c;在不需要的時候自動清楚的變量的存儲區。里面的變量通常是局部變量、函數參數等。 堆&#xff0c;就是那…

【BZOJ-4631】踩氣球 線段樹 + STL

4631: 踩氣球 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 224 Solved: 114[Submit][Status][Discuss]Description 六一兒童節到了&#xff0c; SHUXK 被迫陪著M個熊孩子玩一個無聊的游戲&#xff1a;有N個盒子從左到右排成一排&#xff0c;第i個盒子里裝著Ai個氣球。SH…

3D Reconstruction三維重建halcon算子,持續更新

目錄3D Reconstruction三維重建Binocular Stereo雙目立體binocular_disparitybinocular_disparity_mgbinocular_disparity_msbinocular_distancebinocular_distance_mgbinocular_distance_msdisparity_image_to_xyzdisparity_to_distancedisparity_to_point_3ddistance_to_disp…

遺傳算法初級

遺傳算法是一種基于仿生學的計算機算法&#xff0c;通過模擬自然進化和優勝劣汰法則來搜索問題的最優解(我會說這其實就是稍微改良了一下的暴搜&#xff1f;) 它是由美國的J.Holland于1975年提出來的玄學概率學混合暴力搜索方法&#xff0c;廣泛適用于尋找算法優解、機器學習、…

C++ vector容器類型

vector類為內置數組提供了一種替代表示&#xff0c;與string類一樣 vector 類是隨標準 C引入的標準庫的一部分 &#xff0c;為了使用vector 我們必須包含相關的頭文件 &#xff1a;#include <vector> 使用vector有兩種不同的形式&#xff0c;即所謂的數組習慣和 STL習慣…

redis在linux命令行下連續進行命令操作

redis-cli -a password -n 9 keys "friend*" -a 是auth -n 是選擇數據池 keys就是找key啦、 要是后面再跟上 xargs */redis-cli del redis-cli -a password -n 9 keys "friend*" | xargs redis-cli -a password -n 9 del 就完美了23333 轉載于:https://www…

Calibration校準halcon算子,持續更新

目錄Calibration校準Binocular雙目相機binocular_calibrationCalibration Object 校準物體caltab_pointscreate_caltabdisp_caltabfind_calib_objectfind_caltabfind_marks_and_posegen_caltabsim_caltabCamera parameter相機參數cam_mat_to_cam_parcam_par_to_cam_matdeserial…

javascript:正則表達式、一個表單驗證的例子

閱讀目錄 本文內容&#xff1a;正則表達式&#xff1a;利用正則表達式進行表單驗證的例子&#xff1a;回到頂部本文內容&#xff1a; 正則表達式正則表達式的使用方法正則表達式的特殊匹配字符正則表達式修飾符利用正則表達式進行表單驗證的例子首發日期&#xff1a;2018-05-13…

Spring_01 spring容器、控制反轉(IOC)、依賴注入(DI)

目錄 1 什么是spring框架 2 spring框架的特點 3 spring容器 3.1 什么是spring容器 3.2 spring容器創建對象的編程步驟 3.4 spring容器創建對象的方式 3.5 bean元素的幾個重要屬性 4 IOC 4.1 什么是IOC 4.2 什么事DI 4.3 DI的三種方式 1 什么是spring框架 是一個開源的用來簡化企…