?
encode_one_macroblock()函數中的運動估計分為兩大塊,對于宏塊級的三種模式,分塊后直接對patition依次調用PartitionMotionSearch()函數;而對于亞宏塊級的(含8x8, 8x4,4x8,4x4)模式,首先將宏塊拆分為4個8×8子宏塊,針對每個8×8子宏塊調用PartitionMotionSearch()函數。
void
PartitionMotionSearch (int??? blocktype,? //塊模式
?????????????????? int??? block8x8,? //當前partition在宏塊的序號
?????????????????? double lambda)?? // λ
{
static int? bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
static int? by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}}; //參見注釋[1]
int?? **ref_array, ***mv_array; //參考幀列表和運動向量列表
int?? parttype? = (blocktype<4?blocktype:4);
int?? step_h0?? = (input->blc_size[ parttype][0]>>2);
int?? step_v0?? = (input->blc_size[ parttype][1]>>2);
//partition的尺寸,用于決定block的邊界,對非P8×8模式無意義。
int?? step_h??? = (input->blc_size[blocktype][0]>>2); //子塊的尺寸
int?? step_v??? = (input->blc_size[blocktype][1]>>2);
int?? v, h; // BlockMotionSearch()函數要處理的子塊在當前宏塊中的相對塊坐標
//以上尺寸全部以4×4block為單位
numlists=bslice?2:1;
for (list=0; list
{
for (ref=0; ref < listXsize[list+list_offset]; ref++)
{
ref_array = enc_picture->ref_idx[list];
??? mv_array? = enc_picture->mv[list];
?//遍歷partition中的每一個
for (v=by0[parttype][block8x8]; v??????? {
????????? pic_block_y = img->block_y + v;// 當前子塊在圖像中的塊坐標=當前宏塊的塊坐標+當前子塊在宏塊中的相對塊坐標
????????? for (h=bx0[parttype][block8x8]; h????????? {
??????????? pic_block_x = img->block_x + h; // 當前子塊在圖像中的塊坐標=當前宏塊的塊坐標+當前子塊在宏塊中的相對塊坐標
??????????? mcost = BlockMotionSearch (ref, list, h<<2, v<<2, blocktype, search_range, lambda); //對當前子塊作運動向量搜索
??????????? motion_cost[blocktype][list][ref][block8x8] += mcost;? //保存代價值
????????????
????????? for (j=0; j
???????????? for (i=0; i
???????????? {
???????? mv_array [pic_block_x+i][pic_block_y+j][0] = img->all_mv[h][v][list][ref][blocktype][0];
???????? mv_array [pic_block_x+i][pic_block_y+j][1] = img->all_mv[h][v][list][ref][blocktype][1];
//以4×4block為單位保存運動向量
???????? ref_array [pic_block_x+i][pic_block_y+j]??? = ref;
//保存參考幀序號
???????????? }
????????? }
?????? }
??? }
? }
}
[1] static int? bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
??? static int? by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}};
?這里的bx0, by0兩個數組分別對應了SKIP模式,16×16,16×8,8×16,P8×8這四種模式的橫坐標和縱坐標。舉兩個例子
如圖所示的16×16宏塊,首先劃分為4個8×8子塊(因為PartitionMotionSearch()函數處理的最小塊的尺寸為8×8),以4×4block為單位設定坐標,圖上已標出4個8×8子塊左上角的塊坐標。SKIP模式實際上并不牽涉到這個函數,因此坐標全部置零;16×16模式只有第一個坐標起作用,后三個置零;16×8只有前兩個有意義,標出兩個partition的左上角坐標,如圖標出了(0,0),(0,2),對照bx0, by0可以看到相應坐標值;最多子塊情況為4個8×8,即最后一組坐標。
?