summaryrefslogtreecommitdiff
path: root/vp8/encoder/rdopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp8/encoder/rdopt.c')
-rw-r--r--vp8/encoder/rdopt.c373
1 files changed, 366 insertions, 7 deletions
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
index 8be0c9a48..74f7f464c 100644
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -1156,7 +1156,7 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *bes
bestsme = vp8_hex_search(x, c, e, best_ref_mv, &mode_mv[NEW4X4], step_param, sadpb/*x->errorperbit*/, &num00, v_fn_ptr, x->mvsadcost, mvcost);
else
{
- bestsme = cpi->diamond_search_sad(x, c, e, best_ref_mv, &mode_mv[NEW4X4], step_param, sadpb / 2/*x->errorperbit*/, &num00, v_fn_ptr, x->mvsadcost, mvcost);
+ bestsme = cpi->diamond_search_sad(x, c, e, best_ref_mv, &mode_mv[NEW4X4], step_param, sadpb / 2/*x->errorperbit*/, &num00, v_fn_ptr, x->mvsadcost, mvcost, best_ref_mv);
n = num00;
num00 = 0;
@@ -1169,7 +1169,7 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *bes
num00--;
else
{
- thissme = cpi->diamond_search_sad(x, c, e, best_ref_mv, &temp_mv, step_param + n, sadpb / 2/*x->errorperbit*/, &num00, v_fn_ptr, x->mvsadcost, mvcost);
+ thissme = cpi->diamond_search_sad(x, c, e, best_ref_mv, &temp_mv, step_param + n, sadpb / 2/*x->errorperbit*/, &num00, v_fn_ptr, x->mvsadcost, mvcost, best_ref_mv);
if (thissme < bestsme)
{
@@ -1184,7 +1184,7 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *bes
// Should we do a full search (best quality only)
if ((compressor_speed == 0) && (bestsme >> sseshift) > 4000)
{
- thissme = cpi->full_search_sad(x, c, e, best_ref_mv, sadpb / 4, 16, v_fn_ptr, x->mvcost, x->mvsadcost);
+ thissme = cpi->full_search_sad(x, c, e, best_ref_mv, sadpb / 4, 16, v_fn_ptr, x->mvcost, x->mvsadcost, best_ref_mv);
if (thissme < bestsme)
{
@@ -1305,6 +1305,273 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *bes
}
+
+/////////////////////////
+static void mv_bias(const MODE_INFO *x, int refframe, int_mv *mvp, const int *ref_frame_sign_bias)
+{
+ MV xmv;
+ xmv = x->mbmi.mv.as_mv;
+
+ if (ref_frame_sign_bias[x->mbmi.ref_frame] != ref_frame_sign_bias[refframe])
+ {
+ xmv.row *= -1;
+ xmv.col *= -1;
+ }
+
+ mvp->as_mv = xmv;
+}
+
+static void lf_mv_bias(const int lf_ref_frame_sign_bias, int refframe, int_mv *mvp, const int *ref_frame_sign_bias)
+{
+ MV xmv;
+ xmv = mvp->as_mv;
+
+ if (lf_ref_frame_sign_bias != ref_frame_sign_bias[refframe])
+ {
+ xmv.row *= -1;
+ xmv.col *= -1;
+ }
+
+ mvp->as_mv = xmv;
+}
+
+static void vp8_clamp_mv(MV *mv, const MACROBLOCKD *xd)
+{
+ if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+ mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+ else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+ mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+ if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+ mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+ else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+ mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+}
+
+static void swap(int *x,int *y)
+{
+ int tmp;
+
+ tmp = *x;
+ *x = *y;
+ *y = tmp;
+}
+
+static void quicksortmv(int arr[],int left, int right)
+{
+ int lidx,ridx,pivot;
+
+ lidx = left;
+ ridx = right;
+
+ if( left < right)
+ {
+ pivot = (left + right)/2;
+
+ while(lidx <=pivot && ridx >=pivot)
+ {
+ while(arr[lidx] < arr[pivot] && lidx <= pivot)
+ lidx++;
+ while(arr[ridx] > arr[pivot] && ridx >= pivot)
+ ridx--;
+ swap(&arr[lidx], &arr[ridx]);
+ lidx++;
+ ridx--;
+ if(lidx-1 == pivot)
+ {
+ ridx++;
+ pivot = ridx;
+ }
+ else if(ridx+1 == pivot)
+ {
+ lidx--;
+ pivot = lidx;
+ }
+ }
+ quicksortmv(arr, left, pivot - 1);
+ quicksortmv(arr, pivot + 1, right);
+ }
+}
+
+static void quicksortsad(int arr[],int idx[], int left, int right)
+{
+ int lidx,ridx,pivot;
+
+ lidx = left;
+ ridx = right;
+
+ if( left < right)
+ {
+ pivot = (left + right)/2;
+
+ while(lidx <=pivot && ridx >=pivot)
+ {
+ while(arr[lidx] < arr[pivot] && lidx <= pivot)
+ lidx++;
+ while(arr[ridx] > arr[pivot] && ridx >= pivot)
+ ridx--;
+ swap(&arr[lidx], &arr[ridx]);
+ swap(&idx[lidx], &idx[ridx]);
+ lidx++;
+ ridx--;
+ if(lidx-1 == pivot)
+ {
+ ridx++;
+ pivot = ridx;
+ }
+ else if(ridx+1 == pivot)
+ {
+ lidx--;
+ pivot = lidx;
+ }
+ }
+ quicksortsad(arr, idx, left, pivot - 1);
+ quicksortsad(arr, idx, pivot + 1, right);
+ }
+}
+
+//The improved MV prediction
+static void vp8_mv_pred
+(
+ VP8_COMP *cpi,
+ MACROBLOCKD *xd,
+ const MODE_INFO *here,
+ MV *mvp,
+ int refframe,
+ int *ref_frame_sign_bias,
+ int *sr,
+ int near_sadidx[]
+)
+{
+ const MODE_INFO *above = here - xd->mode_info_stride;
+ const MODE_INFO *left = here - 1;
+ const MODE_INFO *aboveleft = above - 1;
+ int_mv near_mvs[7];
+ int near_ref[7];
+ int_mv mv;
+ int vcnt=0;
+ int find=0;
+ int mb_offset;
+
+ int mvx[7];
+ int mvy[7];
+ int i;
+
+ mv.as_int = 0;
+
+ if(here->mbmi.ref_frame != INTRA_FRAME)
+ {
+ near_mvs[0].as_int = near_mvs[1].as_int = near_mvs[2].as_int = near_mvs[3].as_int = near_mvs[4].as_int = near_mvs[5].as_int = near_mvs[6].as_int = 0;
+ near_ref[0] = near_ref[1] = near_ref[2] = near_ref[3] = near_ref[4] = near_ref[5] = near_ref[6] = 0;
+
+ // read in 3 nearby block's MVs from current frame as prediction candidates.
+ if (above->mbmi.ref_frame != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = above->mbmi.mv.as_int;
+ mv_bias(above, refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = above->mbmi.ref_frame;
+ }
+ vcnt++;
+ if (left->mbmi.ref_frame != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = left->mbmi.mv.as_int;
+ mv_bias(left, refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = left->mbmi.ref_frame;
+ }
+ vcnt++;
+ if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = aboveleft->mbmi.mv.as_int;
+ mv_bias(aboveleft, refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = aboveleft->mbmi.ref_frame;
+ }
+ vcnt++;
+
+ // read in 4 nearby block's MVs from last frame.
+ if(cpi->common.last_frame_type != KEY_FRAME)
+ {
+ mb_offset = (-xd->mb_to_top_edge/128 + 1) * (xd->mode_info_stride) + (-xd->mb_to_left_edge/128 +1) ;
+
+ // current in last frame
+ if (cpi->lf_ref_frame[mb_offset] != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = cpi->lfmv[mb_offset].as_int;
+ lf_mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = cpi->lf_ref_frame[mb_offset];
+ }
+ vcnt++;
+
+ // above in last frame
+ if (cpi->lf_ref_frame[mb_offset - xd->mode_info_stride] != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = cpi->lfmv[mb_offset - xd->mode_info_stride].as_int;
+ lf_mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset - xd->mode_info_stride], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = cpi->lf_ref_frame[mb_offset - xd->mode_info_stride];
+ }
+ vcnt++;
+
+ // left in last frame
+ if (cpi->lf_ref_frame[mb_offset-1] != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = cpi->lfmv[mb_offset -1].as_int;
+ lf_mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset -1], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = cpi->lf_ref_frame[mb_offset - 1];
+ }
+ vcnt++;
+
+ // aboveleft in last frame
+ if (cpi->lf_ref_frame[mb_offset - xd->mode_info_stride -1] != INTRA_FRAME)
+ {
+ near_mvs[vcnt].as_int = cpi->lfmv[mb_offset - xd->mode_info_stride -1].as_int;
+ lf_mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset - xd->mode_info_stride -1], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+ near_ref[vcnt] = cpi->lf_ref_frame[mb_offset - xd->mode_info_stride -1];
+ }
+ vcnt++;
+ }
+
+ for(i=0; i< vcnt; i++)
+ {
+ if(near_ref[near_sadidx[i]] != INTRA_FRAME)
+ {
+ if(here->mbmi.ref_frame == near_ref[near_sadidx[i]])
+ {
+ mv.as_int = near_mvs[near_sadidx[i]].as_int;
+ find = 1;
+ if(vcnt<2)
+ *sr = 4;
+ else if (vcnt<4)
+ *sr = 3;
+ else
+ *sr = 2;
+ break;
+ }
+ }
+ }
+
+ if(!find)
+ {
+ for(i=0; i<vcnt; i++)
+ {
+ mvx[i] = near_mvs[i].as_mv.row;
+ mvy[i] = near_mvs[i].as_mv.col;
+ }
+
+ quicksortmv (mvx, 0, vcnt-1);
+ quicksortmv (mvy, 0, vcnt-1);
+ mv.as_mv.row = mvx[vcnt/2];
+ mv.as_mv.col = mvy[vcnt/2];
+
+ find = 1;
+ //sr is set to 0 to allow calling function to decide the search range.
+ *sr = 0;
+ }
+ }
+
+ /* Set up return values */
+ *mvp = mv.as_mv;
+ vp8_clamp_mv(mvp, xd);
+}
+
int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra)
{
BLOCK *b = &x->block[0];
@@ -1342,6 +1609,12 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int tteob = 0;
int force_no_skip = 0;
+ MV mvp;
+ int near_sad[7]; // 0-cf above, 1-cf left, 2-cf aboveleft, 3-lf current, 4-lf above, 5-lf left, 6-lf aboveleft
+ int near_sadidx[7] = {0, 1, 2, 3, 4, 5, 6};
+ int saddone=0;
+ int sr=0; //search range got from mv_pred(). It uses step_param levels. (0-7)
+
*returnintra = INT_MAX;
vpx_memset(&best_mbmode, 0, sizeof(best_mbmode)); // clean
@@ -1509,6 +1782,72 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
&mode_mv[NEARESTMV], &mode_mv[NEARMV], &best_ref_mv,
mdcounts, x->e_mbd.mode_info_context->mbmi.ref_frame, cpi->common.ref_frame_sign_bias);
+ if(x->e_mbd.mode_info_context->mbmi.mode == NEWMV)
+ {
+ if(!saddone)
+ {
+ //calculate sad for current frame 3 nearby MBs.
+ if( xd->mb_to_top_edge==0 && xd->mb_to_left_edge ==0)
+ {
+ near_sad[0] = near_sad[1] = near_sad[2] = INT_MAX;
+ }else if(xd->mb_to_top_edge==0)
+ { //only has left MB for sad calculation.
+ near_sad[0] = near_sad[2] = INT_MAX;
+ near_sad[1] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, xd->dst.y_buffer - 16,xd->dst.y_stride, 0x7fffffff);
+ }else if(xd->mb_to_left_edge ==0)
+ { //only has left MB for sad calculation.
+ near_sad[1] = near_sad[2] = INT_MAX;
+ near_sad[0] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, xd->dst.y_buffer - xd->dst.y_stride *16,xd->dst.y_stride, 0x7fffffff);
+ }else
+ {
+ near_sad[0] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, xd->dst.y_buffer - xd->dst.y_stride *16,xd->dst.y_stride, 0x7fffffff);
+ near_sad[1] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, xd->dst.y_buffer - 16,xd->dst.y_stride, 0x7fffffff);
+ near_sad[2] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, xd->dst.y_buffer - xd->dst.y_stride *16 -16,xd->dst.y_stride, 0x7fffffff);
+ }
+
+ if(cpi->common.last_frame_type != KEY_FRAME)
+ {
+ //calculate sad for last frame 4 nearby MBs.
+ unsigned char *pre_y_buffer = cpi->common.yv12_fb[cpi->common.lst_fb_idx].y_buffer + recon_yoffset;
+ int pre_y_stride = cpi->common.yv12_fb[cpi->common.lst_fb_idx].y_stride;
+
+ if( xd->mb_to_top_edge==0 && xd->mb_to_left_edge ==0)
+ {
+ near_sad[4] = near_sad[5] = near_sad[6] = INT_MAX;
+ near_sad[3] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer, pre_y_stride, 0x7fffffff);
+ }else if(xd->mb_to_top_edge==0)
+ { //only has left MB for sad calculation.
+ near_sad[4] = near_sad[6] = INT_MAX;
+ near_sad[3] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer, pre_y_stride, 0x7fffffff);
+ near_sad[5] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer - 16, pre_y_stride, 0x7fffffff);
+ }else if(xd->mb_to_left_edge ==0)
+ { //only has left MB for sad calculation.
+ near_sad[5] = near_sad[6] = INT_MAX;
+ near_sad[3] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer, pre_y_stride, 0x7fffffff);
+ near_sad[4] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer - pre_y_stride *16, pre_y_stride, 0x7fffffff);
+ }else
+ {
+ near_sad[3] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer, pre_y_stride, 0x7fffffff);
+ near_sad[4] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer - pre_y_stride *16, pre_y_stride, 0x7fffffff);
+ near_sad[5] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer - 16, pre_y_stride, 0x7fffffff);
+ near_sad[6] = cpi->fn_ptr[BLOCK_16X16].sdf(x->src.y_buffer, x->src.y_stride, pre_y_buffer - pre_y_stride *16 -16, pre_y_stride, 0x7fffffff);
+ }
+ }
+
+ if(cpi->common.last_frame_type != KEY_FRAME)
+ {
+ quicksortsad(near_sad, near_sadidx, 0, 6);
+ }else
+ {
+ quicksortsad(near_sad, near_sadidx, 0, 2);
+ }
+
+ saddone = 1;
+ }
+
+ vp8_mv_pred(cpi, &x->e_mbd, x->e_mbd.mode_info_context, &mvp,
+ x->e_mbd.mode_info_context->mbmi.ref_frame, cpi->common.ref_frame_sign_bias, &sr, &near_sadidx[0]);
+ }
// Estimate the reference frame signaling cost and add it to the rolling cost variable.
frame_cost = ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
@@ -1696,6 +2035,10 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int further_steps;
int n;
+ //adjust search range according to sr from mv prediction
+ if(sr > step_param)
+ step_param = sr;
+
// Work out how long a search we should do
search_range = MAXF(abs(best_ref_mv.col), abs(best_ref_mv.row)) >> 3;
@@ -1716,7 +2059,7 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
}
else
{
- bestsme = cpi->diamond_search_sad(x, b, d, &best_ref_mv, &d->bmi.mv.as_mv, step_param, sadpb / 2/*x->errorperbit*/, &num00, &cpi->fn_ptr[BLOCK_16X16], x->mvsadcost, x->mvcost); //sadpb < 9
+ bestsme = cpi->diamond_search_sad(x, b, d, &mvp, &d->bmi.mv.as_mv, step_param, sadpb / 2/*x->errorperbit*/, &num00, &cpi->fn_ptr[BLOCK_16X16], x->mvsadcost, x->mvcost, &best_ref_mv); //sadpb < 9
mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
@@ -1735,7 +2078,7 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
num00--;
else
{
- thissme = cpi->diamond_search_sad(x, b, d, &best_ref_mv, &d->bmi.mv.as_mv, step_param + n, sadpb / 4/*x->errorperbit*/, &num00, &cpi->fn_ptr[BLOCK_16X16], x->mvsadcost, x->mvcost); //sadpb = 9
+ thissme = cpi->diamond_search_sad(x, b, d, &mvp, &d->bmi.mv.as_mv, step_param + n, sadpb / 4/*x->errorperbit*/, &num00, &cpi->fn_ptr[BLOCK_16X16], x->mvsadcost, x->mvcost, &best_ref_mv); //sadpb = 9
if (thissme < bestsme)
{
@@ -1759,9 +2102,14 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
{
int thissme;
int full_flag_thresh = 0;
+ MV full_mvp;
+
+ full_mvp.row = d->bmi.mv.as_mv.row <<3; // use diamond search result as full search staring point
+ full_mvp.col = d->bmi.mv.as_mv.col <<3;
// Update x->vector_range based on best vector found in step search
- search_range = MAXF(abs(d->bmi.mv.as_mv.row), abs(d->bmi.mv.as_mv.col));
+ search_range = MAXF(abs((mvp.row>>3) - d->bmi.mv.as_mv.row), abs((mvp.col>>3) - d->bmi.mv.as_mv.col));
+ //search_range *= 1.4; //didn't improve PSNR
if (search_range > x->vector_range)
x->vector_range = search_range;
@@ -1770,9 +2118,20 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
// Apply limits
search_range = (search_range > cpi->sf.max_fs_radius) ? cpi->sf.max_fs_radius : search_range;
+
+ //add this to reduce full search range.
+ if(sr<=3 && search_range > 8) search_range = 8;
+
{
int sadpb = x->sadperbit16 >> 2;
- thissme = cpi->full_search_sad(x, b, d, &best_ref_mv, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, x->mvsadcost);
+ thissme = cpi->full_search_sad(x, b, d, &full_mvp, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, x->mvsadcost,&best_ref_mv);
+ /*
+ MV dia_ref_mv;
+ dia_ref_mv.row = d->bmi.mv.as_mv.row << 3;
+ dia_ref_mv.col = d->bmi.mv.as_mv.col << 3;
+ thissme = cpi->full_search_sad(x, b, d, &dia_ref_mv, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, x->mvsadcost,&best_ref_mv);
+ */
+
}
// Barrier threshold to initiating full search