From 8e776366dc0c4dda9201717832cfb081fa066129 Mon Sep 17 00:00:00 2001 From: Marko Viitanen Date: Mon, 16 Sep 2013 16:37:24 +0300 Subject: [PATCH] Added (basic) motion vector prediction --- src/encoder.c | 22 +++++++++---- src/inter.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/inter.h | 5 ++- src/search.c | 2 +- 4 files changed, 110 insertions(+), 8 deletions(-) diff --git a/src/encoder.c b/src/encoder.c index 13226272..3f8cb64b 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -969,6 +969,10 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui else { uint32_t uiRefListIdx; + + int16_t mv_cand[2][2]; + + /* // Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx ) if(encoder->in.cur_pic->slicetype == SLICE_B) @@ -989,6 +993,7 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui */ + for(uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++) { //if(encoder->ref_idx_num[uiRefListIdx] > 0) @@ -1029,18 +1034,19 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui } } + /* Get MV candidates */ + inter_get_mv_cand(encoder, xCtb, yCtb, depth, mv_cand); + cur_CU->inter.mv_ref = 0; if (!(/*pcCU->getSlice()->getMvdL1ZeroFlag() &&*/ encoder->ref_list == REF_PIC_LIST_1 && cur_CU->inter.mv_dir==3)) { - /*const TComCUMvField* pcCUMvField = pcCU->getCUMvField( eRefList );*/ - //TODO: calculate MV field difference - const int32_t mvd_hor = cur_CU->inter.mv[0];//pcCUMvField->getMvd( uiAbsPartIdx ).getHor(); - const int32_t mvd_ver = cur_CU->inter.mv[1];//pcCUMvField->getMvd( uiAbsPartIdx ).getVer(); + const int32_t mvd_hor = cur_CU->inter.mv[0]-mv_cand[cur_CU->inter.mv_ref][0]; + const int32_t mvd_ver = cur_CU->inter.mv[1]-mv_cand[cur_CU->inter.mv_ref][1]; const int8_t bHorAbsGr0 = mvd_hor != 0; const int8_t bVerAbsGr0 = mvd_ver != 0; const uint32_t mvd_hor_abs = abs(mvd_hor); const uint32_t mvd_ver_abs = abs(mvd_ver); - + cabac.ctx = &g_cCUMvdSCModel[0]; CABAC_BIN(&cabac, (mvd_hor!=0)?1:0, "abs_mvd_greater0_flag_hor"); CABAC_BIN(&cabac, (mvd_ver!=0)?1:0, "abs_mvd_greater0_flag_ver"); @@ -1077,10 +1083,14 @@ void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, ui /* Inter reconstruction */ inter_recon(encoder->ref->pics[0],xCtb*CU_MIN_SIZE_PIXELS,yCtb*CU_MIN_SIZE_PIXELS,LCU_WIDTH>>depth,cur_CU->inter.mv,encoder->in.cur_pic); + + /* Mark this block as "coded" (can be used for predictions..) */ + picture_setBlockCoded(encoder->in.cur_pic,xCtb, yCtb, depth, 1); } { - int32_t iSymbol = cur_CU->inter.mv_ref;//pcCU->getMVPIdx(eRefList, uiAbsPartIdx); + /* Signal which candidate MV to use */ + int32_t iSymbol = cur_CU->inter.mv_ref; int32_t iNum = AMVP_MAX_NUM_CANDS; cabac_writeUnaryMaxSymbol(&cabac,g_cMVPIdxSCModel, iSymbol,1,iNum-1); } diff --git a/src/inter.c b/src/inter.c index 12a3c5ea..fb5ca546 100644 --- a/src/inter.c +++ b/src/inter.c @@ -163,4 +163,93 @@ void inter_recon(picture* ref,int32_t xpos, int32_t ypos,int32_t width, int16_t } } +} + +/*! + \brief Get MV prediction for current block + \param encoder encoder control struct to use + \param xCtb block x position in SCU + \param yCtb block y position in SCU + \param depth current block depth + \param mv_pred[2][2] 2x motion vector prediction + \returns Void +*/ +void inter_get_mv_cand(encoder_control *encoder,int32_t xCtb, int32_t yCtb,int8_t depth, int16_t mv_cand[2][2]) +{ + uint8_t cur_block_in_scu = (LCU_WIDTH>>depth) / CU_MIN_SIZE_PIXELS; + CU_info *cur_cu = &encoder->in.cur_pic->CU[depth][xCtb+yCtb*(encoder->in.width_in_LCU<in.cur_pic->CU[depth][xCtb-1+(yCtb+cur_block_in_scu-1)*(encoder->in.width_in_LCU<coded) a1 = NULL; + + if (yCtb+cur_block_in_scu < encoder->in.height_in_LCU<in.cur_pic->CU[depth][xCtb-1+(yCtb+cur_block_in_scu)*(encoder->in.width_in_LCU<coded) a0 = NULL; + } + } + + if (yCtb != 0) { + b0 = &encoder->in.cur_pic->CU[depth][xCtb+cur_block_in_scu+(yCtb-1)*(encoder->in.width_in_LCU<coded) b0 = NULL; + b1 = &encoder->in.cur_pic->CU[depth][xCtb+cur_block_in_scu-1+(yCtb-1)*(encoder->in.width_in_LCU<coded) b1 = NULL; + + if (xCtb != 0) { + b2 = &encoder->in.cur_pic->CU[depth][xCtb-1+(yCtb-1)*(encoder->in.width_in_LCU<coded) b2 = NULL; + } + } + + /* Left predictors */ + if (a0 && a0->type == CU_INTER) { + mv_cand[candidates][0] = a0->inter.mv[0]; + mv_cand[candidates][1] = a0->inter.mv[1]; + candidates++; + } else if (a1 && a1->type == CU_INTER) { + mv_cand[candidates][0] = a1->inter.mv[0]; + mv_cand[candidates][1] = a1->inter.mv[1]; + candidates++; + } + + /* Top predictors */ + if (b0 && b0->type == CU_INTER) { + mv_cand[candidates][0] = b0->inter.mv[0]; + mv_cand[candidates][1] = b0->inter.mv[1]; + candidates++; + } else if (b1 && b1->type == CU_INTER) { + mv_cand[candidates][0] = b1->inter.mv[0]; + mv_cand[candidates][1] = b1->inter.mv[1]; + candidates++; + } else if(b2 && b2->type == CU_INTER) { + mv_cand[candidates][0] = b2->inter.mv[0]; + mv_cand[candidates][1] = b2->inter.mv[1]; + candidates++; + } + + if(candidates < 2) { + //TODO: add temporal mv predictor + } + + for (;candidates < 2; candidates++) { + mv_cand[candidates][0] = 0; + mv_cand[candidates][1] = 0; + candidates++; + } + } \ No newline at end of file diff --git a/src/inter.h b/src/inter.h index d2bc807b..f0262b93 100644 --- a/src/inter.h +++ b/src/inter.h @@ -14,5 +14,8 @@ #define __INTER_H void inter_setBlockMode(picture* pic,uint32_t xCtb, uint32_t yCtb, uint8_t depth, CU_info* cur_cu); -void inter_recon(picture* ref,int32_t xpos, int32_t ypos,int32_t width, int16_t mv[2], picture* dst); +void inter_recon(picture *ref,int32_t xpos, int32_t ypos,int32_t width, int16_t mv[2], picture* dst); + +void inter_get_mv_cand(encoder_control *encoder, int32_t xCtb, int32_t yCtb, int8_t depth, int16_t mv_cand[2][2]); + #endif diff --git a/src/search.c b/src/search.c index 695acb77..615546ba 100644 --- a/src/search.c +++ b/src/search.c @@ -19,9 +19,9 @@ #include "config.h" #include "bitstream.h" #include "picture.h" +#include "encoder.h" #include "intra.h" #include "inter.h" -#include "encoder.h" #include "filter.h" #include "search.h"